diff -u --recursive --new-file v2.1.35/linux/Documentation/Changes linux/Documentation/Changes
--- v2.1.35/linux/Documentation/Changes	Wed Apr 16 14:14:58 1997
+++ linux/Documentation/Changes	Thu Apr 17 12:46:56 1997
@@ -29,7 +29,7 @@
    Also, don't forget http://www.linuxhq.com/ for all your Linux kernel
 needs.
 
-Last updated: April 15, 1997.
+Last updated: April 17, 1997.
 Current Author: Chris Ricker (gt1355b@prism.gatech.edu).
 
 Current Minimal Requirements
@@ -184,7 +184,7 @@
 
 Binutils: ld -v
 Gnu C: gcc -v or gcc --version
-Kbd: loadkeys -h
+Kbd: dumpkeys -h
 Ld.so: ldd -v
 Libc: ls -l /lib/libc.so.*
 Libc++: ls -l /usr/lib/libg++.so.*
@@ -249,7 +249,7 @@
 
 The 2.1.34 release:
 ftp://ftp.redhat.com/pub/alphabits/modutils-2.1.34.tar.gz
-ftp://ftp.kernel.org/pub/linux/kernel/modutils-2.1.34.tar.gz
+ftp://ftp.kernel.org/pub/linux/kernel/v2.1/modutils-2.1.34.tar.gz
 
 Procps utilities
 ================
diff -u --recursive --new-file v2.1.35/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v2.1.35/linux/Documentation/Configure.help	Wed Apr 16 14:14:58 1997
+++ linux/Documentation/Configure.help	Tue Apr 22 15:32:00 1997
@@ -290,12 +290,13 @@
 Intel 82371 PIIX (Triton I/II) 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
-  or i82371SB), 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
+  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
+  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.
 
 Other IDE chipset support
@@ -3063,22 +3064,20 @@
   Documentation/networking/net-modules.txt. The module will be called
   pt.o.
 
-WaveLAN support
+AT&T WaveLAN & DEC RoamAbout DS support
 CONFIG_WAVELAN
-  These are cards for wireless ethernet-like networking. Supported are
-  AT&T GIS and NCR WaveLAN cards. If you want to use a card of this
-  type under Linux, say Y and read the Ethernet-HOWTO, available via
-  ftp (user: anonymous) in sunsite.unc.edu:/pub/Linux/docs/HOWTO. Some
-  more specific information is contained in
-  drivers/net/README.wavelan. This driver is also available as a
-  module ( = code which can be inserted in and removed from the
-  running kernel whenever you want). The module will be called
-  wavelan.o. If you want to compile it as a module, say M here and
-  read Documentation/modules.txt as well as
-  Documentation/networking/net-modules.txt. If you plan to use more
-  than one network card under linux, read the
-  Multiple-Ethernet-mini-HOWTO, available from
-  sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini.
+    The Lucent Wavelan (formerly NCR and AT&T ; or DEC RoamAbout DS)
+  is a Radio LAN (wireless ethernet-like) at 900 MHz and 2.4 GHz.
+    This driver support the ISA version of the Wavelan. A driver for
+  the pcmcia hardware is available in David Hinds's pcmcia package.
+    This driver is fairly stable and may be compiled as a module
+  (wavelan.o). It implements many nice feature and the Wireless
+  Extensions (you must get the Wireless tools from the net).
+    For documentation, refer to :
+      o the wavelan man page, wireless tools man pages
+      o wavelan.p.h and the source code
+      o Ethernet-HOWTO, Multiple-Ethernet-mini-HOWTO, Module-HOWTO
+      o More documentation to come when I will have the time :-)
 
 HP PCLAN+ (27247B and 27252A) support
 CONFIG_HPLAN_PLUS
diff -u --recursive --new-file v2.1.35/linux/Documentation/parport.txt linux/Documentation/parport.txt
--- v2.1.35/linux/Documentation/parport.txt	Sun Apr 13 10:18:20 1997
+++ linux/Documentation/parport.txt	Thu Apr 17 14:48:53 1997
@@ -47,9 +47,13 @@
 Also:
 
  * If you selected the device autoprobe at compile time, you can say
-`lp=auto' on the kernel command line, and lp will create devices only
-for those ports that seem to have printers attached.
+   `lp=auto' on the kernel command line, and lp will create devices
+   only for those ports that seem to have printers attached.
 
  * If you give PLIP the `timid' parameter, either with `plip=timid' on
-the command line, or with `insmod plip timid=1' when using modules, it
-will avoid any ports that seem to be in use by other devices.
+   the command line, or with `insmod plip timid=1' when using modules,
+   it will avoid any ports that seem to be in use by other devices.
+
+ * If your BIOS allows you to engage "ECP mode", you may find that
+   your port's IRQ can be autoprobed, without having to specify any 
+   parameters.
diff -u --recursive --new-file v2.1.35/linux/Makefile linux/Makefile
--- v2.1.35/linux/Makefile	Wed Apr 16 14:14:59 1997
+++ linux/Makefile	Thu Apr 17 14:48:53 1997
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 1
-SUBLEVEL = 35
+SUBLEVEL = 36
 
 ARCH := $(shell uname -m | sed s/i.86/i386/)
 
@@ -118,7 +118,8 @@
 FILESYSTEMS	=fs/filesystems.a
 NETWORKS	=net/network.a
 DRIVERS		=drivers/block/block.a \
-		 drivers/char/char.a
+		 drivers/char/char.a \
+	         drivers/pnp/pnp.a
 LIBS		=$(TOPDIR)/lib/lib.a
 SUBDIRS		=kernel drivers mm fs net ipc lib
 
@@ -142,10 +143,6 @@
 
 ifdef CONFIG_PCI
 DRIVERS := $(DRIVERS) drivers/pci/pci.a
-endif
-
-ifdef CONFIG_PNP
-DRIVERS := $(DRIVERS) drivers/pnp/pnp.a
 endif
 
 ifdef CONFIG_SBUS
diff -u --recursive --new-file v2.1.35/linux/arch/alpha/Makefile linux/arch/alpha/Makefile
--- v2.1.35/linux/arch/alpha/Makefile	Mon Apr  7 11:35:28 1997
+++ linux/arch/alpha/Makefile	Tue Apr 22 22:38:39 1997
@@ -10,21 +10,8 @@
 
 NM := nm -B
 
-ifdef CONFIG_CROSSCOMPILE
-# enable this for linking under OSF/1:
-LINKFLAGS = -non_shared -T 0xfffffc0000310000 -N
-else
- elf=$(shell if $(LD) --help | grep elf64alpha >/dev/null; then echo yes; fi)
- ifeq ($(elf),yes)
-   LINKFLAGS = -static -Ttext 0xfffffc0000310000 -N
- else
-   LINKFLAGS = -static -T arch/alpha/vmlinux.lds -N
- endif
-# GNU gcc/cc1/as can use pipes instead of temporary files
-CFLAGS := $(CFLAGS) -pipe
-endif
-
-CFLAGS := $(CFLAGS) -mno-fp-regs -ffixed-8
+LINKFLAGS = -static -T arch/alpha/vmlinux.lds -N
+CFLAGS := $(CFLAGS) -pipe -mno-fp-regs -ffixed-8
 
 HEAD := arch/alpha/kernel/head.o
 
diff -u --recursive --new-file v2.1.35/linux/arch/alpha/kernel/entry.S linux/arch/alpha/kernel/entry.S
--- v2.1.35/linux/arch/alpha/kernel/entry.S	Wed Apr 16 14:14:59 1997
+++ linux/arch/alpha/kernel/entry.S	Tue Apr 22 22:49:38 1997
@@ -759,6 +759,6 @@
 	.quad sys_setfsuid, sys_setfsgid, sys_ustat, sys_statfs, sys_fstatfs
 	.quad sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler, sys_sched_yield
 	.quad sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, do_entSys /* sys_afs_syscall */, sys_newuname
-	.quad sys_nanosleep, sys_mremap, do_entSys, sys_setresuid, sys_getresuid
+	.quad sys_nanosleep, sys_mremap, sys_nfsservctl, sys_setresuid, sys_getresuid
 	.quad sys_pciconfig_read, sys_pciconfig_write, sys_query_module
 	.quad do_entSys, do_entSys
diff -u --recursive --new-file v2.1.35/linux/arch/alpha/kernel/osf_sys.c linux/arch/alpha/kernel/osf_sys.c
--- v2.1.35/linux/arch/alpha/kernel/osf_sys.c	Tue Mar  4 10:25:23 1997
+++ linux/arch/alpha/kernel/osf_sys.c	Tue Apr 22 22:38:40 1997
@@ -33,6 +33,7 @@
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
+#include <asm/sysinfo.h>
 
 extern int do_mount(kdev_t, const char *, const char *, char *, int, void *);
 extern int do_pipe(int *);
@@ -171,7 +172,7 @@
 	int prio;
 
 	/*
-	 * We don't need to aquire the kernel lock here, because
+	 * We don't need to acquire the kernel lock here, because
 	 * all of these operations are local. sys_getpriority
 	 * will get the lock as required..
 	 */
@@ -193,7 +194,7 @@
 }
 
 /*
- * No need to aquire the kernel lock, we're local..
+ * No need to acquire the kernel lock, we're local..
  */
 asmlinkage unsigned long sys_getxuid(int a0, int a1, int a2, int a3, int a4, int a5,
 				     struct pt_regs regs)
@@ -218,7 +219,7 @@
 
 	/* 
 	 * This isn't strictly "local" any more and we should actually
-	 * aquire the kernel lock. The "p_opptr" pointer might change
+	 * acquire the kernel lock. The "p_opptr" pointer might change
 	 * if the parent goes away (or due to ptrace). But any race
 	 * isn't actually going to matter, as if the parent happens
 	 * to change we can happily return either of the pids.
@@ -840,62 +841,91 @@
 	return err;
 }
 
-asmlinkage unsigned long osf_getsysinfo(unsigned long op, void *buffer, unsigned long nbytes,
+asmlinkage unsigned long osf_getsysinfo(unsigned long op, void *buffer,
+					unsigned long nbytes,
 					int *start, void *arg)
 {
 	extern unsigned long rdfpcr(void);
-	unsigned long fpcw;
-	unsigned long ret = -EOPNOTSUPP;
+	unsigned long w;
 
-	lock_kernel();
 	switch (op) {
-	case 45:		/* GSI_IEEE_FP_CONTROL */
+	case GSI_IEEE_FP_CONTROL:
 		/* build and return current fp control word: */
-		fpcw = current->tss.flags & IEEE_TRAP_ENABLE_MASK;
-		fpcw |= ((rdfpcr() >> 52) << 17) & IEEE_STATUS_MASK;
-		put_user(fpcw, (unsigned long *) buffer);
-		ret = 0;
-		break;
-	case 46:		/* GSI_IEEE_STATE_AT_SIGNAL */
+		w = current->tss.flags & IEEE_TRAP_ENABLE_MASK;
+		w |= ((rdfpcr() >> 52) << 17) & IEEE_STATUS_MASK;
+		if (put_user(w, (unsigned long *) buffer))
+			return -EFAULT;
+		return 0;
+
+	case GSI_IEEE_STATE_AT_SIGNAL:
 		/*
 		 * Not sure anybody will ever use this weird stuff.  These
 		 * ops can be used (under OSF/1) to set the fpcr that should
 		 * be used when a signal handler starts executing.
 		 */
 		break;
+
+ 	case GSI_UACPROC:
+ 		w = (current->tss.flags >> UAC_SHIFT) & UAC_BITMASK;
+ 		if (put_user(w, (unsigned int *)buffer))
+ 			return -EFAULT;
+ 		return 0;
+
 	default:
 		break;
 	}
-	unlock_kernel();
-	return ret;
+
+	return -EOPNOTSUPP;
 }
 
 
-asmlinkage unsigned long osf_setsysinfo(unsigned long op, void *buffer, unsigned long nbytes,
+asmlinkage unsigned long osf_setsysinfo(unsigned long op, void *buffer,
+					unsigned long nbytes,
 					int *start, void *arg)
 {
-	unsigned long fpcw;
-	unsigned long ret = -EOPNOTSUPP;
+	unsigned long v, w, i;
 
-	lock_kernel();
 	switch (op) {
-	case 14:		/* SSI_IEEE_FP_CONTROL */
+	case SSI_IEEE_FP_CONTROL:
 		/* update trap enable bits: */
-		get_user(fpcw, (unsigned long *) buffer);
+		if (get_user(w, (unsigned long *) buffer))
+			return -EFAULT;
 		current->tss.flags &= ~IEEE_TRAP_ENABLE_MASK;
-		current->tss.flags |= (fpcw & IEEE_TRAP_ENABLE_MASK);
-		ret = 0;
-		break;
-	case 15:		/* SSI_IEEE_STATE_AT_SIGNAL */
-	case 16:		/* SSI_IEEE_IGNORE_STATE_AT_SIGNAL */
+		current->tss.flags |= (w & IEEE_TRAP_ENABLE_MASK);
+		return 0;
+
+	case SSI_IEEE_STATE_AT_SIGNAL:
+	case SSI_IEEE_IGNORE_STATE_AT_SIGNAL:
 		/*
 		 * Not sure anybody will ever use this weird stuff.  These
 		 * ops can be used (under OSF/1) to set the fpcr that should
 		 * be used when a signal handler starts executing.
 		 */
+		break;
+
+ 	case SSI_NVPAIRS:
+ 		for (i = 0; i < nbytes; ++i) {
+ 			if (get_user(v, 2*i + (unsigned int *)buffer))
+ 				return -EFAULT;
+ 			if (get_user(w, 2*i + 1 + (unsigned int *)buffer))
+ 				return -EFAULT;
+ 			switch (v) {
+ 			case SSIN_UACPROC:
+ 				current->tss.flags &=
+ 					~(UAC_BITMASK << UAC_SHIFT);
+ 				current->tss.flags |=
+ 					(w & UAC_BITMASK) << UAC_SHIFT;
+ 				break;
+ 
+ 			default:
+ 				return -EOPNOTSUPP;
+ 			}
+ 		}
+ 		return 0;
+ 
 	default:
 		break;
 	}
-	unlock_kernel();
-	return ret;
+
+	return -EOPNOTSUPP;
 }
diff -u --recursive --new-file v2.1.35/linux/arch/alpha/kernel/process.c linux/arch/alpha/kernel/process.c
--- v2.1.35/linux/arch/alpha/kernel/process.c	Wed Apr 16 14:14:59 1997
+++ linux/arch/alpha/kernel/process.c	Thu Apr 17 09:22:40 1997
@@ -39,7 +39,7 @@
 #include <asm/io.h>
 
 /*
- * No need to aquire the kernel lock, we're entirely local..
+ * No need to acquire the kernel lock, we're entirely local..
  */
 asmlinkage int sys_sethae(unsigned long hae, unsigned long a1, unsigned long a2,
 	unsigned long a3, unsigned long a4, unsigned long a5,
diff -u --recursive --new-file v2.1.35/linux/arch/alpha/kernel/signal.c linux/arch/alpha/kernel/signal.c
--- v2.1.35/linux/arch/alpha/kernel/signal.c	Mon Apr  7 11:35:29 1997
+++ linux/arch/alpha/kernel/signal.c	Tue Apr 22 22:38:40 1997
@@ -41,7 +41,7 @@
  * We change the range to -1 .. 1 in order to let gcc easily
  * use the conditional move instructions.
  *
- * Note that we don't need to aquire the kernel lock for SMP
+ * Note that we don't need to acquire the kernel lock for SMP
  * operation, as all of this is local to this thread.
  */
 asmlinkage unsigned long osf_sigprocmask(int how, unsigned long newmask,
@@ -80,18 +80,17 @@
 {
 	unsigned long oldmask;
 
-	lock_kernel();
+	spin_lock_irq(&current->sigmask_lock);
 	oldmask = current->blocked;
 	current->blocked = mask & _BLOCKABLE;
+	spin_unlock_irq(&current->sigmask_lock);
+
 	while (1) {
 		current->state = TASK_INTERRUPTIBLE;
 		schedule();
-		if (do_signal(oldmask,regs, sw, 0, 0))
-			goto out;
+		if (do_signal(oldmask, regs, sw, 0, 0))
+			return -EINTR;
 	}
-out:
-	unlock_kernel();
-	return -EINTR;
 }
 
 /*
@@ -104,60 +103,64 @@
 	int i;
 
 	/* verify that it's a good sigcontext before using it */
-	lock_kernel();
 	if (verify_area(VERIFY_READ, sc, sizeof(*sc)))
-		do_exit(SIGSEGV);
-	get_user(ps, &sc->sc_ps);
-	if (ps != 8)
-		do_exit(SIGSEGV);
-	get_user(mask, &sc->sc_mask);
-	if (mask & ~_BLOCKABLE)
-		do_exit(SIGSEGV);
+		goto give_sigsegv;
+	if (__get_user(ps, &sc->sc_ps) || ps != 8)
+		goto give_sigsegv;
+	if (__get_user(mask, &sc->sc_mask) || (mask & ~_BLOCKABLE))
+		goto give_sigsegv;
 
 	/* ok, looks fine, start restoring */
-	get_user(usp, sc->sc_regs+30);
+	__get_user(usp, sc->sc_regs+30);
 	wrusp(usp);
-	get_user(regs->pc, &sc->sc_pc);
+	__get_user(regs->pc, &sc->sc_pc);
 	sw->r26 = (unsigned long) ret_from_sys_call;
 	current->blocked = mask;
 
-	get_user(regs->r0, sc->sc_regs+0);
-	get_user(regs->r1, sc->sc_regs+1);
-	get_user(regs->r2, sc->sc_regs+2);
-	get_user(regs->r3, sc->sc_regs+3);
-	get_user(regs->r4, sc->sc_regs+4);
-	get_user(regs->r5, sc->sc_regs+5);
-	get_user(regs->r6, sc->sc_regs+6);
-	get_user(regs->r7, sc->sc_regs+7);
-	get_user(regs->r8, sc->sc_regs+8);
-	get_user(sw->r9, sc->sc_regs+9);
-	get_user(sw->r10, sc->sc_regs+10);
-	get_user(sw->r11, sc->sc_regs+11);
-	get_user(sw->r12, sc->sc_regs+12);
-	get_user(sw->r13, sc->sc_regs+13);
-	get_user(sw->r14, sc->sc_regs+14);
-	get_user(sw->r15, sc->sc_regs+15);
-	get_user(regs->r16, sc->sc_regs+16);
-	get_user(regs->r17, sc->sc_regs+17);
-	get_user(regs->r18, sc->sc_regs+18);
-	get_user(regs->r19, sc->sc_regs+19);
-	get_user(regs->r20, sc->sc_regs+20);
-	get_user(regs->r21, sc->sc_regs+21);
-	get_user(regs->r22, sc->sc_regs+22);
-	get_user(regs->r23, sc->sc_regs+23);
-	get_user(regs->r24, sc->sc_regs+24);
-	get_user(regs->r25, sc->sc_regs+25);
-	get_user(regs->r26, sc->sc_regs+26);
-	get_user(regs->r27, sc->sc_regs+27);
-	get_user(regs->r28, sc->sc_regs+28);
-	get_user(regs->gp, sc->sc_regs+29);
+	__get_user(regs->r0, sc->sc_regs+0);
+	__get_user(regs->r1, sc->sc_regs+1);
+	__get_user(regs->r2, sc->sc_regs+2);
+	__get_user(regs->r3, sc->sc_regs+3);
+	__get_user(regs->r4, sc->sc_regs+4);
+	__get_user(regs->r5, sc->sc_regs+5);
+	__get_user(regs->r6, sc->sc_regs+6);
+	__get_user(regs->r7, sc->sc_regs+7);
+	__get_user(regs->r8, sc->sc_regs+8);
+	__get_user(sw->r9, sc->sc_regs+9);
+	__get_user(sw->r10, sc->sc_regs+10);
+	__get_user(sw->r11, sc->sc_regs+11);
+	__get_user(sw->r12, sc->sc_regs+12);
+	__get_user(sw->r13, sc->sc_regs+13);
+	__get_user(sw->r14, sc->sc_regs+14);
+	__get_user(sw->r15, sc->sc_regs+15);
+	__get_user(regs->r16, sc->sc_regs+16);
+	__get_user(regs->r17, sc->sc_regs+17);
+	__get_user(regs->r18, sc->sc_regs+18);
+	__get_user(regs->r19, sc->sc_regs+19);
+	__get_user(regs->r20, sc->sc_regs+20);
+	__get_user(regs->r21, sc->sc_regs+21);
+	__get_user(regs->r22, sc->sc_regs+22);
+	__get_user(regs->r23, sc->sc_regs+23);
+	__get_user(regs->r24, sc->sc_regs+24);
+	__get_user(regs->r25, sc->sc_regs+25);
+	__get_user(regs->r26, sc->sc_regs+26);
+	__get_user(regs->r27, sc->sc_regs+27);
+	__get_user(regs->r28, sc->sc_regs+28);
+	__get_user(regs->gp, sc->sc_regs+29);
 	for (i = 0; i < 31; i++)
-		get_user(sw->fp[i], sc->sc_fpregs+i);
+		__get_user(sw->fp[i], sc->sc_fpregs+i);
 
 	/* send SIGTRAP if we're single-stepping: */
+	lock_kernel();
 	if (ptrace_cancel_bpt (current))
 		send_sig(SIGTRAP, current, 1);
 	unlock_kernel();
+	return;
+
+give_sigsegv:
+	lock_kernel();
+	do_exit(SIGSEGV);
+	unlock_kernel();
 }
 
 /*
@@ -181,46 +184,46 @@
 
 	wrusp((unsigned long) sc);
 
-	put_user(oldmask, &sc->sc_mask);
-	put_user(8, &sc->sc_ps);
-	put_user(regs->pc, &sc->sc_pc);
-	put_user(oldsp, sc->sc_regs+30);
-
-	put_user(regs->r0 , sc->sc_regs+0);
-	put_user(regs->r1 , sc->sc_regs+1);
-	put_user(regs->r2 , sc->sc_regs+2);
-	put_user(regs->r3 , sc->sc_regs+3);
-	put_user(regs->r4 , sc->sc_regs+4);
-	put_user(regs->r5 , sc->sc_regs+5);
-	put_user(regs->r6 , sc->sc_regs+6);
-	put_user(regs->r7 , sc->sc_regs+7);
-	put_user(regs->r8 , sc->sc_regs+8);
-	put_user(sw->r9   , sc->sc_regs+9);
-	put_user(sw->r10  , sc->sc_regs+10);
-	put_user(sw->r11  , sc->sc_regs+11);
-	put_user(sw->r12  , sc->sc_regs+12);
-	put_user(sw->r13  , sc->sc_regs+13);
-	put_user(sw->r14  , sc->sc_regs+14);
-	put_user(sw->r15  , sc->sc_regs+15);
-	put_user(regs->r16, sc->sc_regs+16);
-	put_user(regs->r17, sc->sc_regs+17);
-	put_user(regs->r18, sc->sc_regs+18);
-	put_user(regs->r19, sc->sc_regs+19);
-	put_user(regs->r20, sc->sc_regs+20);
-	put_user(regs->r21, sc->sc_regs+21);
-	put_user(regs->r22, sc->sc_regs+22);
-	put_user(regs->r23, sc->sc_regs+23);
-	put_user(regs->r24, sc->sc_regs+24);
-	put_user(regs->r25, sc->sc_regs+25);
-	put_user(regs->r26, sc->sc_regs+26);
-	put_user(regs->r27, sc->sc_regs+27);
-	put_user(regs->r28, sc->sc_regs+28);
-	put_user(regs->gp , sc->sc_regs+29);
+	__put_user(oldmask, &sc->sc_mask);
+	__put_user(8, &sc->sc_ps);
+	__put_user(regs->pc, &sc->sc_pc);
+	__put_user(oldsp, sc->sc_regs+30);
+
+	__put_user(regs->r0 , sc->sc_regs+0);
+	__put_user(regs->r1 , sc->sc_regs+1);
+	__put_user(regs->r2 , sc->sc_regs+2);
+	__put_user(regs->r3 , sc->sc_regs+3);
+	__put_user(regs->r4 , sc->sc_regs+4);
+	__put_user(regs->r5 , sc->sc_regs+5);
+	__put_user(regs->r6 , sc->sc_regs+6);
+	__put_user(regs->r7 , sc->sc_regs+7);
+	__put_user(regs->r8 , sc->sc_regs+8);
+	__put_user(sw->r9   , sc->sc_regs+9);
+	__put_user(sw->r10  , sc->sc_regs+10);
+	__put_user(sw->r11  , sc->sc_regs+11);
+	__put_user(sw->r12  , sc->sc_regs+12);
+	__put_user(sw->r13  , sc->sc_regs+13);
+	__put_user(sw->r14  , sc->sc_regs+14);
+	__put_user(sw->r15  , sc->sc_regs+15);
+	__put_user(regs->r16, sc->sc_regs+16);
+	__put_user(regs->r17, sc->sc_regs+17);
+	__put_user(regs->r18, sc->sc_regs+18);
+	__put_user(regs->r19, sc->sc_regs+19);
+	__put_user(regs->r20, sc->sc_regs+20);
+	__put_user(regs->r21, sc->sc_regs+21);
+	__put_user(regs->r22, sc->sc_regs+22);
+	__put_user(regs->r23, sc->sc_regs+23);
+	__put_user(regs->r24, sc->sc_regs+24);
+	__put_user(regs->r25, sc->sc_regs+25);
+	__put_user(regs->r26, sc->sc_regs+26);
+	__put_user(regs->r27, sc->sc_regs+27);
+	__put_user(regs->r28, sc->sc_regs+28);
+	__put_user(regs->gp , sc->sc_regs+29);
 	for (i = 0; i < 31; i++)
-		put_user(sw->fp[i], sc->sc_fpregs+i);
-	put_user(regs->trap_a0, &sc->sc_traparg_a0);
-	put_user(regs->trap_a1, &sc->sc_traparg_a1);
-	put_user(regs->trap_a2, &sc->sc_traparg_a2);
+		__put_user(sw->fp[i], sc->sc_fpregs+i);
+	__put_user(regs->trap_a0, &sc->sc_traparg_a0);
+	__put_user(regs->trap_a1, &sc->sc_traparg_a1);
+	__put_user(regs->trap_a2, &sc->sc_traparg_a2);
 
 	/*
 	 * The following is:
@@ -231,8 +234,8 @@
 	 *
 	 * ie, "sigreturn(stack-pointer)"
 	 */
-	put_user(0x43ecf40047de0410, sc->sc_retcode+0);
-	put_user(0x0000000000000083, sc->sc_retcode+1);
+	__put_user(0x43ecf40047de0410, sc->sc_retcode+0);
+	__put_user(0x0000000000000083, sc->sc_retcode+1);
 	imb();
 
 	/* "return" to the handler */
diff -u --recursive --new-file v2.1.35/linux/arch/alpha/kernel/traps.c linux/arch/alpha/kernel/traps.c
--- v2.1.35/linux/arch/alpha/kernel/traps.c	Sun Feb  2 05:00:46 1997
+++ linux/arch/alpha/kernel/traps.c	Tue Apr 22 22:38:40 1997
@@ -16,6 +16,9 @@
 #include <asm/gentrap.h>
 #include <asm/uaccess.h>
 #include <asm/unaligned.h>
+#include <asm/sysinfo.h>
+#include <asm/smp_lock.h>
+
 
 void die_if_kernel(char * str, struct pt_regs * regs, long err,
 		   unsigned long *r9_15)
@@ -81,10 +84,13 @@
 			return;		/* emulation was successful */
 		}
 	}
+
+	lock_kernel();
 	printk("%s: arithmetic trap at %016lx: %02lx %016lx\n",
 		current->comm, regs.pc, summary, write_mask);
 	die_if_kernel("Arithmetic fault", &regs, 0, 0);
 	force_sig(SIGFPE, current);
+	unlock_kernel();
 }
 
 asmlinkage void do_entIF(unsigned long type, unsigned long a1,
@@ -93,6 +99,7 @@
 {
 	extern int ptrace_cancel_bpt (struct task_struct *who);
 
+	lock_kernel();
 	die_if_kernel("Instruction fault", &regs, type, 0);
 	switch (type) {
 	      case 0: /* breakpoint */
@@ -171,6 +178,7 @@
 	      default:
 		panic("do_entIF: unexpected instruction-fault type");
 	}
+	unlock_kernel();
 }
 
 /*
@@ -204,21 +212,10 @@
 	unsigned long a3, unsigned long a4, unsigned long a5,
 	struct allregs regs)
 {
-	static int cnt = 0;
-	static long last_time = 0;
 	long error, tmp1, tmp2, tmp3, tmp4;
 	unsigned long pc = regs.pc - 4;
 	unsigned fixup;
 
-	if (cnt >= 5 && jiffies - last_time > 5*HZ) {
-		cnt = 0;
-	}
-	if (++cnt < 5) {
-		printk("kernel: unaligned trap at %016lx: %p %lx %ld\n",
-		       pc, va, opcode, reg);
-	}
-	last_time = jiffies;
-
 	unaligned[0].count++;
 	unaligned[0].va = (unsigned long) va;
 	unaligned[0].pc = pc;
@@ -228,7 +225,6 @@
 	   exception will we decide whether we should have caught it.  */
 
 	switch (opcode) {
-#ifdef __HAVE_CPU_BWX
 	case 0x0c: /* ldwu */
 		__asm__ __volatile__(
 		"1:	ldq_u %1,0(%3)\n"
@@ -248,7 +244,6 @@
 			goto got_exception;
 		una_reg(reg) = tmp1|tmp2;
 		return;
-#endif
 
 	case 0x28: /* ldl */
 		__asm__ __volatile__(
@@ -293,7 +288,6 @@
 	/* Note that the store sequences do not indicate that they change
 	   memory because it _should_ be affecting nothing in this context.
 	   (Otherwise we have other, much larger, problems.)  */
-#ifdef __HAVE_CPU_BWX
 	case 0x0d: /* stw */
 		__asm__ __volatile__(
 		"1:	ldq_u %2,1(%5)\n"
@@ -323,7 +317,6 @@
 		if (error)
 			goto got_exception;
 		return;
-#endif
 
 	case 0x2c: /* stl */
 		__asm__ __volatile__(
@@ -385,9 +378,12 @@
 			goto got_exception;
 		return;
 	}
+
+	lock_kernel();
 	printk("Bad unaligned kernel access at %016lx: %p %lx %ld\n",
 		pc, va, opcode, reg);
 	do_exit(SIGSEGV);
+	unlock_kernel();
 	return;
 
 got_exception:
@@ -396,17 +392,23 @@
 	if ((fixup = search_exception_table(pc)) != 0) {
 		unsigned long newpc;
 		newpc = fixup_exception(una_reg, fixup, pc);
+
+		lock_kernel();
 		printk("Forwarding unaligned exception at %lx (%lx)\n",
 		       pc, newpc);
+		unlock_kernel();
+
 		(&regs)->pc = newpc;
 		return;
 	}
 
 	/* Yikes!  No one to forward the exception to.  */
+	lock_kernel();
 	printk("%s: unhandled unaligned exception at pc=%lx ra=%lx"
 	       " (bad address = %p)\n", current->comm,
 	       pc, una_reg(26), va);
 	do_exit(SIGSEGV);
+	unlock_kernel();
 }
 
 /*
@@ -466,50 +468,68 @@
  * uses them as temporary storage for integer memory to memory copies.
  * However, we need to deal with stt/ldt and sts/lds only.
  */
-asmlinkage void do_entUnaUser(void * va, unsigned long opcode, unsigned long reg,
-			      unsigned long * frame)
+
+#define OP_INT_MASK	( 1L << 0x28 | 1L << 0x2c   /* ldl stl */	\
+			| 1L << 0x29 | 1L << 0x2d   /* ldq stq */	\
+			| 1L << 0x0c | 1L << 0x0d ) /* ldwu stw */
+
+#define OP_WRITE_MASK	( 1L << 0x26 | 1L << 0x27   /* sts stt */	\
+			| 1L << 0x2c | 1L << 0x2d   /* stl stq */	\
+			| 1L << 0xd )		    /* stw */
+
+asmlinkage void do_entUnaUser(void * va, unsigned long opcode,
+			      unsigned long reg, unsigned long * frame)
 {
-	long dir, size;
-	unsigned long *reg_addr, *pc_addr, usp, zero = 0;
-	static int cnt = 0;
-	static long last_time = 0;
 	extern void alpha_write_fp_reg (unsigned long reg, unsigned long val);
 	extern unsigned long alpha_read_fp_reg (unsigned long reg);
 
+	static int cnt = 0;
+	static long last_time = 0;
+
+	unsigned long tmp1, tmp2, tmp3, tmp4;
+	unsigned long *reg_addr, *pc_addr, fake_reg;
+	unsigned long uac_bits;
+	long error;
+
 	pc_addr = frame + 7 + 20 + 1;			/* pc in PAL frame */
 
-	if (cnt >= 5 && jiffies - last_time > 5*HZ) {
-		cnt = 0;
+	/* Check the UAC bits to decide what the user wants us to do
+	   with the unaliged access.  */
+
+	uac_bits = (current->tss.flags >> UAC_SHIFT) & UAC_BITMASK;
+	if (!(uac_bits & UAC_NOPRINT)) {
+		if (cnt >= 5 && jiffies - last_time > 5*HZ) {
+			cnt = 0;
+		}
+		if (++cnt < 5) {
+			lock_kernel();
+			printk("%s(%d): unaligned trap at %016lx: %p %lx %ld\n",
+			       current->comm, current->pid,
+			       *pc_addr - 4, va, opcode, reg);
+			unlock_kernel();
+		}
+		last_time = jiffies;
 	}
-	if (++cnt < 5) {
-		printk("%s(%d): unaligned trap at %016lx: %p %lx %ld\n",
-		       current->comm, current->pid,
-		       *pc_addr - 4, va, opcode, reg);
+	if (uac_bits & UAC_SIGBUS) {
+		goto give_sigbus;
 	}
-	last_time = jiffies;
-
-	++unaligned[1].count;
-	unaligned[1].va = (unsigned long) va - 4;
-	unaligned[1].pc = *pc_addr;
-
-	dir = VERIFY_READ;
-	if (opcode & 0x4) {
-		/* it's a stl, stq, stt, or sts */
-		dir = VERIFY_WRITE;
-	}
-	size = 4;
-	if (opcode & 0x1) {
-		/* it's a quadword op */
-		size = 8;
-	}
-	if (verify_area(dir, va, size)) {
-		*pc_addr -= 4;	/* make pc point to faulting insn */
-		force_sig(SIGSEGV, current);
+	if (uac_bits & UAC_NOFIX) {
+		/* Not sure why you'd want to use this, but... */
 		return;
 	}
 
+	/* Don't bother reading ds in the access check since we already
+	   know that this came from the user.  Also rely on the fact that
+	   the page at TASK_SIZE is unmapped and so can't be touched anyway. */
+	if (!__access_ok((unsigned long)va, 0, USER_DS))
+		goto give_sigsegv;
+
+	++unaligned[1].count;
+	unaligned[1].va = (unsigned long)va;
+	unaligned[1].pc = *pc_addr - 4;
+
 	reg_addr = frame;
-	if (opcode >= 0x28) {
+	if ((1L << opcode) & OP_INT_MASK) {
 		/* it's an integer load/store */
 		switch (reg) {
 		      case 0: case 1: case 2: case 3: case 4:
@@ -542,57 +562,249 @@
 
 		      case 30:
 			/* usp in PAL regs */
-			usp = rdusp();
-			reg_addr = &usp;
+			fake_reg = rdusp();
+			reg_addr = &fake_reg;
 			break;
 
 		      case 31:
 			/* zero "register" */
-			reg_addr = &zero;
+			fake_reg = 0;
+			reg_addr = &fake_reg;
 			break;
 		}
 	}
 
+	/* We don't want to use the generic get/put unaligned macros as
+	   we want to trap exceptions.  Only if we actually get an
+	   exception will we decide whether we should have caught it.  */
+
 	switch (opcode) {
-	      case 0x22: /* lds */
-		alpha_write_fp_reg(reg, s_mem_to_reg(
-			get_unaligned((unsigned int *)va)));
-		break;
-	      case 0x26: /* sts */
-		put_unaligned(s_reg_to_mem(alpha_read_fp_reg(reg)),
-			      (unsigned int *)va);
+	case 0x0c: /* ldwu */
+		__asm__ __volatile__(
+		"1:	ldq_u %1,0(%3)\n"
+		"2:	ldq_u %2,1(%3)\n"
+		"	extwl %1,%3,%1\n"
+		"	extwh %2,%3,%2\n"
+		"3:\n"
+		".section __ex_table,\"a\"\n"
+		"	.gprel32 1b\n"
+		"	lda %1,3b-1b(%0)\n"
+		"	.gprel32 2b\n"
+		"	lda %2,3b-2b(%0)\n"
+		".previous"
+			: "=r"(error), "=&r"(tmp1), "=&r"(tmp2)
+			: "r"(va), "0"(0));
+		if (error)
+			goto give_sigsegv;
+		*reg_addr = tmp1|tmp2;
 		break;
 
-	      case 0x23: /* ldt */
-		alpha_write_fp_reg(reg, get_unaligned((unsigned long *)va));
-		break;
-	      case 0x27: /* stt */
-		put_unaligned(alpha_read_fp_reg(reg), (unsigned long *)va);
-		break;
+	case 0x22: /* lds */
+		__asm__ __volatile__(
+		"1:	ldq_u %1,0(%3)\n"
+		"2:	ldq_u %2,3(%3)\n"
+		"	extll %1,%3,%1\n"
+		"	extlh %2,%3,%2\n"
+		"3:\n"
+		".section __ex_table,\"a\"\n"
+		"	.gprel32 1b\n"
+		"	lda %1,3b-1b(%0)\n"
+		"	.gprel32 2b\n"
+		"	lda %2,3b-2b(%0)\n"
+		".previous"
+			: "=r"(error), "=&r"(tmp1), "=&r"(tmp2)
+			: "r"(va), "0"(0));
+		if (error)
+			goto give_sigsegv;
+		alpha_write_fp_reg(reg, s_mem_to_reg((int)(tmp1|tmp2)));
+		return;
 
-	      case 0x28: /* ldl */
-		*reg_addr = get_unaligned((int *)va);
-		break;
-	      case 0x2c: /* stl */
-		put_unaligned(*reg_addr, (int *)va);
-		break;
+	case 0x23: /* ldt */
+		__asm__ __volatile__(
+		"1:	ldq_u %1,0(%3)\n"
+		"2:	ldq_u %2,7(%3)\n"
+		"	extql %1,%3,%1\n"
+		"	extqh %2,%3,%2\n"
+		"3:\n"
+		".section __ex_table,\"a\"\n"
+		"	.gprel32 1b\n"
+		"	lda %1,3b-1b(%0)\n"
+		"	.gprel32 2b\n"
+		"	lda %2,3b-2b(%0)\n"
+		".previous"
+			: "=r"(error), "=&r"(tmp1), "=&r"(tmp2)
+			: "r"(va), "0"(0));
+		if (error)
+			goto give_sigsegv;
+		alpha_write_fp_reg(reg, tmp1|tmp2);
+		return;
 
-	      case 0x29: /* ldq */
-		*reg_addr = get_unaligned((long *)va);
+	case 0x28: /* ldl */
+		__asm__ __volatile__(
+		"1:	ldq_u %1,0(%3)\n"
+		"2:	ldq_u %2,3(%3)\n"
+		"	extll %1,%3,%1\n"
+		"	extlh %2,%3,%2\n"
+		"3:\n"
+		".section __ex_table,\"a\"\n"
+		"	.gprel32 1b\n"
+		"	lda %1,3b-1b(%0)\n"
+		"	.gprel32 2b\n"
+		"	lda %2,3b-2b(%0)\n"
+		".previous"
+			: "=r"(error), "=&r"(tmp1), "=&r"(tmp2)
+			: "r"(va), "0"(0));
+		if (error)
+			goto give_sigsegv;
+		*reg_addr = (int)(tmp1|tmp2);
 		break;
-	      case 0x2d: /* stq */
-		put_unaligned(*reg_addr, (long *)va);
+
+	case 0x29: /* ldq */
+		__asm__ __volatile__(
+		"1:	ldq_u %1,0(%3)\n"
+		"2:	ldq_u %2,7(%3)\n"
+		"	extql %1,%3,%1\n"
+		"	extqh %2,%3,%2\n"
+		"3:\n"
+		".section __ex_table,\"a\"\n"
+		"	.gprel32 1b\n"
+		"	lda %1,3b-1b(%0)\n"
+		"	.gprel32 2b\n"
+		"	lda %2,3b-2b(%0)\n"
+		".previous"
+			: "=r"(error), "=&r"(tmp1), "=&r"(tmp2)
+			: "r"(va), "0"(0));
+		if (error)
+			goto give_sigsegv;
+		*reg_addr = tmp1|tmp2;
 		break;
 
-	      default:
-		*pc_addr -= 4;	/* make pc point to faulting insn */
-		force_sig(SIGBUS, current);
+	/* Note that the store sequences do not indicate that they change
+	   memory because it _should_ be affecting nothing in this context.
+	   (Otherwise we have other, much larger, problems.)  */
+	case 0x0d: /* stw */
+		__asm__ __volatile__(
+		"1:	ldq_u %2,1(%5)\n"
+		"2:	ldq_u %1,0(%5)\n"
+		"	inswh %6,%5,%4\n"
+		"	inswl %6,%5,%3\n"
+		"	mskwh %2,%5,%2\n"
+		"	mskwl %1,%5,%1\n"
+		"	or %2,%4,%2\n"
+		"	or %1,%3,%1\n"
+		"3:	stq_u %2,1(%5)\n"
+		"4:	stq_u %1,0(%5)\n"
+		"5:\n"
+		".section __ex_table,\"a\"\n"
+		"	.gprel32 1b\n"
+		"	lda %2,5b-1b(%0)\n"
+		"	.gprel32 2b\n"
+		"	lda %1,5b-2b(%0)\n"
+		"	.gprel32 3b\n"
+		"	lda $31,5b-3b(%0)\n"
+		"	.gprel32 4b\n"
+		"	lda $31,5b-4b(%0)\n"
+		".previous"
+			: "=r"(error), "=&r"(tmp1), "=&r"(tmp2),
+			  "=&r"(tmp3), "=&r"(tmp4)
+			: "r"(va), "r"(*reg_addr), "0"(0));
+		if (error)
+			goto give_sigsegv;
+		return;
+
+	case 0x26: /* sts */
+		fake_reg = s_reg_to_mem(alpha_read_fp_reg(reg));
+		reg_addr = &fake_reg;
+		/* FALLTHRU */
+
+	case 0x2c: /* stl */
+		__asm__ __volatile__(
+		"1:	ldq_u %2,3(%5)\n"
+		"2:	ldq_u %1,0(%5)\n"
+		"	inslh %6,%5,%4\n"
+		"	insll %6,%5,%3\n"
+		"	msklh %2,%5,%2\n"
+		"	mskll %1,%5,%1\n"
+		"	or %2,%4,%2\n"
+		"	or %1,%3,%1\n"
+		"3:	stq_u %2,3(%5)\n"
+		"4:	stq_u %1,0(%5)\n"
+		"5:\n"
+		".section __ex_table,\"a\"\n"
+		"	.gprel32 1b\n"
+		"	lda %2,5b-1b(%0)\n"
+		"	.gprel32 2b\n"
+		"	lda %1,5b-2b(%0)\n"
+		"	.gprel32 3b\n"
+		"	lda $31,5b-3b(%0)\n"
+		"	.gprel32 4b\n"
+		"	lda $31,5b-4b(%0)\n"
+		".previous"
+			: "=r"(error), "=&r"(tmp1), "=&r"(tmp2),
+			  "=&r"(tmp3), "=&r"(tmp4)
+			: "r"(va), "r"(*reg_addr), "0"(0));
+		if (error)
+			goto give_sigsegv;
+		return;
+
+	case 0x27: /* stt */
+		fake_reg = alpha_read_fp_reg(reg);
+		reg_addr = &fake_reg;
+		/* FALLTHRU */
+
+	case 0x2d: /* stq */
+		__asm__ __volatile__(
+		"1:	ldq_u %2,7(%5)\n"
+		"2:	ldq_u %1,0(%5)\n"
+		"	insqh %6,%5,%4\n"
+		"	insql %6,%5,%3\n"
+		"	mskqh %2,%5,%2\n"
+		"	mskql %1,%5,%1\n"
+		"	or %2,%4,%2\n"
+		"	or %1,%3,%1\n"
+		"3:	stq_u %2,7(%5)\n"
+		"4:	stq_u %1,0(%5)\n"
+		"5:\n"
+		".section __ex_table,\"a\"\n\t"
+		"	.gprel32 1b\n"
+		"	lda %2,5b-1b(%0)\n"
+		"	.gprel32 2b\n"
+		"	lda %1,5b-2b(%0)\n"
+		"	.gprel32 3b\n"
+		"	lda $31,5b-3b(%0)\n"
+		"	.gprel32 4b\n"
+		"	lda $31,5b-4b(%0)\n"
+		".previous"
+			: "=r"(error), "=&r"(tmp1), "=&r"(tmp2),
+			  "=&r"(tmp3), "=&r"(tmp4)
+			: "r"(va), "r"(*reg_addr), "0"(0));
+		if (error)
+			goto give_sigsegv;
 		return;
-	}
 
-	if (opcode >= 0x28 && reg == 30 && dir == VERIFY_WRITE) {
-		wrusp(usp);
+	default:
+		/* What instruction were you trying to use, exactly?  */
+		goto give_sigbus;
 	}
+
+	/* Only integer loads should get here; everyone else returns early. */
+	if (reg == 30)
+		wrusp(fake_reg);
+	return;
+
+give_sigsegv:
+	*pc_addr -= 4;  /* make pc point to faulting insn */
+	lock_kernel();
+	force_sig(SIGSEGV, current);
+	unlock_kernel();
+	return;
+
+give_sigbus:
+	*pc_addr -= 4;
+	lock_kernel();
+	force_sig(SIGBUS, current);
+	unlock_kernel();
+	return;
 }
 
 /*
@@ -610,8 +822,11 @@
 			  unsigned long a3, unsigned long a4, unsigned long a5,
 			  struct pt_regs regs)
 {
-	if (regs.r0 != 112)
+	lock_kernel();
+	/* Only report OSF system calls.  */
+	if (regs.r0 != 112 && regs.r0 < 300)
 		printk("<sc %ld(%lx,%lx,%lx)>", regs.r0, a0, a1, a2);
+	unlock_kernel();
 	return -1;
 }
 
@@ -621,16 +836,11 @@
 extern asmlinkage void entUna(void);
 extern asmlinkage void entSys(void);
 
+register unsigned long gptr __asm__("$29");
+
 void trap_init(void)
 {
-	unsigned long gptr;
-
-	/*
-	 * Tell PAL-code what global pointer we want in the kernel..
-	 */
-	__asm__("br %0,___tmp\n"
-		"___tmp:\tldgp %0,0(%0)"
-		: "=r" (gptr));
+	/* Tell PAL-code what global pointer we want in the kernel.  */
 	wrkgp(gptr);
 
 	wrent(entArith, 1);
diff -u --recursive --new-file v2.1.35/linux/arch/alpha/mm/init.c linux/arch/alpha/mm/init.c
--- v2.1.35/linux/arch/alpha/mm/init.c	Mon Apr 14 16:28:05 1997
+++ linux/arch/alpha/mm/init.c	Tue Apr 22 22:38:40 1997
@@ -150,7 +150,7 @@
 	start_mem = PAGE_ALIGN(start_mem);
 
 	/*
-	 * Mark the pages used by the kernel as reserved..
+	 * Mark the pages used by the kernel as reserved.
 	 */
 	tmp = KERNEL_START;
 	while (tmp < start_mem) {
@@ -171,9 +171,19 @@
 	return;
 }
 
-void free_initmem(void)
+void free_initmem (void)
 {
-	/* To be written */
+        extern char __init_begin, __init_end;
+        unsigned long addr;
+
+        addr = (unsigned long)(&__init_begin);
+        for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
+                mem_map[MAP_NR(addr)].flags &= ~(1 << PG_reserved);
+                atomic_set(&mem_map[MAP_NR(addr)].count, 1);
+                free_page(addr);
+        }
+        printk ("Freeing unused kernel memory: %dk freed\n",
+		(&__init_end - &__init_begin) >> 10);
 }
 
 void si_meminfo(struct sysinfo *val)
diff -u --recursive --new-file v2.1.35/linux/arch/alpha/vmlinux.lds linux/arch/alpha/vmlinux.lds
--- v2.1.35/linux/arch/alpha/vmlinux.lds	Fri Sep 15 01:23:05 1995
+++ linux/arch/alpha/vmlinux.lds	Tue Apr 22 22:38:40 1997
@@ -1,50 +1,46 @@
-OUTPUT_FORMAT("ecoff-littlealpha")
+OUTPUT_FORMAT("elf64-alpha")
 ENTRY(__start)
 SECTIONS
 {
-  .text 0xfffffc0000310000: {
-     _ftext = . ;
-     __istart = . ;
-     eprol  =  .;
-    *(.text)
-     __fstart = . ;
-     _etext  =  .;
-  }
-  .rdata : {
-    *(.rdata)
-  }
-  .pdata : {
-     _fpdata = .;
-    *(.pdata)
-  }
-  .data : {
-     _fdata = .;
-    *(.data)
-    CONSTRUCTORS
-  }
-  .xdata : {
-    *(.xdata)
-  }
-   _gp = ALIGN (16) + 0x8000;
-  .lit8 : {
-    *(.lit8)
-  }
-  .lita : {
-    *(.lita)
-  }
-  .sdata : {
-    *(.sdata)
-  }
-   _EDATA  =  .;
-   _FBSS = .;
-  .sbss : {
-    *(.sbss)
-    *(.scommon)
-    . = ALIGN(16);
-  }
-  .bss : {
-    *(.bss)
-    *(COMMON)
-  }
-   _end = .;
+   . = 0xfffffc0000310000;
+   _text = .;
+   .text : { *(.text) }
+   _etext = .;
+
+  /* Exception table */
+  . = ALIGN(16);
+  __start___ex_table = .;
+  __ex_table : { *(__ex_table) }
+  __stop___ex_table = .;
+
+  /* Kernel symbol table */
+  . = ALIGN(8);
+  __start___ksymtab = .;
+  __ksymtab : { *(__ksymtab) }
+  __stop___ksymtab = .;
+  .kstrtab : { *(.kstrtab) }
+
+  /* Startup code */
+  . = ALIGN(8192);
+  __init_begin = .;
+  .text.init : { *(.text.init) }
+  .data.init : { *(.data.init) }
+  . = ALIGN(8192);
+  __init_end = .;
+
+  /* Global data */
+  _data = .;
+  .rodata : { *(.rodata) }
+  .data : { *(.data) CONSTRUCTORS }
+  .got : { *(.got) }
+  .sdata : { *(.sdata) }
+  _edata = .;
+  _bss = .;
+  .sbss : { *(.sbss) *(.scommon) }
+  .bss : { *(.bss) *(COMMON) }
+  _end = .;
+
+  .mdebug 0 : { *(.mdebug) }
+  .note 0 : { *(.note) }
+  .comment 0 : { *(.comment) }
 }
diff -u --recursive --new-file v2.1.35/linux/arch/i386/Makefile linux/arch/i386/Makefile
--- v2.1.35/linux/arch/i386/Makefile	Wed Apr 16 14:14:59 1997
+++ linux/arch/i386/Makefile	Thu Apr 17 18:02:14 1997
@@ -21,7 +21,7 @@
 CPP=$(CC) -E
 OBJCOPY=$(CROSS_COMPILE)objcopy -O binary -R .note -R .comment -S
 LDFLAGS=-e stext
-LINKFLAGS =-T arch/i386/vmlinux.lds $(LDFLAGS)
+LINKFLAGS =-T $(TOPDIR)/arch/i386/vmlinux.lds $(LDFLAGS)
 
 CFLAGS := $(CFLAGS) -pipe -fno-strength-reduce
 
diff -u --recursive --new-file v2.1.35/linux/arch/i386/boot/Makefile linux/arch/i386/boot/Makefile
--- v2.1.35/linux/arch/i386/boot/Makefile	Wed Apr 16 14:14:59 1997
+++ linux/arch/i386/boot/Makefile	Thu Apr 17 14:24:47 1997
@@ -40,8 +40,8 @@
 	cp $(TOPDIR)/System.map $(INSTALL_PATH)/
 	if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi
 
-install: $(CONFIGURE) zImage
-	sh ./install.sh $(VERSION).$(PATCHLEVEL).$(SUBLEVEL) zImage $(TOPDIR)/System.map "$(INSTALL_PATH)"
+install: $(CONFIGURE) $(BOOTIMAGE)
+	sh -x ./install.sh $(VERSION).$(PATCHLEVEL).$(SUBLEVEL) $(BOOTIMAGE) $(TOPDIR)/System.map "$(INSTALL_PATH)"
 
 tools/build: tools/build.c
 	$(HOSTCC) $(HOSTCFLAGS) -o $@ $< -I$(TOPDIR)/include
diff -u --recursive --new-file v2.1.35/linux/arch/i386/kernel/bios32.c linux/arch/i386/kernel/bios32.c
--- v2.1.35/linux/arch/i386/kernel/bios32.c	Wed Apr 16 14:14:59 1997
+++ linux/arch/i386/kernel/bios32.c	Wed Apr 16 14:53:37 1997
@@ -738,7 +738,7 @@
     outb (0x00, 0xCFB);
     outb (0x00, 0xCF8);
     outb (0x00, 0xCFA);
-    if (inb (0xCF8) == 0x00 && inb (0xCFC) == 0x00) {
+    if (inb (0xCF8) == 0x00 && inb (0xCFB) == 0x00) {
 	restore_flags(flags);
 	printk("pcibios_init: Using configuration type 2\n");
 	return &pci_direct_conf2;
diff -u --recursive --new-file v2.1.35/linux/arch/i386/kernel/entry.S linux/arch/i386/kernel/entry.S
--- v2.1.35/linux/arch/i386/kernel/entry.S	Thu Mar 27 14:39:59 1997
+++ linux/arch/i386/kernel/entry.S	Tue Apr 22 22:49:38 1997
@@ -524,6 +524,7 @@
 	.long SYMBOL_NAME(sys_vm86)
 	.long SYMBOL_NAME(sys_query_module)
 	.long SYMBOL_NAME(sys_poll)
-	.rept NR_syscalls-168
+	.long SYMBOL_NAME(sys_nfsservctl)
+	.rept NR_syscalls-169
 		.long SYMBOL_NAME(sys_ni_syscall)
 	.endr
diff -u --recursive --new-file v2.1.35/linux/arch/i386/kernel/head.S linux/arch/i386/kernel/head.S
--- v2.1.35/linux/arch/i386/kernel/head.S	Wed Apr 16 14:14:59 1997
+++ linux/arch/i386/kernel/head.S	Mon Apr 21 11:34:01 1997
@@ -38,15 +38,16 @@
 	orw %bx,%bx
 	jz 1f
 /*
- *	New page tables may be in 4Mbyte page mode
+ *	New page tables may be in 4Mbyte page mode and may
+ *	be using the global pages.
  */
 #ifdef GAS_KNOWS_CR4
 	movl %cr4,%eax		# Turn on 4Mb pages
-	orl $16,%eax
+	orl $16+128,%eax
 	movl %eax,%cr4
 #else
 	.byte 0x0f,0x20,0xe0
-	orl $16,%eax
+	orl $16+128,%eax
 	.byte 0x0f,0x22,0xe0
 #endif
 	movl %eax,%cr3		/* flush TLB as per app note */
diff -u --recursive --new-file v2.1.35/linux/arch/i386/kernel/i386_ksyms.c linux/arch/i386/kernel/i386_ksyms.c
--- v2.1.35/linux/arch/i386/kernel/i386_ksyms.c	Sun Apr 13 10:18:20 1997
+++ linux/arch/i386/kernel/i386_ksyms.c	Wed Apr 16 16:04:15 1997
@@ -6,6 +6,7 @@
 #include <linux/mca.h>
 #include <linux/sched.h>
 #include <linux/in6.h>
+#include <linux/interrupt.h>
 
 #include <asm/semaphore.h>
 #include <asm/processor.h>
@@ -31,7 +32,7 @@
 EXPORT_SYMBOL_NOVERS(__down_failed);
 EXPORT_SYMBOL_NOVERS(__down_failed_interruptible);
 EXPORT_SYMBOL_NOVERS(__up_wakeup);
-
+EXPORT_SYMBOL(__intel_bh_counter);
 /* Networking helper routines. */
 EXPORT_SYMBOL(csum_partial_copy);
 
@@ -42,6 +43,13 @@
 EXPORT_SYMBOL(active_kernel_processor);
 EXPORT_SYMBOL(smp_invalidate_needed);
 EXPORT_SYMBOL_NOVERS(__lock_kernel);
+
+/* Global SMP irq stuff */
+EXPORT_SYMBOL(global_irq_holder);
+EXPORT_SYMBOL(__global_cli);
+EXPORT_SYMBOL(__global_sti);
+EXPORT_SYMBOL(__global_save_flags);
+EXPORT_SYMBOL(__global_restore_flags);
 #endif
 
 #ifdef CONFIG_MCA
diff -u --recursive --new-file v2.1.35/linux/arch/i386/kernel/irq.c linux/arch/i386/kernel/irq.c
--- v2.1.35/linux/arch/i386/kernel/irq.c	Wed Apr 16 14:14:59 1997
+++ linux/arch/i386/kernel/irq.c	Wed Apr 16 16:52:23 1997
@@ -128,6 +128,11 @@
  * other interrupts would have to avoid using the jiffies variable for delay
  * and interval timing operations to avoid hanging the system.
  */
+
+#if NR_IRQS != 16
+#error make irq stub building NR_IRQS dependent and remove me.
+#endif
+
 BUILD_TIMER_IRQ(FIRST,0,0x01)
 BUILD_IRQ(FIRST,1,0x02)
 BUILD_IRQ(FIRST,2,0x04)
@@ -231,7 +236,7 @@
 	int i, len = 0;
 	struct irqaction * action;
 
-	for (i = 0 ; i < 16 ; i++) {
+	for (i = 0 ; i < NR_IRQS ; i++) {
 		action = irq_action[i];
 		if (!action) 
 			continue;
@@ -734,15 +739,9 @@
 	outb_p(LATCH & 0xff , 0x40);	/* LSB */
 	outb(LATCH >> 8 , 0x40);	/* MSB */
 
-	for (i = 0; i < 16 ; i++)
+	for (i = 0; i < NR_IRQS ; i++)
 		set_intr_gate(0x20+i,bad_interrupt[i]);
 
-	/*
-	 * This bit is a hack because we don't send timer messages to all
-	 * processors yet. It has to be here .. it doesn't work if you put
-	 * it down the bottom - assembler explodes 8)
-	 */
-
 #ifdef __SMP__	
 	/*
 	 * NOTE! The local APIC isn't very good at handling
@@ -752,8 +751,19 @@
 	 * want to spread these out a bit so that they don't
 	 * all fall in the same interrupt level
 	 */
+
+	/*
+	 * The reschedule interrupt slowly changes it's functionality,
+	 * while so far it was a kind of broadcasted timer interrupt,
+	 * in the future it should become a CPU-to-CPU rescheduling IPI,
+	 * driven by schedule() ?
+	 *
+	 * [ It has to be here .. it doesn't work if you put
+	 *   it down the bottom - assembler explodes 8) ]
+	 */
 	/* IRQ '16' (trap 0x30) - IPI for rescheduling */
 	set_intr_gate(0x20+i, reschedule_interrupt);
+
 
 	/* IRQ '17' (trap 0x31) - IPI for invalidation */
 	set_intr_gate(0x21+i, invalidate_interrupt);
diff -u --recursive --new-file v2.1.35/linux/arch/i386/kernel/irq.h linux/arch/i386/kernel/irq.h
--- v2.1.35/linux/arch/i386/kernel/irq.h	Wed Apr 16 14:14:59 1997
+++ linux/arch/i386/kernel/irq.h	Wed Apr 16 16:52:23 1997
@@ -266,4 +266,26 @@
 	UNBLK_##chip(mask) \
 	"jmp ret_from_intr\n");
 
+/*
+ * x86 profiling function, SMP safe. We might want to do this in
+ * assembly totally?
+ */
+static inline void x86_do_profile (unsigned long eip)
+{
+	if (prof_buffer && current->pid) {
+		extern int _stext;
+		eip -= (unsigned long) &_stext;
+		eip >>= prof_shift;
+		if (eip < prof_len)
+			atomic_inc((atomic_t *)&prof_buffer[eip]);
+		else
+		/*
+		 * Dont ignore out-of-bounds EIP values silently,
+		 * put them into the last histogram slot, so if
+		 * present, they will show up as a sharp peak.
+		 */
+			atomic_inc((atomic_t *)&prof_buffer[prof_len-1]);
+	}
+}
+
 #endif
diff -u --recursive --new-file v2.1.35/linux/arch/i386/kernel/ptrace.c linux/arch/i386/kernel/ptrace.c
--- v2.1.35/linux/arch/i386/kernel/ptrace.c	Sun Jan 26 02:07:04 1997
+++ linux/arch/i386/kernel/ptrace.c	Thu Apr 17 13:20:40 1997
@@ -584,10 +584,9 @@
 
 asmlinkage void syscall_trace(void)
 {
-	lock_kernel();
 	if ((current->flags & (PF_PTRACED|PF_TRACESYS))
 			!= (PF_PTRACED|PF_TRACESYS))
-		goto out;
+		return;
 	current->exit_code = SIGTRAP;
 	current->state = TASK_STOPPED;
 	notify_parent(current);
@@ -597,9 +596,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;
-out:
-	unlock_kernel();
 }
diff -u --recursive --new-file v2.1.35/linux/arch/i386/kernel/signal.c linux/arch/i386/kernel/signal.c
--- v2.1.35/linux/arch/i386/kernel/signal.c	Sun Jan 26 02:07:04 1997
+++ linux/arch/i386/kernel/signal.c	Thu Apr 17 13:20:40 1997
@@ -23,7 +23,9 @@
 
 #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);
 
 /*
@@ -31,24 +33,21 @@
  */
 asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, unsigned long set)
 {
+	struct pt_regs * regs = (struct pt_regs *) &restart;
 	unsigned long mask;
-	struct pt_regs * regs;
-	int res = -EINTR;
 
-	lock_kernel();
-	regs = (struct pt_regs *) &restart;
+	spin_lock_irq(&current->sigmask_lock);
 	mask = current->blocked;
 	current->blocked = set & _BLOCKABLE;
+	spin_unlock_irq(&current->sigmask_lock);
+
 	regs->eax = -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 res;
 }
 
 static inline void restore_i387_hard(struct _fpstate *buf)
@@ -108,9 +107,7 @@
 __asm__("mov %w0,%%" #seg: :"r" (tmp)); }
 	struct sigcontext * context;
 	struct pt_regs * regs;
-	int res;
 
-	lock_kernel();
 	regs = (struct pt_regs *) &__unused;
 	context = (struct sigcontext *) regs->esp;
 	if (verify_area(VERIFY_READ, context, sizeof(*context)))
@@ -136,11 +133,12 @@
 			goto badframe;
 		restore_i387(buf);
 	}
-	res = context->eax;
-	unlock_kernel();
-	return res;
+	return context->eax;
+
 badframe:
+	lock_kernel();
 	do_exit(SIGSEGV);
+	unlock_kernel();
 }
 
 static inline struct _fpstate * save_i387_hard(struct _fpstate * buf)
@@ -194,7 +192,7 @@
 		frame = (unsigned long *) sa->sa_restorer;
 	frame -= 64;
 	if (!access_ok(VERIFY_WRITE,frame,64*4))
-		do_exit(SIGSEGV);
+		goto segv_and_exit;
 
 /* set up the "normal" stack seen by the signal handler (iBCS2) */
 #define __CODE ((unsigned long)(frame+24))
@@ -206,7 +204,7 @@
        We use __put_user() here because the access_ok() call was already
        done earlier. */  
 	if (__put_user(__CODE,frame))
-		do_exit(SIGSEGV);
+		goto segv_and_exit;
 	if (current->exec_domain && current->exec_domain->signal_invmap)
 		__put_user(current->exec_domain->signal_invmap[signr], frame+1);
 	else
@@ -259,6 +257,12 @@
 		regs->xcs = USER_CS;
 	}
 	regs->eflags &= ~TF_MASK;
+	return;
+
+segv_and_exit:
+	lock_kernel();
+	do_exit(SIGSEGV);
+	unlock_kernel();
 }
 
 /*
@@ -292,8 +296,11 @@
 
 	if (sa->sa_flags & SA_ONESHOT)
 		sa->sa_handler = NULL;
-	if (!(sa->sa_flags & SA_NOMASK))
+	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);
+	}
 }
 
 /*
@@ -310,9 +317,7 @@
 	unsigned long mask;
 	unsigned long signr;
 	struct sigaction * sa;
-	int res;
 
-	lock_kernel();
 	mask = ~current->blocked;
 	while ((signr = current->signal & mask)) {
 		/*
@@ -322,6 +327,9 @@
 		 */
 		struct task_struct *t=current;
 		__asm__("bsf %3,%1\n\t"
+#ifdef __SMP__
+			"lock ; "
+#endif
 			"btrl %1,%0"
 			:"=m" (t->signal),"=r" (signr)
 			:"0" (t->signal), "1" (signr));
@@ -338,7 +346,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;
@@ -347,7 +357,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;
 		}
@@ -380,14 +390,19 @@
 				}
 				/* 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();
 			}
 		}
 		handle_signal(signr, sa, oldmask, regs);
-		res = 1;
-		goto out;
+		return 1;
 	}
 
 	/* Did we come from a system call? */
@@ -400,8 +415,5 @@
 			regs->eip -= 2;
 		}
 	}
-	res = 0;
-out:
-	unlock_kernel();
-	return res;
+	return 0;
 }
diff -u --recursive --new-file v2.1.35/linux/arch/i386/kernel/smp.c linux/arch/i386/kernel/smp.c
--- v2.1.35/linux/arch/i386/kernel/smp.c	Wed Apr 16 14:14:59 1997
+++ linux/arch/i386/kernel/smp.c	Wed Apr 16 16:52:23 1997
@@ -49,6 +49,9 @@
 #include "irq.h"
 
 extern unsigned long start_kernel, _etext;
+extern void update_one_process( struct task_struct *p,
+                                unsigned long ticks, unsigned long user,
+                                unsigned long system);
 void setup_APIC_clock (void);
 
 /*
@@ -1307,37 +1310,6 @@
 }
 
 /*
- * Platform specific profiling function.
- * it builds a 'prof_shift' resolution EIP distribution histogram
- *
- * it's SMP safe.
- */
-
-static inline void x86_do_profile (unsigned long eip)
-{
-	if (prof_buffer && current->pid) {
-		extern int _stext;
-		eip -= (unsigned long) &_stext;
-		eip >>= prof_shift;
-		if (eip < prof_len)
-			atomic_inc(&prof_buffer[eip]);
-		else
-		/*
-		 * Dont ignore out-of-bounds EIP values silently,
-		 * put them into the last histogram slot, so if
-		 * present, they will show up as a sharp peak.
-		 */
-			atomic_inc(&prof_buffer[prof_len-1]);
-	}
-}
-
-unsigned int prof_multiplier[NR_CPUS];
-unsigned int prof_counter[NR_CPUS];
-
-extern void update_one_process(	struct task_struct *p,
-				unsigned long ticks, unsigned long user,
-				unsigned long system);
-/*
  * Local timer interrupt handler. It does both profiling and
  * process statistics/rescheduling.
  *
@@ -1346,14 +1318,19 @@
  * multiplier is 1 and it can be changed by writing a 4 bytes multiplier
  * value into /proc/profile.
  */
+
+unsigned int prof_multiplier[NR_CPUS];
+unsigned int prof_counter[NR_CPUS];
+
 static inline void smp_local_timer_interrupt(struct pt_regs * regs)
 {
 	int cpu = smp_processor_id();
+
 	/*
-	 * Both the profiling function and the statistics
-	 * counters are SMP safe. We leave the APIC irq
-	 * unacked while updating the profiling info, thus
-	 * we cannot be interrupted by the same APIC interrupt.
+	 * The profiling function is SMP safe. (nothing can mess
+	 * around with "current", and the profiling counters are
+	 * updated with atomic operations). This is especially
+	 * useful with a profiling multiplier != 1
 	 */
 	if (!user_mode(regs))
 		x86_do_profile (regs->eip);
@@ -1363,13 +1340,10 @@
 		struct task_struct * p = current;
 
 		/*
-		 * We mess around with thread statistics, but
-		 * since we are the CPU running it, we dont
-		 * have to lock it. We assume that switch_to()
-		 * protects 'current' against local irqs via __cli.
-		 *
-		 * kernel statistics counters are updated via atomic
-		 * operations.
+		 * After doing the above, we need to make like
+		 * a normal interrupt - otherwise timer interrupts
+		 * ignore the global interrupt lock, which is the
+		 * WrongThing (tm) to do.
 		 */
 
 		if (user_mode(regs))
@@ -1377,7 +1351,9 @@
 		else
 			system=1;
 
+		irq_enter(cpu, 0);
 		if (p->pid) {
+
 			update_one_process(p, 1, user, system);
 
 			p->counter -= 1;
@@ -1386,25 +1362,21 @@
 				need_resched = 1;
 			}
 			if (p->priority < DEF_PRIORITY)
-				atomic_add (user, &kstat.cpu_nice);
+				kstat.cpu_nice += user;
 			else
-				atomic_add (user, &kstat.cpu_user);
+				kstat.cpu_user += user;
 
-			atomic_add (system, &kstat.cpu_system);
+			kstat.cpu_system += system;
 		
 		} else {
 #ifdef __SMP_PROF__
 			if (test_bit(cpu,&smp_idle_map))
 				smp_idle_count[cpu]++;
 #endif
-			/*
-			 * This is a hack until we have need_resched[]
-			 */
-			if (read_smp_counter(&smp_process_available))
-				need_resched=1;
 		}
-
 		prof_counter[cpu]=prof_multiplier[cpu];
+
+		irq_exit(cpu, 0);
 	}
 
 #ifdef __SMP_PROF__
@@ -1432,8 +1404,6 @@
  */
 void smp_apic_timer_interrupt(struct pt_regs * regs)
 {
-	int cpu = smp_processor_id();
-
 	/*
 	 * NOTE! We'd better ACK the irq immediately,
 	 * because timer handling can be slow, and we
@@ -1442,15 +1412,7 @@
 	 */
 	ack_APIC_irq ();
 
-	/*
-	 * After doing the above, we need to make like
-	 * a normal interrupt - otherwise timer interrupts
-	 * ignore the global interrupt lock, which is the
-	 * WrongThing (tm) to do.
-	 */
-	irq_enter(cpu, 0);
 	smp_local_timer_interrupt(regs);
-	irq_exit(cpu, 0);
 }
 
 /*	
diff -u --recursive --new-file v2.1.35/linux/arch/i386/kernel/time.c linux/arch/i386/kernel/time.c
--- v2.1.35/linux/arch/i386/kernel/time.c	Wed Apr 16 14:14:59 1997
+++ linux/arch/i386/kernel/time.c	Wed Apr 16 16:52:23 1997
@@ -33,6 +33,11 @@
 #include <linux/timex.h>
 #include <linux/config.h>
 
+/*
+ * for x86_do_profile()
+ */
+#include "irq.h"
+
 extern int setup_x86_irq(int, struct irqaction *);
 extern volatile unsigned long lost_ticks;
 
@@ -364,29 +369,6 @@
 
 /* last time the cmos clock got updated */
 static long last_rtc_update = 0;
-
-
-/*
- * Move this to a header file - right now it shows
- * up both here and in smp.c
- */
-static inline void x86_do_profile (unsigned long eip)
-{
-	if (prof_buffer && current->pid) {
-		extern int _stext;
-		eip -= (unsigned long) &_stext;
-		eip >>= prof_shift;
-		if (eip < prof_len)
-			atomic_inc(&prof_buffer[eip]);
-		else
-		/*
-		 * Dont ignore out-of-bounds EIP values silently,
-		 * put them into the last histogram slot, so if
-		 * present, they will show up as a sharp peak.
-		 */
-			atomic_inc(&prof_buffer[prof_len-1]);
-	}
-}
 
 /*
  * timer_interrupt() needs to keep up the real-time clock,
diff -u --recursive --new-file v2.1.35/linux/arch/i386/mm/init.c linux/arch/i386/mm/init.c
--- v2.1.35/linux/arch/i386/mm/init.c	Wed Apr 16 14:15:00 1997
+++ linux/arch/i386/mm/init.c	Tue Apr 22 22:44:18 1997
@@ -27,6 +27,8 @@
 #include <asm/pgtable.h>
 #include <asm/dma.h>
 
+const char bad_pmd_string[] = "Bad pmd in pte_alloc: %08lx\n";
+
 extern void die_if_kernel(char *,struct pt_regs *,long);
 extern void show_net_buffers(void);
 
@@ -102,6 +104,48 @@
 extern char _text, _etext, _edata, __bss_start, _end;
 extern char __init_begin, __init_end;
 
+#define X86_CR4_VME		0x0001		/* enable vm86 extensions */
+#define X86_CR4_PVI		0x0002		/* virtual interrupts flag enable */
+#define X86_CR4_TSD		0x0004		/* disable time stamp at ipl 3 */
+#define X86_CR4_DE		0x0008		/* enable debugging extensions */
+#define X86_CR4_PSE		0x0010		/* enable page size extensions */
+#define X86_CR4_PAE		0x0020		/* enable physical address extensions */
+#define X86_CR4_MCE		0x0040		/* Machine check enable */
+#define X86_CR4_PGE		0x0080		/* enable global pages */
+#define X86_CR4_PCE		0x0100		/* enable performance counters at ipl 3 */
+
+#define X86_FEATURE_FPU		0x0001		/* internal FPU */
+#define X86_FEATURE_VME		0x0002		/* vm86 extensions */
+#define X86_FEATURE_DE		0x0004		/* debugging extensions */
+#define X86_FEATURE_PSE		0x0008		/* Page size extensions */
+#define X86_FEATURE_TSC		0x0010		/* Time stamp counter */
+#define X86_FEATURE_MSR		0x0020		/* RDMSR/WRMSR */
+#define X86_FEATURE_PAE		0x0040		/* Physical address extension */
+#define X86_FEATURE_MCE		0x0080		/* Machine check exception */
+#define X86_FEATURE_CXS		0x0100		/* cmpxchg8 available */
+#define X86_FEATURE_APIC	0x0200		/* internal APIC */
+#define X86_FEATURE_10		0x0400
+#define X86_FEATURE_11		0x0800
+#define X86_FEATURE_MTRR	0x1000		/* memory type registers */
+#define X86_FEATURE_PGE		0x2000		/* Global page */
+#define X86_FEATURE_MCA		0x4000		/* Machine Check Architecture */
+#define X86_FEATURE_CMOV	0x8000		/* Cmov/fcomi */
+
+#ifdef GAS_KNOWS_CR4
+#define read_cr4	"movl %%cr4,%%eax"
+#define write_cr4	"movl %%eax,%%cr4"
+#else
+#define read_cr4	".byte 0x0f,0x20,0xe0"
+#define write_cr4	".byte 0x0f,0x22,0xe0"
+#endif
+
+#define set_in_cr4(x) \
+__asm__(read_cr4 "\n\t" \
+	"orl %0,%%eax\n\t" \
+	write_cr4 \
+	: : "i" (x) \
+	:"ax");
+
 /*
  * paging_init() sets up the page tables - note that the first 4MB are
  * already mapped by head.S.
@@ -156,27 +200,25 @@
 	/* Map whole memory from 0xC0000000 */
 
 	while (address < end_mem) {
-		if (x86_capability & 8) {
-			/*
-			 * If we're running on a Pentium CPU, we can use the 4MB
-			 * page tables. 
-			 *
-			 * The page tables we create span up to the next 4MB
-			 * virtual memory boundary, but that's OK as we won't
-			 * use that memory anyway.
-			 */
-#ifdef GAS_KNOWS_CR4
-			__asm__("movl %%cr4,%%eax\n\t"
-				"orl $16,%%eax\n\t"
-				"movl %%eax,%%cr4"
-				: : :"ax");
-#else
-			__asm__(".byte 0x0f,0x20,0xe0\n\t"
-				"orl $16,%%eax\n\t"
-				".byte 0x0f,0x22,0xe0"
-				: : :"ax");
-#endif
+		/*
+		 * If we're running on a Pentium CPU, we can use the 4MB
+		 * page tables. 
+		 *
+		 * The page tables we create span up to the next 4MB
+		 * virtual memory boundary, but that's OK as we won't
+		 * use that memory anyway.
+		 */
+		if (x86_capability & X86_FEATURE_PSE) {
+			unsigned long __pe;
+
+			set_in_cr4(X86_CR4_PSE);
 			wp_works_ok = 1;
+			__pe = _PAGE_TABLE + _PAGE_4M + __pa(address);
+			/* Make it "global" too if supported */
+			if (x86_capability & X86_FEATURE_PGE) {
+				set_in_cr4(X86_CR4_PGE);
+				__pe += _PAGE_GLOBAL;
+			}
 			pgd_val(pg_dir[768]) = _PAGE_TABLE + _PAGE_4M + __pa(address);
 			pg_dir++;
 			address += 4*1024*1024;
@@ -322,6 +364,7 @@
 		atomic_set(&mem_map[MAP_NR(addr)].count, 1);
 		free_page(addr);
 	}
+	printk ("Freeing unused kernel memory: %dk freed\n", (&__init_end - &__init_begin) >> 10);
 }
 
 void si_meminfo(struct sysinfo *val)
diff -u --recursive --new-file v2.1.35/linux/arch/m68k/Makefile linux/arch/m68k/Makefile
--- v2.1.35/linux/arch/m68k/Makefile	Fri Apr  4 08:52:17 1997
+++ linux/arch/m68k/Makefile	Thu Apr 17 13:20:40 1997
@@ -36,7 +36,7 @@
 
 LINKFLAGS = -Ttext 0x1000
 
-CFLAGS := $(CFLAGS) -pipe
+CFLAGS := $(CFLAGS) -pipe -fno-strength-reduce
 
 ifdef CONFIG_OPTIMIZE_040
 CFLAGS := $(CFLAGS) -m68040
@@ -46,40 +46,46 @@
 CFLAGS := $(CFLAGS) -m68020-40
 endif
 
+ifdef CONFIG_KGDB
+# If configured for kgdb support, include debugging infos and keep the
+# frame pointer
+CFLAGS := $(subst -fomit-frame-pointer,,$(CFLAGS)) -g
+endif
+
 HEAD := arch/m68k/kernel/head.o
 
 SUBDIRS += arch/m68k/kernel arch/m68k/mm arch/m68k/lib
-ARCHIVES := arch/m68k/kernel/kernel.o arch/m68k/mm/mm.o $(ARCHIVES)
+CORE_FILES := arch/m68k/kernel/kernel.o arch/m68k/mm/mm.o $(CORE_FILES)
 LIBS += arch/m68k/lib/lib.a
 
 ifdef CONFIG_AMIGA
-ARCHIVES := $(ARCHIVES) arch/m68k/amiga/amiga.o
+CORE_FILES := $(CORE_FILES) arch/m68k/amiga/amiga.o
 SUBDIRS := $(SUBDIRS) arch/m68k/amiga
 endif
 
 ifdef CONFIG_ATARI
-ARCHIVES := $(ARCHIVES) arch/m68k/atari/atari.o
+CORE_FILES := $(CORE_FILES) arch/m68k/atari/atari.o
 SUBDIRS := $(SUBDIRS) arch/m68k/atari
 endif
 
 ifdef CONFIG_MAC
-ARCHIVES := $(ARCHIVES) arch/m68k/mac/mac.o
+CORE_FILES := $(CORE_FILES) arch/m68k/mac/mac.o
 SUBDIRS := $(SUBDIRS) arch/m68k/mac
 endif
 
 ifdef CONFIG_VT
 # add in console.a after {amiga,atari}.o that need it
-ARCHIVES := $(ARCHIVES) arch/m68k/console/console.a
+CORE_FILES := $(CORE_FILES) arch/m68k/console/console.a
 SUBDIRS := $(SUBDIRS) arch/m68k/console
 endif
 
 ifdef CONFIG_M68040
-ARCHIVES := $(ARCHIVES) arch/m68k/fpsp040/fpsp.o
+CORE_FILES := $(CORE_FILES) arch/m68k/fpsp040/fpsp.o
 SUBDIRS := $(SUBDIRS) arch/m68k/fpsp040
 endif
 
 ifdef CONFIG_M68060
-ARCHIVES := $(ARCHIVES) arch/m68k/ifpsp060/ifpsp.o
+CORE_FILES := $(CORE_FILES) arch/m68k/ifpsp060/ifpsp.o
 SUBDIRS := $(SUBDIRS) arch/m68k/ifpsp060
 endif
 
@@ -92,10 +98,24 @@
 	cp System.map $(INSTALL_PATH)/System.map
 	if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi
 
-bootstrap:
+zImage compressed: vmlinux.gz
+
+vmlinux.gz: vmlinux
+
+ifdef CONFIG_KGDB
+	cp vmlinux vmlinux.tmp
+	$(STRIP) vmlinux.tmp
+	gzip -9c vmlinux.tmp >vmlinux.gz
+	rm vmlinux.tmp
+else
+	gzip -9c vmlinux >vmlinux.gz
+endif
+
+bootstrap: dummy
 	@$(MAKEBOOT) bootstrap
 
 archclean:
+	rm -f vmlinux.gz
 	@$(MAKEBOOT) clean
 
 archdep:
diff -u --recursive --new-file v2.1.35/linux/arch/m68k/amiga/Makefile linux/arch/m68k/amiga/Makefile
--- v2.1.35/linux/arch/m68k/amiga/Makefile	Fri Jan  3 01:33:25 1997
+++ linux/arch/m68k/amiga/Makefile	Thu Apr 17 13:20:40 1997
@@ -16,4 +16,8 @@
 O_OBJS := $(O_OBJS) cyberfb.o
 endif
 
+ifdef CONFIG_FB_RETINAZ3
+O_OBJS := $(O_OBJS) retz3fb.o
+endif
+
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.1.35/linux/arch/m68k/amiga/amifb.c linux/arch/m68k/amiga/amifb.c
--- v2.1.35/linux/arch/m68k/amiga/amifb.c	Fri Dec 20 01:19:57 1996
+++ linux/arch/m68k/amiga/amifb.c	Thu Apr 17 13:20:41 1997
@@ -1242,6 +1242,7 @@
 static int amifbcon_switch(int con);
 static int amifbcon_updatevar(int con);
 static void amifbcon_blank(int blank);
+static int amifbcon_setcmap(struct fb_cmap *cmap, int con);
 
 	/*
 	 * Internal routines
@@ -1315,7 +1316,15 @@
 extern struct fb_info *Cyber_fb_init(long *mem_start);
 
 static int amifb_Cyber = 0;
-#endif /* CONFIG_FB_CYBER */
+#endif
+
+#ifdef CONFIG_FB_RETINAZ3			/* RetinaZ3 */
+extern int retz3_probe(void);
+extern void retz3_video_setup(char *options, int *ints);
+extern struct fb_info *retz3_fb_init(long *mem_start);
+
+static int amifb_retz3 = 0;
+#endif
 
 #ifdef CONFIG_GSP_RESOLVER			/* DMI Resolver */
 extern int resolver_probe(void);
@@ -1323,7 +1332,7 @@
 extern struct fb_info *resolver_fb_init(long *mem_start);
 
 static int amifb_resolver = 0;
-#endif /* CONFIG_GSP_RESOLVER */
+#endif
 
 static struct fb_ops amiga_fb_ops = {
 	amiga_fb_get_fix, amiga_fb_get_var, amiga_fb_set_var, amiga_fb_get_cmap,
@@ -1347,7 +1356,15 @@
 			Cyber_video_setup(options, ints);
 			return;
 		}
-#endif /* CONFIG_FB_CYBER */
+#endif
+#ifdef CONFIG_FB_RETINAZ3
+	if (options && *options)
+		if (!strncmp(options, "retz3", 5) && retz3_probe()) {
+			amifb_retz3 = 1;
+			retz3_video_setup(options, ints);
+			return;
+		}
+#endif
 #ifdef CONFIG_GSP_RESOLVER
 	if (options && *options)
 		if (!strncmp(options, "resolver", 5) && resolver_probe()) {
@@ -1797,7 +1814,14 @@
 #ifdef CONFIG_FB_CYBER
 	if (amifb_Cyber)
 		return Cyber_fb_init(mem_start);
-#endif /* CONFIG_FB_CYBER */
+#endif
+#ifdef CONFIG_FB_RETINAZ3
+	if (amifb_retz3){
+		custom.dmacon = DMAF_MASTER | DMAF_RASTER | DMAF_COPPER |
+				DMAF_BLITTER | DMAF_SPRITE;
+		return retz3_fb_init(mem_start);
+	}
+#endif
 #ifdef CONFIG_GSP_RESOLVER
 	if (amifb_resolver){
 		custom.dmacon = DMAF_MASTER | DMAF_RASTER | DMAF_COPPER |
@@ -1943,11 +1967,11 @@
 
 	check_default_mode();
 
-	if (request_irq(IRQ3, amifb_interrupt, IRQ_FLG_LOCK,
+	if (request_irq(IRQ_AMIGA_AUTO_3, amifb_interrupt, IRQ_FLG_LOCK,
 	                "fb vertb handler", NULL))
 		panic("Couldn't add vblank interrupt\n");
-	ami_intena_vals[IRQ_IDX(IRQ_AMIGA_VERTB)] = IF_COPER;
-	ami_intena_vals[IRQ_IDX(IRQ_AMIGA_COPPER)] = 0;
+	ami_intena_vals[IRQ_AMIGA_VERTB] = IF_COPER;
+	ami_intena_vals[IRQ_AMIGA_COPPER] = 0;
 	custom.intena = IF_VERTB;
 	custom.intena = IF_SETCLR | IF_COPER;
 
@@ -1957,6 +1981,7 @@
 	fb_info.switch_con = &amifbcon_switch;
 	fb_info.updatevar = &amifbcon_updatevar;
 	fb_info.blank = &amifbcon_blank;
+	fb_info.setcmap = &amifbcon_setcmap;
 
 	amiga_fb_set_var(&amiga_fb_predefined[0], 0);
 
@@ -1995,6 +2020,15 @@
 	do_blank = blank ? blank : -1;
 }
 
+	/*
+	 * Set the colormap
+	 */
+
+static int amifbcon_setcmap(struct fb_cmap *cmap, int con)
+{
+	return(amiga_fb_set_cmap(cmap, 1, con));
+}
+
 /* ---------------------------- Generic routines ---------------------------- */
 
 static struct fb_cmap *get_default_colormap(int bpp)
@@ -2213,10 +2247,11 @@
 {
 	u_short ints = custom.intreqr & custom.intenar;
 	static struct irq_server server = {0, 0};
+	unsigned long flags;
 
 	if (ints & IF_BLIT) {
 		custom.intreq = IF_BLIT;
-		amiga_do_irq(IRQ_IDX(IRQ_AMIGA_BLIT), fp);
+		amiga_do_irq(IRQ_AMIGA_BLIT, fp);
 	}
 
 	if (ints & IF_COPER) {
@@ -2240,8 +2275,11 @@
 				ami_set_sprite();
 		}
 
-		if (get_vbpos() < down2(currentpar.diwstrt_v - 4))
+		save_flags(flags);
+		cli();
+		if (get_vbpos() < down2(currentpar.diwstrt_v - 6))
 			custom.copjmp2 = 0;
+		restore_flags(flags);
 
 		if (do_blank) {
 			ami_do_blank();
@@ -2252,7 +2290,7 @@
 			ami_reinit_copper();
 			do_vmode_full = 0;
 		}
-		amiga_do_irq_list(IRQ_IDX(IRQ_AMIGA_VERTB), fp, &server);
+		amiga_do_irq_list(IRQ_AMIGA_VERTB, fp, &server);
 	}
 
 	if (ints & IF_VERTB) {
diff -u --recursive --new-file v2.1.35/linux/arch/m68k/amiga/amiga_ksyms.c linux/arch/m68k/amiga/amiga_ksyms.c
--- v2.1.35/linux/arch/m68k/amiga/amiga_ksyms.c	Fri Jan  3 01:33:25 1997
+++ linux/arch/m68k/amiga/amiga_ksyms.c	Thu Apr 17 13:20:41 1997
@@ -1,6 +1,7 @@
-#include <linux/types.h>
+#include <linux/config.h>
 #include <linux/module.h>
-#include <asm/zorro.h>
+#include <linux/types.h>
+#include <linux/zorro.h>
 #include <asm/amigahw.h>
 
 extern volatile u_short amiga_audio_min_period;
diff -u --recursive --new-file v2.1.35/linux/arch/m68k/amiga/amiints.c linux/arch/m68k/amiga/amiints.c
--- v2.1.35/linux/arch/m68k/amiga/amiints.c	Fri Dec 20 01:19:57 1996
+++ linux/arch/m68k/amiga/amiints.c	Thu Apr 17 13:20:41 1997
@@ -172,12 +172,16 @@
 		return -ENXIO;
 	}
 
-	if (irq >= IRQ_IDX(IRQ_AMIGA_CIAB))
-		return cia_request_irq(&ciab_base, irq - IRQ_IDX(IRQ_AMIGA_CIAB),
+	if (irq >= IRQ_AMIGA_AUTO)
+		return sys_request_irq(irq - IRQ_AMIGA_AUTO, handler,
+		                       flags, devname, dev_id);
+
+	if (irq >= IRQ_AMIGA_CIAB)
+		return cia_request_irq(&ciab_base, irq - IRQ_AMIGA_CIAB,
 		                       handler, flags, devname, dev_id);
 
-	if (irq >= IRQ_IDX(IRQ_AMIGA_CIAA))
-		return cia_request_irq(&ciaa_base, irq - IRQ_IDX(IRQ_AMIGA_CIAA),
+	if (irq >= IRQ_AMIGA_CIAA)
+		return cia_request_irq(&ciaa_base, irq - IRQ_AMIGA_CIAA,
 		                       handler, flags, devname, dev_id);
 
 	if (ami_servers[irq]) {
@@ -196,7 +200,7 @@
 				       __FUNCTION__, irq, ami_irq_list[irq]->devname);
 				return -EBUSY;
 			}
-			if (flags & IRQ_FLG_REPLACE) {
+			if (!(flags & IRQ_FLG_REPLACE)) {
 				printk("%s: %s can't replace IRQ %d from %s\n",
 				       __FUNCTION__, devname, irq, ami_irq_list[irq]->devname);
 				return -EBUSY;
@@ -209,7 +213,7 @@
 	}
 
 	/* enable the interrupt */
-	if (irq < IRQ_IDX(IRQ_AMIGA_PORTS) && !ami_ablecount[irq])
+	if (irq < IRQ_AMIGA_PORTS && !ami_ablecount[irq])
 		custom.intena = IF_SETCLR | ami_intena_vals[irq];
 
 	return 0;
@@ -222,20 +226,23 @@
 		return;
 	}
 
-	if (irq >= IRQ_IDX(IRQ_AMIGA_CIAB)) {
-		cia_free_irq(&ciab_base, irq - IRQ_IDX(IRQ_AMIGA_CIAB), dev_id);
+	if (irq >= IRQ_AMIGA_AUTO)
+		sys_free_irq(irq - IRQ_AMIGA_AUTO, dev_id);
+
+	if (irq >= IRQ_AMIGA_CIAB) {
+		cia_free_irq(&ciab_base, irq - IRQ_AMIGA_CIAB, dev_id);
 		return;
 	}
 
-	if (irq >= IRQ_IDX(IRQ_AMIGA_CIAA)) {
-		cia_free_irq(&ciaa_base, irq - IRQ_IDX(IRQ_AMIGA_CIAA), dev_id);
+	if (irq >= IRQ_AMIGA_CIAA) {
+		cia_free_irq(&ciaa_base, irq - IRQ_AMIGA_CIAA, dev_id);
 		return;
 	}
 
 	if (ami_servers[irq]) {
 		amiga_delete_irq(&ami_irq_list[irq], dev_id);
 		/* if server list empty, disable the interrupt */
-		if (!ami_irq_list[irq] && irq < IRQ_IDX(IRQ_AMIGA_PORTS))
+		if (!ami_irq_list[irq] && irq < IRQ_AMIGA_PORTS)
 			custom.intena = ami_intena_vals[irq];
 	} else {
 		if (ami_irq_list[irq]->dev_id != dev_id)
@@ -267,15 +274,22 @@
 	if (--ami_ablecount[irq])
 		return;
 
-	if (irq >= IRQ_IDX(IRQ_AMIGA_CIAB)) {
+	/* No action for auto-vector interrupts */
+	if (irq >= IRQ_AMIGA_AUTO){
+		printk("%s: Trying to enable auto-vector IRQ %i\n",
+		       __FUNCTION__, irq - IRQ_AMIGA_AUTO);
+		return;
+	}
+
+	if (irq >= IRQ_AMIGA_CIAB) {
 		cia_able_irq(&ciab_base, CIA_ICR_SETCLR |
-		             (1 << (irq - IRQ_IDX(IRQ_AMIGA_CIAB))));
+		             (1 << (irq - IRQ_AMIGA_CIAB)));
 		return;
 	}
 
-	if (irq >= IRQ_IDX(IRQ_AMIGA_CIAA)) {
+	if (irq >= IRQ_AMIGA_CIAA) {
 		cia_able_irq(&ciaa_base, CIA_ICR_SETCLR |
-		             (1 << (irq - IRQ_IDX(IRQ_AMIGA_CIAA))));
+		             (1 << (irq - IRQ_AMIGA_CIAA)));
 		return;
 	}
 
@@ -293,13 +307,20 @@
 	if (ami_ablecount[irq]++)
 		return;
 
-	if (irq >= IRQ_IDX(IRQ_AMIGA_CIAB)) {
-		cia_able_irq(&ciab_base, 1 << (irq - IRQ_IDX(IRQ_AMIGA_CIAB)));
+	/* No action for auto-vector interrupts */
+	if (irq >= IRQ_AMIGA_AUTO) {
+		printk("%s: Trying to disable auto-vector IRQ %i\n",
+		       __FUNCTION__, irq - IRQ_AMIGA_AUTO);
+		return;
+	}
+
+	if (irq >= IRQ_AMIGA_CIAB) {
+		cia_able_irq(&ciab_base, 1 << (irq - IRQ_AMIGA_CIAB));
 		return;
 	}
 
-	if (irq >= IRQ_IDX(IRQ_AMIGA_CIAA)) {
-		cia_able_irq(&ciaa_base, 1 << (irq - IRQ_IDX(IRQ_AMIGA_CIAA)));
+	if (irq >= IRQ_AMIGA_CIAA) {
+		cia_able_irq(&ciaa_base, 1 << (irq - IRQ_AMIGA_CIAA));
 		return;
 	}
 
@@ -310,13 +331,12 @@
 inline void amiga_do_irq(int irq, struct pt_regs *fp)
 {
 	kstat.interrupts[SYS_IRQS + irq]++;
-	ami_irq_list[irq]->handler(irq | IRQ_MACHSPEC, ami_irq_list[irq]->dev_id, fp);
+	ami_irq_list[irq]->handler(irq, ami_irq_list[irq]->dev_id, fp);
 }
 
 void amiga_do_irq_list(int irq, struct pt_regs *fp, struct irq_server *server)
 {
 	irq_node_t *node, *slow_nodes;
-	int mach_irq = irq | IRQ_MACHSPEC;
 	unsigned short flags;
 
 	kstat.interrupts[SYS_IRQS + irq]++;
@@ -326,7 +346,7 @@
 	for (node = ami_irq_list[irq];
 	     node && (!(node->flags & IRQ_FLG_SLOW));
 	     node = node->next)
-		node->handler(mach_irq, node->dev_id, fp);
+		node->handler(irq, node->dev_id, fp);
 	custom.intreq = ami_intena_vals[irq];
 	if (!node) {
 		server->count--;
@@ -338,7 +358,7 @@
 	slow_nodes = node;
 	for (;;) {
 		for (; node; node = node->next)
-			node->handler(mach_irq, node->dev_id, fp);
+			node->handler(irq, node->dev_id, fp);
 		/* if reentrance occured, serve slow handlers again */
 		custom.intena = ami_intena_vals[irq];
 		if (!server->reentrance) {
@@ -363,19 +383,19 @@
 	/* if serial transmit buffer empty, interrupt */
 	if (ints & IF_TBE) {
 		custom.intreq = IF_TBE;
-		amiga_do_irq(IRQ_IDX(IRQ_AMIGA_TBE), fp);
+		amiga_do_irq(IRQ_AMIGA_TBE, fp);
 	}
 
 	/* if floppy disk transfer complete, interrupt */
 	if (ints & IF_DSKBLK) {
 		custom.intreq = IF_DSKBLK;
-		amiga_do_irq(IRQ_IDX(IRQ_AMIGA_DSKBLK), fp);
+		amiga_do_irq(IRQ_AMIGA_DSKBLK, fp);
 	}
 
 	/* if software interrupt set, interrupt */
 	if (ints & IF_SOFT) {
 		custom.intreq = IF_SOFT;
-		amiga_do_irq(IRQ_IDX(IRQ_AMIGA_SOFT), fp);
+		amiga_do_irq(IRQ_AMIGA_SOFT, fp);
 	}
 }
 
@@ -387,18 +407,18 @@
 	/* if a blitter interrupt */
 	if (ints & IF_BLIT) {
 		custom.intreq = IF_BLIT;
-		amiga_do_irq(IRQ_IDX(IRQ_AMIGA_BLIT), fp);
+		amiga_do_irq(IRQ_AMIGA_BLIT, fp);
 	}
 
 	/* if a copper interrupt */
 	if (ints & IF_COPER) {
 		custom.intreq = IF_COPER;
-		amiga_do_irq(IRQ_IDX(IRQ_AMIGA_COPPER), fp);
+		amiga_do_irq(IRQ_AMIGA_COPPER, fp);
 	}
 
 	/* if a vertical blank interrupt */
 	if (ints & IF_VERTB)
-		amiga_do_irq_list(IRQ_IDX(IRQ_AMIGA_VERTB), fp, &server);
+		amiga_do_irq_list(IRQ_AMIGA_VERTB, fp, &server);
 }
 
 static void ami_int4(int irq, void *dev_id, struct pt_regs *fp)
@@ -408,25 +428,25 @@
 	/* if audio 0 interrupt */
 	if (ints & IF_AUD0) {
 		custom.intreq = IF_AUD0;
-		amiga_do_irq(IRQ_IDX(IRQ_AMIGA_AUD0), fp);
+		amiga_do_irq(IRQ_AMIGA_AUD0, fp);
 	}
 
 	/* if audio 1 interrupt */
 	if (ints & IF_AUD1) {
 		custom.intreq = IF_AUD1;
-		amiga_do_irq(IRQ_IDX(IRQ_AMIGA_AUD1), fp);
+		amiga_do_irq(IRQ_AMIGA_AUD1, fp);
 	}
 
 	/* if audio 2 interrupt */
 	if (ints & IF_AUD2) {
 		custom.intreq = IF_AUD2;
-		amiga_do_irq(IRQ_IDX(IRQ_AMIGA_AUD2), fp);
+		amiga_do_irq(IRQ_AMIGA_AUD2, fp);
 	}
 
 	/* if audio 3 interrupt */
 	if (ints & IF_AUD3) {
 		custom.intreq = IF_AUD3;
-		amiga_do_irq(IRQ_IDX(IRQ_AMIGA_AUD3), fp);
+		amiga_do_irq(IRQ_AMIGA_AUD3, fp);
 	}
 }
 
@@ -437,13 +457,13 @@
 	/* if serial receive buffer full interrupt */
 	if (ints & IF_RBF) {
 		/* acknowledge of IF_RBF must be done by the serial interrupt */
-		amiga_do_irq(IRQ_IDX(IRQ_AMIGA_RBF), fp);
+		amiga_do_irq(IRQ_AMIGA_RBF, fp);
 	}
 
 	/* if a disk sync interrupt */
 	if (ints & IF_DSKSYN) {
 		custom.intreq = IF_DSKSYN;
-		amiga_do_irq(IRQ_IDX(IRQ_AMIGA_DSKSYN), fp);
+		amiga_do_irq(IRQ_AMIGA_DSKSYN, fp);
 	}
 }
 
diff -u --recursive --new-file v2.1.35/linux/arch/m68k/amiga/cia.c linux/arch/m68k/amiga/cia.c
--- v2.1.35/linux/arch/m68k/amiga/cia.c	Fri Nov 22 05:56:33 1996
+++ linux/arch/m68k/amiga/cia.c	Thu Apr 17 13:20:41 1997
@@ -30,13 +30,13 @@
 	irq_handler_t irq_list[CIA_IRQS];
 } ciaa_base = {
 	&ciaa, 0, 0, IF_PORTS,
-	IRQ2, IRQ_AMIGA_CIAA,
-	IRQ_IDX(IRQ_AMIGA_PORTS),
+	IRQ_AMIGA_AUTO_2, IRQ_AMIGA_CIAA,
+	IRQ_AMIGA_PORTS,
 	"CIAA handler", {0, 0}
 }, ciab_base = {
 	&ciab, 0, 0, IF_EXTER,
-	IRQ6, IRQ_AMIGA_CIAB,
-	IRQ_IDX(IRQ_AMIGA_EXTER),
+	IRQ_AMIGA_AUTO_6, IRQ_AMIGA_CIAB,
+	IRQ_AMIGA_EXTER,
 	"CIAB handler", {0, 0}
 };
 
@@ -95,14 +95,14 @@
 
 	if (!(base->irq_list[irq].flags & IRQ_FLG_STD)) {
 		if (base->irq_list[irq].flags & IRQ_FLG_LOCK) {
-			printk("%s: IRQ %ld from %s is not replaceable\n",
-			       __FUNCTION__, IRQ_IDX(base->cia_irq + irq),
+			printk("%s: IRQ %i from %s is not replaceable\n",
+			       __FUNCTION__, base->cia_irq + irq,
 			       base->irq_list[irq].devname);
 			return -EBUSY;
 		}
-		if (flags & IRQ_FLG_REPLACE) {
-			printk("%s: %s can't replace IRQ %ld from %s\n", __FUNCTION__,
-			       devname, IRQ_IDX(base->cia_irq + irq),
+		if (!(flags & IRQ_FLG_REPLACE)) {
+			printk("%s: %s can't replace IRQ %i from %s\n", __FUNCTION__,
+			       devname, base->cia_irq + irq,
 			       base->irq_list[irq].devname);
 			return -EBUSY;
 		}
@@ -122,8 +122,8 @@
 void cia_free_irq(struct ciabase *base, unsigned int irq, void *dev_id)
 {
 	if (base->irq_list[irq].dev_id != dev_id)
-		printk("%s: removing probably wrong IRQ %ld from %s\n",
-		       __FUNCTION__, IRQ_IDX(base->cia_irq + irq),
+		printk("%s: removing probably wrong IRQ %i from %s\n",
+		       __FUNCTION__, base->cia_irq + irq,
 		       base->irq_list[irq].devname);
 
 	base->irq_list[irq].handler = NULL;
@@ -139,7 +139,7 @@
 	unsigned char ints;
 
 	mach_irq = base->cia_irq;
-	irq = SYS_IRQS + IRQ_IDX(mach_irq);
+	irq = SYS_IRQS + mach_irq;
 	ints = cia_set_irq(base, CIA_ICR_ALL);
 	custom.intreq = base->int_mask;
 	for (i = 0; i < CIA_IRQS; i++, irq++, mach_irq++) {
@@ -176,7 +176,7 @@
 {
 	int i, j, len = 0;
 
-	j = IRQ_IDX(base->cia_irq);
+	j = base->cia_irq;
 	for (i = 0; i < CIA_IRQS; i++) {
 		if (!(base->irq_list[i].flags & IRQ_FLG_STD)) {
 			len += sprintf(buf+len, "cia  %2d: %10d ", j + i,
diff -u --recursive --new-file v2.1.35/linux/arch/m68k/amiga/config.c linux/arch/m68k/amiga/config.c
--- v2.1.35/linux/arch/m68k/amiga/config.c	Fri Dec 20 01:19:57 1996
+++ linux/arch/m68k/amiga/config.c	Thu Apr 17 13:20:41 1997
@@ -29,7 +29,7 @@
 #include <asm/amigaints.h>
 #include <asm/irq.h>
 #include <asm/machdep.h>
-#include <asm/zorro.h>
+#include <linux/zorro.h>
 
 u_long amiga_model;
 u_long amiga_eclock;
@@ -56,7 +56,7 @@
 extern void (*amiga_default_handler[]) (int, void *, struct pt_regs *);
 extern int amiga_request_irq (unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
                               unsigned long flags, const char *devname, void *dev_id);
-extern int amiga_free_irq (unsigned int irq, void *dev_id);
+extern void amiga_free_irq (unsigned int irq, void *dev_id);
 extern void amiga_enable_irq (unsigned int);
 extern void amiga_disable_irq (unsigned int);
 static void amiga_get_model(char *model);
@@ -74,15 +74,20 @@
 extern void amiga_floppy_setup(char *, int *);
 #endif
 static void amiga_reset (void);
-static void amiga_waitbut(void);
+static void amiga_wait_key(void);
 extern struct consw fb_con;
 extern struct fb_info *amiga_fb_init(long *);
 extern void zorro_init(void);
-static void ami_savekmsg_init(void);
-static void ami_mem_print(const char *b);
+static void amiga_savekmsg_init(void);
+static void amiga_mem_console_write(const char *b, unsigned int count);
+static void amiga_serial_console_write(const char *s, unsigned int count);
 static void amiga_debug_init(void);
+
 extern void amiga_video_setup(char *, int *);
-extern void amiga_syms_export(void);
+
+static struct console amiga_console_driver = {
+    NULL, NULL, amiga_wait_key
+};
 
 extern void (*kd_mksound)(unsigned int, unsigned int);
 
@@ -151,6 +156,8 @@
 
   memset(&amiga_hw_present, 0, sizeof(amiga_hw_present));
 
+  amiga_debug_init();
+
   printk("Amiga hardware found: ");
   if (amiga_model >= AMI_500 && amiga_model <= AMI_DRACO)
     printk("[%s] ", amiga_models[amiga_model-AMI_500]);
@@ -304,8 +311,8 @@
   mach_default_handler = &amiga_default_handler;
   mach_request_irq     = amiga_request_irq;
   mach_free_irq        = amiga_free_irq;
-  mach_enable_irq      = amiga_enable_irq;
-  mach_disable_irq     = amiga_disable_irq;
+  enable_irq           = amiga_enable_irq;
+  disable_irq          = amiga_disable_irq;
   mach_get_model       = amiga_get_model;
   mach_get_hardware_list = amiga_get_hardware_list;
   mach_get_irq_list    = amiga_get_irq_list;
@@ -329,18 +336,14 @@
 
   mach_hwclk           = amiga_hwclk;
   mach_set_clock_mmss  = amiga_set_clock_mmss;
-  mach_mksound         = amiga_mksound;
 #ifdef CONFIG_BLK_DEV_FD
   mach_floppy_init     = amiga_floppy_init;
   mach_floppy_setup    = amiga_floppy_setup;
 #endif
   mach_reset           = amiga_reset;
-  waitbut              = amiga_waitbut;
   conswitchp           = &fb_con;
   mach_fb_init         = amiga_fb_init;
-  mach_debug_init      = amiga_debug_init;
   mach_video_setup     = amiga_video_setup;
-  mach_syms_export     = amiga_syms_export;
   kd_mksound           = amiga_mksound;
 
   /* Fill in the clock values (based on the 700 kHz E-Clock) */
@@ -355,10 +358,6 @@
   /* initialize chipram allocator */
   amiga_chip_init ();
 
-  /* initialize only once here, not every time the debug level is raised */
-  if (!strcmp( m68k_debug_device, "mem" ))
-    ami_savekmsg_init();
-
   /*
    * if it is an A3000, set the magic bit that forces
    * a hard rekick
@@ -588,7 +587,7 @@
 	return 0;
 }
 
-static void amiga_waitbut (void)
+static void amiga_wait_key (void)
 {
     int i;
 
@@ -614,33 +613,6 @@
     }
 }
 
-void ami_serial_print (const char *str)
-{
-    while (*str) {
-        if (*str == '\n') {
-            custom.serdat = (unsigned char)'\r' | 0x100;
-            while (!(custom.serdatr & 0x2000))
-                ;
-        }
-        custom.serdat = (unsigned char)*str++ | 0x100;
-        while (!(custom.serdatr & 0x2000))
-            ;
-    }
-}
-
-static void amiga_debug_init (void)
-{
-    extern void (*debug_print_proc)(const char *);
-
-    if (!strcmp( m68k_debug_device, "ser" )) {
-        /* no initialization required (?) */
-        debug_print_proc = ami_serial_print;
-    } else if (!strcmp( m68k_debug_device, "mem" )) {
-        /* already initialized by config_amiga() (needed only once) */
-        debug_print_proc = ami_mem_print;
-    }
-}
-
 void dbprintf(const char *fmt , ...)
 {
 	static char buf[1024];
@@ -672,8 +644,10 @@
       ("movel    %0,%/d0\n\t"
        "andl     #0xff000000,%/d0\n\t"
        "orw      #0xe020,%/d0\n\t"   /* map 16 MB, enable, cacheable */
-       ".long    0x4e7b0004\n\t"   /* movec d0,itt0 */
-       ".long    0x4e7b0006\n\t"   /* movec d0,dtt0 */
+       ".chip    68040\n\t"
+       "movec    %%d0,%%itt0\n\t"
+       "movec    %%d0,%%dtt0\n\t"
+       ".chip    68k\n\t"
        "jmp      %0@\n\t"
        : /* no outputs */
        : "a" (jmp_addr040));
@@ -692,7 +666,9 @@
   /* disable translation on '040 now */
   __asm__ __volatile__    
     ("moveq #0,%/d0\n\t"
-     ".long 0x4e7b0003\n\t"         /* movec d0,tc; disable MMU */
+     ".chip 68040\n\t"
+     "movec %%d0,%%tc\n\t"	/* disable MMU */
+     ".chip 68k\n\t"
      : /* no outputs */
      : /* no inputs */
      : "d0");
@@ -718,12 +694,13 @@
 
 }
 
-extern void *amiga_chip_alloc(long size);
 
+    /*
+     *  Debugging
+     */
 
 #define SAVEKMSG_MAXMEM		128*1024
 
-
 #define SAVEKMSG_MAGIC1		0x53415645	/* 'SAVE' */
 #define SAVEKMSG_MAGIC2		0x4B4D5347	/* 'KMSG' */
 
@@ -737,8 +714,15 @@
 
 static struct savekmsg *savekmsg = NULL;
 
+static void amiga_mem_console_write(const char *s, unsigned int count)
+{
+    if (savekmsg->size+count <= SAVEKMSG_MAXMEM-sizeof(struct savekmsg)) {
+        memcpy(savekmsg->data+savekmsg->size, s, count);
+        savekmsg->size += count;
+    }
+}
 
-static void ami_savekmsg_init(void)
+static void amiga_savekmsg_init(void)
 {
     savekmsg = (struct savekmsg *)amiga_chip_alloc(SAVEKMSG_MAXMEM);
     savekmsg->magic1 = SAVEKMSG_MAGIC1;
@@ -747,18 +731,87 @@
     savekmsg->size = 0;
 }
 
+static void amiga_serial_putc(char c)
+{
+    custom.serdat = (unsigned char)c | 0x100;
+    while (!(custom.serdatr & 0x2000))
+	;
+}
+
+static void amiga_serial_console_write(const char *s, unsigned int count)
+{
+    while (count--) {
+	if (*s == '\n')
+	    amiga_serial_putc('\r');
+	amiga_serial_putc(*s++);
+    }
+}
+
+#ifdef CONFIG_SERIAL_CONSOLE
+void amiga_serial_puts(const char *s)
+{
+    amiga_serial_console_write(s, strlen(s));
+}
 
-static void ami_mem_print(const char *b)
+void amiga_serial_gets(char *s, int len)
 {
-    int len;
+    int ch, cnt = 0;
 
-    for (len = 0; b[len]; len++);
-    if (savekmsg->size+len <= SAVEKMSG_MAXMEM) {
-        memcpy(savekmsg->data+savekmsg->size, b, len);
-        savekmsg->size += len;
+    while (1) {
+	while (!(custom.intreqr & IF_RBF))
+	    barrier();
+	ch = custom.serdatr & 0xff;
+	/* clear the interrupt, so that another character can be read */
+	custom.intreq = IF_RBF;
+
+	/* Check for backspace. */
+	if (ch == 8 || ch == 127) {
+	    if (cnt == 0) {
+		amiga_serial_putc('\007');
+		continue;
+	    }
+	    cnt--;
+	    amiga_serial_puts("\010 \010");
+	    continue;
+	}
+
+	/* Check for enter. */
+	if (ch == 10 || ch == 13)
+	    break;
+
+	/* See if line is too long. */
+	if (cnt >= len + 1) {
+	    amiga_serial_putc(7);
+	    cnt--;
+	    continue;
+	}
+
+	/* Store and echo character. */
+	s[cnt++] = ch;
+	amiga_serial_putc(ch);
+    }
+    /* Print enter. */
+    amiga_serial_puts("\r\n");
+    s[cnt] = 0;
+}
+#endif
+
+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);
 }
 
+
+    /*
+     *  Amiga specific parts of /proc
+     */
 
 static void amiga_get_model(char *model)
 {
diff -u --recursive --new-file v2.1.35/linux/arch/m68k/amiga/cyberfb.c linux/arch/m68k/amiga/cyberfb.c
--- v2.1.35/linux/arch/m68k/amiga/cyberfb.c	Fri Dec 20 01:19:57 1996
+++ linux/arch/m68k/amiga/cyberfb.c	Thu Apr 17 13:20:41 1997
@@ -32,7 +32,7 @@
 #include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/irq.h>
-#include <asm/zorro.h>
+#include <linux/zorro.h>
 #include <asm/pgtable.h>
 #include <linux/fb.h>
 #include "s3blit.h"
@@ -235,6 +235,7 @@
 static int Cyberfb_switch(int con);
 static int Cyberfb_updatevar(int con);
 static void Cyberfb_blank(int blank);
+static int Cyberfb_setcmap(struct fb_cmap *cmap, int con);
 
 
    /*
@@ -1179,6 +1180,7 @@
    fb_info.switch_con = &Cyberfb_switch;
    fb_info.updatevar = &Cyberfb_updatevar;
    fb_info.blank = &Cyberfb_blank;
+   fb_info.setcmap = &Cyberfb_setcmap;
 
    do_fb_set_var(&Cyber_fb_predefined[0], 1);
    Cyber_fb_get_var(&disp[0].var, -1);
@@ -1222,6 +1224,16 @@
 static void Cyberfb_blank(int blank)
 {
    fbhw->blank(blank);
+}
+
+
+   /*
+    *    Set the colormap
+    */
+
+static int Cyberfb_setcmap(struct fb_cmap *cmap, int con)
+{
+   return(Cyber_fb_set_cmap(cmap, 1, con));
 }
 
 
diff -u --recursive --new-file v2.1.35/linux/arch/m68k/amiga/retz3fb.c linux/arch/m68k/amiga/retz3fb.c
--- v2.1.35/linux/arch/m68k/amiga/retz3fb.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/m68k/amiga/retz3fb.c	Tue Apr 22 22:45:15 1997
@@ -0,0 +1,3504 @@
+/*
+ * Linux/arch/m68k/amiga/retz3fb.c -- Low level implementation of the
+ *                                    RetinaZ3 frame buffer device
+ *
+ *    Copyright (C) 1997 Jes Sorensen
+ *
+ * This file is based on the CyberVision64 frame buffer device and
+ * the generic Cirrus Logic driver.
+ *
+ * cyberfb.c: Copyright (C) 1996 Martin Apel,
+ *                               Geert Uytterhoeven
+ * clgen.c:   Copyright (C) 1996 Frank Neumann
+ *
+ * History:
+ *   - 22 Jan 97: Initial work
+ *   - 14 Feb 97: Screen initialization works somewhat, still only
+ *                8-bit packed pixel is supported.
+ *
+ * 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.
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/malloc.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <linux/zorro.h>
+#include <asm/pgtable.h>
+
+#include "retz3fb.h"
+
+/* #define DEBUG if(1) */
+#define DEBUG if(0)
+
+/*
+ * Reserve space for one pattern line.
+ *
+ * For the time being we only support 4MB boards!
+ */
+
+#define PAT_MEM_SIZE 16*3
+#define PAT_MEM_OFF  (4*1024*1024 - PAT_MEM_SIZE)
+
+#define arraysize(x)    (sizeof(x)/sizeof(*(x)))
+
+struct retz3_fb_par {
+	int xres;
+	int yres;
+	int xres_vir;
+	int yres_vir;
+	int xoffset;
+	int yoffset;
+	int bpp;
+
+	struct fb_bitfield red;
+	struct fb_bitfield green;
+	struct fb_bitfield blue;
+	struct fb_bitfield transp;
+
+	int pixclock;
+	int left_margin;	/* time from sync to picture	*/
+	int right_margin;	/* time from picture to sync	*/
+	int upper_margin;	/* time from sync to picture	*/
+	int lower_margin;
+	int hsync_len;	/* length of horizontal sync	*/
+	int vsync_len;	/* length of vertical sync	*/
+	int vmode;
+};
+
+struct display_data {
+	long h_total;		/* Horizontal Total */
+	long h_sstart;		/* Horizontal Sync Start */
+	long h_sstop;		/* Horizontal Sync Stop */
+	long h_bstart;		/* Horizontal Blank Start */
+	long h_bstop;		/* Horizontal Blank Stop */
+	long h_dispend;		/* Horizontal Display End */
+	long v_total;		/* Vertical Total */
+	long v_sstart;		/* Vertical Sync Start */
+	long v_sstop;		/* Vertical Sync Stop */
+	long v_bstart;		/* Vertical Blank Start */
+	long v_bstop;		/* Vertical Blank Stop */
+	long v_dispend;		/* Horizontal Display End */
+};
+
+static struct retz3_fb_par current_par;
+
+static int current_par_valid = 0;
+static int currcon = 0;
+
+static struct display disp[MAX_NR_CONSOLES];
+static struct fb_info fb_info;
+
+static int node;        /* node of the /dev/fb?current file */
+
+
+/*
+ *    Switch for Chipset Independency
+ */
+
+static struct fb_hwswitch {
+
+   /* Initialisation */
+
+   int (*init)(void);
+
+   /* Display Control */
+
+   int (*encode_fix)(struct fb_fix_screeninfo *fix, struct retz3_fb_par *par);
+   int (*decode_var)(struct fb_var_screeninfo *var, struct retz3_fb_par *par);
+   int (*encode_var)(struct fb_var_screeninfo *var, struct retz3_fb_par *par);
+   int (*getcolreg)(unsigned int regno, unsigned int *red, unsigned
+		    int *green, unsigned int *blue, unsigned int *transp);
+   int (*setcolreg)(unsigned int regno, unsigned int red, unsigned int
+		    green, unsigned int blue, unsigned int transp);
+   void (*blank)(int blank);
+} *fbhw;
+
+
+/*
+ *    Frame Buffer Name
+ */
+
+static char retz3_fb_name[16] = "RetinaZ3";
+
+
+static int z3_key = 0;
+static unsigned char retz3_color_table [256][4];
+static unsigned long z3_mem;
+static unsigned long z3_fbmem;
+static unsigned long z3_size;
+static volatile unsigned char *z3_regs;
+
+static long *memstart;
+
+
+/*
+ *    Predefined Video Mode Names
+ */
+
+static char *retz3_fb_modenames[] = {
+
+	/*
+	 *    Autodetect (Default) Video Mode
+	 */
+
+	"default",
+
+	/*
+	 *    Predefined Video Modes
+	 */
+
+	"640x480",		/* RetinaZ3 8 bpp */
+	"800x600",		/* RetinaZ3 8 bpp */
+	"1024x768i",
+	"640x480-16",		/* RetinaZ3 16 bpp */
+	"640x480-24",		/* RetinaZ3 24 bpp */
+	
+	/*
+	 *    Dummy Video Modes
+	 */
+
+	"dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy",
+	"dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy",
+	"dummy", "dummy", "dummy", "dummy", "dummy", "dummy",
+
+	/*
+	 *    User Defined Video Modes
+	 *
+	 *    This doesn't work yet!!
+	 */
+
+	"user0", "user1", "user2", "user3",
+	"user4", "user5", "user6", "user7"
+};
+
+/*
+ * A small info on how to convert XFree86 timing values into fb
+ * timings - by Frank Neumann:
+ *
+An XFree86 mode line consists of the following fields:
+ "800x600"     50      800  856  976 1040    600  637  643  666
+ < name >     DCF       HR  SH1  SH2  HFL     VR  SV1  SV2  VFL
+
+The fields in the fb_var_screeninfo structure are:
+        unsigned long pixclock;         * pixel clock in ps (pico seconds) *
+        unsigned long left_margin;      * time from sync to picture    *
+        unsigned long right_margin;     * time from picture to sync    *
+        unsigned long upper_margin;     * time from sync to picture    *
+        unsigned long lower_margin;
+        unsigned long hsync_len;        * length of horizontal sync    *
+        unsigned long vsync_len;        * length of vertical sync      *
+
+1) Pixelclock:
+   xfree: in MHz
+   fb: In Picoseconds (ps)
+
+   pixclock = 1000000 / DCF
+
+2) horizontal timings:
+   left_margin = HFL - SH2
+   right_margin = SH1 - HR
+   hsync_len = SH2 - SH1
+
+3) vertical timings:
+   upper_margin = VFL - SV2
+   lower_margin = SV1 - VR
+   vsync_len = SV2 - SV1
+
+Good examples for VESA timings can be found in the XFree86 source tree,
+under "programs/Xserver/hw/xfree86/doc/modeDB.txt".
+*/
+
+/*
+ *    Predefined Video Mode Definitions
+ */
+
+static struct fb_var_screeninfo retz3_fb_predefined[] = {
+
+   /*
+    *    Autodetect (Default) Video Mode
+    */
+
+   { 0, },
+
+   /*
+    *    Predefined Video Modes
+    */
+
+   /*
+    * NB: it is very important to adjust the pixel-clock to the color-depth.
+    */
+
+   {
+	   640, 480, 640, 480, 0, 0, 8, 0,
+	   {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+	   0, 0, -1, -1, FB_ACCEL_RETINAZ3, 38461, 28, 32, 12, 10, 96, 2,
+	   FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+   },
+   /*
+    ModeLine "800x600" 36 800 824 896 1024 600 601 603 625
+             < name > DCF HR  SH1 SH2  HFL VR  SV1 SV2 VFL
+    */
+   {
+	   /* 800 x 600, 8 bpp */
+	   800, 600, 800, 600, 0, 0, 8, 0,
+	   {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+	   0, 0, -1, -1, FB_ACCEL_RETINAZ3, 27778, 64, 24, 22, 1, 120, 2,
+	   FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+   },
+   /*
+    ModeLine "1024x768i" 45 1024 1064 1224 1264 768 777 785 817 interlace
+              < name >   DCF HR  SH1  SH2  HFL  VR  SV1 SV2 VFL
+    */
+   {
+	   /* 1024 x 768, 8 bpp, interlaced */
+	   1024, 768, 1024, 768, 0, 0, 8, 0,
+	   {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+	   0, 0, -1, -1, FB_ACCEL_RETINAZ3, 22222, 40, 40, 32, 9, 160, 8,
+	   FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_INTERLACED
+   },
+   {
+	   640, 480, 640, 480, 0, 0, 16, 0,
+	   {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
+	   0, 0, -1, -1, FB_ACCEL_RETINAZ3, 38461/2, 28, 32, 12, 10, 96, 2,
+	   FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+   },
+   {
+	   640, 480, 640, 480, 0, 0, 24, 0,
+	   {8, 8, 8}, {8, 8, 8}, {8, 8, 8}, {0, 0, 0}, 
+	   0, 0, -1, -1, FB_ACCEL_RETINAZ3, 38461/3, 28, 32, 12, 10, 96, 2,
+	   FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+   },
+
+   /*
+    *    Dummy Video Modes
+    */
+
+   { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, },
+   { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, },
+   { 0, }, { 0, },
+
+   /*
+    *    User Defined Video Modes
+    */
+
+   { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }
+};
+
+
+#define NUM_TOTAL_MODES    arraysize(retz3_fb_predefined)
+#define NUM_PREDEF_MODES   (5)
+
+
+static int z3fb_inverse = 0;
+static int z3fb_mode = 0;
+
+
+/*
+ *    Interface used by the world
+ */
+
+int retz3_probe(void);
+void retz3_video_setup(char *options, int *ints);
+
+static int retz3_fb_get_fix(struct fb_fix_screeninfo *fix, int con);
+static int retz3_fb_get_var(struct fb_var_screeninfo *var, int con);
+static int retz3_fb_set_var(struct fb_var_screeninfo *var, int con);
+static int retz3_fb_get_cmap(struct fb_cmap *cmap, int kspc, int con);
+static int retz3_fb_set_cmap(struct fb_cmap *cmap, int kspc, int con);
+static int retz3_fb_pan_display(struct fb_var_screeninfo *var, int con);
+static int retz3_fb_ioctl(struct inode *inode, struct file *file,
+			  unsigned int cmd, unsigned long arg, int con);
+
+
+/*
+ *    Interface to the low level console driver
+ */
+
+struct fb_info *retz3_fb_init(long *mem_start); /* Through amiga_fb_init() */
+static int z3fb_switch(int con);
+static int z3fb_updatevar(int con);
+static void z3fb_blank(int blank);
+static int z3fb_setcmap(struct fb_cmap *cmap, int con);
+
+
+/*
+ *    Accelerated Functions used by the low level console driver
+ */
+
+void retz3_bitblt(struct fb_var_screeninfo *scr,
+		  unsigned short curx, unsigned short cury, unsigned
+		  short destx, unsigned short desty, unsigned short
+		  width, unsigned short height, unsigned short cmd,
+		  unsigned short mask);
+void retz3_fill(unsigned short x, unsigned short y, unsigned short
+		width, unsigned short height, unsigned short mode,
+		unsigned short color);
+
+/*
+ *   Hardware Specific Routines
+ */
+
+static int retz3_init(void);
+static int retz3_encode_fix(struct fb_fix_screeninfo *fix,
+                          struct retz3_fb_par *par);
+static int retz3_decode_var(struct fb_var_screeninfo *var,
+                          struct retz3_fb_par *par);
+static int retz3_encode_var(struct fb_var_screeninfo *var,
+                          struct retz3_fb_par *par);
+static int retz3_getcolreg(unsigned int regno, unsigned int *red,
+			   unsigned int *green, unsigned int *blue,
+			   unsigned int *transp);
+static int retz3_setcolreg(unsigned int regno, unsigned int red,
+			   unsigned int green, unsigned int blue,
+			   unsigned int transp);
+static void retz3_blank(int blank);
+
+
+/*
+ *    Internal routines
+ */
+
+static void retz3_fb_get_par(struct retz3_fb_par *par);
+static void retz3_fb_set_par(struct retz3_fb_par *par);
+static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive);
+static struct fb_cmap *get_default_colormap(int bpp);
+static int do_fb_get_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var,
+                          int kspc);
+static int do_fb_set_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var,
+                          int kspc);
+static void do_install_cmap(int con);
+static void memcpy_fs(int fsfromto, void *to, void *from, int len);
+static void copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto);
+static int alloc_cmap(struct fb_cmap *cmap, int len, int transp);
+static void retz3_fb_set_disp(int con);
+static int get_video_mode(const char *name);
+
+
+/* -------------------- Hardware specific routines -------------------------- */
+
+static unsigned short find_fq(unsigned int freq)
+{
+	unsigned long f;
+	long tmp;
+	long prev = 0x7fffffff;
+	long n2, n1 = 3;
+	unsigned long m;
+	unsigned short res = 0;
+
+	if (freq <= 31250000)
+		n2 = 3;
+	else if (freq <= 62500000)
+		n2 = 2;
+	else if (freq <= 125000000)
+		n2 = 1;
+	else if (freq <= 250000000)
+		n2 = 0;
+	else
+		return(0);
+
+
+	do {
+		f = freq >> (10 - n2);
+
+		m = (f * n1) / (14318180/1024);
+
+		if (m > 129)
+			break;
+
+		tmp =  (((m * 14318180) >> n2) / n1) - freq;
+		if (tmp < 0)
+			tmp = -tmp;
+
+		if (tmp < prev) {
+			prev = tmp;
+			res = (((n2 << 5) | (n1-2)) << 8) | (m-2);
+		}
+
+	} while ( (++n1) <= 21);
+
+	return res;
+}
+
+
+static int retz3_set_video(struct fb_var_screeninfo *var,
+			   struct retz3_fb_par *par)
+{
+	float freq_f;
+	long freq;
+
+	int xres, hfront, hsync, hback;
+	int yres, vfront, vsync, vback;
+	unsigned char tmp;
+	unsigned short best_freq;
+	struct display_data data;
+
+	short clocksel = 0; /* Apparantly this is always zero */
+
+	int bpp = var->bits_per_pixel;
+
+	/*
+	 * XXX
+	 */
+	if (bpp == 24)
+		return 0;
+
+	if ((bpp != 8) && (bpp != 16) && (bpp != 24))
+		return -EFAULT;
+
+	par->xoffset = 0;
+	par->yoffset = 0;
+
+	xres   = var->xres * bpp / 4;
+	hfront = var->right_margin * bpp / 4;
+	hsync  = var->hsync_len * bpp / 4;
+	hback  = var->left_margin * bpp / 4;
+
+	if (var->vmode & FB_VMODE_DOUBLE)
+	{
+		yres = var->yres * 2;
+		vfront = var->lower_margin * 2;
+		vsync  = var->vsync_len * 2;
+		vback  = var->upper_margin * 2;
+	}
+	else if (var->vmode & FB_VMODE_INTERLACED)
+	{
+		yres   = (var->yres + 1) / 2;
+		vfront = (var->lower_margin + 1) / 2;
+		vsync  = (var->vsync_len + 1) / 2;
+		vback  = (var->upper_margin + 1) / 2;
+	}
+	else
+	{
+		yres   = var->yres; /* -1 ? */
+		vfront = var->lower_margin;
+		vsync  = var->vsync_len;
+		vback  = var->upper_margin;
+	}
+
+	data.h_total	= (hback / 8) + (xres / 8) 
+			+ (hfront / 8) + (hsync / 8) - 1 /* + 1 */;
+	data.h_dispend	= ((xres + bpp - 1)/ 8) - 1;
+	data.h_bstart	= xres / 8 /* + 1 */;
+
+	data.h_bstop	= data.h_total+1 + 2 + 1;
+	data.h_sstart	= (xres / 8) + (hfront / 8) + 1;
+	data.h_sstop	= (xres / 8) + (hfront / 8) + (hsync / 8) + 1;
+
+	data.v_total	= yres + vfront + vsync + vback - 1;
+
+	data.v_dispend	= yres - 1;
+	data.v_bstart	= yres;
+
+	data.v_bstop	= data.v_total;
+	data.v_sstart	= yres + vfront - 1 - 2;
+	data.v_sstop	= yres + vfront + vsync - 1;
+
+#if 0 /* testing */
+
+	printk("HBS: %i\n", data.h_bstart);
+	printk("HSS: %i\n", data.h_sstart);
+	printk("HSE: %i\n", data.h_sstop);
+	printk("HBE: %i\n", data.h_bstop);
+	printk("HT: %i\n", data.h_total);
+
+	printk("hsync: %i\n", hsync);
+	printk("hfront: %i\n", hfront);
+	printk("hback: %i\n", hback);
+
+	printk("VBS: %i\n", data.v_bstart);
+	printk("VSS: %i\n", data.v_sstart);
+	printk("VSE: %i\n", data.v_sstop);
+	printk("VBE: %i\n", data.v_bstop);
+	printk("VT: %i\n", data.v_total);
+
+	printk("vsync: %i\n", vsync);
+	printk("vfront: %i\n", vfront);
+	printk("vback: %i\n", vback);
+#endif
+
+	if (data.v_total >= 1024)
+		printk("MAYDAY: v_total >= 1024; bailing out!\n");
+
+	reg_w(GREG_MISC_OUTPUT_W, 0xe3 | ((clocksel & 3) * 0x04));
+	reg_w(GREG_FEATURE_CONTROL_W, 0x00);
+
+	seq_w(SEQ_RESET, 0x00);
+	seq_w(SEQ_RESET, 0x03);	/* reset sequencer logic */
+
+	/*
+	 * CLOCKING_MODE bits:
+	 * 2: This one is only set for certain text-modes, wonder if
+	 *    it may be for EGA-lines? (it was referred to as CLKDIV2)
+	 * (The CL drivers sets it to 0x21 with the comment:
+	 *  FullBandwidth (video off) and 8/9 dot clock)
+	 */
+	seq_w(SEQ_CLOCKING_MODE, 0x01 | 0x00 /* 0x08 */);
+
+	seq_w(SEQ_MAP_MASK, 0x0f);        /* enable writing to plane 0-3 */
+	seq_w(SEQ_CHAR_MAP_SELECT, 0x00); /* doesn't matter in gfx-mode */
+	seq_w(SEQ_MEMORY_MODE, 0x06); /* CL driver says 0x0e for 256 col mode*/
+	seq_w(SEQ_RESET, 0x01);
+	seq_w(SEQ_RESET, 0x03);
+
+	seq_w(SEQ_EXTENDED_ENABLE, 0x05);
+
+	seq_w(SEQ_CURSOR_CONTROL, 0x00);	/* disable cursor */
+	seq_w(SEQ_PRIM_HOST_OFF_HI, 0x00);
+	seq_w(SEQ_PRIM_HOST_OFF_HI, 0x00);
+	seq_w(SEQ_LINEAR_0, 0x4a);
+	seq_w(SEQ_LINEAR_1, 0x00);
+
+	seq_w(SEQ_SEC_HOST_OFF_HI, 0x00);
+	seq_w(SEQ_SEC_HOST_OFF_LO, 0x00);
+	seq_w(SEQ_EXTENDED_MEM_ENA, 0x3 | 0x4 | 0x10 | 0x40);
+
+	/*
+	 * The lower 4 bits (0-3) are used to set the font-width for
+	 * text-mode - DON'T try to set this for gfx-mode.
+	 */
+	seq_w(SEQ_EXT_CLOCK_MODE, 0x10);
+	seq_w(SEQ_EXT_VIDEO_ADDR, 0x03);
+
+	/*
+	 * Extended Pixel Control:
+	 * bit 0:   text-mode=0, gfx-mode=1 (Graphics Byte ?)
+	 * bit 1: (Packed/Nibble Pixel Format ?)
+	 * bit 4-5: depth, 0=1-8bpp, 1=9-16bpp, 2=17-24bpp
+	 */
+	seq_w(SEQ_EXT_PIXEL_CNTL, 0x01 | (((bpp / 8) - 1) << 4));
+
+	seq_w(SEQ_BUS_WIDTH_FEEDB, 0x04);
+	seq_w(SEQ_COLOR_EXP_WFG, 0x01);
+	seq_w(SEQ_COLOR_EXP_WBG, 0x00);
+	seq_w(SEQ_EXT_RW_CONTROL, 0x00);
+	seq_w(SEQ_MISC_FEATURE_SEL, (0x51 | (clocksel & 8)));
+	seq_w(SEQ_COLOR_KEY_CNTL, 0x40);
+	seq_w(SEQ_COLOR_KEY_MATCH0, 0x00);
+	seq_w(SEQ_COLOR_KEY_MATCH1, 0x00);
+	seq_w(SEQ_COLOR_KEY_MATCH2, 0x00);
+	seq_w(SEQ_CRC_CONTROL, 0x00);
+	seq_w(SEQ_PERF_SELECT, 0x10);
+	seq_w(SEQ_ACM_APERTURE_1, 0x00);
+	seq_w(SEQ_ACM_APERTURE_2, 0x30);
+	seq_w(SEQ_ACM_APERTURE_3, 0x00);
+	seq_w(SEQ_MEMORY_MAP_CNTL, 0x03);
+
+
+	/* unlock register CRT0..CRT7 */
+	crt_w(CRT_END_VER_RETR, (data.v_sstop & 0x0f) | 0x20);
+
+	/* Zuerst zu schreibende Werte nur per printk ausgeben */
+	DEBUG printk("CRT_HOR_TOTAL: %ld\n", data.h_total);
+	crt_w(CRT_HOR_TOTAL, data.h_total & 0xff);
+
+	DEBUG printk("CRT_HOR_DISP_ENA_END: %ld\n", data.h_dispend);
+	crt_w(CRT_HOR_DISP_ENA_END, (data.h_dispend) & 0xff);
+
+	DEBUG printk("CRT_START_HOR_BLANK: %ld\n", data.h_bstart);
+	crt_w(CRT_START_HOR_BLANK, data.h_bstart & 0xff);
+
+	DEBUG printk("CRT_END_HOR_BLANK: 128+%ld\n", data.h_bstop % 32);
+	crt_w(CRT_END_HOR_BLANK,  0x80 | (data.h_bstop & 0x1f));
+
+	DEBUG printk("CRT_START_HOR_RETR: %ld\n", data.h_sstart);
+	crt_w(CRT_START_HOR_RETR, data.h_sstart & 0xff);
+
+	tmp = (data.h_sstop & 0x1f);
+	if (data.h_bstop & 0x20)
+		tmp |= 0x80;
+	DEBUG printk("CRT_END_HOR_RETR: %d\n", tmp);
+	crt_w(CRT_END_HOR_RETR, tmp);
+
+	DEBUG printk("CRT_VER_TOTAL: %ld\n", data.v_total & 0xff);
+	crt_w(CRT_VER_TOTAL, (data.v_total & 0xff));
+
+	tmp = 0x10;  /* LineCompare bit #9 */
+	if (data.v_total & 256)
+		tmp |= 0x01;
+	if (data.v_dispend & 256)
+		tmp |= 0x02;
+	if (data.v_sstart & 256)
+		tmp |= 0x04;
+	if (data.v_bstart & 256)
+		tmp |= 0x08;
+	if (data.v_total & 512)
+		tmp |= 0x20;
+	if (data.v_dispend & 512)
+		tmp |= 0x40;
+	if (data.v_sstart & 512)
+		tmp |= 0x80;
+	DEBUG printk("CRT_OVERFLOW: %d\n", tmp);
+	crt_w(CRT_OVERFLOW, tmp);
+
+	crt_w(CRT_PRESET_ROW_SCAN, 0x00); /* not CL !!! */
+
+	tmp = 0x40; /* LineCompare bit #8 */
+	if (data.v_bstart & 512)
+		tmp |= 0x20;
+	if (var->vmode & FB_VMODE_DOUBLE)
+		tmp |= 0x80;
+ 	DEBUG printk("CRT_MAX_SCAN_LINE: %d\n", tmp);
+	crt_w(CRT_MAX_SCAN_LINE, tmp);
+
+	crt_w(CRT_CURSOR_START, 0x00);
+	crt_w(CRT_CURSOR_END, 8 & 0x1f); /* font height */
+
+	crt_w(CRT_START_ADDR_HIGH, 0x00);
+	crt_w(CRT_START_ADDR_LOW, 0x00);
+
+	crt_w(CRT_CURSOR_LOC_HIGH, 0x00);
+	crt_w(CRT_CURSOR_LOC_LOW, 0x00);
+
+ 	DEBUG printk("CRT_START_VER_RETR: %ld\n", data.v_sstart & 0xff);
+	crt_w(CRT_START_VER_RETR, (data.v_sstart & 0xff));
+
+#if 1
+	/* 5 refresh cycles per scanline */
+	DEBUG printk("CRT_END_VER_RETR: 64+32+%ld\n", data.v_sstop % 16);
+	crt_w(CRT_END_VER_RETR, ((data.v_sstop & 0x0f) | 0x40 | 0x20));
+#else
+	DEBUG printk("CRT_END_VER_RETR: 128+32+%ld\n", data.v_sstop % 16);
+	crt_w(CRT_END_VER_RETR, ((data.v_sstop & 0x0f) | 128 | 32));
+#endif
+	DEBUG printk("CRT_VER_DISP_ENA_END: %ld\n", data.v_dispend & 0xff);
+	crt_w(CRT_VER_DISP_ENA_END, (data.v_dispend & 0xff));
+
+	DEBUG printk("CRT_START_VER_BLANK: %ld\n", data.v_bstart & 0xff);
+	crt_w(CRT_START_VER_BLANK, (data.v_bstart & 0xff));
+
+	DEBUG printk("CRT_END_VER_BLANK: %ld\n", data.v_bstop & 0xff);
+	crt_w(CRT_END_VER_BLANK, (data.v_bstop & 0xff));
+
+	DEBUG printk("CRT_MODE_CONTROL: 0xe3\n");
+	crt_w(CRT_MODE_CONTROL, 0xe3);
+
+	DEBUG printk("CRT_LINE_COMPARE: 0xff\n");
+	crt_w(CRT_LINE_COMPARE, 0xff);
+
+	tmp = (var->xres_virtual / 8) * (bpp / 8);
+	crt_w(CRT_OFFSET, tmp);
+
+	crt_w(CRT_UNDERLINE_LOC, 0x07); /* probably font-height - 1 */
+
+	tmp = 0x20;			/* Enable extended end bits */
+	if (data.h_total & 0x100)
+		tmp |= 0x01;
+	if ((data.h_dispend) & 0x100)
+		tmp |= 0x02;
+	if (data.h_bstart & 0x100)
+		tmp |= 0x04;
+	if (data.h_sstart & 0x100)
+		tmp |= 0x08;
+	if (var->vmode & FB_VMODE_INTERLACED)
+		tmp |= 0x10;
+ 	DEBUG printk("CRT_EXT_HOR_TIMING1: %d\n", tmp);
+	crt_w(CRT_EXT_HOR_TIMING1, tmp);
+
+	tmp = 0x00;
+	if (((var->xres_virtual / 8) * (bpp / 8)) & 0x100)
+		tmp |= 0x10;
+	crt_w(CRT_EXT_START_ADDR, tmp);
+
+	tmp = 0x00;
+	if (data.h_total & 0x200)
+		tmp |= 0x01;
+	if ((data.h_dispend) & 0x200)
+		tmp |= 0x02;
+	if (data.h_bstart & 0x200)
+		tmp |= 0x04;
+	if (data.h_sstart & 0x200)
+		tmp |= 0x08;
+	tmp |= ((data.h_bstop & 0xc0) >> 2);
+	tmp |= ((data.h_sstop & 0x60) << 1);
+	crt_w(CRT_EXT_HOR_TIMING2, tmp);
+ 	DEBUG printk("CRT_EXT_HOR_TIMING2: %d\n", tmp);
+
+	tmp = 0x10;			/* Line compare bit 10 */
+	if (data.v_total & 0x400)
+		tmp |= 0x01;
+	if ((data.v_dispend) & 0x400)
+		tmp |= 0x02;
+	if (data.v_bstart & 0x400)
+		tmp |= 0x04;
+	if (data.v_sstart & 0x400)
+		tmp |= 0x08;
+	tmp |= ((data.v_bstop & 0x300) >> 3);
+	if (data.v_sstop & 0x10)
+		tmp |= 0x80;
+	crt_w(CRT_EXT_VER_TIMING, tmp);
+ 	DEBUG printk("CRT_EXT_VER_TIMING: %d\n", tmp);
+
+	crt_w(CRT_MONITOR_POWER, 0x00);
+
+	/*
+	 * Convert from ps to Hz.
+	 */
+	freq_f = (1.0/(float)var->pixclock) * 1000000000;
+	freq = ((long)freq_f) * 1000;
+
+	best_freq = find_fq(freq);
+	pll_w(0x02, best_freq);
+	best_freq = find_fq(61000000);
+	pll_w(0x0a, best_freq);
+	pll_w(0x0e, 0x22);
+
+	gfx_w(GFX_SET_RESET, 0x00);
+	gfx_w(GFX_ENABLE_SET_RESET, 0x00);
+	gfx_w(GFX_COLOR_COMPARE, 0x00);
+	gfx_w(GFX_DATA_ROTATE, 0x00);
+	gfx_w(GFX_READ_MAP_SELECT, 0x00);
+	gfx_w(GFX_GRAPHICS_MODE, 0x00);
+	gfx_w(GFX_MISC, 0x05);
+	gfx_w(GFX_COLOR_XCARE, 0x0f);
+	gfx_w(GFX_BITMASK, 0xff);
+
+	reg_r(ACT_ADDRESS_RESET);
+	attr_w(ACT_PALETTE0 , 0x00);
+	attr_w(ACT_PALETTE1 , 0x01);
+	attr_w(ACT_PALETTE2 , 0x02);
+	attr_w(ACT_PALETTE3 , 0x03);
+	attr_w(ACT_PALETTE4 , 0x04);
+	attr_w(ACT_PALETTE5 , 0x05);
+	attr_w(ACT_PALETTE6 , 0x06);
+	attr_w(ACT_PALETTE7 , 0x07);
+	attr_w(ACT_PALETTE8 , 0x08);
+	attr_w(ACT_PALETTE9 , 0x09);
+	attr_w(ACT_PALETTE10, 0x0a);
+	attr_w(ACT_PALETTE11, 0x0b);
+	attr_w(ACT_PALETTE12, 0x0c);
+	attr_w(ACT_PALETTE13, 0x0d);
+	attr_w(ACT_PALETTE14, 0x0e);
+	attr_w(ACT_PALETTE15, 0x0f);
+	reg_r(ACT_ADDRESS_RESET);
+
+	attr_w(ACT_ATTR_MODE_CNTL, 0x09); /* 0x01 for CL */
+
+	attr_w(ACT_OVERSCAN_COLOR, 0x00);
+	attr_w(ACT_COLOR_PLANE_ENA, 0x0f);
+	attr_w(ACT_HOR_PEL_PANNING, 0x00);
+	attr_w(ACT_COLOR_SELECT, 0x00);
+
+	reg_r(ACT_ADDRESS_RESET);
+	reg_w(ACT_DATA, 0x20);
+
+	reg_w(VDAC_MASK, 0xff);
+
+	/*
+	 * Extended palette adressing ???
+	 */
+	switch (bpp){
+	case 8:
+		reg_w(0x83c6, 0x00); 
+		break;
+	case 16:
+		reg_w(0x83c6, 0x60);
+		break;
+	case 24:
+		reg_w(0x83c6, 0xe0);
+		break;
+	default:
+		printk("Illegal color-depth: %i\n", bpp);
+	}
+
+	reg_w(VDAC_ADDRESS, 0x00);
+
+	seq_w(SEQ_MAP_MASK, 0x0f );  
+
+	return 0;
+}
+
+/*
+ *    Initialization
+ *
+ *    Set the default video mode for this chipset. If a video mode was
+ *    specified on the command line, it will override the default mode.
+ */
+
+static int retz3_init(void)
+{
+	int i;
+#if 0
+	volatile unsigned long *CursorBase;
+#endif
+	unsigned long board_addr, board_size;
+	struct ConfigDev *cd;
+
+	cd = zorro_get_board (z3_key);
+	zorro_config_board (z3_key, 0);
+	board_addr = (unsigned long)cd->cd_BoardAddr;
+	board_size = (unsigned long)cd->cd_BoardSize;
+
+	for (i = 0; i < 256; i++){
+		for (i = 0; i < 256; i++){
+			retz3_color_table [i][0] = i;
+			retz3_color_table [i][1] = i;
+			retz3_color_table [i][2] = i;
+			retz3_color_table [i][3] = 0;
+		}
+	}
+
+	*memstart = (*memstart + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
+
+	z3_mem = kernel_map (board_addr, board_size,
+			     KERNELMAP_NOCACHE_SER, memstart);
+
+	z3_regs = (char*) z3_mem;
+	z3_fbmem = z3_mem + VIDEO_MEM_OFFSET;
+
+	/* Get memory size - for now we asume its a 4MB board */
+
+	z3_size = 0x00400000; /* 4 MB */
+
+	memset ((char*)z3_fbmem, 0, z3_size);
+
+	/* Disable hardware cursor */
+
+	seq_w(SEQ_CURSOR_Y_INDEX, 0x00);
+
+
+#if 0
+	/* Initialize hardware cursor */
+	CursorBase = (unsigned long *)((char *)(z3_mem) + z3_size - 0x400);
+	for (i=0; i < 8; i++){
+		*(CursorBase  +(i*4)) = 0xffffff00;
+		*(CursorBase+1+(i*4)) = 0xffff0000;
+		*(CursorBase+2+(i*4)) = 0xffff0000;
+		*(CursorBase+3+(i*4)) = 0xffff0000;
+	}
+	for (i=8; i < 64; i++){
+		*(CursorBase  +(i*4)) = 0xffff0000;
+		*(CursorBase+1+(i*4)) = 0xffff0000;
+		*(CursorBase+2+(i*4)) = 0xffff0000;
+		*(CursorBase+3+(i*4)) = 0xffff0000;
+	}
+#endif
+
+	retz3_setcolreg (255, 56, 100, 160, 0);
+	retz3_setcolreg (254, 0, 0, 0, 0);
+
+	return 0;
+}
+
+
+/*
+ *    This function should fill in the `fix' structure based on the
+ *    values in the `par' structure.
+ */
+
+static int retz3_encode_fix(struct fb_fix_screeninfo *fix,
+                          struct retz3_fb_par *par)
+{
+	int i;
+
+	strcpy(fix->id, retz3_fb_name);
+	fix->smem_start = z3_fbmem;
+	fix->smem_len = z3_size;
+
+	fix->type = FB_TYPE_PACKED_PIXELS;
+	fix->type_aux = 0;
+	if (par->bpp == 8)
+		fix->visual = FB_VISUAL_PSEUDOCOLOR;
+	else
+		fix->visual = FB_VISUAL_DIRECTCOLOR;
+
+	fix->xpanstep = 0;
+	fix->ypanstep = 0;
+	fix->ywrapstep = 0;
+	fix->line_length = 0;
+
+	for (i = 0; i < arraysize(fix->reserved); i++)
+		fix->reserved[i] = 0;
+
+	return 0;
+}
+
+
+/*
+ *    Get the video params out of `var'. If a value doesn't fit, round
+ *    it up, if it's too big, return -EINVAL.
+ */
+
+static int retz3_decode_var(struct fb_var_screeninfo *var,
+			    struct retz3_fb_par *par)
+{
+	par->xres = var->xres;
+	par->yres = var->yres;
+	par->xres_vir = var->xres_virtual;
+	par->yres_vir = var->yres_virtual;
+	par->bpp = var->bits_per_pixel;
+	par->pixclock = var->pixclock;
+	par->vmode = var->vmode;
+
+	par->red = var->red;
+	par->green = var->green;
+	par->blue = var->blue;
+	par->transp = var->transp;
+
+	par->left_margin = var->left_margin;
+	par->right_margin = var->right_margin;
+	par->upper_margin = var->upper_margin;
+	par->lower_margin = var->lower_margin;
+	par->hsync_len = var->hsync_len;
+	par->vsync_len = var->vsync_len;
+
+	return 0;
+}
+
+
+/*
+ *    Fill the `var' structure based on the values in `par' and maybe
+ *    other values read out of the hardware.
+ */
+
+static int retz3_encode_var(struct fb_var_screeninfo *var,
+			    struct retz3_fb_par *par)
+{
+	int i;
+
+	var->xres = par->xres;
+	var->yres = par->yres;
+	var->xres_virtual = par->xres_vir;
+	var->yres_virtual = par->yres_vir;
+	var->xoffset = 0;
+	var->yoffset = 0;
+
+	var->bits_per_pixel = par->bpp;
+	var->grayscale = 0;
+
+	var->red = par->red;
+	var->green = par->green;
+	var->blue = par->blue;
+	var->transp = par->transp;
+
+	var->nonstd = 0;
+	var->activate = 0;
+
+	var->height = -1;
+	var->width = -1;
+
+	var->accel = FB_ACCEL_RETINAZ3;
+
+	var->pixclock = par->pixclock;
+
+	var->sync = 0;				/* ??? */
+	var->left_margin = par->left_margin;
+	var->right_margin = par->right_margin;
+	var->upper_margin = par->upper_margin;
+	var->lower_margin = par->lower_margin;
+	var->hsync_len = par->hsync_len;
+	var->vsync_len = par->vsync_len;
+
+	for (i = 0; i < arraysize(var->reserved); i++)
+		var->reserved[i] = 0;
+
+	var->vmode = par->vmode;
+	return 0;
+}
+
+
+/*
+ *    Set a single color register. The values supplied are already
+ *    rounded down to the hardware's capabilities (according to the
+ *    entries in the var structure). Return != 0 for invalid regno.
+ */
+
+static int retz3_setcolreg(unsigned int regno, unsigned int red,
+			   unsigned int green, unsigned int blue,
+			   unsigned int transp)
+{
+	/* We'll get to this */
+
+	if (regno > 255)
+		return 1;
+
+	retz3_color_table [regno][0] = red & 0xff;
+	retz3_color_table [regno][1] = green & 0xff;
+	retz3_color_table [regno][2] = blue & 0xff;
+	retz3_color_table [regno][3] = transp;
+
+	reg_w(VDAC_ADDRESS_W, regno);
+	reg_w(VDAC_DATA, (red & 0xff) >> 2);
+	reg_w(VDAC_DATA, (green & 0xff) >> 2);
+	reg_w(VDAC_DATA, (blue & 0xff) >> 2);
+
+	return 0;
+}
+
+
+/*
+ *    Read a single color register and split it into
+ *    colors/transparent. Return != 0 for invalid regno.
+ */
+
+static int retz3_getcolreg(unsigned int regno, unsigned int *red,
+			   unsigned int *green, unsigned int *blue,
+			   unsigned int *transp)
+{
+	if (regno > 255)
+		return 1;
+	*red    = retz3_color_table [regno][0];
+	*green  = retz3_color_table [regno][1];
+	*blue   = retz3_color_table [regno][2];
+	*transp = retz3_color_table [regno][3];
+	return 0;
+}
+
+
+/*
+ *    (Un)Blank the screen
+ */
+
+void retz3_blank(int blank)
+{
+	int i;
+
+	if (blank)
+		for (i = 0; i < 256; i++){
+			reg_w(VDAC_ADDRESS_W, i);
+			reg_w(VDAC_DATA, 0);
+			reg_w(VDAC_DATA, 0);
+			reg_w(VDAC_DATA, 0);
+		}
+	else
+		for (i = 0; i < 256; i++){
+			reg_w(VDAC_ADDRESS_W, i);
+			reg_w(VDAC_DATA, retz3_color_table [i][0] >> 2);
+			reg_w(VDAC_DATA, retz3_color_table [i][1] >> 2);
+			reg_w(VDAC_DATA, retz3_color_table [i][2] >> 2);
+		}
+}
+
+
+void retz3_bitblt (struct fb_var_screeninfo *var,
+		   unsigned short srcx, unsigned short srcy, unsigned
+		   short destx, unsigned short desty, unsigned short
+		   width, unsigned short height, unsigned short cmd,
+		   unsigned short mask)
+{
+
+	volatile unsigned long *acm = (unsigned long *) (z3_mem + ACM_OFFSET);
+	unsigned long *pattern = (unsigned long *)(z3_fbmem + PAT_MEM_OFF);
+
+	unsigned short mod;
+	unsigned long tmp;
+	unsigned long pat, src, dst;
+	unsigned char blt_status;
+
+	int i, xres_virtual = var->xres_virtual;
+	short bpp = (var->bits_per_pixel & 0xff);
+
+	if (bpp < 8)
+		bpp = 8;
+
+	tmp = mask | (mask << 16);
+
+#if 0
+	/*
+	 * Check for blitter finished before we start messing with the
+	 * pattern.
+	 */
+	do{
+		blt_status = *(((volatile unsigned char *)acm) +
+			       (ACM_START_STATUS + 2));
+	}while ((blt_status & 1) == 0);
+#endif
+
+	i = 0;
+	do{
+		*pattern++ = tmp;
+	}while(i++ < bpp/4);
+
+	tmp = cmd << 8;
+	*(acm + ACM_RASTEROP_ROTATION/4) = tmp;
+
+	mod = 0xc0c2;
+
+	pat = 8 * PAT_MEM_OFF;
+	dst = bpp * (destx + desty * xres_virtual);
+
+	/*
+	 * Source is not set for clear.
+	 */
+	if ((cmd != Z3BLTclear) && (cmd != Z3BLTset)) {
+		src = bpp * (srcx + srcy * xres_virtual);
+
+		if (destx > srcx) {
+			mod &= ~0x8000;
+			src += bpp * (width - 1);
+			dst += bpp * (width - 1);
+			pat += bpp * 2;
+		}
+		if (desty > srcy) {
+			mod &= ~0x4000;
+			src += bpp * (height - 1) * xres_virtual;
+			dst += bpp * (height - 1) * xres_virtual;
+			pat += bpp * 4;
+		}
+
+		*(acm + ACM_SOURCE/4) = cpu_to_le32(src);
+	}
+
+	*(acm + ACM_PATTERN/4) = cpu_to_le32(pat);
+
+	*(acm + ACM_DESTINATION/4) = cpu_to_le32(dst);
+
+	tmp = mod << 16;
+	*(acm + ACM_CONTROL/4) = tmp;
+
+	tmp  = width | (height << 16);
+	
+	*(acm + ACM_BITMAP_DIMENSION/4) = cpu_to_le32(tmp);
+
+	*(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x00;
+	*(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x01;
+
+	/*
+	 * No reason to wait for the blitter to finish, it is better
+	 * just to check if it has finished before we use it again.
+	 */
+#if 1
+#if 0
+	while ((*(((volatile unsigned char *)acm) +
+		  (ACM_START_STATUS + 2)) & 1) == 0);
+#else
+	do{
+		blt_status = *(((volatile unsigned char *)acm) +
+			       (ACM_START_STATUS + 2));
+	}
+	while ((blt_status & 1) == 0);
+#endif
+#endif
+}
+
+#if 0
+void retz3_fill (unsigned short x, unsigned short y, unsigned
+		 short width, unsigned short height,
+		 unsigned short mode, unsigned short color)
+{
+
+}
+#endif
+
+
+/**************************************************************
+ * Move cursor to x, y
+ */
+void retz3_MoveCursor (unsigned short x, unsigned short y)
+{
+	/* Guess we gotta deal with the cursor at some point */
+}
+
+
+/* -------------------- Interfaces to hardware functions -------------------- */
+
+
+static struct fb_hwswitch retz3_switch = {
+	retz3_init, retz3_encode_fix, retz3_decode_var, retz3_encode_var,
+	retz3_getcolreg, retz3_setcolreg, retz3_blank
+};
+
+
+/* -------------------- Generic routines ------------------------------------ */
+
+
+/*
+ *    Fill the hardware's `par' structure.
+ */
+
+static void retz3_fb_get_par(struct retz3_fb_par *par)
+{
+	if (current_par_valid)
+		*par = current_par;
+	else
+		fbhw->decode_var(&retz3_fb_predefined[z3fb_mode], par);
+}
+
+
+static void retz3_fb_set_par(struct retz3_fb_par *par)
+{
+	current_par = *par;
+	current_par_valid = 1;
+}
+
+
+static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
+{
+	int err, activate;
+	struct retz3_fb_par par;
+
+	if ((err = fbhw->decode_var(var, &par)))
+		return err;
+	activate = var->activate;
+	if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW && isactive)
+		retz3_fb_set_par(&par);
+	fbhw->encode_var(var, &par);
+	var->activate = activate;
+
+#if 1
+	retz3_set_video(var, &current_par);
+#endif
+	return 0;
+}
+
+
+/*
+ *    Default Colormaps
+ */
+
+static unsigned short red16[] =
+	{ 0x0000, 0x0000, 0x0000, 0x0000, 0xc000, 0xc000, 0xc000, 0xc000,
+	  0x8000, 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff };
+static unsigned short green16[] =
+	{ 0x0000, 0x0000, 0xc000, 0xc000, 0x0000, 0x0000, 0xc000, 0xc000,
+	  0x8000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff };
+static unsigned short blue16[] =
+	{ 0x0000, 0xc000, 0x0000, 0xc000, 0x0000, 0xc000, 0x0000, 0xc000,
+	  0x8000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff };
+
+
+static struct fb_cmap default_16_colors =
+   { 0, 16, red16, green16, blue16, NULL };
+
+
+static struct fb_cmap *get_default_colormap(int bpp)
+{
+	return &default_16_colors;
+}
+
+
+#define CNVT_TOHW(val,width)     ((((val)<<(width))+0x7fff-(val))>>16)
+#define CNVT_FROMHW(val,width)   (((width) ? ((((val)<<16)-(val)) / \
+                                              ((1<<(width))-1)) : 0))
+
+static int do_fb_get_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var,
+                          int kspc)
+{
+	int i, start;
+	unsigned short *red, *green, *blue, *transp;
+	unsigned int hred, hgreen, hblue, htransp;
+
+	red = cmap->red;
+	green = cmap->green;
+	blue = cmap->blue;
+	transp = cmap->transp;
+	start = cmap->start;
+
+	if (start < 0)
+		return -EINVAL;
+	for (i = 0; i < cmap->len; i++) {
+		if (fbhw->getcolreg(start++, &hred, &hgreen, &hblue, &htransp))
+			return 0;
+		hred = CNVT_FROMHW(hred, var->red.length);
+		hgreen = CNVT_FROMHW(hgreen, var->green.length);
+		hblue = CNVT_FROMHW(hblue, var->blue.length);
+		htransp = CNVT_FROMHW(htransp, var->transp.length);
+		if (kspc) {
+			*red = hred;
+			*green = hgreen;
+			*blue = hblue;
+			if (transp)
+				*transp = htransp;
+		} else {
+			put_user(hred, red);
+			put_user(hgreen, green);
+			put_user(hblue, blue);
+			if (transp)
+				put_user(htransp, transp);
+		}
+		red++;
+		green++;
+		blue++;
+		if (transp)
+			transp++;
+	}
+	return 0;
+}
+
+
+static int do_fb_set_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var,
+                          int kspc)
+{
+	int i, start;
+	unsigned short *red, *green, *blue, *transp;
+	unsigned int hred, hgreen, hblue, htransp;
+
+	red = cmap->red;
+	green = cmap->green;
+	blue = cmap->blue;
+	transp = cmap->transp;
+	start = cmap->start;
+
+	if (start < 0)
+		return -EINVAL;
+	for (i = 0; i < cmap->len; i++) {
+		if (kspc) {
+			hred = *red;
+			hgreen = *green;
+			hblue = *blue;
+			htransp = transp ? *transp : 0;
+		} else {
+			get_user(hred, red);
+			get_user(hgreen, green);
+			get_user(hblue, blue);
+			if (transp)
+				get_user(htransp, transp);
+			else
+				htransp = 0;
+		}
+		hred = CNVT_TOHW(hred, var->red.length);
+		hgreen = CNVT_TOHW(hgreen, var->green.length);
+		hblue = CNVT_TOHW(hblue, var->blue.length);
+		htransp = CNVT_TOHW(htransp, var->transp.length);
+		red++;
+		green++;
+		blue++;
+		if (transp)
+			transp++;
+		if (fbhw->setcolreg(start++, hred, hgreen, hblue, htransp))
+			return 0;
+	}
+	return 0;
+}
+
+
+static void do_install_cmap(int con)
+{
+	if (con != currcon)
+		return;
+	if (disp[con].cmap.len)
+		do_fb_set_cmap(&disp[con].cmap, &disp[con].var, 1);
+	else
+		do_fb_set_cmap(get_default_colormap(disp[con].var.bits_per_pixel),
+                                          &disp[con].var, 1);
+}
+
+
+static void memcpy_fs(int fsfromto, void *to, void *from, int len)
+{
+	switch (fsfromto) {
+	case 0:
+		memcpy(to, from, len);
+		return;
+	case 1:
+		copy_from_user(to, from, len);
+		return;
+	case 2:
+		copy_to_user(to, from, len);
+		return;
+	}
+}
+
+
+static void copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto)
+{
+	int size;
+	int tooff = 0, fromoff = 0;
+
+	if (to->start > from->start)
+		fromoff = to->start-from->start;
+	else
+		tooff = from->start-to->start;
+	size = to->len-tooff;
+	if (size > from->len-fromoff)
+		size = from->len-fromoff;
+	if (size < 0)
+		return;
+	size *= sizeof(unsigned short);
+	memcpy_fs(fsfromto, to->red+tooff, from->red+fromoff, size);
+	memcpy_fs(fsfromto, to->green+tooff, from->green+fromoff, size);
+	memcpy_fs(fsfromto, to->blue+tooff, from->blue+fromoff, size);
+	if (from->transp && to->transp)
+		memcpy_fs(fsfromto, to->transp+tooff,
+			  from->transp+fromoff, size);
+}
+
+
+static int alloc_cmap(struct fb_cmap *cmap, int len, int transp)
+{
+	int size = len*sizeof(unsigned short);
+
+	if (cmap->len != len) {
+		if (cmap->red)
+			kfree(cmap->red);
+		if (cmap->green)
+			kfree(cmap->green);
+		if (cmap->blue)
+			kfree(cmap->blue);
+		if (cmap->transp)
+			kfree(cmap->transp);
+		cmap->red = cmap->green = cmap->blue = cmap->transp = NULL;
+		cmap->len = 0;
+		if (!len)
+			return 0;
+		if (!(cmap->red = kmalloc(size, GFP_ATOMIC)))
+			return -1;
+		if (!(cmap->green = kmalloc(size, GFP_ATOMIC)))
+			return -1;
+		if (!(cmap->blue = kmalloc(size, GFP_ATOMIC)))
+			return -1;
+		if (transp) {
+			if (!(cmap->transp = kmalloc(size, GFP_ATOMIC)))
+				return -1;
+		} else
+			cmap->transp = NULL;
+	}
+	cmap->start = 0;
+	cmap->len = len;
+	copy_cmap(get_default_colormap(len), cmap, 0);
+	return 0;
+}
+
+
+/*
+ *    Get the Fixed Part of the Display
+ */
+
+static int retz3_fb_get_fix(struct fb_fix_screeninfo *fix, int con)
+{
+	struct retz3_fb_par par;
+	int error = 0;
+
+	if (con == -1)
+		retz3_fb_get_par(&par);
+	else
+		error = fbhw->decode_var(&disp[con].var, &par);
+	return(error ? error : fbhw->encode_fix(fix, &par));
+}
+
+
+/*
+ *    Get the User Defined Part of the Display
+ */
+
+static int retz3_fb_get_var(struct fb_var_screeninfo *var, int con)
+{
+	struct retz3_fb_par par;
+	int error = 0;
+
+	if (con == -1) {
+		retz3_fb_get_par(&par);
+		error = fbhw->encode_var(var, &par);
+	} else
+		*var = disp[con].var;
+	return error;
+}
+
+
+static void retz3_fb_set_disp(int con)
+{
+	struct fb_fix_screeninfo fix;
+
+	retz3_fb_get_fix(&fix, con);
+	if (con == -1)
+		con = 0;
+	disp[con].screen_base = (unsigned char *)fix.smem_start;
+	disp[con].visual = fix.visual;
+	disp[con].type = fix.type;
+	disp[con].type_aux = fix.type_aux;
+	disp[con].ypanstep = fix.ypanstep;
+	disp[con].ywrapstep = fix.ywrapstep;
+	disp[con].can_soft_blank = 1;
+	disp[con].inverse = z3fb_inverse;
+}
+
+
+/*
+ *    Set the User Defined Part of the Display
+ */
+
+static int retz3_fb_set_var(struct fb_var_screeninfo *var, int con)
+{
+	int err, oldxres, oldyres, oldvxres, oldvyres, oldbpp;
+
+	if ((err = do_fb_set_var(var, con == currcon)))
+		return err;
+	if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
+		oldxres = disp[con].var.xres;
+		oldyres = disp[con].var.yres;
+		oldvxres = disp[con].var.xres_virtual;
+		oldvyres = disp[con].var.yres_virtual;
+		oldbpp = disp[con].var.bits_per_pixel;
+		disp[con].var = *var;
+		if (oldxres != var->xres || oldyres != var->yres ||
+		    oldvxres != var->xres_virtual ||
+		    oldvyres != var->yres_virtual ||
+		    oldbpp != var->bits_per_pixel) {
+			retz3_fb_set_disp(con);
+			(*fb_info.changevar)(con);
+			alloc_cmap(&disp[con].cmap, 0, 0);
+			do_install_cmap(con);
+		}
+	}
+	var->activate = 0;
+	return 0;
+}
+
+
+/*
+ *    Get the Colormap
+ */
+
+static int retz3_fb_get_cmap(struct fb_cmap *cmap, int kspc, int con)
+{
+	if (con == currcon) /* current console? */
+		return(do_fb_get_cmap(cmap, &disp[con].var, kspc));
+	else if (disp[con].cmap.len) /* non default colormap? */
+		copy_cmap(&disp[con].cmap, cmap, kspc ? 0 : 2);
+	else
+		copy_cmap(get_default_colormap(disp[con].var.bits_per_pixel),
+			  cmap, kspc ? 0 : 2);
+	return 0;
+}
+
+
+/*
+ *    Set the Colormap
+ */
+
+static int retz3_fb_set_cmap(struct fb_cmap *cmap, int kspc, int con)
+{
+	int err;
+
+	if (!disp[con].cmap.len) {       /* no colormap allocated? */
+		if ((err = alloc_cmap(&disp[con].cmap,
+				      1<<disp[con].var.bits_per_pixel, 0)))
+			return err;
+	}
+	if (con == currcon)              /* current console? */
+		return(do_fb_set_cmap(cmap, &disp[con].var, kspc));
+	else
+		copy_cmap(cmap, &disp[con].cmap, kspc ? 0 : 1);
+	return 0;
+}
+
+
+/*
+ *    Pan or Wrap the Display
+ *
+ *    This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
+ */
+
+static int retz3_fb_pan_display(struct fb_var_screeninfo *var, int con)
+{
+	return -EINVAL;
+}
+
+
+/*
+ *    RetinaZ3 Frame Buffer Specific ioctls
+ */
+
+static int retz3_fb_ioctl(struct inode *inode, struct file *file,
+                          unsigned int cmd, unsigned long arg, int con)
+{
+	return -EINVAL;
+}
+
+
+static struct fb_ops retz3_fb_ops = {
+   retz3_fb_get_fix, retz3_fb_get_var, retz3_fb_set_var, retz3_fb_get_cmap,
+   retz3_fb_set_cmap, retz3_fb_pan_display, retz3_fb_ioctl
+};
+
+
+int retz3_probe(void)
+{
+	z3_key = zorro_find(MANUF_MACROSYSTEMS2, PROD_RETINA_Z3, 0, 0);
+	return(z3_key);
+}
+
+
+void retz3_video_setup(char *options, int *ints)
+{
+	char *this_opt;
+	int i;
+
+	fb_info.fontname[0] = '\0';
+
+	if (!options || !*options)
+		return;
+
+	for (this_opt = strtok(options, ","); this_opt; 
+	     this_opt = strtok(NULL, ",")){
+		if (!strcmp(this_opt, "inverse")) {
+			z3fb_inverse = 1;
+			for (i = 0; i < 16; i++) {
+				red16[i] = ~red16[i];
+				green16[i] = ~green16[i];
+				blue16[i] = ~blue16[i];
+			}
+		} else if (!strncmp(this_opt, "font:", 5))
+			strcpy(fb_info.fontname, this_opt+5);
+		else
+			z3fb_mode = get_video_mode(this_opt);
+	}
+}
+
+
+/*
+ *    Initialization
+ */
+
+struct fb_info *retz3_fb_init(long *mem_start)
+{
+	int err;
+	struct retz3_fb_par par;
+
+	memstart = mem_start;
+
+	fbhw = &retz3_switch;
+
+	err = register_framebuffer(retz3_fb_name, &node, &retz3_fb_ops,
+				   NUM_TOTAL_MODES, retz3_fb_predefined);
+	if (err < 0)
+		panic("Cannot register frame buffer\n");
+
+	fbhw->init();
+
+	if (z3fb_mode == -1)
+		z3fb_mode = 1;
+
+	fbhw->decode_var(&retz3_fb_predefined[z3fb_mode], &par);
+	fbhw->encode_var(&retz3_fb_predefined[0], &par);
+
+	strcpy(fb_info.modename, retz3_fb_name);
+	fb_info.disp = disp;
+	fb_info.switch_con = &z3fb_switch;
+	fb_info.updatevar = &z3fb_updatevar;
+	fb_info.blank = &z3fb_blank;
+	fb_info.setcmap = &z3fb_setcmap;
+
+	do_fb_set_var(&retz3_fb_predefined[0], 0);
+	retz3_fb_get_var(&disp[0].var, -1);
+	retz3_fb_set_disp(-1);
+	do_install_cmap(0);
+
+	return &fb_info;
+}
+
+
+static int z3fb_switch(int con)
+{
+	/* Do we have to save the colormap? */
+	if (disp[currcon].cmap.len)
+		do_fb_get_cmap(&disp[currcon].cmap, &disp[currcon].var, 1);
+
+	do_fb_set_var(&disp[con].var, 1);
+	currcon = con;
+	/* Install new colormap */
+	do_install_cmap(con);
+	return 0;
+}
+
+
+/*
+ *    Update the `var' structure (called by fbcon.c)
+ *
+ *    This call looks only at yoffset and the FB_VMODE_YWRAP flag in `var'.
+ *    Since it's called by a kernel driver, no range checking is done.
+ */
+
+static int z3fb_updatevar(int con)
+{
+	return 0;
+}
+
+
+/*
+ *    Blank the display.
+ */
+
+static void z3fb_blank(int blank)
+{
+	fbhw->blank(blank);
+}
+
+
+/*
+ *    Set the colormap
+ */
+
+static int z3fb_setcmap(struct fb_cmap *cmap, int con)
+{
+	return(retz3_fb_set_cmap(cmap, 1, con));
+}
+
+
+/*
+ *    Get a Video Mode
+ */
+
+static int get_video_mode(const char *name)
+{
+	int i;
+
+	for (i = 1; i <= NUM_PREDEF_MODES; i++)
+		if (!strcmp(name, retz3_fb_modenames[i])){
+			retz3_fb_predefined[0] = retz3_fb_predefined[i];
+			return i;
+		}
+	return -1;
+}
+/*
+ * Linux/arch/m68k/amiga/retz3fb.c -- Low level implementation of the
+ *                                    RetinaZ3 frame buffer device
+ *
+ *    Copyright (C) 1997 Jes Sorensen
+ *
+ * This file is based on the CyberVision64 frame buffer device and
+ * the generic Cirrus Logic driver.
+ *
+ * cyberfb.c: Copyright (C) 1996 Martin Apel,
+ *                               Geert Uytterhoeven
+ * clgen.c:   Copyright (C) 1996 Frank Neumann
+ *
+ * History:
+ *   - 22 Jan 97: Initial work
+ *   - 14 Feb 97: Screen initialization works somewhat, still only
+ *                8-bit packed pixel is supported.
+ *
+ * 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.
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/malloc.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <linux/zorro.h>
+#include <asm/pgtable.h>
+
+#include "retz3fb.h"
+
+/* #define DEBUG if(1) */
+#define DEBUG if(0)
+
+/*
+ * Reserve space for one pattern line.
+ *
+ * For the time being we only support 4MB boards!
+ */
+
+#define PAT_MEM_SIZE 16*3
+#define PAT_MEM_OFF  (4*1024*1024 - PAT_MEM_SIZE)
+
+#define arraysize(x)    (sizeof(x)/sizeof(*(x)))
+
+struct retz3_fb_par {
+	int xres;
+	int yres;
+	int xres_vir;
+	int yres_vir;
+	int xoffset;
+	int yoffset;
+	int bpp;
+
+	struct fb_bitfield red;
+	struct fb_bitfield green;
+	struct fb_bitfield blue;
+	struct fb_bitfield transp;
+
+	int pixclock;
+	int left_margin;	/* time from sync to picture	*/
+	int right_margin;	/* time from picture to sync	*/
+	int upper_margin;	/* time from sync to picture	*/
+	int lower_margin;
+	int hsync_len;	/* length of horizontal sync	*/
+	int vsync_len;	/* length of vertical sync	*/
+	int vmode;
+};
+
+struct display_data {
+	long h_total;		/* Horizontal Total */
+	long h_sstart;		/* Horizontal Sync Start */
+	long h_sstop;		/* Horizontal Sync Stop */
+	long h_bstart;		/* Horizontal Blank Start */
+	long h_bstop;		/* Horizontal Blank Stop */
+	long h_dispend;		/* Horizontal Display End */
+	long v_total;		/* Vertical Total */
+	long v_sstart;		/* Vertical Sync Start */
+	long v_sstop;		/* Vertical Sync Stop */
+	long v_bstart;		/* Vertical Blank Start */
+	long v_bstop;		/* Vertical Blank Stop */
+	long v_dispend;		/* Horizontal Display End */
+};
+
+static struct retz3_fb_par current_par;
+
+static int current_par_valid = 0;
+static int currcon = 0;
+
+static struct display disp[MAX_NR_CONSOLES];
+static struct fb_info fb_info;
+
+static int node;        /* node of the /dev/fb?current file */
+
+
+/*
+ *    Switch for Chipset Independency
+ */
+
+static struct fb_hwswitch {
+
+   /* Initialisation */
+
+   int (*init)(void);
+
+   /* Display Control */
+
+   int (*encode_fix)(struct fb_fix_screeninfo *fix, struct retz3_fb_par *par);
+   int (*decode_var)(struct fb_var_screeninfo *var, struct retz3_fb_par *par);
+   int (*encode_var)(struct fb_var_screeninfo *var, struct retz3_fb_par *par);
+   int (*getcolreg)(unsigned int regno, unsigned int *red, unsigned
+		    int *green, unsigned int *blue, unsigned int *transp);
+   int (*setcolreg)(unsigned int regno, unsigned int red, unsigned int
+		    green, unsigned int blue, unsigned int transp);
+   void (*blank)(int blank);
+} *fbhw;
+
+
+/*
+ *    Frame Buffer Name
+ */
+
+static char retz3_fb_name[16] = "RetinaZ3";
+
+
+static int z3_key = 0;
+static unsigned char retz3_color_table [256][4];
+static unsigned long z3_mem;
+static unsigned long z3_fbmem;
+static unsigned long z3_size;
+static volatile unsigned char *z3_regs;
+
+static long *memstart;
+
+
+/*
+ *    Predefined Video Mode Names
+ */
+
+static char *retz3_fb_modenames[] = {
+
+	/*
+	 *    Autodetect (Default) Video Mode
+	 */
+
+	"default",
+
+	/*
+	 *    Predefined Video Modes
+	 */
+
+	"640x480",		/* RetinaZ3 8 bpp */
+	"800x600",		/* RetinaZ3 8 bpp */
+	"1024x768i",
+	"640x480-16",		/* RetinaZ3 16 bpp */
+	"640x480-24",		/* RetinaZ3 24 bpp */
+	
+	/*
+	 *    Dummy Video Modes
+	 */
+
+	"dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy",
+	"dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy",
+	"dummy", "dummy", "dummy", "dummy", "dummy", "dummy",
+
+	/*
+	 *    User Defined Video Modes
+	 *
+	 *    This doesn't work yet!!
+	 */
+
+	"user0", "user1", "user2", "user3",
+	"user4", "user5", "user6", "user7"
+};
+
+/*
+ * A small info on how to convert XFree86 timing values into fb
+ * timings - by Frank Neumann:
+ *
+An XFree86 mode line consists of the following fields:
+ "800x600"     50      800  856  976 1040    600  637  643  666
+ < name >     DCF       HR  SH1  SH2  HFL     VR  SV1  SV2  VFL
+
+The fields in the fb_var_screeninfo structure are:
+        unsigned long pixclock;         * pixel clock in ps (pico seconds) *
+        unsigned long left_margin;      * time from sync to picture    *
+        unsigned long right_margin;     * time from picture to sync    *
+        unsigned long upper_margin;     * time from sync to picture    *
+        unsigned long lower_margin;
+        unsigned long hsync_len;        * length of horizontal sync    *
+        unsigned long vsync_len;        * length of vertical sync      *
+
+1) Pixelclock:
+   xfree: in MHz
+   fb: In Picoseconds (ps)
+
+   pixclock = 1000000 / DCF
+
+2) horizontal timings:
+   left_margin = HFL - SH2
+   right_margin = SH1 - HR
+   hsync_len = SH2 - SH1
+
+3) vertical timings:
+   upper_margin = VFL - SV2
+   lower_margin = SV1 - VR
+   vsync_len = SV2 - SV1
+
+Good examples for VESA timings can be found in the XFree86 source tree,
+under "programs/Xserver/hw/xfree86/doc/modeDB.txt".
+*/
+
+/*
+ *    Predefined Video Mode Definitions
+ */
+
+static struct fb_var_screeninfo retz3_fb_predefined[] = {
+
+   /*
+    *    Autodetect (Default) Video Mode
+    */
+
+   { 0, },
+
+   /*
+    *    Predefined Video Modes
+    */
+
+   /*
+    * NB: it is very important to adjust the pixel-clock to the color-depth.
+    */
+
+   {
+	   640, 480, 640, 480, 0, 0, 8, 0,
+	   {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+	   0, 0, -1, -1, FB_ACCEL_RETINAZ3, 38461, 28, 32, 12, 10, 96, 2,
+	   FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+   },
+   /*
+    ModeLine "800x600" 36 800 824 896 1024 600 601 603 625
+             < name > DCF HR  SH1 SH2  HFL VR  SV1 SV2 VFL
+    */
+   {
+	   /* 800 x 600, 8 bpp */
+	   800, 600, 800, 600, 0, 0, 8, 0,
+	   {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+	   0, 0, -1, -1, FB_ACCEL_RETINAZ3, 27778, 64, 24, 22, 1, 120, 2,
+	   FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+   },
+   /*
+    ModeLine "1024x768i" 45 1024 1064 1224 1264 768 777 785 817 interlace
+              < name >   DCF HR  SH1  SH2  HFL  VR  SV1 SV2 VFL
+    */
+   {
+	   /* 1024 x 768, 8 bpp, interlaced */
+	   1024, 768, 1024, 768, 0, 0, 8, 0,
+	   {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+	   0, 0, -1, -1, FB_ACCEL_RETINAZ3, 22222, 40, 40, 32, 9, 160, 8,
+	   FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_INTERLACED
+   },
+   {
+	   640, 480, 640, 480, 0, 0, 16, 0,
+	   {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
+	   0, 0, -1, -1, FB_ACCEL_RETINAZ3, 38461/2, 28, 32, 12, 10, 96, 2,
+	   FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+   },
+   {
+	   640, 480, 640, 480, 0, 0, 24, 0,
+	   {8, 8, 8}, {8, 8, 8}, {8, 8, 8}, {0, 0, 0}, 
+	   0, 0, -1, -1, FB_ACCEL_RETINAZ3, 38461/3, 28, 32, 12, 10, 96, 2,
+	   FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+   },
+
+   /*
+    *    Dummy Video Modes
+    */
+
+   { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, },
+   { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, },
+   { 0, }, { 0, },
+
+   /*
+    *    User Defined Video Modes
+    */
+
+   { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }
+};
+
+
+#define NUM_TOTAL_MODES    arraysize(retz3_fb_predefined)
+#define NUM_PREDEF_MODES   (5)
+
+
+static int z3fb_inverse = 0;
+static int z3fb_mode = 0;
+
+
+/*
+ *    Interface used by the world
+ */
+
+int retz3_probe(void);
+void retz3_video_setup(char *options, int *ints);
+
+static int retz3_fb_get_fix(struct fb_fix_screeninfo *fix, int con);
+static int retz3_fb_get_var(struct fb_var_screeninfo *var, int con);
+static int retz3_fb_set_var(struct fb_var_screeninfo *var, int con);
+static int retz3_fb_get_cmap(struct fb_cmap *cmap, int kspc, int con);
+static int retz3_fb_set_cmap(struct fb_cmap *cmap, int kspc, int con);
+static int retz3_fb_pan_display(struct fb_var_screeninfo *var, int con);
+static int retz3_fb_ioctl(struct inode *inode, struct file *file,
+			  unsigned int cmd, unsigned long arg, int con);
+
+
+/*
+ *    Interface to the low level console driver
+ */
+
+struct fb_info *retz3_fb_init(long *mem_start); /* Through amiga_fb_init() */
+static int z3fb_switch(int con);
+static int z3fb_updatevar(int con);
+static void z3fb_blank(int blank);
+static int z3fb_setcmap(struct fb_cmap *cmap, int con);
+
+
+/*
+ *    Accelerated Functions used by the low level console driver
+ */
+
+void retz3_bitblt(struct fb_var_screeninfo *scr,
+		  unsigned short curx, unsigned short cury, unsigned
+		  short destx, unsigned short desty, unsigned short
+		  width, unsigned short height, unsigned short cmd,
+		  unsigned short mask);
+void retz3_fill(unsigned short x, unsigned short y, unsigned short
+		width, unsigned short height, unsigned short mode,
+		unsigned short color);
+
+/*
+ *   Hardware Specific Routines
+ */
+
+static int retz3_init(void);
+static int retz3_encode_fix(struct fb_fix_screeninfo *fix,
+                          struct retz3_fb_par *par);
+static int retz3_decode_var(struct fb_var_screeninfo *var,
+                          struct retz3_fb_par *par);
+static int retz3_encode_var(struct fb_var_screeninfo *var,
+                          struct retz3_fb_par *par);
+static int retz3_getcolreg(unsigned int regno, unsigned int *red,
+			   unsigned int *green, unsigned int *blue,
+			   unsigned int *transp);
+static int retz3_setcolreg(unsigned int regno, unsigned int red,
+			   unsigned int green, unsigned int blue,
+			   unsigned int transp);
+static void retz3_blank(int blank);
+
+
+/*
+ *    Internal routines
+ */
+
+static void retz3_fb_get_par(struct retz3_fb_par *par);
+static void retz3_fb_set_par(struct retz3_fb_par *par);
+static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive);
+static struct fb_cmap *get_default_colormap(int bpp);
+static int do_fb_get_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var,
+                          int kspc);
+static int do_fb_set_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var,
+                          int kspc);
+static void do_install_cmap(int con);
+static void memcpy_fs(int fsfromto, void *to, void *from, int len);
+static void copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto);
+static int alloc_cmap(struct fb_cmap *cmap, int len, int transp);
+static void retz3_fb_set_disp(int con);
+static int get_video_mode(const char *name);
+
+
+/* -------------------- Hardware specific routines -------------------------- */
+
+static unsigned short find_fq(unsigned int freq)
+{
+	unsigned long f;
+	long tmp;
+	long prev = 0x7fffffff;
+	long n2, n1 = 3;
+	unsigned long m;
+	unsigned short res = 0;
+
+	if (freq <= 31250000)
+		n2 = 3;
+	else if (freq <= 62500000)
+		n2 = 2;
+	else if (freq <= 125000000)
+		n2 = 1;
+	else if (freq <= 250000000)
+		n2 = 0;
+	else
+		return(0);
+
+
+	do {
+		f = freq >> (10 - n2);
+
+		m = (f * n1) / (14318180/1024);
+
+		if (m > 129)
+			break;
+
+		tmp =  (((m * 14318180) >> n2) / n1) - freq;
+		if (tmp < 0)
+			tmp = -tmp;
+
+		if (tmp < prev) {
+			prev = tmp;
+			res = (((n2 << 5) | (n1-2)) << 8) | (m-2);
+		}
+
+	} while ( (++n1) <= 21);
+
+	return res;
+}
+
+
+static int retz3_set_video(struct fb_var_screeninfo *var,
+			   struct retz3_fb_par *par)
+{
+	float freq_f;
+	long freq;
+
+	int xres, hfront, hsync, hback;
+	int yres, vfront, vsync, vback;
+	unsigned char tmp;
+	unsigned short best_freq;
+	struct display_data data;
+
+	short clocksel = 0; /* Apparantly this is always zero */
+
+	int bpp = var->bits_per_pixel;
+
+	/*
+	 * XXX
+	 */
+	if (bpp == 24)
+		return 0;
+
+	if ((bpp != 8) && (bpp != 16) && (bpp != 24))
+		return -EFAULT;
+
+	par->xoffset = 0;
+	par->yoffset = 0;
+
+	xres   = var->xres * bpp / 4;
+	hfront = var->right_margin * bpp / 4;
+	hsync  = var->hsync_len * bpp / 4;
+	hback  = var->left_margin * bpp / 4;
+
+	if (var->vmode & FB_VMODE_DOUBLE)
+	{
+		yres = var->yres * 2;
+		vfront = var->lower_margin * 2;
+		vsync  = var->vsync_len * 2;
+		vback  = var->upper_margin * 2;
+	}
+	else if (var->vmode & FB_VMODE_INTERLACED)
+	{
+		yres   = (var->yres + 1) / 2;
+		vfront = (var->lower_margin + 1) / 2;
+		vsync  = (var->vsync_len + 1) / 2;
+		vback  = (var->upper_margin + 1) / 2;
+	}
+	else
+	{
+		yres   = var->yres; /* -1 ? */
+		vfront = var->lower_margin;
+		vsync  = var->vsync_len;
+		vback  = var->upper_margin;
+	}
+
+	data.h_total	= (hback / 8) + (xres / 8) 
+			+ (hfront / 8) + (hsync / 8) - 1 /* + 1 */;
+	data.h_dispend	= ((xres + bpp - 1)/ 8) - 1;
+	data.h_bstart	= xres / 8 /* + 1 */;
+
+	data.h_bstop	= data.h_total+1 + 2 + 1;
+	data.h_sstart	= (xres / 8) + (hfront / 8) + 1;
+	data.h_sstop	= (xres / 8) + (hfront / 8) + (hsync / 8) + 1;
+
+	data.v_total	= yres + vfront + vsync + vback - 1;
+
+	data.v_dispend	= yres - 1;
+	data.v_bstart	= yres;
+
+	data.v_bstop	= data.v_total;
+	data.v_sstart	= yres + vfront - 1 - 2;
+	data.v_sstop	= yres + vfront + vsync - 1;
+
+#if 0 /* testing */
+
+	printk("HBS: %i\n", data.h_bstart);
+	printk("HSS: %i\n", data.h_sstart);
+	printk("HSE: %i\n", data.h_sstop);
+	printk("HBE: %i\n", data.h_bstop);
+	printk("HT: %i\n", data.h_total);
+
+	printk("hsync: %i\n", hsync);
+	printk("hfront: %i\n", hfront);
+	printk("hback: %i\n", hback);
+
+	printk("VBS: %i\n", data.v_bstart);
+	printk("VSS: %i\n", data.v_sstart);
+	printk("VSE: %i\n", data.v_sstop);
+	printk("VBE: %i\n", data.v_bstop);
+	printk("VT: %i\n", data.v_total);
+
+	printk("vsync: %i\n", vsync);
+	printk("vfront: %i\n", vfront);
+	printk("vback: %i\n", vback);
+#endif
+
+	if (data.v_total >= 1024)
+		printk("MAYDAY: v_total >= 1024; bailing out!\n");
+
+	reg_w(GREG_MISC_OUTPUT_W, 0xe3 | ((clocksel & 3) * 0x04));
+	reg_w(GREG_FEATURE_CONTROL_W, 0x00);
+
+	seq_w(SEQ_RESET, 0x00);
+	seq_w(SEQ_RESET, 0x03);	/* reset sequencer logic */
+
+	/*
+	 * CLOCKING_MODE bits:
+	 * 2: This one is only set for certain text-modes, wonder if
+	 *    it may be for EGA-lines? (it was referred to as CLKDIV2)
+	 * (The CL drivers sets it to 0x21 with the comment:
+	 *  FullBandwidth (video off) and 8/9 dot clock)
+	 */
+	seq_w(SEQ_CLOCKING_MODE, 0x01 | 0x00 /* 0x08 */);
+
+	seq_w(SEQ_MAP_MASK, 0x0f);        /* enable writing to plane 0-3 */
+	seq_w(SEQ_CHAR_MAP_SELECT, 0x00); /* doesn't matter in gfx-mode */
+	seq_w(SEQ_MEMORY_MODE, 0x06); /* CL driver says 0x0e for 256 col mode*/
+	seq_w(SEQ_RESET, 0x01);
+	seq_w(SEQ_RESET, 0x03);
+
+	seq_w(SEQ_EXTENDED_ENABLE, 0x05);
+
+	seq_w(SEQ_CURSOR_CONTROL, 0x00);	/* disable cursor */
+	seq_w(SEQ_PRIM_HOST_OFF_HI, 0x00);
+	seq_w(SEQ_PRIM_HOST_OFF_HI, 0x00);
+	seq_w(SEQ_LINEAR_0, 0x4a);
+	seq_w(SEQ_LINEAR_1, 0x00);
+
+	seq_w(SEQ_SEC_HOST_OFF_HI, 0x00);
+	seq_w(SEQ_SEC_HOST_OFF_LO, 0x00);
+	seq_w(SEQ_EXTENDED_MEM_ENA, 0x3 | 0x4 | 0x10 | 0x40);
+
+	/*
+	 * The lower 4 bits (0-3) are used to set the font-width for
+	 * text-mode - DON'T try to set this for gfx-mode.
+	 */
+	seq_w(SEQ_EXT_CLOCK_MODE, 0x10);
+	seq_w(SEQ_EXT_VIDEO_ADDR, 0x03);
+
+	/*
+	 * Extended Pixel Control:
+	 * bit 0:   text-mode=0, gfx-mode=1 (Graphics Byte ?)
+	 * bit 1: (Packed/Nibble Pixel Format ?)
+	 * bit 4-5: depth, 0=1-8bpp, 1=9-16bpp, 2=17-24bpp
+	 */
+	seq_w(SEQ_EXT_PIXEL_CNTL, 0x01 | (((bpp / 8) - 1) << 4));
+
+	seq_w(SEQ_BUS_WIDTH_FEEDB, 0x04);
+	seq_w(SEQ_COLOR_EXP_WFG, 0x01);
+	seq_w(SEQ_COLOR_EXP_WBG, 0x00);
+	seq_w(SEQ_EXT_RW_CONTROL, 0x00);
+	seq_w(SEQ_MISC_FEATURE_SEL, (0x51 | (clocksel & 8)));
+	seq_w(SEQ_COLOR_KEY_CNTL, 0x40);
+	seq_w(SEQ_COLOR_KEY_MATCH0, 0x00);
+	seq_w(SEQ_COLOR_KEY_MATCH1, 0x00);
+	seq_w(SEQ_COLOR_KEY_MATCH2, 0x00);
+	seq_w(SEQ_CRC_CONTROL, 0x00);
+	seq_w(SEQ_PERF_SELECT, 0x10);
+	seq_w(SEQ_ACM_APERTURE_1, 0x00);
+	seq_w(SEQ_ACM_APERTURE_2, 0x30);
+	seq_w(SEQ_ACM_APERTURE_3, 0x00);
+	seq_w(SEQ_MEMORY_MAP_CNTL, 0x03);
+
+
+	/* unlock register CRT0..CRT7 */
+	crt_w(CRT_END_VER_RETR, (data.v_sstop & 0x0f) | 0x20);
+
+	/* Zuerst zu schreibende Werte nur per printk ausgeben */
+	DEBUG printk("CRT_HOR_TOTAL: %ld\n", data.h_total);
+	crt_w(CRT_HOR_TOTAL, data.h_total & 0xff);
+
+	DEBUG printk("CRT_HOR_DISP_ENA_END: %ld\n", data.h_dispend);
+	crt_w(CRT_HOR_DISP_ENA_END, (data.h_dispend) & 0xff);
+
+	DEBUG printk("CRT_START_HOR_BLANK: %ld\n", data.h_bstart);
+	crt_w(CRT_START_HOR_BLANK, data.h_bstart & 0xff);
+
+	DEBUG printk("CRT_END_HOR_BLANK: 128+%ld\n", data.h_bstop % 32);
+	crt_w(CRT_END_HOR_BLANK,  0x80 | (data.h_bstop & 0x1f));
+
+	DEBUG printk("CRT_START_HOR_RETR: %ld\n", data.h_sstart);
+	crt_w(CRT_START_HOR_RETR, data.h_sstart & 0xff);
+
+	tmp = (data.h_sstop & 0x1f);
+	if (data.h_bstop & 0x20)
+		tmp |= 0x80;
+	DEBUG printk("CRT_END_HOR_RETR: %d\n", tmp);
+	crt_w(CRT_END_HOR_RETR, tmp);
+
+	DEBUG printk("CRT_VER_TOTAL: %ld\n", data.v_total & 0xff);
+	crt_w(CRT_VER_TOTAL, (data.v_total & 0xff));
+
+	tmp = 0x10;  /* LineCompare bit #9 */
+	if (data.v_total & 256)
+		tmp |= 0x01;
+	if (data.v_dispend & 256)
+		tmp |= 0x02;
+	if (data.v_sstart & 256)
+		tmp |= 0x04;
+	if (data.v_bstart & 256)
+		tmp |= 0x08;
+	if (data.v_total & 512)
+		tmp |= 0x20;
+	if (data.v_dispend & 512)
+		tmp |= 0x40;
+	if (data.v_sstart & 512)
+		tmp |= 0x80;
+	DEBUG printk("CRT_OVERFLOW: %d\n", tmp);
+	crt_w(CRT_OVERFLOW, tmp);
+
+	crt_w(CRT_PRESET_ROW_SCAN, 0x00); /* not CL !!! */
+
+	tmp = 0x40; /* LineCompare bit #8 */
+	if (data.v_bstart & 512)
+		tmp |= 0x20;
+	if (var->vmode & FB_VMODE_DOUBLE)
+		tmp |= 0x80;
+ 	DEBUG printk("CRT_MAX_SCAN_LINE: %d\n", tmp);
+	crt_w(CRT_MAX_SCAN_LINE, tmp);
+
+	crt_w(CRT_CURSOR_START, 0x00);
+	crt_w(CRT_CURSOR_END, 8 & 0x1f); /* font height */
+
+	crt_w(CRT_START_ADDR_HIGH, 0x00);
+	crt_w(CRT_START_ADDR_LOW, 0x00);
+
+	crt_w(CRT_CURSOR_LOC_HIGH, 0x00);
+	crt_w(CRT_CURSOR_LOC_LOW, 0x00);
+
+ 	DEBUG printk("CRT_START_VER_RETR: %ld\n", data.v_sstart & 0xff);
+	crt_w(CRT_START_VER_RETR, (data.v_sstart & 0xff));
+
+#if 1
+	/* 5 refresh cycles per scanline */
+	DEBUG printk("CRT_END_VER_RETR: 64+32+%ld\n", data.v_sstop % 16);
+	crt_w(CRT_END_VER_RETR, ((data.v_sstop & 0x0f) | 0x40 | 0x20));
+#else
+	DEBUG printk("CRT_END_VER_RETR: 128+32+%ld\n", data.v_sstop % 16);
+	crt_w(CRT_END_VER_RETR, ((data.v_sstop & 0x0f) | 128 | 32));
+#endif
+	DEBUG printk("CRT_VER_DISP_ENA_END: %ld\n", data.v_dispend & 0xff);
+	crt_w(CRT_VER_DISP_ENA_END, (data.v_dispend & 0xff));
+
+	DEBUG printk("CRT_START_VER_BLANK: %ld\n", data.v_bstart & 0xff);
+	crt_w(CRT_START_VER_BLANK, (data.v_bstart & 0xff));
+
+	DEBUG printk("CRT_END_VER_BLANK: %ld\n", data.v_bstop & 0xff);
+	crt_w(CRT_END_VER_BLANK, (data.v_bstop & 0xff));
+
+	DEBUG printk("CRT_MODE_CONTROL: 0xe3\n");
+	crt_w(CRT_MODE_CONTROL, 0xe3);
+
+	DEBUG printk("CRT_LINE_COMPARE: 0xff\n");
+	crt_w(CRT_LINE_COMPARE, 0xff);
+
+	tmp = (var->xres_virtual / 8) * (bpp / 8);
+	crt_w(CRT_OFFSET, tmp);
+
+	crt_w(CRT_UNDERLINE_LOC, 0x07); /* probably font-height - 1 */
+
+	tmp = 0x20;			/* Enable extended end bits */
+	if (data.h_total & 0x100)
+		tmp |= 0x01;
+	if ((data.h_dispend) & 0x100)
+		tmp |= 0x02;
+	if (data.h_bstart & 0x100)
+		tmp |= 0x04;
+	if (data.h_sstart & 0x100)
+		tmp |= 0x08;
+	if (var->vmode & FB_VMODE_INTERLACED)
+		tmp |= 0x10;
+ 	DEBUG printk("CRT_EXT_HOR_TIMING1: %d\n", tmp);
+	crt_w(CRT_EXT_HOR_TIMING1, tmp);
+
+	tmp = 0x00;
+	if (((var->xres_virtual / 8) * (bpp / 8)) & 0x100)
+		tmp |= 0x10;
+	crt_w(CRT_EXT_START_ADDR, tmp);
+
+	tmp = 0x00;
+	if (data.h_total & 0x200)
+		tmp |= 0x01;
+	if ((data.h_dispend) & 0x200)
+		tmp |= 0x02;
+	if (data.h_bstart & 0x200)
+		tmp |= 0x04;
+	if (data.h_sstart & 0x200)
+		tmp |= 0x08;
+	tmp |= ((data.h_bstop & 0xc0) >> 2);
+	tmp |= ((data.h_sstop & 0x60) << 1);
+	crt_w(CRT_EXT_HOR_TIMING2, tmp);
+ 	DEBUG printk("CRT_EXT_HOR_TIMING2: %d\n", tmp);
+
+	tmp = 0x10;			/* Line compare bit 10 */
+	if (data.v_total & 0x400)
+		tmp |= 0x01;
+	if ((data.v_dispend) & 0x400)
+		tmp |= 0x02;
+	if (data.v_bstart & 0x400)
+		tmp |= 0x04;
+	if (data.v_sstart & 0x400)
+		tmp |= 0x08;
+	tmp |= ((data.v_bstop & 0x300) >> 3);
+	if (data.v_sstop & 0x10)
+		tmp |= 0x80;
+	crt_w(CRT_EXT_VER_TIMING, tmp);
+ 	DEBUG printk("CRT_EXT_VER_TIMING: %d\n", tmp);
+
+	crt_w(CRT_MONITOR_POWER, 0x00);
+
+	/*
+	 * Convert from ps to Hz.
+	 */
+	freq_f = (1.0/(float)var->pixclock) * 1000000000;
+	freq = ((long)freq_f) * 1000;
+
+	best_freq = find_fq(freq);
+	pll_w(0x02, best_freq);
+	best_freq = find_fq(61000000);
+	pll_w(0x0a, best_freq);
+	pll_w(0x0e, 0x22);
+
+	gfx_w(GFX_SET_RESET, 0x00);
+	gfx_w(GFX_ENABLE_SET_RESET, 0x00);
+	gfx_w(GFX_COLOR_COMPARE, 0x00);
+	gfx_w(GFX_DATA_ROTATE, 0x00);
+	gfx_w(GFX_READ_MAP_SELECT, 0x00);
+	gfx_w(GFX_GRAPHICS_MODE, 0x00);
+	gfx_w(GFX_MISC, 0x05);
+	gfx_w(GFX_COLOR_XCARE, 0x0f);
+	gfx_w(GFX_BITMASK, 0xff);
+
+	reg_r(ACT_ADDRESS_RESET);
+	attr_w(ACT_PALETTE0 , 0x00);
+	attr_w(ACT_PALETTE1 , 0x01);
+	attr_w(ACT_PALETTE2 , 0x02);
+	attr_w(ACT_PALETTE3 , 0x03);
+	attr_w(ACT_PALETTE4 , 0x04);
+	attr_w(ACT_PALETTE5 , 0x05);
+	attr_w(ACT_PALETTE6 , 0x06);
+	attr_w(ACT_PALETTE7 , 0x07);
+	attr_w(ACT_PALETTE8 , 0x08);
+	attr_w(ACT_PALETTE9 , 0x09);
+	attr_w(ACT_PALETTE10, 0x0a);
+	attr_w(ACT_PALETTE11, 0x0b);
+	attr_w(ACT_PALETTE12, 0x0c);
+	attr_w(ACT_PALETTE13, 0x0d);
+	attr_w(ACT_PALETTE14, 0x0e);
+	attr_w(ACT_PALETTE15, 0x0f);
+	reg_r(ACT_ADDRESS_RESET);
+
+	attr_w(ACT_ATTR_MODE_CNTL, 0x09); /* 0x01 for CL */
+
+	attr_w(ACT_OVERSCAN_COLOR, 0x00);
+	attr_w(ACT_COLOR_PLANE_ENA, 0x0f);
+	attr_w(ACT_HOR_PEL_PANNING, 0x00);
+	attr_w(ACT_COLOR_SELECT, 0x00);
+
+	reg_r(ACT_ADDRESS_RESET);
+	reg_w(ACT_DATA, 0x20);
+
+	reg_w(VDAC_MASK, 0xff);
+
+	/*
+	 * Extended palette adressing ???
+	 */
+	switch (bpp){
+	case 8:
+		reg_w(0x83c6, 0x00); 
+		break;
+	case 16:
+		reg_w(0x83c6, 0x60);
+		break;
+	case 24:
+		reg_w(0x83c6, 0xe0);
+		break;
+	default:
+		printk("Illegal color-depth: %i\n", bpp);
+	}
+
+	reg_w(VDAC_ADDRESS, 0x00);
+
+	seq_w(SEQ_MAP_MASK, 0x0f );  
+
+	return 0;
+}
+
+/*
+ *    Initialization
+ *
+ *    Set the default video mode for this chipset. If a video mode was
+ *    specified on the command line, it will override the default mode.
+ */
+
+static int retz3_init(void)
+{
+	int i;
+#if 0
+	volatile unsigned long *CursorBase;
+#endif
+	unsigned long board_addr, board_size;
+	struct ConfigDev *cd;
+
+	cd = zorro_get_board (z3_key);
+	zorro_config_board (z3_key, 0);
+	board_addr = (unsigned long)cd->cd_BoardAddr;
+	board_size = (unsigned long)cd->cd_BoardSize;
+
+	for (i = 0; i < 256; i++){
+		for (i = 0; i < 256; i++){
+			retz3_color_table [i][0] = i;
+			retz3_color_table [i][1] = i;
+			retz3_color_table [i][2] = i;
+			retz3_color_table [i][3] = 0;
+		}
+	}
+
+	*memstart = (*memstart + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
+
+	z3_mem = kernel_map (board_addr, board_size,
+			     KERNELMAP_NOCACHE_SER, memstart);
+
+	z3_regs = (char*) z3_mem;
+	z3_fbmem = z3_mem + VIDEO_MEM_OFFSET;
+
+	/* Get memory size - for now we asume its a 4MB board */
+
+	z3_size = 0x00400000; /* 4 MB */
+
+	memset ((char*)z3_fbmem, 0, z3_size);
+
+	/* Disable hardware cursor */
+
+	seq_w(SEQ_CURSOR_Y_INDEX, 0x00);
+
+
+#if 0
+	/* Initialize hardware cursor */
+	CursorBase = (unsigned long *)((char *)(z3_mem) + z3_size - 0x400);
+	for (i=0; i < 8; i++){
+		*(CursorBase  +(i*4)) = 0xffffff00;
+		*(CursorBase+1+(i*4)) = 0xffff0000;
+		*(CursorBase+2+(i*4)) = 0xffff0000;
+		*(CursorBase+3+(i*4)) = 0xffff0000;
+	}
+	for (i=8; i < 64; i++){
+		*(CursorBase  +(i*4)) = 0xffff0000;
+		*(CursorBase+1+(i*4)) = 0xffff0000;
+		*(CursorBase+2+(i*4)) = 0xffff0000;
+		*(CursorBase+3+(i*4)) = 0xffff0000;
+	}
+#endif
+
+	retz3_setcolreg (255, 56, 100, 160, 0);
+	retz3_setcolreg (254, 0, 0, 0, 0);
+
+	return 0;
+}
+
+
+/*
+ *    This function should fill in the `fix' structure based on the
+ *    values in the `par' structure.
+ */
+
+static int retz3_encode_fix(struct fb_fix_screeninfo *fix,
+                          struct retz3_fb_par *par)
+{
+	int i;
+
+	strcpy(fix->id, retz3_fb_name);
+	fix->smem_start = z3_fbmem;
+	fix->smem_len = z3_size;
+
+	fix->type = FB_TYPE_PACKED_PIXELS;
+	fix->type_aux = 0;
+	if (par->bpp == 8)
+		fix->visual = FB_VISUAL_PSEUDOCOLOR;
+	else
+		fix->visual = FB_VISUAL_DIRECTCOLOR;
+
+	fix->xpanstep = 0;
+	fix->ypanstep = 0;
+	fix->ywrapstep = 0;
+	fix->line_length = 0;
+
+	for (i = 0; i < arraysize(fix->reserved); i++)
+		fix->reserved[i] = 0;
+
+	return 0;
+}
+
+
+/*
+ *    Get the video params out of `var'. If a value doesn't fit, round
+ *    it up, if it's too big, return -EINVAL.
+ */
+
+static int retz3_decode_var(struct fb_var_screeninfo *var,
+			    struct retz3_fb_par *par)
+{
+	par->xres = var->xres;
+	par->yres = var->yres;
+	par->xres_vir = var->xres_virtual;
+	par->yres_vir = var->yres_virtual;
+	par->bpp = var->bits_per_pixel;
+	par->pixclock = var->pixclock;
+	par->vmode = var->vmode;
+
+	par->red = var->red;
+	par->green = var->green;
+	par->blue = var->blue;
+	par->transp = var->transp;
+
+	par->left_margin = var->left_margin;
+	par->right_margin = var->right_margin;
+	par->upper_margin = var->upper_margin;
+	par->lower_margin = var->lower_margin;
+	par->hsync_len = var->hsync_len;
+	par->vsync_len = var->vsync_len;
+
+	return 0;
+}
+
+
+/*
+ *    Fill the `var' structure based on the values in `par' and maybe
+ *    other values read out of the hardware.
+ */
+
+static int retz3_encode_var(struct fb_var_screeninfo *var,
+			    struct retz3_fb_par *par)
+{
+	int i;
+
+	var->xres = par->xres;
+	var->yres = par->yres;
+	var->xres_virtual = par->xres_vir;
+	var->yres_virtual = par->yres_vir;
+	var->xoffset = 0;
+	var->yoffset = 0;
+
+	var->bits_per_pixel = par->bpp;
+	var->grayscale = 0;
+
+	var->red = par->red;
+	var->green = par->green;
+	var->blue = par->blue;
+	var->transp = par->transp;
+
+	var->nonstd = 0;
+	var->activate = 0;
+
+	var->height = -1;
+	var->width = -1;
+
+	var->accel = FB_ACCEL_RETINAZ3;
+
+	var->pixclock = par->pixclock;
+
+	var->sync = 0;				/* ??? */
+	var->left_margin = par->left_margin;
+	var->right_margin = par->right_margin;
+	var->upper_margin = par->upper_margin;
+	var->lower_margin = par->lower_margin;
+	var->hsync_len = par->hsync_len;
+	var->vsync_len = par->vsync_len;
+
+	for (i = 0; i < arraysize(var->reserved); i++)
+		var->reserved[i] = 0;
+
+	var->vmode = par->vmode;
+	return 0;
+}
+
+
+/*
+ *    Set a single color register. The values supplied are already
+ *    rounded down to the hardware's capabilities (according to the
+ *    entries in the var structure). Return != 0 for invalid regno.
+ */
+
+static int retz3_setcolreg(unsigned int regno, unsigned int red,
+			   unsigned int green, unsigned int blue,
+			   unsigned int transp)
+{
+	/* We'll get to this */
+
+	if (regno > 255)
+		return 1;
+
+	retz3_color_table [regno][0] = red & 0xff;
+	retz3_color_table [regno][1] = green & 0xff;
+	retz3_color_table [regno][2] = blue & 0xff;
+	retz3_color_table [regno][3] = transp;
+
+	reg_w(VDAC_ADDRESS_W, regno);
+	reg_w(VDAC_DATA, (red & 0xff) >> 2);
+	reg_w(VDAC_DATA, (green & 0xff) >> 2);
+	reg_w(VDAC_DATA, (blue & 0xff) >> 2);
+
+	return 0;
+}
+
+
+/*
+ *    Read a single color register and split it into
+ *    colors/transparent. Return != 0 for invalid regno.
+ */
+
+static int retz3_getcolreg(unsigned int regno, unsigned int *red,
+			   unsigned int *green, unsigned int *blue,
+			   unsigned int *transp)
+{
+	if (regno > 255)
+		return 1;
+	*red    = retz3_color_table [regno][0];
+	*green  = retz3_color_table [regno][1];
+	*blue   = retz3_color_table [regno][2];
+	*transp = retz3_color_table [regno][3];
+	return 0;
+}
+
+
+/*
+ *    (Un)Blank the screen
+ */
+
+void retz3_blank(int blank)
+{
+	int i;
+
+	if (blank)
+		for (i = 0; i < 256; i++){
+			reg_w(VDAC_ADDRESS_W, i);
+			reg_w(VDAC_DATA, 0);
+			reg_w(VDAC_DATA, 0);
+			reg_w(VDAC_DATA, 0);
+		}
+	else
+		for (i = 0; i < 256; i++){
+			reg_w(VDAC_ADDRESS_W, i);
+			reg_w(VDAC_DATA, retz3_color_table [i][0] >> 2);
+			reg_w(VDAC_DATA, retz3_color_table [i][1] >> 2);
+			reg_w(VDAC_DATA, retz3_color_table [i][2] >> 2);
+		}
+}
+
+
+void retz3_bitblt (struct fb_var_screeninfo *var,
+		   unsigned short srcx, unsigned short srcy, unsigned
+		   short destx, unsigned short desty, unsigned short
+		   width, unsigned short height, unsigned short cmd,
+		   unsigned short mask)
+{
+
+	volatile unsigned long *acm = (unsigned long *) (z3_mem + ACM_OFFSET);
+	unsigned long *pattern = (unsigned long *)(z3_fbmem + PAT_MEM_OFF);
+
+	unsigned short mod;
+	unsigned long tmp;
+	unsigned long pat, src, dst;
+	unsigned char blt_status;
+
+	int i, xres_virtual = var->xres_virtual;
+	short bpp = (var->bits_per_pixel & 0xff);
+
+	if (bpp < 8)
+		bpp = 8;
+
+	tmp = mask | (mask << 16);
+
+#if 0
+	/*
+	 * Check for blitter finished before we start messing with the
+	 * pattern.
+	 */
+	do{
+		blt_status = *(((volatile unsigned char *)acm) +
+			       (ACM_START_STATUS + 2));
+	}while ((blt_status & 1) == 0);
+#endif
+
+	i = 0;
+	do{
+		*pattern++ = tmp;
+	}while(i++ < bpp/4);
+
+	tmp = cmd << 8;
+	*(acm + ACM_RASTEROP_ROTATION/4) = tmp;
+
+	mod = 0xc0c2;
+
+	pat = 8 * PAT_MEM_OFF;
+	dst = bpp * (destx + desty * xres_virtual);
+
+	/*
+	 * Source is not set for clear.
+	 */
+	if ((cmd != Z3BLTclear) && (cmd != Z3BLTset)) {
+		src = bpp * (srcx + srcy * xres_virtual);
+
+		if (destx > srcx) {
+			mod &= ~0x8000;
+			src += bpp * (width - 1);
+			dst += bpp * (width - 1);
+			pat += bpp * 2;
+		}
+		if (desty > srcy) {
+			mod &= ~0x4000;
+			src += bpp * (height - 1) * xres_virtual;
+			dst += bpp * (height - 1) * xres_virtual;
+			pat += bpp * 4;
+		}
+
+		*(acm + ACM_SOURCE/4) = cpu_to_le32(src);
+	}
+
+	*(acm + ACM_PATTERN/4) = cpu_to_le32(pat);
+
+	*(acm + ACM_DESTINATION/4) = cpu_to_le32(dst);
+
+	tmp = mod << 16;
+	*(acm + ACM_CONTROL/4) = tmp;
+
+	tmp  = width | (height << 16);
+	
+	*(acm + ACM_BITMAP_DIMENSION/4) = cpu_to_le32(tmp);
+
+	*(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x00;
+	*(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x01;
+
+	/*
+	 * No reason to wait for the blitter to finish, it is better
+	 * just to check if it has finished before we use it again.
+	 */
+#if 1
+#if 0
+	while ((*(((volatile unsigned char *)acm) +
+		  (ACM_START_STATUS + 2)) & 1) == 0);
+#else
+	do{
+		blt_status = *(((volatile unsigned char *)acm) +
+			       (ACM_START_STATUS + 2));
+	}
+	while ((blt_status & 1) == 0);
+#endif
+#endif
+}
+
+#if 0
+void retz3_fill (unsigned short x, unsigned short y, unsigned
+		 short width, unsigned short height,
+		 unsigned short mode, unsigned short color)
+{
+
+}
+#endif
+
+
+/**************************************************************
+ * Move cursor to x, y
+ */
+void retz3_MoveCursor (unsigned short x, unsigned short y)
+{
+	/* Guess we gotta deal with the cursor at some point */
+}
+
+
+/* -------------------- Interfaces to hardware functions -------------------- */
+
+
+static struct fb_hwswitch retz3_switch = {
+	retz3_init, retz3_encode_fix, retz3_decode_var, retz3_encode_var,
+	retz3_getcolreg, retz3_setcolreg, retz3_blank
+};
+
+
+/* -------------------- Generic routines ------------------------------------ */
+
+
+/*
+ *    Fill the hardware's `par' structure.
+ */
+
+static void retz3_fb_get_par(struct retz3_fb_par *par)
+{
+	if (current_par_valid)
+		*par = current_par;
+	else
+		fbhw->decode_var(&retz3_fb_predefined[z3fb_mode], par);
+}
+
+
+static void retz3_fb_set_par(struct retz3_fb_par *par)
+{
+	current_par = *par;
+	current_par_valid = 1;
+}
+
+
+static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
+{
+	int err, activate;
+	struct retz3_fb_par par;
+
+	if ((err = fbhw->decode_var(var, &par)))
+		return err;
+	activate = var->activate;
+	if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW && isactive)
+		retz3_fb_set_par(&par);
+	fbhw->encode_var(var, &par);
+	var->activate = activate;
+
+#if 1
+	retz3_set_video(var, &current_par);
+#endif
+	return 0;
+}
+
+
+/*
+ *    Default Colormaps
+ */
+
+static unsigned short red16[] =
+	{ 0x0000, 0x0000, 0x0000, 0x0000, 0xc000, 0xc000, 0xc000, 0xc000,
+	  0x8000, 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff };
+static unsigned short green16[] =
+	{ 0x0000, 0x0000, 0xc000, 0xc000, 0x0000, 0x0000, 0xc000, 0xc000,
+	  0x8000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff };
+static unsigned short blue16[] =
+	{ 0x0000, 0xc000, 0x0000, 0xc000, 0x0000, 0xc000, 0x0000, 0xc000,
+	  0x8000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff };
+
+
+static struct fb_cmap default_16_colors =
+   { 0, 16, red16, green16, blue16, NULL };
+
+
+static struct fb_cmap *get_default_colormap(int bpp)
+{
+	return &default_16_colors;
+}
+
+
+#define CNVT_TOHW(val,width)     ((((val)<<(width))+0x7fff-(val))>>16)
+#define CNVT_FROMHW(val,width)   (((width) ? ((((val)<<16)-(val)) / \
+                                              ((1<<(width))-1)) : 0))
+
+static int do_fb_get_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var,
+                          int kspc)
+{
+	int i, start;
+	unsigned short *red, *green, *blue, *transp;
+	unsigned int hred, hgreen, hblue, htransp;
+
+	red = cmap->red;
+	green = cmap->green;
+	blue = cmap->blue;
+	transp = cmap->transp;
+	start = cmap->start;
+
+	if (start < 0)
+		return -EINVAL;
+	for (i = 0; i < cmap->len; i++) {
+		if (fbhw->getcolreg(start++, &hred, &hgreen, &hblue, &htransp))
+			return 0;
+		hred = CNVT_FROMHW(hred, var->red.length);
+		hgreen = CNVT_FROMHW(hgreen, var->green.length);
+		hblue = CNVT_FROMHW(hblue, var->blue.length);
+		htransp = CNVT_FROMHW(htransp, var->transp.length);
+		if (kspc) {
+			*red = hred;
+			*green = hgreen;
+			*blue = hblue;
+			if (transp)
+				*transp = htransp;
+		} else {
+			put_user(hred, red);
+			put_user(hgreen, green);
+			put_user(hblue, blue);
+			if (transp)
+				put_user(htransp, transp);
+		}
+		red++;
+		green++;
+		blue++;
+		if (transp)
+			transp++;
+	}
+	return 0;
+}
+
+
+static int do_fb_set_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var,
+                          int kspc)
+{
+	int i, start;
+	unsigned short *red, *green, *blue, *transp;
+	unsigned int hred, hgreen, hblue, htransp;
+
+	red = cmap->red;
+	green = cmap->green;
+	blue = cmap->blue;
+	transp = cmap->transp;
+	start = cmap->start;
+
+	if (start < 0)
+		return -EINVAL;
+	for (i = 0; i < cmap->len; i++) {
+		if (kspc) {
+			hred = *red;
+			hgreen = *green;
+			hblue = *blue;
+			htransp = transp ? *transp : 0;
+		} else {
+			get_user(hred, red);
+			get_user(hgreen, green);
+			get_user(hblue, blue);
+			if (transp)
+				get_user(htransp, transp);
+			else
+				htransp = 0;
+		}
+		hred = CNVT_TOHW(hred, var->red.length);
+		hgreen = CNVT_TOHW(hgreen, var->green.length);
+		hblue = CNVT_TOHW(hblue, var->blue.length);
+		htransp = CNVT_TOHW(htransp, var->transp.length);
+		red++;
+		green++;
+		blue++;
+		if (transp)
+			transp++;
+		if (fbhw->setcolreg(start++, hred, hgreen, hblue, htransp))
+			return 0;
+	}
+	return 0;
+}
+
+
+static void do_install_cmap(int con)
+{
+	if (con != currcon)
+		return;
+	if (disp[con].cmap.len)
+		do_fb_set_cmap(&disp[con].cmap, &disp[con].var, 1);
+	else
+		do_fb_set_cmap(get_default_colormap(disp[con].var.bits_per_pixel),
+                                          &disp[con].var, 1);
+}
+
+
+static void memcpy_fs(int fsfromto, void *to, void *from, int len)
+{
+	switch (fsfromto) {
+	case 0:
+		memcpy(to, from, len);
+		return;
+	case 1:
+		copy_from_user(to, from, len);
+		return;
+	case 2:
+		copy_to_user(to, from, len);
+		return;
+	}
+}
+
+
+static void copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto)
+{
+	int size;
+	int tooff = 0, fromoff = 0;
+
+	if (to->start > from->start)
+		fromoff = to->start-from->start;
+	else
+		tooff = from->start-to->start;
+	size = to->len-tooff;
+	if (size > from->len-fromoff)
+		size = from->len-fromoff;
+	if (size < 0)
+		return;
+	size *= sizeof(unsigned short);
+	memcpy_fs(fsfromto, to->red+tooff, from->red+fromoff, size);
+	memcpy_fs(fsfromto, to->green+tooff, from->green+fromoff, size);
+	memcpy_fs(fsfromto, to->blue+tooff, from->blue+fromoff, size);
+	if (from->transp && to->transp)
+		memcpy_fs(fsfromto, to->transp+tooff,
+			  from->transp+fromoff, size);
+}
+
+
+static int alloc_cmap(struct fb_cmap *cmap, int len, int transp)
+{
+	int size = len*sizeof(unsigned short);
+
+	if (cmap->len != len) {
+		if (cmap->red)
+			kfree(cmap->red);
+		if (cmap->green)
+			kfree(cmap->green);
+		if (cmap->blue)
+			kfree(cmap->blue);
+		if (cmap->transp)
+			kfree(cmap->transp);
+		cmap->red = cmap->green = cmap->blue = cmap->transp = NULL;
+		cmap->len = 0;
+		if (!len)
+			return 0;
+		if (!(cmap->red = kmalloc(size, GFP_ATOMIC)))
+			return -1;
+		if (!(cmap->green = kmalloc(size, GFP_ATOMIC)))
+			return -1;
+		if (!(cmap->blue = kmalloc(size, GFP_ATOMIC)))
+			return -1;
+		if (transp) {
+			if (!(cmap->transp = kmalloc(size, GFP_ATOMIC)))
+				return -1;
+		} else
+			cmap->transp = NULL;
+	}
+	cmap->start = 0;
+	cmap->len = len;
+	copy_cmap(get_default_colormap(len), cmap, 0);
+	return 0;
+}
+
+
+/*
+ *    Get the Fixed Part of the Display
+ */
+
+static int retz3_fb_get_fix(struct fb_fix_screeninfo *fix, int con)
+{
+	struct retz3_fb_par par;
+	int error = 0;
+
+	if (con == -1)
+		retz3_fb_get_par(&par);
+	else
+		error = fbhw->decode_var(&disp[con].var, &par);
+	return(error ? error : fbhw->encode_fix(fix, &par));
+}
+
+
+/*
+ *    Get the User Defined Part of the Display
+ */
+
+static int retz3_fb_get_var(struct fb_var_screeninfo *var, int con)
+{
+	struct retz3_fb_par par;
+	int error = 0;
+
+	if (con == -1) {
+		retz3_fb_get_par(&par);
+		error = fbhw->encode_var(var, &par);
+	} else
+		*var = disp[con].var;
+	return error;
+}
+
+
+static void retz3_fb_set_disp(int con)
+{
+	struct fb_fix_screeninfo fix;
+
+	retz3_fb_get_fix(&fix, con);
+	if (con == -1)
+		con = 0;
+	disp[con].screen_base = (unsigned char *)fix.smem_start;
+	disp[con].visual = fix.visual;
+	disp[con].type = fix.type;
+	disp[con].type_aux = fix.type_aux;
+	disp[con].ypanstep = fix.ypanstep;
+	disp[con].ywrapstep = fix.ywrapstep;
+	disp[con].can_soft_blank = 1;
+	disp[con].inverse = z3fb_inverse;
+}
+
+
+/*
+ *    Set the User Defined Part of the Display
+ */
+
+static int retz3_fb_set_var(struct fb_var_screeninfo *var, int con)
+{
+	int err, oldxres, oldyres, oldvxres, oldvyres, oldbpp;
+
+	if ((err = do_fb_set_var(var, con == currcon)))
+		return err;
+	if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
+		oldxres = disp[con].var.xres;
+		oldyres = disp[con].var.yres;
+		oldvxres = disp[con].var.xres_virtual;
+		oldvyres = disp[con].var.yres_virtual;
+		oldbpp = disp[con].var.bits_per_pixel;
+		disp[con].var = *var;
+		if (oldxres != var->xres || oldyres != var->yres ||
+		    oldvxres != var->xres_virtual ||
+		    oldvyres != var->yres_virtual ||
+		    oldbpp != var->bits_per_pixel) {
+			retz3_fb_set_disp(con);
+			(*fb_info.changevar)(con);
+			alloc_cmap(&disp[con].cmap, 0, 0);
+			do_install_cmap(con);
+		}
+	}
+	var->activate = 0;
+	return 0;
+}
+
+
+/*
+ *    Get the Colormap
+ */
+
+static int retz3_fb_get_cmap(struct fb_cmap *cmap, int kspc, int con)
+{
+	if (con == currcon) /* current console? */
+		return(do_fb_get_cmap(cmap, &disp[con].var, kspc));
+	else if (disp[con].cmap.len) /* non default colormap? */
+		copy_cmap(&disp[con].cmap, cmap, kspc ? 0 : 2);
+	else
+		copy_cmap(get_default_colormap(disp[con].var.bits_per_pixel),
+			  cmap, kspc ? 0 : 2);
+	return 0;
+}
+
+
+/*
+ *    Set the Colormap
+ */
+
+static int retz3_fb_set_cmap(struct fb_cmap *cmap, int kspc, int con)
+{
+	int err;
+
+	if (!disp[con].cmap.len) {       /* no colormap allocated? */
+		if ((err = alloc_cmap(&disp[con].cmap,
+				      1<<disp[con].var.bits_per_pixel, 0)))
+			return err;
+	}
+	if (con == currcon)              /* current console? */
+		return(do_fb_set_cmap(cmap, &disp[con].var, kspc));
+	else
+		copy_cmap(cmap, &disp[con].cmap, kspc ? 0 : 1);
+	return 0;
+}
+
+
+/*
+ *    Pan or Wrap the Display
+ *
+ *    This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
+ */
+
+static int retz3_fb_pan_display(struct fb_var_screeninfo *var, int con)
+{
+	return -EINVAL;
+}
+
+
+/*
+ *    RetinaZ3 Frame Buffer Specific ioctls
+ */
+
+static int retz3_fb_ioctl(struct inode *inode, struct file *file,
+                          unsigned int cmd, unsigned long arg, int con)
+{
+	return -EINVAL;
+}
+
+
+static struct fb_ops retz3_fb_ops = {
+   retz3_fb_get_fix, retz3_fb_get_var, retz3_fb_set_var, retz3_fb_get_cmap,
+   retz3_fb_set_cmap, retz3_fb_pan_display, retz3_fb_ioctl
+};
+
+
+int retz3_probe(void)
+{
+	z3_key = zorro_find(MANUF_MACROSYSTEMS2, PROD_RETINA_Z3, 0, 0);
+	return(z3_key);
+}
+
+
+void retz3_video_setup(char *options, int *ints)
+{
+	char *this_opt;
+	int i;
+
+	fb_info.fontname[0] = '\0';
+
+	if (!options || !*options)
+		return;
+
+	for (this_opt = strtok(options, ","); this_opt; 
+	     this_opt = strtok(NULL, ",")){
+		if (!strcmp(this_opt, "inverse")) {
+			z3fb_inverse = 1;
+			for (i = 0; i < 16; i++) {
+				red16[i] = ~red16[i];
+				green16[i] = ~green16[i];
+				blue16[i] = ~blue16[i];
+			}
+		} else if (!strncmp(this_opt, "font:", 5))
+			strcpy(fb_info.fontname, this_opt+5);
+		else
+			z3fb_mode = get_video_mode(this_opt);
+	}
+}
+
+
+/*
+ *    Initialization
+ */
+
+struct fb_info *retz3_fb_init(long *mem_start)
+{
+	int err;
+	struct retz3_fb_par par;
+
+	memstart = mem_start;
+
+	fbhw = &retz3_switch;
+
+	err = register_framebuffer(retz3_fb_name, &node, &retz3_fb_ops,
+				   NUM_TOTAL_MODES, retz3_fb_predefined);
+	if (err < 0)
+		panic("Cannot register frame buffer\n");
+
+	fbhw->init();
+
+	if (z3fb_mode == -1)
+		z3fb_mode = 1;
+
+	fbhw->decode_var(&retz3_fb_predefined[z3fb_mode], &par);
+	fbhw->encode_var(&retz3_fb_predefined[0], &par);
+
+	strcpy(fb_info.modename, retz3_fb_name);
+	fb_info.disp = disp;
+	fb_info.switch_con = &z3fb_switch;
+	fb_info.updatevar = &z3fb_updatevar;
+	fb_info.blank = &z3fb_blank;
+	fb_info.setcmap = &z3fb_setcmap;
+
+	do_fb_set_var(&retz3_fb_predefined[0], 0);
+	retz3_fb_get_var(&disp[0].var, -1);
+	retz3_fb_set_disp(-1);
+	do_install_cmap(0);
+
+	return &fb_info;
+}
+
+
+static int z3fb_switch(int con)
+{
+	/* Do we have to save the colormap? */
+	if (disp[currcon].cmap.len)
+		do_fb_get_cmap(&disp[currcon].cmap, &disp[currcon].var, 1);
+
+	do_fb_set_var(&disp[con].var, 1);
+	currcon = con;
+	/* Install new colormap */
+	do_install_cmap(con);
+	return 0;
+}
+
+
+/*
+ *    Update the `var' structure (called by fbcon.c)
+ *
+ *    This call looks only at yoffset and the FB_VMODE_YWRAP flag in `var'.
+ *    Since it's called by a kernel driver, no range checking is done.
+ */
+
+static int z3fb_updatevar(int con)
+{
+	return 0;
+}
+
+
+/*
+ *    Blank the display.
+ */
+
+static void z3fb_blank(int blank)
+{
+	fbhw->blank(blank);
+}
+
+
+/*
+ *    Set the colormap
+ */
+
+static int z3fb_setcmap(struct fb_cmap *cmap, int con)
+{
+	return(retz3_fb_set_cmap(cmap, 1, con));
+}
+
+
+/*
+ *    Get a Video Mode
+ */
+
+static int get_video_mode(const char *name)
+{
+	int i;
+
+	for (i = 1; i <= NUM_PREDEF_MODES; i++)
+		if (!strcmp(name, retz3_fb_modenames[i])){
+			retz3_fb_predefined[0] = retz3_fb_predefined[i];
+			return i;
+		}
+	return -1;
+}
diff -u --recursive --new-file v2.1.35/linux/arch/m68k/amiga/retz3fb.h linux/arch/m68k/amiga/retz3fb.h
--- v2.1.35/linux/arch/m68k/amiga/retz3fb.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/m68k/amiga/retz3fb.h	Tue Apr 22 22:45:15 1997
@@ -0,0 +1,572 @@
+/*
+ * Linux/arch/m68k/amiga/retz3fb.h -- Defines and macros for the
+ *                                    RetinaZ3 frame buffer device
+ *
+ *    Copyright (C) 1997 Jes Sorensen
+ *
+ * History:
+ *   - 22 Jan 97: Initial work
+ *
+ *
+ * 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.
+ */
+
+/*
+ * Macros to read and write to registers.
+ */
+#define reg_w(reg,dat) (*(z3_regs + reg) = dat)
+#define reg_r(reg) (*(z3_regs + reg))
+
+/*
+ * Macro to access the sequencer.
+ */
+#define seq_w(sreg,sdat) \
+	do{ reg_w(SEQ_IDX, sreg); reg_w(SEQ_DATA, sdat); } while(0)
+
+/*
+ * Macro to access the CRT controller.
+ */
+#define crt_w(creg,cdat) \
+	do{ reg_w(CRT_IDX, creg); reg_w(CRT_DATA, cdat); } while(0)
+
+/*
+ * Macro to access the graphics controller.
+ */
+#define gfx_w(greg,gdat) \
+	do{ reg_w(GFX_IDX, greg); reg_w(GFX_DATA, gdat); } while(0)
+
+/*
+ * Macro to access the attribute controller.
+ */
+#define attr_w(areg,adat) \
+	do{ reg_w(ACT_IDX, areg); reg_w(ACT_DATA, adat); } while(0)
+
+/*
+ * Macro to access the pll.
+ */
+#define pll_w(preg,pdat) \
+	do{ reg_w(PLL_IDX, preg); \
+	    reg_w(PLL_DATA, (pdat & 0xff)); \
+	    reg_w(PLL_DATA, (pdat >> 8));\
+	} while(0)
+
+/*
+ * Offsets
+ */
+#define VIDEO_MEM_OFFSET	0x00c00000
+#define ACM_OFFSET		0x00b00000
+
+/*
+ * Accelerator Control Menu
+ */
+#define ACM_PRIMARY_OFFSET	0x00
+#define ACM_SECONDARY_OFFSET	0x04
+#define ACM_MODE_CONTROL	0x08
+#define ACM_CURSOR_POSITION	0x0c
+#define ACM_START_STATUS	0x30
+#define ACM_CONTROL		0x34
+#define ACM_RASTEROP_ROTATION	0x38
+#define ACM_BITMAP_DIMENSION	0x3c
+#define ACM_DESTINATION		0x40
+#define ACM_SOURCE		0x44
+#define ACM_PATTERN		0x48
+#define ACM_FOREGROUND		0x4c
+#define ACM_BACKGROUND		0x50
+
+/*
+ * Video DAC addresses
+ */
+#define VDAC_ADDRESS		0x03c8
+#define VDAC_ADDRESS_W		0x03c8
+#define VDAC_ADDRESS_R		0x03c7
+#define VDAC_STATE		0x03c7
+#define VDAC_DATA		0x03c9
+#define VDAC_MASK		0x03c6
+
+/*
+ * Sequencer
+ */
+#define SEQ_IDX			0x03c4	/* Sequencer Index */
+#define SEQ_DATA		0x03c5
+#define SEQ_RESET		0x00
+#define SEQ_CLOCKING_MODE	0x01
+#define SEQ_MAP_MASK		0x02
+#define SEQ_CHAR_MAP_SELECT	0x03
+#define SEQ_MEMORY_MODE		0x04
+#define SEQ_EXTENDED_ENABLE	0x05	/* NCR extensions */
+#define SEQ_UNKNOWN1         	0x06
+#define SEQ_UNKNOWN2         	0x07
+#define SEQ_CHIP_ID		0x08
+#define SEQ_UNKNOWN3         	0x09
+#define SEQ_CURSOR_COLOR1	0x0a
+#define SEQ_CURSOR_COLOR0	0x0b
+#define SEQ_CURSOR_CONTROL	0x0c
+#define SEQ_CURSOR_X_LOC_HI	0x0d
+#define SEQ_CURSOR_X_LOC_LO	0x0e
+#define SEQ_CURSOR_Y_LOC_HI	0x0f
+#define SEQ_CURSOR_Y_LOC_LO	0x10
+#define SEQ_CURSOR_X_INDEX	0x11
+#define SEQ_CURSOR_Y_INDEX	0x12
+#define SEQ_CURSOR_STORE_HI	0x13
+#define SEQ_CURSOR_STORE_LO	0x14
+#define SEQ_CURSOR_ST_OFF_HI	0x15
+#define SEQ_CURSOR_ST_OFF_LO	0x16
+#define SEQ_CURSOR_PIXELMASK	0x17
+#define SEQ_PRIM_HOST_OFF_HI	0x18
+#define SEQ_PRIM_HOST_OFF_LO	0x19
+#define SEQ_LINEAR_0		0x1a
+#define SEQ_LINEAR_1		0x1b
+#define SEQ_SEC_HOST_OFF_HI	0x1c
+#define SEQ_SEC_HOST_OFF_LO	0x1d
+#define SEQ_EXTENDED_MEM_ENA	0x1e
+#define SEQ_EXT_CLOCK_MODE	0x1f
+#define SEQ_EXT_VIDEO_ADDR	0x20
+#define SEQ_EXT_PIXEL_CNTL	0x21
+#define SEQ_BUS_WIDTH_FEEDB	0x22
+#define SEQ_PERF_SELECT		0x23
+#define SEQ_COLOR_EXP_WFG	0x24
+#define SEQ_COLOR_EXP_WBG	0x25
+#define SEQ_EXT_RW_CONTROL	0x26
+#define SEQ_MISC_FEATURE_SEL	0x27
+#define SEQ_COLOR_KEY_CNTL	0x28
+#define SEQ_COLOR_KEY_MATCH0	0x29
+#define SEQ_COLOR_KEY_MATCH1 	0x2a
+#define SEQ_COLOR_KEY_MATCH2 	0x2b
+#define SEQ_UNKNOWN6         	0x2c
+#define SEQ_CRC_CONTROL		0x2d
+#define SEQ_CRC_DATA_LOW	0x2e
+#define SEQ_CRC_DATA_HIGH	0x2f
+#define SEQ_MEMORY_MAP_CNTL	0x30
+#define SEQ_ACM_APERTURE_1	0x31
+#define SEQ_ACM_APERTURE_2	0x32
+#define SEQ_ACM_APERTURE_3	0x33
+#define SEQ_BIOS_UTILITY_0	0x3e
+#define SEQ_BIOS_UTILITY_1	0x3f
+
+/*
+ * Graphics Controller
+ */
+#define GFX_IDX			0x03ce
+#define GFX_DATA		0x03cf
+#define GFX_SET_RESET		0x00
+#define GFX_ENABLE_SET_RESET	0x01
+#define GFX_COLOR_COMPARE	0x02
+#define GFX_DATA_ROTATE		0x03
+#define GFX_READ_MAP_SELECT	0x04
+#define GFX_GRAPHICS_MODE	0x05
+#define GFX_MISC		0x06
+#define GFX_COLOR_XCARE		0x07
+#define GFX_BITMASK		0x08
+
+/*
+ * CRT Controller
+ */
+#define CRT_IDX			0x03d4
+#define CRT_DATA		0x03d5
+#define CRT_HOR_TOTAL		0x00
+#define CRT_HOR_DISP_ENA_END	0x01
+#define CRT_START_HOR_BLANK	0x02
+#define CRT_END_HOR_BLANK	0x03
+#define CRT_START_HOR_RETR	0x04
+#define CRT_END_HOR_RETR	0x05
+#define CRT_VER_TOTAL		0x06
+#define CRT_OVERFLOW		0x07
+#define CRT_PRESET_ROW_SCAN	0x08
+#define CRT_MAX_SCAN_LINE	0x09
+#define CRT_CURSOR_START	0x0a
+#define CRT_CURSOR_END		0x0b
+#define CRT_START_ADDR_HIGH	0x0c
+#define CRT_START_ADDR_LOW	0x0d
+#define CRT_CURSOR_LOC_HIGH	0x0e
+#define CRT_CURSOR_LOC_LOW	0x0f
+#define CRT_START_VER_RETR	0x10
+#define CRT_END_VER_RETR	0x11
+#define CRT_VER_DISP_ENA_END	0x12
+#define CRT_OFFSET		0x13
+#define CRT_UNDERLINE_LOC	0x14
+#define CRT_START_VER_BLANK	0x15
+#define CRT_END_VER_BLANK	0x16
+#define CRT_MODE_CONTROL	0x17
+#define CRT_LINE_COMPARE	0x18
+#define CRT_UNKNOWN1         	0x19
+#define CRT_UNKNOWN2         	0x1a
+#define CRT_UNKNOWN3         	0x1b
+#define CRT_UNKNOWN4         	0x1c
+#define CRT_UNKNOWN5         	0x1d
+#define CRT_UNKNOWN6         	0x1e
+#define CRT_UNKNOWN7         	0x1f
+#define CRT_UNKNOWN8         	0x20
+#define CRT_UNKNOWN9		0x21
+#define CRT_UNKNOWN10		0x22
+#define CRT_UNKNOWN11      	0x23
+#define CRT_UNKNOWN12      	0x24
+#define CRT_UNKNOWN13      	0x25
+#define CRT_UNKNOWN14      	0x26
+#define CRT_UNKNOWN15      	0x27
+#define CRT_UNKNOWN16      	0x28
+#define CRT_UNKNOWN17      	0x29
+#define CRT_UNKNOWN18      	0x2a
+#define CRT_UNKNOWN19      	0x2b
+#define CRT_UNKNOWN20      	0x2c
+#define CRT_UNKNOWN21      	0x2d
+#define CRT_UNKNOWN22      	0x2e
+#define CRT_UNKNOWN23      	0x2f
+#define CRT_EXT_HOR_TIMING1	0x30	/* NCR crt extensions */
+#define CRT_EXT_START_ADDR	0x31
+#define CRT_EXT_HOR_TIMING2	0x32
+#define CRT_EXT_VER_TIMING	0x33
+#define CRT_MONITOR_POWER	0x34
+
+/*
+ * General Registers
+ */
+#define GREG_STATUS0_R		0x03c2
+#define GREG_STATUS1_R		0x03da
+#define GREG_MISC_OUTPUT_R	0x03cc
+#define GREG_MISC_OUTPUT_W	0x03c2	
+#define GREG_FEATURE_CONTROL_R	0x03ca
+#define GREG_FEATURE_CONTROL_W	0x03da
+#define GREG_POS		0x0102
+
+/*
+ * Attribute Controller
+ */
+#define ACT_IDX			0x03C0
+#define ACT_ADDRESS_R		0x03C0
+#define ACT_DATA		0x03C0
+#define ACT_ADDRESS_RESET	0x03DA
+#define ACT_PALETTE0		0x00
+#define ACT_PALETTE1		0x01
+#define ACT_PALETTE2		0x02
+#define ACT_PALETTE3		0x03
+#define ACT_PALETTE4		0x04
+#define ACT_PALETTE5		0x05
+#define ACT_PALETTE6		0x06
+#define ACT_PALETTE7		0x07
+#define ACT_PALETTE8		0x08
+#define ACT_PALETTE9		0x09
+#define ACT_PALETTE10		0x0A
+#define ACT_PALETTE11		0x0B
+#define ACT_PALETTE12		0x0C
+#define ACT_PALETTE13		0x0D
+#define ACT_PALETTE14		0x0E
+#define ACT_PALETTE15		0x0F
+#define ACT_ATTR_MODE_CNTL	0x10
+#define ACT_OVERSCAN_COLOR	0x11
+#define ACT_COLOR_PLANE_ENA	0x12
+#define ACT_HOR_PEL_PANNING	0x13
+#define ACT_COLOR_SELECT	0x14
+
+/*
+ * PLL
+ */
+#define PLL_IDX			0x83c8
+#define PLL_DATA		0x83c9
+
+/*
+ * Blitter operations
+ */
+#define	Z3BLTclear		0x00	/* 0 */
+#define Z3BLTand		0x80	/* src AND dst */
+#define Z3BLTandReverse		0x40	/* src AND NOT dst */
+#define Z3BLTcopy		0xc0	/* src */
+#define Z3BLTandInverted	0x20	/* NOT src AND dst */
+#define	Z3BLTnoop		0xa0	/* dst */
+#define Z3BLTxor		0x60	/* src XOR dst */
+#define Z3BLTor			0xe0	/* src OR dst */
+#define Z3BLTnor		0x10	/* NOT src AND NOT dst */
+#define Z3BLTequiv		0x90	/* NOT src XOR dst */
+#define Z3BLTinvert		0x50	/* NOT dst */
+#define Z3BLTorReverse		0xd0	/* src OR NOT dst */
+#define Z3BLTcopyInverted	0x30	/* NOT src */
+#define Z3BLTorInverted		0xb0	/* NOT src OR dst */
+#define Z3BLTnand		0x70	/* NOT src OR NOT dst */
+#define Z3BLTset		0xf0	/* 1 */
+/*
+ * Linux/arch/m68k/amiga/retz3fb.h -- Defines and macros for the
+ *                                    RetinaZ3 frame buffer device
+ *
+ *    Copyright (C) 1997 Jes Sorensen
+ *
+ * History:
+ *   - 22 Jan 97: Initial work
+ *
+ *
+ * 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.
+ */
+
+/*
+ * Macros to read and write to registers.
+ */
+#define reg_w(reg,dat) (*(z3_regs + reg) = dat)
+#define reg_r(reg) (*(z3_regs + reg))
+
+/*
+ * Macro to access the sequencer.
+ */
+#define seq_w(sreg,sdat) \
+	do{ reg_w(SEQ_IDX, sreg); reg_w(SEQ_DATA, sdat); } while(0)
+
+/*
+ * Macro to access the CRT controller.
+ */
+#define crt_w(creg,cdat) \
+	do{ reg_w(CRT_IDX, creg); reg_w(CRT_DATA, cdat); } while(0)
+
+/*
+ * Macro to access the graphics controller.
+ */
+#define gfx_w(greg,gdat) \
+	do{ reg_w(GFX_IDX, greg); reg_w(GFX_DATA, gdat); } while(0)
+
+/*
+ * Macro to access the attribute controller.
+ */
+#define attr_w(areg,adat) \
+	do{ reg_w(ACT_IDX, areg); reg_w(ACT_DATA, adat); } while(0)
+
+/*
+ * Macro to access the pll.
+ */
+#define pll_w(preg,pdat) \
+	do{ reg_w(PLL_IDX, preg); \
+	    reg_w(PLL_DATA, (pdat & 0xff)); \
+	    reg_w(PLL_DATA, (pdat >> 8));\
+	} while(0)
+
+/*
+ * Offsets
+ */
+#define VIDEO_MEM_OFFSET	0x00c00000
+#define ACM_OFFSET		0x00b00000
+
+/*
+ * Accelerator Control Menu
+ */
+#define ACM_PRIMARY_OFFSET	0x00
+#define ACM_SECONDARY_OFFSET	0x04
+#define ACM_MODE_CONTROL	0x08
+#define ACM_CURSOR_POSITION	0x0c
+#define ACM_START_STATUS	0x30
+#define ACM_CONTROL		0x34
+#define ACM_RASTEROP_ROTATION	0x38
+#define ACM_BITMAP_DIMENSION	0x3c
+#define ACM_DESTINATION		0x40
+#define ACM_SOURCE		0x44
+#define ACM_PATTERN		0x48
+#define ACM_FOREGROUND		0x4c
+#define ACM_BACKGROUND		0x50
+
+/*
+ * Video DAC addresses
+ */
+#define VDAC_ADDRESS		0x03c8
+#define VDAC_ADDRESS_W		0x03c8
+#define VDAC_ADDRESS_R		0x03c7
+#define VDAC_STATE		0x03c7
+#define VDAC_DATA		0x03c9
+#define VDAC_MASK		0x03c6
+
+/*
+ * Sequencer
+ */
+#define SEQ_IDX			0x03c4	/* Sequencer Index */
+#define SEQ_DATA		0x03c5
+#define SEQ_RESET		0x00
+#define SEQ_CLOCKING_MODE	0x01
+#define SEQ_MAP_MASK		0x02
+#define SEQ_CHAR_MAP_SELECT	0x03
+#define SEQ_MEMORY_MODE		0x04
+#define SEQ_EXTENDED_ENABLE	0x05	/* NCR extensions */
+#define SEQ_UNKNOWN1         	0x06
+#define SEQ_UNKNOWN2         	0x07
+#define SEQ_CHIP_ID		0x08
+#define SEQ_UNKNOWN3         	0x09
+#define SEQ_CURSOR_COLOR1	0x0a
+#define SEQ_CURSOR_COLOR0	0x0b
+#define SEQ_CURSOR_CONTROL	0x0c
+#define SEQ_CURSOR_X_LOC_HI	0x0d
+#define SEQ_CURSOR_X_LOC_LO	0x0e
+#define SEQ_CURSOR_Y_LOC_HI	0x0f
+#define SEQ_CURSOR_Y_LOC_LO	0x10
+#define SEQ_CURSOR_X_INDEX	0x11
+#define SEQ_CURSOR_Y_INDEX	0x12
+#define SEQ_CURSOR_STORE_HI	0x13
+#define SEQ_CURSOR_STORE_LO	0x14
+#define SEQ_CURSOR_ST_OFF_HI	0x15
+#define SEQ_CURSOR_ST_OFF_LO	0x16
+#define SEQ_CURSOR_PIXELMASK	0x17
+#define SEQ_PRIM_HOST_OFF_HI	0x18
+#define SEQ_PRIM_HOST_OFF_LO	0x19
+#define SEQ_LINEAR_0		0x1a
+#define SEQ_LINEAR_1		0x1b
+#define SEQ_SEC_HOST_OFF_HI	0x1c
+#define SEQ_SEC_HOST_OFF_LO	0x1d
+#define SEQ_EXTENDED_MEM_ENA	0x1e
+#define SEQ_EXT_CLOCK_MODE	0x1f
+#define SEQ_EXT_VIDEO_ADDR	0x20
+#define SEQ_EXT_PIXEL_CNTL	0x21
+#define SEQ_BUS_WIDTH_FEEDB	0x22
+#define SEQ_PERF_SELECT		0x23
+#define SEQ_COLOR_EXP_WFG	0x24
+#define SEQ_COLOR_EXP_WBG	0x25
+#define SEQ_EXT_RW_CONTROL	0x26
+#define SEQ_MISC_FEATURE_SEL	0x27
+#define SEQ_COLOR_KEY_CNTL	0x28
+#define SEQ_COLOR_KEY_MATCH0	0x29
+#define SEQ_COLOR_KEY_MATCH1 	0x2a
+#define SEQ_COLOR_KEY_MATCH2 	0x2b
+#define SEQ_UNKNOWN6         	0x2c
+#define SEQ_CRC_CONTROL		0x2d
+#define SEQ_CRC_DATA_LOW	0x2e
+#define SEQ_CRC_DATA_HIGH	0x2f
+#define SEQ_MEMORY_MAP_CNTL	0x30
+#define SEQ_ACM_APERTURE_1	0x31
+#define SEQ_ACM_APERTURE_2	0x32
+#define SEQ_ACM_APERTURE_3	0x33
+#define SEQ_BIOS_UTILITY_0	0x3e
+#define SEQ_BIOS_UTILITY_1	0x3f
+
+/*
+ * Graphics Controller
+ */
+#define GFX_IDX			0x03ce
+#define GFX_DATA		0x03cf
+#define GFX_SET_RESET		0x00
+#define GFX_ENABLE_SET_RESET	0x01
+#define GFX_COLOR_COMPARE	0x02
+#define GFX_DATA_ROTATE		0x03
+#define GFX_READ_MAP_SELECT	0x04
+#define GFX_GRAPHICS_MODE	0x05
+#define GFX_MISC		0x06
+#define GFX_COLOR_XCARE		0x07
+#define GFX_BITMASK		0x08
+
+/*
+ * CRT Controller
+ */
+#define CRT_IDX			0x03d4
+#define CRT_DATA		0x03d5
+#define CRT_HOR_TOTAL		0x00
+#define CRT_HOR_DISP_ENA_END	0x01
+#define CRT_START_HOR_BLANK	0x02
+#define CRT_END_HOR_BLANK	0x03
+#define CRT_START_HOR_RETR	0x04
+#define CRT_END_HOR_RETR	0x05
+#define CRT_VER_TOTAL		0x06
+#define CRT_OVERFLOW		0x07
+#define CRT_PRESET_ROW_SCAN	0x08
+#define CRT_MAX_SCAN_LINE	0x09
+#define CRT_CURSOR_START	0x0a
+#define CRT_CURSOR_END		0x0b
+#define CRT_START_ADDR_HIGH	0x0c
+#define CRT_START_ADDR_LOW	0x0d
+#define CRT_CURSOR_LOC_HIGH	0x0e
+#define CRT_CURSOR_LOC_LOW	0x0f
+#define CRT_START_VER_RETR	0x10
+#define CRT_END_VER_RETR	0x11
+#define CRT_VER_DISP_ENA_END	0x12
+#define CRT_OFFSET		0x13
+#define CRT_UNDERLINE_LOC	0x14
+#define CRT_START_VER_BLANK	0x15
+#define CRT_END_VER_BLANK	0x16
+#define CRT_MODE_CONTROL	0x17
+#define CRT_LINE_COMPARE	0x18
+#define CRT_UNKNOWN1         	0x19
+#define CRT_UNKNOWN2         	0x1a
+#define CRT_UNKNOWN3         	0x1b
+#define CRT_UNKNOWN4         	0x1c
+#define CRT_UNKNOWN5         	0x1d
+#define CRT_UNKNOWN6         	0x1e
+#define CRT_UNKNOWN7         	0x1f
+#define CRT_UNKNOWN8         	0x20
+#define CRT_UNKNOWN9		0x21
+#define CRT_UNKNOWN10		0x22
+#define CRT_UNKNOWN11      	0x23
+#define CRT_UNKNOWN12      	0x24
+#define CRT_UNKNOWN13      	0x25
+#define CRT_UNKNOWN14      	0x26
+#define CRT_UNKNOWN15      	0x27
+#define CRT_UNKNOWN16      	0x28
+#define CRT_UNKNOWN17      	0x29
+#define CRT_UNKNOWN18      	0x2a
+#define CRT_UNKNOWN19      	0x2b
+#define CRT_UNKNOWN20      	0x2c
+#define CRT_UNKNOWN21      	0x2d
+#define CRT_UNKNOWN22      	0x2e
+#define CRT_UNKNOWN23      	0x2f
+#define CRT_EXT_HOR_TIMING1	0x30	/* NCR crt extensions */
+#define CRT_EXT_START_ADDR	0x31
+#define CRT_EXT_HOR_TIMING2	0x32
+#define CRT_EXT_VER_TIMING	0x33
+#define CRT_MONITOR_POWER	0x34
+
+/*
+ * General Registers
+ */
+#define GREG_STATUS0_R		0x03c2
+#define GREG_STATUS1_R		0x03da
+#define GREG_MISC_OUTPUT_R	0x03cc
+#define GREG_MISC_OUTPUT_W	0x03c2	
+#define GREG_FEATURE_CONTROL_R	0x03ca
+#define GREG_FEATURE_CONTROL_W	0x03da
+#define GREG_POS		0x0102
+
+/*
+ * Attribute Controller
+ */
+#define ACT_IDX			0x03C0
+#define ACT_ADDRESS_R		0x03C0
+#define ACT_DATA		0x03C0
+#define ACT_ADDRESS_RESET	0x03DA
+#define ACT_PALETTE0		0x00
+#define ACT_PALETTE1		0x01
+#define ACT_PALETTE2		0x02
+#define ACT_PALETTE3		0x03
+#define ACT_PALETTE4		0x04
+#define ACT_PALETTE5		0x05
+#define ACT_PALETTE6		0x06
+#define ACT_PALETTE7		0x07
+#define ACT_PALETTE8		0x08
+#define ACT_PALETTE9		0x09
+#define ACT_PALETTE10		0x0A
+#define ACT_PALETTE11		0x0B
+#define ACT_PALETTE12		0x0C
+#define ACT_PALETTE13		0x0D
+#define ACT_PALETTE14		0x0E
+#define ACT_PALETTE15		0x0F
+#define ACT_ATTR_MODE_CNTL	0x10
+#define ACT_OVERSCAN_COLOR	0x11
+#define ACT_COLOR_PLANE_ENA	0x12
+#define ACT_HOR_PEL_PANNING	0x13
+#define ACT_COLOR_SELECT	0x14
+
+/*
+ * PLL
+ */
+#define PLL_IDX			0x83c8
+#define PLL_DATA		0x83c9
+
+/*
+ * Blitter operations
+ */
+#define	Z3BLTclear		0x00	/* 0 */
+#define Z3BLTand		0x80	/* src AND dst */
+#define Z3BLTandReverse		0x40	/* src AND NOT dst */
+#define Z3BLTcopy		0xc0	/* src */
+#define Z3BLTandInverted	0x20	/* NOT src AND dst */
+#define	Z3BLTnoop		0xa0	/* dst */
+#define Z3BLTxor		0x60	/* src XOR dst */
+#define Z3BLTor			0xe0	/* src OR dst */
+#define Z3BLTnor		0x10	/* NOT src AND NOT dst */
+#define Z3BLTequiv		0x90	/* NOT src XOR dst */
+#define Z3BLTinvert		0x50	/* NOT dst */
+#define Z3BLTorReverse		0xd0	/* src OR NOT dst */
+#define Z3BLTcopyInverted	0x30	/* NOT src */
+#define Z3BLTorInverted		0xb0	/* NOT src OR dst */
+#define Z3BLTnand		0x70	/* NOT src OR NOT dst */
+#define Z3BLTset		0xf0	/* 1 */
diff -u --recursive --new-file v2.1.35/linux/arch/m68k/amiga/zorro.c linux/arch/m68k/amiga/zorro.c
--- v2.1.35/linux/arch/m68k/amiga/zorro.c	Fri Dec 20 01:19:57 1996
+++ linux/arch/m68k/amiga/zorro.c	Thu Apr 17 13:20:41 1997
@@ -16,7 +16,7 @@
 #include <asm/setup.h>
 #include <asm/bitops.h>
 #include <asm/amigahw.h>
-#include <asm/zorro.h>
+#include <linux/zorro.h>
 
 
 #ifdef CONFIG_ZORRO
@@ -82,6 +82,10 @@
    PROD("Stormbringer", STORMBRINGER)
 END
 
+BEGIN_PROD(3_STATE)
+   PROD("Megamix 2000 RAM", MEGAMIX_2000)
+END
+
 BEGIN_PROD(COMMODORE2)
    PROD("A2088 XT Bridgeboard", A2088)
    PROD("A2286 AT Bridgeboard", A2286)
@@ -141,8 +145,12 @@
    PROD("StarDrive", STARDRIVE)
    PROD("8-Up (Rev A)", 8_UP_A)
    PROD("8-Up (Rev Z)", 8_UP_Z)
+   PROD("Delta Card RAM", DELTA_RAM)
+   PROD("8-Star RAM", 8_STAR_RAM)
+   PROD("8-Star", 8_STAR)
    PROD("VXL RAM", VXL_RAM)
    PROD("VXL-30 Turbo Board", VXL_30)
+   PROD("Delta Card", DELTA)
    PROD("MBX 1200", MBX_1200)
    PROD("Hardframe 2000", HARDFRAME_2000)
    PROD("MBX 1200", MBX_1200_2)
@@ -180,8 +188,8 @@
    PROD("SupraDrive 4x4 SCSI Controller", SUPRADRIVE_4x4)
    PROD("2000 DMA HD", SUPRA_2000)
    PROD("500 HD/RAM", SUPRA_500)
+   PROD("500XP/2000 RAM", SUPRA_500XP)
    PROD("500RX/2000 RAM", SUPRA_500RX)
-   PROD("500RX/2000 RAM", SUPRA_500RX_2)
    PROD("2400zi Modem", SUPRA_2400ZI)
    PROD("Wordsync SCSI Controller", WORDSYNC)
    PROD("Wordsync II SCSI Controller", WORDSYNC_II)
@@ -193,6 +201,10 @@
    PROD("12 Gauge SCSI Controller", 12GAUGE)
 END
 
+BEGIN_PROD(MTEC2)
+   PROD("AT500 RAM", AT500_2)
+END
+
 BEGIN_PROD(GVP3)
    PROD("Impact SCSI/Memory", IMPACT)
 END
@@ -203,7 +215,11 @@
 
 BEGIN_PROD(POWER_COMPUTING)
    PROD("DKB 3128 RAM", DKB_3128)
+   PROD("Rapid Fire SCSI Controller", RAPID_FIRE)
+   PROD("DKB 1202 RAM", DKB_1202)
    PROD("DKB Cobra / Viper II Turbo Board", VIPER_II_COBRA)
+   PROD("WildFire 060 Turbo Board", WILDFIRE_060)
+   PROD("WildFire 060 Turbo Board", WILDFIRE_060_2)
 END
 
 BEGIN_PROD(GVP)
@@ -257,6 +273,9 @@
    PROD("PP&S A500 68040 Turbo Board", PPS_A500_040)
 END
 
+BEGIN_PROD(XEBEC)
+END
+
 BEGIN_PROD(SPIRIT)
    PROD("HDA 506 Harddisk", HDA_506)
    PROD("OctaByte RAM", OCTABYTE_RAM)
@@ -268,6 +287,7 @@
 
 BEGIN_PROD(BSC3)
    PROD("ALF 2 SCSI Controller", ALF_2_SCSI)
+   PROD("ALF 2 SCSI Controller", ALF_2_SCSI_2)
    PROD("ALF 3 SCSI Controller", ALF_3_SCSI_2)
 END
 
@@ -291,9 +311,17 @@
 BEGIN_PROD(KUPKE2)
    PROD("Golem SCSI-II Controller", KUPKE_SCSI_II)
    PROD("Golem Box", GOLEM_BOX)
+   PROD("030/882 Turbo Board", KUPKE_TURBO)
    PROD("Golem SCSI/AT Controller", KUPKE_SCSI_AT)
 END
 
+BEGIN_PROD(GVP4)
+   PROD("A2000-RAM8/2", A2000_RAM8)
+END
+
+BEGIN_PROD(INTERWORKS_NET)
+END
+
 BEGIN_PROD(HARDITAL)
    PROD("TQM 68030+68882 Turbo Board", TQM)
 END
@@ -301,10 +329,14 @@
 BEGIN_PROD(BSC2)
    PROD("Oktagon 2008 SCSI Controller", OKTAGON_SCSI)
    PROD("Tandem AT-2008/508 IDE Controller", TANDEM)
+   PROD("Alpha RAM 1200", ALPHA_RAM_1200)
    PROD("Oktagon 2008 RAM", OKTAGON_RAM)
    PROD("Alfa Data MultiFace I", MULTIFACE_I)
    PROD("Alfa Data MultiFace II", MULTIFACE_II)
    PROD("Alfa Data MultiFace III", MULTIFACE_III)
+   PROD("Framebuffer", BSC_FRAEMBUFFER)
+   PROD("Graffiti Graphics Board (RAM)", GRAFFITI_RAM)
+   PROD("Graffiti Graphics Board (REG)", GRAFFITI_REG)
    PROD("ISDN MasterCard", ISDN_MASTERCARD)
    PROD("ISDN MasterCard II", ISDN_MASTERCARD_2)
 END
@@ -319,12 +351,15 @@
 END
 
 BEGIN_PROD(IVS)
-   PROD("GrandSlam RAM", GRANDSLAM)
+   PROD("GrandSlam PIC 2 RAM", GRANDSLAM_PIC_2)
+   PROD("GrandSlam PIC 1 RAM", GRANDSLAM_PIC_1)
    PROD("OverDrive HD", IVS_OVERDRIVE)
    PROD("Trumpcard Classic SCSI Controller", TRUMPCARD_CLASSIC)
    PROD("Trumpcard Pro SCSI Controller", TRUMPCARD_PRO)
    PROD("Meta-4 RAM", META_4)
+   PROD("Wavetools Sound Board", WAVETOOLS)
    PROD("Vector SCSI Controller", VECTOR)
+   PROD("Vector SCSI Controller", VECTOR_2)
 END
 
 BEGIN_PROD(VECTOR)
@@ -336,6 +371,7 @@
    PROD("Visiona Graphics Board (REG)", VISIONA_REG)
    PROD("Merlin Graphics Board (RAM)", MERLIN_RAM)
    PROD("Merlin Graphics Board (REG)", MERLIN_REG)
+   PROD("Merlin Graphics Board (REG)", MERLIN_REG_2)
 END
 
 BEGIN_PROD(HYDRA_SYSTEMS)
@@ -388,7 +424,11 @@
    PROD("Domino Graphics Board (REG)", DOMINO_REG)
    PROD("Picasso II Graphics Board (RAM)", PICASSO_II_RAM)
    PROD("Picasso II Graphics Board (REG)", PICASSO_II_REG)
-   PROD("Picasso II Graphics Board (REG)", PICASSO_II_REG_2)
+   PROD("Picasso II/II+ Graphics Board (Segmented Mode)", PICASSO_II_SEGM)
+   PROD("Picassio IV Graphics Board", PICASSO_IV)
+   PROD("Picassio IV Graphics Board", PICASSO_IV_2)
+   PROD("Picassio IV Graphics Board", PICASSO_IV_3)
+   PROD("Picassio IV Graphics Board", PICASSO_IV_4)
    PROD("Ariadne Ethernet Card", ARIADNE)
 END
 
@@ -402,8 +442,18 @@
    PROD("CD-RAM Memory", AMITRIX_CD_RAM)
 END
 
+BEGIN_PROD(ARMAX)
+   PROD("OmniBus Graphics Board", OMNIBUS)
+END
+
+BEGIN_PROD(NEWTEK)
+   PROD("VideoToaster", VIDEOTOASTER)
+END
+
 BEGIN_PROD(MTEC)
+   PROD("AT500 IDE Controller", AT500)
    PROD("68030 Turbo Board", MTEC_68030)
+   PROD("68020i Turbo Board", MTEC_68020I)
    PROD("A1200 T68030/42 RTC Turbo Board", MTEC_T1230)
    PROD("8MB RAM", MTEC_RAM)
 END
@@ -439,6 +489,11 @@
    PROD("RCA 120 RAM", RCA_120)
 END
 
+BEGIN_PROD(MEGA_MICRO)
+   PROD("SCRAM 500 SCSI Controller", SCRAM_500_SCSI)
+   PROD("SCRAM 500 RAM", SCRAM_500_RAM)
+END
+
 BEGIN_PROD(IMTRONICS2)
    PROD("Hurricane 2800 68030", HURRICANE_2800_3)
    PROD("Hurricane 2800 68030", HURRICANE_2800_4)
@@ -448,6 +503,15 @@
    PROD("Golem HD 3000", GOLEM_3000)
 END
 
+BEGIN_PROD(ITH)
+   PROD("ISDN-Master II", ISDN_MASTER_II)
+END
+
+BEGIN_PROD(VMC)
+   PROD("ISDN Blaster Z2", ISDN_BLASTER_Z2)
+   PROD("HyperCom 4", HYPERCOM_4)
+END
+
 BEGIN_PROD(INFORMATION)
    PROD("ISDN Engine I", ISDN_ENGINE_I)
 END
@@ -479,6 +543,8 @@
    PROD("Blizzard 2060 SCSI Controller", BLIZZARD_2060SCSI)
    PROD("CyberStorm Mk II", CYBERSTORM_II)
    PROD("CyberVision64 Graphics Board", CYBERVISION)
+   PROD("CyberVision64-3D Graphics Board Prototype)", CYBERVISION3D_PRT)
+   PROD("CyberVision64-3D Graphics Board", CYBERVISION3D)
 END
 
 BEGIN_PROD(DPS)
@@ -487,6 +553,7 @@
 
 BEGIN_PROD(APOLLO2)
    PROD("A620 68020 Accelerator", A620)
+   PROD("A620 68020 Accelerator", A620_2)
 END
 
 BEGIN_PROD(APOLLO)
@@ -494,6 +561,10 @@
    PROD("Turbo Board", APOLLO_TURBO)
 END
 
+BEGIN_PROD(PETSOFF)
+   PROD("Delfina DSP", DELFINA)
+END
+
 BEGIN_PROD(UWE_GERLACH)
    PROD("RAM/ROM", UG_RAM_ROM)
 END
@@ -507,6 +578,7 @@
    PROD("Toccata Sound Board", TOCCATA)
    PROD("Retina Z3 Graphics Board", RETINA_Z3)
    PROD("VLab Motion", VLAB_MOTION)
+   PROD("Altais Graphics Board", ALTAIS)
    PROD("Falcon '040 Turbo Board", FALCON_040)
 END
 
@@ -514,11 +586,12 @@
 END
 
 BEGIN_PROD(SKI)
+   PROD("MAST Fireball SCSI Controller", MAST_FIREBALL)
    PROD("SCSI / Dual Serial", SKI_SCSI_SERIAL)
 END
 
 BEGIN_PROD(CAMERON)
-   PROD("Scanner Interface", CAMERON_SCANNER)
+   PROD("Personal A4", PERSONAL_A4)
 END
 
 BEGIN_PROD(REIS_WARE)
@@ -530,6 +603,7 @@
    MANUF("Pacific Peripherals", PACIFIC)
    MANUF("Kupke", KUPKE)
    MANUF("Memphis", MEMPHIS)
+   MANUF("3-State", 3_STATE)
    MANUF("Commodore", COMMODORE2)
    MANUF("Commodore", COMMODORE)
    MANUF("Commodore", COMMODORE3)
@@ -546,7 +620,8 @@
    MANUF("University of Lowell", UNIV_OF_LOWELL)
    MANUF("Ameristar", AMERISTAR)
    MANUF("Supra", SUPRA)
-   MANUF("CSA", CSA)
+   MANUF("Computer Systems Ass.", CSA)
+   MANUF("M-Tech", MTEC2)
    MANUF("Great Valley Products", GVP3)
    MANUF("ByteBox", BYTEBOX)
    MANUF("Power Computing", POWER_COMPUTING)
@@ -554,6 +629,7 @@
    MANUF("Synergy", SYNERGY)
    MANUF("Xetec", XETEC)
    MANUF("Progressive Peripherals", PPI)
+   MANUF("Xebec", XEBEC)
    MANUF("Spirit", SPIRIT)
    MANUF("BSC", BSC)
    MANUF("BSC", BSC3)
@@ -562,6 +638,8 @@
    MANUF("Checkpoint Technologies", CHECKPOINT)
    MANUF("ICD", ICD)
    MANUF("Kupke", KUPKE2)
+   MANUF("Great Valley Products", GVP4)
+   MANUF("Interworks Network", INTERWORKS_NET)
    MANUF("Hardital Synthesis", HARDITAL)
    MANUF("BSC", BSC2)
    MANUF("Advanced Systems & Software", ADV_SYS_SOFT)
@@ -582,15 +660,20 @@
    MANUF("Village Tronic", VILLAGE_TRONIC)
    MANUF("Utilities Unlimited", UTILITIES_ULTD)
    MANUF("Amitrix", AMITRIX)
-   MANUF("MTEC", MTEC)
+   MANUF("ArMax", ARMAX)
+   MANUF("NewTek", NEWTEK)
+   MANUF("M-Tech", MTEC)
    MANUF("Great Valley Products", GVP2)
    MANUF("Helfrich", HELFRICH2)
    MANUF("MacroSystems", MACROSYSTEMS)
    MANUF("ElBox Computer", ELBOX)
    MANUF("Harms Professional", HARMS_PROF)
    MANUF("Micronik", MICRONIK)
+   MANUF("MegaMicro", MEGA_MICRO)
    MANUF("Imtronics", IMTRONICS2)
    MANUF("Kupke", KUPKE3)
+   MANUF("ITH", ITH)
+   MANUF("VMC", VMC)
    MANUF("Information", INFORMATION)
    MANUF("Vortex", VORTEX)
    MANUF("DataFlyer", DATAFLYER)
@@ -599,6 +682,7 @@
    MANUF("DPS", DPS)
    MANUF("Apollo", APOLLO2)
    MANUF("Apollo", APOLLO)
+   MANUF("Petsoff LP", PETSOFF)
    MANUF("Uwe Gerlach", UWE_GERLACH)
    MANUF("MacroSystems", MACROSYSTEMS2)
    MANUF("Combitec", COMBITEC)
@@ -758,7 +842,11 @@
                   identified = 1;
                   break;
                } else {
-                  epc = *(enum GVP_ident *)ZTWO_VADDR(addr+0x8000) &
+		       /*
+			* The epc must be read as a short from the
+			* hardware.
+			*/
+                  epc = *(unsigned short *)ZTWO_VADDR(addr+0x8000) &
                         GVP_PRODMASK;
                   for (k = 0; k < NUM_GVP_PROD; k++)
                      if (Ext_Prod_GVP[k].ID == epc) {
diff -u --recursive --new-file v2.1.35/linux/arch/m68k/atari/atafb.c linux/arch/m68k/atari/atafb.c
--- v2.1.35/linux/arch/m68k/atari/atafb.c	Fri Dec 20 01:19:57 1996
+++ linux/arch/m68k/atari/atafb.c	Thu Apr 17 13:20:41 1997
@@ -2905,6 +2905,12 @@
 		do_install_cmap(currcon);
 }
 
+static int
+atafb_setcmap(struct fb_cmap *cmap, int con)
+{
+	return(atari_fb_set_cmap(cmap, 1, con));
+}
+
 struct fb_info *
 atari_fb_init(long *mem_start)
 {
@@ -2999,6 +3005,7 @@
 	fb_info.switch_con=&atafb_switch;
 	fb_info.updatevar=&fb_update_var;
 	fb_info.blank=&atafb_blank;
+	fb_info.setcmap=&atafb_setcmap;
 	var=atari_fb_predefined+default_par-1;
 	do_fb_set_var(var,1);
 	strcat(fb_info.modename,fb_var_names[default_par-1][0]);
diff -u --recursive --new-file v2.1.35/linux/arch/m68k/atari/ataints.c linux/arch/m68k/atari/ataints.c
--- v2.1.35/linux/arch/m68k/atari/ataints.c	Fri Dec 20 01:19:58 1996
+++ linux/arch/m68k/atari/ataints.c	Thu Apr 17 13:20:41 1997
@@ -56,9 +56,7 @@
  * All interrupt source have an internal number (defined in
  * <asm/atariints.h>): Autovector interrupts are 1..7, then follow ST-MFP,
  * TT-MFP, SCC, and finally VME interrupts. Vector numbers for the latter can
- * be allocated by atari_register_vme_int(). Currently, all int source numbers
- * have the IRQ_MACHSPEC bit set, to keep the general int handling functions
- * in kernel/ints.c from them.
+ * be allocated by atari_register_vme_int().
  *
  * Each interrupt can be of three types:
  * 
@@ -180,7 +178,7 @@
 void atari_slow_irq_##n##_dummy (void) {				   \
 __asm__ (ALIGN_STR "\n"							   \
 SYMBOL_NAME_STR(atari_slow_irq_) #n "_handler:\t"			   \
-"	addql	#1,"SYMBOL_NAME_STR(intr_count)"\n"			   \
+"	addql	#1,"SYMBOL_NAME_STR(local_irq_count)"\n"		   \
 	SAVE_ALL "\n"							   \
 "	andb	#~(1<<(" #n "&7)),"	/* mask this interrupt */	   \
 	"("MFP_MK_BASE"+(((" #n "&8)^8)>>2)+((" #n "&16)<<3)):w\n"	   \
@@ -192,7 +190,7 @@
 "	lea	"SYMBOL_NAME_STR(irq_handler)"+("#n"+8)*8,%%a0\n"	   \
 "	pea 	%%sp@\n"		/* push addr of frame */	   \
 "	movel	%%a0@(4),%%sp@-\n"	/* push handler data */		   \
-"	pea 	(" #n "+0x10000008)\n"	/* push int number */		   \
+"	pea 	(" #n "+8)\n"		/* push int number */		   \
 "	movel	%%a0@,%%a0\n"						   \
 "	jbsr	%%a0@\n"		/* call the handler */		   \
 "	addql	#8,%%sp\n"						   \
@@ -283,7 +281,7 @@
 SYMBOL_NAME_STR(atari_fast_irq_handler) ":
 	orw 	#0x700,%%sr		/* disable all interrupts */
 "SYMBOL_NAME_STR(atari_prio_irq_handler) ":\t
-	addql	#1,"SYMBOL_NAME_STR(intr_count)"\n"
+	addql	#1,"SYMBOL_NAME_STR(local_irq_count)"\n"
 	SAVE_ALL "
 	/* get vector number from stack frame and convert to source */
 	bfextu	%%sp@(" FORMATVEC "){#4,#10},%%d0
@@ -296,7 +294,6 @@
 	lea	%%a0@(%%d0:l:8),%%a0
 	pea 	%%sp@			/* push frame address */
 	movel	%%a0@(4),%%sp@-		/* push handler data */
-	bset	#28,%%d0		/* set MACHSPEC bit */
 	movel	%%d0,%%sp@-		/* push int number */
 	movel	%%a0@,%%a0
 	jsr	%%a0@			/* and call the handler */
@@ -587,14 +584,12 @@
 		return 0;
 
 	free_vme_vec_bitmap |= 1 << i;
-	return (VME_SOURCE_BASE + i) | IRQ_MACHSPEC;
+	return (VME_SOURCE_BASE + i);
 }
 
 
 void atari_unregister_vme_int(unsigned long irq)
 {
-	irq &= ~IRQ_MACHSPEC;
-	
 	if(irq >= VME_SOURCE_BASE && irq < VME_SOURCE_BASE + VME_MAX_SOURCES) {
 		irq -= VME_SOURCE_BASE;
 		free_vme_vec_bitmap &= ~(1 << irq);
diff -u --recursive --new-file v2.1.35/linux/arch/m68k/atari/atakeyb.c linux/arch/m68k/atari/atakeyb.c
--- v2.1.35/linux/arch/m68k/atari/atakeyb.c	Wed Sep 25 00:47:38 1996
+++ linux/arch/m68k/atari/atakeyb.c	Thu Apr 17 13:20:41 1997
@@ -14,6 +14,7 @@
  */
 
 #include <linux/sched.h>
+#include <linux/kernel.h>
 #include <linux/interrupt.h>
 #include <linux/errno.h>
 #include <linux/keyboard.h>
@@ -40,6 +41,15 @@
 /* Hook for mouse driver */
 void (*atari_mouse_interrupt_hook) (char *);
 
+/* variables for IKBD self test: */
+
+/* state: 0: off; >0: in progress; >1: 0xf1 received */
+static volatile int ikbd_self_test;
+/* timestamp when last received a char */
+static volatile unsigned long self_test_last_rcv;
+/* bitmap of keys reported as broken */
+static unsigned long broken_keys[128/(sizeof(unsigned long)*8)] = { 0, };
+
 #define BREAK_MASK	(0x80)
 
 /*
@@ -331,12 +341,15 @@
     {
 	/* a very fast typist or a slow system, give a warning */
 	/* ...happens often if interrupts were disabled for too long */
-	printk( "Keyboard overrun\n" );
+	printk( KERN_DEBUG "Keyboard overrun\n" );
 	scancode = acia.key_data;
 	/* Turn off autorepeating in case a break code has been lost */
 	del_timer( &atakeyb_rep_timer );
 	rep_scancode = 0;
-	if (IS_SYNC_CODE(scancode)) {
+	if (ikbd_self_test)
+	    /* During self test, don't do resyncing, just process the code */
+	    goto interpret_scancode;
+	else if (IS_SYNC_CODE(scancode)) {
 	    /* This code seem already to be the start of a new packet or a
 	     * single scancode */
 	    kb_state.state = KEYBOARD;
@@ -386,10 +399,47 @@
 		kb_state.buf[0] = scancode;
 		break;
 
+	      case 0xF1:
+		/* during self-test, note that 0xf1 received */
+		if (ikbd_self_test) {
+		    ++ikbd_self_test;
+		    self_test_last_rcv = jiffies;
+		    break;
+		}
+		/* FALL THROUGH */
+		
 	      default:
 		break_flag = scancode & BREAK_MASK;
 		scancode &= ~BREAK_MASK;
 
+		if (ikbd_self_test) {
+		    /* Scancodes sent during the self-test stand for broken
+		     * keys (keys being down). The code *should* be a break
+		     * code, but nevertheless some AT keyboard interfaces send
+		     * make codes instead. Therefore, simply ignore
+		     * break_flag...
+		     * */
+		    int keyval = ataplain_map[scancode], keytyp;
+		    
+		    set_bit( scancode, broken_keys );
+		    self_test_last_rcv = jiffies;
+		    keyval = ataplain_map[scancode];
+		    keytyp = KTYP(keyval) - 0xf0;
+		    keyval = KVAL(keyval);
+		    
+		    printk( KERN_WARNING "Key with scancode %d ", scancode );
+		    if (keytyp == KT_LATIN || keytyp == KT_LETTER) {
+			if (keyval < ' ')
+			    printk( "('^%c') ", keyval + '@' );
+			else
+			    printk( "('%c') ", keyval );
+		    }
+		    printk( "is broken -- will be ignored.\n" );
+		    break;
+		}
+		else if (test_bit( scancode, broken_keys ))
+		    break;
+		
 		if (break_flag) {
 		    del_timer( &atakeyb_rep_timer );
 		    rep_scancode = 0;
@@ -815,7 +865,18 @@
     mfp.active_edge &= ~0x10;
     atari_turnon_irq(IRQ_MFP_ACIA);
 
+    ikbd_self_test = 1;
     ikbd_reset();
+    /* wait for a period of inactivity (here: 0.25s), then assume the IKBD's
+     * self-test is finished */
+    self_test_last_rcv = jiffies;
+    while( jiffies < self_test_last_rcv + HZ/4 )
+	barrier();
+    /* if not incremented: no 0xf1 received */
+    if (ikbd_self_test == 1)
+	printk( KERN_ERR "WARNING: keyboard self test failed!\n" );
+    ikbd_self_test = 0;
+    
     ikbd_mouse_disable();
     ikbd_joystick_disable();
 
diff -u --recursive --new-file v2.1.35/linux/arch/m68k/atari/atari_ksyms.c linux/arch/m68k/atari/atari_ksyms.c
--- v2.1.35/linux/arch/m68k/atari/atari_ksyms.c	Fri Jan  3 01:33:25 1997
+++ linux/arch/m68k/atari/atari_ksyms.c	Thu Apr 17 13:20:41 1997
@@ -1,3 +1,4 @@
+#include <linux/config.h>
 #include <linux/module.h>
 #include <asm/ptrace.h>
 #include <asm/traps.h>
@@ -8,11 +9,12 @@
 #include <asm/atari_stdma.h>
 
 extern void atari_microwire_cmd( int cmd );
-
+extern int atari_SCC_reset_done;
 
 EXPORT_SYMBOL(atari_mch_cookie);
 EXPORT_SYMBOL(atari_hw_present);
 EXPORT_SYMBOL(is_medusa);
+EXPORT_SYMBOL(is_hades);
 EXPORT_SYMBOL(atari_register_vme_int);
 EXPORT_SYMBOL(atari_unregister_vme_int);
 EXPORT_SYMBOL(stdma_lock);
@@ -23,7 +25,7 @@
 EXPORT_SYMBOL(atari_mouse_buttons);
 EXPORT_SYMBOL(atari_mouse_interrupt_hook);
 EXPORT_SYMBOL(atari_MIDI_interrupt_hook);
-EXPORT_SYMBOL(atari_mch_cookie);
+EXPORT_SYMBOL(atari_SCC_reset_done);
 EXPORT_SYMBOL(ikbd_write);
 EXPORT_SYMBOL(ikbd_mouse_y0_top);
 EXPORT_SYMBOL(ikbd_mouse_thresh);
diff -u --recursive --new-file v2.1.35/linux/arch/m68k/atari/config.c linux/arch/m68k/atari/config.c
--- v2.1.35/linux/arch/m68k/atari/config.c	Fri Dec 20 01:19:58 1996
+++ linux/arch/m68k/atari/config.c	Thu Apr 17 13:20:41 1997
@@ -45,9 +45,15 @@
 #include <asm/pgtable.h>
 #include <asm/machdep.h>
 
+#ifdef CONFIG_KGDB
+#include <asm/kgdb.h>
+#endif
+
 u_long atari_mch_cookie;
 struct atari_hw_present atari_hw_present;
 
+extern char m68k_debug_device[];
+
 static void atari_sched_init(void (*)(int, void *, struct pt_regs *));
 /* atari specific keyboard functions */
 extern int atari_keyb_init(void);
@@ -57,7 +63,7 @@
 extern void atari_init_IRQ (void);
 extern int atari_request_irq (unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
                               unsigned long flags, const char *devname, void *dev_id);
-extern int atari_free_irq (unsigned int irq, void *dev_id);
+extern void atari_free_irq (unsigned int irq, void *dev_id);
 extern void atari_enable_irq (unsigned int);
 extern void atari_disable_irq (unsigned int);
 extern int atari_get_irq_list (char *buf);
@@ -77,12 +83,17 @@
 extern int atari_floppy_init (void);
 extern void atari_floppy_setup(char *, int *);
 #endif
-static void atari_waitbut (void);
 extern struct consw fb_con;
 extern struct fb_info *atari_fb_init(long *);
-static void atari_debug_init (void);
+static void atari_debug_init(void);
 extern void atari_video_setup(char *, int *);
-extern void atari_syms_export(void);
+
+static struct console atari_console_driver;
+
+/* Can be set somewhere, if a SCC master reset has already be done and should
+ * not be repeated; used by kgdb */
+int atari_SCC_reset_done = 0;
+
 
 extern void (*kd_mksound)(unsigned int, unsigned int);
 
@@ -240,6 +251,8 @@
 {
     memset(&atari_hw_present, 0, sizeof(atari_hw_present));
 
+    atari_debug_init();
+
     mach_sched_init      = atari_sched_init;
     mach_keyb_init       = atari_keyb_init;
     mach_kbdrate         = atari_kbdrate;
@@ -247,25 +260,21 @@
     mach_init_IRQ        = atari_init_IRQ;
     mach_request_irq     = atari_request_irq;
     mach_free_irq        = atari_free_irq;
-    mach_enable_irq      = atari_enable_irq;
-    mach_disable_irq     = atari_disable_irq;
+    enable_irq           = atari_enable_irq;
+    disable_irq          = atari_disable_irq;
     mach_get_model	 = atari_get_model;
     mach_get_hardware_list = atari_get_hardware_list;
     mach_get_irq_list	 = atari_get_irq_list;
     mach_gettimeoffset   = atari_gettimeoffset;
-    mach_mksound         = atari_mksound;
     mach_reset           = atari_reset;
 #ifdef CONFIG_BLK_DEV_FD
     mach_floppy_init	 = atari_floppy_init;
     mach_floppy_setup	 = atari_floppy_setup;
 #endif
     conswitchp	         = &fb_con;
-    waitbut		 = atari_waitbut;
     mach_fb_init         = atari_fb_init;
     mach_max_dma_address = 0xffffff;
-    mach_debug_init	 = atari_debug_init;
     mach_video_setup	 = atari_video_setup;
-    mach_syms_export     = atari_syms_export;
     kd_mksound		 = atari_mksound;
 
     /* ++bjoern: 
@@ -273,7 +282,7 @@
      */
 
     printk( "Atari hardware found: " );
-    if (is_medusa) {
+    if (is_medusa || is_hades) {
         /* There's no Atari video hardware on the Medusa, but all the
          * addresses below generate a DTACK so no bus error occurs! */
     }
@@ -315,7 +324,7 @@
 	ATARIHW_SET(SCSI_DMA);
         printk( "TT_SCSI_DMA " );
     }
-    if (hwreg_present( &st_dma.dma_hi )) {
+    if (!is_hades && hwreg_present( &st_dma.dma_hi )) {
 	ATARIHW_SET(STND_DMA);
         printk( "STND_DMA " );
     }
@@ -337,21 +346,25 @@
 	ATARIHW_SET(YM_2149);
         printk( "YM2149 " );
     }
-    if (!is_medusa && hwreg_present( &tt_dmasnd.ctrl )) {
+    if (!is_medusa && !is_hades && hwreg_present( &tt_dmasnd.ctrl )) {
 	ATARIHW_SET(PCM_8BIT);
         printk( "PCM " );
     }
-    if (hwreg_present( (void *)(0xffff8940) )) {
+    if (!is_hades && hwreg_present( &codec.unused5 )) {
 	ATARIHW_SET(CODEC);
         printk( "CODEC " );
     }
+    if (hwreg_present( &dsp56k_host_interface.icr )) {
+	ATARIHW_SET(DSP56K);
+        printk( "DSP56K " );
+    }
     if (hwreg_present( &tt_scc_dma.dma_ctrl ) &&
 #if 0
 	/* This test sucks! Who knows some better? */
 	(tt_scc_dma.dma_ctrl = 0x01, (tt_scc_dma.dma_ctrl & 1) == 1) &&
 	(tt_scc_dma.dma_ctrl = 0x00, (tt_scc_dma.dma_ctrl & 1) == 0)
 #else
-	!is_medusa
+	!is_medusa && !is_hades
 #endif
 	) {
 	ATARIHW_SET(SCC_DMA);
@@ -365,7 +378,12 @@
 	ATARIHW_SET( ST_ESCC );
 	printk( "ST_ESCC " );
     }
-    if (hwreg_present( &tt_scu.sys_mask )) {
+    if (is_hades)
+    {
+        ATARIHW_SET( VME );
+        printk( "VME " );
+    }
+    else if (hwreg_present( &tt_scu.sys_mask )) {
 	ATARIHW_SET(SCU);
 	/* Assume a VME bus if there's a SCU */
 	ATARIHW_SET( VME );
@@ -375,7 +393,7 @@
 	ATARIHW_SET(ANALOG_JOY);
         printk( "ANALOG_JOY " );
     }
-    if (hwreg_present( blitter.halftone )) {
+    if (!is_hades && hwreg_present( blitter.halftone )) {
 	ATARIHW_SET(BLITTER);
         printk( "BLITTER " );
     }
@@ -384,7 +402,7 @@
         printk( "IDE " );
     }
 #if 1 /* This maybe wrong */
-    if (!is_medusa &&
+    if (!is_medusa && !is_hades &&
 	hwreg_present( &tt_microwire.data ) &&
 	hwreg_present( &tt_microwire.mask ) &&
 	(tt_microwire.mask = 0x7ff,
@@ -402,20 +420,20 @@
         mach_hwclk = atari_hwclk;
         mach_set_clock_mmss = atari_set_clock_mmss;
     }
-    if (hwreg_present( &mste_rtc.sec_ones)) {
+    if (!is_hades && hwreg_present( &mste_rtc.sec_ones)) {
 	ATARIHW_SET(MSTE_CLK);
         printk( "MSTE_CLK ");
         mach_gettod = atari_mste_gettod;
         mach_hwclk = atari_mste_hwclk;
         mach_set_clock_mmss = atari_mste_set_clock_mmss;
     }
-    if (!is_medusa &&
+    if (!is_medusa && !is_hades &&
 	hwreg_present( &dma_wd.fdc_speed ) &&
 	hwreg_write( &dma_wd.fdc_speed, 0 )) {
 	    ATARIHW_SET(FDCSPEED);
 	    printk( "FDC_SPEED ");
     }
-    if (!ATARIHW_PRESENT(ST_SCSI)) {
+    if (!is_hades && !ATARIHW_PRESENT(ST_SCSI)) {
 	ATARIHW_SET(ACSI);
         printk( "ACSI " );
     }
@@ -426,9 +444,11 @@
          * translation (the one that must not be turned off in
          * head.S...)
          */
-        __asm__ volatile ("moveq #0,%/d0;"
-                          ".long 0x4e7b0004;"	/* movec d0,itt0 */
-                          ".long 0x4e7b0006;"	/* movec d0,dtt0 */
+        __asm__ volatile ("moveq #0,%/d0\n\t"
+                          ".chip 68040\n\t"
+			  "movec %%d0,%%itt0\n\t"
+			  "movec %%d0,%%dtt0\n\t"
+			  ".chip 68k"
 						  : /* no outputs */
 						  : /* no inputs */
 						  : "d0");
@@ -452,13 +472,18 @@
         tt1_val = 0xfe008543;	/* Translate 0xfexxxxxx, enable, cache
                                  * inhibit, read and write, FDC mask = 3,
                                  * FDC val = 4 -> Supervisor only */
-        __asm__ __volatile__ ( "pmove	%0@,%/tt1" : : "a" (&tt1_val) );
+        __asm__ __volatile__ ( ".chip 68030\n\t"
+				"pmove	%0@,%/tt1\n\t"
+				".chip 68k"
+				: : "a" (&tt1_val) );
     }
     else {
         __asm__ __volatile__
             ( "movel %0,%/d0\n\t"
-              ".long 0x4e7b0005\n\t"	/* movec d0,itt1 */
-              ".long 0x4e7b0007"	/* movec d0,dtt1 */
+	      ".chip 68040\n\t"
+	      "movec %%d0,%%itt1\n\t"
+	      "movec %%d0,%%dtt1\n\t"
+	      ".chip 68k"
               :
               : "g" (0xfe00a040)	/* Translate 0xfexxxxxx, enable,
                                          * supervisor only, non-cacheable/
@@ -621,7 +646,7 @@
        we use the fact that in head.S we have set up a mapping
        0xFFxxxxxx -> 0x00xxxxxx, so that the first 16MB is accessible
        in the last 16MB of the address space. */
-    tos_version = is_medusa ? 0xfff : *(unsigned short *)0xFF000002;
+    tos_version = (is_medusa || is_hades) ? 0xfff : *(unsigned short *)0xFF000002;
     *yearp += (tos_version < 0x306) ? 70 : 68;
 }
 
@@ -696,7 +721,7 @@
 
     /* Tos version at Physical 2.  See above for explanation why we
        cannot use PTOV(2).  */
-    tos_version = is_medusa ? 0xfff : *(unsigned short *)0xff000002;
+    tos_version = (is_medusa || is_hades) ? 0xfff : *(unsigned short *)0xff000002;
 
     ctrl = RTC_READ(RTC_CONTROL); /* control registers are
                                    * independent from the UIP */
@@ -875,13 +900,6 @@
     return retval;
 }
 
-
-static void atari_waitbut (void)
-{
-    /* sorry, no-op */
-}
-
-
 static inline void ata_mfp_out (char c)
 {
     while (!(mfp.trn_stat & 0x80)) /* wait for tx buf empty */
@@ -889,12 +907,12 @@
     mfp.usart_dta = c;
 }
 
-void ata_mfp_print (const char *str)
+static void atari_mfp_console_write (const char *str, unsigned int count)
 {
-    for( ; *str; ++str ) {
+    while (count--) {
 	if (*str == '\n')
 	    ata_mfp_out( '\r' );
-	ata_mfp_out( *str );
+	ata_mfp_out( *str++ );
     }
 }
 
@@ -907,12 +925,12 @@
     scc.cha_b_data = c;
 }
 
-void ata_scc_print (const char *str)
+static void atari_scc_console_write (const char *str, unsigned int count)
 {
-    for( ; *str; ++str ) {
+    while (count--) {
 	if (*str == '\n')
 	    ata_scc_out( '\r' );
-	ata_scc_out( *str );
+	ata_scc_out( *str++ );
     }
 }
 
@@ -937,20 +955,20 @@
     return( 1 );
 }
 
-void ata_par_print (const char *str)
+static void atari_par_console_write (const char *str, unsigned int count)
 {
     static int printer_present = 1;
 
     if (!printer_present)
 	return;
 
-    for( ; *str; ++str ) {
+    while (count--) {
 	if (*str == '\n')
 	    if (!ata_par_out( '\r' )) {
 		printer_present = 0;
 		return;
 	    }
-	if (!ata_par_out( *str )) {
+	if (!ata_par_out( *str++ )) {
 	    printer_present = 0;
 	    return;
 	}
@@ -958,11 +976,14 @@
 }
 
 
-static void atari_debug_init( void )
+static void atari_debug_init(void)
 {
-    extern void (*debug_print_proc)(const char *);
-    extern char m68k_debug_device[];
-    
+#ifdef CONFIG_KGDB
+	/* if the m68k_debug_device is used by the GDB stub, do nothing here */
+	if (kgdb_initialized)
+		return(NULL);
+#endif
+
     if (!strcmp( m68k_debug_device, "ser" )) {
 	/* defaults to ser2 for a Falcon and ser1 otherwise */
 	strcpy( m68k_debug_device, 
@@ -979,7 +1000,7 @@
 	mfp.tim_dt_d   = 2;     /* 9600 bps */
 	mfp.tim_ct_cd |= 0x01;  /* start timer D, 1:4 */
 	mfp.trn_stat  |= 0x01;  /* enable TX */
-	debug_print_proc = ata_mfp_print;
+	atari_console_driver.write = atari_mfp_console_write;
     }
     else if (!strcmp( m68k_debug_device, "ser2" )) {
 	/* SCC Modem2 serial port */
@@ -1005,7 +1026,7 @@
 	    scc.cha_b_ctrl = *p++;
 	    MFPDELAY();
 	}
-	debug_print_proc = ata_scc_print;
+	atari_console_driver.write = atari_scc_console_write;
     }
     else if (!strcmp( m68k_debug_device, "par" )) {
 	/* parallel printer */
@@ -1016,29 +1037,10 @@
 	sound_ym.wd_data = 0;          /* no char */
 	sound_ym.rd_data_reg_sel = 14; /* select port A */
 	sound_ym.wd_data = sound_ym.rd_data_reg_sel | 0x20; /* strobe H */
-	debug_print_proc = ata_par_print;
-    }
-    else
-	debug_print_proc = NULL;
-}
-
-
-void ata_serial_print (const char *str)
-{
-  int c;
-
-  while (c = *str++, c != 0)
-    {
-      if (c == '\n')
-	{
-	  while (!(mfp.trn_stat & (1 << 7)))
-	    barrier ();
-	  mfp.usart_dta = '\r';
-	}
-      while (!(mfp.trn_stat & (1 << 7)))
-	barrier ();
-      mfp.usart_dta = c;
+	atari_console_driver.write = atari_par_console_write;
     }
+    if (atari_console_driver.write)
+	register_console(&atari_console_driver);
 }
 
 /* ++roman:
@@ -1079,7 +1081,8 @@
 
     /* On the Medusa, phys. 0x4 may contain garbage because it's no
        ROM.  See above for explanation why we cannot use PTOV(4). */
-    reset_addr = is_medusa ? 0xe00030 : *(unsigned long *) 0xff000004;
+    reset_addr = is_hades ? 0x7fe00030 :
+                 (is_medusa ? 0xe00030 : *(unsigned long *) 0xff000004);
 
     acia.key_ctrl = ACIA_RESET;             /* reset ACIA for switch off OverScan, if it's active */
 
@@ -1159,6 +1162,8 @@
 	    if (is_medusa)
 		/* Medusa has TT _MCH cookie */
 		strcat (model, "Medusa");
+	    else if (is_hades)
+		strcat(model, "Hades");
 	    else
 		strcat (model, "TT");
 	    break;
@@ -1215,6 +1220,7 @@
     ATARIHW_ANNOUNCE(SCU, "System Control Unit");
     ATARIHW_ANNOUNCE(BLITTER, "Blitter");
     ATARIHW_ANNOUNCE(VME, "VME Bus");
+    ATARIHW_ANNOUNCE(DSP56K, "DSP56001 processor");
 
     return(len);
 }
diff -u --recursive --new-file v2.1.35/linux/arch/m68k/atari/joystick.c linux/arch/m68k/atari/joystick.c
--- v2.1.35/linux/arch/m68k/atari/joystick.c	Fri Apr  4 08:52:17 1997
+++ linux/arch/m68k/atari/joystick.c	Thu Apr 17 13:20:41 1997
@@ -10,6 +10,7 @@
 #include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/major.h>
+#include <linux/poll.h>
 
 #include <asm/atarikb.h>
 #include <asm/atari_joystick.h>
@@ -90,30 +91,28 @@
 			  char *buffer, unsigned long count)
 {
     int minor = DEVICE_NR(inode->i_rdev);
-    int i;
 
     if (count < 2)
 	return -EINVAL;
     if (!joystick[minor].ready)
 	return -EAGAIN;
-    put_user(joystick[minor].fire, buffer++);
-    put_user(joystick[minor].dir, buffer++);
-    for (i = 0; i < count; i++)
-	put_user(0, buffer++);
     joystick[minor].ready = 0;
-
-    return i;
+    if (put_user(joystick[minor].fire, buffer++) ||
+	put_user(joystick[minor].dir, buffer++))
+	return -EFAULT;
+    if (count > 2)
+	if (clear_user(buffer, count - 2))
+	    return -EFAULT;
+    return count;
 }
 
-static int joystick_select(struct inode *inode, struct file *file, int sel_type, select_table *wait)
+static unsigned int joystick_poll(struct file *file, poll_table *wait)
 {
-    int minor = DEVICE_NR(inode->i_rdev);
+    int minor = DEVICE_NR(file->f_inode->i_rdev);
 
-    if (sel_type != SEL_IN)
-	return 0;
+    poll_wait(&joystick[minor].wait, wait);
     if (joystick[minor].ready)
-	return 1;
-    select_wait(&joystick[minor].wait, wait);
+	return POLLIN | POLLRDNORM;
     return 0;
 }
 
@@ -122,7 +121,7 @@
 	read_joystick,
 	write_joystick,
 	NULL,		/* joystick_readdir */
-	joystick_select,
+	joystick_poll,
 	NULL,		/* joystick_ioctl */
 	NULL,		/* joystick_mmap */
 	open_joystick,
@@ -135,7 +134,7 @@
     joystick[0].ready = joystick[1].ready = 0;
     joystick[0].wait = joystick[1].wait = NULL;
 
-    if (register_chrdev(MAJOR_NR, "joystick", &atari_joystick_fops))
+    if (register_chrdev(MAJOR_NR, "Joystick", &atari_joystick_fops))
 	printk("unable to get major %d for joystick devices\n", MAJOR_NR);
 
     return 0;
diff -u --recursive --new-file v2.1.35/linux/arch/m68k/boot/Makefile linux/arch/m68k/boot/Makefile
--- v2.1.35/linux/arch/m68k/boot/Makefile	Wed Sep 25 00:47:38 1996
+++ linux/arch/m68k/boot/Makefile	Thu Apr 17 13:20:41 1997
@@ -8,14 +8,16 @@
 ifdef CONFIG_AMIGA
 AMIGA_BOOTSTRAP = amiga_bootstrap
 AMIGA_BOOTOBJS := amiga/bootstrap.o amiga/linuxboot.o
-AMIGA_HOSTCC = m68k-cbm-amigados-gcc -I$(TOPDIR)/include
+AMIGA_HOSTCC = m68k-cbm-amigados-gcc
+AMIGA_HOSTINC = -I$(TOPDIR)/include
 AMIGA_HOSTFLAGS=-m68030 -O2 -Wall -Dlinux
 endif
 
 ifdef CONFIG_ATARI
 ATARI_BOOTSTRAP = atari_bootstrap
 ATARI_BOOTOBJS := atari/bootstrap.o
-ATARI_HOSTCC = m68k-mint-gcc -I$(TOPDIR)/include
+ATARI_HOSTCC = m68k-mint-gcc
+ATARI_HOSTINC = -I$(TOPDIR)/include
 ATARI_HOSTFLAGS = -m68030 -m68881 -Dlinux -O2 -Wall
 
 # BOOTP/TFTP support in bootstrap?
@@ -36,27 +38,28 @@
 
 ifdef CONFIG_ATARI
 atari_bootstrap: $(ATARI_BOOTOBJS)
-	$(ATARI_HOSTCC) $(ATARI_HOSTFLAGS) -o $@ $(ATARI_BOOTOBJS)
+	$(ATARI_HOSTCC) $(ATARI_HOSTINC) $(ATARI_HOSTFLAGS) -o $@ $(ATARI_BOOTOBJS)
 	rm -f ../../../bootstrap
 	ln $@ ../../../bootstrap
 endif
 
 ifdef CONFIG_AMIGA
 amiga_bootstrap: $(AMIGA_BOOTOBJS)
-	$(AMIGA_HOSTCC) $(AMIGA_HOSTFLAGS) -o $@ -s -noixemul $(AMIGA_BOOTOBJS)
+	$(AMIGA_HOSTCC) $(AMIGA_HOSTINC) $(AMIGA_HOSTFLAGS) -o $@ -s -noixemul $(AMIGA_BOOTOBJS)
 	rm -f ../../../bootstrap
 	ln $@ ../../../bootstrap
 endif
 
 $(AMIGA_BOOTOBJS): %.o: %.c
-	$(AMIGA_HOSTCC) $(AMIGA_HOSTFLAGS) -c $< -o $@
+	$(AMIGA_HOSTCC) $(AMIGA_HOSTINC) $(AMIGA_HOSTFLAGS) -c $< -o $@
 
 $(ATARI_BOOTOBJS): %.o: %.c
-	$(ATARI_HOSTCC) $(ATARI_HOSTFLAGS) -c $< -o $@
+	$(ATARI_HOSTCC) $(ATARI_HOSTINC) $(ATARI_HOSTFLAGS) -c $< -o $@
 
 bootstrap: $(AMIGA_BOOTSTRAP) $(ATARI_BOOTSTRAP)
 
 clean:
-	rm -f *.o amiga/*.o atari/*.o amiga_bootstrap atari_bootstrap
+	rm -f *.o amiga/*.o atari/*.o amiga_bootstrap atari_bootstrap \
+          ../../../bootstrap
 
 dep:
diff -u --recursive --new-file v2.1.35/linux/arch/m68k/boot/amiga/bootstrap.c linux/arch/m68k/boot/amiga/bootstrap.c
--- v2.1.35/linux/arch/m68k/boot/amiga/bootstrap.c	Fri Dec 20 01:19:58 1996
+++ linux/arch/m68k/boot/amiga/bootstrap.c	Thu Apr 17 13:20:41 1997
@@ -51,9 +51,8 @@
 
 
 /* Library Bases */
+long __oslibversion = 36;
 extern const struct ExecBase *SysBase;
-const struct ExpansionBase *ExpansionBase;
-const struct GfxBase *GfxBase;
 
 static const char *memfile_name = NULL;
 
@@ -80,24 +79,25 @@
 static void Close(int fd);
 static int FileSize(const char *path);
 static void Sleep(u_long micros);
-static int ModifyBootinfo(struct amiga_bootinfo *bi);
 
 
 static void Usage(void)
 {
     fprintf(stderr,
-	    "Linux/m68k Amiga Bootstrap version " AMIBOOT_VERSION "\n\n"
-	    "Usage: %s [options] [kernel command line]\n\n"
-	    "Valid options are:\n"
-	    "    -h, --help           Display this usage information\n"
-	    "    -k, --kernel file    Use kernel image `file' (default is `vmlinux')\n"
-	    "    -r, --ramdisk file   Use ramdisk image `file'\n"
-	    "    -d, --debug          Enable debug mode\n"
-	    "    -b, --baud speed     Set the serial port speed (default is 9600)\n"
-	    "    -m, --memfile file   Use memory file `file'\n"
-	    "    -v, --keep-video     Don't reset the video mode\n"
-	    "    -t, --model id       Set the Amiga model to `id'\n\n",
-	    ProgramName);
+	"Linux/m68k Amiga Bootstrap version " AMIBOOT_VERSION "\n\n"
+	"Usage: %s [options] [kernel command line]\n\n"
+	"Basic options:\n"
+	"    -h, --help           Display this usage information\n"
+	"    -k, --kernel file    Use kernel image `file' (default is `vmlinux')\n"
+	"    -r, --ramdisk file   Use ramdisk image `file'\n"
+	"Advanced options:\n"
+	"    -d, --debug          Enable debug mode\n"
+	"    -b, --baud speed     Set the serial port speed (default is 9600)\n"
+	"    -m, --memfile file   Use memory file `file'\n"
+	"    -v, --keep-video     Don't reset the video mode\n"
+	"    -t, --model id       Set the Amiga model to `id'\n"
+	"    -p, --processor cfm  Set the processor type to `cfm\n\n",
+	ProgramName);
     exit(EXIT_FAILURE);
 }
 
@@ -105,7 +105,7 @@
 int main(int argc, char *argv[])
 {
     int i;
-    int debugflag = 0, keep_video = 0;
+    int processor = 0, debugflag = 0, keep_video = 0;
     u_int baud = 0;
     const char *kernel_name = NULL;
     const char *ramdisk_name = NULL;
@@ -117,17 +117,17 @@
 	if (!strcmp(argv[0], "-h") || !strcmp(argv[0], "--help"))
 	    Usage();
 	else if (!strcmp(argv[0], "-k") || !strcmp(argv[0], "--kernel"))
-            if (--argc && !kernel_name) {
-                kernel_name = argv[1];
-                argv++;
-            } else
-                Usage();
+	    if (--argc && !kernel_name) {
+		kernel_name = argv[1];
+		argv++;
+	    } else
+		Usage();
 	else if (!strcmp(argv[0], "-r") || !strcmp(argv[0], "--ramdisk"))
-            if (--argc && !ramdisk_name) {
-                ramdisk_name = argv[1];
-                argv++;
-            } else
-                Usage();
+	    if (--argc && !ramdisk_name) {
+		ramdisk_name = argv[1];
+		argv++;
+	    } else
+		Usage();
 	else if (!strcmp(argv[0], "-d") || !strcmp(argv[0], "--debug"))
 	    debugflag = 1;
 	else if (!strcmp(argv[0], "-b") || !strcmp(argv[0], "--baud"))
@@ -137,19 +137,25 @@
 	    } else
 		Usage();
 	else if (!strcmp(argv[0], "-m") || !strcmp(argv[0], "--memfile"))
-            if (--argc && !memfile_name) {
-                memfile_name = argv[1];
-                argv++;
-            } else
-                Usage();
+	    if (--argc && !memfile_name) {
+		memfile_name = argv[1];
+		argv++;
+	    } else
+		Usage();
 	else if (!strcmp(argv[0], "-v") || !strcmp(argv[0], "--keep-video"))
 	    keep_video = 1;
 	else if (!strcmp(argv[0], "-t") || !strcmp(argv[0], "--model"))
-            if (--argc && !model) {
-                model = atoi(argv[1]);
-                argv++;
-            } else
-                Usage();
+	    if (--argc && !model) {
+		model = atoi(argv[1]);
+		argv++;
+	    } else
+		Usage();
+	else if (!strcmp(argv[0], "-p") || !strcmp(argv[0], "--processor"))
+	    if (--argc && !processor) {
+		processor = atoi(argv[1]);
+		argv++;
+	    } else
+		Usage();
 	else
 	    break;
     }
@@ -158,22 +164,6 @@
 
     SysBase = *(struct ExecBase **)4;
 
-    /* open Expansion Library */
-    ExpansionBase = (struct ExpansionBase *)OpenLibrary("expansion.library",
-							36);
-    if (!ExpansionBase) {
-	fputs("Unable to open expansion.library V36 or greater!  Aborting...\n",
-	      stderr);
-	exit(EXIT_FAILURE);
-   }
-
-    /* open Graphics Library */
-    GfxBase = (struct GfxBase *)OpenLibrary ("graphics.library", 0);
-    if (!GfxBase) {
-	fputs("Unable to open graphics.library!  Aborting...\n", stderr);
-	exit(EXIT_FAILURE);
-    }
-
     /*
      *	Join command line options
      */
@@ -187,9 +177,52 @@
 	}
     }
 
+    memset(&args.bi, 0, sizeof(args.bi));
+    if (processor) {
+	int cpu = processor/100%10;
+	int fpu = processor/10%10;
+	int mmu = processor%10;
+	if (cpu)
+	    args.bi.cputype = 1<<(cpu-1);
+	if (fpu)
+	    args.bi.fputype = 1<<(fpu-1);
+	if (mmu)
+	    args.bi.mmutype = 1<<(mmu-1);
+    }
+    /*
+     *	If we have a memory file, read the memory information from it
+     */
+    if (memfile_name) {
+	FILE *fp;
+	int i;
+
+	if ((fp = fopen(memfile_name, "r")) == NULL) {
+	    perror("open memory file");
+	    fprintf(stderr, "Cannot open memory file %s\n", memfile_name);
+	    return(FALSE);
+	}
+
+	if (fscanf(fp, "%lu", &args.bi.chip_size) != 1) {
+	    fprintf(stderr, "memory file does not contain chip memory size\n");
+	    fclose(fp);
+	    return(FALSE);
+	}
+
+	for (i = 0; i < NUM_MEMINFO; i++)
+	    if (fscanf(fp, "%lx %lu", &args.bi.memory[i].addr,
+		       &args.bi.memory[i].size) != 2)
+		break;
+
+	fclose(fp);
+	args.bi.num_memory = i;
+    }
+    strncpy(args.bi.command_line, commandline, CL_SIZE);
+    args.bi.command_line[CL_SIZE-1] = '\0';
+    if (model != AMI_UNKNOWN)
+	args.bi.model = model;
+
     args.kernelname = kernel_name;
     args.ramdiskname = ramdisk_name;
-    args.commandline = commandline;
     args.debugflag = debugflag;
     args.keep_video = keep_video;
     args.reset_boards = 1;
@@ -204,14 +237,10 @@
     args.close = Close;
     args.filesize = FileSize;
     args.sleep = Sleep;
-    args.modify_bootinfo = ModifyBootinfo;
 
     /* Do The Right Stuff */
     linuxboot(&args);
 
-    CloseLibrary((struct Library *)GfxBase);
-    CloseLibrary((struct Library *)ExpansionBase);
-
     /* if we ever get here, something went wrong */
     exit(EXIT_FAILURE);
 }
@@ -224,6 +253,7 @@
 static void Puts(const char *str)
 {
     fputs(str, stderr);
+    fflush(stderr);
 }
 
 static long GetChar(void)
@@ -234,6 +264,7 @@
 static void PutChar(char c)
 {
     fputc(c, stderr);
+    fflush(stderr);
 }
 
 static void Printf(const char *fmt, ...)
@@ -243,6 +274,7 @@
     va_start(args, fmt);
     vfprintf(stderr, fmt, args);
     va_end(args);
+    fflush(stderr);
 }
 
 static int Open(const char *path)
@@ -271,8 +303,8 @@
     int fd, size = -1;
 
     if ((fd = open(path, O_RDONLY)) != -1) {
-        size = lseek(fd, 0, SEEK_END);
-        close(fd);
+	size = lseek(fd, 0, SEEK_END);
+	close(fd);
     }
     return(size);
 }
@@ -298,47 +330,4 @@
 	}
 	DeleteMsgPort(TimerPort);
     }
-}
-
-
-static int ModifyBootinfo(struct amiga_bootinfo *bi)
-{
-   /*
-    * if we have a memory file, read the memory information from it
-    */
-   if (memfile_name) {
-      FILE *fp;
-      int i;
-
-      if ((fp = fopen(memfile_name, "r")) == NULL) {
-         perror("open memory file");
-         fprintf(stderr, "Cannot open memory file %s\n", memfile_name);
-         return(FALSE);
-      }
-
-      if (fscanf(fp, "%lu", &bi->chip_size) != 1) {
-         fprintf(stderr, "memory file does not contain chip memory size\n");
-         fclose(fp);
-         return(FALSE);
-      }
-                
-      for (i = 0; i < NUM_MEMINFO; i++) {
-         if (fscanf(fp, "%lx %lu", &bi->memory[i].addr, &bi->memory[i].size)
-	     != 2)
-            break;
-      }
-
-      fclose(fp);
-
-      if (i != bi->num_memory && i > 0)
-         bi->num_memory = i;
-   }
-
-   /*
-    * change the Amiga model, if necessary
-    */
-   if (model != AMI_UNKNOWN)
-      bi->model = model;
-
-   return(TRUE);
 }
diff -u --recursive --new-file v2.1.35/linux/arch/m68k/boot/amiga/bootstrap.h linux/arch/m68k/boot/amiga/bootstrap.h
--- v2.1.35/linux/arch/m68k/boot/amiga/bootstrap.h	Fri Dec 20 01:19:58 1996
+++ linux/arch/m68k/boot/amiga/bootstrap.h	Thu Apr 17 13:20:41 1997
@@ -59,30 +59,6 @@
 struct IORequest;
 
 
-static __inline void CloseLibrary(struct Library *library)
-{
-    register const struct ExecBase *a6 __asm("a6") = SysBase;
-    register struct Library *a1 __asm("a1") = library;
-    __asm __volatile ("jsr a6@(-0x19e)"
-		      : /* no output */
-		      : "r" (a6), "r" (a1)
-		      : "a0","a1","d0","d1", "memory");
-}
-
-static __inline struct Library *OpenLibrary(char *libName,
-					    unsigned long version)
-{
-    register struct Library * _res  __asm("d0");
-    register const struct ExecBase *a6 __asm("a6") = SysBase;
-    register u_char *a1 __asm("a1") = libName;
-    register unsigned long d0 __asm("d0") = version;
-    __asm __volatile ("jsr a6@(-0x228)"
-		      : "=r" (_res)
-		      : "r" (a6), "r" (a1), "r" (d0)
-		      : "a0","a1","d0","d1", "memory");
-    return _res;
-}
-
 static __inline char OpenDevice(u_char *devName, u_long unit,
 				struct IORequest *ioRequest, u_long flags)
 {
diff -u --recursive --new-file v2.1.35/linux/arch/m68k/boot/amiga/linuxboot.c linux/arch/m68k/boot/amiga/linuxboot.c
--- v2.1.35/linux/arch/m68k/boot/amiga/linuxboot.c	Fri Dec 20 01:19:58 1996
+++ linux/arch/m68k/boot/amiga/linuxboot.c	Thu Apr 17 13:20:42 1997
@@ -20,6 +20,24 @@
  *  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.
+ *
+ *  History:
+ *	03 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)
+ *      27 Nov 1996 Compatibility with bootinfo interface version 1.0 (Geert)
+ *       9 Sep 1996 Rewritten option parsing
+ *		    New parameter passing to linuxboot() (linuxboot_args)
+ *		    (Geert)
+ *	18 Aug 1996 Updated for the new boot information structure (Geert)
+ *	10 Jan 1996 The real Linux/m68k boot code moved to linuxboot.[ch]
+ *		    (Geert)
+ *	11 Jul 1995 Support for ELF kernel (untested!) (Andreas)
+ *	 7 Mar 1995 Memory block sizes are rounded to a multiple of 256K
+ *		    instead of 1M (Geert)
+ *	31 May 1994 Memory thrash problem solved (Geert)
+ *	11 May 1994 A3640 MapROM check (Geert)
  */
 
 
@@ -29,6 +47,8 @@
 
 
 #define BOOTINFO_COMPAT_1_0	/* bootinfo interface version 1.0 compatible */
+/* support compressed kernels? */
+#define ZKERNEL
 
 #include <stddef.h>
 #include <string.h>
@@ -60,7 +80,7 @@
 static const struct linuxboot_args *linuxboot_args;
 
 /* Bootinfo */
-static struct amiga_bootinfo bi;
+struct amiga_bootinfo bi;
 
 #ifdef BOOTINFO_COMPAT_1_0
 static struct compat_bootinfo compat_bootinfo;
@@ -75,7 +95,6 @@
 
 #define kernelname	linuxboot_args->kernelname
 #define ramdiskname	linuxboot_args->ramdiskname
-#define commandline	linuxboot_args->commandline
 #define debugflag	linuxboot_args->debugflag
 #define keep_video	linuxboot_args->keep_video
 #define reset_boards	linuxboot_args->reset_boards
@@ -91,8 +110,6 @@
 #define Close		linuxboot_args->close
 #define FileSize	linuxboot_args->filesize
 #define Sleep		linuxboot_args->sleep
-#define ModifyBootinfo	linuxboot_args->modify_bootinfo
-
 
     /*
      *  Function Prototypes
@@ -115,6 +132,16 @@
 			 u_long kernel_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);
+static int KSeek(int fd, int offset);
+static int KClose(int fd);
+#else
+#define KRead		Read
+#define KSeek		Seek
+#define KClose		Close
+#endif
 
 
     /*
@@ -174,7 +201,7 @@
 
 u_long linuxboot(const struct linuxboot_args *args)
 {
-    int kfd = -1, rfd = -1, elf_kernel = 0;
+    int kfd = -1, rfd = -1, elf_kernel = 0, do_fast, do_chip;
     int i, j;
     const struct MemHeader *mnp;
     struct ConfigDev *cdp = NULL;
@@ -196,38 +223,42 @@
     Puts("\nLinux/m68k Amiga Bootstrap version " AMIBOOT_VERSION "\n");
     Puts("Copyright 1993,1994 by Hamish Macdonald and Greg Harp\n\n");
 
-    memset(&bi, 0, sizeof(bi));
+    /* Note: Initial values in bi override detected values */
+    bi = args->bi;
 
     /* machine is Amiga */
     bi.machtype = MACH_AMIGA;
 
     /* determine chipset */
-    bi.chipset = get_chipset();
+    if (!bi.chipset)
+	bi.chipset = get_chipset();
 
     /* determine CPU, FPU and MMU type */
-    get_processor(&bi.cputype, &bi.fputype, &bi.mmutype);
+    if (!bi.cputype)
+	get_processor(&bi.cputype, &bi.fputype, &bi.mmutype);
 
     /* determine Amiga model */
-    bi.model = get_model(bi.chipset);
+    if (!bi.model)
+	bi.model = get_model(bi.chipset);
     model_mask = (bi.model != AMI_UNKNOWN) ? 1<<bi.model : 0;
 
     /* Memory & AutoConfig based on 'unix_boot.c' by C= */
 
     /* find all of the autoconfig boards in the system */
-    bi.num_autocon = 0;
-    for (i = 0; (cdp = (struct ConfigDev *)FindConfigDev(cdp, -1, -1)); i++) {
-	if (bi.num_autocon < ZORRO_NUM_AUTO) {
-	    /* copy the contents of each structure into our boot info */
-	    memcpy(&bi.autocon[bi.num_autocon], cdp, sizeof(struct ConfigDev));
-	    /* count this device */
-	    bi.num_autocon++;
-	} else
-	    Printf("Warning: too many AutoConfig devices. Ignoring device at "
-		   "0x%08lx\n", cdp->cd_BoardAddr);
-    }
+    if (!bi.num_autocon)
+	for (i = 0; (cdp = (struct ConfigDev *)FindConfigDev(cdp, -1, -1)); i++)
+	    if (bi.num_autocon < ZORRO_NUM_AUTO)
+		/* copy the contents of each structure into our boot info and
+		   count this device */
+		memcpy(&bi.autocon[bi.num_autocon++], cdp,
+		       sizeof(struct ConfigDev));
+	    else
+		Printf("Warning: too many AutoConfig devices. Ignoring device at "
+		       "0x%08lx\n", cdp->cd_BoardAddr);
 
+    do_fast = bi.num_memory ? 0 : 1;
+    do_chip = bi.chip_size ? 0 : 1;
     /* find out the memory in the system */
-    bi.num_memory = 0;
     for (mnp = (struct MemHeader *)SysBase->MemList.lh_Head;
 	 mnp->mh_Node.ln_Succ;
 	 mnp = (struct MemHeader *)mnp->mh_Node.ln_Succ) {
@@ -266,7 +297,7 @@
 	mh.mh_Lower = (void *)((u_long)mh.mh_Lower & 0xfffff000);
 
 	/* if fast memory */
-	if (mh.mh_Attributes & MEMF_FAST) {
+	if (do_fast && mh.mh_Attributes & MEMF_FAST) {
 	    /* set the size value to the size of this block and mask off to a
 	       256K increment */
 	    u_long size = ((u_long)mh.mh_Upper-(u_long)mh.mh_Lower)&0xfffc0000;
@@ -279,30 +310,26 @@
 		    bi.num_memory++;
 		} else
 		    Printf("Warning: too many memory blocks. Ignoring block "
-			   "of %ldK at 0x%08x\n", size>>10,
+		    	   "of %ldK at 0x%08x\n", size>>10,
 			   (u_long)mh.mh_Lower);
-	} else if (mh.mh_Attributes & MEMF_CHIP)
+	} else if (do_chip && mh.mh_Attributes & MEMF_CHIP)
 	    /* if CHIP memory, record the size */
 	    bi.chip_size = (u_long)mh.mh_Upper;
     }
 
     /* get info from ExecBase */
-    bi.vblank = SysBase->VBlankFrequency;
-    bi.psfreq = SysBase->PowerSupplyFrequency;
-    bi.eclock = SysBase->ex_EClockFrequency;
+    if (!bi.vblank)
+	bi.vblank = SysBase->VBlankFrequency;
+    if (!bi.psfreq)
+	bi.psfreq = SysBase->PowerSupplyFrequency;
+    if (!bi.eclock)
+	bi.eclock = SysBase->ex_EClockFrequency;
 
     /* serial port */
-    realbaud = baud ? baud : DEFAULT_BAUD;
-    bi.serper = (5*bi.eclock+realbaud/2)/realbaud-1;
-
-    /* copy command line options into the kernel command line */
-    strncpy(bi.command_line, commandline, CL_SIZE);
-    bi.command_line[CL_SIZE-1] = '\0';
-
-
-    /* modify the bootinfo, e.g. to change the memory configuration */
-    if (ModifyBootinfo && !ModifyBootinfo(&bi))
-	goto Fail;
+    if (!bi.serper) {
+	realbaud = baud ? baud : DEFAULT_BAUD;
+	bi.serper = (5*bi.eclock+realbaud/2)/realbaud-1;
+    }
 
     /* display Amiga model */
     if (bi.model >= first_amiga_model && bi.model <= last_amiga_model)
@@ -347,7 +374,7 @@
     }
 
     /* display the chipset */
-    switch(bi.chipset) {
+    switch (bi.chipset) {
 	case CS_STONEAGE:
 	    Puts(", old or unknown chipset");
 	    break;
@@ -457,11 +484,24 @@
 	Printf("Unable to open kernel file `%s'\n", kernelname);
 	goto Fail;
     }
-    if (Read(kfd, (void *)&kexec, sizeof(kexec)) != sizeof(kexec)) {
+    if (KRead(kfd, (void *)&kexec, sizeof(kexec)) != sizeof(kexec)) {
 	Puts("Unable to read exec header from kernel file\n");
 	goto Fail;
     }
 
+#ifdef ZKERNEL
+    if (((unsigned char *)&kexec)[0] == 037 &&
+	(((unsigned char *)&kexec)[1] == 0213 ||
+	 ((unsigned char *)&kexec)[1] == 0236)) {
+	/* That's a compressed kernel */
+	Puts("Kernel is compressed\n");
+	if (load_zkernel(kfd)) {
+	    Puts("Decompression error -- aborting\n");
+	    goto Fail;
+	}
+    }
+#endif
+
     switch (N_MAGIC(kexec)) {
 	case ZMAGIC:
 	    if (debugflag)
@@ -479,8 +519,8 @@
 
 	default:
 	    /* Try to parse it as an ELF header */
-	    Seek(kfd, 0);
-	    if ((Read(kfd, (void *)&kexec_elf, sizeof(kexec_elf)) ==
+	    KSeek(kfd, 0);
+	    if ((KRead(kfd, (void *)&kexec_elf, sizeof(kexec_elf)) ==
 		 sizeof(kexec_elf)) &&
 		 (memcmp(&kexec_elf.e_ident[EI_MAG0], ELFMAG, SELFMAG) == 0)) {
 		elf_kernel = 1;
@@ -501,8 +541,8 @@
 		    Puts("Unable to allocate memory for program headers\n");
 		    goto Fail;
 		}
-		Seek(kfd, kexec_elf.e_phoff);
-		if (Read(kfd, (void *)kernel_phdrs,
+		KSeek(kfd, kexec_elf.e_phoff);
+		if (KRead(kfd, (void *)kernel_phdrs,
 			 kexec_elf.e_phnum*sizeof(*kernel_phdrs)) !=
 		    kexec_elf.e_phnum*sizeof(*kernel_phdrs)) {
 		    Puts("Unable to read program headers from kernel file\n");
@@ -557,32 +597,32 @@
     /* read the text and data segments from the kernel image */
     if (elf_kernel)
 	for (i = 0; i < kexec_elf.e_phnum; i++) {
-	    if (Seek(kfd, kernel_phdrs[i].p_offset) == -1) {
+	    if (KSeek(kfd, kernel_phdrs[i].p_offset) == -1) {
 		Printf("Failed to seek to segment %ld\n", i);
 		goto Fail;
 	    }
-	    if (Read(kfd, memptr+kernel_phdrs[i].p_vaddr-PAGE_SIZE,
-		     kernel_phdrs[i].p_filesz) != kernel_phdrs[i].p_filesz) {
+	    if (KRead(kfd, memptr+kernel_phdrs[i].p_vaddr-PAGE_SIZE,
+		      kernel_phdrs[i].p_filesz) != kernel_phdrs[i].p_filesz) {
 		Printf("Failed to read segment %ld\n", i);
 		goto Fail;
 	    }
 	}
     else {
-	if (Seek(kfd, text_offset) == -1) {
+	if (KSeek(kfd, text_offset) == -1) {
 	    Puts("Failed to seek to text\n");
 	    goto Fail;
 	}
-	if (Read(kfd, memptr, kexec.a_text) != kexec.a_text) {
+	if (KRead(kfd, memptr, kexec.a_text) != kexec.a_text) {
 	    Puts("Failed to read text\n");
 	    goto Fail;
 	}
 	/* data follows immediately after text */
-	if (Read(kfd, memptr+kexec.a_text, kexec.a_data) != kexec.a_data) {
+	if (KRead(kfd, memptr+kexec.a_text, kexec.a_data) != kexec.a_data) {
 	    Puts("Failed to read data\n");
 	    goto Fail;
 	}
     }
-    Close(kfd);
+    KClose(kfd);
     kfd = -1;
 
     /* Check kernel's bootinfo version */
@@ -706,7 +746,7 @@
     /* Clean up and exit in case of a failure */
 Fail:
     if (kfd != -1)
-	Close(kfd);
+	KClose(kfd);
     if (rfd != -1)
 	Close(rfd);
     if (memptr)
@@ -748,37 +788,17 @@
      *	Determine the CPU Type
      */
 
-/* Dectection of 68030 and up is unreliable, so we check ourself */
-/* Keep consistent with asm/setup.h! */
-/* 24.11.1996 Joerg Dorchain */
-asm( ".text\n"
-ALIGN_STR "\n"
-SYMBOL_NAME_STR(check346) ":
-	orw	#0x700,%sr	| disable ints
-	movec	%vbr,%a0	| get vbr
-	movel	%a0@(11*4),%a1	| save old trap vector (Line F)
-	movel	#L1,%a0@(11*4)	| set L1 as new vector
-	movel	%sp,%d1		| save stack pointer
-	moveq	#2,%d0		| value with exception (030)
-	.long	0xf6208000	| move16 %a0@+,%a0@+, the 030 test instruction
-	nop			| clear instruction pipeline
-	movel	%d1,%sp		| restore stack pointer
-	movec	%vbr,%a0	| get vbr again
-	moveq	#4,%d0		| value with exception (040)
-	.word	0xf5c8		| plpar %a0@, the 040 test instruction
-	nop			| clear instruction pipeline
-	moveq	#8,%d0		| value if we come here
-L1:	movel	%d1,%sp		| restore stack pointer
-	movel	%a1,%a0@(11*4)	| restore vector
-	rte"
-);
-
 static void get_processor(u_long *cpu, u_long *fpu, u_long *mmu)
 {
-    if (SysBase->AttnFlags & (AFF_68030|AFF_68040|AFF_68060))
-        *cpu = Supervisor(check346);
+    *cpu = *fpu = 0;
+    if (SysBase->AttnFlags & AFF_68060)
+	*cpu = CPU_68060;
+    else if (SysBase->AttnFlags & AFF_68040)
+	*cpu = CPU_68040;
+    else if (SysBase->AttnFlags & AFF_68030)
+	*cpu = CPU_68030;
     else if (SysBase->AttnFlags & AFF_68020)
-        *cpu = CPU_68020;
+	*cpu = CPU_68020;
     if (*cpu == CPU_68040 || *cpu == CPU_68060) {
 	if (SysBase->AttnFlags & AFF_FPU40)
 	    *fpu = *cpu;
@@ -786,7 +806,7 @@
 	if (SysBase->AttnFlags & AFF_68882)
 	    *fpu = FPU_68882;
 	else if (SysBase->AttnFlags & AFF_68881)
-	    *cpu = FPU_68881;
+	    *fpu = FPU_68881;
     }
     *mmu = *cpu;
 }
@@ -806,7 +826,7 @@
     else {
 	if (debugflag)
 	    Puts("    Chipset: ");
-	switch(chipset) {
+	switch (chipset) {
 	    case CS_STONEAGE:
 		if (debugflag)
 		    Puts("Old or unknown\n");
@@ -1361,7 +1381,7 @@
     Disable();
  
     *nic_cr = 0x21;	/* nic command register: software reset etc. */
-    while(((*nic_isr & 0x80) == 0) && --n)  /* wait for reset to complete */
+    while (((*nic_isr & 0x80) == 0) && --n)  /* wait for reset to complete */
 	;
  
     Enable();
@@ -1373,3 +1393,294 @@
 #error reset_a2060: not yet implemented
 }
 #endif
+
+
+#ifdef ZKERNEL
+
+#define	ZFILE_CHUNK_BITS	16  /* chunk is 64 KB */
+#define	ZFILE_CHUNK_SIZE	(1 << ZFILE_CHUNK_BITS)
+#define	ZFILE_CHUNK_MASK	(ZFILE_CHUNK_SIZE-1)
+#define	ZFILE_N_CHUNKS		(2*1024*1024/ZFILE_CHUNK_SIZE)
+
+/* variables for storing the uncompressed data */
+static char *ZFile[ZFILE_N_CHUNKS];
+static int ZFileSize = 0;
+static int ZFpos = 0;
+static int Zwpos = 0;
+
+static int Zinfd = 0;	     /* fd of compressed file */
+
+/*
+ * gzip declarations
+ */
+
+#define OF(args)  args
+
+#define memzero(s, n)     memset ((s), 0, (n))
+
+typedef unsigned char  uch;
+typedef unsigned short ush;
+typedef unsigned long  ulg;
+
+#define INBUFSIZ 4096
+#define WSIZE 0x8000    /* window size--must be a power of two, and */
+			/*  at least 32K for zip's deflate method */
+
+static uch *inbuf;
+static uch *window;
+
+static unsigned insize = 0;  /* valid bytes in inbuf */
+static unsigned inptr = 0;   /* index of next byte to be processed in inbuf */
+static unsigned outcnt = 0;  /* bytes in output buffer */
+static int exit_code = 0;
+static long bytes_out = 0;
+
+#define get_byte()  (inptr < insize ? inbuf[inptr++] : fill_inbuf())
+		
+/* Diagnostic functions (stubbed out) */
+#define Assert(cond,msg)
+#define Trace(x)
+#define Tracev(x)
+#define Tracevv(x)
+#define Tracec(c,x)
+#define Tracecv(c,x)
+
+#define STATIC static
+
+static int  fill_inbuf(void);
+static void flush_window(void);
+static void error(char *m);
+static void gzip_mark(void **);
+static void gzip_release(void **);
+
+#define malloc(x)	AllocVec(x, MEMF_FAST | MEMF_PUBLIC)
+#define free(x)		FreeVec(x)
+
+#ifdef LILO
+#include "inflate.c"
+#else
+#include "../../../../lib/inflate.c"
+#endif
+
+static void gzip_mark(void **ptr)
+{
+}
+
+static void gzip_release(void **ptr)
+{
+}
+
+
+/*
+ * Fill the input buffer. This is called only when the buffer is empty
+ * and at least one byte is really needed.
+ */
+static int fill_inbuf(void)
+{
+    if (exit_code)
+	return -1;
+
+    insize = Read(Zinfd, inbuf, INBUFSIZ);
+    if (insize <= 0)
+	return -1;
+
+    inptr = 1;
+    return(inbuf[0]);
+}
+
+/*
+ * Write the output window window[0..outcnt-1] and update crc and bytes_out.
+ * (Used for the decompressed data only.)
+ */
+static void flush_window(void)
+{
+    ulg c = crc;         /* temporary variable */
+    unsigned n;
+    uch *in, ch;
+    int chunk = Zwpos >> ZFILE_CHUNK_BITS;
+
+    if (exit_code)
+	return;
+
+    if (chunk >= ZFILE_N_CHUNKS) {
+	error("Compressed image too large! Aborting.\n");
+	return;
+    }
+    if (!ZFile[chunk]) {
+	if (!(ZFile[chunk] = (char *)AllocMem(ZFILE_CHUNK_SIZE,
+					      MEMF_FAST | MEMF_PUBLIC))) {
+	    error("Out of memory for decompresing kernel image\n");
+	    return;
+	}
+    }
+    memcpy(ZFile[chunk] + (Zwpos & ZFILE_CHUNK_MASK), window, outcnt);
+    Zwpos += outcnt;
+    
+#define	DISPLAY_BITS 10
+    if ((Zwpos & ((1 << DISPLAY_BITS)-1)) == 0)
+	PutChar('.');
+    
+    in = window;
+    for (n = 0; n < outcnt; n++) {
+	ch = *in++;
+	c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
+    }
+    crc = c;
+    bytes_out += (ulg)outcnt;
+    outcnt = 0;
+}
+
+static void error(char *x)
+{
+    Printf("\n%s", x);
+    exit_code = 1;
+}
+
+static inline int call_sub(int (*func)(void), void *stackp)
+{
+    register int _res __asm("d0");
+    register int (*a0)(void) __asm("a0") = func;
+    register int (*a1)(void) __asm("a1") = stackp;
+
+    __asm __volatile ("movel sp,a2;"
+    		      "movel a1,sp;"
+    		      "jsr a0@;"
+    		      "movel a2,sp"
+		      : "=r" (_res)
+		      : "r" (a0), "r" (a1)
+		      : "a0", "a1", "a2", "d0", "d1", "memory");
+    return(_res);
+}
+
+static int load_zkernel(int fd)
+{
+    int i, err = -1;
+#define ZSTACKSIZE	(16384)
+    u_long *zstack;
+    
+    for (i = 0; i < ZFILE_N_CHUNKS; ++i)
+	ZFile[i] = NULL;
+    Zinfd = fd;
+    Seek(fd, 0);
+    
+    if (!(inbuf = (uch *)AllocMem(INBUFSIZ, MEMF_FAST | MEMF_PUBLIC)))
+	Puts("Couldn't allocate gunzip buffer\n");
+    else {
+	if (!(window = (uch *)AllocMem(WSIZE, MEMF_FAST | MEMF_PUBLIC)))
+	    Puts("Couldn't allocate gunzip window\n");
+	else {
+	    if (!(zstack = (u_long *)AllocMem(ZSTACKSIZE,
+	    				      MEMF_FAST | MEMF_PUBLIC)))
+		Puts("Couldn't allocate gunzip stack\n");
+	    else {
+		Puts("Uncompressing kernel image ");
+		makecrc();
+		if (!(err = call_sub(gunzip, (char *)zstack+ZSTACKSIZE)))
+		    Puts("done\n");
+		ZFileSize = Zwpos;
+		FreeMem(zstack, ZSTACKSIZE);
+	    }
+	    FreeMem(window, WSIZE);
+	    window = NULL;
+	}
+	FreeMem(inbuf, INBUFSIZ);
+	inbuf = NULL;
+    }
+    Close(Zinfd);	/* input file not needed anymore */
+    return(err);
+}
+
+
+/* Note about the read/lseek wrapper and its memory management: It assumes
+ * that all seeks are only forward, and thus data already read or skipped can
+ * be freed. This is true for current organization of bootstrap and kernels.
+ * Little exception: The struct kexec at the start of the file. After reading
+ * it, there may be a seek back to the end of the file. But this currently
+ * doesn't hurt. (Roman)
+ */
+
+static int KRead(int fd, void *buf, int cnt)
+{
+    unsigned done = 0;
+	
+    if (!ZFileSize)
+	return(Read(fd, buf, cnt));
+    
+    if (ZFpos + cnt > ZFileSize)
+	cnt = ZFileSize - ZFpos;
+    
+    while (cnt > 0) {
+	unsigned chunk = ZFpos >> ZFILE_CHUNK_BITS;
+	unsigned endchunk = (chunk+1) << ZFILE_CHUNK_BITS;
+	unsigned n = cnt;
+
+	if (ZFpos + n > endchunk)
+	    n = endchunk - ZFpos;
+	memcpy(buf, ZFile[chunk] + (ZFpos & ZFILE_CHUNK_MASK), n);
+	cnt -= n;
+	buf += n;
+	done += n;
+	ZFpos += n;
+
+	if (ZFpos == endchunk) {
+	    FreeMem(ZFile[chunk], ZFILE_CHUNK_SIZE);
+	    ZFile[chunk] = NULL;
+	}
+    }
+
+    return(done);
+}
+
+
+static int KSeek(int fd, int offset)
+{
+    unsigned oldpos, oldchunk, newchunk;
+
+    if (!ZFileSize)
+	return(Seek(fd, offset));
+
+    oldpos = ZFpos;
+    ZFpos = offset;
+    if (ZFpos < 0) {
+	ZFpos = 0;
+	return(-1);
+    } else if (ZFpos > ZFileSize) {
+	ZFpos = ZFileSize;
+	return(-1);
+    }
+
+    /* free memory of skipped-over data */
+    oldchunk = oldpos >> ZFILE_CHUNK_BITS;
+    newchunk = ZFpos  >> ZFILE_CHUNK_BITS;
+    while(oldchunk < newchunk) {
+	if (ZFile[oldchunk]) {
+	    FreeMem(ZFile[oldchunk], ZFILE_CHUNK_SIZE);
+	    ZFile[oldchunk] = NULL;
+	}
+	++oldchunk;
+    }
+    return(ZFpos);
+}
+
+
+static void free_zfile(void)
+{
+    int i;
+
+    for (i = 0; i < ZFILE_N_CHUNKS; ++i)
+	if (ZFile[i]) {
+	    FreeMem(ZFile[i], ZFILE_CHUNK_SIZE);
+	    ZFile[i] = NULL;
+	}
+}
+
+static int KClose(int fd)
+{
+    if (ZFileSize) {
+	free_zfile();
+	ZFileSize = 0;
+    } else
+	Close(fd);
+    return(0);
+}
+#endif /* ZKERNEL */
diff -u --recursive --new-file v2.1.35/linux/arch/m68k/boot/amiga/linuxboot.h linux/arch/m68k/boot/amiga/linuxboot.h
--- v2.1.35/linux/arch/m68k/boot/amiga/linuxboot.h	Fri Dec 20 01:19:58 1996
+++ linux/arch/m68k/boot/amiga/linuxboot.h	Thu Apr 17 13:20:42 1997
@@ -24,14 +24,14 @@
 
 
 #include <asm/setup.h>
-#include <asm/zorro.h>
+#include <linux/zorro.h>
 
 
     /*
      *  Amiboot Version
      */
 
-#define AMIBOOT_VERSION		"5.1"
+#define AMIBOOT_VERSION		"5.4"
 
 
     /*
@@ -42,7 +42,7 @@
      */
 
 struct amiga_bootinfo {
-    u_long machtype;			/* machine type */
+    u_long machtype;			/* machine type = MACH_AMIGA */
     u_long cputype;			/* system CPU */
     u_long fputype;			/* system FPU */
     u_long mmutype;			/* system MMU */
@@ -67,9 +67,9 @@
      */
 
 struct linuxboot_args {
+    struct amiga_bootinfo bi;	/* Initial values override detected values */
     const char *kernelname;
     const char *ramdiskname;
-    const char *commandline;
     int debugflag;
     int keep_video;
     int reset_boards;
@@ -84,7 +84,6 @@
     void (*close)(int fd);
     int (*filesize)(const char *path);
     void (*sleep)(u_long micros);
-    int (*modify_bootinfo)(struct amiga_bootinfo *bi);
 };
 
 
diff -u --recursive --new-file v2.1.35/linux/arch/m68k/boot/atari/bootp.c linux/arch/m68k/boot/atari/bootp.c
--- v2.1.35/linux/arch/m68k/boot/atari/bootp.c	Wed Sep 25 00:47:39 1996
+++ linux/arch/m68k/boot/atari/bootp.c	Thu Apr 17 13:20:42 1997
@@ -203,18 +203,20 @@
 /* get_remote_kernel():
  * Perform all necessary steps to get the kernel image
  * from the boot server. If successfull (retval == 0), subsequent calls to
- * kread() can access the data.
+ * kread() can access the data. Fatal errors (i.e., retrying is useless)
+ * return -2, others -1.
  */
 
 int get_remote_kernel( const char *kname /* optional */ )
 
 {	char	image_name[256];
-	
+	int		rv;
+
 	/* Check if a Ethernet interface is present and determine the Ethernet
 	 * address */
 	if (check_ethif() < 0) {
 		printf( "No Ethernet interface found -- no remote boot possible.\n" );
-		return( -1 );
+		return( -2 );
 	}
 	
 	/* Do a BOOTP request to find out our IP address and the kernel image's
@@ -223,23 +225,23 @@
 		strcpy( image_name, kname );
 	else
 		*image_name = 0;
-	if (bootp( image_name ) < 0)
-		return( -1 );
+	if ((rv = bootp( image_name )) < 0)
+		return( rv );
 	
 	/* Now start a TFTP connection to receive the kernel image */
-	if (tftp( image_name ) < 0)
-		return( -1 );
+	if ((rv = tftp( image_name )) < 0)
+		return( rv );
 
 	return( 0 );
 }
 
 
-/* kread(), klseek(), kclose():
+/* ll_read(), ll_lseek(), ll_close():
  * Functions for accessing the received kernel image like with read(),
  * lseek(), close().
  */
 
-int kread( int fd, void *buf, unsigned cnt )
+int ll_read( int fd, void *buf, unsigned cnt )
 
 {	unsigned done = 0;
 	
@@ -261,18 +263,26 @@
 		buf += n;
 		done += n;
 		KFpos += n;
+
+		if (KFpos == endchunk) {
+			free( KFile[chunk] );
+			KFile[chunk] = NULL;
+		}
 	}
 
 	return( done );
 }
 
 
-int klseek( int fd, int where, int whence )
+int ll_lseek( int fd, int where, int whence )
 
 {
+    unsigned oldpos, oldchunk, newchunk;
+
 	if (!KFileSize)
 		return( lseek( fd, where, whence ) );
 
+    oldpos = KFpos;
 	switch( whence ) {
 	  case SEEK_SET:
 		KFpos = where;
@@ -295,11 +305,22 @@
 		return( -1 );
 	}
 
+    /* free memory of skipped-over data */
+    oldchunk = oldpos >> KFILE_CHUNK_BITS;
+    newchunk = KFpos  >> KFILE_CHUNK_BITS;
+    while( oldchunk < newchunk ) {
+		if (KFile[oldchunk]) {
+			free( KFile[oldchunk] );
+			KFile[oldchunk] = NULL;
+		}
+		++oldchunk;
+    }
+    
 	return( KFpos );
 }
 
 
-int kclose( int fd )
+int ll_close( int fd )
 
 {
 	if (!KFileSize)
@@ -382,7 +403,7 @@
 	}
 	if (retry >= BOOTP_RETRYS) {
 		printf( "No response from a bootp server\n" );
-		return( -1 );
+		return( -2 );
 	}
 	
 	ServerIPaddr = reply->bootp.siaddr;
@@ -433,7 +454,7 @@
 		printf( "TFTP RREQ: %s\n", ErrStr[-err-1] );
 		if (--retries > 0)
 			goto repeat_req;
-		return( -1 );
+		return( err == ETIMEO ? -2 : -1 );
 	}
 
 	retries = 5;
diff -u --recursive --new-file v2.1.35/linux/arch/m68k/boot/atari/bootp.h linux/arch/m68k/boot/atari/bootp.h
--- v2.1.35/linux/arch/m68k/boot/atari/bootp.h	Wed Sep 25 00:47:39 1996
+++ linux/arch/m68k/boot/atari/bootp.h	Thu Apr 17 13:20:42 1997
@@ -34,9 +34,9 @@
 /***************************** Prototypes *****************************/
 
 int get_remote_kernel( const char *kname );
-int kread( int fd, void *buf, unsigned cnt );
-int klseek( int fd, int where, int whence );
-int kclose( int fd );
+int ll_read( int fd, void *buf, unsigned cnt );
+int ll_lseek( int fd, int where, int whence );
+int ll_close( int fd );
 
 /************************* End of Prototypes **************************/
 
diff -u --recursive --new-file v2.1.35/linux/arch/m68k/boot/atari/bootstrap.c linux/arch/m68k/boot/atari/bootstrap.c
--- v2.1.35/linux/arch/m68k/boot/atari/bootstrap.c	Fri Dec 20 01:19:58 1996
+++ linux/arch/m68k/boot/atari/bootstrap.c	Thu Apr 17 13:20:42 1997
@@ -8,6 +8,8 @@
 ** for more details.
 **
 ** History:
+**	01 Feb 1997 Implemented kernel decompression (Roman)
+**	28 Nov 1996 Fixed and tested previous change (James)
 **	27 Nov 1996 Compatibility with bootinfo interface version 1.0 (Geert)
 **	12 Nov 1996 Fixed and tested previous change (Andreas)
 **	18 Aug 1996 Updated for the new boot information structure (untested!)
@@ -32,6 +34,8 @@
 
 
 #define BOOTINFO_COMPAT_1_0	/* bootinfo interface version 1.0 compatible */
+/* support compressed kernels? */
+#define ZKERNEL
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -159,6 +163,9 @@
  * ...err! On the Afterburner040 (for the Falcon) it's the same... So we do
  * another test with 0x00ff82fe, that gives a bus error on the Falcon, but is
  * in the range where the Medusa always asserts DTACK.
+ * On the Hades address 0 is writeable as well and it asserts DTACK on
+ * address 0x00ff82fe. To test if the machine is a Hades, address 0xb0000000
+ * is tested. On the Medusa this gives a bus error.
  */
 
 int test_medusa( void )
@@ -177,7 +184,10 @@
 		  "nop		\n\t"
 		  "tstb		0x00ff82fe\n\t"
 		  "nop		\n\t"
-		  "moveq	#1,%0\n"
+		  "moveq	#1,%0\n\t"
+		  "tstb		0xb0000000\n\t"
+		  "nop		\n\t"
+		  "moveq	#0,%0\n"
 		"Lberr:\t"
 		  "movel	a1,sp\n\t"
 		  "movel	a0,0x8"
@@ -357,11 +367,21 @@
 #ifdef USE_BOOTP
 # include "bootp.h"
 #else
-# define kread	read
-# define klseek	lseek
-# define kclose	close
+# define ll_read	read
+# define ll_lseek	lseek
+# define ll_close	close
 #endif
 
+#ifdef ZKERNEL
+static int load_zkernel( int fd );
+static int kread( int fd, void *buf, unsigned cnt );
+static int klseek( int fd, int where, int whence );
+static int kclose( int fd );
+#else
+# define kread		read
+# define klseek		lseek
+# define kclose		close
+#endif
 
 /* ++andreas: this must be inline due to Super */
 static inline void boot_exit (int) __attribute__ ((noreturn));
@@ -385,16 +405,18 @@
     Elf32_Ehdr kexec_elf;
     Elf32_Phdr *kernel_phdrs = NULL;
     u_long start_mem, mem_size, rd_size, text_offset = 0, kernel_size;
+    int prefer_bootp = 1, kname_set = 0, n_knames;
 #ifdef USE_BOOTP
-    int prefer_bootp = 1, kname_set = 0;
+    int err;
 #endif
+    char kname_list[5][64];
     void *bi_ptr;
 
     ramdisk_name = NULL;
     kernel_name = "vmlinux";
 
     /* print the startup message */
-    puts("\fLinux/68k Atari Bootstrap version 2.0"
+    puts("\fLinux/68k Atari Bootstrap version 2.2"
 #ifdef USE_BOOTP
 	 " (with BOOTP)"
 #endif
@@ -410,11 +432,7 @@
     bi.machtype = MACH_ATARI;
 
     /* check arguments */
-#ifdef USE_BOOTP
     while ((ch = getopt(argc, argv, "bdtsk:r:")) != EOF)
-#else
-    while ((ch = getopt(argc, argv, "dtsk:r:")) != EOF)
-#endif
 	switch (ch) {
 	  case 'd':
 	    debugflag = 1;
@@ -427,18 +445,14 @@
 	    break;
 	  case 'k':
 	    kernel_name = optarg;
-#ifdef USE_BOOTP
 	    kname_set = 1;
-#endif
 	    break;
 	  case 'r':
 	    ramdisk_name = optarg;
 	    break;
-#ifdef USE_BOOTP
 	  case 'b':
 	    prefer_bootp = 0;
 	    break;
-#endif
 	  case '?':
 	  default:
 	    usage();
@@ -744,38 +758,60 @@
     boot_exit(-1);
 #endif /* TEST */
 
+    i = 0;
 #ifdef USE_BOOTP
+    if (!kname_set)
+	kname_list[i++][0] = '\0'; /* default kernel which BOOTP server says */
+#endif
+#ifdef ZKERNEL
+    strcpy( kname_list[i], kernel_name );
+    strcat( kname_list[i], ".gz" );
+    ++i;
+#endif
+    strcpy( kname_list[i++], kernel_name );
+#ifdef ZKERNEL
+    if (!kname_set)
+	strcpy( kname_list[i++], "vmlinuz" );
+#endif
+    n_knames = i;
+
     kfd = -1;
+#ifdef USE_BOOTP
     if (prefer_bootp) {
-	/* First try to get a remote kernel, then use a local kernel (if
-	 * present) */
-	if (get_remote_kernel( kname_set ? kernel_name : NULL ) < 0) {
-	    printf( "\nremote boot failed; trying local kernel\n" );
-	    if ((kfd = open (kernel_name, O_RDONLY)) == -1) {
-		fprintf (stderr, "Unable to open kernel file %s\n",
-			 kernel_name);
-		boot_exit (EXIT_FAILURE);
-	    }
+	for( i = 0; i < n_knames; ++i ) {
+	    if ((err = get_remote_kernel( kname_list[i] )) >= 0)
+		goto kernel_open;
+	    if (err < -1) /* fatal error; retries don't help... */
+		break;
 	}
+	printf( "\nremote boot failed; trying local kernel\n" );
     }
-    else {
-	/* Try BOOTP if local kernel cannot be opened */
-	if ((kfd = open (kernel_name, O_RDONLY)) == -1) {
-	    printf( "\nlocal kernel failed; trying remote boot\n" );
-	    if (get_remote_kernel( kname_set ? kernel_name : NULL ) < 0) {
-		fprintf (stderr, "Unable to remote boot and "
-			 "to open kernel file %s\n", kernel_name);
-		boot_exit (EXIT_FAILURE);
-	    }
-	}
+#endif
+    for( i = 0; i < n_knames; ++i ) {
+	if ((kfd = open( kname_list[i], O_RDONLY )) != -1)
+	    goto kernel_open;
     }
-#else
-    /* open kernel executable and read exec header */
-    if ((kfd = open (kernel_name, O_RDONLY)) == -1) {
-	fprintf (stderr, "Unable to open kernel file %s\n", kernel_name);
-	boot_exit (EXIT_FAILURE);
+#ifdef USE_BOOTP
+    if (!prefer_bootp) {
+	printf( "\nlocal kernel failed; trying remote boot\n" );
+	for( i = 0; i < n_knames; ++i ) {
+	    if ((err = get_remote_kernel( kname_list[i] )) >= 0)
+		goto kernel_open;
+	    if (err < -1) /* fatal error; retries don't help... */
+		break;
+	}
     }
 #endif
+    fprintf( stderr, "Unable to open any kernel file\n(Tried " );
+    for( i = 0; i < n_knames; ++i ) {
+	fprintf( stderr, "%s%s", kname_list[i],
+		 i <  n_knames-2 ? ", " :
+		 i == n_knames-2 ? ", and " :
+		 ")\n" );
+    }
+    boot_exit( EXIT_FAILURE );
+    
+  kernel_open:
 
     if (kread (kfd, (void *)&kexec, sizeof(kexec)) != sizeof(kexec))
     {
@@ -783,6 +819,19 @@
 	boot_exit (EXIT_FAILURE);
     }
 
+#ifdef ZKERNEL
+    if (((unsigned char *)&kexec)[0] == 037 &&
+	(((unsigned char *)&kexec)[1] == 0213 ||
+	 ((unsigned char *)&kexec)[1] == 0236)) {
+	/* That's a compressed kernel */
+	printf( "Kernel is compressed\n" );
+	if (load_zkernel( kfd )) {
+	    printf( "Decompression error -- aborting\n" );
+	    boot_exit( EXIT_FAILURE );
+	}
+    }
+#endif
+    
     switch (N_MAGIC(kexec)) {
     case ZMAGIC:
 	text_offset = N_TXTOFF(kexec);
@@ -847,18 +896,6 @@
     }
     else
 	bi.ramdisk.size = 0;
-
-    rd_size = bi.ramdisk.size;
-    if (mem_size - rd_size < MB && bi.num_memory > 1)
-      /* If running low on ST ram load ramdisk into alternate ram.  */
-      bi.ramdisk.addr = (u_long) bi.memory[1].addr + bi.memory[1].size - rd_size;
-    else
-      /* Else hopefully there is enough ST ram. */
-      bi.ramdisk.addr = (u_long)start_mem + mem_size - rd_size;
-
-    /* create the bootinfo structure */
-    if (!create_bootinfo())
-	boot_exit (EXIT_FAILURE);
  
     /* calculate the total required amount of memory */
     if (elf_kernel)
@@ -885,6 +922,19 @@
       }
     else
       kernel_size = kexec.a_text + kexec.a_data + kexec.a_bss;
+
+    rd_size = bi.ramdisk.size;
+    if (rd_size + kernel_size > mem_size - MB/2 && bi.num_memory > 1)
+      /* If running low on ST ram load ramdisk into alternate ram.  */
+      bi.ramdisk.addr = (u_long) bi.memory[1].addr + bi.memory[1].size - rd_size;
+    else
+      /* Else hopefully there is enough ST ram. */
+      bi.ramdisk.addr = (u_long)start_mem + mem_size - rd_size;
+
+    /* create the bootinfo structure */
+    if (!create_bootinfo())
+	boot_exit (EXIT_FAILURE);
+
     memreq = kernel_size + bi_size;
 #ifdef BOOTINFO_COMPAT_1_0
     if (sizeof(compat_bootinfo) > bi_size)
@@ -997,7 +1047,7 @@
     if (debugflag)
     {
 	if (bi.ramdisk.size)
-	    printf ("RAM disk at %#lx, size is %ldK\n",
+	    printf ("RAM disk at %#lx, size is %ld\n",
 		    (u_long)(memptr + memreq - rd_size),
 		    bi.ramdisk.size);
 
@@ -1192,7 +1242,7 @@
 static int add_bi_record(u_short tag, u_short size, const void *data)
 {
     struct bi_record *record;
-    u_int size2;
+    u_short size2;
 
     size2 = (sizeof(struct bi_record)+size+3)&-4;
     if (bi_size+size2+sizeof(bi_union.record.tag) > MAX_BI_SIZE) {
@@ -1238,7 +1288,7 @@
     else if (bi.cputype & CPU_68060)
 	compat_bootinfo.cputype = COMPAT_CPU_68060;
     else {
-	Printf("CPU type 0x%08lx not supported by kernel\n", bi.cputype);
+	printf("CPU type 0x%08lx not supported by kernel\n", bi.cputype);
 	return(0);
     }
     if (bi.fputype & FPU_68881)
@@ -1250,12 +1300,12 @@
     else if (bi.fputype & FPU_68060)
 	compat_bootinfo.cputype |= COMPAT_FPU_68060;
     else {
-	Printf("FPU type 0x%08lx not supported by kernel\n", bi.fputype);
+	printf("FPU type 0x%08lx not supported by kernel\n", bi.fputype);
 	return(0);
     }
     compat_bootinfo.num_memory = bi.num_memory;
     if (compat_bootinfo.num_memory > COMPAT_NUM_MEMINFO) {
-	Printf("Warning: using only %d blocks of memory\n",
+	printf("Warning: using only %d blocks of memory\n",
 	       COMPAT_NUM_MEMINFO);
 	compat_bootinfo.num_memory = COMPAT_NUM_MEMINFO;
     }
@@ -1278,3 +1328,275 @@
     return(1);
 }
 #endif /* BOOTINFO_COMPAT_1_0 */
+
+
+#ifdef ZKERNEL
+
+#define	ZFILE_CHUNK_BITS	16  /* chunk is 64 KB */
+#define	ZFILE_CHUNK_SIZE	(1 << ZFILE_CHUNK_BITS)
+#define	ZFILE_CHUNK_MASK	(ZFILE_CHUNK_SIZE-1)
+#define	ZFILE_N_CHUNKS		(2*1024*1024/ZFILE_CHUNK_SIZE)
+
+/* variables for storing the uncompressed data */
+static char *ZFile[ZFILE_N_CHUNKS];
+static int ZFileSize = 0;
+static int ZFpos = 0;
+static int Zwpos = 0;
+
+static int Zinfd = 0;	     /* fd of compressed file */
+
+/*
+ * gzip declarations
+ */
+
+#define OF(args)  args
+
+#define memzero(s, n)     memset ((s), 0, (n))
+
+typedef unsigned char  uch;
+typedef unsigned short ush;
+typedef unsigned long  ulg;
+
+#define INBUFSIZ 4096
+#define WSIZE 0x8000    /* window size--must be a power of two, and */
+			/*  at least 32K for zip's deflate method */
+
+static uch *inbuf;
+static uch *window;
+
+static unsigned insize = 0;  /* valid bytes in inbuf */
+static unsigned inptr = 0;   /* index of next byte to be processed in inbuf */
+static unsigned outcnt = 0;  /* bytes in output buffer */
+static int exit_code = 0;
+static long bytes_out = 0;
+
+#define get_byte()  (inptr < insize ? inbuf[inptr++] : fill_inbuf())
+		
+/* Diagnostic functions (stubbed out) */
+#define Assert(cond,msg)
+#define Trace(x)
+#define Tracev(x)
+#define Tracevv(x)
+#define Tracec(c,x)
+#define Tracecv(c,x)
+
+#define STATIC static
+
+static int  fill_inbuf(void);
+static void flush_window(void);
+static void error(char *m);
+static void gzip_mark(void **);
+static void gzip_release(void **);
+
+#include "../../../../lib/inflate.c"
+
+static void gzip_mark( void **ptr )
+{
+}
+
+static void gzip_release( void **ptr )
+{
+}
+
+
+/*
+ * Fill the input buffer. This is called only when the buffer is empty
+ * and at least one byte is really needed.
+ */
+static int fill_inbuf( void )
+{
+    if (exit_code)
+	return -1;
+
+    insize = ll_read( Zinfd, inbuf, INBUFSIZ );
+    if (insize <= 0)
+	return -1;
+
+    inptr = 1;
+    return( inbuf[0] );
+}
+
+/*
+ * Write the output window window[0..outcnt-1] and update crc and bytes_out.
+ * (Used for the decompressed data only.)
+ */
+static void flush_window( void )
+{
+    ulg c = crc;         /* temporary variable */
+    unsigned n;
+    uch *in, ch;
+    int chunk = Zwpos >> ZFILE_CHUNK_BITS;
+
+    if (chunk >= ZFILE_N_CHUNKS) {
+	fprintf( stderr, "compressed image too large! Aborting.\n" );
+	boot_exit( EXIT_FAILURE );
+    }
+    if (!ZFile[chunk]) {
+	if (!(ZFile[chunk] = (char *)Malloc( ZFILE_CHUNK_SIZE ))) {
+	    fprintf( stderr, "Out of memory for decompresing kernel image\n" );
+	    boot_exit( EXIT_FAILURE );
+	}
+    }
+    memcpy( ZFile[chunk] + (Zwpos & ZFILE_CHUNK_MASK), window, outcnt );
+    Zwpos += outcnt;
+    
+#define	DISPLAY_BITS 13
+    if ((Zwpos & ((1 << DISPLAY_BITS)-1)) == 0) {
+	printf( "." );
+	fflush( stdout );
+    }
+    
+    in = window;
+    for (n = 0; n < outcnt; n++) {
+	    ch = *in++;
+	    c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
+    }
+    crc = c;
+    bytes_out += (ulg)outcnt;
+    outcnt = 0;
+}
+
+static void error( char *x )
+{
+    fprintf( stderr, "\n%s", x);
+    exit_code = 1;
+}
+
+static int load_zkernel( int fd )
+{
+    int i, err;
+    
+    for( i = 0; i < ZFILE_N_CHUNKS; ++i )
+	ZFile[i] = NULL;
+    Zinfd = fd;
+    ll_lseek( fd, 0, SEEK_SET );
+    
+    if (!(inbuf = (uch *)Malloc( INBUFSIZ ))) {
+	fprintf( stderr, "Couldn't allocate gunzip buffer\n" );
+	boot_exit( EXIT_FAILURE );
+    }
+    if (!(window = (uch *)Malloc( WSIZE ))) {
+	fprintf( stderr, "Couldn't allocate gunzip window\n" );
+	boot_exit( EXIT_FAILURE );
+    }
+
+    printf( "Uncompressing kernel image " );
+    fflush( stdout );
+    makecrc();
+    if (!(err = gunzip()))
+	printf( "done\n" );
+    ZFileSize = Zwpos;
+    ll_close( Zinfd ); /* input file not needed anymore */
+    
+    Mfree( inbuf );
+    Mfree( window );
+    return( err );
+}
+
+/* Note about the read/lseek wrapper and its memory management: It assumes
+ * that all seeks are only forward, and thus data already read or skipped can
+ * be freed. This is true for current organization of bootstrap and kernels.
+ * Little exception: The struct kexec at the start of the file. After reading
+ * it, there may be a seek back to the end of the file. But this currently
+ * doesn't hurt. Same considerations apply to the TFTP file buffers. (Roman)
+ */
+
+static int kread( int fd, void *buf, unsigned cnt )
+{
+    unsigned done = 0;
+	
+    if (!ZFileSize)
+	return( ll_read( fd, buf, cnt ) );
+    
+    if (ZFpos + cnt > ZFileSize)
+	cnt = ZFileSize - ZFpos;
+    
+    while( cnt > 0 ) {
+	unsigned chunk = ZFpos >> ZFILE_CHUNK_BITS;
+	unsigned endchunk = (chunk+1) << ZFILE_CHUNK_BITS;
+	unsigned n = cnt;
+
+	if (ZFpos + n > endchunk)
+	    n = endchunk - ZFpos;
+	memcpy( buf, ZFile[chunk] + (ZFpos & ZFILE_CHUNK_MASK), n );
+	cnt -= n;
+	buf += n;
+	done += n;
+	ZFpos += n;
+
+	if (ZFpos == endchunk) {
+	    Mfree( ZFile[chunk] );
+	    ZFile[chunk] = NULL;
+	}
+    }
+
+    return( done );
+}
+
+
+static int klseek( int fd, int where, int whence )
+{
+    unsigned oldpos, oldchunk, newchunk;
+
+    if (!ZFileSize)
+	return( ll_lseek( fd, where, whence ) );
+
+    oldpos = ZFpos;
+    switch( whence ) {
+      case SEEK_SET:
+	ZFpos = where;
+	break;
+      case SEEK_CUR:
+	ZFpos += where;
+	break;
+      case SEEK_END:
+	ZFpos = ZFileSize + where;
+	break;
+      default:
+	return( -1 );
+    }
+    if (ZFpos < 0) {
+	ZFpos = 0;
+	return( -1 );
+    }
+    else if (ZFpos > ZFileSize) {
+	ZFpos = ZFileSize;
+	return( -1 );
+    }
+
+    /* free memory of skipped-over data */
+    oldchunk = oldpos >> ZFILE_CHUNK_BITS;
+    newchunk = ZFpos  >> ZFILE_CHUNK_BITS;
+    while( oldchunk < newchunk ) {
+	if (ZFile[oldchunk]) {
+	    Mfree( ZFile[oldchunk] );
+	    ZFile[oldchunk] = NULL;
+	}
+	++oldchunk;
+    }
+    
+    return( ZFpos );
+}
+
+
+static void free_zfile( void )
+{
+    int i;
+
+    for( i = 0; i < ZFILE_N_CHUNKS; ++i )
+	if (ZFile[i]) Mfree( ZFile[i] );
+}
+
+static int kclose( int fd )
+{
+    if (ZFileSize) {
+	free_zfile();
+	return( 0 );
+    }
+    else
+	return( ll_close( fd ) );
+}
+
+
+
+#endif /* ZKERNEL */
diff -u --recursive --new-file v2.1.35/linux/arch/m68k/config.in linux/arch/m68k/config.in
--- v2.1.35/linux/arch/m68k/config.in	Mon Apr  7 11:35:29 1997
+++ linux/arch/m68k/config.in	Thu Apr 17 13:20:42 1997
@@ -58,6 +58,9 @@
   bool 'Amiga ECS chipset support' CONFIG_AMIFB_ECS
   bool 'Amiga AGA chipset support' CONFIG_AMIFB_AGA
   bool 'Amiga Cybervision support' CONFIG_FB_CYBER
+  if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+    bool 'Amiga RetinaZ3 support' CONFIG_FB_RETINAZ3
+  fi
 #  bool 'Amiga GSP (TMS340x0) support' CONFIG_AMIGA_GSP
 #  if [ "$CONFIG_AMIGA_GSP" = "y" ]; then
 #    bool 'DMI Resolver support' CONFIG_GSP_RESOLVER
@@ -82,15 +85,15 @@
   dep_tristate '   SCSI emulation support' CONFIG_BLK_DEV_IDESCSI $CONFIG_BLK_DEV_IDE
 fi
 if [ "$CONFIG_AMIGA" = "y" ]; then
-tristate 'Amiga Zorro II ramdisk support' CONFIG_AMIGA_Z2RAM
+  tristate 'Amiga Zorro II ramdisk support' CONFIG_AMIGA_Z2RAM
 fi
 if [ "$CONFIG_ATARI" = "y" ]; then
-tristate 'Atari ACSI support' CONFIG_ATARI_ACSI
-if [ "$CONFIG_ATARI_ACSI" != "n" ]; then
-comment 'Some devices (e.g. CD jukebox) support multiple LUNs'
-bool 'Probe all LUNs on each ACSI device' CONFIG_ACSI_MULTI_LUN
-dep_tristate 'Atari SLM laser printer support' CONFIG_ATARI_SLM $CONFIG_ATARI_ACSI
-fi
+  tristate 'Atari ACSI support' CONFIG_ATARI_ACSI
+  if [ "$CONFIG_ATARI_ACSI" != "n" ]; then
+    comment 'Some devices (e.g. CD jukebox) support multiple LUNs'
+    bool 'Probe all LUNs on each ACSI device' CONFIG_ACSI_MULTI_LUN
+    dep_tristate 'Atari SLM laser printer support' CONFIG_ATARI_SLM $CONFIG_ATARI_ACSI
+  fi
 fi
 
 comment 'Additional Block Devices'
@@ -138,17 +141,23 @@
 comment 'SCSI low-level drivers'
 
 if [ "$CONFIG_AMIGA" = "y" ]; then
-tristate 'A3000 WD33C93A support' CONFIG_A3000_SCSI
-tristate 'A2091 WD33C93A support' CONFIG_A2091_SCSI
-tristate 'GVP Series II WD33C93A support' CONFIG_GVP11_SCSI
-bool 'CyberStorm SCSI support' CONFIG_CYBERSTORM_SCSI
-bool 'CyberStorm SCSI Mk II support' CONFIG_CYBERSTORMII_SCSI
-bool 'Blizzard 2060 SCSI support' CONFIG_BLZ2060_SCSI
-bool 'Blizzard 1230IV/1260 SCSI support' CONFIG_BLZ1230_SCSI
+  tristate 'A3000 WD33C93A support' CONFIG_A3000_SCSI
+  tristate 'A2091 WD33C93A support' CONFIG_A2091_SCSI
+  tristate 'GVP Series II WD33C93A support' CONFIG_GVP11_SCSI
+  bool 'CyberStorm SCSI support' CONFIG_CYBERSTORM_SCSI
+  bool 'CyberStorm SCSI Mk II support' CONFIG_CYBERSTORMII_SCSI
+  bool 'Blizzard 2060 SCSI support' CONFIG_BLZ2060_SCSI
+  bool 'Blizzard 1230IV/1260 SCSI support' CONFIG_BLZ1230_SCSI
+  bool 'Fastlane SCSI support' CONFIG_FASTLANE_SCSI
+  if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+    bool 'A4000T SCSI support' CONFIG_A4000T_SCSI
+    bool 'A4091 SCSI support' CONFIG_A4091_SCSI
+    bool 'WarpEngine SCSI support' CONFIG_WARPENGINE_SCSI
+  fi
 fi
 if [ "$CONFIG_ATARI" = "y" ]; then
-dep_tristate 'Atari native SCSI support' CONFIG_ATARI_SCSI $CONFIG_SCSI
-bool 'Long delays for Toshiba CD-ROMs' CONFIG_ATARI_SCSI_TOSHIBA_DELAY
+  dep_tristate 'Atari native SCSI support' CONFIG_ATARI_SCSI $CONFIG_SCSI
+  bool 'Long delays for Toshiba CD-ROMs' CONFIG_ATARI_SCSI_TOSHIBA_DELAY
 fi
 #dep_tristate 'SCSI debugging host adapter' CONFIG_SCSI_DEBUG $CONFIG_SCSI
 endmenu
@@ -202,6 +211,7 @@
 
 define_bool CONFIG_VT y
 define_bool CONFIG_VT_CONSOLE y
+define_bool CONFIG_FB_CONSOLE y
 
 tristate 'Parallel printer support' CONFIG_PRINTER
 if [ "$CONFIG_AMIGA" = "y" ]; then
@@ -214,13 +224,26 @@
 if [ "$CONFIG_ATARI" = "y" ]; then
   tristate 'Atari MFP serial support' CONFIG_ATARI_MFPSER
   tristate 'Atari SCC serial support' CONFIG_ATARI_SCC
+  if [ "$CONFIG_ATARI_SCC" = "y" -o "$CONFIG_ATARI_SCC" = "m" ]; then
+    bool 'Atari SCC serial DMA support' CONFIG_ATARI_SCC_DMA
+  fi
   tristate 'Atari MIDI serial support' CONFIG_ATARI_MIDI
+  if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+    tristate 'Atari DSP56k support (EXPERIMENTAL)' CONFIG_ATARI_DSP56K
+  fi
 fi
 if [ "$CONFIG_AMIGA" = "y" ]; then
   tristate 'Amiga builtin serial support' CONFIG_AMIGA_BUILTIN_SERIAL
-  bool 'GVP IO-Extender support' CONFIG_GVPIOEXT
+  tristate 'GVP IO-Extender support' CONFIG_GVPIOEXT
+  dep_tristate 'GVP IO-Extender parallel printer support' CONFIG_GVPIOEXT_LP $CONFIG_GVPIOEXT
+  dep_tristate 'GVP IO-Extender PLIP support' CONFIG_GVPIOEXT_PLIP $CONFIG_GVPIOEXT
   tristate 'Multiface Card III serial support' CONFIG_MULTIFACE_III_TTY
 fi
+if [ "$CONFIG_ATARI_MFPSER" = "y" -o "$CONFIG_ATARI_SCC" = "y" -o \
+     "$CONFIG_ATARI_MIDI" = "y" -o "$CONFIG_AMIGA_BUILTIN_SERIAL" = "y" -o \
+     "$CONFIG_GVPIOEXT" = "y" -o "$CONFIG_MULTIFACE_III_TTY" = "y" ]; then
+  bool 'Serial console support' CONFIG_SERIAL_CONSOLE
+fi
 bool 'Support for user serial device modules' CONFIG_USERIAL
 bool 'Watchdog Timer Support'	CONFIG_WATCHDOG
 if [ "$CONFIG_WATCHDOG" != "n" ]; then
@@ -228,6 +251,9 @@
   bool '   Software Watchdog' CONFIG_SOFT_WATCHDOG
 fi
 bool 'Support for user misc device modules' CONFIG_UMISC
+if [ "$CONFIG_AMIGA" = "y" -o "$CONFIG_ATARI" = "y" ]; then
+  define_bool CONFIG_ABSTRACT_CONSOLE y
+fi
 endmenu
 
 mainmenu_option next_comment
@@ -247,4 +273,5 @@
 if [ "$CONFIG_PROFILE" = "y" ]; then
   int ' Profile shift count' CONFIG_PROFILE_SHIFT 2
 fi
+bool 'Remote debugging support' CONFIG_KGDB
 endmenu
diff -u --recursive --new-file v2.1.35/linux/arch/m68k/console/fbcon.c linux/arch/m68k/console/fbcon.c
--- v2.1.35/linux/arch/m68k/console/fbcon.c	Fri Dec 20 01:19:58 1996
+++ linux/arch/m68k/console/fbcon.c	Thu Apr 17 13:20:42 1997
@@ -61,7 +61,7 @@
 #endif
 #ifdef CONFIG_FB_CYBER
 #include "../amiga/s3blit.h"
-#endif /* CONFIG_FB_CYBER */
+#endif
 #include <linux/fb.h>
 #include <asm/font.h>
 #include <asm/machdep.h>
@@ -70,7 +70,7 @@
 #include <asm/uaccess.h>
 
 #include "../../../drivers/char/vt_kern.h"   /* vt_cons and vc_resize_con() */
-
+#include "../../../drivers/char/console_struct.h"
 
 /* Import console_blanked from console.c */
 
@@ -95,6 +95,7 @@
 #undef CONFIG_FBCON_24PACKED
 #undef CONFIG_FBCON_32PACKED
 #undef CONFIG_FBCON_CYBER
+#undef CONFIG_FBCON_RETINAZ3
 
 
 /* Monochrome is default */
@@ -117,7 +118,18 @@
 #ifndef CONFIG_FBCON_CYBER
 #define CONFIG_FBCON_CYBER
 #endif
-#endif /* CONFIG_FB_CYBER */
+#endif
+
+/* RetinaZ3 Graphics Board */
+
+#ifdef CONFIG_FB_RETINAZ3
+#ifndef CONFIG_FBCON_RETINAZ3
+#define CONFIG_FBCON_RETINAZ3
+#endif
+#ifndef CONFIG_FBCON_8PACKED
+#define CONFIG_FBCON_8PACKED
+#endif
+#endif
 
 #endif /* CONFIG_AMIGA */
 
@@ -151,9 +163,9 @@
 #undef CONFIG_FBCON_IPLAN2
 #endif
 
-#if defined(CONFIG_FBCON_CYBER) || defined(CONFIG_FBCON_8PACKED) || \
-    defined(CONFIG_FBCON_16PACKED) || defined(CONFIG_FBCON_24PACKED) || \
-    defined(CONFIG_FBCON_32PACKED)
+#if defined(CONFIG_FBCON_CYBER) || defined(CONFIG_FBCON_RETINAZ3) || \
+    defined(CONFIG_FBCON_8PACKED) || defined(CONFIG_FBCON_16PACKED) || \
+    defined(CONFIG_FBCON_24PACKED) || defined(CONFIG_FBCON_32PACKED)
 #define CONFIG_FBCON_PACKED
 #else
 #undef CONFIG_FBCON_PACKED
@@ -224,21 +236,24 @@
     *    Interface used by the world
     */
 
-static u_long fbcon_startup(u_long kmem_start, char **display_desc);
+static u_long fbcon_startup(u_long kmem_start, const char **display_desc);
 static void fbcon_init(struct vc_data *conp);
 static int fbcon_deinit(struct vc_data *conp);
 static int fbcon_changevar(int con);
 static int fbcon_clear(struct vc_data *conp, int sy, int sx, int height,
                        int width);
-static int fbcon_putc(struct vc_data *conp, int c, int y, int x);
-static int fbcon_putcs(struct vc_data *conp, const char *s, int count, int y,
-                       int x);
+static int fbcon_putc(struct vc_data *conp, int c, int yy, int xx);
+static int fbcon_putcs(struct vc_data *conp, const char *s, int count, int yy,
+                       int xx);
 static int fbcon_cursor(struct vc_data *conp, int mode);
 static int fbcon_scroll(struct vc_data *conp, int t, int b, int dir, int count);
 static int fbcon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx,
                        int height, int width);
 static int fbcon_switch(struct vc_data *conp);
 static int fbcon_blank(int blank);
+static int fbcon_get_font(struct vc_data *conp, int *w, int *h, char *data);
+static int fbcon_set_font(struct vc_data *conp, int w, int h, char *data);
+static int fbcon_set_palette(struct vc_data *conp, unsigned char *table);
 
 
    /*
@@ -264,14 +279,22 @@
                                       u_long val2, u_long val3, u_long val4);
 static __inline__ void memmove_8p_col(void *d, void *s, int h, int bpr);
 static __inline__ void expand8dl(u_char c, u_long *ret1, u_long *ret2);
-static __inline__ void memclear_2p_col(void *d, size_t h, u_short val, int bpr);
+static __inline__ void memclear_2p_col(void *d, size_t h, u_short val,
+				       int bpr);
 static __inline__ void memset_even_2p(void *d, size_t count, u_long val);
 static __inline__ void memmove_2p_col(void *d, void *s, int h, int bpr);
 static __inline__ u_short expand2w(u_char c);
 static __inline__ u_long expand2l(u_char c);
 static __inline__ u_short dup2w(u_char c);
-static __inline__ int real_y(struct display *p, int y);
+static __inline__ int real_y(struct display *p, int yy);
 static void fbcon_vbl_handler(int irq, void *dummy, struct pt_regs *fp);
+static __inline__ void updatescrollmode(struct display *p);
+static __inline__ void ywrap_up(int unit, struct display *p, int count);
+static __inline__ void ywrap_down(int unit, struct display *p, int count);
+static __inline__ void ypan_up(int unit, struct vc_data *conp,
+			       struct display *p, int count);
+static __inline__ void ypan_down(int unit, struct vc_data *conp,
+				 struct display *p, int count);
 static void fbcon_bmove_rec(struct display *p, int sy, int sx, int dy, int dx,
                             int height, int width, u_int y_break);
 
@@ -285,11 +308,11 @@
                        int height, int width);
 static void clear_mono(struct vc_data *conp, struct display *p, int sy, int sx,
                        int height, int width);
-static void putc_mono(struct vc_data *conp, struct display *p, int c, int y,
-                      int x);
+static void putc_mono(struct vc_data *conp, struct display *p, int c, int yy,
+                      int xx);
 static void putcs_mono(struct vc_data *conp, struct display *p, const char *s,
-                       int count, int y, int x);
-static void rev_char_mono(struct display *p, int x, int y);
+                       int count, int yy, int xx);
+static void rev_char_mono(struct display *p, int xx, int yy);
 #endif /* CONFIG_FBCON_MONO */
 
 
@@ -302,11 +325,11 @@
                        int height, int width);
 static void clear_ilbm(struct vc_data *conp, struct display *p, int sy, int sx,
                        int height, int width);
-static void putc_ilbm(struct vc_data *conp, struct display *p, int c, int y,
-                      int x);
+static void putc_ilbm(struct vc_data *conp, struct display *p, int c, int yy,
+                      int xx);
 static void putcs_ilbm(struct vc_data *conp, struct display *p, const char *s,
-                       int count, int y, int x);
-static void rev_char_ilbm(struct display *p, int x, int y);
+                       int count, int yy, int xx);
+static void rev_char_ilbm(struct display *p, int xx, int yy);
 #endif /* CONFIG_FBCON_ILBM */
 
 
@@ -319,11 +342,11 @@
                        int height, int width);
 static void clear_plan(struct vc_data *conp, struct display *p, int sy, int sx,
                        int height, int width);
-static void putc_plan(struct vc_data *conp, struct display *p, int c, int y,
-                      int x);
+static void putc_plan(struct vc_data *conp, struct display *p, int c, int yy,
+                      int xx);
 static void putcs_plan(struct vc_data *conp, struct display *p, const char *s,
-                       int count, int y, int x);
-static void rev_char_plan(struct display *p, int x, int y);
+                       int count, int yy, int xx);
+static void rev_char_plan(struct display *p, int xx, int yy);
 #endif /* CONFIG_FBCON_PLANES */
 
 
@@ -336,11 +359,11 @@
                           int height, int width);
 static void clear_2_plane(struct vc_data *conp, struct display *p, int sy,
                           int sx, int height, int width);
-static void putc_2_plane(struct vc_data *conp, struct display *p, int c, int y,
-                         int x);
+static void putc_2_plane(struct vc_data *conp, struct display *p, int c, int yy,
+                         int xx);
 static void putcs_2_plane(struct vc_data *conp, struct display *p,
-                          const char *s, int count, int y, int x);
-static void rev_char_2_plane(struct display *display, int x, int y);
+                          const char *s, int count, int yy, int xx);
+static void rev_char_2_plane(struct display *display, int xx, int yy);
 #endif /* CONFIG_FBCON_2PLANE */
 
 
@@ -353,11 +376,11 @@
                           int height, int width);
 static void clear_4_plane(struct vc_data *conp, struct display *p, int sy,
                           int sx, int height, int width);
-static void putc_4_plane(struct vc_data *conp, struct display *p, int c, int y,
-                         int x);
+static void putc_4_plane(struct vc_data *conp, struct display *p, int c, int yy,
+                         int xx);
 static void putcs_4_plane(struct vc_data *conp, struct display *p,
-                          const char *s, int count, int y, int x);
-static void rev_char_4_plane(struct display *p, int x, int y);
+                          const char *s, int count, int yy, int xx);
+static void rev_char_4_plane(struct display *p, int xx, int yy);
 #endif /* CONFIG_FBCON_4PLANE */
 
 
@@ -370,11 +393,11 @@
                           int height, int width);
 static void clear_8_plane(struct vc_data *conp, struct display *p, int sy,
                           int sx, int height, int width);
-static void putc_8_plane(struct vc_data *conp, struct display *p, int c, int y,
-                         int x);
+static void putc_8_plane(struct vc_data *conp, struct display *p, int c, int yy,
+                         int xx);
 static void putcs_8_plane(struct vc_data *conp, struct display *p,
-                          const char *s, int count, int y, int x);
-static void rev_char_8_plane(struct display *display, int x, int y);
+                          const char *s, int count, int yy, int xx);
+static void rev_char_8_plane(struct display *display, int xx, int yy);
 #endif /* CONFIG_FBCON_8PLANE */
 
 
@@ -387,11 +410,11 @@
                            int height, int width);
 static void clear_8_packed(struct vc_data *conp, struct display *p, int sy,
                            int sx, int height, int width);
-static void putc_8_packed(struct vc_data *conp, struct display *p, int c, int y,
-                          int x);
+static void putc_8_packed(struct vc_data *conp, struct display *p, int c, int yy,
+                          int xx);
 static void putcs_8_packed(struct vc_data *conp, struct display *p,
-                           const char *s, int count, int y, int x);
-static void rev_char_8_packed(struct display *p, int x, int y);
+                           const char *s, int count, int yy, int xx);
+static void rev_char_8_packed(struct display *p, int xx, int yy);
 #endif /* CONFIG_FBCON_8PACKED */
 
 
@@ -405,10 +428,10 @@
 static void clear_16_packed(struct vc_data *conp, struct display *p, int sy,
                             int sx, int height, int width);
 static void putc_16_packed(struct vc_data *conp, struct display *p, int c,
-                           int y, int x);
+                           int yy, int xx);
 static void putcs_16_packed(struct vc_data *conp, struct display *p,
-                            const char *s, int count, int y, int x);
-static void rev_char_16_packed(struct display *p, int x, int y);
+                            const char *s, int count, int yy, int xx);
+static void rev_char_16_packed(struct display *p, int xx, int yy);
 #endif */ CONFIG_FBCON_8PACKED */
 
 
@@ -421,22 +444,38 @@
                         int height, int width);
 static void clear_cyber(struct vc_data *conp, struct display *p, int sy, int sx,
                         int height, int width);
-static void putc_cyber(struct vc_data *conp, struct display *p, int c, int y,
-                       int x);
+static void putc_cyber(struct vc_data *conp, struct display *p, int c, int yy,
+                       int xx);
 static void putcs_cyber(struct vc_data *conp, struct display *p, const char *s,
-                        int count, int y, int x);
-static void rev_char_cyber(struct display *p, int x, int y);
+                        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_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 x, u_short y, u_short width, u_short height,
+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 x, u_short y);
+extern void Cyber_MoveCursor(u_short xx, u_short yy);
 #endif /* CONFIG_FBCON_CYBER */
 
+#ifdef CONFIG_FBCON_RETINAZ3
+static void clear_retz3(struct vc_data *conp, struct display *p, int
+			sy, int sx, int height, int width);
+static void bmove_retz3(struct display *p, int sy, int sx, int dy, int dx,
+                        int height, int width);
+extern void retz3_bitblt(struct fb_var_screeninfo *scr,
+			 unsigned short srcx, unsigned short srcy, unsigned
+			 short destx, unsigned short desty, unsigned short
+			 width, unsigned short height, unsigned short cmd,
+			 unsigned short mask);
+static void putc_retz3(struct vc_data *conp, struct display *p, int c,
+		       int yy, int xx);
+static void putcs_retz3(struct vc_data *conp, struct display *p, const
+			char *s, int count, int yy, int xx);
+static void rev_char_retz3(struct display *p, int xx, int yy);
+#endif
 
    /*
     *    `switch' for the Low Level Operations
@@ -447,10 +486,10 @@
                   int width);
     void (*clear)(struct vc_data *conp, struct display *p, int sy, int sx,
                   int height, int width);
-    void (*putc)(struct vc_data *conp, struct display *p, int c, int y, int x);
+    void (*putc)(struct vc_data *conp, struct display *p, int c, int yy, int xx);
     void (*putcs)(struct vc_data *conp, struct display *p, const char *s,
-                  int count, int y, int x);
-    void (*rev_char)(struct display *p, int x, int y);
+                  int count, int yy, int xx);
+    void (*rev_char)(struct display *p, int xx, int yy);
 };
 
 
@@ -509,8 +548,15 @@
 };
 #endif /* CONFIG_FBCON_CYBER */
 
+#ifdef CONFIG_FBCON_RETINAZ3
+static struct display_switch dispsw_retz3 = {
+   bmove_retz3, clear_retz3, putc_retz3,
+   putcs_retz3, rev_char_retz3
+};
+#endif
+
 
-static u_long fbcon_startup(u_long kmem_start, char **display_desc)
+static u_long fbcon_startup(u_long kmem_start, const char **display_desc)
 {
    int irqres = 0;
 
@@ -566,6 +612,19 @@
 }
 
 
+static __inline__ void updatescrollmode(struct display *p)
+{
+   if (divides(p->ywrapstep, p->fontheight) &&
+       divides(p->fontheight, p->var.yres_virtual))
+      p->scrollmode = SCROLL_YWRAP;
+   else if (divides(p->ypanstep, p->fontheight) &&
+            p->var.yres_virtual >= p->var.yres+p->fontheight)
+      p->scrollmode = SCROLL_YPAN;
+   else
+      p->scrollmode = SCROLL_YMOVE;
+}
+
+
 static void fbcon_setup(int con, int setcol, int init)
 {
    struct display *p = &disp[con];
@@ -579,16 +638,12 @@
                      &p->fontdata) || p->fontwidth != 8)
 	   getdefaultfont(p->var.xres, p->var.yres, NULL, &p->fontwidth,
 	                  &p->fontheight, &p->fontdata);
-   if (p->fontwidth != 8)
-      panic("fbcon_setup: No support for fontwidth != 8");
-
-   if (divides(p->ywrapstep, p->fontheight) && divides(p->fontheight, p->var.yres_virtual))
-      p->scrollmode = SCROLL_YWRAP;
-   else if (divides(p->ypanstep, p->fontheight) &&
-            p->var.yres_virtual >= p->var.yres+p->fontheight)
-      p->scrollmode = SCROLL_YPAN;
-   else
-      p->scrollmode = SCROLL_YMOVE;
+   if (p->fontwidth != 8) {
+      /* ++Geert: changed from panic() to `correct and continue' */
+      printk("fbcon_setup: No support for fontwidth != 8");
+      p->fontwidth = 8;
+   }
+   updatescrollmode(p);
 
    nr_cols = p->var.xres/p->fontwidth;
    nr_rows = p->var.yres/p->fontheight;
@@ -638,7 +693,8 @@
    if (p->type == FB_TYPE_INTERLEAVED_PLANES && p->type_aux != 2) {
       if (p->line_length) {
          p->next_line = p->line_length*p->var.bits_per_pixel;
-         p->next_plane = p->line_length;
+         p->next_plane = p->line_length
+;
       } else {
          p->next_line = p->type_aux;
          p->next_plane = p->type_aux/p->var.bits_per_pixel;
@@ -658,13 +714,18 @@
 #endif /* CONFIG_FBCON_PLANES */
 #ifdef CONFIG_FBCON_PACKED
    if (p->type == FB_TYPE_PACKED_PIXELS) {
-      p->next_line = p->var.xres_virtual*p->var.bits_per_pixel>>3;
+      p->next_line = (p->var.xres_virtual*p->var.bits_per_pixel)>>3;
       p->next_plane = 0;
 #ifdef CONFIG_FBCON_CYBER
       if (p->var.accel == FB_ACCEL_CYBERVISION)
          p->dispsw = &dispsw_cyber;
       else
-#endif /* CONFIG_FBCON_CYBER */
+#endif
+#ifdef CONFIG_FBCON_RETINAZ3
+      if (p->var.accel == FB_ACCEL_RETINAZ3)
+         p->dispsw = &dispsw_retz3;
+      else
+#endif
 #ifdef CONFIG_FBCON_8PACKED
       if (p->var.bits_per_pixel == 8)
          p->dispsw = &dispsw_8_packed;
@@ -1399,12 +1460,12 @@
  * restriction is simplicity & efficiency at the moment.
  */
 
-static __inline__ int real_y(struct display *p, int y)
+static __inline__ int real_y(struct display *p, int yy)
 {
    int rows = p->vrows;
 
-   y += p->yscroll;
-   return(y < rows ? y : y-rows);
+   yy += p->yscroll;
+   return(yy < rows ? yy : yy-rows);
 }
 
 
@@ -1436,7 +1497,7 @@
 }
 
 
-static int fbcon_putc(struct vc_data *conp, int c, int y, int x)
+static int fbcon_putc(struct vc_data *conp, int c, int yy, int xx)
 {
    int unit = conp->vc_num;
    struct display *p = &disp[unit];
@@ -1444,17 +1505,17 @@
    if (!p->can_soft_blank && console_blanked)
       return(0);
 
-   if ((p->cursor_x == x) && (p->cursor_y == y))
+   if ((p->cursor_x == xx) && (p->cursor_y == yy))
        CURSOR_UNDRAWN();
 
-   p->dispsw->putc(conp, p, c, real_y(p, y), x);
+   p->dispsw->putc(conp, p, c, real_y(p, yy), xx);
 
    return(0);
 }
 
 
-static int fbcon_putcs(struct vc_data *conp, const char *s, int count, int y,
-                       int x)
+static int fbcon_putcs(struct vc_data *conp, const char *s, int count, int yy,
+                       int xx)
 {
    int unit = conp->vc_num;
    struct display *p = &disp[unit];
@@ -1462,10 +1523,10 @@
    if (!p->can_soft_blank && console_blanked)
       return(0);
 
-   if ((p->cursor_y == y) && (x <= p->cursor_x) && (p->cursor_x < x+count))
+   if ((p->cursor_y == yy) && (xx <= p->cursor_x) && (p->cursor_x < xx+count))
       CURSOR_UNDRAWN();
 
-   p->dispsw->putcs(conp, p, s, count, real_y(p, y), x);
+   p->dispsw->putcs(conp, p, s, count, real_y(p, yy), xx);
 
    return(0);
 }
@@ -1520,6 +1581,62 @@
 }
 
 
+static __inline__ void ywrap_up(int unit, struct display *p, int count)
+{
+   p->yscroll += count;
+   if (p->yscroll >= p->vrows)	/* Deal with wrap */
+      p->yscroll -= p->vrows;
+   p->var.xoffset = 0;
+   p->var.yoffset = p->yscroll*p->fontheight;
+   p->var.vmode |= FB_VMODE_YWRAP;
+   fb_info->updatevar(unit);
+}
+
+
+static __inline__ void ywrap_down(int unit, struct display *p, int count)
+{
+   p->yscroll -= count;
+   if (p->yscroll < 0)		/* Deal with wrap */
+      p->yscroll += p->vrows;
+   p->var.xoffset = 0;
+   p->var.yoffset = p->yscroll*p->fontheight;
+   p->var.vmode |= FB_VMODE_YWRAP;
+   fb_info->updatevar(unit);
+}
+
+
+static __inline__ void ypan_up(int unit, struct vc_data *conp,
+			       struct display *p, int count)
+{
+   p->yscroll += count;
+   if (p->yscroll+conp->vc_rows > p->vrows) {
+      p->dispsw->bmove(p, p->yscroll, 0, 0, 0, conp->vc_rows-count,
+		       conp->vc_cols);
+      p->yscroll = 0;
+   }
+   p->var.xoffset = 0;
+   p->var.yoffset = p->yscroll*p->fontheight;
+   p->var.vmode &= ~FB_VMODE_YWRAP;
+   fb_info->updatevar(unit);
+}
+
+
+static __inline__ void ypan_down(int unit, struct vc_data *conp,
+				 struct display *p, int count)
+{
+   p->yscroll -= count;
+   if (p->yscroll < 0) {
+      p->yscroll = p->vrows-conp->vc_rows;
+      p->dispsw->bmove(p, 0, 0, p->yscroll+count, 0, conp->vc_rows-count,
+		       conp->vc_cols);
+   }
+   p->var.xoffset = 0;
+   p->var.yoffset = p->yscroll*p->fontheight;
+   p->var.vmode &= ~FB_VMODE_YWRAP;
+   fb_info->updatevar(unit);
+}
+
+
 static int fbcon_scroll(struct vc_data *conp, int t, int b, int dir, int count)
 {
    int unit = conp->vc_num;
@@ -1536,84 +1653,98 @@
 
    switch (dir) {
       case SM_UP:
-         if (t == 0 && b == conp->vc_rows &&
-             vt_cons[unit]->vc_mode == KD_TEXT) {
-            if (count > conp->vc_rows)             /* Maximum realistic size */
-               count = conp->vc_rows;
-            switch (p->scrollmode) {
-               case SCROLL_YWRAP:
-                  p->yscroll += count;
-                  if (p->yscroll >= p->vrows) /* Deal with wrap */
-                     p->yscroll -= p->vrows;
-                  p->var.xoffset = 0;
-                  p->var.yoffset = p->yscroll*p->fontheight;
-                  p->var.vmode |= FB_VMODE_YWRAP;
-                  fb_info->updatevar(unit);
-                  break;
-
-               case SCROLL_YPAN:
-                  p->yscroll += count;
-                  if (p->yscroll+conp->vc_rows > p->vrows) {
-                     p->dispsw->bmove(p, p->yscroll, 0, 0, 0, b-count,
-                                      conp->vc_cols);
-                     p->yscroll = 0;
-                  }
-                  p->var.xoffset = 0;
-                  p->var.yoffset = p->yscroll*p->fontheight;
-                  p->var.vmode &= ~FB_VMODE_YWRAP;
-                  fb_info->updatevar(unit);
-                  break;
-
-               case SCROLL_YMOVE:
-                  p->dispsw->bmove(p, count, 0, 0, 0, b-count, conp->vc_cols);
-                  break;
-            }
-         } else
-            fbcon_bmove(conp, t+count, 0, t, 0, b-t-count, conp->vc_cols);
-         fbcon_clear(conp, b-count, 0, count, conp->vc_cols);
+	 if (count > conp->vc_rows)	/* Maximum realistic size */
+	    count = conp->vc_rows;
+	 if (vt_cons[unit]->vc_mode == KD_TEXT)
+	    switch (p->scrollmode) {
+	       case SCROLL_YWRAP:
+		  if (b-t-count > 3*conp->vc_rows>>2) {
+		     if (t > 0)
+			fbcon_bmove(conp, 0, 0, count, 0, t, conp->vc_cols);
+		     ywrap_up(unit, p, count);
+		     if (conp->vc_rows-b > 0)
+			fbcon_bmove(conp, b-count, 0, b, 0, conp->vc_rows-b,
+				    conp->vc_cols);
+		  } else
+		     fbcon_bmove(conp, t+count, 0, t, 0, b-t-count,
+				 conp->vc_cols);
+		  fbcon_clear(conp, b-count, 0, count, conp->vc_cols);
+		  break;
+
+	       case SCROLL_YPAN:
+		  if (b-t-count > 3*conp->vc_rows>>2) {
+		     if (t > 0)
+			fbcon_bmove(conp, 0, 0, count, 0, t, conp->vc_cols);
+		     ypan_up(unit, conp, p, count);
+		     if (conp->vc_rows-b > 0)
+			fbcon_bmove(conp, b-count, 0, b, 0, conp->vc_rows-b,
+				    conp->vc_cols);
+		  } else
+		     fbcon_bmove(conp, t+count, 0, t, 0, b-t-count,
+				 conp->vc_cols);
+		  fbcon_clear(conp, b-count, 0, count, conp->vc_cols);
+		  break;
+
+	       case SCROLL_YMOVE:
+		  p->dispsw->bmove(p, t+count, 0, t, 0, b-t-count,
+				   conp->vc_cols);
+		  p->dispsw->clear(conp, p, b-count, 0, count, conp->vc_cols);
+		  break;
+	    }
+	 else {
+	    fbcon_bmove(conp, t+count, 0, t, 0, b-t-count, conp->vc_cols);
+	    fbcon_clear(conp, b-count, 0, count, conp->vc_cols);
+	 }
          break;
 
       case SM_DOWN:
-         if (t == 0 && b == conp->vc_rows &&
-             vt_cons[unit]->vc_mode == KD_TEXT) {
-            if (count > conp->vc_rows)             /* Maximum realistic size */
-               count = conp->vc_rows;
-            switch (p->scrollmode) {
-               case SCROLL_YWRAP:
-                  p->yscroll -= count;
-                  if (p->yscroll < 0)              /* Deal with wrap */
-                     p->yscroll += p->vrows;
-                  p->var.xoffset = 0;
-                  p->var.yoffset = p->yscroll*p->fontheight;
-                  p->var.vmode |= FB_VMODE_YWRAP;
-                  fb_info->updatevar(unit);
-                  break;
-
-               case SCROLL_YPAN:
-                  p->yscroll -= count;
-                  if (p->yscroll < 0) {
-                     p->yscroll = p->vrows-conp->vc_rows;
-                     p->dispsw->bmove(p, 0, 0, p->yscroll+count, 0, b-count,
-                                      conp->vc_cols);
-                  }
-                  p->var.xoffset = 0;
-                  p->var.yoffset = p->yscroll*p->fontheight;
-                  p->var.vmode &= ~FB_VMODE_YWRAP;
-                  fb_info->updatevar(unit);
-                  break;
-
-               case SCROLL_YMOVE:
-                  p->dispsw->bmove(p, 0, 0, count, 0, b-count, conp->vc_cols);
-                  break;
-            }
-         } else
-            fbcon_bmove(conp, t, 0, t+count, 0, b-t-count, conp->vc_cols);
-
-         /* Fixed bmove() should end Arno's frustration with copying?
-          * Confucius says:
-          *    Man who copies in wrong direction, end up with trashed data
-          */
-         fbcon_clear(conp, t, 0, count, conp->vc_cols);
+	 if (count > conp->vc_rows)	/* Maximum realistic size */
+	    count = conp->vc_rows;
+	 if (vt_cons[unit]->vc_mode == KD_TEXT)
+	    switch (p->scrollmode) {
+	       case SCROLL_YWRAP:
+		  if (b-t-count > 3*conp->vc_rows>>2) {
+		     if (conp->vc_rows-b > 0)
+			fbcon_bmove(conp, b, 0, b-count, 0, conp->vc_rows-b,
+				    conp->vc_cols);
+		     ywrap_down(unit, p, count);
+		     if (t > 0)
+			fbcon_bmove(conp, count, 0, 0, 0, t, conp->vc_cols);
+		  } else
+		     fbcon_bmove(conp, t, 0, t+count, 0, b-t-count,
+				 conp->vc_cols);
+		  fbcon_clear(conp, t, 0, count, conp->vc_cols);
+		  break;
+
+	       case SCROLL_YPAN:
+		  if (b-t-count > 3*conp->vc_rows>>2) {
+		     if (conp->vc_rows-b > 0)
+			fbcon_bmove(conp, b, 0, b-count, 0, conp->vc_rows-b,
+				    conp->vc_cols);
+		     ypan_down(unit, conp, p, count);
+		     if (t > 0)
+			fbcon_bmove(conp, count, 0, 0, 0, t, conp->vc_cols);
+		  } else
+		     fbcon_bmove(conp, t, 0, t+count, 0, b-t-count,
+				 conp->vc_cols);
+		  fbcon_clear(conp, t, 0, count, conp->vc_cols);
+		  break;
+
+	       case SCROLL_YMOVE:
+		  p->dispsw->bmove(p, t, 0, t+count, 0, b-t-count,
+				   conp->vc_cols);
+		  p->dispsw->clear(conp, p, t, 0, count, conp->vc_cols);
+		  break;
+	    }
+	 else {
+	    /*
+	     * Fixed bmove() should end Arno's frustration with copying?
+	     * Confucius says:
+	     *    Man who copies in wrong direction, end up with trashed data
+	     */
+	    fbcon_bmove(conp, t, 0, t+count, 0, b-t-count, conp->vc_cols);
+	    fbcon_clear(conp, t, 0, count, conp->vc_cols);
+	 }
          break;
 
       case SM_LEFT:
@@ -1832,14 +1963,7 @@
 		/* Adjust the virtual screen-size to fontheight*rows */
 		p->var.yres_virtual = (p->var.yres/h)*h;
 		p->vrows = p->var.yres_virtual/h;
-		if (divides(p->ywrapstep, p->fontheight))
-			p->scrollmode = SCROLL_YWRAP;
-		else if (divides(p->ypanstep, p->fontheight) &&
-				 p->var.yres_virtual >= p->var.yres+p->fontheight)
-			p->scrollmode = SCROLL_YPAN;
-		else
-			p->scrollmode = SCROLL_YMOVE;
-
+		updatescrollmode(p);
 		vc_resize_con( p->var.yres/h, p->var.xres/w, unit );
 	}
 	else if (unit == fg_console)
@@ -1854,6 +1978,38 @@
 	return( 0 );
 }
 
+static unsigned short palette_red[16];
+static unsigned short palette_green[16];
+static unsigned short palette_blue[16];
+
+static struct fb_cmap palette_cmap  = {
+    0, 16, palette_red, palette_green, palette_blue, NULL
+};
+
+static int fbcon_set_palette(struct vc_data *conp, unsigned char *table)
+{
+    int unit = conp->vc_num;
+    struct display *p = &disp[unit];
+    int i, j, k;
+    u_char val;
+
+    if (!conp->vc_can_do_color || (!p->can_soft_blank && console_blanked))
+	return(-EINVAL);
+    for (i = j = 0; i < 16; i++) {
+	k = table[i];
+	val = conp->vc_palette[j++];
+	palette_red[k] = (val<<8)|val;
+	val = conp->vc_palette[j++];
+	palette_green[k] = (val<<8)|val;
+	val = conp->vc_palette[j++];
+	palette_blue[k] = (val<<8)|val;
+    }
+    palette_cmap.len = 1<<p->var.bits_per_pixel;
+    if (palette_cmap.len > 16)
+	palette_cmap.len = 16;
+    return(fb_info->setcmap(&palette_cmap, unit));
+}
+
 
 /* ====================================================================== */
 
@@ -1882,8 +2038,8 @@
    u_char *src, *dest;
    u_int rows;
 
-   if (sx == 0 && sy == 0 && width == p->next_line) {
-      src = p->screen_base;
+   if (sx == 0 && dx == 0 && width == p->next_line) {
+      src = p->screen_base+sy*p->fontheight*width;
       dest = p->screen_base+dy*p->fontheight*width;
       mymemmove(dest, src, height*p->fontheight*width);
    } else if (dy <= sy) {
@@ -1928,28 +2084,28 @@
 }
 
 
-static void putc_mono(struct vc_data *conp, struct display *p, int c, int y,
-                      int x)
+static void putc_mono(struct vc_data *conp, struct display *p, int c, int yy,
+                      int xx)
 {
    u_char *dest, *cdat;
-   u_int rows, bold, reverse, underline;
+   u_int rows, bold, revs, underl;
    u_char d;
 
    c &= 0xff;
 
-   dest = p->screen_base+y*p->fontheight*p->next_line+x;
+   dest = p->screen_base + yy*p->fontheight*p->next_line + xx;
    cdat = p->fontdata+c*p->fontheight;
    bold = attr_bold(p,conp);
-   reverse = attr_reverse(p,conp);
-   underline = attr_underline(p,conp);
+   revs = attr_reverse(p,conp);
+   underl = attr_underline(p,conp);
 
    for (rows = p->fontheight; rows--; dest += p->next_line) {
       d = *cdat++;
-      if (underline && !rows)
+      if (underl && !rows)
          d = 0xff;
       else if (bold)
          d |= d>>1;
-      if (reverse)
+      if (revs)
          d = ~d;
       *dest = d;
    }
@@ -1957,16 +2113,16 @@
 
 
 static void putcs_mono(struct vc_data *conp, struct display *p, const char *s,
-                       int count, int y, int x)
+                       int count, int yy, int xx)
 {
    u_char *dest, *dest0, *cdat;
-   u_int rows, bold, reverse, underline;
+   u_int rows, bold, revs, underl;
    u_char c, d;
 
-   dest0 = p->screen_base+y*p->fontheight*p->next_line+x;
+   dest0 = p->screen_base + yy*p->fontheight*p->next_line + xx;
    bold = attr_bold(p,conp);
-   reverse = attr_reverse(p,conp);
-   underline = attr_underline(p,conp);
+   revs = attr_reverse(p,conp);
+   underl = attr_underline(p,conp);
 
    while (count--) {
       c = *s++;
@@ -1974,11 +2130,11 @@
       cdat = p->fontdata+c*p->fontheight;
       for (rows = p->fontheight; rows--; dest += p->next_line) {
          d = *cdat++;
-         if (underline && !rows)
+         if (underl && !rows)
             d = 0xff;
          else if (bold)
             d |= d>>1;
-         if (reverse)
+         if (revs)
             d = ~d;
          *dest = d;
       }
@@ -1986,12 +2142,12 @@
 }
 
 
-static void rev_char_mono(struct display *p, int x, int y)
+static void rev_char_mono(struct display *p, int xx, int yy)
 {
    u_char *dest;
    u_int rows;
 
-   dest = p->screen_base+y*p->fontheight*p->next_line+x;
+   dest = p->screen_base + yy*p->fontheight*p->next_line + xx;
    for (rows = p->fontheight; rows--; dest += p->next_line)
       *dest = ~*dest;
 }
@@ -2017,8 +2173,9 @@
 static void bmove_ilbm(struct display *p, int sy, int sx, int dy, int dx,
                        int height, int width)
 {
-   if (sx == 0 && sy == 0 && width == p->next_plane)
-      mymemmove(p->screen_base+dy*p->fontheight*p->next_line, p->screen_base,
+   if (sx == 0 && dx == 0 && width == p->next_plane)
+      mymemmove(p->screen_base+dy*p->fontheight*p->next_line,
+		p->screen_base+sy*p->fontheight*p->next_line,
                 height*p->fontheight*p->next_line);
    else {
       u_char *src, *dest;
@@ -2068,8 +2225,8 @@
 }
 
 
-static void putc_ilbm(struct vc_data *conp, struct display *p, int c, int y,
-                      int x)
+static void putc_ilbm(struct vc_data *conp, struct display *p, int c, int yy,
+                      int xx)
 {
    u_char *dest, *cdat;
    u_int rows, i;
@@ -2078,7 +2235,7 @@
 
    c &= 0xff;
 
-   dest = p->screen_base+y*p->fontheight*p->next_line+x;
+   dest = p->screen_base + yy*p->fontheight*p->next_line + xx;
    cdat = p->fontdata+c*p->fontheight;
    fg0 = attr_fgcol(p,conp);
    bg0 = attr_bgcol(p,conp);
@@ -2114,14 +2271,14 @@
  *                      address, to reduce the number of expensive Chip RAM
  *                      accesses.
  *
- *    Experiments on my A4000/040 revealed that this makes a console switch on a
- *    640x400 screen with 256 colors about 3 times faster.
+ *    Experiments on my A4000/040 revealed that this makes a console
+ *    switch on a 640x400 screen with 256 colors about 3 times faster.
  *
  *                                                                Geert
  */
 
 static void putcs_ilbm(struct vc_data *conp, struct display *p, const char *s,
-                       int count, int y, int x)
+                       int count, int yy, int xx)
 {
    u_char *dest0, *dest, *cdat1, *cdat2, *cdat3, *cdat4;
    u_int rows, i;
@@ -2129,15 +2286,15 @@
    u_long d;
    int fg0, bg0, fg, bg;
 
-   dest0 = p->screen_base+y*p->fontheight*p->next_line+x;
+   dest0 = p->screen_base + yy*p->fontheight*p->next_line + xx;
    fg0 = attr_fgcol(p,conp);
    bg0 = attr_bgcol(p,conp);
 
    while (count--)
-      if (x&3 || count < 3) {   /* Slow version */
+      if (xx & 3 || count < 3) {   /* Slow version */
          c1 = *s++;
          dest = dest0++;
-         x++;
+         xx++;
 
          cdat1 = p->fontdata+c1*p->fontheight;
          for (rows = p->fontheight; rows--;) {
@@ -2191,19 +2348,19 @@
          }
          s += 4;
          dest0 += 4;
-         x += 4;
+         xx += 4;
          count -= 3;
       }
 }
 
 
-static void rev_char_ilbm(struct display *p, int x, int y)
+static void rev_char_ilbm(struct display *p, int xx, int yy)
 {
    u_char *dest, *dest0;
    u_int rows, i;
    int mask;
 
-   dest0 = p->screen_base+y*p->fontheight*p->next_line+x;
+   dest0 = p->screen_base + yy*p->fontheight*p->next_line + xx;
    mask = p->fgcol ^ p->bgcol;
 
    /*
@@ -2239,8 +2396,8 @@
    u_char *src, *dest, *src0, *dest0;
    u_int i, rows;
 
-   if (sx == 0 && sy == 0 && width == p->next_line) {
-      src = p->screen_base;
+   if (sx == 0 && dx == 0 && width == p->next_line) {
+      src = p->screen_base+sy*p->fontheight*width;
       dest = p->screen_base+dy*p->fontheight*width;
       for (i = p->var.bits_per_pixel; i--;) {
          mymemmove(dest, src, height*p->fontheight*width);
@@ -2301,8 +2458,8 @@
 }
 
 
-static void putc_plan(struct vc_data *conp, struct display *p, int c, int y,
-                      int x)
+static void putc_plan(struct vc_data *conp, struct display *p, int c, int yy,
+                      int xx)
 {
    u_char *dest, *dest0, *cdat, *cdat0;
    u_int rows, i;
@@ -2311,7 +2468,7 @@
 
    c &= 0xff;
 
-   dest0 = p->screen_base+y*p->fontheight*p->next_line+x;
+   dest0 = p->screen_base + yy*p->fontheight*p->next_line + xx;
    cdat0 = p->fontdata+c*p->fontheight;
    fg = attr_fgcol(p,conp);
    bg = attr_bgcol(p,conp);
@@ -2344,7 +2501,7 @@
  */
 
 static void putcs_plan(struct vc_data *conp, struct display *p, const char *s,
-                       int count, int y, int x)
+                       int count, int yy, int xx)
 {
    u_char *dest, *dest0, *dest1;
    u_char *cdat1, *cdat2, *cdat3, *cdat4, *cdat10, *cdat20, *cdat30, *cdat40;
@@ -2353,15 +2510,15 @@
    u_long d;
    int fg0, bg0, fg, bg;
 
-   dest0 = p->screen_base+y*p->fontheight*p->next_line+x;
+   dest0 = p->screen_base + yy*p->fontheight*p->next_line + xx;
    fg0 = attr_fgcol(p,conp);
    bg0 = attr_bgcol(p,conp);
 
    while (count--)
-      if (x&3 || count < 3) {   /* Slow version */
+      if (xx & 3 || count < 3) {   /* Slow version */
          c1 = *s++;
          dest1 = dest0++;
-         x++;
+         xx++;
 
          cdat10 = p->fontdata+c1*p->fontheight;
          fg = fg0;
@@ -2424,19 +2581,19 @@
          }
          s += 4;
          dest0 += 4;
-         x += 4;
+         xx += 4;
          count -= 3;
       }
 }
 
 
-static void rev_char_plan(struct display *p, int x, int y)
+static void rev_char_plan(struct display *p, int xx, int yy)
 {
    u_char *dest, *dest0;
    u_int rows, i;
    int mask;
 
-   dest0 = p->screen_base+y*p->fontheight*p->next_line+x;
+   dest0 = p->screen_base + yy*p->fontheight*p->next_line + xx;
    mask = p->fgcol ^ p->bgcol;
 
    /*
@@ -2499,8 +2656,8 @@
 		 * done with memmove()
 		 */
 		mymemmove(p->screen_base + dy * p->next_line * p->fontheight,
-				   p->screen_base + sy * p->next_line * p->fontheight,
-				   p->next_line * height * p->fontheight);
+			  p->screen_base + sy * p->next_line * p->fontheight,
+			  p->next_line * height * p->fontheight);
     } else {
         int rows, cols;
         u_char *src;
@@ -2607,8 +2764,8 @@
     int bytes = p->next_line;
     int lines = height * p->fontheight;
     ulong  size;
-	u_long          cval;
-	u_short			pcval;
+    u_long          cval;
+    u_short			pcval;
 
     cval = expand2l (COLOR_2P (attr_bgcol_ec(p,conp)));
 
@@ -2650,43 +2807,45 @@
 }
 
 
-static void putc_2_plane(struct vc_data *conp, struct display *p, int c, int y,
-                         int x)
+static void putc_2_plane(struct vc_data *conp, struct display *p, int
+			 c, int yy, int xx)
 {
-   u_char   *dest;
-    u_char   *cdat;
-    int rows;
-    int bytes = p->next_line;
-	ulong			  eorx, fgx, bgx, fdx;
+	u_char   *dest;
+	u_char   *cdat;
+	int rows;
+	int bytes = p->next_line;
+	ulong    eorx, fgx, bgx, fdx;
 
 	c &= 0xff;
 
-    dest  = p->screen_base + y * p->fontheight * bytes + (x>>1)*4 + (x & 1);
-    cdat  = p->fontdata + (c * p->fontheight);
+	dest  = p->screen_base + yy * p->fontheight * bytes +
+		(xx >> 1)*4 + (xx & 1);
+	cdat  = p->fontdata + (c * p->fontheight);
 
 	fgx   = expand2w(COLOR_2P(attr_fgcol(p,conp)));
 	bgx   = expand2w(COLOR_2P(attr_bgcol(p,conp)));
 	eorx  = fgx ^ bgx;
 
-    for(rows = p->fontheight ; rows-- ; dest += bytes) {
+	for(rows = p->fontheight ; rows-- ; dest += bytes) {
 		fdx = dup2w(*cdat++);
 		__asm__ __volatile__ ("movepw %1,%0@(0)" : /* no outputs */
-							   : "a" (dest), "d" ((fdx & eorx) ^ bgx));
+				      : "a" (dest), "d" ((fdx & eorx) ^ bgx));
 	}
 }
 
 
 static void putcs_2_plane(struct vc_data *conp, struct display *p,
-                          const char *s, int count, int y, int x)
+                          const char *s, int count, int yy, int xx)
 {
 	u_char   *dest, *dest0;
-    u_char   *cdat, c;
-    int rows;
-    int bytes;
-	ulong			  eorx, fgx, bgx, fdx;
-
-    bytes = p->next_line;
-    dest0 = p->screen_base + y * p->fontheight * bytes + (x>>1)*4 + (x & 1);
+	u_char   *cdat, c;
+	int rows;
+	int bytes;
+	ulong    eorx, fgx, bgx, fdx;
+
+	bytes = p->next_line;
+	dest0 = p->screen_base + yy * p->fontheight * bytes
+		+ (xx >> 1)*4 + (xx & 1);
 	fgx   = expand2w(COLOR_2P(attr_fgcol(p,conp)));
 	bgx   = expand2w(COLOR_2P(attr_bgcol(p,conp)));
 	eorx  = fgx ^ bgx;
@@ -2699,32 +2858,33 @@
 		for(rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) {
 			fdx = dup2w(*cdat++);
 			__asm__ __volatile__ ("movepw %1,%0@(0)" : /* no outputs */
-								   : "a" (dest), "d" ((fdx & eorx) ^ bgx));
+					      : "a" (dest), "d" ((fdx & eorx) ^ bgx));
 		}
 		INC_2P(dest0);
 	}
 }
 
 
-static void rev_char_2_plane(struct display *p, int x, int y)
+static void rev_char_2_plane(struct display *p, int xx, int yy)
 {
-   u_char *dest;
-   int j;
-   int bytes;
+	u_char *dest;
+	int j;
+	int bytes;
 
-   dest = p->screen_base + y * p->fontheight * p->next_line + (x>>1)*4 + (x & 1);
-   j = p->fontheight;
-   bytes = p->next_line;
-   while (j--)
-     {
-      /* This should really obey the individual character's
-       * background and foreground colors instead of simply
-       * inverting.
-       */
-       dest[0] = ~dest[0];
-       dest[2] = ~dest[2];
-       dest += bytes;
-     }
+	dest = p->screen_base + yy * p->fontheight * p->next_line +
+		(xx >> 1)*4 + (xx & 1);
+	j = p->fontheight;
+	bytes = p->next_line;
+	while (j--)
+	{
+		/* This should really obey the individual character's
+		 * background and foreground colors instead of simply
+		 * inverting.
+		 */
+		dest[0] = ~dest[0];
+		dest[2] = ~dest[2];
+		dest += bytes;
+	}
 }
 #endif /* CONFIG_FBCON_2PLANE */
 
@@ -2763,8 +2923,8 @@
 		 * done with memmove()
 		 */
 		mymemmove(p->screen_base + dy * p->next_line * p->fontheight,
-				   p->screen_base + sy * p->next_line * p->fontheight,
-				   p->next_line * height * p->fontheight);
+			  p->screen_base + sy * p->next_line * p->fontheight,
+			  p->next_line * height * p->fontheight);
     } else {
         int rows, cols;
         u_char *src;
@@ -2871,9 +3031,9 @@
     int bytes = p->next_line;
     int lines = height * p->fontheight;
     ulong  size;
-	u_long          cval1, cval2, pcval;
+    u_long          cval1, cval2, pcval;
 
-	expand4dl(attr_bgcol_ec(p,conp), &cval1, &cval2);
+    expand4dl(attr_bgcol_ec(p,conp), &cval1, &cval2);
 
     if (sx == 0 && width == bytes/4) {
 
@@ -2913,43 +3073,45 @@
 }
 
 
-static void putc_4_plane(struct vc_data *conp, struct display *p, int c, int y,
-                         int x)
+static void putc_4_plane(struct vc_data *conp, struct display *p, int
+			 c, int yy, int xx)
 {
 	u_char   *dest;
-    u_char   *cdat;
-    int rows;
-    int bytes = p->next_line;
-	ulong			  eorx, fgx, bgx, fdx;
+	u_char   *cdat;
+	int rows;
+	int bytes = p->next_line;
+	ulong	  eorx, fgx, bgx, fdx;
 
 	c &= 0xff;
 
-    dest  = p->screen_base + y * p->fontheight * bytes + (x>>1)*8 + (x & 1);
-    cdat  = p->fontdata + (c * p->fontheight);
+	dest  = p->screen_base + yy * p->fontheight * bytes +
+		(xx >> 1)*8 + (xx & 1);
+	cdat  = p->fontdata + (c * p->fontheight);
 
 	fgx   = expand4l(attr_fgcol(p,conp));
 	bgx   = expand4l(attr_bgcol(p,conp));
 	eorx  = fgx ^ bgx;
 
-    for(rows = p->fontheight ; rows-- ; dest += bytes) {
+	for(rows = p->fontheight ; rows-- ; dest += bytes) {
 		fdx = dup4l(*cdat++);
 		__asm__ __volatile__ ("movepl %1,%0@(0)" : /* no outputs */
-							   : "a" (dest), "d" ((fdx & eorx) ^ bgx));
+				      : "a" (dest), "d" ((fdx & eorx) ^ bgx));
 	}
 }
 
 
 static void putcs_4_plane(struct vc_data *conp, struct display *p,
-                          const char *s, int count, int y, int x)
+                          const char *s, int count, int yy, int xx)
 {
 	u_char   *dest, *dest0;
-    u_char   *cdat, c;
-    int rows;
-    int bytes;
-	ulong			  eorx, fgx, bgx, fdx;
-
-    bytes = p->next_line;
-    dest0 = p->screen_base + y * p->fontheight * bytes + (x>>1)*8 + (x & 1);
+	u_char   *cdat, c;
+	int rows;
+	int bytes;
+	ulong	  eorx, fgx, bgx, fdx;
+
+	bytes = p->next_line;
+	dest0 = p->screen_base + yy * p->fontheight * bytes
+		+ (xx >> 1)*8 + (xx & 1);
 	fgx   = expand4l(attr_fgcol(p,conp));
 	bgx   = expand4l(attr_bgcol(p,conp));
 	eorx  = fgx ^ bgx;
@@ -2969,20 +3131,21 @@
 		for(rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) {
 			fdx = dup4l(*cdat++);
 			__asm__ __volatile__ ("movepl %1,%0@(0)" : /* no outputs */
-								   : "a" (dest), "d" ((fdx & eorx) ^ bgx));
+					      : "a" (dest), "d" ((fdx & eorx) ^ bgx));
 		}
 		INC_4P(dest0);
 	}
 }
 
 
-static void rev_char_4_plane(struct display *p, int x, int y)
+static void rev_char_4_plane(struct display *p, int xx, int yy)
 {
    u_char *dest;
    int j;
    int bytes;
 
-   dest = p->screen_base + y * p->fontheight * p->next_line + (x>>1)*8 + (x & 1);
+   dest = p->screen_base + yy * p->fontheight * p->next_line +
+	   (xx >> 1)*8 + (xx & 1);
    j = p->fontheight;
    bytes = p->next_line;
 
@@ -3150,15 +3313,16 @@
     int bytes = p->next_line;
     int lines = height * p->fontheight;
     ulong  size;
-	u_long          cval1, cval2, cval3, cval4, pcval1, pcval2;
+    u_long          cval1, cval2, cval3, cval4, pcval1, pcval2;
 
-	expand8ql(attr_bgcol_ec(p,conp), cval1, cval2, cval3, cval4);
+    expand8ql(attr_bgcol_ec(p,conp), cval1, cval2, cval3, cval4);
 
     if (sx == 0 && width == bytes/8) {
 
         offset = sy * bytes * p->fontheight;
         size   = lines * bytes;
-		memset_even_8p(p->screen_base+offset, size, cval1, cval2, cval3, cval4);
+		memset_even_8p(p->screen_base+offset, size, cval1,
+			       cval2, cval3, cval4);
 
     } else {
 
@@ -3193,48 +3357,50 @@
 }
 
 
-static void putc_8_plane(struct vc_data *conp, struct display *p, int c, int y,
-                         int x)
+static void putc_8_plane(struct vc_data *conp, struct display *p, int c, int yy,
+                         int xx)
 {
 	u_char   *dest;
-    u_char   *cdat;
-    int rows;
-    int bytes = p->next_line;
-	ulong			  eorx1, eorx2, fgx1, fgx2, bgx1, bgx2, fdx;
+	u_char   *cdat;
+	int rows;
+	int bytes = p->next_line;
+	ulong	  eorx1, eorx2, fgx1, fgx2, bgx1, bgx2, fdx;
 
 	c &= 0xff;
 
-    dest  = p->screen_base + y * p->fontheight * bytes + (x>>1)*16 + (x & 1);
-    cdat  = p->fontdata + (c * p->fontheight);
+	dest  = p->screen_base + yy * p->fontheight * bytes +
+		(xx >> 1)*16 + (xx & 1);
+	cdat  = p->fontdata + (c * p->fontheight);
 
 	expand8dl(attr_fgcol(p,conp), &fgx1, &fgx2);
 	expand8dl(attr_bgcol(p,conp), &bgx1, &bgx2);
 	eorx1  = fgx1 ^ bgx1; eorx2  = fgx2 ^ bgx2;
 
-    for(rows = p->fontheight ; rows-- ; dest += bytes) {
+	for(rows = p->fontheight ; rows-- ; dest += bytes) {
 		fdx = dup4l(*cdat++);
 		__asm__ __volatile__
 			("movepl %1,%0@(0)\n\t"
-			  "movepl %2,%0@(8)"
-			  : /* no outputs */
-			  : "a" (dest), "d" ((fdx & eorx1) ^ bgx1),
-			    "d" ((fdx & eorx2) ^ bgx2)
+			 "movepl %2,%0@(8)"
+			 : /* no outputs */
+			 : "a" (dest), "d" ((fdx & eorx1) ^ bgx1),
+			 "d" ((fdx & eorx2) ^ bgx2)
 			);
 	}
 }
 
 
 static void putcs_8_plane(struct vc_data *conp, struct display *p,
-                          const char *s, int count, int y, int x)
+                          const char *s, int count, int yy, int xx)
 {
 	u_char   *dest, *dest0;
-    u_char   *cdat, c;
-    int rows;
-    int bytes;
-	ulong			  eorx1, eorx2, fgx1, fgx2, bgx1, bgx2, fdx;
-
-    bytes = p->next_line;
-    dest0 = p->screen_base + y * p->fontheight * bytes + (x>>1)*16 + (x & 1);
+	u_char   *cdat, c;
+	int rows;
+	int bytes;
+	ulong	  eorx1, eorx2, fgx1, fgx2, bgx1, bgx2, fdx;
+
+	bytes = p->next_line;
+	dest0 = p->screen_base + yy * p->fontheight * bytes
+		+ (xx >> 1)*16 + (xx & 1);
 
 	expand8dl(attr_fgcol(p,conp), &fgx1, &fgx2);
 	expand8dl(attr_bgcol(p,conp), &bgx1, &bgx2);
@@ -3267,30 +3433,31 @@
 }
 
 
-static void rev_char_8_plane(struct display *p, int x, int y)
+static void rev_char_8_plane(struct display *p, int xx, int yy)
 {
-   u_char *dest;
-   int j;
-   int bytes;
-
-   dest = p->screen_base + y * p->fontheight * p->next_line + (x>>1)*16 + (x & 1);
-   j = p->fontheight;
-   bytes = p->next_line;
+	u_char *dest;
+	int j;
+	int bytes;
 
-   while (j--)
-     {
-      /* This should really obey the individual character's
-       * background and foreground colors instead of simply
-       * inverting. For 8 plane mode, only the lower 4 bits of the
-       * color are inverted, because only that color registers have
-       * been set up.
-       */
-       dest[0] = ~dest[0];
-       dest[2] = ~dest[2];
-       dest[4] = ~dest[4];
-       dest[6] = ~dest[6];
-       dest += bytes;
-     }
+	dest = p->screen_base + yy * p->fontheight * p->next_line
+		+ (xx >> 1)*16 + (xx & 1);
+	j = p->fontheight;
+	bytes = p->next_line;
+
+	while (j--)
+	{
+		/* This should really obey the individual character's
+		 * background and foreground colors instead of simply
+		 * inverting. For 8 plane mode, only the lower 4 bits of the
+		 * color are inverted, because only that color registers have
+		 * been set up.
+		 */
+		dest[0] = ~dest[0];
+		dest[2] = ~dest[2];
+		dest[4] = ~dest[4];
+		dest[6] = ~dest[6];
+		dest += bytes;
+	}
 }
 #endif /* CONFIG_FBCON_8PLANE */
 
@@ -3378,8 +3545,8 @@
 }
 
 
-static void putc_8_packed(struct vc_data *conp, struct display *p, int c, int y,
-                          int x)
+static void putc_8_packed(struct vc_data *conp, struct display *p, int c,
+			  int yy, int xx)
 {
 	u_char *dest,*cdat;
 	int bytes=p->next_line,rows;
@@ -3387,7 +3554,7 @@
 
 	c &= 0xff;
 
-	dest = p->screen_base + y * p->fontheight * bytes + x * 8;
+	dest = p->screen_base + yy * p->fontheight * bytes + xx * 8;
 	cdat = p->fontdata + c * p->fontheight;
 
 	fgx=attr_fgcol(p,conp);
@@ -3408,13 +3575,13 @@
 
 
 static void putcs_8_packed(struct vc_data *conp, struct display *p,
-                           const char *s, int count, int y, int x)
+                           const char *s, int count, int yy, int xx)
 {
 	u_char *cdat, c, *dest, *dest0;
 	int rows,bytes=p->next_line;
 	u_long eorx, fgx, bgx;
 
-	dest0 = p->screen_base + y * p->fontheight * bytes + x * 8;
+	dest0 = p->screen_base + yy * p->fontheight * bytes + xx * 8;
 	fgx=attr_fgcol(p,conp);
 	bgx=attr_bgcol(p,conp);
 	fgx |= (fgx << 8);
@@ -3437,12 +3604,12 @@
 }
 
 
-static void rev_char_8_packed(struct display *p, int x, int y)
+static void rev_char_8_packed(struct display *p, int xx, int yy)
 {
 	u_char *dest;
 	int bytes=p->next_line, rows;
 
-	dest = p->screen_base + y * p->fontheight * bytes + x * 8;
+	dest = p->screen_base + yy * p->fontheight * bytes + xx * 8;
 	for (rows = p->fontheight ; rows-- ; dest += bytes) {
 		((u_long *)dest)[0] ^= 0x0f0f0f0f;
 		((u_long *)dest)[1] ^= 0x0f0f0f0f;
@@ -3539,7 +3706,7 @@
 
 
 static void putc_16_packed(struct vc_data *conp, struct display *p, int c,
-                           int y, int x)
+                           int yy, int xx)
 {
 	u_char *dest,*cdat;
 	int bytes=p->next_line,rows;
@@ -3547,7 +3714,7 @@
 
 	c &= 0xff;
 
-	dest = p->screen_base + y * p->fontheight * bytes + x * 16;
+	dest = p->screen_base + yy * p->fontheight * bytes + xx * 16;
 	cdat = p->fontdata + c * p->fontheight;
 
 	fgx = attr_fgcol(p,conp);
@@ -3573,13 +3740,13 @@
 
 /* TODO */
 static void putcs_16_packed(struct vc_data *conp, struct display *p,
-                            const char *s, int count, int y, int x)
+                            const char *s, int count, int yy, int xx)
 {
 	u_char *cdat, c, *dest, *dest0;
 	int rows,bytes=p->next_line;
 	u_long eorx, fgx, bgx;
 
-	dest0 = p->screen_base + y * p->fontheight * bytes + x * 16;
+	dest0 = p->screen_base + yy * p->fontheight * bytes + xx * 16;
 	fgx = attr_fgcol(p,conp);
 	fgx = packed16_cmap[fgx];
 	bgx = attr_bgcol(p,conp);
@@ -3606,12 +3773,12 @@
 }
 
 
-static void rev_char_16_packed(struct display *p, int x, int y)
+static void rev_char_16_packed(struct display *p, int xx, int yy)
 {
 	u_char *dest;
 	int bytes=p->next_line, rows;
 
-	dest = p->screen_base + y * p->fontheight * bytes + x * 16;
+	dest = p->screen_base + yy * p->fontheight * bytes + xx * 16;
 	for (rows = p->fontheight ; rows-- ; dest += bytes) {
 		((u_long *)dest)[0] ^= 0xffffffff;
 		((u_long *)dest)[1] ^= 0xffffffff;
@@ -3641,87 +3808,90 @@
 }
 
 
-static void clear_cyber(struct vc_data *conp, struct display *p, int sy, int sx,
-                        int height, int width)
+static void clear_cyber(struct vc_data *conp, struct display *p, int
+			sy, int sx, int height, int width)
 {
-   u_char bg;
+	unsigned char bg;
         
 	sx *= 8; width *= 8;
 	bg = attr_bgcol_ec(p,conp);
-   Cyber_RectFill((u_short)sx, (u_short)(sy*p->fontheight), (u_short)width,
-                  (u_short)(height*p->fontheight), (u_short)S3_NEW,
-                  (u_short)bg); 
+	Cyber_RectFill((u_short)sx,
+		       (u_short)(sy*p->fontheight),
+		       (u_short)width,
+		       (u_short)(height*p->fontheight),
+		       (u_short)S3_NEW, 
+		       (u_short)bg); 
 }
 
 
-static void putc_cyber(struct vc_data *conp, struct display *p, int c, int y,
-                       int x)
+static void putc_cyber(struct vc_data *conp, struct display *p, int c, int yy,
+                       int xx)
 {
 	u_char *dest, *cdat;
 	u_long tmp;
-	u_int rows, reverse, underline; 
+	u_int rows, revs, underl; 
 	u_char d;
-   u_char fg, bg;
+	u_char fg, bg;
 
-   c &= 0xff;
+	c &= 0xff;
 
 	dest = p->screen_base+y*p->fontheight*p->next_line+8*x;
 	cdat = p->fontdata+(c*p->fontheight);
-   fg = disp->fgcol;
-   bg = disp->bgcol;
-	reverse = conp->vc_reverse;
-	underline = conp->vc_underline;
+	fg = disp->fgcol;
+	bg = disp->bgcol;
+	revs = conp->vc_reverse;
+	underl = conp->vc_underline;
 
    Cyber_WaitBlit();
 	for (rows = p->fontheight; rows--; dest += p->next_line) {
   		d = *cdat++;
 
-		if (underline && !rows)
+		if (underl && !rows)
 			d = 0xff;
-		if (reverse)
+		if (revs)
 			d = ~d;
 
-      tmp =  ((d & 0x80) ? fg : bg) << 24;
-      tmp |= ((d & 0x40) ? fg : bg) << 16;
-      tmp |= ((d & 0x20) ? fg : bg) << 8;
-      tmp |= ((d & 0x10) ? fg : bg);
-      *((u_long*) dest) = tmp;
-      tmp =  ((d & 0x8) ? fg : bg) << 24;
-      tmp |= ((d & 0x4) ? fg : bg) << 16;
-      tmp |= ((d & 0x2) ? fg : bg) << 8;
-      tmp |= ((d & 0x1) ? fg : bg);
-      *((u_long*) dest + 1) = tmp;
+		tmp =  ((d & 0x80) ? fg : bg) << 24;
+		tmp |= ((d & 0x40) ? fg : bg) << 16;
+		tmp |= ((d & 0x20) ? fg : bg) << 8;
+		tmp |= ((d & 0x10) ? fg : bg);
+		*((u_long*) dest) = tmp;
+		tmp =  ((d & 0x8) ? fg : bg) << 24;
+		tmp |= ((d & 0x4) ? fg : bg) << 16;
+		tmp |= ((d & 0x2) ? fg : bg) << 8;
+		tmp |= ((d & 0x1) ? fg : bg);
+		*((u_long*) dest + 1) = tmp;
 	}
 }
 
 
 static void putcs_cyber(struct vc_data *conp, struct display *p, const char *s,
-                        int count, int y, int x)
+                        int count, int yy, int xx)
 {
 	u_char *dest, *dest0, *cdat;
-   u_long tmp;
-	u_int rows, reverse, underline;
+	u_long tmp;
+	u_int rows, revs, underl;
 	u_char c, d;
-   u_char fg, bg;
+	u_char fg, bg;
 
 	dest0 = p->screen_base+y*p->fontheight*p->next_line+8*x;
-   fg = disp->fgcol;
-   bg = disp->bgcol;
-	reverse = conp->vc_reverse;
-	underline = conp->vc_underline;
+	fg = disp->fgcol;
+	bg = disp->bgcol;
+	revs = conp->vc_reverse;
+	underl = conp->vc_underline;
 
    Cyber_WaitBlit();
 	while (count--) {
 		c = *s++;
 		dest = dest0;
-      dest0 += 8;
+		dest0 += 8;
 		cdat = p->fontdata+(c*p->fontheight);
 		for (rows = p->fontheight; rows--; dest += p->next_line) {
  			d = *cdat++;
 
-			if (underline && !rows)
+			if (underl && !rows)
 				d = 0xff;
-			if (reverse)
+			if (revs)
 				d = ~d;
 
          tmp =  ((d & 0x80) ? fg : bg) << 24;
@@ -3739,32 +3909,208 @@
 }
 
 
-static void rev_char_cyber(struct display *p, int x, int y)
+static void rev_char_cyber(struct display *p, int xx, int yy)
 {
-	u_char *dest;
-	u_int rows;
-   u_char fg, bg;
+	unsigned char *dest;
+	unsigned int rows;
+	unsigned char fg, bg;
 
-   fg = disp->fgcol;
-   bg = disp->bgcol;
+	fg = disp->fgcol;
+	bg = disp->bgcol;
 
 	dest = p->screen_base+y*p->fontheight*p->next_line+8*x;
    Cyber_WaitBlit();
 	for (rows = p->fontheight; rows--; dest += p->next_line) {
 		*dest = (*dest == fg) ? bg : fg;
-      *(dest+1) = (*(dest + 1) == fg) ? bg : fg;
-      *(dest+2) = (*(dest + 2) == fg) ? bg : fg;
-      *(dest+3) = (*(dest + 3) == fg) ? bg : fg;
-      *(dest+4) = (*(dest + 4) == fg) ? bg : fg;
-      *(dest+5) = (*(dest + 5) == fg) ? bg : fg;
-      *(dest+6) = (*(dest + 6) == fg) ? bg : fg;
-      *(dest+7) = (*(dest + 7) == fg) ? bg : fg;
+		*(dest+1) = (*(dest + 1) == fg) ? bg : fg;
+		*(dest+2) = (*(dest + 2) == fg) ? bg : fg;
+		*(dest+3) = (*(dest + 3) == fg) ? bg : fg;
+		*(dest+4) = (*(dest + 4) == fg) ? bg : fg;
+		*(dest+5) = (*(dest + 5) == fg) ? bg : fg;
+		*(dest+6) = (*(dest + 6) == fg) ? bg : fg;
+		*(dest+7) = (*(dest + 7) == fg) ? bg : fg;
 	}
 }
 
 #endif /* CONFIG_FBCON_CYBER */
 
 
+#ifdef CONFIG_FBCON_RETINAZ3
+
+/*
+ *    RetinaZ3 (accelerated)
+ */
+
+#define Z3BLTcopy		0xc0
+#define Z3BLTset		0xf0
+
+static void clear_retz3(struct vc_data *conp, struct display *p, int
+			sy, int sx, int height, int width)
+{
+	unsigned short col;
+	int fontwidth = p->fontwidth;
+
+	sx *= fontwidth;
+	width *= fontwidth;
+
+	col = attr_bgcol_ec(p, conp);
+	col &= 0xff;
+	col |= (col << 8);
+
+	retz3_bitblt(&p->var,
+		     (unsigned short)sx,
+		     (unsigned short)(sy*p->fontheight),
+		     (unsigned short)sx,
+		     (unsigned short)(sy*p->fontheight),
+		     (unsigned short)width,
+		     (unsigned short)(height*p->fontheight),
+		     Z3BLTset,
+		     col); 
+}
+
+static void bmove_retz3(struct display *p, int sy, int sx, int dy, int dx,
+                        int height, int width)
+{
+	int fontwidth = p->fontwidth;
+
+	sx *= fontwidth;
+	dx *= fontwidth;
+	width *= fontwidth;
+
+	retz3_bitblt(&p->var,
+		     (unsigned short)sx,
+		     (unsigned short)(sy*p->fontheight),
+		     (unsigned short)dx,
+		     (unsigned short)(dy*p->fontheight),
+		     (unsigned short)width,
+		     (unsigned short)(height*p->fontheight),
+		     Z3BLTcopy,
+		     0xffff);
+}
+
+static void putc_retz3(struct vc_data *conp, struct display *p,
+		       int c, int yy, int xx)
+{
+	unsigned char *dest, *cdat;
+	unsigned long tmp;
+	unsigned int rows, revs, underl, bytes;
+	unsigned char d;
+	unsigned char fg, bg;
+   
+	c &= 0xff;
+
+	bytes = p->next_line;
+
+	dest = p->screen_base + yy*p->fontheight*bytes
+		+ xx*p->var.bits_per_pixel;
+	cdat = p->fontdata + c * p->fontheight;
+
+	fg = disp->fgcol;
+	bg = disp->bgcol;
+	revs = conp->vc_reverse;
+	underl = conp->vc_underline;
+
+	for (rows = p->fontheight; rows--; dest += bytes) {
+		d = *cdat++;
+
+		if (underl && !rows)
+			d = 0xff;
+		if (revs)
+			d = ~d;
+
+		tmp =  ((d & 0x80) ? fg : bg) << 24;
+		tmp |= ((d & 0x40) ? fg : bg) << 16;
+		tmp |= ((d & 0x20) ? fg : bg) << 8;
+		tmp |= ((d & 0x10) ? fg : bg);
+		*((unsigned long*) dest) = tmp;
+		tmp =  ((d & 0x8) ? fg : bg) << 24;
+		tmp |= ((d & 0x4) ? fg : bg) << 16;
+		tmp |= ((d & 0x2) ? fg : bg) << 8;
+		tmp |= ((d & 0x1) ? fg : bg);
+		*((unsigned long*) dest + 1) = tmp;
+	}
+}
+
+
+static void putcs_retz3(struct vc_data *conp, struct display *p,
+			const char *s, int count, int yy, int xx)
+{
+	unsigned char *dest, *dest0, *cdat;
+	unsigned long tmp;
+	unsigned int rows, revs, underl, bytes;
+	unsigned char c, d;
+	unsigned char fg, bg;
+
+	bytes = p->next_line;
+
+	dest0 = p->screen_base + yy*p->fontheight*bytes
+		+ xx * p->var.bits_per_pixel;
+	fg = disp->fgcol;
+	bg = disp->bgcol;
+	revs = conp->vc_reverse;
+	underl = conp->vc_underline;
+
+	while (count--) {
+		c = *s++;
+		dest = dest0;
+		dest0 += 8;
+
+		cdat = p->fontdata + c * p->fontheight;
+		for (rows = p->fontheight; rows--; dest += bytes) {
+ 			d = *cdat++;
+
+			if (underl && !rows)
+				d = 0xff;
+			if (revs)
+				d = ~d;
+
+			tmp =  ((d & 0x80) ? fg : bg) << 24;
+			tmp |= ((d & 0x40) ? fg : bg) << 16;
+			tmp |= ((d & 0x20) ? fg : bg) << 8;
+			tmp |= ((d & 0x10) ? fg : bg);
+			*((unsigned long*) dest) = tmp;
+			tmp =  ((d & 0x8) ? fg : bg) << 24;
+			tmp |= ((d & 0x4) ? fg : bg) << 16;
+			tmp |= ((d & 0x2) ? fg : bg) << 8;
+			tmp |= ((d & 0x1) ? fg : bg);
+			*((unsigned long*) dest + 1) = tmp;
+		}
+	}
+}
+
+static void rev_char_retz3(struct display *p, int xx, int yy)
+{
+	unsigned char *dest;
+	int bytes=p->next_line, rows;
+	unsigned int bpp, mask;
+
+	bpp = p->var.bits_per_pixel;
+
+	switch (bpp){
+	case 8:
+		mask = 0x0f0f0f0f;
+		break;
+	case 16:
+		mask = 0xffffffff;
+		break;
+	case 24:
+		mask = 0xffffffff; /* ??? */
+		break;
+	default:
+		printk("illegal depth for rev_char_retz3(), bpp = %i\n", bpp);
+		return;
+	}
+
+	dest = p->screen_base + yy * p->fontheight * bytes + xx * bpp;
+
+	for (rows = p->fontheight ; rows-- ; dest += bytes) {
+		((unsigned long *)dest)[0] ^= mask;
+		((unsigned long *)dest)[1] ^= mask;
+	}
+}
+
+#endif
+
 /* ====================================================================== */
 
    /*
@@ -3774,5 +4120,5 @@
 struct consw fb_con = {
    fbcon_startup, fbcon_init, fbcon_deinit, fbcon_clear, fbcon_putc,
    fbcon_putcs, fbcon_cursor, fbcon_scroll, fbcon_bmove, fbcon_switch,
-   fbcon_blank, fbcon_get_font, fbcon_set_font
+   fbcon_blank, fbcon_get_font, fbcon_set_font, fbcon_set_palette
 };
diff -u --recursive --new-file v2.1.35/linux/arch/m68k/console/txtcon.c linux/arch/m68k/console/txtcon.c
--- v2.1.35/linux/arch/m68k/console/txtcon.c	Sun May 19 21:54:26 1996
+++ linux/arch/m68k/console/txtcon.c	Thu Apr 17 13:20:42 1997
@@ -22,7 +22,7 @@
     *    Interface used by the world
     */
 
-static u_long txtcon_startup(u_long kmem_start, char **display_desc);
+static u_long txtcon_startup(u_long kmem_start, const char **display_desc);
 static void txtcon_init(struct vc_data *conp);
 static int txtcon_deinit(struct vc_data *conp);
 static int txtcon_clear(struct vc_data *conp, int sy, int sx, int height,
@@ -36,10 +36,12 @@
                         int height, int width);
 static int txtcon_switch(struct vc_data *conp);
 static int txtcon_blank(int blank);
+static int txtcon_get_font(struct vc_data *conp, int *w, int *h, char *data);
+static int txtcon_set_font(struct vc_data *conp, int w, int h, char *data);
+static int txtcon_set_palette(struct vc_data *conp, unsigned char *table);
 
 
-
-static u_long txtcon_startup(u_long kmem_start, char **display_desc)
+static u_long txtcon_startup(u_long kmem_start, const char **display_desc)
 {
    *display_desc = "Not yet implemented";
    return(kmem_start);
@@ -113,6 +115,24 @@
 }
 
 
+static int txtcon_get_font(struct vc_data *conp, int *w, int *h, char *data)
+{
+   return(0);
+}
+
+
+static int txtcon_set_font(struct vc_data *conp, int w, int h, char *data)
+{
+   return(0);
+}
+
+
+static int txtcon_set_palette(struct vc_data *conp, unsigned char *table)
+{
+   return(0);
+}
+
+
 /* ====================================================================== */
 
    /*
@@ -122,6 +142,6 @@
 struct consw txt_con = {
    txtcon_startup, txtcon_init, txtcon_deinit, txtcon_clear, txtcon_putc,
    txtcon_putcs, txtcon_cursor, txtcon_scroll, txtcon_bmove, txtcon_switch,
-   txtcon_blank
+   txtcon_blank, txtcon_get_font, txtcon_set_font, txtcon_set_palette
 };
 
diff -u --recursive --new-file v2.1.35/linux/arch/m68k/defconfig linux/arch/m68k/defconfig
--- v2.1.35/linux/arch/m68k/defconfig	Mon Apr  7 11:35:29 1997
+++ linux/arch/m68k/defconfig	Thu Apr 17 13:20:42 1997
@@ -46,6 +46,7 @@
 CONFIG_AMIFB_ECS=y
 CONFIG_AMIFB_AGA=y
 # CONFIG_FB_CYBER is not set
+# CONFIG_FB_RETINAZ3 is not set
 # CONFIG_AMIGA_GSP is not set
 # CONFIG_GSP_RESOLVER is not set
 # CONFIG_GSP_A2410 is not set
@@ -79,9 +80,10 @@
 # CONFIG_FIREWALL is not set
 # CONFIG_NET_ALIAS is not set
 CONFIG_INET=y
-# CONFIG_IP_FORWARD is not set
 # 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)
@@ -123,18 +125,19 @@
 # SCSI low-level drivers
 #
 CONFIG_A3000_SCSI=y
-# CONFIG_A2091_SCSI is not set
-# CONFIG_GVP11_SCSI is not set
+CONFIG_A2091_SCSI=y
+CONFIG_GVP11_SCSI=y
 # CONFIG_CYBERSTORM_SCSI is not set
 # CONFIG_CYBERSTORMII_SCSI is not set
 # CONFIG_BLZ2060_SCSI is not set
 # CONFIG_BLZ1230_SCSI is not set
+# CONFIG_FASTLANE_SCSI is not set
 CONFIG_ATARI_SCSI=y
 
 #
 # Network device support
 #
-# CONFIG_NETDEVICES is not set
+CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_SLIP is not set
 # CONFIG_PPP is not set
@@ -164,6 +167,7 @@
 # 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_UFS_FS is not set
 
 #
@@ -176,6 +180,8 @@
 CONFIG_ATARIMOUSE=y
 CONFIG_AMIGA_BUILTIN_SERIAL=y
 # CONFIG_GVPIOEXT is not set
+# CONFIG_GVPIOEXT_LP is not set
+# CONFIG_GVPIOEXT_PLIP is not set
 # CONFIG_MULTIFACE_III_TTY is not set
 # CONFIG_USERIAL is not set
 # CONFIG_WATCHDOG is not set
diff -u --recursive --new-file v2.1.35/linux/arch/m68k/fpsp040/skeleton.S linux/arch/m68k/fpsp040/skeleton.S
--- v2.1.35/linux/arch/m68k/fpsp040/skeleton.S	Wed Sep 25 00:47:39 1996
+++ linux/arch/m68k/fpsp040/skeleton.S	Thu Apr 17 13:20:42 1997
@@ -513,9 +513,12 @@
 	movel	12(%sp),%d0	| count
 	subl	#1,%d0		| dec count by 1 for dbra
 	movel	#1,%d1
-	movec	%d1,%DFC		| set dfc for user data space
+
+|	DFC is already set
+|	movec	%d1,%DFC		| set dfc for user data space
 moreout:
 	moveb	(%a0)+,%d1	| fetch supervisor byte
+out_ea:
 	movesb	%d1,(%a1)+	| write user byte
 	dbf	%d0,moreout
 	rts
@@ -526,11 +529,24 @@
 	movel	12(%sp),%d0	| count
 	subl	#1,%d0		| dec count by 1 for dbra
 	movel	#1,%d1
-	movec	%d1,%SFC		| set sfc for user space
+|	SFC is already set
+|	movec	%d1,%SFC		| set sfc for user space
 morein:
+in_ea:
 	movesb	(%a0)+,%d1	| fetch user byte
 	moveb	%d1,(%a1)+	| write supervisor byte
 	dbf	%d0,morein
 	rts
+
+	.section .fixup,#alloc,#execinstr
+	.even
+1:
+	jbra	SYMBOL_NAME(fpsp040_die)
+
+	.section __ex_table,#alloc
+	.align	4
+
+	.long	in_ea,1b
+	.long	out_ea,1b
 
 	|end
diff -u --recursive --new-file v2.1.35/linux/arch/m68k/ifpsp060/os.S linux/arch/m68k/ifpsp060/os.S
--- v2.1.35/linux/arch/m68k/ifpsp060/os.S	Wed Sep 25 00:47:39 1996
+++ linux/arch/m68k/ifpsp060/os.S	Thu Apr 17 13:20:42 1997
@@ -153,7 +153,7 @@
 	btst		#0x5,0x4(%a6)		| check for supervisor state
 	bnes		dmrbs			| supervisor
 dmrbu:	clr.l		%d0			| clear whole longword
-	movs.b		(%a0),%d0		| fetch user byte
+dmrbuae:movs.b		(%a0),%d0		| fetch user byte
 	bras		dmrbr
 dmrbs:	clr.l		%d0			| clear whole longword
 	move.b		(%a0),%d0		| fetch super byte
@@ -190,7 +190,7 @@
 	btst		#0x5,0x4(%a6)		| check for supervisor state
 	bnes		dmrws			| supervisor
 dmrwu:	clr.l		%d0			| clear whole longword
-	movs.w		(%a0), %d0		| fetch user word
+dmrwuae:movs.w		(%a0), %d0		| fetch user word
 	bras		dmrwr
 dmrws:	clr.l		%d0			| clear whole longword
 	move.w		(%a0), %d0		| fetch super word
@@ -226,7 +226,8 @@
 _060_imem_read_long:
 	btst		#0x5,0x4(%a6)		| check for supervisor state
 	bnes		dmrls			| supervisor
-dmrlu:	movs.l		(%a0),%d0		| fetch user longword
+dmrlu:
+dmrluae:movs.l		(%a0),%d0		| fetch user longword
 	bras		dmrlr
 dmrls:	move.l		(%a0),%d0		| fetch super longword
 dmrlr:	clr.l		%d1			| return success
@@ -248,7 +249,8 @@
 _060_dmem_write_byte:
 	btst		#0x5,0x4(%a6)		| check for supervisor state
 	bnes		dmwbs			| supervisor
-dmwbu:	movs.b		%d0,(%a0)		| store user byte
+dmwbu:
+dmwbuae:movs.b		%d0,(%a0)		| store user byte
 	bras		dmwbr
 dmwbs:	move.b		%d0,(%a0)		| store super byte
 dmwbr:	clr.l		%d1			| return success
@@ -270,7 +272,8 @@
 _060_dmem_write_word:
 	btst		#0x5,0x4(%a6)		| check for supervisor state
 	bnes		dmwws			| supervisor
-dmwwu:	movs.w		%d0,(%a0)		| store user word
+dmwwu:
+dmwwuae:movs.w		%d0,(%a0)		| store user word
 	bras		dmwwr
 dmwws:	move.w		%d0,(%a0)		| store super word
 dmwwr:	clr.l		%d1			| return success
@@ -292,7 +295,8 @@
 _060_dmem_write_long:
 	btst		#0x5,0x4(%a6)		| check for supervisor state
 	bnes		dmwls			| supervisor
-dmwlu:	movs.l		%d0,(%a0)		| store user longword
+dmwlu:
+dmwluae:movs.l		%d0,(%a0)		| store user longword
 	bra		dmwlr
 dmwls:	move.l		%d0,(%a0)		| store super longword
 dmwlr:	clr.l		%d1			| return success
@@ -322,9 +326,10 @@
     subq.l      #1,%d0
 moreout:
 	move.b		(%a0)+,%d1		| fetch supervisor byte
+copyoutae:
 	movs.b		%d1,(%a1)+		| store user byte
 	dbra		%d0,moreout		| are we through yet?
-    moveq		#0,%d0			| return success
+	moveq		#0,%d0			| return success
 	rts
 
 |
@@ -337,11 +342,12 @@
 	move.l		12(%sp),%d0		| count
     subq.l      #1,%d0
 morein:
+copyinae:	
 	movs.b		(%a0)+,%d1		| fetch user byte
 	move.b		%d1,(%a1)+		| write supervisor byte
 	subq.l		#0x1,%d0		| are we through yet?
 	dbra		%d0,morein		| are we through yet?
-    moveq		#0,%d0			| return success
+	moveq		#0,%d0			| return success
 	rts
 
 |###########################################################################
@@ -374,3 +380,22 @@
 	.global		_060_real_access
 _060_real_access:
 	bral	SYMBOL_NAME(buserr)
+
+
+
+| Execption handling for movs access to illegal memory	
+	.section .fixup,#alloc,#execinstr
+	.even
+1:	moveq		#-1,%d1
+	rts
+.section __ex_table,#alloc
+	.align 4
+	.long	dmrbuae,1b
+	.long	dmrwuae,1b
+	.long	dmrluae,1b
+	.long	dmwbuae,1b
+	.long	dmwwuae,1b
+	.long	dmwluae,1b
+	.long	copyoutae,1b
+	.long	copyinae,1b
+	.text
diff -u --recursive --new-file v2.1.35/linux/arch/m68k/kernel/Makefile linux/arch/m68k/kernel/Makefile
--- v2.1.35/linux/arch/m68k/kernel/Makefile	Fri Apr  4 08:52:17 1997
+++ linux/arch/m68k/kernel/Makefile	Thu Apr 17 13:20:42 1997
@@ -19,6 +19,10 @@
 endif
 OX_OBJS := m68k_ksyms.o
 
+ifdef CONFIG_KGDB
+O_OBJS += kgdb.o
+endif
+
 head.o: head.S
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.1.35/linux/arch/m68k/kernel/console.c linux/arch/m68k/kernel/console.c
--- v2.1.35/linux/arch/m68k/kernel/console.c	Fri Apr  4 08:52:17 1997
+++ linux/arch/m68k/kernel/console.c	Thu Apr 17 13:20:42 1997
@@ -20,7 +20,7 @@
  *     'unsigned long con_init(unsigned long)'
  *     'int con_open(struct tty_struct *tty, struct file * filp)'
  *     'void con_write(struct tty_struct * tty)'
- *     'void console_print(const char * b)'
+ *     'void vt_console_print(const char * b)'
  *     'void update_screen(int new_console)'
  *
  *     'void do_blank_screen(int)'
@@ -103,11 +103,13 @@
  * interrupt, as we use trap-gates. Hopefully all is well.
  */
 
+#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/console.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/errno.h>
@@ -127,6 +129,7 @@
 #include "../../../drivers/char/vt_kern.h"
 #include "../../../drivers/char/consolemap.h"
 #include "../../../drivers/char/selection.h"
+#include "../../../drivers/char/console_struct.h"
 
 
 #ifndef MIN
@@ -146,12 +149,13 @@
 static void save_cur(int currcons);
 static void blank_screen(void);
 static void unblank_screen(void);
+static int con_open(struct tty_struct *, struct file *);
 extern void change_console(unsigned int);
 static inline void set_cursor(int currcons);
 static void reset_terminal(int currcons, int do_clear);
 extern void reset_vc(unsigned int new_console);
 extern void vt_init(void);
-extern void register_console(void (*proc)(const char *));
+static void set_vesa_blanking(unsigned long arg);
 extern void vesa_blank(void);
 extern void vesa_unblank(void);
 extern void compute_shiftstate(void);
@@ -170,6 +174,7 @@
 static unsigned short console_charmask = 0x0ff;
 
 static unsigned short *vc_scrbuf[MAX_NR_CONSOLES];
+struct vc vc_cons [MAX_NR_CONSOLES];
 
 /* used by kbd_bh - set by keyboard_interrupt */
        int do_poke_blanked_console = 0;
@@ -189,13 +194,6 @@
 int want_console = -1;
 int kmsg_redirect = 0;
 
-static struct vc {
-	struct vc_data *d;
-
-	/* might add  scrmem, vt_struct, kbd  at some time,
-	   to have everything in one place - the disadvantage
-	   would be that vc_cons etc can no longer be static */
-} vc_cons [MAX_NR_CONSOLES];
 struct consw *conswitchp;
 
 #define cols            (vc_cons[currcons].d->vc_cols)
@@ -270,8 +268,6 @@
 #define	vtnewvt		(vt_cons[currcons]->vt_newvt)
 #endif
 
-#define structsize	(sizeof(struct vc_data) + sizeof(struct vt_struct))
-
 int vc_cons_allocated(unsigned int i)
 {
 	return (i < MAX_NR_CONSOLES && vc_cons[i].d);
@@ -621,8 +617,7 @@
 	return;
 }
 
-static void scrup(int currcons, unsigned int t, unsigned int b,
-		  int nr)
+static void scrup(int currcons, unsigned int t, unsigned int b, int nr)
 {
 	unsigned short *p;
 	int i;
@@ -636,10 +631,10 @@
 
 	p = video_mem_start + (b - nr) * cols;
 	for (i = nr * cols; i > 0; i--)
-	  *p++ = video_erase_char;
+		*p++ = video_erase_char;
 
 	if (currcons != fg_console)
-	  return;
+		return;
 /*
  * Arno:
  * Scrolling has now been moved to amicon.c where it should have
@@ -812,8 +807,8 @@
 	if (!vpar)
 		vpar++;
 
-	start=pos;
-	count=(vpar > cols-x) ? (cols-x) : vpar;
+	start = pos;
+	count = (vpar > cols-x) ? (cols-x) : vpar;
 
 	if (currcons == fg_console)
 		sw->con_clear(vc_cons[currcons].d,y,x,1,count);
@@ -1008,7 +1003,7 @@
 	respond_string(buf, tty);
 }
 
-/* invoked via ioctl(TIOCLINUX) */
+/* invoked via ioctl(TIOCLINUX) and through set_selection */
 int mouse_reporting(void)
 {
 	int currcons = fg_console;
@@ -1309,12 +1304,12 @@
 	unsigned short *p = pos;
 
 	for (i = cols - x - 2; i >= 0; i--)
-	  p[i + 1] = p[i];
+		p[i + 1] = p[i];
 	*pos = video_erase_char;
 	need_wrap = 0;
 
 	if (currcons != fg_console)
-	  return;
+		return;
 
 	/* Arno:
 	 * Move the remainder of the line (-1 character) one spot to the right
@@ -1338,19 +1333,19 @@
 
 	p = pos + cols - x - nr;
 	while (--p >= pos)
-	  p[nr] = *p;
+		p[nr] = *p;
 	for (i = 0; i < nr; i++)
-	  *++p = video_erase_char;
+		*++p = video_erase_char;
 	need_wrap = 0;
 
 	if (currcons != fg_console)
-	  return;
+		return;
 
 	sw->con_bmove (vc_cons[currcons].d, y, x, y, x + nr,
 		       1, cols - x - nr);
 	while (nr--)
-	  sw->con_putc (vc_cons[currcons].d, video_erase_char & 0x00ff,
-			y, x + nr);
+		sw->con_putc (vc_cons[currcons].d,
+			      video_erase_char & 0x00ff, y, x + nr);
 }
 
 static void csi_L(int currcons, unsigned int nr)
@@ -1645,9 +1640,9 @@
 			 */
 			
 			/* Only use this for the foreground console,
-                           where we really draw the chars */
+			   where we really draw the chars */
 
-                        if (count > 2 &&
+			if (count > 2 &&
 			    !decim && !utf && currcons == fg_console) { 
 				static char putcs_buf[256];
 				char   *p     = putcs_buf;
@@ -1660,13 +1655,11 @@
 				if (nextx == cols) {
 					sw->con_putc(vc_cons[currcons].d,
 						     *putcs_buf, y, x);
-					pos--;
+					((unsigned short *)pos)--;
 					need_wrap = decawm;
 					continue;
 				}
 				
-				/* TAB TAB TAB - Arghh!!!! */
-
 				while (count)
 				{
 					enable_bh(CONSOLE_BH);
@@ -2129,12 +2122,13 @@
 
 /* DPC: New version of console_print using putcs */
 
-void console_print(const char * b)
+#ifdef CONFIG_VT_CONSOLE
+void vt_console_print(const char * b, unsigned int count)
 {
    int currcons = fg_console;
    unsigned char c;
    const char *start = b;
-   ushort count      = 0;
+   ushort cnt        = 0;
    ushort myx        = x;
    static int printing = 0;
 
@@ -2147,7 +2141,7 @@
 
    if (!vc_cons_allocated(currcons)) {
 	   /* impossible */
-	   printk("console_print: tty %d not allocated ??\n", currcons+1);
+	   printk("vt_console_print: tty %d not allocated ??\n", currcons+1);
 	   printing = 0;
 	   return;
    }
@@ -2157,52 +2151,51 @@
 
    /* Contrived structure to try to emulate original need_wrap behaviour
     * Problems caused when we have need_wrap set on '\n' character */
-   
-   while ((c = *(b++)) != 0) {
-       if (c == 10 || c == 13 || c == 8 || need_wrap) {
-           if ((count = b - start - 1) > 0) {
-               sw->con_putcs(vc_cons[currcons].d, start, count ,
-                             y, x);
-               x += count;
-	       if (need_wrap)
-		 x--;
-           }
-
-	   if (c == 8) {	/* backspace */
-	       bs(currcons);
-	       start = b;
-	       myx = x;
-	       continue;
+
+   while (count-- > 0) {
+	   c = *(b++);
+	   if (c == 10 || c == 13 || c == 8 || need_wrap) {
+			if ((cnt = b - start - 1) > 0) {
+				sw->con_putcs(vc_cons[currcons].d,
+					      start, cnt, y, x);
+				x += cnt;
+				if (need_wrap)
+					x--;
+		   }
+
+		   if (c == 8) {	/* backspace */
+			   bs(currcons);
+			   start = b;
+			   myx = x;
+			   continue;
+		   }
+		   if (c != 13)
+			   lf(currcons);
+		   cr(currcons);
+
+		   if (c == 10 || c == 13) {
+			   start = b; myx = x; continue;
+		   }
+
+		   start = b-1; myx = x;
 	   }
-           if (c != 13)
-               lf(currcons);
-           cr(currcons);
-
-           if (c == 10 || c == 13) {
-               start = b; myx = x; continue;
-           }
-
-           start = b-1; myx = x;
-       }
-
-       *pos = c | (attr << 8);
-       if (myx == cols - 1) {
-           need_wrap = 1;
-           continue;
-       }
-       pos++;
-       myx++;
+
+	   *pos = c | (attr << 8);
+	   if (myx == cols - 1) {
+		   need_wrap = 1;
+		   continue;
+	   }
+	   pos++;
+	   myx++;
    }
 
-   if ((count = b - start -1) > 0) {
-       sw->con_putcs(vc_cons[currcons].d, start, count ,
-                     y, x);
-       x += count;
-       if (x == cols)
-	 {
-	   x--;
-           need_wrap = 1;
-	 }
+   if ((cnt = b - start) > 0) {
+	   sw->con_putcs(vc_cons[currcons].d, start, cnt, y, x);
+	   x += cnt;
+	   if (x == cols){
+		   x--;
+		   need_wrap = 1;
+	   }
    }
    
    set_cursor(currcons);
@@ -2210,6 +2203,18 @@
    printing = 0;
 }
 
+static int vt_console_device(void)
+{
+	return MKDEV(TTY_MAJOR, fg_console + 1);
+}
+
+extern void keyboard_wait_for_keypress(void);
+
+struct console vt_console_driver = {
+	vt_console_print, do_unblank_screen,
+        keyboard_wait_for_keypress, vt_console_device
+};
+#endif
 
 /*
  * con_throttle and con_unthrottle are only used for
@@ -2280,7 +2285,7 @@
  */
 unsigned long con_init(unsigned long kmem_start)
 {
-	char *display_desc = "????";
+	const char *display_desc = "????";
 	unsigned int currcons = 0;
 	extern int serial_debug;
 
@@ -2354,14 +2359,15 @@
 	printable = 1;
 
 	/* If "serdebug" cmd line option was present, don't register for printk */
+#ifdef CONFIG_VT_CONSOLE
 	if (!serial_debug)
-		register_console(console_print);
+		register_console(&vt_console_driver);
 	printk("Console: %s %s %ldx%ld, %d virtual console%s (max %d)\n",
 		can_do_color ? "colour":"mono",
 		display_desc,
 		cols,rows,
 		MIN_NR_CONSOLES, (MIN_NR_CONSOLES == 1) ? "" : "s", MAX_NR_CONSOLES);
-
+#endif
 	init_bh(CONSOLE_BH, console_bh);
 	return kmem_start;
 }
@@ -2527,7 +2533,7 @@
 /*
  * Allocate the console screen memory.
  */
-int con_open(struct tty_struct *tty, struct file * filp)
+static int con_open(struct tty_struct *tty, struct file * filp)
 {
 	unsigned int currcons;
 	int i;
@@ -2664,7 +2670,7 @@
 	return -EINVAL;
 }
 
-void set_vesa_blanking(int arg)
+static void set_vesa_blanking(unsigned long arg)
 {
 	char *argp = (char *)arg + 1;
 	unsigned int mode;
diff -u --recursive --new-file v2.1.35/linux/arch/m68k/kernel/entry.S linux/arch/m68k/kernel/entry.S
--- v2.1.35/linux/arch/m68k/kernel/entry.S	Fri Dec 20 01:19:58 1996
+++ linux/arch/m68k/kernel/entry.S	Tue Apr 22 22:49:38 1997
@@ -52,6 +52,10 @@
 #include <linux/linkage.h>
 #include <asm/setup.h>
 #include <asm/segment.h>
+#ifdef CONFIG_KGDB
+#include <asm/kgdb.h>
+.globl SYMBOL_NAME(kgdb_registers)
+#endif
 
 LENOSYS = 38
 
@@ -66,7 +70,7 @@
 LTASK_FLAGS	= 20
 
 /* the following macro is used when enabling interrupts */
-#if defined(CONFIG_ATARI_ONLY)
+#if defined(MACH_ATARI_ONLY)
 	/* block out HSYNC on the atari */
 #define ALLOWINT 0xfbff
 #define	MAX_NOINT_IPL	3
@@ -87,11 +91,23 @@
  * regs are a2-a6 and d6-d7 preserved by C code
  * the kernel doesn't mess with usp unless it needs to
  */
+#ifndef CONFIG_KGDB
 #define SAVE_ALL			\
 	clrl	%sp@-;    /* stk_adj */	\
 	movel	%d0,%sp@-; /* orig d0 */	\
 	movel	%d0,%sp@-; /* d0 */	\
 	moveml	%d1-%d5/%a0-%a1,%sp@-
+#else
+/* Need to save the "missing" registers for kgdb...
+ */
+#define SAVE_ALL						\
+	clrl	%sp@-;    /* stk_adj */				\
+	movel	%d0,%sp@-; /* orig d0 */			\
+	movel	%d0,%sp@-; /* d0 */				\
+	moveml	%d1-%d5/%a0-%a1,%sp@-;				\
+	moveml	%d6-%d7,SYMBOL_NAME(kgdb_registers)+GDBOFFA_D6;	\
+	moveml	%a2-%a6,SYMBOL_NAME(kgdb_registers)+GDBOFFA_A2
+#endif
 
 #define RESTORE_ALL			\
 	moveml	%sp@+,%a0-%a1/%d1-%d5;	\
@@ -244,7 +260,7 @@
 	movel	%d0,%sp@(LORIG_D0)	| a -1 in the ORIG_D0 field
 					| signifies that the stack frame
 					| is NOT for syscall
-	addql	#1,SYMBOL_NAME(intr_count)
+	addql	#1,SYMBOL_NAME(local_irq_count)
 					|  put exception # in d0
 	bfextu %sp@(LFORMATVEC){#4,#10},%d0
 
@@ -255,27 +271,26 @@
 
 SYMBOL_NAME_LABEL(ret_from_interrupt)
 	/* check if we need to do software interrupts */
-1:
-	movel	SYMBOL_NAME(intr_count),%d1
+	movel	SYMBOL_NAME(local_irq_count),%d1
 	subql	#1,%d1
 	jne	4f
-	bfextu  %sp@(LSR){#5,#3},%d0    | Check for nested interrupt.
+#if 0
+		bfextu  %sp@(LSR){#5,#3},%d0    | Check for nested interrupt.
 #if MAX_NOINT_IPL > 0
 	cmpiw	#MAX_NOINT_IPL,%d0
 #endif
 	jhi	4f
-2:
+#endif
 	movel	SYMBOL_NAME(bh_active),%d0
 	andl	SYMBOL_NAME(bh_mask),%d0
-	jne	3f
+	jeq	3f
 
-	clrl	SYMBOL_NAME(intr_count)	| deliver signals, reschedule etc..
-	jra	SYMBOL_NAME(ret_from_exception)
-3:	
 	jbsr	SYMBOL_NAME(do_bottom_half)
-	jbra	2b
+3:	
+	clrl	SYMBOL_NAME(local_irq_count)
+	jra	SYMBOL_NAME(ret_from_exception)
 4:
-	movel	%d1,SYMBOL_NAME(intr_count)
+	movel	%d1,SYMBOL_NAME(local_irq_count)
 	RESTORE_ALL
 
 
@@ -339,8 +354,10 @@
 	/* save sr */
 	movew	%sr,%a0@(LTSS_SR)
 
+#if 0
 	/* disable interrupts */
 	oriw	#0x0700,%sr
+#endif
 
 	/* save fs (sfc,%dfc) (may be pointing to kernel memory) */
 	movec	%sfc,%d0
@@ -361,18 +378,18 @@
 	fsave	%a0@(LTSS_FPCTXT+27*4)
 
 #if defined(CONFIG_M68060)
-#if !defined(CONFIG_M68060_ONLY)
+#if !defined(CPU_M68060_ONLY)
 	btst	#3,SYMBOL_NAME(m68k_cputype)+3
 	beqs	1f
 #endif
 	/* The 060 FPU keeps status in bits 15-8 of the first longword */
 	tstb	%a0@(LTSS_FPCTXT+27*4+2)
 	jeq	3f
-#if !defined(CONFIG_M68060_ONLY)
+#if !defined(CPU_M68060_ONLY)
 	jra	2f
 #endif
 #endif /* CONFIG_M68060 */
-#if !defined(CONFIG_M68060_ONLY)
+#if !defined(CPU_M68060_ONLY)
 1:	tstb	%a0@(LTSS_FPCTXT+27*4)
 	jeq	3f
 #endif
@@ -388,12 +405,12 @@
 	tstb	%d2
 	jne	4f
 
-#if defined(CONFIG_M68020_OR_M68030) && defined(CONFIG_M68040_OR_M68060)
+#if defined(CPU_M68020_OR_M68030) && defined(CPU_M68040_OR_M68060)
 	/* 68040 or 68060 ? */
 	tstl	SYMBOL_NAME(m68k_is040or060)
 	bnes	1f
 #endif
-#if defined(CONFIG_M68020_OR_M68030)
+#if defined(CPU_M68020_OR_M68030)
 	/*
 	 * switch address space
 	 */
@@ -407,11 +424,11 @@
 	pmove	%a1@(LTSS_CRP),%crp
 #endif
 
-#if defined(CONFIG_M68020_OR_M68030) && defined(CONFIG_M68040_OR_M68060)
+#if defined(CPU_M68020_OR_M68030) && defined(CPU_M68040_OR_M68060)
 	jra	2f	/* skip m68040 stuff */
 1:
 #endif
-#if defined(CONFIG_M68040_OR_M68060)
+#if defined(CPU_M68040_OR_M68060)
 	/*
 	 * switch address space
 	 */
@@ -434,24 +451,24 @@
 	movec	%d0,%cacr
 #endif /* CONFIG_M68060 */
 	.chip	68k
-#endif /* CONFIG_M68040_OR_M68060 */
+#endif /* CPU_M68040_OR_M68060 */
 2:
 4:
 	/* restore floating point context */
 
 #if defined(CONFIG_M68060)
-#if !defined(CONFIG_M68060_ONLY)
+#if !defined(CPU_M68060_ONLY)
 	btst	#3,SYMBOL_NAME(m68k_cputype)+3
 	beqs	1f
 #endif
 	/* The 060 FPU keeps status in bits 15-8 of the first longword */
 	tstb	%a1@(LTSS_FPCTXT+27*4+2)
 	jeq	3f
-#if !defined(CONFIG_M68060_ONLY)
+#if !defined(CPU_M68060_ONLY)
 	jra	2f
 #endif
 #endif /* CONFIG_M68060 */
-#if !defined(CONFIG_M68060_ONLY)
+#if !defined(CPU_M68060_ONLY)
 1:	tstb	%a1@(LTSS_FPCTXT+27*4)
 	jeq	3f
 #endif	
@@ -647,8 +664,11 @@
 	.long SYMBOL_NAME(sys_nanosleep)
 	.long SYMBOL_NAME(sys_mremap)
 	.long SYMBOL_NAME(sys_setresuid)
-	.long SYMBOL_NAME(sys_getresuid)
+	.long SYMBOL_NAME(sys_getresuid)	/* 165 */
 	.long SYMBOL_NAME(sys_ni_syscall)	/* for vm86 */
+	.long SYMBOL_NAME(sys_query_module)
+	.long SYMBOL_NAME(sys_poll)
+	.long SYMBOL_NAME(sys_nfsservctl)
 	.rept NR_syscalls-(.-SYMBOL_NAME(sys_call_table))/4
 		.long SYMBOL_NAME(sys_ni_syscall)
 	.endr
diff -u --recursive --new-file v2.1.35/linux/arch/m68k/kernel/head.S linux/arch/m68k/kernel/head.S
--- v2.1.35/linux/arch/m68k/kernel/head.S	Fri Dec 20 01:19:58 1996
+++ linux/arch/m68k/kernel/head.S	Thu Apr 17 13:20:42 1997
@@ -73,6 +73,7 @@
 
 .globl SYMBOL_NAME(kernel_pg_dir), SYMBOL_NAME(kpt)
 .globl SYMBOL_NAME(availmem), SYMBOL_NAME(is_medusa)
+.globl SYMBOL_NAME(is_hades)
 .globl SYMBOL_NAME(m68k_pgtable_cachemode)
 .globl SYMBOL_NAME(kernel_pmd_table), SYMBOL_NAME(swapper_pg_dir)
 
@@ -235,8 +236,58 @@
 #endif
 
 /*
+   If running on an Atari, determine the I/O base of the
+   serial port and test if we are running on a Medusa or Hades.
+   This test is necessary here, because on the Hades the serial
+   port is only accessible in the high I/O memory area.
+
+   The test whether it is a Medusa is done by writing to the byte at
+   phys. 0x0. This should result in a bus error on all other machines.
+
+   ...should, but doesn't. The Afterburner040 for the Falcon has the
+   same behaviour (0x0..0x7 are no ROM shadow). So we have to do
+   another test to distinguish Medusa and AB040. This is a
+   read attempt for 0x00ff82fe phys. that should bus error on a Falcon
+   (+AB040), but is in the range where the Medusa always asserts DTACK.
+
+   The test for the Hades is done by reading address 0xb0000000. This
+   should give a bus error on the Medusa.
+ */
+
+#ifdef CONFIG_ATARI
+	is_not_atari(Lnotypetest)
+
+	moveq	#0,%d3			/* base addr for others: 0x00000000 */
+	moveq	#0,%d2			/* no Hades */
+	movec	%d3,%vbr
+	lea	%pc@(Ltest_berr),%a0
+	movel	%a0,0x8
+	movel	%sp,%a0
+	moveb	0x0,%d1
+	clrb	0x0
+	nop
+	moveb	%d1,0x0
+	nop
+	tstb	0x00ff82fe
+	nop
+	movel	#0xff000000,%d3		/* Medusa base addr: 0xff000000 */
+	tstb	0xb0000000
+	nop
+	movel	#0xff000000,%d2		/* Computer is a Hades */
+	moveq	#0,%d3
+Ltest_berr:
+	movel	%a0,%sp
+	lea	%pc@(SYMBOL_NAME(is_hades)),%a0
+	movel	%d2,%a0@
+	lea	%pc@(SYMBOL_NAME(is_medusa)),%a0
+	movel	%d3,%a0@
+Lnotypetest:
+#endif
+
+/*
  * Initialize serial port
  */
+
 	jbsr Lserial_init
 
 	putr()
@@ -491,35 +542,16 @@
 
    For the Medusa it is better to map the I/O region transparently
    (i.e. 0xffxxxxxx -> 0xffxxxxxx), because some I/O registers are
-   accessible only in the high area. The test whether it is a Medusa
-   is done by writing to the byte at phys. 0x0. This should result
-   in a bus error on all other machines.
+   accessible only in the high area.
 
-   ...should, but doesn't. The Afterburner040 for the Falcon has the
-   same behaviour (0x0..0x7 are no ROM shadow). So we have to do
-   another test to distinguish Medusa and AB040. This is a
-   read attempt for 0x00ff82fe phys. that should bus error on a Falcon
-   (+AB040), but is in the range where the Medusa always asserts DTACK.
+   On the Hades all I/O registers are only accessible in the high
+   area.
 */
 
-	moveq	#0,%d3			/* base addr for others: 0x00000000 */
-	movec	%d3,%vbr
-	lea	%pc@(Ltest_berr),%a0
-	movel	%a0,0x8
-	movel	%sp,%a0
-	moveb	0x0,%d1
-	clrb	0x0
-	nop
-	moveb	%d1,0x0
-	nop
-	tstb	0x00ff82fe
-	nop
-	movel	#0xff000000,%d3		/* Medusa base addr: 0xff000000 */
-Ltest_berr:
-	movel	%a0,%sp
-	lea     %pc@(SYMBOL_NAME(is_medusa)),%a0
-	movel	%d3,%a0@
-
+	movel   %pc@(is_medusa),%d3
+	bne     1f
+	movel   %pc@(is_hades),%d3
+1:
 	/* Let the root table point to the new pointer table */
 	lea	%a4@(PTR_TABLE_SIZE<<2),%a4
 	movel	%a4,%a0
@@ -979,19 +1011,20 @@
 #ifdef CONFIG_ATARI
 	cmpil   #MACH_ATARI,%d4
 	jne	4f
+	movel	%pc@(Liobase),%a1
 #ifdef USE_PRINTER
-	bclr	#0,LSTMFP_IERB
-	bclr	#0,LSTMFP_DDR
-	moveb	#LPSG_CONTROL,LPSG_SELECT
-	moveb	#0xff,LPSG_WRITE
-	moveb	#LPSG_IO_B,LPSG_SELECT
-	clrb	LPSG_WRITE
-	moveb	#LPSG_IO_A,LPSG_SELECT
-	moveb	LPSG_READ,%d0
+	bclr	#0,%a1@(LSTMFP_IERB)
+	bclr	#0,%a1@(LSTMFP_DDR)
+	moveb	#LPSG_CONTROL,%a1@(LPSG_SELECT)
+	moveb	#0xff,%a1@(LPSG_WRITE)
+	moveb	#LPSG_IO_B,%a1@(LPSG_SELECT)
+	clrb	%a1@(LPSG_WRITE)
+	moveb	#LPSG_IO_A,%a1@(LPSG_SELECT)
+	moveb	%a1@(LPSG_READ),%d0
 	bset	#5,%d0
-	moveb	%d0,LPSG_WRITE
+	moveb	%d0,%a1@(LPSG_WRITE)
 #elif defined(USE_SCC)
-	lea	LSCC_CTRL_B,%a0
+	lea	%a1@(LSCC_CTRL_B),%a0
 	lea	%pc@(scc_initable:w),%a1
 2:	moveb	%a1@+,%d0
 	jmi	3f
@@ -1000,12 +1033,12 @@
 	jra	2b
 3:	clrb	%a0@
 #elif defined(USE_MFP)
-	bclr	#1,LMFP_TSR
-	moveb   #0x88,LMFP_UCR
-	andb	#0x70,LMFP_TDCDR
-	moveb   #2,LMFP_TDDR
-	orb	#1,LMFP_TDCDR
-	bset	#1,LMFP_TSR
+	bclr	#1,%a1@(LMFP_TSR)
+	moveb   #0x88,%a1@(LMFP_UCR)
+	andb	#0x70,%a1@(LMFP_TDCDR)
+	moveb   #2,%a1@(LMFP_TDDR)
+	orb	#1,%a1@(LMFP_TDCDR)
+	bset	#1,%a1@(LMFP_TSR)
 #endif
 4:
 #endif
@@ -1140,6 +1173,8 @@
 SYMBOL_NAME_LABEL(availmem)
 	.long 0
 SYMBOL_NAME_LABEL(is_medusa)
+	.long 0
+SYMBOL_NAME_LABEL(is_hades)
 	.long 0
 SYMBOL_NAME_LABEL(m68k_pgtable_cachemode)
 	.long 0
diff -u --recursive --new-file v2.1.35/linux/arch/m68k/kernel/ints.c linux/arch/m68k/kernel/ints.c
--- v2.1.35/linux/arch/m68k/kernel/ints.c	Wed Sep 25 00:47:39 1996
+++ linux/arch/m68k/kernel/ints.c	Thu Apr 17 13:20:42 1997
@@ -50,6 +50,24 @@
 #define NUM_IRQ_NODES 100
 static irq_node_t nodes[NUM_IRQ_NODES];
 
+unsigned int local_irq_count[NR_CPUS];
+
+int __m68k_bh_counter;
+
+static void dummy_enable_irq(unsigned int irq);
+static void dummy_disable_irq(unsigned int irq);
+static int dummy_request_irq(unsigned int irq,
+		void (*handler) (int, void *, struct pt_regs *),
+		unsigned long flags, const char *devname, void *dev_id);
+static void dummy_free_irq(unsigned int irq, void *dev_id);
+
+void (*enable_irq) (unsigned int) = dummy_enable_irq;
+void (*disable_irq) (unsigned int) = dummy_disable_irq;
+
+int (*mach_request_irq) (unsigned int, void (*)(int, void *, struct pt_regs *),
+                      unsigned long, const char *, void *) = dummy_request_irq;
+void (*mach_free_irq) (unsigned int, void *) = dummy_free_irq;
+
 /*
  * void init_IRQ(void)
  *
@@ -92,14 +110,30 @@
 	return NULL;
 }
 
-int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
-                unsigned long flags, const char *devname, void *dev_id)
+/*
+ * We will keep these functions until I have convinced Linus to move
+ * the declaration of them from include/linux/sched.h to
+ * include/asm/irq.h.
+ */
+int request_irq(unsigned int irq,
+		void (*handler) (int, void *, struct pt_regs *),
+		unsigned long flags, const char *devname, void *dev_id)
+{
+	return mach_request_irq(irq, handler, flags, devname, dev_id);
+}
+
+void free_irq(unsigned int irq, void *dev_id)
 {
-	if (irq & IRQ_MACHSPEC)
-		return mach_request_irq(IRQ_IDX(irq), handler, flags, devname, dev_id);
+	mach_free_irq(irq, dev_id);
+}
 
+int sys_request_irq(unsigned int irq, 
+                    void (*handler)(int, void *, struct pt_regs *), 
+                    unsigned long flags, const char *devname, void *dev_id)
+{
 	if (irq < IRQ1 || irq > IRQ7) {
-		printk("%s: Incorrect IRQ %d from %s\n", __FUNCTION__, irq, devname);
+		printk("%s: Incorrect IRQ %d from %s\n",
+		       __FUNCTION__, irq, devname);
 		return -ENXIO;
 	}
 
@@ -109,7 +143,7 @@
 			       __FUNCTION__, irq, irq_list[irq].devname);
 			return -EBUSY;
 		}
-		if (flags & IRQ_FLG_REPLACE) {
+		if (!(flags & IRQ_FLG_REPLACE)) {
 			printk("%s: %s can't replace IRQ %d from %s\n",
 			       __FUNCTION__, devname, irq, irq_list[irq].devname);
 			return -EBUSY;
@@ -122,13 +156,8 @@
 	return 0;
 }
 
-void free_irq(unsigned int irq, void *dev_id)
+void sys_free_irq(unsigned int irq, void *dev_id)
 {
-	if (irq & IRQ_MACHSPEC) {
-		mach_free_irq(IRQ_IDX(irq), dev_id);
-		return;
-	}
-
 	if (irq < IRQ1 || irq > IRQ7) {
 		printk("%s: Incorrect IRQ %d\n", __FUNCTION__, irq);
 		return;
@@ -157,31 +186,42 @@
 	return 0;
 }
 
-void enable_irq(unsigned int irq)
+static void dummy_enable_irq(unsigned int irq)
 {
-	if ((irq & IRQ_MACHSPEC) && mach_enable_irq)
-		mach_enable_irq(IRQ_IDX(irq));
+	printk("calling uninitialized enable_irq()\n");
 }
 
-void disable_irq(unsigned int irq)
+static void dummy_disable_irq(unsigned int irq)
 {
-	if ((irq & IRQ_MACHSPEC) && mach_disable_irq)
-		mach_disable_irq(IRQ_IDX(irq));
+	printk("calling uninitialized disable_irq()\n");
+}
+
+static int dummy_request_irq(unsigned int irq,
+		void (*handler) (int, void *, struct pt_regs *),
+		unsigned long flags, const char *devname, void *dev_id)
+{
+	printk("calling uninitialized request_irq()\n");
+	return 0;
+}
+
+static void dummy_free_irq(unsigned int irq, void *dev_id)
+{
+	printk("calling uninitialized disable_irq()\n");
 }
 
 asmlinkage void process_int(unsigned long vec, struct pt_regs *fp)
 {
-	if (vec < VEC_INT1 || vec > VEC_INT7) {
+	if (vec >= VEC_INT1 && vec <= VEC_INT7) {
+		vec -= VEC_SPUR;
+		kstat.interrupts[vec]++;
+		irq_list[vec].handler(vec, irq_list[vec].dev_id, fp);
+	} else {
 		if (mach_process_int)
 			mach_process_int(vec, fp);
 		else
 			panic("Can't process interrupt vector %ld\n", vec);
 		return;
 	}
-
-	vec -= VEC_SPUR;
-	kstat.interrupts[vec]++;
-	irq_list[vec].handler(vec, irq_list[vec].dev_id, fp);
 }
 
 int get_irq_list(char *buf)
diff -u --recursive --new-file v2.1.35/linux/arch/m68k/kernel/m68k_ksyms.c linux/arch/m68k/kernel/m68k_ksyms.c
--- v2.1.35/linux/arch/m68k/kernel/m68k_ksyms.c	Thu Mar 27 14:39:59 1997
+++ linux/arch/m68k/kernel/m68k_ksyms.c	Thu Apr 17 13:20:42 1997
@@ -1,3 +1,4 @@
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/linkage.h>
 #include <linux/sched.h>
@@ -11,6 +12,8 @@
 #include <asm/pgtable.h>
 #include <asm/irq.h>
 #include <asm/semaphore.h>
+#include <asm/checksum.h>
+#include <asm/hardirq.h>
 
 asmlinkage long long __ashrdi3 (long long, int);
 extern char m68k_debug_device[];
@@ -31,13 +34,15 @@
 EXPORT_SYMBOL(mm_ptov);
 EXPORT_SYMBOL(mm_end_of_chunk);
 EXPORT_SYMBOL(m68k_debug_device);
-EXPORT_SYMBOL(request_irq);
-EXPORT_SYMBOL(free_irq);
 EXPORT_SYMBOL(dump_fpu);
 EXPORT_SYMBOL(dump_thread);
 EXPORT_SYMBOL(strnlen);
 EXPORT_SYMBOL(strrchr);
 EXPORT_SYMBOL(strstr);
+EXPORT_SYMBOL(local_irq_count);
+
+/* Networking helper routines. */
+EXPORT_SYMBOL(csum_partial_copy);
 
 /* The following are special because they're not called
    explicitly (the C compiler generates them).  Fortunately,
diff -u --recursive --new-file v2.1.35/linux/arch/m68k/kernel/process.c linux/arch/m68k/kernel/process.c
--- v2.1.35/linux/arch/m68k/kernel/process.c	Sun Jan 26 02:07:05 1997
+++ linux/arch/m68k/kernel/process.c	Thu Apr 17 13:20:42 1997
@@ -22,6 +22,7 @@
 #include <linux/malloc.h>
 #include <linux/user.h>
 #include <linux/a.out.h>
+#include <linux/reboot.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -43,6 +44,7 @@
 		goto out;
 
 	/* endless idle loop with no priority at all */
+	current->priority = -100;
 	current->counter = -100;
 	for (;;)
 		schedule();
@@ -52,12 +54,23 @@
 	return ret;
 }
 
-void hard_reset_now(void)
+void machine_restart(char * __unused)
 {
 	if (mach_reset)
 		mach_reset();
 }
 
+void machine_halt(void)
+{
+}
+
+void machine_power_off(void)
+{
+#if defined(CONFIG_APM) && defined(CONFIG_APM_POWER_OFF)
+	apm_set_power_state(APM_STATE_OFF);
+#endif
+}
+
 void show_regs(struct pt_regs * regs)
 {
 	printk("\n");
@@ -169,7 +182,7 @@
 
 /* Fill in the fpu structure for a core dump.  */
 
-int dump_fpu (struct user_m68kfp_struct *fpu)
+int dump_fpu (struct pt_regs *regs, struct user_m68kfp_struct *fpu)
 {
   char fpustate[216];
 
@@ -207,7 +220,7 @@
 	if (dump->start_stack < TASK_SIZE)
 		dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT;
 
-	dump->u_ar0 = (struct pt_regs *)(((int)(&dump->regs)) -((int)(dump)));
+	dump->u_ar0 = (struct user_regs_struct *)((int)&dump->regs - (int)dump);
 	sw = ((struct switch_stack *)regs) - 1;
 	dump->regs.d1 = regs->d1;
 	dump->regs.d2 = regs->d2;
@@ -230,7 +243,7 @@
 	dump->regs.pc = regs->pc;
 	dump->regs.fmtvec = (regs->format << 12) | regs->vector;
 	/* dump floating point stuff */
-	dump->u_fpvalid = dump_fpu (&dump->m68kfp);
+	dump->u_fpvalid = dump_fpu (regs, &dump->m68kfp);
 }
 
 /*
diff -u --recursive --new-file v2.1.35/linux/arch/m68k/kernel/ptrace.c linux/arch/m68k/kernel/ptrace.c
--- v2.1.35/linux/arch/m68k/kernel/ptrace.c	Sun Jan 26 02:07:05 1997
+++ linux/arch/m68k/kernel/ptrace.c	Thu Apr 17 13:20:43 1997
@@ -324,7 +324,6 @@
 asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
 {
 	struct task_struct *child;
-	struct user * dummy = NULL;
 	int ret;
 
 	lock_kernel();
diff -u --recursive --new-file v2.1.35/linux/arch/m68k/kernel/setup.c linux/arch/m68k/kernel/setup.c
--- v2.1.35/linux/arch/m68k/kernel/setup.c	Fri Dec 20 01:19:58 1996
+++ linux/arch/m68k/kernel/setup.c	Thu Apr 17 13:20:43 1997
@@ -55,11 +55,6 @@
 static char m68k_command_line[CL_SIZE];
 char saved_command_line[CL_SIZE];
 
-/* setup some dummy routines */
-static void dummy_waitbut(void)
-{
-}
-
 void (*mach_sched_init) (void (*handler)(int, void *, struct pt_regs *));
 /* machine dependent keyboard functions */
 int (*mach_keyb_init) (void);
@@ -68,11 +63,6 @@
 /* machine dependent irq functions */
 void (*mach_init_IRQ) (void);
 void (*(*mach_default_handler)[]) (int, void *, struct pt_regs *) = NULL;
-int (*mach_request_irq) (unsigned int, void (*)(int, void *, struct pt_regs *),
-                         unsigned long, const char *, void *);
-int (*mach_free_irq) (unsigned int, void *);
-void (*mach_enable_irq) (unsigned int) = NULL;
-void (*mach_disable_irq) (unsigned int) = NULL;
 void (*mach_get_model) (char *model) = NULL;
 int (*mach_get_hardware_list) (char *buffer) = NULL;
 int (*mach_get_irq_list) (char *) = NULL;
@@ -82,19 +72,15 @@
 void (*mach_gettod) (int*, int*, int*, int*, int*, int*);
 int (*mach_hwclk) (int, struct hwclk_time*) = NULL;
 int (*mach_set_clock_mmss) (unsigned long) = NULL;
-void (*mach_mksound)( unsigned int count, unsigned int ticks );
 void (*mach_reset)( void );
-void (*waitbut)(void) = dummy_waitbut;
 struct fb_info *(*mach_fb_init)(long *);
 long mach_max_dma_address = 0x00ffffff; /* default set to the lower 16MB */
-void (*mach_debug_init)(void);
 void (*mach_video_setup) (char *, int *);
 #ifdef CONFIG_BLK_DEV_FD
 int (*mach_floppy_init) (void) = NULL;
 void (*mach_floppy_setup) (char *, int *) = NULL;
 void (*mach_floppy_eject) (void) = NULL;
 #endif
-void (*mach_syms_export)(void) = NULL;
 
 extern int amiga_parse_bootinfo(const struct bi_record *);
 extern int atari_parse_bootinfo(const struct bi_record *);
@@ -105,10 +91,6 @@
 extern void config_sun3(void);
 extern void config_apollo(void);
 
-extern void register_console(void (*proc)(const char *));
-extern void ami_serial_print(const char *str);
-extern void ata_serial_print(const char *str);
-
 #define MASK_256K 0xfffc0000
 
 
@@ -166,12 +148,6 @@
 	extern int _etext, _edata, _end;
 	int i;
 	char *p, *q;
-
-	/* machtype is set up by head.S, thus we know our gender */
-	if (MACH_IS_AMIGA)
-		register_console(ami_serial_print);
-	if (MACH_IS_ATARI)
-		register_console(ata_serial_print);
 
 	/* The bootinfo is located right after the kernel bss */
 	m68k_parse_bootinfo((const struct bi_record *)&_end);
diff -u --recursive --new-file v2.1.35/linux/arch/m68k/kernel/signal.c linux/arch/m68k/kernel/signal.c
--- v2.1.35/linux/arch/m68k/kernel/signal.c	Fri Jan  3 08:48:37 1997
+++ linux/arch/m68k/kernel/signal.c	Thu Apr 17 13:20:43 1997
@@ -291,20 +291,23 @@
 	tframe = frame;
 
 	/* return address points to code on stack */
-	put_user((ulong)(frame+4), tframe); tframe++;
+
+	if(put_user((ulong)(frame+4), tframe))
+		do_exit(SIGSEGV);
+	tframe++;
 	if (current->exec_domain && current->exec_domain->signal_invmap)
-	    put_user(current->exec_domain->signal_invmap[signr], tframe);
+	    __put_user(current->exec_domain->signal_invmap[signr], tframe);
 	else
-	    put_user(signr, tframe);
+	    __put_user(signr, tframe);
 	tframe++;
 
-	put_user(regs->vector, tframe); tframe++;
+	__put_user(regs->vector, tframe); tframe++;
 	/* "scp" parameter.  points to sigcontext */
-	put_user((ulong)(frame+6), tframe); tframe++;
+	__put_user((ulong)(frame+6), tframe); tframe++;
 
 /* set up the return code... */
-	put_user(0xdefc0014,tframe); tframe++; /* addaw #20,sp */
-	put_user(0x70774e40,tframe); tframe++; /* moveq #119,d0; trap #0 */
+	__put_user(0xdefc0014,tframe); tframe++; /* addaw #20,sp */
+	__put_user(0x70774e40,tframe); tframe++; /* moveq #119,d0; trap #0 */
 
 /* Flush caches so the instructions will be correctly executed. (MA) */
 	cache_push_v ((unsigned long)frame, (int)tframe - (int)frame);
diff -u --recursive --new-file v2.1.35/linux/arch/m68k/kernel/sys_m68k.c linux/arch/m68k/kernel/sys_m68k.c
--- v2.1.35/linux/arch/m68k/kernel/sys_m68k.c	Sun Jan 26 02:07:05 1997
+++ linux/arch/m68k/kernel/sys_m68k.c	Thu Apr 17 13:20:43 1997
@@ -34,15 +34,11 @@
 	int error;
 
 	lock_kernel();
-	error = verify_area(VERIFY_WRITE,fildes,8);
-	if (error)
-		goto out;
 	error = do_pipe(fd);
-	if (error)
-		goto out;
-	put_user(fd[0],0+fildes);
-	put_user(fd[1],1+fildes);
-out:
+	if (!error) {
+		if (copy_to_user(fildes, fd, 2*sizeof(int)))
+			error = -EFAULT;
+	}
 	unlock_kernel();
 	return error;
 }
@@ -70,10 +66,10 @@
 	struct mmap_arg_struct a;
 
 	lock_kernel();
-	error = verify_area(VERIFY_READ, arg, sizeof(*arg));
-	if (error)
+	error = -EFAULT;
+	if (copy_from_user(&a, arg, sizeof(a)))
 		goto out;
-	copy_from_user(&a, arg, sizeof(a));
+
 	if (!(a.flags & MAP_ANONYMOUS)) {
 		error = -EBADF;
 		if (a.fd >= NR_OPEN || !(file = current->files->fd[a.fd]))
@@ -98,15 +94,11 @@
 asmlinkage int old_select(struct sel_arg_struct *arg)
 {
 	struct sel_arg_struct a;
-	int ret = -EFAULT;
 
-	lock_kernel();
 	if (copy_from_user(&a, arg, sizeof(a)))
-		goto out;
-	ret = sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
-out:
-	unlock_kernel();
-	return ret;
+		return -EFAULT;
+       /* sys_select() does the appropriate kernel locking */
+	return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
 }
 
 /*
@@ -134,9 +126,8 @@
 			ret = -EINVAL;
 			if (!ptr)
 				goto out;
-			if ((ret = verify_area (VERIFY_READ, ptr, sizeof(long))))
+			if ((ret = get_user(fourth.__pad, (void **) ptr)))
 				goto out;
-			get_user(fourth.__pad, (void **)ptr);
 			ret = sys_semctl (first, second, third, fourth);
 			goto out;
 			}
@@ -183,22 +174,13 @@
 			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_user (raddr, (ulong *) third);
-				ret = 0;
-				goto out;
-				}
-			case 1:	/* iBCS2 emulator entry point */
-				ret = -EINVAL;
-				if (get_fs() != get_ds())
-					goto out;
-				ret = sys_shmat (first, (char *) ptr, second, (ulong *) third);
+				ret = put_user (raddr, (ulong *) third);
 				goto out;
 			}
+			}
 		case SHMDT: 
 			ret = sys_shmdt ((char *)ptr);
 			goto out;
@@ -212,8 +194,7 @@
 			ret = -EINVAL;
 			goto out;
 		}
-	else
-		ret = -EINVAL;
+	ret = -EINVAL;
 out:
 	unlock_kernel();
 	return ret;
diff -u --recursive --new-file v2.1.35/linux/arch/m68k/kernel/traps.c linux/arch/m68k/kernel/traps.c
--- v2.1.35/linux/arch/m68k/kernel/traps.c	Fri Dec 20 01:19:59 1996
+++ linux/arch/m68k/kernel/traps.c	Thu Apr 17 13:20:43 1997
@@ -29,11 +29,15 @@
 #include <linux/linkage.h>
 
 #include <asm/setup.h>
+#include <asm/fpu.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/traps.h>
 #include <asm/pgtable.h>
 #include <asm/machdep.h>
+#ifdef CONFIG_KGDB
+#include <asm/kgdb.h>
+#endif
 
 /* assembler routines */
 asmlinkage void system_call(void);
@@ -140,10 +144,9 @@
 {
 	extern int console_loglevel;
 	console_loglevel = 15;
-	mach_debug_init();
 }
 
-char *vec_names[] = {
+static char *vec_names[] = {
 	"RESET SP", "RESET PC", "BUS ERROR", "ADDRESS ERROR",
 	"ILLEGAL INSTRUCTION", "ZERO DIVIDE", "CHK", "TRAPcc",
 	"PRIVILEGE VIOLATION", "TRACE", "LINE 1010", "LINE 1111",
@@ -162,17 +165,17 @@
 	"FPCP BSUN", "FPCP INEXACT", "FPCP DIV BY 0", "FPCP UNDERFLOW",
 	"FPCP OPERAND ERROR", "FPCP OVERFLOW", "FPCP SNAN",
 	"FPCP UNSUPPORTED OPERATION",
-	"MMU CONFIGUATION ERROR"
+	"MMU CONFIGURATION ERROR"
 	};
 
-char *space_names[] = {
+static char *space_names[] = {
 	"Space 0", "User Data", "User Program", "Space 3",
 	"Space 4", "Super Data", "Super Program", "CPU"
 	};
 
 
 
-extern void die_if_kernel(char *,struct pt_regs *,int);
+void die_if_kernel(char *,struct pt_regs *,int);
 asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
                              unsigned long error_code);
 
@@ -184,7 +187,7 @@
 	unsigned long fslw = fp->un.fmt4.pc; /* is really FSLW for access error */
 
 #ifdef DEBUG
-	printk("fslw=%#lx, fa=%#lx\n", ssw, fp->un.fmt4.effaddr);
+	printk("fslw=%#lx, fa=%#lx\n", fslw, fp->un.fmt4.effaddr);
 #endif
 
 	if (fslw & MMU060_BPE) {
@@ -194,7 +197,7 @@
 				      "movec %/d0,%/cacr"
 				      : : : "d0" );
 		/* return if there's no other error */
-		if (!(fslw & MMU060_ERR_BITS))
+		if ((!(fslw & MMU060_ERR_BITS)) && !(fslw & MMU060_SEE))
 			return;
 	}
 	
@@ -209,8 +212,13 @@
 		if (fslw & MMU060_MA)
 			addr = PAGE_ALIGN(addr);
 		do_page_fault(&fp->ptregs, addr, errorcode);
-	}
-	else {
+	} else if (fslw & (MMU060_SEE)){
+		/* Software Emulation Error. Probably an instruction
+		 * using an unsupported addressing mode
+		 */
+		send_sig (SIGSEGV, current, 1);
+	} else {
+		printk("pc=%#lx, fa=%#lx\n", fp->ptregs.pc, fp->un.fmt4.effaddr);
 		printk( "68060 access error, fslw=%lx\n", fslw );
 		trap_c( fp );
 	}
@@ -349,7 +357,7 @@
 }
 #endif /* CONFIG_M68040 */
 
-#if defined(CONFIG_M68020_OR_M68030)
+#if defined(CPU_M68020_OR_M68030)
 static inline void bus_error030 (struct frame *fp)
 {
 	volatile unsigned short temp;
@@ -628,7 +636,7 @@
 	asm volatile ("ploadr #2,%0@" : /* no outputs */
 		      : "a" (addr));
 }
-#endif /* CONFIG_M68020_OR_M68030 */
+#endif /* CPU_M68020_OR_M68030 */
 
 asmlinkage void buserr_c(struct frame *fp)
 {
@@ -651,7 +659,7 @@
 	  access_error040 (fp);
 	  break;
 #endif
-#if defined (CONFIG_M68020_OR_M68030)
+#if defined (CPU_M68020_OR_M68030)
 	case 0xa:
 	case 0xb:
 	  bus_error030 (fp);
@@ -675,6 +683,11 @@
 
 static void dump_stack(struct frame *fp)
 {
+#ifdef CONFIG_KGDB
+	/* This will never return to here, if kgdb has been initialized. And if
+	 * it returns from there, then to where the error happened... */
+	enter_kgdb( &fp->ptregs );
+#else
 	unsigned long *stack, *endstack, addr, module_start, module_end;
 	extern char _start, _etext;
 	int i;
@@ -772,10 +785,15 @@
 	for (i = 0; i < 10; i++)
 		printk("%04x ", 0xffff & ((short *) fp->ptregs.pc)[i]);
 	printk ("\n");
+#endif
 }
 
 void bad_super_trap (struct frame *fp)
 {
+#ifdef CONFIG_KGDB
+	/* Save the register dump if we'll enter kgdb anyways */
+	if (!kgdb_initialized) {
+#endif
 	console_verbose();
 	if (fp->ptregs.vector < 4*sizeof(vec_names)/sizeof(vec_names[0]))
 		printk ("*** %s ***   FORMAT=%X\n",
@@ -805,6 +823,9 @@
 				fp->ptregs.pc);
 	}
 	printk ("Current process id is %d\n", current->pid);
+#ifdef CONFIG_KGDB
+	}
+#endif
 	die_if_kernel("BAD KERNEL TRAP", &fp->ptregs, 0);
 }
 
@@ -863,7 +884,7 @@
 	    case VEC_FPOVER:
 	    case VEC_FPNAN:
 		{
-		  unsigned char fstate[216];
+		  unsigned char fstate[FPSTATESIZE];
 
 		  __asm__ __volatile__ (".chip 68k/68881\n\t"
 		  			"fsave %0@\n\t"
@@ -905,9 +926,13 @@
 	if (!(fp->sr & PS_S))
 		return;
 
+#ifdef CONFIG_KGDB
+	/* Save the register dump if we'll enter kgdb anyways */
+	if (!kgdb_initialized) {
+#endif
 	console_verbose();
 	printk("%s: %08x\n",str,nr);
-	printk("PC: %08lx\nSR: %04x  SP: %p\n", fp->pc, fp->sr, fp);
+	printk("PC: [<%08lx>]\nSR: %04x  SP: %p\n", fp->pc, fp->sr, fp);
 	printk("d0: %08lx    d1: %08lx    d2: %08lx    d3: %08lx\n",
 	       fp->d0, fp->d1, fp->d2, fp->d3);
 	printk("d4: %08lx    d5: %08lx    a0: %08lx    a1: %08lx\n",
@@ -917,6 +942,18 @@
 		printk("Corrupted stack page\n");
 	printk("Process %s (pid: %d, stackpage=%08lx)\n",
 		current->comm, current->pid, current->kernel_stack_page);
+#ifdef CONFIG_KGDB
+	}
+#endif
 	dump_stack((struct frame *)fp);
+	do_exit(SIGSEGV);
+}
+
+/*
+ * This function is called if an error occur while accessing
+ * user-space from the fpsp040 code.
+ */
+asmlinkage void fpsp040_die(void)
+{
 	do_exit(SIGSEGV);
 }
diff -u --recursive --new-file v2.1.35/linux/arch/m68k/lib/checksum.c linux/arch/m68k/lib/checksum.c
--- v2.1.35/linux/arch/m68k/lib/checksum.c	Fri Jan  3 08:48:37 1997
+++ linux/arch/m68k/lib/checksum.c	Thu Apr 17 13:20:43 1997
@@ -19,8 +19,8 @@
  *		(%1). Thanks to Roman Hodek for pointing this out.
  *		B: GCC seems to mess up if one uses too many
  *		data-registers to hold input values and one tries to
- *		specify d0 and d1 as scratch registers. Letting gcc choose these
- *      registers itself solves the problem.
+ *		specify d0 and d1 as scratch registers. Letting gcc
+ *		choose these registers itself solves the problem.
  *
  *		This program is free software; you can redistribute it and/or
  *		modify it under the terms of the GNU General Public License
@@ -124,13 +124,20 @@
 
 
 /*
- * copy from user space while checksumming, otherwise like csum_partial
+ * copy from user space while checksumming, with exception handling.
  */
 
 unsigned int
-csum_partial_copy_fromuser(const char *src, char *dst, int len, int sum)
+csum_partial_copy_from_user(const char *src, char *dst, int len,
+			    int sum, int *csum_err)
 {
+	/*
+	 * GCC doesn't like more than 10 operands for the asm
+	 * statements so we have to use tmp2 for the error
+	 * code.
+	 */
 	unsigned long tmp1, tmp2;
+
 	__asm__("movel %2,%4\n\t"
 		"btst #1,%4\n\t"	/* Check alignment */
 		"jeq 2f\n\t"
@@ -226,27 +233,49 @@
 	     "6:\t"
 		"addl %5,%0\n\t"	/* now add rest long to sum */
 		"clrl %5\n\t"
-		"addxl %5,%0\n"		/* add X bit */
-	     "7:\n"
+		"addxl %5,%0\n\t"	/* add X bit */
+	     "7:\t"
+		"clrl %5\n"		/* no error - clear return value */
+	     "8:\n"
+		".section .fixup,\"ax\"\n"
+		".even\n"
+	     "9:\t"
+		"moveq #-14,%5\n\t"	/* -EFAULT, out of inputs to asm ;( */
+		"jra 8b\n"
+		".previous\n"
 		".section __ex_table,\"a\"\n"
-		".long 10b,7b\n"
-		".long 11b,7b\n"
-		".long 12b,7b\n"
-		".long 13b,7b\n"
-		".long 14b,7b\n"
-		".long 15b,7b\n"
-		".long 16b,7b\n"
-		".long 17b,7b\n"
-		".long 18b,7b\n"
-		".long 19b,7b\n"
-		".long 20b,7b\n"
-		".long 21b,7b\n"
+		".long 10b,9b\n"
+		".long 11b,9b\n"
+		".long 12b,9b\n"
+		".long 13b,9b\n"
+		".long 14b,9b\n"
+		".long 15b,9b\n"
+		".long 16b,9b\n"
+		".long 17b,9b\n"
+		".long 18b,9b\n"
+		".long 19b,9b\n"
+		".long 20b,9b\n"
+		".long 21b,9b\n"
 		".previous"
 		: "=d" (sum), "=d" (len), "=a" (src), "=a" (dst),
-		  "=&d" (tmp1), "=&d" (tmp2)
+		  "=&d" (tmp1), "=d" (tmp2)
 		: "0" (sum), "1" (len), "2" (src), "3" (dst)
 	    );
+
+	*csum_err = tmp2;
+
 	return(sum);
+}
+
+/*
+ * This one will go away soon.
+ */
+unsigned int
+csum_partial_copy_fromuser(const char *src, char *dst, int len, int sum)
+{
+	int dummy;
+
+	return csum_partial_copy_from_user(src, dst, len, sum, &dummy);
 }
 /*
  * copy from kernel space while checksumming, otherwise like csum_partial
diff -u --recursive --new-file v2.1.35/linux/arch/m68k/lib/semaphore.S linux/arch/m68k/lib/semaphore.S
--- v2.1.35/linux/arch/m68k/lib/semaphore.S	Fri Nov 22 05:56:35 1996
+++ linux/arch/m68k/lib/semaphore.S	Thu Apr 17 13:20:43 1997
@@ -9,18 +9,26 @@
 #include <linux/linkage.h>
 
 /*
- * "down_failed" is called with the eventual return address
- * in %a0, and the address of the semaphore in %a1. We need
- * to call "__down()", and then re-try until we succeed..
+ * The semaphore operations have a special calling sequence that
+ * allow us to do a simpler in-line version of them. These routines
+ * need to convert that sequence back into the C sequence when
+ * there is contention on the semaphore.
  */
 ENTRY(__down_failed)
 	moveml %a0/%d0/%d1,-(%sp)
-1:	movel %a1,-(%sp)
+	movel %a1,-(%sp)
 	jbsr SYMBOL_NAME(__down)
 	movel (%sp)+,%a1
-	subql #1,(%a1)
-	jmi 1b
 	movel (%sp)+,%d0
+	movel (%sp)+,%d1
+	rts
+
+ENTRY(__down_failed_interruptible)
+	movel %a0,-(%sp)
+	movel %d1,-(%sp)
+	movel %a1,-(%sp)
+	jbsr SYMBOL_NAME(__down_interruptible)
+	movel (%sp)+,%a1
 	movel (%sp)+,%d1
 	rts
 
diff -u --recursive --new-file v2.1.35/linux/arch/m68k/mm/extable.c linux/arch/m68k/mm/extable.c
--- v2.1.35/linux/arch/m68k/mm/extable.c	Fri Dec 27 02:03:20 1996
+++ linux/arch/m68k/mm/extable.c	Thu Apr 17 13:20:43 1997
@@ -46,7 +46,7 @@
 		if (mp->ex_table_start == NULL)
 			continue;
 		ret = search_one_table(mp->ex_table_start,
-				       mp->ex_table_stop-1, addr);
+				       mp->ex_table_end-1, addr);
 		if (ret) return ret;
 	}
 #endif
diff -u --recursive --new-file v2.1.35/linux/arch/m68k/mm/fault.c linux/arch/m68k/mm/fault.c
--- v2.1.35/linux/arch/m68k/mm/fault.c	Sat Dec 21 04:24:02 1996
+++ linux/arch/m68k/mm/fault.c	Thu Apr 17 13:20:43 1997
@@ -108,10 +108,7 @@
 	up(&mm->mmap_sem);
 
 	/* Are we prepared to handle this fault?  */
-	if (CPU_IS_060 && regs->format == 4)
-		fault_pc = ((struct frame *)regs)->un.fmt4.pc;
-	else
-		fault_pc = regs->pc;
+	fault_pc = regs->pc;
 	if ((fixup = search_exception_table(fault_pc)) != 0) {
 		struct pt_regs *tregs;
 		printk(KERN_DEBUG "Exception at [<%lx>] (%lx)\n", fault_pc, fixup);
diff -u --recursive --new-file v2.1.35/linux/arch/m68k/mm/init.c linux/arch/m68k/mm/init.c
--- v2.1.35/linux/arch/m68k/mm/init.c	Mon Apr 14 16:28:06 1997
+++ linux/arch/m68k/mm/init.c	Thu Apr 17 13:20:43 1997
@@ -109,6 +109,8 @@
 	else
 		ptablep = (pte_t *)__get_free_page(GFP_KERNEL);
 
+	flush_page_to_ram((unsigned long) ptablep);
+	flush_tlb_kernel_page((unsigned long) ptablep);
 	nocache_page ((unsigned long)ptablep);
 
 	return ptablep;
@@ -293,8 +295,6 @@
 {
 	int chunk;
 	unsigned long mem_avail = 0;
-	/* pointer to page table for kernel stacks */
-	extern unsigned long availmem;
 
 #ifdef DEBUG
 	{
@@ -324,21 +324,12 @@
 
 	for (chunk = 0; chunk < m68k_num_memory; chunk++) {
 		mem_avail = map_chunk (m68k_memory[chunk].addr,
-				       m68k_memory[chunk].size, &availmem);
+				       m68k_memory[chunk].size, &start_mem);
 
 	}
 	flush_tlb_all();
 #ifdef DEBUG
 	printk ("memory available is %ldKB\n", mem_avail >> 10);
-#endif
-
-	/*
-	 * virtual address after end of kernel
-	 * "availmem" is setup by the code in head.S.
-	 */
-	start_mem = availmem;
-
-#ifdef DEBUG
 	printk ("start_mem is %#lx\nvirtual_end is %#lx\n",
 		start_mem, end_mem);
 #endif
@@ -401,7 +392,7 @@
 	printk ("before free_area_init\n");
 #endif
 
-	return free_area_init (start_mem, end_mem);
+	return PAGE_ALIGN(free_area_init (start_mem, end_mem));
 }
 
 void mem_init(unsigned long start_mem, unsigned long end_mem)
diff -u --recursive --new-file v2.1.35/linux/arch/m68k/mm/memory.c linux/arch/m68k/mm/memory.c
--- v2.1.35/linux/arch/m68k/mm/memory.c	Fri Dec 20 01:19:59 1996
+++ linux/arch/m68k/mm/memory.c	Thu Apr 17 13:20:43 1997
@@ -63,11 +63,12 @@
 			return 0;
 		}
 
-		if (!(dp->page = __get_free_page (GFP_KERNEL))) {
+		if (!(dp->page = get_free_page (GFP_KERNEL))) {
 			kfree (dp);
 			return 0;
 		}
 
+		flush_tlb_kernel_page((unsigned long) dp->page);
 		nocache_page (dp->page);
 
 		dp->alloced = 0;
@@ -210,10 +211,11 @@
 		return NULL;
 	}
 	if (!(page = kptr_pages.page[i])) {
-		if (!(page = (pmd_tablepage *)__get_free_page(GFP_KERNEL))) {
+		if (!(page = (pmd_tablepage *)get_free_page(GFP_KERNEL))) {
 			printk("No space for kernel pointer table!\n");
 			return NULL;
 		}
+		flush_tlb_kernel_page((unsigned long) page);
 		nocache_page((u_long)(kptr_pages.page[i] = page));
 	}
 	asm volatile("bfset %0@{%1,#1}"
@@ -306,21 +308,31 @@
 	if (CPU_IS_030) {
 	    unsigned long ttreg;
 	    
-	    asm volatile( "pmove %/tt0,%0@" : : "a" (&ttreg) );
+	    asm volatile( ".chip 68030\n\t"
+			  "pmove %/tt0,%0@\n\t"
+			  ".chip 68k"
+			  : : "a" (&ttreg) );
 	    if (transp_transl_matches( ttreg, vaddr ))
 		return vaddr;
-	    asm volatile( "pmove %/tt1,%0@" : : "a" (&ttreg) );
+	    asm volatile( ".chip 68030\n\t"
+			  "pmove %/tt1,%0@\n\t"
+			  ".chip 68k"
+			  : : "a" (&ttreg) );
 	    if (transp_transl_matches( ttreg, vaddr ))
 		return vaddr;
 	}
-	else {
-	    register unsigned long ttreg __asm__( "d0" );
+	else if (CPU_IS_040_OR_060) {
+	    unsigned long ttreg;
 	    
-	    asm volatile( ".long 0x4e7a0006" /* movec %dtt0,%d0 */
+	    asm volatile( ".chip 68040\n\t"
+			  "movec %%dtt0,%0\n\t"
+			  ".chip 68k"
 			  : "=d" (ttreg) );
 	    if (transp_transl_matches( ttreg, vaddr ))
 		return vaddr;
-	    asm volatile( ".long 0x4e7a0007" /* movec %dtt1,%d0 */
+	    asm volatile( ".chip 68040\n\t"
+			  "movec %%dtt1,%0\n\t"
+			  ".chip 68k"
 			  : "=d" (ttreg) );
 	    if (transp_transl_matches( ttreg, vaddr ))
 		return vaddr;
diff -u --recursive --new-file v2.1.35/linux/arch/sparc/defconfig linux/arch/sparc/defconfig
--- v2.1.35/linux/arch/sparc/defconfig	Mon Apr 14 16:28:06 1997
+++ linux/arch/sparc/defconfig	Thu Apr 17 13:20:43 1997
@@ -145,7 +145,7 @@
 #
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
 #
-# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_MULTI_LUN=y
 CONFIG_SCSI_CONSTANTS=y
 
 #
diff -u --recursive --new-file v2.1.35/linux/arch/sparc/kernel/entry.S linux/arch/sparc/kernel/entry.S
--- v2.1.35/linux/arch/sparc/kernel/entry.S	Mon Apr 14 16:28:07 1997
+++ linux/arch/sparc/kernel/entry.S	Tue Apr 15 21:47:23 1997
@@ -1,4 +1,4 @@
-/* $Id: entry.S,v 1.137 1997/04/14 05:38:17 davem Exp $
+/* $Id: entry.S,v 1.138 1997/04/15 09:00:50 davem Exp $
  * arch/sparc/kernel/entry.S:  Sparc trap low-level entry points.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -301,15 +301,26 @@
 	mov	%l7, %o0		! irq level
 	call	C_LABEL(handler_irq)
 	 add	%sp, REGWIN_SZ, %o1	! pt_regs ptr
-
-#if 1 /* ndef __SMP__ */ /* You don't want to know... -DaveM */
 	wr	%l0, PSR_ET, %psr
 	WRITE_PAUSE
-#endif
 
 	RESTORE_ALL
 
 #ifdef __SMP__
+	/* SMP per-cpu ticker interrupts are handled specially. */
+smp_ticker:
+	bne	real_irq_continue
+	 or	%l0, PSR_PIL, %g2
+	wr	%g2, 0x0, %psr
+	WRITE_PAUSE
+	wr	%g2, PSR_ET, %psr
+	WRITE_PAUSE
+	call	C_LABEL(smp_percpu_timer_interrupt)
+	 add	%sp, REGWIN_SZ, %o0
+	wr	%l0, PSR_ET, %psr
+	WRITE_PAUSE
+	RESTORE_ALL
+
 	/* Here is where we check for possible SMP IPI passed to us
 	 * on some level other than 15 which is the NMI and only used
 	 * for cross calls.  That has a seperate entry point below.
@@ -322,8 +333,9 @@
 	sll	%o3, 12, %o3
 	ld	[%o5 + %o3], %o1
 	andcc	%o1, %o4, %g0
-	be	real_irq_continue
-	 cmp	%l7, 13
+	be,a	smp_ticker
+	 cmp	%l7, 14
+	cmp	%l7, 13
 	add	%o5, %o3, %o5
 	bne,a	1f
 	 sethi	%hi(0x40000000), %o2
diff -u --recursive --new-file v2.1.35/linux/arch/sparc/kernel/head.S linux/arch/sparc/kernel/head.S
--- v2.1.35/linux/arch/sparc/kernel/head.S	Mon Mar 17 14:54:20 1997
+++ linux/arch/sparc/kernel/head.S	Thu Apr 17 13:20:43 1997
@@ -1,4 +1,4 @@
-/* $Id: head.S,v 1.79 1997/03/04 16:26:31 jj Exp $
+/* $Id: head.S,v 1.81 1997/04/16 07:15:48 davem Exp $
  * head.S: The initial boot code for the Sparc port of Linux.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
diff -u --recursive --new-file v2.1.35/linux/arch/sparc/kernel/irq.c linux/arch/sparc/kernel/irq.c
--- v2.1.35/linux/arch/sparc/kernel/irq.c	Mon Apr 14 16:28:07 1997
+++ linux/arch/sparc/kernel/irq.c	Tue Apr 22 22:39:12 1997
@@ -1,4 +1,4 @@
-/*  $Id: irq.c,v 1.66 1997/04/14 05:38:21 davem Exp $
+/*  $Id: irq.c,v 1.72 1997/04/20 11:41:26 ecd Exp $
  *  arch/sparc/kernel/irq.c:  Interrupt request handling routines. On the
  *                            Sparc the IRQ's are basically 'cast in stone'
  *                            and you are supposed to probe the prom's device
@@ -41,6 +41,10 @@
 #include <asm/hardirq.h>
 #include <asm/softirq.h>
 
+#ifdef __SMP_PROF__
+extern volatile unsigned long smp_local_timer_ticks[1+NR_CPUS];
+#endif
+
 /*
  * Dave Redman (djhr@tadpole.co.uk)
  *
@@ -71,11 +75,11 @@
 void (*disable_irq)(unsigned int) = (void (*)(unsigned int)) irq_panic;
 void (*enable_pil_irq)(unsigned int) = (void (*)(unsigned int)) irq_panic;
 void (*disable_pil_irq)(unsigned int) = (void (*)(unsigned int)) irq_panic;
-void (*clear_clock_irq)( void ) = irq_panic;
-void (*clear_profile_irq)( void ) = irq_panic;
-void (*load_profile_irq)( unsigned int ) =  (void (*)(unsigned int)) irq_panic;
-void (*init_timers)( void (*)(int, void *,struct pt_regs *)) =
-    (void (*)( void (*)(int, void *,struct pt_regs *))) irq_panic;
+void (*clear_clock_irq)(void) = irq_panic;
+void (*clear_profile_irq)(int) = (void (*)(int)) irq_panic;
+void (*load_profile_irq)(int, unsigned int) =  (void (*)(int, unsigned int)) irq_panic;
+void (*init_timers)(void (*)(int, void *,struct pt_regs *)) =
+    (void (*)(void (*)(int, void *,struct pt_regs *))) irq_panic;
 
 #ifdef __SMP__
 void (*set_cpu_int)(int, int);
@@ -128,6 +132,109 @@
 	return len;
 }
 
+#ifdef __SMP_PROF__
+
+static unsigned int int_count[NR_CPUS][NR_IRQS] = {{0},};
+
+extern unsigned int prof_multiplier[NR_CPUS];
+extern unsigned int prof_counter[NR_CPUS];
+
+int get_smp_prof_list(char *buf) {
+	int i,j, len = 0;
+	struct irqaction * action;
+	unsigned long sum_spins = 0;
+	unsigned long sum_spins_syscall = 0;
+	unsigned long sum_spins_sys_idle = 0;
+	unsigned long sum_smp_idle_count = 0;
+	unsigned long sum_local_timer_ticks = 0;
+
+	for (i=0;i<smp_num_cpus;i++) {
+		int cpunum = cpu_logical_map[i];
+		sum_spins+=smp_spins[cpunum];
+		sum_spins_syscall+=smp_spins_syscall[cpunum];
+		sum_spins_sys_idle+=smp_spins_sys_idle[cpunum];
+		sum_smp_idle_count+=smp_idle_count[cpunum];
+		sum_local_timer_ticks+=smp_local_timer_ticks[cpunum];
+	}
+
+	len += sprintf(buf+len,"CPUS: %10i \n", smp_num_cpus);
+	len += sprintf(buf+len,"            SUM ");
+	for (i=0;i<smp_num_cpus;i++)
+		len += sprintf(buf+len,"        P%1d ",cpu_logical_map[i]);
+	len += sprintf(buf+len,"\n");
+	for (i = 0 ; i < NR_IRQS ; i++) {
+		action = *(i + irq_action);
+		if (!action || !action->handler)
+			continue;
+		len += sprintf(buf+len, "%3d: %10d ",
+			i, kstat.interrupts[i]);
+		for (j=0;j<smp_num_cpus;j++)
+			len+=sprintf(buf+len, "%10d ",
+				int_count[cpu_logical_map[j]][i]);
+		len += sprintf(buf+len, "%c %s",
+			(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, "\n");
+	}
+	len+=sprintf(buf+len, "LCK: %10lu",
+		sum_spins);
+
+	for (i=0;i<smp_num_cpus;i++)
+		len+=sprintf(buf+len," %10lu",smp_spins[cpu_logical_map[i]]);
+
+	len +=sprintf(buf+len,"   spins from int\n");
+
+	len+=sprintf(buf+len, "LCK: %10lu",
+		sum_spins_syscall);
+
+	for (i=0;i<smp_num_cpus;i++)
+		len+=sprintf(buf+len," %10lu",smp_spins_syscall[cpu_logical_map[i]]);
+
+	len +=sprintf(buf+len,"   spins from syscall\n");
+
+	len+=sprintf(buf+len, "LCK: %10lu",
+		sum_spins_sys_idle);
+
+	for (i=0;i<smp_num_cpus;i++)
+		len+=sprintf(buf+len," %10lu",smp_spins_sys_idle[cpu_logical_map[i]]);
+
+	len +=sprintf(buf+len,"   spins from sysidle\n");
+	len+=sprintf(buf+len,"IDLE %10lu",sum_smp_idle_count);
+
+	for (i=0;i<smp_num_cpus;i++)
+		len+=sprintf(buf+len," %10lu",smp_idle_count[cpu_logical_map[i]]);
+
+	len +=sprintf(buf+len,"   idle ticks\n");
+
+	len+=sprintf(buf+len,"TICK %10lu",sum_local_timer_ticks);
+	for (i=0;i<smp_num_cpus;i++)
+		len+=sprintf(buf+len," %10lu",smp_local_timer_ticks[cpu_logical_map[i]]);
+
+	len +=sprintf(buf+len,"   local APIC timer ticks\n");
+
+	len+=sprintf(buf+len,"MULT:          ");
+	for (i=0;i<smp_num_cpus;i++)
+		len+=sprintf(buf+len," %10u",prof_multiplier[cpu_logical_map[i]]);
+	len +=sprintf(buf+len,"   profiling multiplier\n");
+
+	len+=sprintf(buf+len,"COUNT:         ");
+	for (i=0;i<smp_num_cpus;i++)
+		len+=sprintf(buf+len," %10u",prof_counter[cpu_logical_map[i]]);
+
+	len +=sprintf(buf+len,"   profiling counter\n");
+
+	len+=sprintf(buf+len, "IPI: %10lu   received\n",
+		ipi_count);
+
+	return len;
+}
+#endif 
+
 void free_irq(unsigned int irq, void *dev_id)
 {
 	struct irqaction * action;
@@ -185,7 +292,11 @@
 
 /* Per-processor IRQ locking depth, both SMP and non-SMP code use this. */
 unsigned int local_irq_count[NR_CPUS];
-atomic_t __sparc_bh_counter;
+#ifdef __SMP__
+atomic_t __sparc_bh_counter = ATOMIC_INIT(0);
+#else
+int __sparc_bh_counter = 0;
+#endif
 
 #ifdef __SMP__
 /* SMP interrupt locking on Sparc. */
@@ -200,49 +311,10 @@
 spinlock_t global_bh_lock = SPIN_LOCK_UNLOCKED;
 
 /* Global IRQ locking depth. */
-atomic_t global_irq_count = ATOMIC_INIT;
-
-#define irq_active(cpu) \
-	(atomic_read(&global_irq_count) != local_irq_count[cpu])
-
-static unsigned long previous_irqholder;
-
-#define INIT_STUCK 10000000
-
-#define STUCK \
-if (!--stuck) { \
-	printk("wait_on_irq CPU#%d stuck at %08lx, waiting for [%08lx:%x] " \
-	       "(local=[%d(%x:%x:%x:%x)], global=[%d:%x]) ", \
-	       cpu, where, previous_irqholder, global_irq_holder, \
-	       local_count, local_irq_count[0], local_irq_count[1], \
-	       local_irq_count[2], local_irq_count[3], \
-	       atomic_read(&global_irq_count), global_irq_lock); \
-	printk("g[%d:%x]\n", atomic_read(&global_irq_count), global_irq_lock); \
-	stuck = INIT_STUCK; \
-}
-
-static inline void wait_on_irq(int cpu, unsigned long where)
-{
-	int stuck = INIT_STUCK;
-	int local_count = local_irq_count[cpu];
-
-	while(local_count != atomic_read(&global_irq_count)) {
-		atomic_sub(local_count, &global_irq_count);
-		spin_unlock(&global_irq_lock);
-		while(1) {
-			STUCK;
-			if(atomic_read(&global_irq_count))
-				continue;
-			if(global_irq_lock)
-				continue;
-			if(spin_trylock(&global_irq_lock))
-				break;
-		}
-		atomic_add(local_count, &global_irq_count);
-	}
-}
+atomic_t global_irq_count = ATOMIC_INIT(0);
 
 /* There has to be a better way. */
+/* XXX Must write faster version in irqlock.S -DaveM */
 void synchronize_irq(void)
 {
 	int cpu = smp_processor_id();
@@ -259,123 +331,6 @@
 	}
 }
 
-#undef INIT_STUCK
-#define INIT_STUCK 10000000
-
-#undef STUCK
-#define STUCK \
-if (!--stuck) {printk("get_irqlock stuck at %08lx, waiting for %08lx\n", where, previous_irqholder); stuck = INIT_STUCK;}
-
-static inline void get_irqlock(int cpu, unsigned long where)
-{
-	int stuck = INIT_STUCK;
-
-	if(!spin_trylock(&global_irq_lock)) {
-		if((unsigned char) cpu == global_irq_holder)
-			return;
-		do {
-			do {
-				STUCK;
-				barrier();
-			} while(global_irq_lock);
-		} while(!spin_trylock(&global_irq_lock));
-	}
-	wait_on_irq(cpu, where);
-	global_irq_holder = cpu;
-	previous_irqholder = where;
-}
-
-void __global_cli(void)
-{
-	int cpu = smp_processor_id();
-	unsigned long where;
-
-	__asm__ __volatile__("mov %%i7, %0\n\t" : "=r" (where));
-	__cli();
-	get_irqlock(cpu, where);
-}
-
-void __global_sti(void)
-{
-	release_irqlock(smp_processor_id());
-	__sti();
-}
-
-/* Yes, I know this is broken, but for the time being...
- *
- * On Sparc we must differentiate between real local processor
- * interrupts being disabled and global interrupt locking, this
- * is so that interrupt handlers which call this stuff don't get
- * interrupts turned back on when restore_flags() runs because
- * our current drivers will be very surprised about this, yes I
- * know they need to be fixed... -DaveM
- */
-unsigned long __global_save_flags(void)
-{
-	unsigned long flags, retval = 0;
-
-	__save_flags(flags);
-	if(global_irq_holder == (unsigned char) smp_processor_id())
-		retval |= 1;
-	if(flags & PSR_PIL)
-		retval |= 2;
-	return retval;
-}
-
-void __global_restore_flags(unsigned long flags)
-{
-	if(flags & 1) {
-		__global_cli();
-	} else {
-		release_irqlock(smp_processor_id());
-
-		if(flags & 2)
-			__cli();
-		else
-			__sti();
-	}
-}
-
-#undef INIT_STUCK
-#define INIT_STUCK 200000000
-
-#undef STUCK
-#define STUCK \
-if (!--stuck) { \
-	printk("irq_enter stuck (irq=%d, cpu=%d, global=%d)\n", \
-	       irq, cpu, global_irq_holder); \
-	stuck = INIT_STUCK; \
-}
-
-static void irq_enter(int cpu, int irq)
-{
-	extern void smp_irq_rotate(int cpu);
-	int stuck = INIT_STUCK;
-
-	smp_irq_rotate(cpu);
-	hardirq_enter(cpu);
-	while(global_irq_lock) {
-		if((unsigned char) cpu == global_irq_holder) {
-			printk("YEEEE Local interrupts enabled, global disabled\n");
-			break;
-		}
-		STUCK;
-		barrier();
-	}
-}
-
-static void irq_exit(int cpu, int irq)
-{
-	__cli();
-	hardirq_exit(cpu);
-	release_irqlock(cpu);
-}
-
-#else /* !__SMP__ */
-
-#define irq_enter(cpu, irq)	(local_irq_count[cpu]++)
-#define irq_exit(cpu, irq)	(local_irq_count[cpu]--)
-
 #endif /* __SMP__ */
 
 void unexpected_irq(int irq, void *dev_id, struct pt_regs * regs)
@@ -406,9 +361,17 @@
 	struct irqaction * action;
 	unsigned int cpu_irq = irq & NR_IRQS;
 	int cpu = smp_processor_id();
+#ifdef __SMP__
+	extern void smp_irq_rotate(int cpu);
+#endif
 	
 	disable_pil_irq(cpu_irq);
-	irq_enter(cpu, irq);
+#ifdef __SMP__
+	/* Only rotate on lower priority IRQ's (scsi, ethernet, etc.). */
+	if(irq < 10)
+		smp_irq_rotate(cpu);
+#endif
+	irq_enter(cpu, cpu_irq);
 	action = *(cpu_irq + irq_action);
 	kstat.interrupts[cpu_irq]++;
 	do {
@@ -417,7 +380,7 @@
 		action->handler(irq, action->dev_id, regs);
 		action = action->next;
 	} while (action);
-	irq_exit(cpu, irq);
+	irq_exit(cpu, cpu_irq);
 	enable_pil_irq(cpu_irq);
 }
 
@@ -432,7 +395,7 @@
 	irq_enter(cpu, irq);
 	floppy_interrupt(irq, dev_id, regs);
 	irq_exit(cpu, irq);
-	disable_pil_irq(irq);
+	enable_pil_irq(irq);
 }
 #endif
 
@@ -596,12 +559,12 @@
  */
 unsigned long probe_irq_on(void)
 {
-  return 0;
+	return 0;
 }
 
 int probe_irq_off(unsigned long mask)
 {
-  return 0;
+	return 0;
 }
 
 /* djhr
diff -u --recursive --new-file v2.1.35/linux/arch/sparc/kernel/ptrace.c linux/arch/sparc/kernel/ptrace.c
--- v2.1.35/linux/arch/sparc/kernel/ptrace.c	Mon Apr 14 16:28:07 1997
+++ linux/arch/sparc/kernel/ptrace.c	Thu Apr 17 13:20:43 1997
@@ -889,13 +889,12 @@
 
 asmlinkage void syscall_trace(void)
 {
-	lock_kernel();
 #ifdef DEBUG_PTRACE
 	printk("%s [%d]: syscall_trace\n", current->comm, current->pid);
 #endif
 	if ((current->flags & (PF_PTRACED|PF_TRACESYS))
 			!= (PF_PTRACED|PF_TRACESYS))
-		goto out;
+		return;
 	current->exit_code = SIGTRAP;
 	current->state = TASK_STOPPED;
 	current->tss.flags ^= MAGIC_CONSTANT;
@@ -911,9 +910,9 @@
 		current->pid, current->exit_code);
 #endif
 	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;
-out:
-	unlock_kernel();
 }
diff -u --recursive --new-file v2.1.35/linux/arch/sparc/kernel/signal.c linux/arch/sparc/kernel/signal.c
--- v2.1.35/linux/arch/sparc/kernel/signal.c	Mon Mar 17 14:54:21 1997
+++ linux/arch/sparc/kernel/signal.c	Thu Apr 17 13:20:43 1997
@@ -1,4 +1,4 @@
-/*  $Id: signal.c,v 1.72 1997/03/03 16:51:43 jj Exp $
+/*  $Id: signal.c,v 1.73 1997/04/16 05:56:05 davem Exp $
  *  linux/arch/sparc/kernel/signal.c
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
@@ -28,7 +28,8 @@
 
 #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);
 
 extern void fpsave(unsigned long *fpregs, unsigned long *fsr,
 		   void *fpqueue, unsigned long *fpqdepth);
@@ -85,12 +86,15 @@
  * atomically swap in the new signal mask, and wait for a signal.
  * This is really tricky on the Sparc, watch out...
  */
-asmlinkage inline void _sigpause_common(unsigned int set, struct pt_regs *regs)
+asmlinkage void _sigpause_common(unsigned int set, struct pt_regs *regs)
 {
 	unsigned long mask;
 
+	spin_lock_irq(&current->sigmask_lock);
 	mask = current->blocked;
 	current->blocked = set & _BLOCKABLE;
+	spin_unlock_irq(&current->sigmask_lock);
+
 	regs->pc = regs->npc;
 	regs->npc += 4;
 
@@ -115,16 +119,12 @@
 
 asmlinkage void do_sigpause(unsigned int set, struct pt_regs *regs)
 {
-	lock_kernel();
 	_sigpause_common(set, regs);
-	unlock_kernel();
 }
 
 asmlinkage void do_sigsuspend (struct pt_regs *regs)
 {
-	lock_kernel();
 	_sigpause_common(regs->u_regs[UREG_I0], regs);
-	unlock_kernel();
 }
 
 
@@ -159,26 +159,20 @@
 	struct new_signal_frame *sf;
 	unsigned long up_psr, pc, npc, mask;
 	
-	lock_kernel();
 	sf = (struct new_signal_frame *) regs->u_regs [UREG_FP];
 
 	/* 1. Make sure we are not getting garbage from the user */
-	if (verify_area (VERIFY_READ, sf, sizeof (*sf))){
-		do_exit (SIGSEGV);
-		goto out;
-	}
-	if (((uint) sf) & 3){
-		do_exit (SIGSEGV);
-		goto out;
-	}
+	if (verify_area (VERIFY_READ, sf, sizeof (*sf)))
+		goto segv_and_exit;
+
+	if (((uint) sf) & 3)
+		goto segv_and_exit;
 
 	__get_user(pc,  &sf->info.si_regs.pc);
 	__get_user(npc, &sf->info.si_regs.npc);
 
-	if ((pc | npc) & 3) {
-		do_exit (SIGSEGV);
-		goto out;
-	}
+	if ((pc | npc) & 3)
+		goto segv_and_exit;
 	
 	/* 2. Restore the state */
 	up_psr = regs->psr;
@@ -191,43 +185,55 @@
 	if (sf->fpu_save)
 		restore_fpu_state(regs, sf->fpu_save);
 
+	/* This is pretty much atomic, no amount locking would prevent
+	 * the races which exist anyways.
+	 */
 	__get_user(mask, &sf->info.si_mask);
 	current->blocked = (mask & _BLOCKABLE);
-out:
+	return;
+
+segv_and_exit:
+	/* Ugh, we need to grab master lock in these rare cases ;-( */
+	lock_kernel();
+	do_exit(SIGSEGV);
 	unlock_kernel();
 }
 
 asmlinkage void do_sigreturn(struct pt_regs *regs)
 {
 	struct sigcontext *scptr;
-	unsigned long pc, npc, psr;
+	unsigned long pc, npc, psr, mask;
 
-	lock_kernel();
 	synchronize_user_stack();
-	if (current->tss.new_signal){
-		do_new_sigreturn (regs);
-		goto out;
-	}
+
+	if (current->tss.new_signal)
+		return do_new_sigreturn (regs);
+
 	scptr = (struct sigcontext *) regs->u_regs[UREG_I0];
+
 	/* Check sanity of the user arg. */
 	if(verify_area(VERIFY_READ, scptr, sizeof(struct sigcontext)) ||
-	   (((unsigned long) scptr) & 3)) {
-		printk("%s [%d]: do_sigreturn, scptr is invalid at "
-		       "pc<%08lx> scptr<%p>\n",
-		       current->comm, current->pid, regs->pc, scptr);
-		do_exit(SIGSEGV);
-	}
+	   (((unsigned long) scptr) & 3))
+		goto segv_and_exit;
+
 	__get_user(pc, &scptr->sigc_pc);
 	__get_user(npc, &scptr->sigc_npc);
+
 	if((pc | npc) & 3)
-		do_exit(SIGSEGV); /* Nice try. */
+		goto segv_and_exit;
+
+	/* This is pretty much atomic, no amount locking would prevent
+	 * the races which exist anyways.
+	 */
+	__get_user(mask, &scptr->sigc_mask);
+	current->blocked = (mask & _BLOCKABLE);
 
-	__get_user(current->blocked, &scptr->sigc_mask);
-	current->blocked &= _BLOCKABLE;
 	__get_user(current->tss.sstk_info.cur_status, &scptr->sigc_onstack);
 	current->tss.sstk_info.cur_status &= 1;
+
 	regs->pc = pc;
 	regs->npc = npc;
+
 	__get_user(regs->u_regs[UREG_FP], &scptr->sigc_sp);
 	__get_user(regs->u_regs[UREG_I0], &scptr->sigc_o0);
 	__get_user(regs->u_regs[UREG_G1], &scptr->sigc_g1);
@@ -236,7 +242,12 @@
 	__get_user(psr, &scptr->sigc_psr);
 	regs->psr &= ~(PSR_ICC);
 	regs->psr |= (psr & PSR_ICC);
-out:
+	return;
+
+segv_and_exit:
+	/* Ugh, we need to grab master lock in these rare cases ;-( */
+	lock_kernel();
+	do_exit(SIGSEGV);
 	unlock_kernel();
 }
 
@@ -252,9 +263,8 @@
 	return 0;
 }
 
-static inline void
-setup_frame(struct sigaction *sa, unsigned long pc, unsigned long npc,
-	    struct pt_regs *regs, int signr, unsigned long oldmask)
+static void setup_frame(struct sigaction *sa, unsigned long pc, unsigned long npc,
+			struct pt_regs *regs, int signr, unsigned long oldmask)
 {
 	struct signal_sframe *sframep;
 	struct sigcontext *sc;
@@ -274,8 +284,7 @@
 		/* Don't change signal code and address, so that
 		 * post mortem debuggers can have a look.
 		 */
-		do_exit(SIGILL);
-		return;
+		goto sigill_and_return;
 	}
 
 	sc = &sframep->sig_context;
@@ -319,6 +328,13 @@
 	regs->u_regs[UREG_FP] = (unsigned long) sframep;
 	regs->pc = (unsigned long) sa->sa_handler;
 	regs->npc = (regs->pc + 4);
+	return;
+
+sigill_and_return:
+	/* Ugh, we need to grab master lock in these rare cases ;-( */
+	lock_kernel();
+	do_exit(SIGILL);
+	unlock_kernel();
 }
 
 
@@ -353,9 +369,8 @@
 	current->used_math = 0;
 }
 
-
-static inline void
-new_setup_frame(struct sigaction *sa, struct pt_regs *regs, int signo, unsigned long oldmask)
+static void new_setup_frame(struct sigaction *sa, struct pt_regs *regs,
+			    int signo, unsigned long oldmask)
 {
 	struct new_signal_frame *sf;
 	int sigframe_size;
@@ -369,16 +384,13 @@
 
 	sf = (struct new_signal_frame *)(regs->u_regs[UREG_FP] - sigframe_size);
 
-	if (invalid_frame_pointer (sf, sigframe_size)){
-		do_exit(SIGILL);
-		return;
-	}
+	if (invalid_frame_pointer (sf, sigframe_size))
+		goto sigill_and_return;
 
-	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);
-		do_exit (SIGILL);
-		return;
+		goto sigill_and_return;
 	}
 
 	/* 2. Save the current process state */
@@ -411,6 +423,12 @@
 
 	/* Flush instruction space. */
 	flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0]));
+	return;
+
+sigill_and_return:
+	lock_kernel();
+	do_exit(SIGILL);
+	unlock_kernel();
 }
 
 
@@ -435,8 +453,7 @@
 #ifdef DEBUG_SIGNALS
 		printk ("Invalid stack frame\n");
 #endif
-		do_exit(SIGILL);
-		return;
+		goto sigill_and_return;
 	}
 
 	/* Start with a clean frame pointer and fill it */
@@ -525,23 +542,26 @@
 		regs->u_regs[UREG_I1] = (uint) si;
 		regs->u_regs[UREG_I2] = (uint) uc;
 	}
+	return;
+
+sigill_and_return:
+	lock_kernel();
+	do_exit(SIGILL);
+	unlock_kernel();
 }
 
-asmlinkage int
-svr4_getcontext (svr4_ucontext_t *uc, struct pt_regs *regs)
+asmlinkage int svr4_getcontext (svr4_ucontext_t *uc, struct pt_regs *regs)
 {
 	svr4_gregset_t  *gr;
 	svr4_mcontext_t *mc;
-	int ret = -EFAULT;
 
-	lock_kernel();
 	synchronize_user_stack();
-	if (current->tss.w_saved){
-		printk ("Uh oh, w_saved is not zero (%ld)\n", current->tss.w_saved);
-		do_exit (SIGSEGV);
-	}
+
+	if (current->tss.w_saved)
+		goto sigsegv_and_return;
+
 	if(clear_user(uc, sizeof (*uc)))
-		goto out;
+		return -EFAULT;
 
 	/* Setup convenience variables */
 	mc = &uc->mcontext;
@@ -568,58 +588,53 @@
 	/* The register file is not saved
 	 * we have already stuffed all of it with sync_user_stack
 	 */
-	ret = 0;
-out:
+	return 0;
+
+sigsegv_and_return:
+	lock_kernel();
+	do_exit(SIGSEGV);
 	unlock_kernel();
-	return ret;
+	return -EFAULT;
 }
 
-
 /* Set the context for a svr4 application, this is Solaris way to sigreturn */
 asmlinkage int svr4_setcontext (svr4_ucontext_t *c, struct pt_regs *regs)
 {
 	struct thread_struct *tp = &current->tss;
 	svr4_gregset_t  *gr;
-	unsigned long pc, npc, psr;
-	int ret = -EINTR;
+	unsigned long pc, npc, psr, mask;
 	
-	lock_kernel();
 	/* Fixme: restore windows, or is this already taken care of in
 	 * svr4_setup_frame when sync_user_windows is done?
 	 */
 	flush_user_windows();
 	
-	if (tp->w_saved){
-		printk ("Uh oh, w_saved is: 0x%lx\n", tp->w_saved);
-		do_exit(SIGSEGV);
-		goto out;
-	}
-	if (((uint) c) & 3){
-		printk ("Unaligned structure passed\n");
-		do_exit (SIGSEGV);
-		goto out;
-	}
+	if (tp->w_saved)
+		goto sigsegv_and_return;
 
-	if(!__access_ok((unsigned long)c, sizeof(*c))) {
-		/* Miguel, add nice debugging msg _here_. ;-) */
-		do_exit(SIGSEGV);
-		goto out;
-	}
+	if (((uint) c) & 3)
+		goto sigsegv_and_return;
+
+	if(!__access_ok((unsigned long)c, sizeof(*c)))
+		goto sigsegv_and_return;
 
 	/* Check for valid PC and nPC */
 	gr = &c->mcontext.greg;
 	__get_user(pc, &((*gr)[SVR4_PC]));
 	__get_user(npc, &((*gr)[SVR4_NPC]));
-	if((pc | npc) & 3) {
-	        printk ("setcontext, PC or nPC were bogus\n");
-		do_exit (SIGSEGV);
-		goto out;
-	}
+
+	if((pc | npc) & 3)
+		goto sigsegv_and_return;
+
 	/* Retrieve information from passed ucontext */
-	    /* note that nPC is ored a 1, this is used to inform entry.S */
-	    /* that we don't want it to mess with our PC and nPC */
-	__get_user(current->blocked, &c->sigmask.sigbits [0]);
-	current->blocked &= _BLOCKABLE;
+	/* note that nPC is ored a 1, this is used to inform entry.S */
+	/* that we don't want it to mess with our PC and nPC */
+
+	/* This is pretty much atomic, no amount locking would prevent
+	 * the races which exist anyways.
+	 */
+	__get_user(mask, &c->sigmask.sigbits [0]);
+	current->blocked = (mask & _BLOCKABLE);
 	regs->pc = pc;
 	regs->npc = npc | 1;
 	__get_user(regs->y, &((*gr) [SVR4_Y]));
@@ -630,9 +645,13 @@
 	/* Restore g[1..7] and o[0..7] registers */
 	copy_from_user(&regs->u_regs [UREG_G1], &(*gr)[SVR4_G1], sizeof (long) * 7);
 	copy_from_user(&regs->u_regs [UREG_I0], &(*gr)[SVR4_O0], sizeof (long) * 8);
-out:
+	return 0;
+
+sigsegv_and_return:
+	lock_kernel();
+	do_exit(SIGSEGV);
 	unlock_kernel();
-	return ret;
+	return -EFAULT;
 }
 
 static inline void handle_signal(unsigned long signr, struct sigaction *sa,
@@ -649,8 +668,11 @@
 	}
 	if(sa->sa_flags & SA_ONESHOT)
 		sa->sa_handler = NULL;
-	if(!(sa->sa_flags & SA_NOMASK))
+	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);
+	}
 }
 
 static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs,
@@ -683,17 +705,23 @@
 	unsigned long signr, mask = ~current->blocked;
 	struct sigaction *sa;
 	int svr4_signal = current->personality == PER_SVR4;
-	int ret;
 	
-	lock_kernel();
 	while ((signr = current->signal & mask) != 0) {
 		signr = ffz(~signr);
-		clear_bit(signr, &current->signal);
+
+		spin_lock_irq(&current->sigmask_lock);
+		current->signal &= ~(1 << signr);
+		spin_unlock_irq(&current->sigmask_lock);
+
 		sa = current->sig->action + signr;
 		signr++;
 		if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
 			current->exit_code = signr;
 			current->state = TASK_STOPPED;
+
+			/* This happens to be SMP safe so no need to
+			 * grab master kernel lock even in this case.
+			 */
 			notify_parent(current);
 			schedule();
 			if (!(signr = current->exit_code))
@@ -702,7 +730,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;
@@ -710,7 +740,14 @@
 		if(sa->sa_handler == SIG_IGN) {
 			if(signr != SIGCHLD)
 				continue;
-			while(sys_waitpid(-1,NULL,WNOHANG) > 0);
+
+			/* sys_wait4() grabs the master kernel lock, so
+			 * we need not do so, that sucker should be
+			 * threaded and would not be that difficult to
+			 * do anyways.
+			 */
+			while(sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
+				;
 			continue;
 		}
 		if(sa->sa_handler == SIG_DFL) {
@@ -721,6 +758,9 @@
 				continue;
 
 			case SIGTSTP: case SIGTTIN: case SIGTTOU:
+				/* The operations performed by is_orphaned_pgrp()
+				 * are protected by the tasklist_lock.
+				 */
 				if (is_orphaned_pgrp(current->pgrp))
 					continue;
 
@@ -729,6 +769,8 @@
 					continue;
 				current->state = TASK_STOPPED;
 				current->exit_code = signr;
+
+				/* notify_parent() is SMP safe */
 				if(!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags &
 				     SA_NOCLDSTOP))
 					notify_parent(current);
@@ -748,16 +790,21 @@
 #endif
 				/* 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();
 			}
 		}
 		if(restart_syscall)
 			syscall_restart(orig_i0, regs, sa);
 		handle_signal(signr, sa, oldmask, regs, svr4_signal);
-		ret = 1;
-		goto out;
+		return 1;
 	}
 	if(restart_syscall &&
 	   (regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
@@ -768,10 +815,7 @@
 		regs->pc -= 4;
 		regs->npc -= 4;
 	}
-	ret = 0;
-out:
-	unlock_kernel();
-	return ret;
+	return 0;
 }
 
 asmlinkage int
diff -u --recursive --new-file v2.1.35/linux/arch/sparc/kernel/smp.c linux/arch/sparc/kernel/smp.c
--- v2.1.35/linux/arch/sparc/kernel/smp.c	Mon Apr 14 16:28:07 1997
+++ linux/arch/sparc/kernel/smp.c	Tue Apr 15 21:47:23 1997
@@ -12,6 +12,7 @@
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
 #include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
 
 #include <asm/delay.h>
 #include <asm/irq.h>
@@ -139,6 +140,8 @@
 	local_flush_tlb_all();
 }
 
+static void smp_setup_percpu_timer(void);
+
 void smp_callin(void)
 {
 	int cpuid = smp_processor_id();
@@ -146,6 +149,10 @@
 	local_flush_cache_all();
 	local_flush_tlb_all();
 	set_irq_udt(mid_xlate[boot_cpu_id]);
+
+	/* Get our local ticker going. */
+	smp_setup_percpu_timer();
+
 	calibrate_delay();
 	smp_store_cpu_info(cpuid);
 	local_flush_cache_all();
@@ -215,6 +222,7 @@
 	klock_info.akp = boot_cpu_id;
 	smp_store_cpu_info(boot_cpu_id);
 	set_irq_udt(mid_xlate[boot_cpu_id]);
+	smp_setup_percpu_timer();
 	local_flush_cache_all();
 	if(linux_num_cpus == 1)
 		return;  /* Not an MP box. */
@@ -506,4 +514,102 @@
 	__sti();
 	while(1)
 		barrier();
+}
+
+/* Protects counters touched during level14 ticker */
+spinlock_t ticker_lock = SPIN_LOCK_UNLOCKED;
+
+/* 32-bit Sparc specific profiling function. */
+static inline void sparc_do_profile(unsigned long pc)
+{
+	if(prof_buffer && current->pid) {
+		extern int _stext;
+
+		pc -= (unsigned long) &_stext;
+		pc >>= prof_shift;
+
+		spin_lock(&ticker_lock);
+		if(pc < prof_len)
+			prof_buffer[pc]++;
+		else
+			prof_buffer[prof_len - 1]++;
+		spin_unlock(&ticker_lock);
+	}
+}
+
+volatile unsigned long smp_local_timer_ticks[1+NR_CPUS]={0,};
+
+unsigned int prof_multiplier[NR_CPUS];
+unsigned int prof_counter[NR_CPUS];
+
+extern void update_one_process(struct task_struct *p, unsigned long ticks,
+			       unsigned long user, unsigned long system);
+
+void smp_percpu_timer_interrupt(struct pt_regs *regs)
+{
+	int cpu = smp_processor_id();
+
+	clear_profile_irq(mid_xlate[cpu]);
+	if(!user_mode(regs))
+		sparc_do_profile(regs->pc);
+	if(!--prof_counter[cpu]) {
+		int user = user_mode(regs);
+		if(current->pid) {
+			update_one_process(current, 1, user, !user);
+
+			if(--current->counter < 0) {
+				current->counter = 0;
+				need_resched = 1;
+			}
+
+			spin_lock(&ticker_lock);
+			if(user) {
+				if(current->priority < DEF_PRIORITY)
+					kstat.cpu_nice++;
+				else
+					kstat.cpu_user++;
+			} else {
+				kstat.cpu_system++;
+			}
+			spin_unlock(&ticker_lock);
+		}
+		prof_counter[cpu] = prof_multiplier[cpu];
+	}
+#ifdef __SMP_PROF__
+	smp_local_timer_ticks[cpu]++;
+#endif
+}
+
+extern unsigned int lvl14_resolution;
+
+static void smp_setup_percpu_timer(void)
+{
+	int cpu = smp_processor_id();
+
+	prof_counter[cpu] = prof_multiplier[cpu] = 1;
+	load_profile_irq(mid_xlate[cpu], lvl14_resolution);
+
+	if(cpu == boot_cpu_id)
+		enable_pil_irq(14);
+}
+
+int setup_profiling_timer(unsigned int multiplier)
+{
+	int i;
+	unsigned long flags;
+
+	/* Prevent level14 ticker IRQ flooding. */
+	if((!multiplier) || (lvl14_resolution / multiplier) < 500)
+		return -EINVAL;
+
+	save_and_cli(flags);
+	for(i = 0; i < NR_CPUS; i++) {
+		if(cpu_present_map & (1 << i)) {
+			load_profile_irq(mid_xlate[i], lvl14_resolution / multiplier);
+			prof_multiplier[i] = multiplier;
+		}
+	}
+	restore_flags(flags);
+
+	return 0;
 }
diff -u --recursive --new-file v2.1.35/linux/arch/sparc/kernel/sparc_ksyms.c linux/arch/sparc/kernel/sparc_ksyms.c
--- v2.1.35/linux/arch/sparc/kernel/sparc_ksyms.c	Mon Apr 14 16:28:07 1997
+++ linux/arch/sparc/kernel/sparc_ksyms.c	Tue Apr 22 22:39:12 1997
@@ -1,4 +1,4 @@
-/* $Id: sparc_ksyms.c,v 1.54 1997/04/14 05:38:25 davem Exp $
+/* $Id: sparc_ksyms.c,v 1.56 1997/04/18 05:44:35 davem Exp $
  * arch/sparc/kernel/ksyms.c: Sparc specific ksyms support.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -87,7 +87,18 @@
 EXPORT_SYMBOL_PRIVATE(_lock_kernel);
 EXPORT_SYMBOL_PRIVATE(_unlock_kernel);
 EXPORT_SYMBOL_PRIVATE(_spinlock_waitfor);
+EXPORT_SYMBOL_PRIVATE(_rw_read_enter);
+EXPORT_SYMBOL_PRIVATE(_rw_read_exit);
+EXPORT_SYMBOL_PRIVATE(_rw_write_enter);
 EXPORT_SYMBOL(__sparc_bh_counter);
+#ifdef __SMP__
+EXPORT_SYMBOL_PRIVATE(_irq_enter);
+EXPORT_SYMBOL_PRIVATE(_irq_exit);
+EXPORT_SYMBOL_PRIVATE(_global_restore_flags);
+EXPORT_SYMBOL_PRIVATE(_global_sti);
+EXPORT_SYMBOL_PRIVATE(_global_cli);
+#endif
+
 EXPORT_SYMBOL(page_offset);
 EXPORT_SYMBOL(stack_top);
 
@@ -110,10 +121,6 @@
 EXPORT_SYMBOL(global_irq_lock);
 EXPORT_SYMBOL(global_bh_lock);
 EXPORT_SYMBOL(global_irq_count);
-EXPORT_SYMBOL(__global_cli);
-EXPORT_SYMBOL(__global_sti);
-EXPORT_SYMBOL(__global_save_flags);
-EXPORT_SYMBOL(__global_restore_flags);
 EXPORT_SYMBOL(synchronize_irq);
 #endif
 
diff -u --recursive --new-file v2.1.35/linux/arch/sparc/kernel/sun4c_irq.c linux/arch/sparc/kernel/sun4c_irq.c
--- v2.1.35/linux/arch/sparc/kernel/sun4c_irq.c	Mon Apr 14 16:28:07 1997
+++ linux/arch/sparc/kernel/sun4c_irq.c	Tue Apr 15 21:47:23 1997
@@ -111,12 +111,12 @@
 	clear_intr = sun4c_timers->timer_limit10;
 }
 
-static void sun4c_clear_profile_irq(void)
+static void sun4c_clear_profile_irq(int cpu)
 {
 	/* Errm.. not sure how to do this.. */
 }
 
-static void sun4c_load_profile_irq(unsigned int limit)
+static void sun4c_load_profile_irq(int cpu, unsigned int limit)
 {
 	/* Errm.. not sure how to do this.. */
 }
diff -u --recursive --new-file v2.1.35/linux/arch/sparc/kernel/sun4m_irq.c linux/arch/sparc/kernel/sun4m_irq.c
--- v2.1.35/linux/arch/sparc/kernel/sun4m_irq.c	Mon Apr 14 16:28:07 1997
+++ linux/arch/sparc/kernel/sun4m_irq.c	Thu Apr 17 13:20:43 1997
@@ -29,6 +29,7 @@
 #include <asm/openprom.h>
 #include <asm/oplib.h>
 #include <asm/traps.h>
+#include <asm/pgtable.h>
 #include <asm/smp.h>
 #include <asm/irq.h>
 #include <asm/io.h>
@@ -145,7 +146,7 @@
 /*11*/	SUN4M_INT_SBUS(5) | SUN4M_INT_VME(5) | SUN4M_INT_FLOPPY,
 /*12*/	SUN4M_INT_SERIAL | SUN4M_INT_KBDMS,
 /*13*/	SUN4M_INT_AUDIO,
-/*14*/	0x00000000,
+/*14*/	SUN4M_INT_E14,
 /*15*/	0x00000000
 };
 
@@ -196,37 +197,18 @@
 	clear_intr = sun4m_timers->l10_timer_limit;
 }
 
-static void sun4m_clear_profile_irq(void)
+static void sun4m_clear_profile_irq(int cpu)
 {
 	volatile unsigned int clear;
     
-	clear = sun4m_timers->cpu_timers[0].l14_timer_limit;
+	clear = sun4m_timers->cpu_timers[cpu].l14_timer_limit;
 }
 
-static void sun4m_load_profile_irq(unsigned int limit)
+static void sun4m_load_profile_irq(int cpu, unsigned int limit)
 {
-	sun4m_timers->cpu_timers[0].l14_timer_limit = limit;
+	sun4m_timers->cpu_timers[cpu].l14_timer_limit = limit;
 }
 
-#if HANDLE_LVL14_IRQ
-static void sun4m_lvl14_handler(int irq, void *dev_id, struct pt_regs * regs)
-{
-	volatile unsigned int clear;
-    
-	printk("CPU[%d]: TOOK A LEVEL14!\n", smp_processor_id());
-	/* we do nothing with this at present
-	 * this is purely to prevent OBP getting its mucky paws
-	 * in linux.
-	 */
-	clear = sun4m_timers->cpu_timers[0].l14_timer_limit; /* clear interrupt */
-    
-	/* reload with value, this allows on the fly retuning of the level14
-	 * timer
-	 */
-	sun4m_timers->cpu_timers[0].l14_timer_limit = lvl14_resolution;
-}
-#endif /* HANDLE_LVL14_IRQ */
-
 __initfunc(static void sun4m_init_timers(void (*counter_fn)(int, void *, struct pt_regs *)))
 {
 	int reg_count, irq, cpu;
@@ -282,13 +264,6 @@
 		prom_halt();
 	}
     
-	/* Can't cope with multiple CPUS yet so no level14 tick events */
-#if HANDLE_LVL14_IRQ
-	if (linux_num_cpus > 1)
-		claim_ticker14(NULL, PROFILE_IRQ, 0);
-	else
-		claim_ticker14(sun4m_lvl14_handler, PROFILE_IRQ, lvl14_resolution);
-#endif /* HANDLE_LVL14_IRQ */
 	if(linux_num_cpus > 1) {
 		for(cpu = 0; cpu < 4; cpu++)
 			sun4m_timers->cpu_timers[cpu].l14_timer_limit = 0;
@@ -296,6 +271,25 @@
 	} else {
 		sun4m_timers->cpu_timers[0].l14_timer_limit = 0;
 	}
+#ifdef __SMP__
+	{
+		unsigned long flags;
+		extern unsigned long lvl14_save[4];
+		struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (14 - 1)];
+
+		/* For SMP we use the level 14 ticker, however the bootup code
+		 * has copied the firmwares level 14 vector into boot cpu's
+		 * trap table, we must fix this now or we get squashed.
+		 */
+		__save_and_cli(flags);
+		trap_table->inst_one = lvl14_save[0];
+		trap_table->inst_two = lvl14_save[1];
+		trap_table->inst_three = lvl14_save[2];
+		trap_table->inst_four = lvl14_save[3];
+		local_flush_cache_all();
+		__restore_flags(flags);
+	}
+#endif
 }
 
 __initfunc(void sun4m_init_IRQ(void))
@@ -349,10 +343,6 @@
 		 * Not sure, but writing here on SLAVIO systems may puke
 		 * so I don't do it unless there is more than 1 cpu.
 		 */
-#if 0
-		printk("Warning:"
-		       "sun4m multiple CPU interrupt code requires work\n");
-#endif
 		irq_rcvreg = (unsigned long *)
 				&sun4m_interrupts->undirected_target;
 		sun4m_interrupts->undirected_target = 0;
diff -u --recursive --new-file v2.1.35/linux/arch/sparc/kernel/sys_sparc.c linux/arch/sparc/kernel/sys_sparc.c
--- v2.1.35/linux/arch/sparc/kernel/sys_sparc.c	Sun Jan 26 02:07:08 1997
+++ linux/arch/sparc/kernel/sys_sparc.c	Thu Apr 17 13:20:43 1997
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc.c,v 1.34 1997/01/06 06:52:35 davem Exp $
+/* $Id: sys_sparc.c,v 1.35 1997/04/16 05:56:09 davem Exp $
  * linux/arch/sparc/kernel/sys_sparc.c
  *
  * This file contains various random system calls that
@@ -254,49 +254,45 @@
 sparc_sigaction (int signum, const struct sigaction *action, struct sigaction *oldaction)
 {
 	struct sigaction new_sa, *p;
-	int err = -EINVAL;
 
-	lock_kernel();
 	if(signum < 0) {
 		current->tss.new_signal = 1;
 		signum = -signum;
 	}
+	if(signum<1 || signum>32)
+		return -EINVAL;
 
-	if (signum<1 || signum>32)
-		goto out;
 	p = signum - 1 + current->sig->action;
-	if (action) {
-		err = verify_area(VERIFY_READ,action,sizeof(struct sigaction));
-		if (err)
-			goto out;
-		err = -EINVAL;
+	if(action) {
+		if(verify_area(VERIFY_READ,action,sizeof(struct sigaction)))
+			return -EFAULT;
 		if (signum==SIGKILL || signum==SIGSTOP)
-			goto out;
-		err = -EFAULT;
+			return -EINVAL;
 		if(copy_from_user(&new_sa, action, sizeof(struct sigaction)))
-			goto out;	
+			return -EFAULT;	
 		if (new_sa.sa_handler != SIG_DFL && new_sa.sa_handler != SIG_IGN) {
-			err = verify_area(VERIFY_READ, new_sa.sa_handler, 1);
-			if (err)
-				goto out;
+			if(verify_area(VERIFY_READ, new_sa.sa_handler, 1))
+				return -EFAULT;
 		}
 	}
 
 	if (oldaction) {
-		err = -EFAULT;
+		/* 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.
+		 */
 		if (copy_to_user(oldaction, p, sizeof(struct sigaction)))
-			goto out;	
+			return -EFAULT;	
 	}
 
 	if (action) {
+		spin_lock_irq(&current->sig->siglock);
 		*p = new_sa;
 		check_pending(signum);
+		spin_unlock_irq(&current->sig->siglock);
 	}
-
-	err = 0;
-out:
-	unlock_kernel();
-	return err;
+	return 0;
 }
 
 #ifndef CONFIG_AP1000
diff -u --recursive --new-file v2.1.35/linux/arch/sparc/kernel/sys_sunos.c linux/arch/sparc/kernel/sys_sunos.c
--- v2.1.35/linux/arch/sparc/kernel/sys_sunos.c	Mon Mar 17 14:54:21 1997
+++ linux/arch/sparc/kernel/sys_sunos.c	Thu Apr 17 13:20:44 1997
@@ -1,4 +1,4 @@
-/* $Id: sys_sunos.c,v 1.77 1997/02/15 01:17:04 davem Exp $
+/* $Id: sys_sunos.c,v 1.78 1997/04/16 05:56:12 davem Exp $
  * sys_sunos.c: SunOS specific syscall compatibility support.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -1184,39 +1184,39 @@
 	struct sigaction *oldaction)
 {
 	struct sigaction new_sa, *p;
-	const  int sigaction_size = sizeof (struct sigaction) - sizeof (void *);
-	int err = -EINVAL;
+	const int sigaction_size = sizeof (struct sigaction) - sizeof (void *);
 
-	lock_kernel();
 	current->personality |= PER_BSD;
-
-	if (signum<1 || signum>32)
-		goto out;
+	if(signum < 1 || signum > 32)
+		return -EINVAL;
 
 	p = signum - 1 + current->sig->action;
-	if (action) {
-		err = -EFAULT;
+
+	if(action) {
 		if(copy_from_user(&new_sa, action, sigaction_size))
-			goto out;
-		err = -EINVAL;
+			return -EFAULT;
 		if (signum==SIGKILL || signum==SIGSTOP)
-			goto out;
+			return -EINVAL;
 		memset(&new_sa, 0, sizeof(struct sigaction));
-		err = -EFAULT;
 		if(copy_from_user(&new_sa, action, sigaction_size))
-			goto out;
+			return -EFAULT;
 		if (new_sa.sa_handler != SIG_DFL && new_sa.sa_handler != SIG_IGN) {
-			err = verify_area(VERIFY_READ, new_sa.sa_handler, 1);
-			if (err)
-				goto out;
+			if(verify_area(VERIFY_READ, new_sa.sa_handler, 1))
+				return -EFAULT;
 		}
 		new_sa.sa_flags ^= SUNOS_SV_INTERRUPT;
 	}
 
 	if (oldaction) {
-		err = -EFAULT;
+		/* 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 ;-)
+		 */
 		if (copy_to_user(oldaction, p, sigaction_size))
-			goto out;	
+			 return -EFAULT;
+
 		if (oldaction->sa_flags & SA_RESTART)
 			oldaction->sa_flags &= ~SA_RESTART;
 		else
@@ -1224,13 +1224,12 @@
 	}
 
 	if (action) {
+		spin_lock_irq(&current->sig->siglock);
 		*p = new_sa;
 		check_pending(signum);
+		spin_unlock_irq(&current->sig->siglock);
 	}
-	err = 0;
-out:
-	unlock_kernel();
-	return err;
+	return 0;
 }
 
 
diff -u --recursive --new-file v2.1.35/linux/arch/sparc/kernel/systbls.S linux/arch/sparc/kernel/systbls.S
--- v2.1.35/linux/arch/sparc/kernel/systbls.S	Mon Mar 17 14:54:21 1997
+++ linux/arch/sparc/kernel/systbls.S	Tue Apr 22 22:49:38 1997
@@ -1,4 +1,4 @@
-/* $Id: systbls.S,v 1.59 1997/02/14 03:12:54 davem Exp $
+/* $Id: systbls.S,v 1.60 1997/04/19 08:52:15 jj Exp $
  * systbls.S: System call entry point tables for OS compatibility.
  *            The native Linux system call table lives here also.
  *
@@ -113,7 +113,7 @@
 	.long C_LABEL(sys_sched_rr_get_interval), C_LABEL(sys_nanosleep)
 /*250*/	.long C_LABEL(sys_mremap)
 	.long C_LABEL(sys_sysctl)
-	.long C_LABEL(sys_getsid), C_LABEL(sys_fdatasync), C_LABEL(sys_nis_syscall)
+	.long C_LABEL(sys_getsid), C_LABEL(sys_fdatasync), C_LABEL(sys_nfsservctl)
 	.long C_LABEL(sys_aplib), C_LABEL(sys_nis_syscall)
 
 	/* Now the SunOS syscall table. */
diff -u --recursive --new-file v2.1.35/linux/arch/sparc/kernel/tick14.c linux/arch/sparc/kernel/tick14.c
--- v2.1.35/linux/arch/sparc/kernel/tick14.c	Sat Nov  9 00:11:50 1996
+++ linux/arch/sparc/kernel/tick14.c	Tue Apr 15 21:47:23 1997
@@ -60,6 +60,8 @@
 void claim_ticker14(void (*handler)(int, void *, struct pt_regs *),
 		    int irq_nr, unsigned int timeout )
 {
+	int cpu = smp_processor_id();
+
 	/* first we copy the obp handler instructions
 	 */
 	disable_irq(irq_nr);
@@ -78,7 +80,7 @@
 			 "counter14",
 			 NULL)) {
 		install_linux_ticker();
-		load_profile_irq(timeout);
+		load_profile_irq(cpu, timeout);
 		enable_irq(irq_nr);
 	}
 }
diff -u --recursive --new-file v2.1.35/linux/arch/sparc/kernel/time.c linux/arch/sparc/kernel/time.c
--- v2.1.35/linux/arch/sparc/kernel/time.c	Mon Apr 14 16:28:07 1997
+++ linux/arch/sparc/kernel/time.c	Tue Apr 22 22:39:12 1997
@@ -1,4 +1,4 @@
-/* $Id: time.c,v 1.27 1997/04/14 05:38:31 davem Exp $
+/* $Id: time.c,v 1.29 1997/04/18 09:48:44 davem Exp $
  * linux/arch/sparc/kernel/time.c
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -54,11 +54,6 @@
 	    last_rtc_update = xtime.tv_sec;
 	  else
 	    last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
-
-#ifdef __SMP__
-	/* I really think it should not be done this way... -DaveM */
-	smp_message_pass(MSG_ALL_BUT_SELF, MSG_RESCHEDULE, 0L, 0);
-#endif
 }
 
 /* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
@@ -313,11 +308,11 @@
 	xor	%o5, %o3, %o3
 	orcc	%o2, %o3, %g0
 	bne	1b
-	 subcc	%o1, 0x0, %g0
-	bpos	1f
+	 cmp	%o1, 0
+	bge	1f
 	 srl	%o1, 0xa, %o1
-	sethi	%hi(0x2710), %o3
-	or	%o3, %lo(0x2710), %o3
+	sethi	%hi(tick), %o3
+	ld	[%o3 + %lo(tick)], %o3
 	sethi	%hi(0x1fffff), %o2
 	or	%o2, %lo(0x1fffff), %o2
 	add	%o5, %o3, %o5
diff -u --recursive --new-file v2.1.35/linux/arch/sparc/lib/Makefile linux/arch/sparc/lib/Makefile
--- v2.1.35/linux/arch/sparc/lib/Makefile	Thu Mar 27 14:39:59 1997
+++ linux/arch/sparc/lib/Makefile	Tue Apr 22 22:39:12 1997
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.22 1997/03/14 21:04:17 jj Exp $
+# $Id: Makefile,v 1.23 1997/04/18 05:44:39 davem Exp $
 # Makefile for Sparc library files..
 #
 
@@ -9,6 +9,10 @@
 	strncpy_from_user.o divdi3.o udivdi3.o strlen_user.o \
 	copy_user.o locks.o atomic.o bitops.o
 
+ifdef SMP
+OBJS += irqlock.o
+endif
+
 lib.a: $(OBJS)
 	$(AR) rcs lib.a $(OBJS)
 	sync
@@ -53,6 +57,9 @@
 
 bitops.o: bitops.S
 	$(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c -o bitops.o bitops.S
+
+irqlock.o: irqlock.S
+	$(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c -o irqlock.o irqlock.S
 
 else
 
diff -u --recursive --new-file v2.1.35/linux/arch/sparc/lib/checksum.S linux/arch/sparc/lib/checksum.S
--- v2.1.35/linux/arch/sparc/lib/checksum.S	Mon Mar 17 14:54:22 1997
+++ linux/arch/sparc/lib/checksum.S	Tue Apr 22 22:39:12 1997
@@ -471,8 +471,6 @@
 	 addx	%g0, %g7, %o0
 C_LABEL(__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... */
 
@@ -568,6 +566,7 @@
 	add	%i1, %i2, %i1
 2:
 	mov	%i1, %o0
+6:
 	call	C_LABEL(__bzero)
 	 mov	%i3, %o1
 1:
@@ -579,3 +578,4 @@
         .section __ex_table,#alloc
         .align 4
         .word 5b,2
+	.word 6b,2
diff -u --recursive --new-file v2.1.35/linux/arch/sparc/lib/irqlock.S linux/arch/sparc/lib/irqlock.S
--- v2.1.35/linux/arch/sparc/lib/irqlock.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/sparc/lib/irqlock.S	Tue Apr 22 22:39:12 1997
@@ -0,0 +1,185 @@
+/* $Id: irqlock.S,v 1.2 1997/04/19 04:33:37 davem Exp $
+ * irqlock.S: High performance IRQ global locking and interrupt entry.
+ *
+ * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#include <asm/psr.h>
+#include <asm/smp.h>
+
+	.text
+	.align	4
+
+	/* This is incredibly insane... */
+	.globl	___irq_enter
+___irq_enter:
+	sethi	%hi(local_irq_count), %g2
+	sll	%g1, 2, %g1
+	or	%g2, %lo(local_irq_count), %g2
+	ld	[%g2 + %g1], %g3
+	sethi	%hi(global_irq_count), %g5
+	add	%g3, 1, %g3
+	or	%g5, %lo(global_irq_count), %g5
+	st	%g3, [%g2 + %g1]
+1:
+	ldstub	[%g5 + 3], %g2
+	orcc	%g2, 0x0, %g0
+	bne	1b
+	 ld	[%g5], %g3
+	sra	%g3, 8, %g3
+	add	%g3, 1, %g3
+	sll	%g3, 8, %g3
+	st	%g3, [%g5]
+	sethi	%hi(global_irq_lock), %g1
+	ldub	[%g1 + %lo(global_irq_lock)], %g2
+1:	
+	orcc	%g2, 0x0, %g0
+	bne,a	1b
+	 ldub	[%g1 + %lo(global_irq_lock)], %g2
+___irq_enter_out:
+	jmpl	%o7, %g0
+	 mov	%g4, %o7
+
+	.globl	___irq_exit
+___irq_exit:
+	rd	%psr, %g3
+	sethi	%hi(global_irq_count), %g1
+	or	%g3, PSR_PIL, %g3
+	or	%g1, %lo(global_irq_count), %g1
+	wr	%g3, 0x0, %psr
+	sethi	%hi(local_irq_count), %g2
+	sll	%g7, 2, %g7
+	or	%g2, %lo(local_irq_count), %g2
+	ld	[%g2 + %g7], %g3
+1:	
+	ldstub	[%g1 + 3], %g5
+	orcc	%g5, 0x0, %g0
+	bne	1b
+	 ld	[%g1], %g5
+	sra	%g5, 8, %g5
+	sub	%g5, 1, %g5
+	sll	%g5, 8, %g5
+	st	%g5, [%g1]
+	sub	%g3, 1, %g3
+	sethi	%hi(global_irq_holder), %g1
+	st	%g3, [%g2 + %g7]
+	srl	%g7, 2, %g7
+	ldub	[%g1 + %lo(global_irq_holder)], %g5
+	cmp	%g5, %g7
+	bne	___irq_enter_out
+	 mov	NO_PROC_ID, %g2
+	stb	%g2, [%g1 + %lo(global_irq_holder)]
+	sethi	%hi(global_irq_lock), %g5
+	b	___irq_enter_out
+	 stb	%g0, [%g5 + %lo(global_irq_lock)]
+
+	/* Weird calling conventions... %g7=flags, %g4=%prev_o7
+	 * Very clever for the __global_sti case, the inline which
+	 * gets us here clears %g7 and it just works.
+	 */
+	.globl	___global_restore_flags, ___global_sti, ___global_cli
+___global_restore_flags:
+	bne,a	___global_cli
+	 rd	%tbr, %g7
+	rd	%tbr, %g2
+
+___global_sti:
+	sethi	%hi(global_irq_holder), %g1
+	sethi	%hi(global_irq_lock), %g3
+	srl	%g2, 12, %g2
+	ldub	[%g1 + %lo(global_irq_holder)], %g5
+	and	%g2, 3, %g2
+	cmp	%g5, %g2
+	bne	1f
+	 mov	NO_PROC_ID, %g5
+	stb	%g5, [%g1 + %lo(global_irq_holder)]
+	stb	%g0, [%g3 + %lo(global_irq_lock)]
+1:
+	rd	%psr, %g3
+	andcc	%g7, 2, %g0
+	bne,a	1f
+	 or	%g3, PSR_PIL, %g3
+	andn	%g3, PSR_PIL, %g3
+1:
+	wr	%g3, 0x0, %psr
+	nop
+__global_cli_out:			! All togther now... "fuuunnnnn"
+	retl
+	 mov	%g4, %o7
+
+__spin_on_global_irq_lock:
+	orcc	%g2, 0x0, %g0
+	bne,a	__spin_on_global_irq_lock
+	 ldub	[%g1], %g2
+	b,a	1f
+
+	/* This is a royal pain in the ass to make fast... 8-( */
+___global_cli:
+	sethi	%hi(global_irq_lock), %g5
+	srl	%g7, 12, %g7
+	sethi	%hi(global_irq_holder), %g3
+	and	%g7, 3, %g7
+	ldub	[%g3 + %lo(global_irq_holder)], %g1
+	rd	%psr, %g2
+	cmp	%g1, %g7
+	or	%g2, PSR_PIL, %g2
+	be	__global_cli_out
+	 wr	%g2, 0x0, %psr			! XXX some sparcs may choke on this...
+	sethi	%hi(local_irq_count), %g3
+	or	%g3, %lo(local_irq_count), %g3
+	or	%g5, %lo(global_irq_lock), %g1
+1:
+	ldstub	[%g1], %g2
+	orcc	%g2, 0x0, %g0
+	bne,a	__spin_on_global_irq_lock
+	 ldub	[%g1], %g2
+__wait_on_irq:
+	sll	%g7, 2, %g7
+	ld	[%g3 + %g7], %g2
+	sethi	%hi(global_irq_count), %g1
+	or	%g1, %lo(global_irq_count), %g1
+	srl	%g7, 2, %g7
+	ld	[%g1], %g5
+	sra	%g5, 8, %g5
+__wait_on_irq_loop:
+	cmp	%g5, %g2
+	sethi	%hi(global_irq_holder), %g3
+	be,a	__global_cli_out	! Mamamia, Mamamia, this is the fast path
+	 stb	%g7, [%g3 + %lo(global_irq_holder)]
+1:
+	ldstub	[%g1 + 3], %g3
+	orcc	%g3, 0x0, %g0
+	bne	1b
+	 ld	[%g1], %g3
+	sra	%g3, 8, %g3
+	sub	%g3, %g2, %g3
+	sll	%g3, 8, %g3
+	st	%g3, [%g1]
+	sethi	%hi(global_irq_lock), %g3
+	stb	%g0, [%g3 + %lo(global_irq_lock)]
+0:
+	ld	[%g1], %g5
+9:
+	ldub	[%g3 + %lo(global_irq_lock)], %g3
+	sra	%g5, 8, %g5
+	orcc	%g3, %g5, %g0
+	bne	0b
+	 sethi	%hi(global_irq_lock), %g3
+	ldstub	[%g3 + %lo(global_irq_lock)], %g5
+	orcc	%g5, 0x0, %g0
+	bne,a	9b
+	 ld	[%g1], %g5
+1:
+	ldstub	[%g1 + 3], %g3
+	orcc	%g3, 0x0, %g0
+	bne	1b
+	 ld	[%g1], %g3
+	sra	%g3, 8, %g3
+	add	%g3, %g2, %g5
+	sll	%g5, 8, %g3
+	b	__wait_on_irq_loop
+	 st	%g3, [%g1]
+
+#if 0 /* XXX I'm not delirious enough to debug this yet. */
+	 add	%o7, (8 + (__wait_on_irq_loop - . - 4)), %o7	! AIEEEEE
+#endif
diff -u --recursive --new-file v2.1.35/linux/arch/sparc/lib/locks.S linux/arch/sparc/lib/locks.S
--- v2.1.35/linux/arch/sparc/lib/locks.S	Mon Apr 14 16:28:08 1997
+++ linux/arch/sparc/lib/locks.S	Tue Apr 22 22:39:12 1997
@@ -1,4 +1,4 @@
-/* $Id: locks.S,v 1.9 1997/04/14 05:38:41 davem Exp $
+/* $Id: locks.S,v 1.12 1997/04/22 18:48:07 davem Exp $
  * locks.S: SMP low-level lock primitives on Sparc.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -7,6 +7,7 @@
 #include <asm/cprefix.h>
 #include <asm/ptrace.h>
 #include <asm/psr.h>
+#include <asm/smp.h>
 #include <asm/spinlock.h>
 
 	.text
@@ -19,8 +20,8 @@
 	 * itself in %g1, %g4 must be restored into %o7 when we return,
 	 * and the caller wants us to return to him at three instructions
 	 * previous to the call instruction which got us here.  See how
-	 * this is used in asm-sparc/smp_lock.h if what I just said
-	 * confuses you to no end.
+	 * this is used in asm/smp_lock.h and asm/spinlock.h if what I
+	 * just said confuses you to no end.
 	 */
 	.globl	___spinlock_waitfor
 ___spinlock_waitfor:
@@ -59,8 +60,8 @@
 9:	jmpl	%o7 + 0x8, %g0
 	 mov	%g4, %o7
 
-	.globl	___lock_reaquire_kernel
-___lock_reaquire_kernel:
+	.globl	___lock_reacquire_kernel
+___lock_reacquire_kernel:
 	rd	%psr, %g3
 	or	%g3, PSR_PIL, %g7
 	wr	%g7, 0x0, %psr
@@ -81,9 +82,6 @@
 	jmpl	%o7 + 0x8, %g0
 	 mov	%g4, %o7
 
-#undef NO_PROC_ID
-#define NO_PROC_ID	0xff
-
 	.globl	___unlock_kernel
 ___unlock_kernel:
 	addcc	%g2, 1, %g2
@@ -100,4 +98,65 @@
 	wr	%g3, 0x0, %psr
 	nop; nop; nop;
 1:	jmpl	%o7 + 0x8, %g0
+	 mov	%g4, %o7
+
+	/* Read/writer locks, as usual this is overly clever to make it
+	 * as fast as possible.
+	 */
+
+	/* caches... */
+___rw_read_enter_spin_on_wlock:
+	orcc	%g2, 0x0, %g0
+	be,a	___rw_read_enter
+	 ldstub	[%g1 + 3], %g2
+	b	___rw_read_enter_spin_on_wlock
+	 ldub	[%g1 + 3], %g2
+___rw_write_enter_spin_on_wlock:
+	orcc	%g2, 0x0, %g0
+	be,a	___rw_write_enter
+	 ldstub	[%g1 + 3], %g2
+	b	___rw_write_enter_spin_on_wlock
+	 ldub	[%g1 + 3], %g2
+
+	.globl	___rw_read_enter
+___rw_read_enter:
+	orcc	%g2, 0x0, %g0
+	bne,a	___rw_read_enter_spin_on_wlock
+	 ldub	[%g1 + 3], %g2
+1:
+	ldstub	[%g1 + 2], %g7
+	orcc	%g7, 0x0, %g0
+	bne	1b
+	 ldsh	[%g1], %g2
+	add	%g2, 1, %g2
+	sth	%g2, [%g1]
+	sth	%g0, [%g1 + 2]
+	retl
+	 mov	%g4, %o7
+
+	/* We must be careful here to not blow away wlock. */
+	.globl	___rw_read_exit
+___rw_read_exit_spin:
+	ldstub	[%g1 + 2], %g2
+___rw_read_exit:
+	orcc	%g2, 0x0, %g0
+	bne	___rw_read_exit_spin
+	 ldsh	[%g1], %g7
+	sub	%g7, 1, %g7
+	sth	%g7, [%g1]
+	stb	%g0, [%g1 + 2]
+	retl
+	 mov	%g4, %o7
+
+	.globl	___rw_write_enter
+___rw_write_enter:
+	orcc	%g2, 0x0, %g0
+	bne,a	___rw_write_enter_spin_on_wlock
+	 ldub	[%g1 + 3], %g2
+	ld	[%g1], %g2
+1:
+	andncc	%g2, 0xff, %g0
+	bne,a	1b
+	 ld	[%g1], %g2
+	retl
 	 mov	%g4, %o7
diff -u --recursive --new-file v2.1.35/linux/arch/sparc/mm/Makefile linux/arch/sparc/mm/Makefile
--- v2.1.35/linux/arch/sparc/mm/Makefile	Thu Mar 27 14:39:59 1997
+++ linux/arch/sparc/mm/Makefile	Tue Apr 22 22:39:12 1997
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.23 1997/03/10 09:16:52 davem Exp $
+# $Id: Makefile,v 1.24 1997/04/20 14:11:49 ecd Exp $
 # Makefile for the linux Sparc-specific parts of the memory manager.
 #
 # Note! Dependencies are done automagically by 'make dep', which also
@@ -8,10 +8,13 @@
 # Note 2! The CFLAGS definition is now in the main makefile...
 
 O_TARGET := mm.o
-O_OBJS   := fault.o init.o sun4c.o srmmu.o hypersparc.o loadmmu.o \
-	    generic.o asyncd.o extable.o
+O_OBJS   := fault.o init.o sun4c.o srmmu.o hypersparc.o viking.o \
+	    loadmmu.o generic.o asyncd.o extable.o
 
 include $(TOPDIR)/Rules.make
 
 hypersparc.o: hypersparc.S
 	$(CC) -D__ASSEMBLY__ -ansi -c -o hypersparc.o hypersparc.S
+
+viking.o: viking.S
+	$(CC) -D__ASSEMBLY__ -ansi -c -o viking.o viking.S
diff -u --recursive --new-file v2.1.35/linux/arch/sparc/mm/hypersparc.S linux/arch/sparc/mm/hypersparc.S
--- v2.1.35/linux/arch/sparc/mm/hypersparc.S	Mon Apr 14 16:28:08 1997
+++ linux/arch/sparc/mm/hypersparc.S	Tue Apr 22 22:39:12 1997
@@ -1,4 +1,4 @@
-/* $Id: hypersparc.S,v 1.3 1997/04/13 06:38:13 davem Exp $
+/* $Id: hypersparc.S,v 1.4 1997/04/19 04:33:39 davem Exp $
  * hypersparc.S: High speed Hypersparc mmu/cache operations.
  *
  * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -271,10 +271,15 @@
 	retl
 	 nop
 
+	/* It was noted that at boot time a TLB flush all in a delay slot
+	 * can deliver an illegal instruction to the processor if the timing
+	 * is just right...
+	 */
 hypersparc_flush_tlb_all:
 	mov	0x400, %g1
+	sta	%g0, [%g1] ASI_M_FLUSH_PROBE
 	retl
-	 sta	%g0, [%g1] ASI_M_FLUSH_PROBE
+	 nop
 
 hypersparc_flush_tlb_mm:
 	mov	SRMMU_CTX_REG, %g1
diff -u --recursive --new-file v2.1.35/linux/arch/sparc/mm/init.c linux/arch/sparc/mm/init.c
--- v2.1.35/linux/arch/sparc/mm/init.c	Mon Apr 14 16:28:08 1997
+++ linux/arch/sparc/mm/init.c	Tue Apr 22 22:39:12 1997
@@ -1,4 +1,4 @@
-/*  $Id: init.c,v 1.48 1997/04/12 04:28:37 davem Exp $
+/*  $Id: init.c,v 1.49 1997/04/17 21:49:31 jj Exp $
  *  linux/arch/sparc/mm/init.c
  *
  *  Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -34,6 +34,9 @@
 struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS];
 unsigned long sparc_unmapped_base;
 
+/* References to section boundaries */
+extern char __init_begin, __init_end, etext;
+
 /*
  * BAD_PAGE is the page that is used for page faults when linux
  * is out-of-memory. Older versions of linux just did a
@@ -208,8 +211,8 @@
 {
 	int codepages = 0;
 	int datapages = 0;
+	int initpages = 0; 
 	unsigned long tmp2, addr;
-	extern char etext;
 
 	/* Saves us work later. */
 	memset((void *) ZERO_PAGE, 0, PAGE_SIZE);
@@ -237,7 +240,9 @@
 		if(PageReserved(mem_map + MAP_NR(addr))) {
 			if ((addr < (unsigned long) &etext) && (addr >= KERNBASE))
 				codepages++;
-			else if((addr < start_mem) && (addr >= KERNBASE))
+                        else if((addr >= (unsigned long)&__init_begin && addr < (unsigned long)&__init_end))
+                                initpages++;
+                        else if((addr < start_mem) && (addr >= KERNBASE))
 				datapages++;
 			continue;
 		}
@@ -252,10 +257,12 @@
 
 	tmp2 = nr_free_pages << PAGE_SHIFT;
 
-	printk("Memory: %luk available (%dk kernel code, %dk data) [%08lx,%08lx]\n",
+	printk("Memory: %luk available (%dk kernel code, %dk data, %dk init) [%08lx,%08lx]\n",
 	       tmp2 >> 10,
 	       codepages << (PAGE_SHIFT-10),
-	       datapages << (PAGE_SHIFT-10), PAGE_OFFSET, end_mem);
+	       datapages << (PAGE_SHIFT-10), 
+	       initpages << (PAGE_SHIFT-10),
+	       PAGE_OFFSET, end_mem);
 
 	min_free_pages = nr_free_pages >> 7;
 	if(min_free_pages < 16)
@@ -266,7 +273,6 @@
 
 void free_initmem (void)
 {
-	extern char __init_begin, __init_end;
 	unsigned long addr;
 	
 	addr = (unsigned long)(&__init_begin);
@@ -275,7 +281,6 @@
 		atomic_set(&mem_map[MAP_NR(addr)].count, 1);
 		free_page(addr);
 	}
-	printk ("Freeing unused kernel memory: %dk freed\n", (&__init_end - &__init_begin) >> 10);
 }
 
 void si_meminfo(struct sysinfo *val)
diff -u --recursive --new-file v2.1.35/linux/arch/sparc/mm/srmmu.c linux/arch/sparc/mm/srmmu.c
--- v2.1.35/linux/arch/sparc/mm/srmmu.c	Mon Apr 14 16:28:08 1997
+++ linux/arch/sparc/mm/srmmu.c	Tue Apr 22 22:39:12 1997
@@ -1,4 +1,4 @@
-/* $Id: srmmu.c,v 1.135 1997/04/14 05:38:49 davem Exp $
+/* $Id: srmmu.c,v 1.136 1997/04/20 14:11:51 ecd Exp $
  * srmmu.c:  SRMMU specific routines for memory management.
  *
  * Copyright (C) 1995 David S. Miller  (davem@caip.rutgers.edu)
@@ -74,7 +74,10 @@
 ctxd_t *srmmu_ctx_table_phys;
 ctxd_t *srmmu_context_table;
 
-static struct srmmu_trans {
+/* Don't change this without changing access to this
+ * in arch/sparc/mm/viking.S
+ */
+struct srmmu_trans {
 	unsigned long vbase;
 	unsigned long pbase;
 	unsigned long size;
@@ -705,7 +708,7 @@
 	} while(line != page);
 }
 
-static void srmmu_set_pte_nocache_nomxccvik(pte_t *ptep, pte_t pteval)
+static void srmmu_set_pte_nocache_viking(pte_t *ptep, pte_t pteval)
 {
 	unsigned long vaddr;
 	int set;
@@ -1083,255 +1086,6 @@
  * with respect to cache coherency.
  */
 
-/* Viking flushes.  For Sun's mainline MBUS processor it is pretty much
- * a crappy mmu.  The on-chip I&D caches only have full flushes, no fine
- * grained cache invalidations.  It only has these "flash clear" things
- * just like the MicroSparcI.  Added to this many revs of the chip are
- * teaming with hardware buggery.  Someday maybe we'll do direct
- * diagnostic tag accesses for page level flushes as those should
- * be painless and will increase performance due to the frequency of
- * page level flushes. This is a must to _really_ flush the caches,
- * crazy hardware ;-)
- */
-
-static void viking_flush_cache_all(void)
-{
-}
-
-static void viking_flush_cache_mm(struct mm_struct *mm)
-{
-}
-
-static void viking_flush_cache_range(struct mm_struct *mm, unsigned long start, unsigned long end)
-{
-}
-
-static void viking_flush_cache_page(struct vm_area_struct *vma, unsigned long page)
-{
-}
-
-/* Non-mxcc vikings are copy-back but are pure-physical so no flushing. */
-static void viking_flush_page_to_ram(unsigned long page)
-{
-}
-
-static void viking_mxcc_flush_chunk(unsigned long chunk)
-{
-}
-
-/* All vikings have an icache which snoops the processor bus and is fully
- * coherent with the dcache, so no flush is necessary at all.
- */
-static void viking_flush_sig_insns(struct mm_struct *mm, unsigned long insn_addr)
-{
-}
-
-static void viking_mxcc_flush_page(unsigned long page)
-{
-	unsigned long ppage = srmmu_v2p(page & PAGE_MASK);
-	unsigned long paddr0, paddr1;
-
-	if (ppage == 0xffffffffUL)
-		return;
-
-	paddr0 = 0x10;			/* Set cacheable bit. */
-	paddr1 = ppage;
-
-	/* Read the page's data through the stream registers,
-	 * and write it back to memory. This will issue
-	 * coherent write invalidates to all other caches, thus
-         * should also be sufficient in an MP system.
-	 */
-	__asm__ __volatile__ ("or %%g0, %0, %%g2\n\t"
-			      "or %%g0, %1, %%g3\n"
-			      "1:\n\t"
-			      "stda %%g2, [%2] %5\n\t"
-			      "stda %%g2, [%3] %5\n\t"
-			      "add %%g3, %4, %%g3\n\t"
-			      "btst 0xfff, %%g3\n\t"
-			      "bne 1b\n\t"
-			      "nop\n\t" : :
-			      "r" (paddr0), "r" (paddr1),
-			      "r" (MXCC_SRCSTREAM),
-			      "r" (MXCC_DESSTREAM),
-			      "r" (MXCC_STREAM_SIZE),
-			      "i" (ASI_M_MXCC) : "g2", "g3", "cc");
-
-	/* This was handcoded after a look at the gcc output from
-	 *
-	 *	do {
-	 *		mxcc_set_stream_src(paddr);
-	 *		mxcc_set_stream_dst(paddr);
-	 *		paddr[1] += MXCC_STREAM_SIZE;
-	 *	} while (paddr[1] & ~PAGE_MASK);
-	 */
-}
-
-static void viking_no_mxcc_flush_page(unsigned long page)
-{
-	unsigned long ppage = srmmu_v2p(page & PAGE_MASK);
-	int set, block;
-	unsigned long ptag[2];
-	unsigned long vaddr;
-	int i;
-
-	if (ppage == 0xffffffffUL)
-		return;
-	ppage >>= 12;
-
-	for (set = 0; set < 128; set++) {
-		for (block = 0; block < 4; block++) {
-
-			viking_get_dcache_ptag(set, block, ptag);
-
-			if (ptag[1] != ppage)
-				continue;
-			if (!(ptag[0] & VIKING_PTAG_VALID))
-				continue;
-			if (!(ptag[0] & VIKING_PTAG_DIRTY))
-				continue;
-
-			/* There was a great cache from TI
-			 * with comfort as much as vi,
-			 * 4 pages to flush,
-			 * 4 pages, no rush,
-			 * since anything else makes him die.
-			 */
-			vaddr = (KERNBASE + PAGE_SIZE) | (set << 5);
-			for (i = 0; i < 8; i++) {
-				__asm__ __volatile__ ("ld [%0], %%g2\n\t" : :
-						      "r" (vaddr) : "g2");
-				vaddr += PAGE_SIZE;
-			}
-
-			/* Continue with next set. */
-			break;
-		}
-	}
-}
-
-static void viking_nomxcc_flush_chunk(unsigned long chunk)
-{
-	viking_no_mxcc_flush_page(chunk);
-}
-
-/* Viking is IO cache coherent, but really only on MXCC. */
-static void viking_flush_page_for_dma(unsigned long page)
-{
-}
-
-static void viking_flush_tlb_all(void)
-{
-	register int ctr asm("g5");
-
-	ctr = 0;
-	__asm__ __volatile__("
-	1:	ld	[%%g6 + %2], %%g4	! flush user windows
-		orcc	%%g0, %%g4, %%g0
-		add	%0, 1, %0
-		bne	1b
-		 save	%%sp, -64, %%sp
-	2:	subcc	%0, 1, %0
-		bne	2b
-		 restore %%g0, %%g0, %%g0"
-	: "=&r" (ctr) : "0" (ctr), "i" (UWINMASK_OFFSET) : "g4", "cc");
-	srmmu_flush_whole_tlb();
-	module_stats.invall++;
-}
-
-static void viking_flush_tlb_mm(struct mm_struct *mm)
-{
-	register int ctr asm("g5");
-
-	FLUSH_BEGIN(mm)
-	ctr = 0;
-	__asm__ __volatile__("
-1:	ld	[%%g6 + %7], %%g4	! flush user windows
-	orcc	%%g0, %%g4, %%g0
-	add	%0, 1, %0
-	bne	1b
-	 save	%%sp, -64, %%sp
-2:	subcc	%0, 1, %0
-	bne	2b
-	 restore %%g0, %%g0, %%g0
-	lda	[%1] %4, %0
-	sta	%3, [%1] %4
-	sta	%%g0, [%2] %5
-	sta	%0, [%1] %4"
-	: "=&r" (ctr)
-	: "r" (SRMMU_CTX_REG), "r" (0x300), "r" (mm->context),
-	  "i" (ASI_M_MMUREGS), "i" (ASI_M_FLUSH_PROBE), "0" (ctr),
-	  "i" (UWINMASK_OFFSET)
-	: "g4", "cc");
-	module_stats.invmm++;
-	FLUSH_END
-}
-
-static void viking_flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end)
-{
-	register int ctr asm("g5");
-	unsigned long size;
-
-	FLUSH_BEGIN(mm)
-	ctr = 0;
-	__asm__ __volatile__("
-	1:	ld	[%%g6 + %2], %%g4	! flush user windows
-		orcc	%%g0, %%g4, %%g0
-		add	%0, 1, %0
-		bne	1b
-		 save	%%sp, -64, %%sp
-	2:	subcc	%0, 1, %0
-		bne	2b
-		 restore %%g0, %%g0, %%g0"
-	: "=&r" (ctr) : "0" (ctr), "i" (UWINMASK_OFFSET) : "g4", "cc");
-	start &= SRMMU_PGDIR_MASK;
-	size = SRMMU_PGDIR_ALIGN(end) - start;
-	__asm__ __volatile__("
-		lda	[%0] %5, %%g5
-		sta	%1, [%0] %5
-	1:	subcc	%3, %4, %3
-		bne	1b
-		 sta	%%g0, [%2 + %3] %6
-		sta	%%g5, [%0] %5"
-	: /* no outputs */
-	: "r" (SRMMU_CTX_REG), "r" (mm->context), "r" (start | 0x200),
-	  "r" (size), "r" (SRMMU_PGDIR_SIZE), "i" (ASI_M_MMUREGS),
-	  "i" (ASI_M_FLUSH_PROBE)
-	: "g5", "cc");
-	module_stats.invrnge++;
-	FLUSH_END
-}
-
-static void viking_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
-{
-	struct mm_struct *mm = vma->vm_mm;
-	register int ctr asm("g5");
-
-	FLUSH_BEGIN(mm)
-	ctr = 0;
-	__asm__ __volatile__("
-	1:	ld	[%%g6 + %2], %%g4	! flush user windows
-		orcc	%%g0, %%g4, %%g0
-		add	%0, 1, %0
-		bne	1b
-		 save	%%sp, -64, %%sp
-	2:	subcc	%0, 1, %0
-		bne	2b
-		 restore %%g0, %%g0, %%g0"
-	: "=&r" (ctr) : "0" (ctr), "i" (UWINMASK_OFFSET) : "g4", "cc");
-	__asm__ __volatile__("
-	lda	[%0] %3, %%g5
-	sta	%1, [%0] %3
-	sta	%%g0, [%2] %4
-	sta	%%g5, [%0] %3"
-	: /* no outputs */
-	: "r" (SRMMU_CTX_REG), "r" (mm->context), "r" (page & PAGE_MASK),
-	  "i" (ASI_M_MMUREGS), "i" (ASI_M_FLUSH_PROBE)
-	: "g5");
-	module_stats.invpg++;
-	FLUSH_END
-}
-
 /* Cypress flushes. */
 static void cypress_flush_cache_all(void)
 {
@@ -1576,6 +1330,27 @@
 	FLUSH_END
 }
 
+/* viking.S */
+extern void viking_flush_cache_all(void);
+extern void viking_flush_cache_mm(struct mm_struct *mm);
+extern void viking_flush_cache_range(struct mm_struct *mm, unsigned long start,
+				     unsigned long end);
+extern void viking_flush_cache_page(struct vm_area_struct *vma,
+				    unsigned long page);
+extern void viking_flush_page_to_ram(unsigned long page);
+extern void viking_flush_page_for_dma(unsigned long page);
+extern void viking_flush_sig_insns(struct mm_struct *mm, unsigned long addr);
+extern void viking_flush_page(unsigned long page);
+extern void viking_mxcc_flush_page(unsigned long page);
+extern void viking_flush_chunk(unsigned long chunk);
+extern void viking_mxcc_flush_chunk(unsigned long chunk);
+extern void viking_flush_tlb_all(void);
+extern void viking_flush_tlb_mm(struct mm_struct *mm);
+extern void viking_flush_tlb_range(struct mm_struct *mm, unsigned long start,
+				   unsigned long end);
+extern void viking_flush_tlb_page(struct vm_area_struct *vma,
+				  unsigned long page);
+
 /* hypersparc.S */
 extern void hypersparc_flush_cache_all(void);
 extern void hypersparc_flush_cache_mm(struct mm_struct *mm);
@@ -1608,9 +1383,9 @@
 	}
 }
 
-static void viking_no_mxcc_update_rootmmu_dir(struct task_struct *tsk, pgd_t *pgdp) 
+static void viking_update_rootmmu_dir(struct task_struct *tsk, pgd_t *pgdp) 
 {
-	viking_no_mxcc_flush_page((unsigned long)pgdp);
+	viking_flush_page((unsigned long)pgdp);
 	if(tsk->mm->context != NO_CONTEXT) {
 		flush_cache_mm(current->mm);
 		ctxd_set(&srmmu_context_table[tsk->mm->context], pgdp);
@@ -1768,11 +1543,11 @@
 			viking_mxcc_flush_page(start);
 			start += PAGE_SIZE;
 		}
-	} else if(flush_page_for_dma == viking_no_mxcc_flush_page) {
+	} else if(flush_page_for_dma == viking_flush_page) {
 		unsigned long start = (unsigned long) iommu->page_table;
 		unsigned long end = (start + ptsize);
 		while(start < end) {
-			viking_no_mxcc_flush_page(start);
+			viking_flush_page(start);
 			start += PAGE_SIZE;
 		}
 	}
@@ -1809,11 +1584,11 @@
 			viking_mxcc_flush_page(start);
 			start += PAGE_SIZE;
 		}
-	} else if(flush_page_for_dma == viking_no_mxcc_flush_page) {
+	} else if(flush_page_for_dma == viking_flush_page) {
 		unsigned long start = (unsigned long) iommu;
 		unsigned long end = (start + 16 * PAGE_SIZE);
 		while(start < end) {
-			viking_no_mxcc_flush_page(start);
+			viking_flush_page(start);
 			start += PAGE_SIZE;
 		}
 	}
@@ -2029,11 +1804,11 @@
 			viking_mxcc_flush_page(start);
 			start += PAGE_SIZE;
 		}
-	} else if(flush_page_for_dma == viking_no_mxcc_flush_page) {
+	} else if(flush_page_for_dma == viking_flush_page) {
 		unsigned long start = ((unsigned long) iopte_first) & PAGE_MASK;
 		unsigned long end = PAGE_ALIGN(((unsigned long) iopte));
 		while(start < end) {
-			viking_no_mxcc_flush_page(start);
+			viking_flush_page(start);
 			start += PAGE_SIZE;
 		}
 	}
@@ -2449,12 +2224,12 @@
 	start_mem = PAGE_ALIGN(mempool);
 
 	flush_cache_all();
-	if(flush_page_for_dma == viking_no_mxcc_flush_page) {
+	if(flush_page_for_dma == viking_flush_page) {
 		unsigned long start = ptables_start;
 		unsigned long end = start_mem;
 
 		while(start < end) {
-			viking_no_mxcc_flush_page(start);
+			viking_flush_page(start);
 			start += PAGE_SIZE;
 		}
 	}
@@ -2999,10 +2774,10 @@
 
 		msi_set_sync();
 
-		set_pte = srmmu_set_pte_nocache_nomxccvik;
-		sparc_update_rootmmu_dir = viking_no_mxcc_update_rootmmu_dir;
+		set_pte = srmmu_set_pte_nocache_viking;
+		sparc_update_rootmmu_dir = viking_update_rootmmu_dir;
 
-		flush_chunk = viking_nomxcc_flush_chunk; /* local flush _only_ */
+		flush_chunk = viking_flush_chunk; /* local flush _only_ */
 
 		/* We need this to make sure old viking takes no hits
 		 * on it's cache for dma snoops to workaround the
@@ -3010,7 +2785,7 @@
 		 * This is only necessary because of the new way in
 		 * which we use the IOMMU.
 		 */
-		flush_page_for_dma = viking_no_mxcc_flush_page;
+		flush_page_for_dma = viking_flush_page;
 	} else {
 		srmmu_name = "TI Viking/MXCC";
 		viking_mxcc_present = 1;
diff -u --recursive --new-file v2.1.35/linux/arch/sparc/mm/viking.S linux/arch/sparc/mm/viking.S
--- v2.1.35/linux/arch/sparc/mm/viking.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/sparc/mm/viking.S	Tue Apr 22 22:39:12 1997
@@ -0,0 +1,267 @@
+/* $Id: viking.S,v 1.2 1997/04/20 21:21:49 ecd Exp $
+ * viking.S: High speed Viking cache/mmu operations
+ *
+ * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
+ */
+
+#include <asm/ptrace.h>
+#include <asm/psr.h>
+#include <asm/asi.h>
+#include <asm/mxcc.h>
+#include <asm/page.h>
+#include <asm/pgtsrmmu.h>
+#include <asm/viking.h>
+#include <asm/cprefix.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	viking_flush_cache_all, viking_flush_cache_mm
+	.globl	viking_flush_cache_range, viking_flush_cache_page
+	.globl	viking_flush_page, viking_mxcc_flush_page
+	.globl	viking_flush_page_for_dma, viking_flush_page_to_ram
+	.globl	viking_flush_chunk, viking_mxcc_flush_chunk
+	.globl	viking_flush_sig_insns
+	.globl	viking_flush_tlb_all, viking_flush_tlb_mm
+	.globl	viking_flush_tlb_range, viking_flush_tlb_page
+
+viking_flush_page:
+viking_flush_chunk:
+	sethi	%hi(C_LABEL(srmmu_map)), %g2
+	or	%g2, %lo(C_LABEL(srmmu_map)), %g3
+	ld	[%g3 + 8], %g2
+	cmp	%g2, 0
+	be	3f
+	 and	%o0, PAGE_MASK, %o0
+
+	ld	[%g3], %o1
+1:
+	cmp	%o1, %o0
+	bgu,a	2f
+	 add	%g3, 0xc, %g3
+
+	add	%o1, %g2, %g2
+	cmp	%g2, %o0
+	bleu,a	2f
+	 add	%g3, 0xc, %g3
+
+	sub	%o0, %o1, %g2
+	ld	[%g3 + 4], %o0
+	add	%g2, %o0, %g3
+	b	4f
+	 srl	%g3, 12, %g1		! ppage >> 12
+
+2:
+	ld	[%g3 + 8], %g2
+	cmp	%g2, 0
+	bne,a	1b
+	 ld	[%g3], %o1
+3:
+	retl
+	 nop
+
+4:
+	clr	%o1			! set counter, 0 - 127
+	sethi	%hi(KERNBASE + PAGE_SIZE - 0x80000000), %o3
+	sethi	%hi(0x80000000), %o4
+	sethi	%hi(VIKING_PTAG_VALID | VIKING_PTAG_DIRTY), %o5
+	sethi	%hi(PAGE_SIZE), %o0
+	clr	%o2			! block counter, 0 - 3
+5:
+	sll	%o1, 5, %g4
+	or	%g4, %o4, %g4		! 0x80000000 | (set << 5)
+
+	sll	%o2, 26, %g5		! block << 26
+6:
+	or	%g5, %g4, %g5
+	ldda	[%g5] ASI_M_DATAC_TAG, %g2
+	cmp	%g3, %g1		! ptag == ppage?
+	bne,a	7f
+	 inc	%o2
+
+	and	%g2, %o5, %g3		! ptag VALID and DIRTY?
+	cmp	%g3, %o5
+	bne,a	7f
+	 inc	%o2
+
+	add	%g4, %o3, %g2		! (KERNBASE + PAGE_SIZE) | (set << 5)
+	ld	[%g2], %g3
+	add	%g2, %o0, %g2
+	ld	[%g2], %g3
+	add	%g2, %o0, %g2
+	ld	[%g2], %g3
+	add	%g2, %o0, %g2
+	ld	[%g2], %g3
+	add	%g2, %o0, %g2
+	ld	[%g2], %g3
+	add	%g2, %o0, %g2
+	ld	[%g2], %g3
+	add	%g2, %o0, %g2
+	ld	[%g2], %g3
+	add	%g2, %o0, %g2
+	ld	[%g2], %g3
+
+	b	8f
+	 inc	%o1
+
+7:
+	cmp	%o2, 3
+	ble	6b
+	 sll	%o2, 26, %g5			! block << 26
+
+	inc	%o1
+8:
+	cmp	%o1, 0x7f
+	ble	5b
+	 clr	%o2
+
+	retl
+	 nop
+
+
+viking_mxcc_flush_page:
+	sethi	%hi(C_LABEL(srmmu_map)), %g2
+	or	%g2, %lo(C_LABEL(srmmu_map)), %g3
+	ld	[%g3 + 8], %g2
+	cmp	%g2, 0
+	be	3f
+	 and	%o0, PAGE_MASK, %o0
+
+	ld	[%g3], %o1
+1:
+	cmp	%o1, %o0
+	bgu,a	2f
+	 add	%g3, 0xc, %g3
+
+	add	%o1, %g2, %g2
+	cmp	%g2, %o0
+	bleu,a	2f
+	 add	%g3, 0xc, %g3
+
+	sub	%o0, %o1, %g2
+	ld	[%g3 + 4], %o0
+	add	%g2, %o0, %g3
+	sethi	%hi(PAGE_SIZE), %g4
+	b	4f
+	 add	%g3, %g4, %g3			! ppage + PAGE_SIZE
+
+2:
+	ld	[%g3 + 8], %g2
+	cmp	%g2, 0
+	bne,a	1b
+	 ld	[%g3], %o1
+3:
+	retl
+	 nop
+4:
+	mov	0x10, %g2			! set cacheable bit
+	sethi	%hi(MXCC_SRCSTREAM), %o2
+	or	%o2, %lo(MXCC_SRCSTREAM), %o2
+	sethi	%hi(MXCC_DESSTREAM), %o3
+	or	%o3, %lo(MXCC_DESSTREAM), %o3
+
+5:
+	sub	%g3, MXCC_STREAM_SIZE, %g3
+6:
+	stda	%g2, [%o2] ASI_M_MXCC
+	stda	%g2, [%o3] ASI_M_MXCC
+	andncc	%g3, PAGE_MASK, %g0
+	bne	6b
+	 sub	%g3, MXCC_STREAM_SIZE, %g3
+
+	retl
+	 nop
+
+viking_mxcc_flush_chunk:
+	retl
+	 nop
+
+viking_flush_cache_all:
+viking_flush_cache_mm:
+viking_flush_cache_range:
+viking_flush_cache_page:
+	retl
+	 nop
+
+viking_flush_tlb_all:
+	WINDOW_FLUSH(%g4, %g5)
+	mov	0x400, %g1
+	retl
+	 sta	%g0, [%g1] ASI_M_FLUSH_PROBE
+
+viking_flush_tlb_mm:
+	mov	SRMMU_CTX_REG, %g1
+	ld	[%o0 + AOFF_mm_context], %o1
+	lda	[%g1] ASI_M_MMUREGS, %g5
+#ifndef __SMP__
+	cmp	%o1, -1
+	be	viking_flush_tlb_mm_out
+#endif
+	WINDOW_FLUSH(%g2, %g3)
+
+	mov	0x300, %g2
+	sta	%o1, [%g1] ASI_M_MMUREGS
+	sta	%g0, [%g2] ASI_M_FLUSH_PROBE
+viking_flush_tlb_mm_out:
+	retl
+	 sta	%g5, [%g1] ASI_M_MMUREGS
+
+viking_flush_tlb_range:
+	mov	SRMMU_CTX_REG, %g1
+	ld	[%o0 + AOFF_mm_context], %o3
+	lda	[%g1] ASI_M_MMUREGS, %g5
+#ifndef __SMP__
+	cmp	%o3, -1
+	be	viking_flush_tlb_range_out
+#endif
+	WINDOW_FLUSH(%g2, %g3)
+
+	srl	%o1, SRMMU_PGDIR_SHIFT, %o1
+	sta	%o3, [%g1] ASI_M_MMUREGS
+	sll	%o1, SRMMU_PGDIR_SHIFT, %o1
+	sethi	%hi(1 << SRMMU_PGDIR_SHIFT), %o4
+	add	%o1, 0x200, %o1
+	sta	%g0, [%o1] ASI_M_FLUSH_PROBE
+1:
+	add	%o1, %o4, %o1
+	cmp	%o1, %o2
+	blu,a	1b
+	 sta	%g0, [%o1] ASI_M_FLUSH_PROBE
+viking_flush_tlb_range_out:
+	retl
+	 sta	%g5, [%g1] ASI_M_MMUREGS
+
+viking_flush_tlb_page:
+	ld	[%o0 + 0x00], %o0	/* XXX vma->vm_mm GROSS XXX */
+	mov	SRMMU_CTX_REG, %g1
+	ld	[%o0 + AOFF_mm_context], %o3
+	and	%o1, PAGE_MASK, %o1
+	lda	[%g1] ASI_M_MMUREGS, %g5
+#ifndef __SMP__
+	cmp	%o3, -1
+	be	viking_flush_tlb_page_out
+#endif
+	WINDOW_FLUSH(%g2, %g3)
+
+	sta	%o3, [%g1] ASI_M_MMUREGS
+	sta	%g0, [%o1] ASI_M_FLUSH_PROBE
+viking_flush_tlb_page_out:
+	retl
+	 sta	%g5, [%g1] ASI_M_MMUREGS
+
+viking_flush_page_to_ram:
+viking_flush_page_for_dma:
+viking_flush_sig_insns:
+	retl
+	 nop
diff -u --recursive --new-file v2.1.35/linux/arch/sparc64/Makefile linux/arch/sparc64/Makefile
--- v2.1.35/linux/arch/sparc64/Makefile	Mon Apr 14 16:28:08 1997
+++ linux/arch/sparc64/Makefile	Tue Apr 15 21:47:23 1997
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.14 1997/04/10 23:32:33 davem Exp $
+# $Id: Makefile,v 1.15 1997/04/14 17:04:49 jj Exp $
 # sparc64/Makefile
 #
 # Makefile for the architecture dependent flags and dependencies on the
@@ -24,7 +24,7 @@
 # debugging of the kernel to get the proper debugging information.
 
 #CFLAGS := $(CFLAGS) -g -pipe -fcall-used-g5 -fcall-used-g7 
-CFLAGS := $(CFLAGS) -pipe -fno-sibling-call \
+CFLAGS := $(CFLAGS) -pipe \
           -fcall-used-g5 -fcall-used-g7 -Wno-sign-compare
 
 LINKFLAGS = -T arch/sparc64/vmlinux.lds
diff -u --recursive --new-file v2.1.35/linux/arch/sparc64/config.in linux/arch/sparc64/config.in
--- v2.1.35/linux/arch/sparc64/config.in	Mon Apr 14 16:28:08 1997
+++ linux/arch/sparc64/config.in	Tue Apr 22 22:39:12 1997
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.5 1997/04/10 17:06:08 jj Exp $
+# $Id: config.in,v 1.6 1997/04/17 20:35:42 jj Exp $
 # For a description of the syntax of this configuration file,
 # see the Configure script.
 #
@@ -50,9 +50,12 @@
 bool 'Networking support' CONFIG_NET
 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
-tristate 'Kernel support for 32-bit ELF binaries' CONFIG_BINFMT_ELF32
+if [ "$CONFIG_SPARC32_COMPAT" != "n" ]; then
+  tristate 'Kernel support for 32-bit ELF binaries' CONFIG_BINFMT_ELF32
+fi
 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
   tristate 'Kernel support for JAVA binaries' CONFIG_BINFMT_JAVA
 fi
diff -u --recursive --new-file v2.1.35/linux/arch/sparc64/defconfig linux/arch/sparc64/defconfig
--- v2.1.35/linux/arch/sparc64/defconfig	Mon Apr 14 16:28:08 1997
+++ linux/arch/sparc64/defconfig	Tue Apr 22 22:39:12 1997
@@ -50,6 +50,7 @@
 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
@@ -107,7 +108,7 @@
 #
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
 #
-# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_MULTI_LUN=y
 CONFIG_SCSI_CONSTANTS=y
 
 #
diff -u --recursive --new-file v2.1.35/linux/arch/sparc64/kernel/Makefile linux/arch/sparc64/kernel/Makefile
--- v2.1.35/linux/arch/sparc64/kernel/Makefile	Mon Apr 14 16:28:08 1997
+++ linux/arch/sparc64/kernel/Makefile	Tue Apr 22 22:39:12 1997
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.15 1997/04/10 07:53:30 davem Exp $
+# $Id: Makefile,v 1.16 1997/04/17 20:35:37 jj Exp $
 # Makefile for the linux kernel.
 #
 # Note! Dependencies are done automagically by 'make dep', which also
@@ -18,8 +18,12 @@
 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 time.o sys_sparc.o sys_sparc32.o signal32.o
+	    irq.o time.o sys_sparc.o
 OX_OBJS  := sparc64_ksyms.o
+
+ifdef CONFIG_SPARC32_COMPAT
+  O_OBJS += sys_sparc32.o signal32.o
+endif
 
 ifdef CONFIG_BINFMT_ELF32
   O_OBJS += sparcelf32.o
diff -u --recursive --new-file v2.1.35/linux/arch/sparc64/kernel/etrap.S linux/arch/sparc64/kernel/etrap.S
--- v2.1.35/linux/arch/sparc64/kernel/etrap.S	Mon Apr 14 16:28:09 1997
+++ linux/arch/sparc64/kernel/etrap.S	Tue Apr 15 21:47:23 1997
@@ -1,4 +1,4 @@
-/* $Id: etrap.S,v 1.10 1997/04/03 13:03:49 davem Exp $
+/* $Id: etrap.S,v 1.11 1997/04/14 17:04:45 jj Exp $
  * etrap.S: Preparing for entry into the kernel on Sparc V9.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -19,9 +19,8 @@
 etrap:
 	rdpr		%pil, %g4
 etrap_irq:
-	rdpr		%wstate, %g5
-	sllx		%g4, 20, %g4
 	rdpr		%tstate, %g1
+	sllx		%g4, 20, %g4
 	rdpr		%tpc, %g2
 	or		%g1, %g4, %g1
 	rdpr		%tnpc, %g3
@@ -39,6 +38,7 @@
 	 * trap level until PRIMARY_CONTEXT is set to zero, else
 	 * we fall out of NUCLEUS too soon and crash hard.
 	 */
+	rdpr		%wstate, %g5
 	mov		PRIMARY_CONTEXT, %g7
 	ldxa		[%g7] ASI_DMMU, %g4
 	mov		SECONDARY_CONTEXT, %g6
diff -u --recursive --new-file v2.1.35/linux/arch/sparc64/kernel/idprom.c linux/arch/sparc64/kernel/idprom.c
--- v2.1.35/linux/arch/sparc64/kernel/idprom.c	Mon Dec 30 01:59:59 1996
+++ linux/arch/sparc64/kernel/idprom.c	Thu Apr 17 13:20:44 1997
@@ -1,4 +1,4 @@
-/* $Id: idprom.c,v 1.1 1996/12/28 18:39:38 davem Exp $
+/* $Id: idprom.c,v 1.2 1997/04/17 02:28:10 miguel Exp $
  * idprom.c: Routines to load the idprom into kernel addresses and
  *           interpret the data contained within.
  *
@@ -34,14 +34,12 @@
 	idprom = &idprom_buffer;
 
 	if (idprom->id_format != 0x01)  {
-		prom_printf("IDPROM: Unknown format type!\n");
-		prom_halt();
+		prom_printf("IDPROM: Warning, unknown format type!\n");
 	}
 
 	if (idprom->id_cksum != calc_idprom_cksum(idprom)) {
-		prom_printf("IDPROM: Checksum failure (nvram=%x, calc=%x)!\n",
+		prom_printf("IDPROM: Warning, checksum failure (nvram=%x, calc=%x)!\n",
 			    idprom->id_cksum, calc_idprom_cksum(idprom));
-		prom_halt();
 	}
 
 	printk("Ethernet address: %02x:%02x:%02x:%02x:%02x:%02x\n",
diff -u --recursive --new-file v2.1.35/linux/arch/sparc64/kernel/irq.c linux/arch/sparc64/kernel/irq.c
--- v2.1.35/linux/arch/sparc64/kernel/irq.c	Mon Apr 14 16:28:09 1997
+++ linux/arch/sparc64/kernel/irq.c	Thu Apr 17 13:20:44 1997
@@ -1,4 +1,4 @@
-/* $Id: irq.c,v 1.11 1997/04/14 05:38:59 davem Exp $
+/* $Id: irq.c,v 1.12 1997/04/16 05:56:20 davem Exp $
  * irq.c: UltraSparc IRQ handling/init/registry.
  *
  * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -382,7 +382,7 @@
 
 /* Per-processor IRQ locking depth, both SMP and non-SMP code use this. */
 unsigned int local_irq_count[NR_CPUS];
-atomic_t __sparc64_bh_counter;
+atomic_t __sparc64_bh_counter = ATOMIC_INIT(0);
 
 #ifdef __SMP__
 #error SMP not supported on sparc64 just yet
diff -u --recursive --new-file v2.1.35/linux/arch/sparc64/kernel/signal32.c linux/arch/sparc64/kernel/signal32.c
--- v2.1.35/linux/arch/sparc64/kernel/signal32.c	Mon Apr 14 16:28:09 1997
+++ linux/arch/sparc64/kernel/signal32.c	Thu Apr 17 13:20:44 1997
@@ -1,4 +1,4 @@
-/*  $Id: signal32.c,v 1.5 1997/04/07 18:57:09 jj Exp $
+/*  $Id: signal32.c,v 1.6 1997/04/16 10:27:17 jj Exp $
  *  arch/sparc64/kernel/signal32.c
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
@@ -32,7 +32,8 @@
 
 #define synchronize_user_stack() do { } while (0)
 
-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_signal32(unsigned long oldmask, struct pt_regs * regs,
 			 unsigned long orig_o0, int ret_from_syscall);
@@ -85,12 +86,15 @@
  * atomically swap in the new signal mask, and wait for a signal.
  * This is really tricky on the Sparc, watch out...
  */
-asmlinkage inline void _sigpause32_common(unsigned int set, struct pt_regs *regs)
+asmlinkage void _sigpause32_common(unsigned int set, struct pt_regs *regs)
 {
 	unsigned int mask;
 
+	spin_lock_irq(&current->sigmask_lock);
 	mask = current->blocked;
 	current->blocked = set & _BLOCKABLE;
+	spin_unlock_irq(&current->sigmask_lock);
+	
 	regs->tpc = regs->tnpc;
 	regs->tnpc += 4;
 
@@ -115,16 +119,12 @@
 
 asmlinkage void do_sigpause32(unsigned int set, struct pt_regs *regs)
 {
-	lock_kernel ();
 	_sigpause32_common(set, regs);
-	unlock_kernel ();
 }
 
 asmlinkage void do_sigsuspend32(struct pt_regs *regs)
 {
-	lock_kernel ();
 	_sigpause32_common(regs->u_regs[UREG_I0], regs);
-	unlock_kernel ();
 }
 
 
@@ -158,15 +158,15 @@
 	sf = (struct new_signal_frame32 *) regs->u_regs [UREG_FP];
 	/* 1. Make sure we are not getting garbage from the user */
 	if (verify_area (VERIFY_READ, sf, sizeof (*sf))){
-		do_exit (SIGSEGV);
+		goto segv;
 	}
 	if (((unsigned long) sf) & 3){
-		do_exit (SIGSEGV);
+		goto segv;
 	}
 	get_user(pc, &sf->info.si_regs.pc);
 	__get_user(npc, &sf->info.si_regs.npc);
 	if ((pc | npc) & 3){
-		do_exit (SIGSEGV);
+		goto segv;
 	}
 	regs->tpc = pc;
 	regs->tnpc = npc;
@@ -187,15 +187,18 @@
 		restore_fpu_state32(regs, &sf->fpu_state);
 	__get_user(mask, &sf->info.si_mask);
 	current->blocked = mask & _BLOCKABLE;
-	unlock_kernel();
+	return;
+segv:
+	lock_kernel();
+	do_exit(SIGSEGV);
 }
 
 asmlinkage void do_sigreturn32(struct pt_regs *regs)
 {
 	struct sigcontext32 *scptr;
 	unsigned pc, npc, psr;
+	unsigned long mask;
 
-	lock_kernel ();
 	synchronize_user_stack();
 	if (current->tss.new_signal)
 		return do_new_sigreturn32(regs);
@@ -204,18 +207,15 @@
 	/* Check sanity of the user arg. */
 	if(verify_area(VERIFY_READ, scptr, sizeof(struct sigcontext32)) ||
 	   (((unsigned long) scptr) & 3)) {
-		printk("%s [%d]: do_sigreturn, scptr is invalid at "
-		       "pc<%016lx> scptr<%p>\n",
-		       current->comm, current->pid, regs->tpc, scptr);
-		do_exit(SIGSEGV);
+		goto segv;
 	}
 	__get_user(pc, &scptr->sigc_pc);
 	__get_user(npc, &scptr->sigc_npc);
 	if((pc | npc) & 3)
-		do_exit(SIGSEGV); /* Nice try. */
+		goto segv; /* Nice try. */
 
-	__get_user(current->blocked, &scptr->sigc_mask);
-	current->blocked &= _BLOCKABLE;
+	__get_user(mask, &scptr->sigc_mask);
+	current->blocked = (mask & _BLOCKABLE);
 	__get_user(current->tss.sstk_info.cur_status, &scptr->sigc_onstack);
 	current->tss.sstk_info.cur_status &= 1;
 	regs->tpc = pc;
@@ -228,7 +228,10 @@
 	__get_user(psr, &scptr->sigc_psr);
 	regs->tstate &= ~(TSTATE_ICC);
 	regs->tstate |= psr_to_tstate_icc(psr);
-	unlock_kernel ();
+	return;
+segv:
+	lock_kernel ();
+	do_exit (SIGSEGV);
 }
 
 /* Checks if the fp is valid */
@@ -239,7 +242,7 @@
 	return 0;
 }
 
-static inline void
+static void
 setup_frame32(struct sigaction *sa, unsigned long pc, unsigned long npc,
 	      struct pt_regs *regs, int signr, unsigned long oldmask)
 {
@@ -264,8 +267,8 @@
 		/* Don't change signal code and address, so that
 		 * post mortem debuggers can have a look.
 		 */
+		lock_kernel ();
 		do_exit(SIGILL);
-		return;
 	}
 
 	sc = &sframep->sig_context;
@@ -358,15 +361,15 @@
 	sf = (struct new_signal_frame32 *)(regs->u_regs[UREG_FP] - sigframe_size);
 	
 	if (invalid_frame_pointer (sf, sigframe_size)){
+		lock_kernel ();
 		do_exit(SIGILL);
-		return;
 	}
 
 	if (current->tss.w_saved != 0){
 		printk ("%s[%d]: Invalid user stack frame for "
 			"signal delivery.\n", current->comm, current->pid);
+		lock_kernel ();
 		do_exit (SIGILL);
-		return;
 	}
 
 	/* 2. Save the current process state */
@@ -433,8 +436,8 @@
 #ifdef DEBUG_SIGNALS
 		printk ("Invalid stack frame\n");
 #endif
+		lock_kernel ();
 		do_exit(SIGILL);
-		return;
 	}
 
 	/* Start with a clean frame pointer and fill it */
@@ -705,7 +708,14 @@
 		if(sa->sa_handler == SIG_IGN) {
 			if(signr != SIGCHLD)
 				continue;
-			while(sys_waitpid(-1,NULL,WNOHANG) > 0);
+
+                        /* sys_wait4() grabs the master kernel lock, so
+                         * we need not do so, that sucker should be
+                         * threaded and would not be that difficult to
+                         * do anyways.
+                         */
+                        while(sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
+                                ;
 			continue;
 		}
 		if(sa->sa_handler == SIG_DFL) {
diff -u --recursive --new-file v2.1.35/linux/arch/sparc64/kernel/sparc64_ksyms.c linux/arch/sparc64/kernel/sparc64_ksyms.c
--- v2.1.35/linux/arch/sparc64/kernel/sparc64_ksyms.c	Thu Mar 27 14:40:01 1997
+++ linux/arch/sparc64/kernel/sparc64_ksyms.c	Tue Apr 15 21:47:23 1997
@@ -1,4 +1,4 @@
-/* $Id: sparc64_ksyms.c,v 1.3 1997/03/18 17:59:10 jj Exp $
+/* $Id: sparc64_ksyms.c,v 1.4 1997/04/14 17:04:43 jj Exp $
  * arch/sparc/kernel/ksyms.c: Sparc specific ksyms support.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -162,7 +162,8 @@
 EXPORT_SYMBOL(__csum_partial_copy_sparc_generic);
 
 /* Moving data to/from userspace. */
-EXPORT_SYMBOL(__copy_user);
+EXPORT_SYMBOL(__copy_to_user);
+EXPORT_SYMBOL(__copy_from_user);
 EXPORT_SYMBOL(__strncpy_from_user);
 
 /* No version information on this, heavily used in inline asm,
diff -u --recursive --new-file v2.1.35/linux/arch/sparc64/kernel/sparcelf32.c linux/arch/sparc64/kernel/sparcelf32.c
--- v2.1.35/linux/arch/sparc64/kernel/sparcelf32.c	Mon Apr 14 16:28:09 1997
+++ linux/arch/sparc64/kernel/sparcelf32.c	Thu Apr 17 13:20:44 1997
@@ -38,6 +38,7 @@
 #include <linux/shm.h>
 #include <linux/personality.h>
 #include <linux/elfcore.h>
+#include <linux/init.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -156,20 +157,20 @@
 	sp -= argc+1;
 	argv = (__u32 *) sp;
 	if (!ibcs) {
-		__put_user(((__u32) envp),--sp);
-		__put_user(((__u32) argv),--sp);
+		__put_user(((__u32)(long) envp),--sp);
+		__put_user(((__u32)(long) argv),--sp);
 	}
 
 	__put_user((__u32)argc,--sp);
 	current->mm->arg_start = (unsigned long) p;
 	while (argc-->0) {
-		__put_user(((__u32)p),argv++);
+		__put_user(((__u32)(long)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(((__u32)p),envp++);
+		__put_user(((__u32)(long)p),envp++);
 		p += strlen_user(p);
 	}
 	__put_user(NULL, envp);
@@ -1108,7 +1109,7 @@
 #else
 	if (sizeof(elf_gregset_t) != sizeof(struct pt_regs))
 	{
-		printk("sizeof(elf_gregset_t) (%d) != sizeof(struct pt_regs) (%d)\n",
+		printk("sizeof(elf_gregset_t) (%ld) != sizeof(struct pt_regs) (%ld)\n",
 			sizeof(elf_gregset_t), sizeof(struct pt_regs));
 	}
 	else
@@ -1255,7 +1256,7 @@
 }
 #endif		/* USE_ELF_CORE_DUMP */
 
-int init_elf32_binfmt(void)
+__initfunc(int init_elf32_binfmt(void))
 {
 	return register_binfmt(&elf32_format);
 }
diff -u --recursive --new-file v2.1.35/linux/arch/sparc64/kernel/sys_sparc32.c linux/arch/sparc64/kernel/sys_sparc32.c
--- v2.1.35/linux/arch/sparc64/kernel/sys_sparc32.c	Mon Apr 14 16:28:09 1997
+++ linux/arch/sparc64/kernel/sys_sparc32.c	Tue Apr 22 22:39:12 1997
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc32.c,v 1.3 1997/04/09 08:25:17 jj Exp $
+/* $Id: sys_sparc32.c,v 1.9 1997/04/21 08:34:24 jj Exp $
  * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
  *
  * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -14,6 +14,7 @@
 #include <linux/resource.h>
 #include <linux/sched.h>
 #include <linux/times.h>
+#include <linux/utime.h>
 #include <linux/utsname.h>
 #include <linux/timex.h>
 #include <linux/smp.h>
@@ -21,6 +22,11 @@
 #include <linux/sem.h>
 #include <linux/msg.h>
 #include <linux/shm.h>
+#include <linux/malloc.h>
+#include <linux/uio.h>
+#include <linux/nfs_fs.h>
+#include <linux/smb_fs.h>
+#include <linux/ncp_fs.h>
 
 #include <asm/types.h>
 #include <asm/poll.h>
@@ -32,9 +38,6 @@
  * produce warnings */
 #define A(x) ((unsigned long)x)
  
-/* FIXME: All struct * etc. stuff should be examined and proper structure conversions
- * added ASAP -JJ */
-
 extern asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on);
 extern asmlinkage unsigned long sys_brk(unsigned long brk);
 extern asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long off);
@@ -69,7 +72,6 @@
 extern asmlinkage long sys_write(unsigned int fd, const char * buf, unsigned long count);
 extern asmlinkage long sys_readv(unsigned long fd, const struct iovec * vector, unsigned long count);
 extern asmlinkage long sys_writev(unsigned long fd, const struct iovec * vector, unsigned long count);
-extern asmlinkage int sys_getdents(unsigned int fd, void * dirent, unsigned int count);
 extern asmlinkage int sys_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, struct timeval *tvp);
 extern asmlinkage int sys_poll(struct pollfd * ufds, unsigned int nfds, int timeout);
 extern asmlinkage int sys_newstat(char * filename, struct stat * statbuf);
@@ -102,7 +104,6 @@
 extern asmlinkage int sys_getgroups(int gidsetsize, gid_t *grouplist);
 extern asmlinkage int sys_setgroups(int gidsetsize, gid_t *grouplist);
 extern asmlinkage int sys_newuname(struct new_utsname * name);
-extern asmlinkage int sys_uname(struct old_utsname * name);
 extern asmlinkage int sys_olduname(struct oldold_utsname * name);
 extern asmlinkage int sys_sethostname(char *name, int len);
 extern asmlinkage int sys_gethostname(char *name, int len);
@@ -136,12 +137,57 @@
 extern asmlinkage int sys_sendmsg(int fd, struct msghdr *msg, unsigned flags);
 extern asmlinkage int sys_recvmsg(int fd, struct msghdr *msg, unsigned int flags);
 extern asmlinkage int sys_socketcall(int call, unsigned long *args);
+extern asmlinkage int sys_nfsservctl(int cmd, void *argp, void *resp);
 
 asmlinkage int sys32_ioperm(u32 from, u32 num, int on)
 {
 	return sys_ioperm((unsigned long)from, (unsigned long)num, on);
 }
 
+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;
+};
+
+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; 
+};
+                                                        
 /*
  * sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit emulation..
  *
@@ -184,32 +230,111 @@
 	if (call <= MSGCTL) 
 		switch (call) {
 		case MSGSND:
-			/* XXX struct msgbuf has a long first :(( */
-			err = sys_msgsnd (first, (struct msgbuf *) A(ptr), 
-					  second, third);
+			{
+				struct msgbuf *p = kmalloc (second + sizeof (struct msgbuf), GFP_KERNEL);
+				
+				if (!p) err = -ENOMEM;
+				else {
+					if (get_user(p->mtype, &(((struct msgbuf32 *)A(ptr))->mtype)) ||
+					    __copy_from_user(p->mtext, &(((struct msgbuf32 *)A(ptr))->mtext), second))
+						err = -EFAULT;
+					else {
+						unsigned long old_fs = get_fs();
+						set_fs (KERNEL_DS);
+						err = sys_msgsnd (first, p, second, third);
+						set_fs (old_fs);
+					}
+					kfree (p);
+				}
+			}
 			goto out;
 		case MSGRCV:
-			switch (version) {
-			case 0: {
-				struct ipc_kludge tmp;
-				err = -EINVAL;
-				if (!ptr)
-					goto out;
-				err = -EFAULT;
-				if(copy_from_user(&tmp,(struct ipc_kludge *) ptr, sizeof (tmp)))
+			{
+				struct msgbuf *p;
+				unsigned long old_fs;
+				
+				if (!version) {
+					struct ipc_kludge tmp;
+					err = -EINVAL;
+					if (!ptr)
+						goto out;
+					err = -EFAULT;
+					if(copy_from_user(&tmp,(struct ipc_kludge *)A(ptr), sizeof (tmp)))
+						goto out;
+					ptr = tmp.msgp;
+					fifth = tmp.msgtyp;
+				}
+				p = kmalloc (second + sizeof (struct msgbuf), GFP_KERNEL);
+				if (!p) {
+					err = -EFAULT;
 					goto out;
-				err = sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp, third);
-				goto out;
 				}
-			case 1: default:
-				err = sys_msgrcv (first, (struct msgbuf *) ptr, second, fifth, third);
+				old_fs = get_fs();
+				set_fs (KERNEL_DS);
+				err = sys_msgrcv (first, p, second, fifth, third);
+				set_fs (old_fs);
+				if (put_user (p->mtype, &(((struct msgbuf32 *)A(ptr))->mtype)) ||
+				    __copy_to_user(&(((struct msgbuf32 *)A(ptr))->mtext), p->mtext, second))
+					err = -EFAULT;
+				kfree (p);
 				goto out;
 			}
 		case MSGGET:
 			err = sys_msgget ((key_t) first, second);
 			goto out;
 		case MSGCTL:
-			err = sys_msgctl (first, second, (struct msqid_ds *) ptr);
+			{
+				struct msqid_ds m;
+				unsigned long old_fs;
+				
+				switch (second) {
+					case IPC_INFO:
+					case MSG_INFO:
+						/* struct msginfo is the same */
+					case IPC_RMID:
+						/* and this doesn't care about ptr */
+						err = sys_msgctl (first, second, (struct msqid_ds *)A(ptr));
+						goto out;
+						
+					case IPC_SET:
+						if (get_user (m.msg_perm.uid, &(((struct msqid_ds32 *)A(ptr))->msg_perm.uid)) ||
+						    __get_user (m.msg_perm.gid, &(((struct msqid_ds32 *)A(ptr))->msg_perm.gid)) ||
+						    __get_user (m.msg_perm.mode, &(((struct msqid_ds32 *)A(ptr))->msg_perm.mode)) ||
+						    __get_user (m.msg_qbytes, &(((struct msqid_ds32 *)A(ptr))->msg_qbytes))) {
+							err = -EFAULT;  
+							goto out;
+						}
+					default:
+						break;
+				}
+				old_fs = get_fs();
+				set_fs (KERNEL_DS);
+				err = sys_msgctl (first, second, &m);
+				set_fs (old_fs);
+				switch (second) {
+					case MSG_STAT:
+					case IPC_STAT:
+						if (put_user (m.msg_perm.key, &(((struct msqid_ds32 *)A(ptr))->msg_perm.key)) ||
+						    __put_user (m.msg_perm.uid, &(((struct msqid_ds32 *)A(ptr))->msg_perm.uid)) ||
+						    __put_user (m.msg_perm.gid, &(((struct msqid_ds32 *)A(ptr))->msg_perm.gid)) ||
+						    __put_user (m.msg_perm.cuid, &(((struct msqid_ds32 *)A(ptr))->msg_perm.cuid)) ||
+						    __put_user (m.msg_perm.cgid, &(((struct msqid_ds32 *)A(ptr))->msg_perm.cgid)) ||
+						    __put_user (m.msg_perm.mode, &(((struct msqid_ds32 *)A(ptr))->msg_perm.mode)) ||
+						    __put_user (m.msg_perm.seq, &(((struct msqid_ds32 *)A(ptr))->msg_perm.seq)) ||
+						    __put_user (m.msg_stime, &(((struct msqid_ds32 *)A(ptr))->msg_stime)) ||
+						    __put_user (m.msg_rtime, &(((struct msqid_ds32 *)A(ptr))->msg_rtime)) ||
+						    __put_user (m.msg_ctime, &(((struct msqid_ds32 *)A(ptr))->msg_ctime)) ||
+						    __put_user (m.msg_cbytes, &(((struct msqid_ds32 *)A(ptr))->msg_cbytes)) ||
+						    __put_user (m.msg_qnum, &(((struct msqid_ds32 *)A(ptr))->msg_qnum)) ||
+						    __put_user (m.msg_qbytes, &(((struct msqid_ds32 *)A(ptr))->msg_qbytes)) ||
+						    __put_user (m.msg_lspid, &(((struct msqid_ds32 *)A(ptr))->msg_lspid)) ||
+						    __put_user (m.msg_lrpid, &(((struct msqid_ds32 *)A(ptr))->msg_lrpid)))
+							err = -EFAULT;
+						break;
+					default:
+						break;
+				}
+			}
 			goto out;
 		default:
 			err = -EINVAL;
@@ -220,28 +345,92 @@
 		case SHMAT:
 			switch (version) {
 			case 0: default: {
-				ulong raddr;
-				err = sys_shmat (first, (char *) ptr, second, &raddr);
+				unsigned long raddr;
+				err = sys_shmat (first, (char *)A(ptr), second, &raddr);
 				if (err)
 					goto out;
 				err = -EFAULT;
-				if(put_user (raddr, (ulong *) third))
+				if(put_user (raddr, ((u32 *)A(third))))
 					goto out;
 				err = 0;
 				goto out;
 				}
-			case 1:	/* iBCS2 emulator entry point */
-				err = sys_shmat (first, (char *) ptr, second, (ulong *) third);
+			case 1: /* If iBCS2 should ever run, then for sure in 64bit mode, not 32bit... */
+				err = -EINVAL;
 				goto out;
 			}
 		case SHMDT: 
-			err = sys_shmdt ((char *)ptr);
+			err = sys_shmdt ((char *)A(ptr));
 			goto out;
 		case SHMGET:
 			err = sys_shmget (first, second, third);
 			goto out;
 		case SHMCTL:
-			err = sys_shmctl (first, second, (struct shmid_ds *) ptr);
+			{
+				struct shmid_ds s;
+				unsigned long old_fs;
+				
+				switch (second) {
+					case IPC_INFO:
+						/* struct shminfo is the same */
+					case SHM_LOCK:
+					case SHM_UNLOCK:
+					case IPC_RMID:
+						/* and these three aren't using ptr at all */
+						err = sys_shmctl (first, second, (struct shmid_ds *)A(ptr));
+						goto out;
+						
+					case IPC_SET:
+						if (get_user (s.shm_perm.uid, &(((struct shmid_ds32 *)A(ptr))->shm_perm.uid)) ||
+						    __get_user (s.shm_perm.gid, &(((struct shmid_ds32 *)A(ptr))->shm_perm.gid)) ||
+						    __get_user (s.shm_perm.mode, &(((struct shmid_ds32 *)A(ptr))->shm_perm.mode))) {
+							err = -EFAULT; 
+							goto out;
+						}
+					default:
+						break;
+				}
+				old_fs = get_fs();
+				set_fs (KERNEL_DS);
+				err = sys_shmctl (first, second, &s);
+				set_fs (old_fs);
+				switch (second) {
+					case SHM_INFO:
+						{
+							struct shm_info32 { int used_ids; u32 shm_tot; u32 shm_rss; u32 shm_swp; u32 swap_attempts; u32 swap_successes; };
+							struct shm_info *si = (struct shm_info *)&s;
+
+							if (put_user (si->used_ids, &(((struct shm_info32 *)A(ptr))->used_ids)) ||
+							    __put_user (si->shm_tot, &(((struct shm_info32 *)A(ptr))->shm_tot)) ||
+							    __put_user (si->shm_rss, &(((struct shm_info32 *)A(ptr))->shm_rss)) ||
+							    __put_user (si->shm_swp, &(((struct shm_info32 *)A(ptr))->shm_swp)) ||
+							    __put_user (si->swap_attempts, &(((struct shm_info32 *)A(ptr))->swap_attempts)) ||
+							    __put_user (si->swap_successes, &(((struct shm_info32 *)A(ptr))->swap_successes)))
+								err = -EFAULT;
+						}
+						break;
+					case SHM_STAT:
+					case IPC_STAT:
+						if (put_user (s.shm_perm.key, &(((struct shmid_ds32 *)A(ptr))->shm_perm.key)) ||
+						    __put_user (s.shm_perm.uid, &(((struct shmid_ds32 *)A(ptr))->shm_perm.uid)) ||
+						    __put_user (s.shm_perm.gid, &(((struct shmid_ds32 *)A(ptr))->shm_perm.gid)) ||
+						    __put_user (s.shm_perm.cuid, &(((struct shmid_ds32 *)A(ptr))->shm_perm.cuid)) ||
+						    __put_user (s.shm_perm.cgid, &(((struct shmid_ds32 *)A(ptr))->shm_perm.cgid)) ||
+						    __put_user (s.shm_perm.mode, &(((struct shmid_ds32 *)A(ptr))->shm_perm.mode)) ||
+						    __put_user (s.shm_perm.seq, &(((struct shmid_ds32 *)A(ptr))->shm_perm.seq)) ||
+						    __put_user (s.shm_atime, &(((struct shmid_ds32 *)A(ptr))->shm_atime)) ||
+						    __put_user (s.shm_dtime, &(((struct shmid_ds32 *)A(ptr))->shm_dtime)) ||
+						    __put_user (s.shm_ctime, &(((struct shmid_ds32 *)A(ptr))->shm_ctime)) ||
+						    __put_user (s.shm_segsz, &(((struct shmid_ds32 *)A(ptr))->shm_segsz)) ||
+						    __put_user (s.shm_nattch, &(((struct shmid_ds32 *)A(ptr))->shm_nattch)) ||
+						    __put_user (s.shm_lpid, &(((struct shmid_ds32 *)A(ptr))->shm_cpid)) ||
+						    __put_user (s.shm_cpid, &(((struct shmid_ds32 *)A(ptr))->shm_lpid)))
+							err = -EFAULT;
+						break;
+					default:
+						break;
+				}
+			}
 			goto out;
 		default:
 			err = -EINVAL;
@@ -272,15 +461,45 @@
 
 asmlinkage long sys32_fcntl(unsigned int fd, unsigned int cmd, u32 arg)
 {
-	return sys_fcntl(fd, cmd, (unsigned long)arg);
+	switch (cmd) {
+	case F_GETLK:
+	case F_SETLK:
+	case F_SETLKW:
+		{
+			struct flock f;
+			unsigned long old_fs;
+			long ret;
+			
+			if (get_user (f.l_type, &(((struct flock32 *)A(arg))->l_type)) ||
+			    __get_user (f.l_whence, &(((struct flock32 *)A(arg))->l_whence)) ||
+			    __get_user (f.l_start, &(((struct flock32 *)A(arg))->l_start)) ||
+			    __get_user (f.l_len, &(((struct flock32 *)A(arg))->l_len)) ||
+			    __get_user (f.l_pid, &(((struct flock32 *)A(arg))->l_pid)))
+				return -EFAULT;
+			old_fs = get_fs(); set_fs (KERNEL_DS);
+			ret = sys_fcntl(fd, cmd, (unsigned long)&f);
+			set_fs (old_fs);
+   			if (__put_user (f.l_type, &(((struct flock32 *)A(arg))->l_type)) ||
+			    __put_user (f.l_whence, &(((struct flock32 *)A(arg))->l_whence)) ||
+			    __put_user (f.l_start, &(((struct flock32 *)A(arg))->l_start)) ||
+			    __put_user (f.l_len, &(((struct flock32 *)A(arg))->l_len)) ||
+			    __put_user (f.l_pid, &(((struct flock32 *)A(arg))->l_pid)))
+				return -EFAULT;
+			return ret;
+		}
+	default:
+		return sys_fcntl(fd, cmd, (unsigned long)arg);
+	}
 }
 
+/* Conversion of args should be probably done in all the locations where it is handled,
+   using if (current->tss.flags & SPARC_FLAG_32BIT */
 asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, u32 arg)
 {
 	return sys_ioctl(fd, cmd, (unsigned long)arg);
 }
 
-asmlinkage int sys32_mknod(u32 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);
 }
@@ -315,19 +534,52 @@
 	return sys_rename((const char *)A(oldname), (const char *)A(newname));
 }
 
+/* XXX: Play with the addr, it will be ugly :(( */
 asmlinkage int sys32_quotactl(int cmd, u32 special, int id, u32 addr)
 {
 	return sys_quotactl(cmd, (const char *)A(special), id, (caddr_t)A(addr));
 }
 
+static int put_statfs (u32 buf, struct statfs *s)
+{
+	if (put_user (s->f_type, &(((struct statfs32 *)A(buf))->f_type)) ||
+	    __put_user (s->f_bsize, &(((struct statfs32 *)A(buf))->f_bsize)) ||
+	    __put_user (s->f_blocks, &(((struct statfs32 *)A(buf))->f_blocks)) ||
+	    __put_user (s->f_bfree, &(((struct statfs32 *)A(buf))->f_bfree)) ||
+	    __put_user (s->f_bavail, &(((struct statfs32 *)A(buf))->f_bavail)) ||
+	    __put_user (s->f_files, &(((struct statfs32 *)A(buf))->f_files)) ||
+	    __put_user (s->f_ffree, &(((struct statfs32 *)A(buf))->f_ffree)) ||
+	    __put_user (s->f_namelen, &(((struct statfs32 *)A(buf))->f_namelen)) ||
+	    __put_user (s->f_fsid.val[0], &(((struct statfs32 *)A(buf))->f_fsid.val[0])) ||
+	    __put_user (s->f_fsid.val[1], &(((struct statfs32 *)A(buf))->f_fsid.val[1])))
+		return -EFAULT;
+	return 0;
+}
+
 asmlinkage int sys32_statfs(u32 path, u32 buf)
 {
-	return sys_statfs((const char *)A(path), (struct statfs *)A(buf));
+	int ret;
+	struct statfs s;
+	unsigned long old_fs = get_fs();
+	
+	set_fs (KERNEL_DS);
+	ret = sys_statfs((const char *)A(path), &s);
+	set_fs (old_fs);
+	if (put_statfs(buf, &s)) return -EFAULT;
+	return ret;
 }
 
 asmlinkage int sys32_fstatfs(unsigned int fd, u32 buf)
 {
-	return sys_fstatfs(fd, (struct statfs *)A(buf));
+	int ret;
+	struct statfs s;
+	unsigned long old_fs = get_fs();
+	
+	set_fs (KERNEL_DS);
+	ret = sys_fstatfs(fd, &s);
+	set_fs (old_fs);
+	if (put_statfs(buf, &s)) return -EFAULT;
+	return ret;
 }
 
 asmlinkage int sys32_truncate(u32 path, u32 length)
@@ -342,11 +594,24 @@
 
 asmlinkage int sys32_utime(u32 filename, u32 times)
 {
-	return sys_utime((char *)A(filename), (struct utimbuf *)A(times));
+	struct utimbuf32 { __kernel_time_t32 actime, modtime; };
+	struct utimbuf t;
+	unsigned long old_fs;
+	int ret;
+	
+	if (get_user (t.actime, &(((struct utimbuf32 *)A(times))->actime)) ||
+	    __get_user (t.modtime, &(((struct utimbuf32 *)A(times))->modtime)))
+		return -EFAULT;
+	old_fs = get_fs();
+	set_fs (KERNEL_DS); 
+	ret = sys_utime((char *)A(filename), &t);
+	set_fs (old_fs);
+	return ret;
 }
 
 asmlinkage int sys32_utimes(u32 filename, u32 utimes)
 {
+	/* struct timeval is the same :)) */
 	return sys_utimes((char *)A(filename), (struct timeval *)A(utimes));
 }
 
@@ -365,12 +630,12 @@
 	return sys_chroot((const char *)A(filename));
 }
 
-asmlinkage int sys32_chmod(u32 filename, mode_t mode)
+asmlinkage int sys32_chmod(u32 filename, __kernel_mode_t32 mode)
 {
 	return sys_chmod((const char *)A(filename), mode);
 }
 
-asmlinkage int sys32_chown(u32 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);
 }
@@ -392,6 +657,7 @@
 
 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);
 }
 
@@ -405,24 +671,264 @@
 	return sys_write(fd, (const char *)A(buf), (unsigned long)count);
 }
 
+struct iovec32 { u32 iov_base; __kernel_size_t32 iov_len; };
+
 asmlinkage long sys32_readv(u32 fd, u32 vector, u32 count)
 {
-	return sys_readv((unsigned long)fd, (const struct iovec *)A(vector), (unsigned long)count);
+	struct iovec *v;
+	struct iovec vf[UIO_FASTIOV];
+	u32 i;
+	long ret;
+	unsigned long old_fs;
+	
+	if (!count) return 0; if (count > UIO_MAXIOV) return -EINVAL;
+	if (count <= UIO_FASTIOV)
+		v = vf;
+	else {
+		lock_kernel ();
+		v = kmalloc (count * sizeof (struct iovec), GFP_KERNEL);
+		if (!v) {
+			ret = -ENOMEM;
+			goto out;
+		}
+	}
+	for (i = 0; i < count; i++) {
+		if (__get_user ((unsigned long)(v[i].iov_base), &((((struct iovec32 *)A(vector))+i)->iov_base)) ||
+		    __get_user (v[i].iov_len, &((((struct iovec32 *)A(vector))+i)->iov_len))) {
+		    	ret = -EFAULT;
+		    	goto out;
+		}
+	}
+	old_fs = get_fs();
+	set_fs (KERNEL_DS);
+	ret = sys_readv((unsigned long)fd, v, (unsigned long)count);
+	set_fs (old_fs);
+out:
+	if (count > UIO_FASTIOV) {
+		kfree (v);
+		unlock_kernel ();
+	}
+	return ret;
 }
 
 asmlinkage long sys32_writev(u32 fd, u32 vector, u32 count)
 {
-	return sys_writev((unsigned long)fd, (const struct iovec *)A(vector), (unsigned long)count);
+	struct iovec *v;
+	struct iovec vf[UIO_FASTIOV];
+	u32 i;
+	long ret;
+	unsigned long old_fs;
+	
+	if (!count) return 0; if (count > UIO_MAXIOV) return -EINVAL;
+	if (count <= UIO_FASTIOV)
+		v = vf;
+	else {
+		lock_kernel ();
+		v = kmalloc (count * sizeof (struct iovec), GFP_KERNEL);
+		if (!v) {
+			ret = -ENOMEM;
+			goto out;
+		}
+	}
+	for (i = 0; i < count; i++) {
+		if (__get_user ((unsigned long)(v[i].iov_base), &((((struct iovec32 *)A(vector))+i)->iov_base)) ||
+		    __get_user (v[i].iov_len, &((((struct iovec32 *)A(vector))+i)->iov_len))) {
+			ret = -EFAULT;
+			goto out;
+		}
+	}
+	old_fs = get_fs();
+	set_fs (KERNEL_DS);
+	ret = sys_writev((unsigned long)fd, v, (unsigned long)count);
+	set_fs (old_fs);
+out:	
+	if (count > UIO_FASTIOV) {
+		kfree (v);
+		unlock_kernel ();
+	}
+	return ret;
+}
+
+/* readdir & getdents */
+
+#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
+#define ROUND_UP(x) (((x)+sizeof(long)-1) & ~(sizeof(long)-1))
+
+struct old_linux_dirent32 {
+	u32		d_ino;
+	u32		d_offset;
+	unsigned short	d_namlen;
+	char		d_name[1];
+};
+
+struct readdir_callback32 {
+	struct old_linux_dirent32 * dirent;
+	int count;
+};
+
+static int fillonedir(void * __buf, const char * name, int namlen, off_t offset, ino_t ino)
+{
+	struct readdir_callback32 * buf = (struct readdir_callback32 *) __buf;
+	struct old_linux_dirent32 * dirent;
+
+	if (buf->count)
+		return -EINVAL;
+	buf->count++;
+	dirent = buf->dirent;
+	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;
+}
+
+asmlinkage int old32_readdir(unsigned int fd, u32 dirent, unsigned int count)
+{
+	int error = -EBADF;
+	struct file * file;
+	struct readdir_callback32 buf;
+
+	lock_kernel();
+	if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
+		goto out;
+	error = -ENOTDIR;
+	if (!file->f_op || !file->f_op->readdir)
+		goto out;
+	error = verify_area(VERIFY_WRITE, (void *)A(dirent), sizeof(struct old_linux_dirent32));
+	if (error)
+		goto out;
+	buf.count = 0;
+	buf.dirent = (struct old_linux_dirent32 *)A(dirent);
+	error = file->f_op->readdir(file->f_inode, file, &buf, fillonedir);
+	if (error < 0)
+		goto out;
+	error = buf.count;
+out:
+	unlock_kernel();
+	return error;
+}
+
+struct linux_dirent32 {
+	u32		d_ino;
+	u32		d_off;
+	unsigned short	d_reclen;
+	char		d_name[1];
+};
+
+struct getdents_callback32 {
+	struct linux_dirent32 * current_dir;
+	struct linux_dirent32 * previous;
+	int count;
+	int error;
+};
+
+static int filldir(void * __buf, const char * name, int namlen, off_t offset, ino_t ino)
+{
+	struct linux_dirent32 * dirent;
+	struct getdents_callback32 * buf = (struct getdents_callback32 *) __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->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;
+	return 0;
 }
 
 asmlinkage int sys32_getdents(unsigned int fd, u32 dirent, unsigned int count)
 {
-	return sys_getdents(fd, (void *)A(dirent), count);
+	struct file * file;
+	struct linux_dirent32 * lastdirent;
+	struct getdents_callback32 buf;
+	int error = -EBADF;
+
+	lock_kernel();
+	if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
+		goto out;
+	error = -ENOTDIR;
+	if (!file->f_op || !file->f_op->readdir)
+		goto out;
+	error = verify_area(VERIFY_WRITE, (void *)A(dirent), count);
+	if (error)
+		goto out;
+	buf.current_dir = (struct linux_dirent32 *) A(dirent);
+	buf.previous = NULL;
+	buf.count = count;
+	buf.error = 0;
+	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, &lastdirent->d_off);
+		error = count - buf.count;
+	}
+out:
+	unlock_kernel();
+	return error;
 }
 
+/* end of readdir & getdents */
+
 asmlinkage int sys32_select(int n, u32 inp, u32 outp, u32 exp, u32 tvp)
 {
-	return sys_select(n, (fd_set *)A(inp), (fd_set *)A(outp), (fd_set *)A(exp), (struct timeval *)A(tvp));
+	unsigned long old_fs;
+	char *p;
+	u32 *q;
+	int i, ret = -EINVAL, nn;
+	u32 *Inp, *Outp, *Exp;
+	
+	if (n < 0 || n > PAGE_SIZE*2) return -EINVAL;
+	lock_kernel ();
+	p = (char *)__get_free_page (GFP_KERNEL);
+	if (!p) goto out;
+	q = (u32 *)p;
+	nn = (n + 8 * sizeof(unsigned long) - 1) / (8 * sizeof (unsigned long));
+	Inp = (u32 *)A(inp); Outp = (u32 *)A(outp); Exp = (u32 *)A(exp);
+	ret = -EFAULT;
+	for (i = 0; i < ret; i++, Inp += 2, Outp += 2, Exp += 2, q += 2) {
+		if (__get_user (q[1], Inp) ||
+		    __get_user (q[0], Inp+1) ||
+		    __get_user (q[1+PAGE_SIZE/4], Outp) ||
+		    __get_user (q[PAGE_SIZE/4], Outp+1) ||
+		    __get_user (q[1+PAGE_SIZE/2], Exp) ||
+		    __get_user (q[PAGE_SIZE/2], Exp+1))
+			goto out;
+	}
+	old_fs = get_fs ();
+	set_fs (KERNEL_DS);
+	ret = sys_select(n, (fd_set *)p, (fd_set *)(p + PAGE_SIZE/4), (fd_set *)(p + PAGE_SIZE/2), (struct timeval *)A(tvp));
+	set_fs (old_fs);
+	q = (u32 *)p;
+	Inp = (u32 *)A(inp); Outp = (u32 *)A(outp); Exp = (u32 *)A(exp);
+	for (i = 0; i < ret; i++, Inp += 2, Outp += 2, Exp += 2, q += 2) {
+		if (__put_user (q[1], Inp) ||
+		    __put_user (q[0], Inp+1) ||
+		    __put_user (q[1+PAGE_SIZE/4], Outp) ||
+		    __put_user (q[PAGE_SIZE/4], Outp+1) ||
+		    __put_user (q[1+PAGE_SIZE/2], Exp) ||
+		    __put_user (q[PAGE_SIZE/2], Exp+1)) {
+		    	ret = -EFAULT;
+			goto out;
+		}
+	}
+out:
+	free_page ((unsigned long)p);
+	return ret;
 }
 
 asmlinkage int sys32_poll(u32 ufds, unsigned int nfds, int timeout)
@@ -430,19 +936,62 @@
 	return sys_poll((struct pollfd *)A(ufds), nfds, timeout);
 }
 
+static inline int putstat(u32 statbuf, struct stat *s)
+{
+	if (put_user (s->st_dev, &(((struct stat32 *)A(statbuf))->st_dev)) ||
+	    __put_user (s->st_ino, &(((struct stat32 *)A(statbuf))->st_ino)) ||
+	    __put_user (s->st_mode, &(((struct stat32 *)A(statbuf))->st_mode)) ||
+	    __put_user (s->st_nlink, &(((struct stat32 *)A(statbuf))->st_nlink)) ||
+	    __put_user (s->st_uid, &(((struct stat32 *)A(statbuf))->st_uid)) ||
+	    __put_user (s->st_gid, &(((struct stat32 *)A(statbuf))->st_gid)) ||
+	    __put_user (s->st_rdev, &(((struct stat32 *)A(statbuf))->st_rdev)) ||
+	    __put_user (s->st_size, &(((struct stat32 *)A(statbuf))->st_size)) ||
+	    __put_user (s->st_atime, &(((struct stat32 *)A(statbuf))->st_atime)) ||
+	    __put_user (s->st_mtime, &(((struct stat32 *)A(statbuf))->st_mtime)) ||
+	    __put_user (s->st_ctime, &(((struct stat32 *)A(statbuf))->st_ctime)) ||
+	    __put_user (s->st_blksize, &(((struct stat32 *)A(statbuf))->st_blksize)) ||
+	    __put_user (s->st_blocks, &(((struct stat32 *)A(statbuf))->st_blocks)))
+		return -EFAULT;
+	return 0;
+}
+
 asmlinkage int sys32_newstat(u32 filename, u32 statbuf)
 {
-	return sys_newstat((char *)A(filename), (struct stat *)A(statbuf));
+	int ret;
+	struct stat s;
+	unsigned long old_fs = get_fs();
+	
+	set_fs (KERNEL_DS);
+	ret = sys_newstat((char *)A(filename), &s);
+	set_fs (old_fs);
+	if (putstat (statbuf, &s)) return -EFAULT;
+	return ret;
 }
 
 asmlinkage int sys32_newlstat(u32 filename, u32 statbuf)
 {
-	return sys_newlstat((char *)A(filename), (struct stat *)A(statbuf));
+	int ret;
+	struct stat s;
+	unsigned long old_fs = get_fs();
+	
+	set_fs (KERNEL_DS);
+	ret = sys_newlstat((char *)A(filename), &s);
+	set_fs (old_fs);
+	if (putstat (statbuf, &s)) return -EFAULT;
+	return ret;
 }
 
 asmlinkage int sys32_newfstat(unsigned int fd, u32 statbuf)
 {
-	return sys_newfstat(fd, (struct stat *)A(statbuf));
+	int ret;
+	struct stat s;
+	unsigned long old_fs = get_fs();
+	
+	set_fs (KERNEL_DS);
+	ret = sys_newfstat(fd, &s);
+	set_fs (old_fs);
+	if (putstat (statbuf, &s)) return -EFAULT;
+	return ret;
 }
 
 asmlinkage int sys32_readlink(u32 path, u32 buf, int bufsiz)
@@ -454,7 +1003,7 @@
 {
         va_list args;
 	unsigned int x;
-	int ret;
+	int ret = -EINVAL;
 
         va_start(args, option);
         switch (option) {
@@ -475,6 +1024,7 @@
 
 asmlinkage int sys32_ustat(dev_t dev, u32 ubuf)
 {
+	/* ustat is the same :)) */
 	return sys_ustat(dev, (struct ustat *)A(ubuf));
 }
 
@@ -499,23 +1049,111 @@
 	return sys_personality((unsigned long)personality);
 }
 
-asmlinkage int sys32_wait4(pid_t pid, u32 stat_addr, int options, u32 ru)
-{
-	return sys_wait4(pid, (unsigned int *)A(stat_addr), options, (struct rusage *)A(ru));
+struct rusage32 {
+        struct timeval ru_utime;
+        struct timeval ru_stime;
+        s32    ru_maxrss;
+        s32    ru_ixrss;
+        s32    ru_idrss;
+        s32    ru_isrss;
+        s32    ru_minflt;
+        s32    ru_majflt;
+        s32    ru_nswap;
+        s32    ru_inblock;
+        s32    ru_oublock;
+        s32    ru_msgsnd; 
+        s32    ru_msgrcv; 
+        s32    ru_nsignals;
+        s32    ru_nvcsw;
+        s32    ru_nivcsw;
+};
+
+static int put_rusage (u32 ru, struct rusage *r)
+{
+	if (put_user (r->ru_utime.tv_sec, &(((struct rusage32 *)A(ru))->ru_utime.tv_sec)) ||
+	    __put_user (r->ru_utime.tv_usec, &(((struct rusage32 *)A(ru))->ru_utime.tv_usec)) ||
+	    __put_user (r->ru_stime.tv_sec, &(((struct rusage32 *)A(ru))->ru_stime.tv_sec)) ||
+	    __put_user (r->ru_stime.tv_usec, &(((struct rusage32 *)A(ru))->ru_stime.tv_usec)) ||
+	    __put_user (r->ru_maxrss, &(((struct rusage32 *)A(ru))->ru_maxrss)) ||
+	    __put_user (r->ru_ixrss, &(((struct rusage32 *)A(ru))->ru_ixrss)) ||
+	    __put_user (r->ru_idrss, &(((struct rusage32 *)A(ru))->ru_idrss)) ||
+	    __put_user (r->ru_isrss, &(((struct rusage32 *)A(ru))->ru_isrss)) ||
+	    __put_user (r->ru_minflt, &(((struct rusage32 *)A(ru))->ru_minflt)) ||
+	    __put_user (r->ru_majflt, &(((struct rusage32 *)A(ru))->ru_majflt)) ||
+	    __put_user (r->ru_nswap, &(((struct rusage32 *)A(ru))->ru_nswap)) ||
+	    __put_user (r->ru_inblock, &(((struct rusage32 *)A(ru))->ru_inblock)) ||
+	    __put_user (r->ru_oublock, &(((struct rusage32 *)A(ru))->ru_oublock)) ||
+	    __put_user (r->ru_msgsnd, &(((struct rusage32 *)A(ru))->ru_msgsnd)) ||
+	    __put_user (r->ru_msgrcv, &(((struct rusage32 *)A(ru))->ru_msgrcv)) ||
+	    __put_user (r->ru_nsignals, &(((struct rusage32 *)A(ru))->ru_nsignals)) ||
+	    __put_user (r->ru_nvcsw, &(((struct rusage32 *)A(ru))->ru_nvcsw)) ||
+	    __put_user (r->ru_nivcsw, &(((struct rusage32 *)A(ru))->ru_nivcsw)))
+		return -EFAULT;
+	return 0;
+}
+
+asmlinkage int sys32_wait4(__kernel_pid_t32 pid, u32 stat_addr, int options, u32 ru)
+{
+	if (!ru)
+		return sys_wait4(pid, (unsigned int *)A(stat_addr), options, NULL);
+	else {
+		struct rusage r;
+		int ret;
+		unsigned long old_fs = get_fs();
+		
+		set_fs (KERNEL_DS);
+		ret = sys_wait4(pid, (unsigned int *)A(stat_addr), options, &r);
+		set_fs (old_fs);
+		if (put_rusage (ru, &r)) return -EFAULT;
+		return ret;
+	}
 }
 
-asmlinkage int sys32_waitpid(pid_t pid, u32 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];
+        u32 totalram;
+        u32 freeram;
+        u32 sharedram;
+        u32 bufferram;
+        u32 totalswap;
+        u32 freeswap;
+        unsigned short procs;
+        char _f[22];
+};
+
 asmlinkage int sys32_sysinfo(u32 info)
 {
-	return sys_sysinfo((struct sysinfo *)A(info));
+	struct sysinfo s;
+	int ret;
+	unsigned long old_fs = get_fs ();
+	
+	set_fs (KERNEL_DS);
+	ret = sys_sysinfo(&s);
+	set_fs (old_fs);
+	if (put_user (s.uptime, &(((struct sysinfo32 *)A(info))->uptime)) ||
+	    __put_user (s.loads[0], &(((struct sysinfo32 *)A(info))->loads[0])) ||
+	    __put_user (s.loads[1], &(((struct sysinfo32 *)A(info))->loads[1])) ||
+	    __put_user (s.loads[2], &(((struct sysinfo32 *)A(info))->loads[2])) ||
+	    __put_user (s.totalram, &(((struct sysinfo32 *)A(info))->totalram)) ||
+	    __put_user (s.freeram, &(((struct sysinfo32 *)A(info))->freeram)) ||
+	    __put_user (s.sharedram, &(((struct sysinfo32 *)A(info))->sharedram)) ||
+	    __put_user (s.bufferram, &(((struct sysinfo32 *)A(info))->bufferram)) ||
+	    __put_user (s.totalswap, &(((struct sysinfo32 *)A(info))->totalswap)) ||
+	    __put_user (s.freeswap, &(((struct sysinfo32 *)A(info))->freeswap)) ||
+	    __put_user (s.procs, &(((struct sysinfo32 *)A(info))->procs)))
+		return -EFAULT;
+	return ret;
 }
 
 asmlinkage int sys32_getitimer(int which, u32 value)
 {
+	/* itimerval is the same :)) */
 	return sys_getitimer(which, (struct itimerval *)A(value));
 }
 
@@ -524,39 +1162,87 @@
 	return sys_setitimer(which, (struct itimerval *)A(value), (struct itimerval *)A(ovalue));
 }
 
-asmlinkage int sys32_sched_setscheduler(pid_t pid, int policy, u32 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));
 }
 
-asmlinkage int sys32_sched_setparam(pid_t pid, u32 param)
+asmlinkage int sys32_sched_setparam(__kernel_pid_t32 pid, u32 param)
 {
 	return sys_sched_setparam(pid, (struct sched_param *)A(param));
 }
 
-asmlinkage int sys32_sched_getparam(pid_t pid, u32 param)
+asmlinkage int sys32_sched_getparam(__kernel_pid_t32 pid, u32 param)
 {
 	return sys_sched_getparam(pid, (struct sched_param *)A(param));
 }
 
-asmlinkage int sys32_sched_rr_get_interval(pid_t pid, u32 interval)
+struct timespec32 {
+	s32    tv_sec;
+	s32    tv_nsec;
+};
+                
+asmlinkage int sys32_sched_rr_get_interval(__kernel_pid_t32 pid, u32 interval)
 {
-	return sys_sched_rr_get_interval(pid, (struct timespec *)A(interval));
+	struct timespec t;
+	int ret;
+	unsigned long old_fs = get_fs ();
+	
+	set_fs (KERNEL_DS);
+	ret = sys_sched_rr_get_interval(pid, &t);
+	set_fs (old_fs);
+	if (put_user (t.tv_sec, &(((struct timespec32 *)A(interval))->tv_sec)) ||
+	    __put_user (t.tv_nsec, &(((struct timespec32 *)A(interval))->tv_nsec)))
+		return -EFAULT;
+	return ret;
 }
 
 asmlinkage int sys32_nanosleep(u32 rqtp, u32 rmtp)
 {
-	return sys_nanosleep((struct timespec *)A(rqtp), (struct timespec *)A(rmtp));
+	struct timespec t;
+	int ret;
+	unsigned long old_fs = get_fs ();
+	
+	if (get_user (t.tv_sec, &(((struct timespec32 *)A(rqtp))->tv_sec)) ||
+	    __get_user (t.tv_nsec, &(((struct timespec32 *)A(rqtp))->tv_nsec)))
+		return -EFAULT;
+	set_fs (KERNEL_DS);
+	ret = sys_nanosleep(&t, rmtp ? &t : NULL);
+	set_fs (old_fs);
+	if (rmtp && ret == -EINTR) {
+		if (__put_user (t.tv_sec, &(((struct timespec32 *)A(rmtp))->tv_sec)) ||
+	    	    __put_user (t.tv_nsec, &(((struct timespec32 *)A(rmtp))->tv_nsec)))
+			return -EFAULT;
+	}
+	return ret;
 }
 
 asmlinkage int sys32_sigprocmask(int how, u32 set, u32 oset)
 {
-	return sys_sigprocmask(how, (sigset_t *)A(set), (sigset_t *)A(oset));
+	sigset_t s;
+	int ret;
+	unsigned long old_fs = get_fs();
+	
+	if (set && get_user (s, (sigset_t32 *)A(set))) return -EFAULT;
+	set_fs (KERNEL_DS);
+	ret = sys_sigprocmask(how, set ? &s : NULL, oset ? &s : NULL);
+	set_fs (old_fs);
+	if (oset && put_user (s, (sigset_t32 *)A(oset))) return -EFAULT;
+	return ret;
 }
 
 asmlinkage int sys32_sigpending(u32 set)
 {
-	return sys_sigpending((sigset_t *)A(set));
+	sigset_t s;
+	int ret;
+	unsigned long old_fs = get_fs();
+		
+	set_fs (KERNEL_DS);
+	ret = sys_sigpending(&s);
+	set_fs (old_fs);
+	if (put_user (s, (sigset_t32 *)A(set))) return -EFAULT;
+	return ret;
 }
 
 asmlinkage unsigned long sys32_signal(int signum, u32 handler)
@@ -576,34 +1262,84 @@
 
 asmlinkage int sys32_getresuid(u32 ruid, u32 euid, u32 suid)
 {
-	return sys_getresuid((uid_t *)A(ruid), (uid_t *)A(euid), (uid_t *)A(suid));
+	uid_t a, b, c;
+	int ret;
+	unsigned long old_fs = get_fs();
+		
+	set_fs (KERNEL_DS);
+	ret = sys_getresuid(&a, &b, &c);
+	set_fs (old_fs);
+	if (put_user (a, (__kernel_uid_t32 *)A(ruid)) ||
+	    put_user (b, (__kernel_uid_t32 *)A(euid)) ||
+	    put_user (c, (__kernel_uid_t32 *)A(suid)))
+		return -EFAULT;
+	return ret;
 }
 
+struct tms32 {
+	__kernel_clock_t32 tms_utime;
+	__kernel_clock_t32 tms_stime;
+	__kernel_clock_t32 tms_cutime;
+	__kernel_clock_t32 tms_cstime;
+};
+                                
 asmlinkage long sys32_times(u32 tbuf)
 {
-	return sys_times((struct tms *)A(tbuf));
+	struct tms t;
+	long ret;
+	unsigned long old_fs = get_fs ();
+	
+	set_fs (KERNEL_DS);
+	ret = sys_times(tbuf ? &t : NULL);
+	set_fs (old_fs);
+	if (tbuf && (
+	    put_user (t.tms_utime, &(((struct tms32 *)A(tbuf))->tms_utime)) ||
+	    __put_user (t.tms_stime, &(((struct tms32 *)A(tbuf))->tms_stime)) ||
+	    __put_user (t.tms_cutime, &(((struct tms32 *)A(tbuf))->tms_cutime)) ||
+	    __put_user (t.tms_cstime, &(((struct tms32 *)A(tbuf))->tms_cstime))))
+		return -EFAULT;
+	return ret;
 }
 
 asmlinkage int sys32_getgroups(int gidsetsize, u32 grouplist)
 {
-	return sys_getgroups(gidsetsize, (gid_t *)A(grouplist));
+	gid_t gl[NGROUPS];
+	int ret, i;
+	unsigned long old_fs = get_fs ();
+	
+	set_fs (KERNEL_DS);
+	ret = sys_getgroups(gidsetsize, gl);
+	set_fs (old_fs);
+	if (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;
+	return ret;
 }
 
 asmlinkage int sys32_setgroups(int gidsetsize, u32 grouplist)
 {
-	return sys_setgroups(gidsetsize, (gid_t *)A(grouplist));
+	gid_t gl[NGROUPS];
+	int ret, i;
+	unsigned long old_fs = get_fs ();
+	
+	if ((unsigned) gidsetsize > NGROUPS)
+		return -EINVAL;
+	for (i = 0; i < gidsetsize; i++, grouplist += sizeof(__kernel_gid_t32))
+		if (__get_user (gl[i], (__kernel_gid_t32 *)A(grouplist)))
+			return -EFAULT;
+        set_fs (KERNEL_DS);
+	ret = sys_setgroups(gidsetsize, gl);
+	set_fs (old_fs);
+	return ret;
 }
 
 asmlinkage int sys32_newuname(u32 name)
 {
+	/* utsname is the same :)) */
 	return sys_newuname((struct new_utsname *)A(name));
 }
 
-asmlinkage int sys32_uname(u32 name)
-{
-	return sys_uname((struct old_utsname *)A(name));
-}
-
 asmlinkage int sys32_olduname(u32 name)
 {
 	return sys_olduname((struct oldold_utsname *)A(name));
@@ -624,19 +1360,54 @@
 	return sys_setdomainname((char *)A(name), len);
 }
 
+struct rlimit32 {
+	s32	rlim_cur;
+	s32	rlim_max;
+};
+
 asmlinkage int sys32_getrlimit(unsigned int resource, u32 rlim)
 {
-	return sys_getrlimit(resource, (struct rlimit *)A(rlim));
+	struct rlimit r;
+	int ret;
+	unsigned long old_fs = get_fs ();
+	
+	set_fs (KERNEL_DS);
+	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))))
+		return -EFAULT;
+	return ret;
 }
 
 asmlinkage int sys32_setrlimit(unsigned int resource, u32 rlim)
 {
-	return sys_setrlimit(resource, (struct rlimit *)A(rlim));
+	struct rlimit r;
+	int ret;
+	unsigned long old_fs = get_fs ();
+
+	if (resource >= RLIM_NLIMITS) return -EINVAL;	
+	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;
+	set_fs (KERNEL_DS);
+	ret = sys_setrlimit(resource, &r);
+	set_fs (old_fs);
+	return ret;
 }
 
 asmlinkage int sys32_getrusage(int who, u32 ru)
 {
-	return sys_getrusage(who, (struct rusage *)A(ru));
+	struct rusage r;
+	int ret;
+	unsigned long old_fs = get_fs();
+		
+	set_fs (KERNEL_DS);
+	ret = sys_getrusage(who, &r);
+	set_fs (old_fs);
+	if (put_rusage (ru, &r)) return -EFAULT;
+	return ret;
 }
 
 asmlinkage int sys32_time(u32 tloc)
@@ -646,6 +1417,7 @@
 
 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));
 }
 
@@ -654,22 +1426,86 @@
 	return sys_settimeofday((struct timeval *)A(tv), (struct timezone *)A(tz));
 }
 
+struct timex32 {
+	unsigned int modes;
+	s32 offset;
+	s32 freq;
+	s32 maxerror;
+	s32 esterror;
+	int status;
+	s32 constant;
+	s32 precision;
+	s32 tolerance;
+	struct timeval time;
+	s32 tick;
+	s32 ppsfreq;
+	s32 jitter;
+	int shift;
+	s32 stabil;
+	s32 jitcnt;
+	s32 calcnt;
+	s32 errcnt;
+	s32 stbcnt;
+	int  :32; int  :32; int  :32; int  :32;
+	int  :32; int  :32; int  :32; int  :32;
+	int  :32; int  :32; int  :32; int  :32;
+};
+
 asmlinkage int sys32_adjtimex(u32 txc_p)
 {
-	return sys_adjtimex((struct timex *)A(txc_p));
+	struct timex t;
+	int ret;
+	unsigned long old_fs = get_fs ();
+
+	if (get_user (t.modes, &(((struct timex32 *)A(txc_p))->modes)) ||
+	    __get_user (t.offset, &(((struct timex32 *)A(txc_p))->offset)) ||
+	    __get_user (t.freq, &(((struct timex32 *)A(txc_p))->freq)) ||
+	    __get_user (t.maxerror, &(((struct timex32 *)A(txc_p))->maxerror)) ||
+	    __get_user (t.esterror, &(((struct timex32 *)A(txc_p))->esterror)) ||
+	    __get_user (t.status, &(((struct timex32 *)A(txc_p))->status)) ||
+	    __get_user (t.constant, &(((struct timex32 *)A(txc_p))->constant)) ||
+	    __get_user (t.tick, &(((struct timex32 *)A(txc_p))->tick)) ||
+	    __get_user (t.shift, &(((struct timex32 *)A(txc_p))->shift)))
+		return -EFAULT;
+	set_fs (KERNEL_DS);
+	ret = sys_adjtimex(&t);
+	set_fs (old_fs);
+	if ((unsigned)ret >= 0 && (
+	    __put_user (t.modes, &(((struct timex32 *)A(txc_p))->modes)) ||
+	    __put_user (t.offset, &(((struct timex32 *)A(txc_p))->offset)) ||
+	    __put_user (t.freq, &(((struct timex32 *)A(txc_p))->freq)) ||
+	    __put_user (t.maxerror, &(((struct timex32 *)A(txc_p))->maxerror)) ||
+	    __put_user (t.esterror, &(((struct timex32 *)A(txc_p))->esterror)) ||
+	    __put_user (t.status, &(((struct timex32 *)A(txc_p))->status)) ||
+	    __put_user (t.constant, &(((struct timex32 *)A(txc_p))->constant)) ||
+	    __put_user (t.precision, &(((struct timex32 *)A(txc_p))->precision)) ||
+	    __put_user (t.tolerance, &(((struct timex32 *)A(txc_p))->tolerance)) ||
+	    __put_user (t.time.tv_sec, &(((struct timex32 *)A(txc_p))->time.tv_sec)) ||
+	    __put_user (t.time.tv_usec, &(((struct timex32 *)A(txc_p))->time.tv_usec)) ||
+	    __put_user (t.tick, &(((struct timex32 *)A(txc_p))->tick)) ||
+	    __put_user (t.ppsfreq, &(((struct timex32 *)A(txc_p))->ppsfreq)) ||
+	    __put_user (t.jitter, &(((struct timex32 *)A(txc_p))->jitter)) ||
+	    __put_user (t.shift, &(((struct timex32 *)A(txc_p))->shift)) ||
+	    __put_user (t.stabil, &(((struct timex32 *)A(txc_p))->stabil)) ||
+	    __put_user (t.jitcnt, &(((struct timex32 *)A(txc_p))->jitcnt)) ||
+	    __put_user (t.calcnt, &(((struct timex32 *)A(txc_p))->calcnt)) ||
+	    __put_user (t.errcnt, &(((struct timex32 *)A(txc_p))->errcnt)) ||
+	    __put_user (t.stbcnt, &(((struct timex32 *)A(txc_p))->stbcnt))))
+		return -EFAULT;
+	return ret;
 }
 
-asmlinkage int sys32_msync(u32 start, u32 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);
 }
 
-asmlinkage int sys32_mlock(u32 start, u32 len)
+asmlinkage int sys32_mlock(u32 start, __kernel_size_t32 len)
 {
 	return sys_mlock((unsigned long)start, (size_t)len);
 }
 
-asmlinkage int sys32_munlock(u32 start, u32 len)
+asmlinkage int sys32_munlock(u32 start, __kernel_size_t32 len)
 {
 	return sys_munlock((unsigned long)start, (size_t)len);
 }
@@ -679,12 +1515,12 @@
 	return sys_brk((unsigned long)brk);
 }
 
-asmlinkage int sys32_munmap(u32 addr, u32 len)
+asmlinkage int sys32_munmap(u32 addr, __kernel_size_t32 len)
 {
 	return sys_munmap((unsigned long)addr, (size_t)len);
 }
 
-asmlinkage int sys32_mprotect(u32 start, u32 len, u32 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);
 }
@@ -706,6 +1542,7 @@
 
 asmlinkage int sys32_bind(int fd, u32 umyaddr, int addrlen)
 {
+	/* sockaddr is the same :)) */
 	return sys_bind(fd, (struct sockaddr *)A(umyaddr), addrlen);
 }
 
@@ -729,28 +1566,31 @@
 	return sys_getpeername(fd, (struct sockaddr *)A(usockaddr), (int *)A(usockaddr_len));
 }
 
-asmlinkage int sys32_send(int fd, u32 buff, u32 len, unsigned flags)
+asmlinkage int sys32_send(int fd, u32 buff, __kernel_size_t32 len, unsigned flags)
 {
 	return sys_send(fd, (void *)A(buff), (size_t)len, flags);
 }
 
-asmlinkage int sys32_sendto(int fd, u32 buff, u32 len, unsigned flags, u32 addr, int addr_len)
+asmlinkage 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);
 }
 
-asmlinkage int sys32_recv(int fd, u32 ubuf, u32 size, unsigned flags)
+asmlinkage int sys32_recv(int fd, u32 ubuf, __kernel_size_t32 size, unsigned flags)
 {
 	return sys_recv(fd, (void *)A(ubuf), (size_t)size, flags);
 }
 
-asmlinkage int sys32_recvfrom(int fd, u32 ubuf, u32 size, unsigned flags, u32 addr, u32 addr_len)
+asmlinkage 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));
 }
  
 asmlinkage 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);
 }
 
@@ -759,6 +1599,7 @@
 	return sys_getsockopt(fd, level, optname, (char *)A(optval), (int *)A(optlen));
 }
 
+/* Continue here */
 asmlinkage int sys32_sendmsg(int fd, u32 msg, unsigned flags)
 {
 	return sys_sendmsg(fd, (struct msghdr *)A(msg), flags);
@@ -809,7 +1650,7 @@
 	if (oldaction) {
 		err = -EFAULT;
 		old_sa.sa_handler = (unsigned)(u64)(p->sa_handler);
-		old_sa.sa_mask = (sigset32_t)(p->sa_mask);
+		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)))
@@ -828,4 +1669,73 @@
 out:
 	unlock_kernel();
 	return err;
+}
+
+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));
+}
+
+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;
+};
+
+void *do_ncp_super_data_conv(void *raw_data)
+{
+	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;
+}
+
+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;
+};
+
+void *do_smb_super_data_conv(void *raw_data)
+{
+	struct smb_mount_data *s = (struct smb_mount_data *)raw_data;
+	struct smb_mount_data32 *s32 = (struct smb_mount_data32 *)raw_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;
 }
diff -u --recursive --new-file v2.1.35/linux/arch/sparc64/kernel/systbls.S linux/arch/sparc64/kernel/systbls.S
--- v2.1.35/linux/arch/sparc64/kernel/systbls.S	Mon Apr 14 16:28:09 1997
+++ linux/arch/sparc64/kernel/systbls.S	Tue Apr 22 22:49:38 1997
@@ -1,8 +1,9 @@
-/* $Id: systbls.S,v 1.5 1997/04/09 08:25:16 jj Exp $
+/* $Id: systbls.S,v 1.8 1997/04/21 08:34:23 jj Exp $
  * systbls.S: System call entry point tables for OS compatibility.
  *            The native Linux system call table lives here also.
  *
  * Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
  *
  * Based upon preliminary work which is:
  *
@@ -56,7 +57,7 @@
 	.xword sys_setpgid, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_newuname
 /*190*/	.xword sys_nis_syscall, 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, old_readdir
+/*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
@@ -66,7 +67,7 @@
 	.xword sys_nis_syscall, sys32_llseek, sys32_mlock, sys32_munlock, sys_mlockall
 /*240*/	.xword sys_munlockall, sys32_sched_setparam, sys32_sched_getparam, sys_nis_syscall, sys_nis_syscall
 	.xword sys_nis_syscall, sys_sched_get_priority_max, sys_sched_get_priority_min, sys32_sched_rr_get_interval, sys_nanosleep
-/*250*/	.xword sys32_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nis_syscall
+/*250*/	.xword sys32_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys32_nfsservctl
 	.xword sys_aplib, sys_nis_syscall
 
 	/* Now the 64-bit native Linux syscall table. */
@@ -114,8 +115,8 @@
 	.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, old_readdir
-	.xword sys_nis_syscall, sys_socketcall, sys_syslog, sys_olduname, sys_nis_syscall
+/*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
 /*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
@@ -124,7 +125,7 @@
 	.xword sys_nis_syscall, sys_llseek, sys_mlock, sys_munlock, sys_mlockall
 /*240*/	.xword sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_nis_syscall, sys_nis_syscall
 	.xword sys_nis_syscall, sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, sys_nanosleep
-/*250*/	.xword sys_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nis_syscall
+/*250*/	.xword sys_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl
 	.xword sys_aplib, sys_nis_syscall
 
 	/* Now the 32-bit SunOS syscall table. */
diff -u --recursive --new-file v2.1.35/linux/arch/sparc64/lib/checksum.S linux/arch/sparc64/lib/checksum.S
--- v2.1.35/linux/arch/sparc64/lib/checksum.S	Mon Apr 14 16:28:10 1997
+++ linux/arch/sparc64/lib/checksum.S	Tue Apr 22 22:39:12 1997
@@ -16,6 +16,7 @@
 #include <asm/errno.h>
 #include <asm/head.h>
 #include <asm/ptrace.h>
+#include <asm/asi.h>
 
 #define CSUM_BIGCHUNK(buf, offset, sum, t0, t1, t2, t3, t4, t5)	\
 	ldd	[buf + offset + 0x00], t0;			\
@@ -547,22 +548,18 @@
 	brz,pn	%i2, 2f
 	 mov	%i0, %o1
 	mov	%i1, %o0
-5:
-	call	__memcpy
+	call	__copy_from_user
 	 mov	%i2, %o2
 	brnz,a,pn %o0, 2f
 	 add	%i3, %i2, %i3
 	add	%i1, %i2, %i1
 2:
 	mov	%i1, %o0
-	call	__bzero
+        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
-
-        .section __ex_table,#alloc
-        .align 4
-        .word 5b,2
diff -u --recursive --new-file v2.1.35/linux/arch/sparc64/mm/init.c linux/arch/sparc64/mm/init.c
--- v2.1.35/linux/arch/sparc64/mm/init.c	Mon Apr 14 16:28:10 1997
+++ linux/arch/sparc64/mm/init.c	Tue Apr 22 22:39:12 1997
@@ -1,4 +1,4 @@
-/*  $Id: init.c,v 1.22 1997/04/12 04:28:48 davem Exp $
+/*  $Id: init.c,v 1.24 1997/04/17 21:49:41 jj Exp $
  *  arch/sparc64/mm/init.c
  *
  *  Copyright (C) 1996,1997 David S. Miller (davem@caip.rutgers.edu)
@@ -32,6 +32,9 @@
 
 unsigned long tlb_context_cache = CTX_FIRST_VERSION;
 
+/* References to section boundaries */
+extern char __init_begin, __init_end, etext, __p1275_loc, __bss_start;
+
 /*
  * BAD_PAGE is the page that is used for page faults when linux
  * is out-of-memory. Older versions of linux just did a
@@ -268,6 +271,7 @@
 
 char *mmu_info(void)
 {
+	/* XXX */
 	return "MMU Type: Spitfire\n\tFIXME: Write this\n";
 }
 
@@ -436,15 +440,6 @@
 	else
 		pte = mk_pte_phys(physaddr, __pgprot(pg_iobits | __DIRTY_BITS));
 
-#if 0
-	prom_printf("IOMAP: vaddr[%016lx]paddr[%016lx]ptep[%016lx]pte[%016lx])\n",
-		    virt_addr, physaddr, (unsigned long) ptep, pte_val(pte));
-	prom_printf("IOMAP: pgd[%016lx,%016lx]\n",
-		    (unsigned long) pgdp, pgd_val(*pgdp));
-	prom_printf("IOMAP: pmd[%016lx,%016lx]\n",
-		    (unsigned long) pmdp, pmd_val(*pmdp));
-#endif
-
 	set_pte(ptep, pte);
 }
 
@@ -462,6 +457,7 @@
 	pte_clear(ptep);
 }
 
+#ifdef DEBUG_MMU
 void sparc_ultra_dump_itlb(void)
 {
         int slot;
@@ -485,6 +481,7 @@
         		slot+1, spitfire_get_dtlb_tag(slot+1), spitfire_get_dtlb_data(slot+1));
         }
 }
+#endif
 
 /* paging_init() sets up the page tables */
 
@@ -493,7 +490,6 @@
 __initfunc(unsigned long 
 paging_init(unsigned long start_mem, unsigned long end_mem))
 {
-	extern unsigned long __p1275_loc;
 	extern unsigned long phys_base;
 	extern void setup_tba(unsigned long kpgdir);
 	extern void __bfill64(void *, unsigned long);
@@ -637,9 +633,10 @@
 {
 	int codepages = 0;
 	int datapages = 0;
+	int initpages = 0;
+	int prompages = 0;
 	unsigned long tmp2, addr;
 	unsigned long data_end;
-	extern char etext;
 
 	end_mem &= PAGE_MASK;
 	max_mapnr = MAP_NR(end_mem);
@@ -665,6 +662,10 @@
 		if(PageReserved(mem_map + MAP_NR(addr))) {
 			if ((addr < (unsigned long) &etext) && (addr >= PAGE_OFFSET))
 				codepages++;
+			else if((addr >= (unsigned long)&__init_begin && addr < (unsigned long)&__init_end))
+				initpages++;
+			else if((addr >= (unsigned long)&__p1275_loc && addr < (unsigned long)&__bss_start))
+				prompages++;
 			else if((addr < data_end) && (addr >= PAGE_OFFSET))
 				datapages++;
 			continue;
@@ -680,26 +681,23 @@
 
 	tmp2 = nr_free_pages << PAGE_SHIFT;
 
-	printk("Memory: %luk available (%dk kernel code, %dk data) [%016lx,%016lx]\n",
+	printk("Memory: %luk available (%dk kernel code, %dk data, %dk init, %dk prom) [%016lx,%016lx]\n",
 	       tmp2 >> 10,
 	       codepages << (PAGE_SHIFT-10),
-	       datapages << (PAGE_SHIFT-10), PAGE_OFFSET, end_mem);
+	       datapages << (PAGE_SHIFT-10), 
+	       initpages << (PAGE_SHIFT-10), 
+	       prompages << (PAGE_SHIFT-10), 
+	       PAGE_OFFSET, end_mem);
 
 	min_free_pages = nr_free_pages >> 7;
 	if(min_free_pages < 16)
 		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("Done in mem_init() halting\n");
-	prom_cmdline();
-#endif
 }
 
 void free_initmem (void)
 {
-	extern char __init_begin, __init_end;
 	unsigned long addr;
 	
 	addr = (unsigned long)(&__init_begin);
@@ -708,7 +706,6 @@
 		atomic_set(&mem_map[MAP_NR(addr)].count, 1);
 		free_page(addr);
 	}
-	printk ("Freeing unused kernel memory: %dk freed\n", (unsigned)((&__init_end - &__init_begin) >> 10));
 }
 
 void si_meminfo(struct sysinfo *val)
diff -u --recursive --new-file v2.1.35/linux/drivers/Makefile linux/drivers/Makefile
--- v2.1.35/linux/drivers/Makefile	Sun Apr 13 10:18:20 1997
+++ linux/drivers/Makefile	Thu Apr 17 14:48:53 1997
@@ -7,17 +7,12 @@
 #
 # Note 2! The CFLAGS definitions are now in the main makefile...
 
-SUB_DIRS     := block char net #streams
+SUB_DIRS     := block char net pnp #streams
 MOD_SUB_DIRS := $(SUB_DIRS) sbus
 ALL_SUB_DIRS := $(SUB_DIRS) pci scsi sbus sound cdrom isdn pnp
 
 ifdef CONFIG_PCI
 SUB_DIRS += pci
-endif
-
-ifdef CONFIG_PNP
-SUB_DIRS += pnp
-MOD_SUB_DIRS += pnp
 endif
 
 ifdef CONFIG_SBUS
diff -u --recursive --new-file v2.1.35/linux/drivers/block/Config.in linux/drivers/block/Config.in
--- v2.1.35/linux/drivers/block/Config.in	Thu Mar 27 14:40:02 1997
+++ linux/drivers/block/Config.in	Tue Apr 22 15:32:00 1997
@@ -23,7 +23,7 @@
     fi
     if [ "$CONFIG_PCI" = "y" ]; then
       bool '   RZ1000 chipset bugfix/support' CONFIG_BLK_DEV_RZ1000
-      bool '   Intel PIIX/PIIX3 (Triton 430FX/HX/VX, 440FX) DMA support' CONFIG_BLK_DEV_TRITON
+      bool '   Intel PIIX/PIIX3/PIIX4 (Triton 430FX/HX/VX/TX, 440FX) DMA support' CONFIG_BLK_DEV_TRITON
     fi
     bool '   Other IDE chipset support' CONFIG_IDE_CHIPSETS
     if [ "$CONFIG_IDE_CHIPSETS" = "y" ]; then
diff -u --recursive --new-file v2.1.35/linux/drivers/block/acsi.c linux/drivers/block/acsi.c
--- v2.1.35/linux/drivers/block/acsi.c	Fri Dec 20 01:19:59 1996
+++ linux/drivers/block/acsi.c	Thu Apr 17 13:20:44 1997
@@ -43,8 +43,6 @@
  *
  */
 
-#include <linux/module.h>
-
 #define MAJOR_NR ACSI_MAJOR
 
 #include <linux/config.h>
@@ -1127,9 +1125,8 @@
 		 * ACSI disks...
 		 */
 	  case BLKGETSIZE:   /* Return device size */
-		if (put_user(acsi_part[MINOR(inode->i_rdev)].nr_sects,
-			     (long *)arg))
-                    return -EFAULT;                                     
+		return put_user(acsi_part[MINOR(inode->i_rdev)].nr_sects,
+				(long *) arg);
 	  case BLKFLSBUF:
 		if(!suser())  return -EACCES;
 		if(!inode->i_rdev) return -EINVAL;
@@ -1629,33 +1626,23 @@
 	return DEV_SUPPORTED;
 }
 
-#ifdef CONFIG_ATARI_SLM_MODULE
-void acsi_attach_SLMs( int (*attach_func)( int, int ) );
-#endif
+EXPORT_SYMBOL(acsi_delay_start);
+EXPORT_SYMBOL(acsi_delay_end);
+EXPORT_SYMBOL(acsi_wait_for_IRQ);
+EXPORT_SYMBOL(acsi_wait_for_noIRQ);
+EXPORT_SYMBOL(acsicmd_nodma);
+EXPORT_SYMBOL(acsi_getstatus);
+EXPORT_SYMBOL(acsi_buffer);
+EXPORT_SYMBOL(phys_acsi_buffer);
 
-static struct symbol_table acsi_symbol_table =
-{
-#include <linux/symtab_begin.h>
-
-	X(acsi_delay_start),
-	X(acsi_delay_end),
-	X(acsi_wait_for_IRQ),
-	X(acsi_wait_for_noIRQ),
-	X(acsicmd_nodma),
-	X(acsi_getstatus),
-	X(acsi_buffer),
-	X(phys_acsi_buffer),
 #ifdef CONFIG_ATARI_SLM_MODULE
-	X(acsi_extstatus),
-	X(acsi_end_extstatus),
-	X(acsi_extcmd),
-	X(acsi_attach_SLMs),
-#endif
+void acsi_attach_SLMs( int (*attach_func)( int, int ) );
 
-#include <linux/symtab_end.h>
-};
+EXPORT_SYMBOL(acsi_extstatus);
+EXPORT_SYMBOL(acsi_end_extstatus);
+EXPORT_SYMBOL(acsi_extcmd);
+EXPORT_SYMBOL(acsi_attach_SLMs);
 
-#ifdef CONFIG_ATARI_SLM_MODULE
 /* to remember IDs of SLM devices, SLM module is loaded later
  * (index is target#, contents is lun#, -1 means "no SLM") */
 int SLM_devices[8];
@@ -1751,7 +1738,6 @@
 	for( i = 0; i < (MAX_DEV << 4); i++ )
 		acsi_blocksizes[i] = 1024;
 	blksize_size[MAJOR_NR] = acsi_blocksizes;
-	register_symtab (&acsi_symbol_table);
 }
 
 #ifdef CONFIG_ATARI_SLM_MODULE
diff -u --recursive --new-file v2.1.35/linux/drivers/block/amiflop.c linux/drivers/block/amiflop.c
--- v2.1.35/linux/drivers/block/amiflop.c	Fri Apr  4 08:52:17 1997
+++ linux/drivers/block/amiflop.c	Thu Apr 17 13:20:44 1997
@@ -56,6 +56,7 @@
 #include <linux/kernel.h>
 #include <linux/timer.h>
 #include <linux/fd.h>
+#include <linux/hdreg.h>
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/delay.h>
@@ -401,6 +402,7 @@
 	restore_flags(flags);
 
 	if (on_attempts == 0) {
+		on_attempts = -1;
 #if 0
 		printk (KERN_ERR "motor_on failed, turning motor off\n");
 		fd_motor_off (nr);
@@ -1511,93 +1513,103 @@
 	int error;
 	unsigned long flags;
 
-	switch(cmd)
-	 {
-	  case FDFMTBEG:
-	  get_hw(drive);
-	    if (fd_ref[drive] > 1) {
-	      rel_hw();
-	      return -EBUSY;
-	    }
-	    fsync_dev(inode->i_rdev);
-	    if (motor_on(drive) == 0) {
-	      rel_hw();
-	      return -ENODEV;
-	    }
-	    if (fd_calibrate(drive) == 0) {
-	      rel_hw();
-	      return -ENXIO;
-	    }
-	    floppy_off(drive);
-	    rel_hw();
-	    break;
-	  case FDFMTTRK:
-	    if (param < unit[drive].type->tracks * unit[drive].type->heads)
-	     {
-	      get_fdc(drive);
-	      get_hw(drive);
-	      fd_select(drive);
-	      if (fd_seek(drive,param)!=0)
-	       {
-	        savedtrack=param;
-	        memset(trackdata,FD_FILL_BYTE,unit[drive].sects*512);
-	        non_int_flush_track(drive);
-	       }
-	      floppy_off(drive);
-	      rel_hw();
-	      rel_fdc();
-	     }
-	    else
-	      return -EINVAL;
-	    break;
-	  case FDFMTEND:
-	    floppy_off(drive);
-	    invalidate_inodes(inode->i_rdev);
-	    invalidate_buffers(inode->i_rdev);
-	    break;
-	  case FDGETPRM:
-	    error = verify_area(VERIFY_WRITE, (void *)param,
-				sizeof(struct floppy_struct));
-	    if (error)
-	      return error;
-	    memset((void *)&getprm, 0, sizeof (getprm));
-	    getprm.track=unit[drive].type->tracks;
-	    getprm.head=unit[drive].type->heads;
-	    getprm.sect=unit[drive].sects;
-	    getprm.size=unit[drive].blocks;
-	    copy_to_user((void *)param,(void *)&getprm,sizeof(struct floppy_struct));
+	switch(cmd){
+	case HDIO_GETGEO:
+	{
+		struct hd_geometry loc;
+		loc.heads = unit[drive].type->heads;
+		loc.sectors = unit[drive].sects;
+		loc.cylinders = unit[drive].type->tracks;
+		loc.start = 0;
+		if ((error = copy_to_user((void *)param, (void *)&loc,
+					  sizeof(struct hd_geometry))))
+			return error;
+		break;
+	}
+	case FDFMTBEG:
+		get_hw(drive);
+		if (fd_ref[drive] > 1) {
+			rel_hw();
+			return -EBUSY;
+		}
+		fsync_dev(inode->i_rdev);
+		if (motor_on(drive) == 0) {
+			rel_hw();
+			return -ENODEV;
+		}
+		if (fd_calibrate(drive) == 0) {
+			rel_hw();
+			return -ENXIO;
+		}
+		floppy_off(drive);
+		rel_hw();
+		break;
+	case FDFMTTRK:
+		if (param < unit[drive].type->tracks * unit[drive].type->heads)
+		{
+			get_fdc(drive);
+			get_hw(drive);
+			fd_select(drive);
+			if (fd_seek(drive,param)!=0){
+				savedtrack=param;
+				memset(trackdata, FD_FILL_BYTE,
+				       unit[drive].sects*512);
+				non_int_flush_track(drive);
+			}
+			floppy_off(drive);
+			rel_hw();
+			rel_fdc();
+		}
+		else
+			return -EINVAL;
+		break;
+	case FDFMTEND:
+		floppy_off(drive);
+		invalidate_inodes(inode->i_rdev);
+		invalidate_buffers(inode->i_rdev);
+		break;
+	case FDGETPRM:
+		memset((void *)&getprm, 0, sizeof (getprm));
+		getprm.track=unit[drive].type->tracks;
+		getprm.head=unit[drive].type->heads;
+		getprm.sect=unit[drive].sects;
+		getprm.size=unit[drive].blocks;
+		if ((error = copy_to_user((void *)param,
+					  (void *)&getprm,
+					  sizeof(struct floppy_struct))))
+			return error;
 	    break;
-	  case BLKGETSIZE:
-	    if (put_user(unit[drive].blocks,(long *)param))
-		    return -EFAULT;
-            break;
-          case FDSETPRM:
-          case FDDEFPRM:
-            return -EINVAL;
-          case FDFLUSH:
-	    save_flags(flags);
-	    cli();
-            if ((drive == selected) && (writepending)) {
-              del_timer (&flush_track_timer);
-              restore_flags(flags);
-              non_int_flush_track(selected);
-            }
-            else
-              restore_flags(flags);
-            break;
+	case BLKGETSIZE:
+		if (put_user(unit[drive].blocks,(long *)param))
+			return -EFAULT;
+		break;
+	case FDSETPRM:
+	case FDDEFPRM:
+		return -EINVAL;
+	case FDFLUSH:
+		save_flags(flags);
+		cli();
+		if ((drive == selected) && (writepending)) {
+			del_timer (&flush_track_timer);
+			restore_flags(flags);
+			non_int_flush_track(selected);
+		}
+		else
+			restore_flags(flags);
+		break;
 #ifdef RAW_IOCTL
-	  case IOCTL_RAW_TRACK:
-	    error = verify_area(VERIFY_WRITE, (void *)param,
-	      unit[drive].type->read_size);
-	    if (error)
-	      return error;
-	    copy_to_user((void *)param, raw_buf, unit[drive].type->read_size);
-	    return unit[drive].type->read_size;
+	case IOCTL_RAW_TRACK:
+		error = copy_to_user((void *)param, raw_buf,
+				     unit[drive].type->read_size);
+		if (error)
+			return error;
+		else
+			return unit[drive].type->read_size;
 #endif
-	  default:
-	    printk(KERN_DEBUG "fd_ioctl: unknown cmd %d for drive %d.",cmd,drive);
-	    return -ENOSYS;
-         }
+	default:
+		printk(KERN_DEBUG "fd_ioctl: unknown cmd %d for drive %d.",cmd,drive);
+		return -ENOSYS;
+	}
 	return 0;
 }
 
diff -u --recursive --new-file v2.1.35/linux/drivers/block/ataflop.c linux/drivers/block/ataflop.c
--- v2.1.35/linux/drivers/block/ataflop.c	Fri Apr  4 08:52:17 1997
+++ linux/drivers/block/ataflop.c	Thu Apr 17 13:20:44 1997
@@ -52,6 +52,9 @@
  * Michael (MSch) 11/07/96:
  *  - implemented FDSETPRM and FDDEFPRM ioctl
  *
+ * Andreas (97/03/19):
+ *  - implemented missing BLK* ioctls
+ *
  *  Things left to do:
  *   - Formatting
  *   - Maybe a better strategy for disk change detection (does anyone
@@ -281,6 +284,7 @@
 static unsigned long PhysDMABuffer;   /* physical address */
 
 static int UseTrackbuffer = -1;		  /* Do track buffering? */
+MODULE_PARM(UseTrackbuffer, "i");
 
 unsigned char *TrackBuffer;			  /* buffer for reads */
 static unsigned long PhysTrackBuffer; /* physical address */
@@ -305,6 +309,7 @@
 static int IsFormatting = 0, FormatError;
 
 static int UserSteprate[FD_MAX_UNITS] = { -1, -1 };
+MODULE_PARM(UserSteprate, "1-" __MODULE_STRING(FD_MAX_UNITS) "i");
 
 /* Synchronization of FDC access. */
 static volatile int fdc_busy = 0;
@@ -405,7 +410,7 @@
 static int fd_test_drive_present( int drive );
 static void config_types( void );
 static int floppy_open( struct inode *inode, struct file *filp );
-static void floppy_release( struct inode * inode, struct file * filp );
+static int floppy_release( struct inode * inode, struct file * filp );
 
 /************************* End of Prototypes **************************/
 
@@ -1582,6 +1587,7 @@
 	drive &= 3;
 	switch (cmd) {
 	case FDGETPRM:
+	case BLKGETSIZE:
 		if (type) {
 			if (--type >= NUM_DISK_MINORS)
 				return -ENODEV;
@@ -1599,6 +1605,9 @@
 			else
 				dtp = UDT;
 		}
+		if (cmd == BLKGETSIZE)
+			return put_user(dtp->blocks, (long *)param);
+
 		memset((void *)&getprm, 0, sizeof(getprm));
 		getprm.size = dtp->blocks;
 		getprm.sect = dtp->spt;
@@ -1607,6 +1616,22 @@
 		getprm.stretch = dtp->stretch;
 		if (copy_to_user((void *)param, &getprm, sizeof(getprm)))
 			return -EFAULT;
+		return 0;
+	case BLKRASET:
+		if (!suser())
+			return -EACCES;
+		if (param > 0xff)
+			return -EINVAL;
+		read_ahead[MAJOR(inode->i_rdev)] = param;
+		return 0;
+	case BLKRAGET:
+		return put_user(read_ahead[MAJOR(inode->i_rdev)],
+				(int *) param);
+	case BLKFLSBUF:
+		if (!suser())
+			return -EACCES;
+		fsync_dev(inode->i_rdev);
+		invalidate_buffers(inode->i_rdev);
 		return 0;
 	}
 	if (!IOCTL_ALLOWED)
diff -u --recursive --new-file v2.1.35/linux/drivers/block/floppy.c linux/drivers/block/floppy.c
--- v2.1.35/linux/drivers/block/floppy.c	Mon Apr 14 16:28:11 1997
+++ linux/drivers/block/floppy.c	Tue Apr 15 22:26:28 1997
@@ -1676,10 +1676,13 @@
 		} while ((ST0 & 0x83) != UNIT(current_drive) && inr == 2);
 	}
 	if (handler) {
-		if (in_interrupt())
-			schedule_bh( (void *)(void *) handler);
-		else
+		if(softirq_trylock()) {
+			/* got the lock, call the handler immediately */
 			handler();
+			softirq_endlock();
+		} else
+			/* we interrupted a bottom half. Defer handler */
+			schedule_bh( (void *)(void *) handler);
 	} else
 		FDCS->reset = 1;
 	is_alive("normal interrupt end");
diff -u --recursive --new-file v2.1.35/linux/drivers/block/genhd.c linux/drivers/block/genhd.c
--- v2.1.35/linux/drivers/block/genhd.c	Sun Apr 13 10:18:20 1997
+++ linux/drivers/block/genhd.c	Thu Apr 17 13:20:44 1997
@@ -25,6 +25,7 @@
 #include <linux/major.h>
 #include <linux/string.h>
 #include <linux/blk.h>
+#include <linux/init.h>
 
 #include <asm/system.h>
 
@@ -739,7 +740,7 @@
 	}
 }
 
-static void setup_dev(struct gendisk *dev)
+static inline void setup_dev(struct gendisk *dev)
 {
 	int i, drive;
 	int end_minor	= dev->max_nr * dev->max_p;
@@ -762,7 +763,7 @@
 	}
 }
 
-void device_setup(void)
+__initfunc(void device_setup(void))
 {
 	extern void console_map_init(void);
 #ifdef CONFIG_PNP_PARPORT
diff -u --recursive --new-file v2.1.35/linux/drivers/block/ide.c linux/drivers/block/ide.c
--- v2.1.35/linux/drivers/block/ide.c	Fri Apr  4 08:52:17 1997
+++ linux/drivers/block/ide.c	Tue Apr 22 15:32:00 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);
 #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.35/linux/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c
--- v2.1.35/linux/drivers/block/ll_rw_blk.c	Thu Mar 27 14:40:02 1997
+++ linux/drivers/block/ll_rw_blk.c	Thu Apr 17 13:20:44 1997
@@ -16,6 +16,7 @@
 #include <linux/config.h>
 #include <linux/locks.h>
 #include <linux/mm.h>
+#include <linux/init.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
@@ -631,7 +632,7 @@
 extern void bpcd_init( void );
 #endif
 
-int blk_dev_init(void)
+__initfunc(int blk_dev_init(void))
 {
 	struct request * req;
 	struct blk_dev_struct *dev;
diff -u --recursive --new-file v2.1.35/linux/drivers/block/rd.c linux/drivers/block/rd.c
--- v2.1.35/linux/drivers/block/rd.c	Fri Apr  4 08:52:18 1997
+++ linux/drivers/block/rd.c	Thu Apr 17 13:20:44 1997
@@ -200,7 +200,7 @@
 {
 	unsigned long i;
 
-	if (--initrd_users) return;
+	if (--initrd_users) return 0;
 	for (i = initrd_start; i < initrd_end; i += PAGE_SIZE)
 		free_page(i);
 	initrd_start = 0;
@@ -405,11 +405,11 @@
 	}
 
 	/* Try ext2 */
-	if (ext2sb->s_magic == EXT2_SUPER_MAGIC) {
+	if (ext2sb->s_magic == cpu_to_le16(EXT2_SUPER_MAGIC)) {
 		printk(KERN_NOTICE
 		       "RAMDISK: Ext2 filesystem found at block %d\n",
 		       start_block);
-		nblocks = ext2sb->s_blocks_count;
+		nblocks = le32_to_cpu(ext2sb->s_blocks_count);
 		goto done;
 	}
 
diff -u --recursive --new-file v2.1.35/linux/drivers/block/triton.c linux/drivers/block/triton.c
--- v2.1.35/linux/drivers/block/triton.c	Fri Apr  4 08:52:18 1997
+++ linux/drivers/block/triton.c	Tue Apr 22 15:32:00 1997
@@ -1,5 +1,5 @@
 /*
- *  linux/drivers/block/triton.c	Version 2.00  March 9, 1997
+ *  linux/drivers/block/triton.c	Version 2.10  April 22, 1997
  *
  *  Copyright (c) 1995-1997  Mark Lord
  *  May be copied or modified under the terms of the GNU General Public License
@@ -8,8 +8,8 @@
 /*
  * This module provides support for the bus-master IDE DMA function
  * of the Intel PCI Triton chipset families, which use the PIIX (i82371FB,
- * for the 430 FX chipset), and the enhanced PIIX3 (i82371SB for the 430 HX/VX
- * and 440 chipsets).
+ * for the 430 FX chipset), the PIIX3 (i82371SB for the 430 HX/VX and 
+ * 440 chipsets), and the PIIX4 (i82371AB for the 430 TX chipset).
  *
  * "PIIX" stands for "PCI ISA IDE Xcellerator".
  *
@@ -18,12 +18,12 @@
  *
  * DMA is supported for all IDE devices (disk drives, cdroms, tapes, floppies).
  *
- * Up to four drives may be enabled for DMA, and the PIIX/PIIX3 chips
+ * Up to four drives may be enabled for DMA, and the PIIX* chips
  * will arbitrate the PCI bus among them.  Note that the PIIX/PIIX3
  * provides a single "line buffer" for the BM IDE function, so performance of
  * multiple (two) drives doing DMA simultaneously will suffer somewhat,
  * as they contest for that resource bottleneck.  This is handled transparently
- * inside the PIIX/PIIX3.
+ * inside the PIIX/PIIX3.  The PIIX4 does not have this problem.
  *
  * By default, DMA support is prepared for use, but is currently enabled only
  * for drives which support DMA mode2 (multi/single word), or which are
@@ -60,6 +60,9 @@
  * Thanks to "Christopher J. Reimer" <reimer@doe.carleton.ca> for fixing the
  * problem with some (all?) ACER motherboards/BIOSs.
  *
+ * Thanks to "Benoit Poulot-Cazajous" <poulot@chorus.fr> for testing
+ * "TX" chipset compatibility and for providing patches for the "TX" chipset.
+ *
  * And, yes, Intel Zappa boards really *do* use both PIIX IDE ports.
  */
 #include <linux/types.h>
@@ -342,7 +345,7 @@
 #ifdef DISPLAY_PIIX_TIMINGS
 /*
  * print_piix_drive_flags() displays the currently programmed options
- * in the PIIX/PIIX3 for a given drive.
+ * in the PIIX/PIIX3/PIIX4 for a given drive.
  */
 static void print_piix_drive_flags (const char *unit, byte dflags)
 {
@@ -448,7 +451,13 @@
 
 	if (pcibios_read_config_word(bus, fn, 0x02, &devid))
 		goto quit;
-	chipset = (devid == PCI_DEVICE_ID_INTEL_82371SB_1) ? "PIIX3" : "PIIX";
+
+	if (devid == PCI_DEVICE_ID_INTEL_82371AB)
+		chipset = "PIIX4";
+	else if (devid == PCI_DEVICE_ID_INTEL_82371SB_1)
+		chipset = "PIIX3";
+	else
+		chipset = "PIIX";
 
 	printk("%s: bus-master IDE device on PCI bus %d function %d\n", chipset, bus, fn);
 
@@ -532,10 +541,11 @@
 			piix_sidetim_t sidetim;
 			byte sample   = 5 - timing.sample;
 			byte recovery = 4 - timing.recovery;
-			if (devid == PCI_DEVICE_ID_INTEL_82371SB_1
+			if ((devid == PCI_DEVICE_ID_INTEL_82371SB_1
+			     || devid == PCI_DEVICE_ID_INTEL_82371AB)
 			 && timing.sidetim_enabled
 			 && !pcibios_read_config_byte(bus, fn, 0x44, (byte *) &sidetim))
-				slave = "";		/* PIIX3 */
+				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);
diff -u --recursive --new-file v2.1.35/linux/drivers/block/z2ram.c linux/drivers/block/z2ram.c
--- v2.1.35/linux/drivers/block/z2ram.c	Sun Jan 26 02:07:11 1997
+++ linux/drivers/block/z2ram.c	Thu Apr 17 13:20:44 1997
@@ -36,7 +36,7 @@
 #include <asm/setup.h>
 #include <asm/bitops.h>
 #include <asm/amigahw.h>
-#include <asm/zorro.h>
+#include <linux/zorro.h>
 
 #define TRUE                  (1)
 #define FALSE                 (0)
diff -u --recursive --new-file v2.1.35/linux/drivers/char/Makefile linux/drivers/char/Makefile
--- v2.1.35/linux/drivers/char/Makefile	Fri Apr  4 08:52:18 1997
+++ linux/drivers/char/Makefile	Thu Apr 17 13:20:45 1997
@@ -43,6 +43,16 @@
 endif
 endif
 
+ifeq ($(CONFIG_ATARI_DSP56K),y)
+L_OBJS += dsp56k.o
+S = y
+else
+  ifeq ($(CONFIG_ATARI_DSP56K),m)
+  M_OBJS += dsp56k.o
+  SM = y
+  endif
+endif
+
 ifeq ($(CONFIG_DIGI),y)
 L_OBJS += pcxx.o
 else
diff -u --recursive --new-file v2.1.35/linux/drivers/char/amigamouse.c linux/drivers/char/amigamouse.c
--- v2.1.35/linux/drivers/char/amigamouse.c	Fri Apr  4 08:52:18 1997
+++ linux/drivers/char/amigamouse.c	Tue Apr 22 22:42:47 1997
@@ -43,6 +43,7 @@
 #include <linux/miscdevice.h>
 #include <linux/random.h>
 #include <linux/poll.h>
+#include <linux/init.h>
 
 #include <asm/setup.h>
 #include <asm/system.h>
@@ -172,11 +173,11 @@
  * close access to the mouse
  */
 
-static int close_mouse(struct inode * inode, struct file * file)
+static int release_mouse(struct inode * inode, struct file * file)
 {
 	fasync_mouse(inode, file, 0);
 	if (--mouse.active)
-	  return;
+		return 0;
 	free_irq(IRQ_AMIGA_VERTB, mouse_interrupt);
 	MSE_INT_OFF();
 	MOD_DEC_USE_COUNT;
@@ -299,7 +300,7 @@
 	NULL, 		/* mouse_ioctl */
 	NULL,		/* mouse_mmap */
 	open_mouse,
-	close_mouse,
+	release_mouse,
 	NULL,
 	fasync_mouse,
 };
@@ -308,7 +309,7 @@
 	AMIGAMOUSE_MINOR, "amigamouse", &amiga_mouse_fops
 };
 
-int amiga_mouse_init(void)
+__initfunc(int amiga_mouse_init(void))
 {
 	if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_MOUSE))
 		return -ENODEV;
diff -u --recursive --new-file v2.1.35/linux/drivers/char/apm_bios.c linux/drivers/char/apm_bios.c
--- v2.1.35/linux/drivers/char/apm_bios.c	Fri Apr  4 08:52:18 1997
+++ linux/drivers/char/apm_bios.c	Tue Apr 22 22:42:47 1997
@@ -73,6 +73,7 @@
 #endif
 #include <linux/miscdevice.h>
 #include <linux/apm_bios.h>
+#include <linux/init.h>
 
 EXPORT_SYMBOL(apm_register_callback);
 EXPORT_SYMBOL(apm_unregister_callback);
@@ -451,7 +452,7 @@
 
 #ifdef CONFIG_APM_DO_ENABLE
 /* Called by apm_setup if apm_enabled will be true. */
-static int apm_enable_power_management(void)
+static inline int apm_enable_power_management(void)
 {
 	u_short	error;
 
@@ -474,7 +475,7 @@
 	return APM_SUCCESS;
 }
 
-static int apm_engage_power_management(u_short device)
+static inline int apm_engage_power_management(u_short device)
 {
 	u_short	error;
 
@@ -1059,7 +1060,7 @@
 }
 #endif
 
-void apm_bios_init(void)
+__initfunc(void apm_bios_init(void))
 {
 	unsigned short	bx;
 	unsigned short	cx;
diff -u --recursive --new-file v2.1.35/linux/drivers/char/atarimouse.c linux/drivers/char/atarimouse.c
--- v2.1.35/linux/drivers/char/atarimouse.c	Fri Apr  4 08:52:18 1997
+++ linux/drivers/char/atarimouse.c	Tue Apr 22 22:42:47 1997
@@ -20,6 +20,7 @@
 #include <linux/mm.h>
 #include <linux/random.h>
 #include <linux/poll.h>
+#include <linux/init.h>
 
 #include <asm/setup.h>
 #include <asm/atarikb.h>
@@ -27,7 +28,8 @@
 #include <asm/uaccess.h>
 
 static struct mouse_status mouse;
-static int atari_mouse_x_threshold = 2, atari_mouse_y_threshold = 2;
+static int mouse_threshold[2] = {2,2};
+MODULE_PARM(mouse_threshold, "2i");
 extern int atari_mouse_buttons;
 
 static void atari_mouse_interrupt(char *buf)
@@ -82,7 +84,7 @@
     mouse.dx = mouse.dy = 0;
     atari_mouse_buttons = 0;
     ikbd_mouse_y0_top ();
-    ikbd_mouse_thresh (atari_mouse_x_threshold, atari_mouse_y_threshold);
+    ikbd_mouse_thresh (mouse_threshold[0], mouse_threshold[1]);
     ikbd_mouse_rel_pos();
     MOD_INC_USE_COUNT;
     atari_mouse_interrupt_hook = atari_mouse_interrupt;
@@ -99,12 +101,9 @@
 		       char *buffer, unsigned long count)
 {
     int dx, dy, buttons;
-    int r;
 
     if (count < 3)
 	return -EINVAL;
-    if ((r = verify_area(VERIFY_WRITE, buffer, count)))
-	return r;
     if (!mouse.ready)
 	return -EAGAIN;
     /* ikbd_mouse_disable */
@@ -124,12 +123,14 @@
     if (mouse.dx == 0 && mouse.dy == 0)
       mouse.ready = 0;
     /* ikbd_mouse_rel_pos(); */
-    put_user(buttons | 0x80, buffer);
-    put_user((char) dx, buffer + 1);
-    put_user((char) dy, buffer + 2);
-    for (r = 3; r < count; r++)
-      put_user (0, buffer + r);
-    return r;
+    if (put_user(buttons | 0x80, buffer++) ||
+	put_user((char) dx, buffer++) ||
+	put_user((char) dy, buffer++))
+	return -EFAULT;
+    if (count > 3)
+	if (clear_user(buffer, count - 3))
+	    return -EFAULT;
+    return count;
 }
 
 static unsigned int mouse_poll(struct file *file, poll_table *wait)
@@ -158,7 +159,7 @@
     ATARIMOUSE_MINOR, "atarimouse", &atari_mouse_fops
 };
 
-int atari_mouse_init(void)
+__initfunc(int atari_mouse_init(void))
 {
     mouse.active = 0;
     mouse.ready = 0;
@@ -188,13 +189,13 @@
     if (ints[1] < MIN_THRESHOLD || ints[1] > MAX_THRESHOLD)
 	printk( "atari_mouse_setup: bad threshold value (ignored)\n" );
     else {
-	atari_mouse_x_threshold = ints[1];
-	atari_mouse_y_threshold = ints[1];
+	mouse_threshold[0] = ints[1];
+	mouse_threshold[1] = ints[1];
 	if (ints[0] > 1) {
 	    if (ints[2] < MIN_THRESHOLD || ints[2] > MAX_THRESHOLD)
 		printk("atari_mouse_setup: bad threshold value (ignored)\n" );
 	    else
-		atari_mouse_y_threshold = ints[2];
+		mouse_threshold[1] = ints[2];
 	}
     }
 	
diff -u --recursive --new-file v2.1.35/linux/drivers/char/atixlmouse.c linux/drivers/char/atixlmouse.c
--- v2.1.35/linux/drivers/char/atixlmouse.c	Fri Apr  4 08:52:18 1997
+++ linux/drivers/char/atixlmouse.c	Tue Apr 22 22:42:47 1997
@@ -19,6 +19,7 @@
 #include <linux/miscdevice.h>
 #include <linux/random.h>
 #include <linux/poll.h>
+#include <linux/init.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -201,7 +202,7 @@
 };
 
 
-int atixl_busmouse_init(void)
+__initfunc(int atixl_busmouse_init(void))
 {
 	unsigned char a,b,c;
 
diff -u --recursive --new-file v2.1.35/linux/drivers/char/busmouse.c linux/drivers/char/busmouse.c
--- v2.1.35/linux/drivers/char/busmouse.c	Fri Apr  4 08:52:19 1997
+++ linux/drivers/char/busmouse.c	Tue Apr 22 22:42:47 1997
@@ -46,6 +46,7 @@
 #include <linux/random.h>
 #include <linux/delay.h>
 #include <linux/ioport.h>
+#include <linux/init.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -246,7 +247,7 @@
 	LOGITECH_BUSMOUSE, "busmouse", &bus_mouse_fops
 };
 
-int bus_mouse_init(void)
+__initfunc(int bus_mouse_init(void))
 {
 	if (check_region(LOGIBM_BASE, LOGIBM_EXTENT)) {
 	  mouse.present = 0;
diff -u --recursive --new-file v2.1.35/linux/drivers/char/cyclades.c linux/drivers/char/cyclades.c
--- v2.1.35/linux/drivers/char/cyclades.c	Sat Nov 30 00:48:33 1996
+++ linux/drivers/char/cyclades.c	Tue Apr 22 22:42:47 1997
@@ -288,6 +288,7 @@
 #include <linux/kernel.h>
 #include <linux/bios32.h>
 #include <linux/pci.h>
+#include <linux/init.h>
 
 #define small_delay(x) for(j=0;j<x;j++)k++;
 
@@ -2696,7 +2697,7 @@
  * number, and identifies which options were configured into this
  * driver.
  */
-static void
+static inline void
 show_version(void)
 {
     printk("Cyclom driver %s\n",rcsid);
@@ -2704,8 +2705,8 @@
 
 /* initialize chips on card -- return number of valid
    chips (which is number of ports/4) */
-int
-cy_init_card(unsigned char *true_base_addr,int index)
+__initfunc(static int
+cy_init_card(unsigned char *true_base_addr,int index))
 {
   unsigned int chip_number;
   unsigned char* base_addr;
@@ -2785,8 +2786,8 @@
     If there are more cards with more ports than have been statically
     allocated above, a warning is printed and the extra ports are ignored.
  */
-int
-cy_init(void)
+__initfunc(int
+cy_init(void))
 {
   struct cyclades_port	*info;
   struct cyclades_card *cinfo;
@@ -2941,13 +2942,17 @@
 void
 cleanup_module(void)
 {
+    unsigned long flags;
     int i;
 
-
+    save_flags(flags);
+    cli();
+    remove_bh(CYCLADES_BH); 
     if (tty_unregister_driver(&cy_callout_driver))
 	    printk("Couldn't unregister Cyclom callout driver\n");
     if (tty_unregister_driver(&cy_serial_driver))
 	    printk("Couldn't unregister Cyclom serial driver\n");
+    restore_flags(flags);
 
     for (i = 0; i < NR_CARDS; i++) {
         if (cy_card[i].base_addr != 0)
@@ -2964,8 +2969,8 @@
  * sets global variables and return the number of ISA boards found.
  * ---------------------------------------------------------------------
  */
-int
-cy_detect_isa()
+__initfunc(int
+cy_detect_isa())
 {
   unsigned int		cy_isa_irq,nboard;
   unsigned char		*cy_isa_address;
@@ -3043,8 +3048,8 @@
  * sets global variables and return the number of PCI boards found.
  * ---------------------------------------------------------------------
  */
-int
-cy_detect_pci()
+__initfunc(int
+cy_detect_pci())
 {
 #ifdef CONFIG_PCI
   unsigned char		cyy_bus, cyy_dev_fn, cyy_rev_id;
diff -u --recursive --new-file v2.1.35/linux/drivers/char/digi_bios.h linux/drivers/char/digi_bios.h
--- v2.1.35/linux/drivers/char/digi_bios.h	Tue Apr  2 22:20:45 1996
+++ linux/drivers/char/digi_bios.h	Tue Apr 22 22:42:47 1997
@@ -1,6 +1,6 @@
 /* DigiBoard PCXX Bios */
 
-static unsigned char pcxx_bios[] = {
+static unsigned char pcxx_bios[] __initdata = {
   0x28,0x43,0x29,0x20,0x43,0x6f,0x70,0x79,0x72,0x69,0x67,0x68,
   0x74,0x20,0x31,0x39,0x39,0x34,0x2c,0x20,0x44,0x69,0x67,0x69,
   0x42,0x6f,0x61,0x72,0x64,0x20,0x49,0x6e,0x63,0x2e,0x00,0x00,
diff -u --recursive --new-file v2.1.35/linux/drivers/char/digi_fep.h linux/drivers/char/digi_fep.h
--- v2.1.35/linux/drivers/char/digi_fep.h	Tue Apr  2 22:20:45 1996
+++ linux/drivers/char/digi_fep.h	Tue Apr 22 22:42:47 1997
@@ -1,6 +1,6 @@
 /* DigiBoard PCXX Bios */
 
-static unsigned char pcxx_cook[] = {
+static unsigned char pcxx_cook[] __initdata = {
   0x4f,0x53,0x18,0x80,0xe9,0xbf,0x15,0x00,0x40,0x28,0x23,0x29,
   0x46,0x45,0x50,0x4f,0x53,0x20,0x37,0x2e,0x30,0x38,0x20,0x34,
   0x2f,0x32,0x30,0x2f,0x39,0x35,0x00,0x40,0x28,0x23,0x29,0x28,
diff -u --recursive --new-file v2.1.35/linux/drivers/char/dsp56k.c linux/drivers/char/dsp56k.c
--- v2.1.35/linux/drivers/char/dsp56k.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/dsp56k.c	Tue Apr 22 22:45:15 1997
@@ -0,0 +1,1150 @@
+/*
+ * The DSP56001 Device Driver, saviour of the Free World(tm)
+ *
+ * Authors: Fredrik Noring   <noring@lysator.liu.se>
+ *          lars brinkhoff   <f93labr@dd.chalmers.se>
+ *          Tomas Berndtsson <tobe@lysator.liu.se>
+ *
+ * First version May 1996
+ *
+ * History:
+ *  97-01-29   Tomas Berndtsson,
+ *               Integrated with Linux 2.1.21 kernel sources.
+ *  97-02-15   Tomas Berndtsson,
+ *               Fixed for kernel 2.1.26
+ *
+ * BUGS:
+ *  Hmm... there must be something here :)
+ *
+ * Copyright (C) 1996,1997 Fredrik Noring, lars brinkhoff & Tomas Berndtsson
+ *
+ * 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.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/malloc.h>	/* for kmalloc() and kfree() */
+#include <linux/sched.h>	/* for struct wait_queue etc */
+#include <linux/major.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/delay.h>	/* guess what */
+#include <linux/fs.h>
+#include <linux/mm.h>
+
+#include <asm/segment.h>
+#include <asm/atarihw.h>
+#include <asm/traps.h>
+#include <asm/uaccess.h>	/* For put_user and get_user */
+
+#include <asm/dsp56k.h>
+
+/* minor devices */
+#define DSP56K_DEV_56001        0    /* The only device so far */
+
+#define TIMEOUT    10   /* Host port timeout in number of tries */
+#define MAXIO    2048   /* Maximum number of words before sleep */
+#define DSP56K_MAX_BINARY_LENGTH (3*64*1024)
+
+#define DSP56K_TX_INT_ON	dsp56k_host_interface.icr |=  DSP56K_ICR_TREQ
+#define DSP56K_RX_INT_ON	dsp56k_host_interface.icr |=  DSP56K_ICR_RREQ
+#define DSP56K_TX_INT_OFF	dsp56k_host_interface.icr &= ~DSP56K_ICR_TREQ
+#define DSP56K_RX_INT_OFF	dsp56k_host_interface.icr &= ~DSP56K_ICR_RREQ
+
+#define DSP56K_TRANSMIT		(dsp56k_host_interface.isr & DSP56K_ISR_TXDE)
+#define DSP56K_RECEIVE		(dsp56k_host_interface.isr & DSP56K_ISR_RXDF)
+
+#define max(a,b) ((a) > (b) ? (a) : (b))
+#define min(a,b) ((a) < (b) ? (a) : (b))
+
+#define wait_some(n) \
+{ \
+	current->state = TASK_INTERRUPTIBLE; \
+	current->timeout = jiffies + n; \
+	schedule(); \
+}
+
+#define handshake(count, maxio, timeout, ENABLE, f) \
+{ \
+	long i, t, m; \
+	while (count > 0) { \
+		m = min(count, maxio); \
+		for (i = 0; i < m; i++) { \
+			for (t = 0; t < timeout && !ENABLE; t++) \
+				wait_some(2); \
+			if(!ENABLE) \
+				return -EIO; \
+			f; \
+		} \
+		count -= m; \
+		if (m == maxio) wait_some(2); \
+	} \
+}
+
+#define tx_wait(n) \
+{ \
+	int t; \
+	for(t = 0; t < n && !DSP56K_TRANSMIT; t++) \
+		wait_some(1); \
+	if(!DSP56K_TRANSMIT) { \
+		return -EIO; \
+	} \
+}
+
+#define rx_wait(n) \
+{ \
+	int t; \
+	for(t = 0; t < n && !DSP56K_RECEIVE; t++) \
+		wait_some(1); \
+	if(!DSP56K_RECEIVE) { \
+		return -EIO; \
+	} \
+}
+
+/* DSP56001 bootstrap code */
+static char bootstrap[] = {
+	0x0c, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x60, 0xf4, 0x00, 0x00, 0x00, 0x4f, 0x61, 0xf4,
+	0x00, 0x00, 0x7e, 0xa9, 0x06, 0x2e, 0x80, 0x00, 0x00, 0x47,
+	0x07, 0xd8, 0x84, 0x07, 0x59, 0x84, 0x08, 0xf4, 0xa8, 0x00,
+	0x00, 0x04, 0x08, 0xf4, 0xbf, 0x00, 0x0c, 0x00, 0x00, 0xfe,
+	0xb8, 0x0a, 0xf0, 0x80, 0x00, 0x7e, 0xa9, 0x08, 0xf4, 0xa0,
+	0x00, 0x00, 0x01, 0x08, 0xf4, 0xbe, 0x00, 0x00, 0x00, 0x0a,
+	0xa9, 0x80, 0x00, 0x7e, 0xad, 0x08, 0x4e, 0x2b, 0x44, 0xf4,
+	0x00, 0x00, 0x00, 0x03, 0x44, 0xf4, 0x45, 0x00, 0x00, 0x01,
+	0x0e, 0xa0, 0x00, 0x0a, 0xa9, 0x80, 0x00, 0x7e, 0xb5, 0x08,
+	0x50, 0x2b, 0x0a, 0xa9, 0x80, 0x00, 0x7e, 0xb8, 0x08, 0x46,
+	0x2b, 0x44, 0xf4, 0x45, 0x00, 0x00, 0x02, 0x0a, 0xf0, 0xaa,
+	0x00, 0x7e, 0xc9, 0x20, 0x00, 0x45, 0x0a, 0xf0, 0xaa, 0x00,
+	0x7e, 0xd0, 0x06, 0xc6, 0x00, 0x00, 0x7e, 0xc6, 0x0a, 0xa9,
+	0x80, 0x00, 0x7e, 0xc4, 0x08, 0x58, 0x6b, 0x0a, 0xf0, 0x80,
+	0x00, 0x7e, 0xad, 0x06, 0xc6, 0x00, 0x00, 0x7e, 0xcd, 0x0a,
+	0xa9, 0x80, 0x00, 0x7e, 0xcb, 0x08, 0x58, 0xab, 0x0a, 0xf0,
+	0x80, 0x00, 0x7e, 0xad, 0x06, 0xc6, 0x00, 0x00, 0x7e, 0xd4,
+	0x0a, 0xa9, 0x80, 0x00, 0x7e, 0xd2, 0x08, 0x58, 0xeb, 0x0a,
+	0xf0, 0x80, 0x00, 0x7e, 0xad};
+static int sizeof_bootstrap = 375;
+
+
+static struct dsp56k_device {
+	int in_use;
+	long maxio, timeout;
+	int tx_wsize, rx_wsize;
+} dsp56k;
+
+static int dsp56k_reset(void)
+{
+	u_char status;
+	
+	/* Power down the DSP */
+	sound_ym.rd_data_reg_sel = 14;
+	status = sound_ym.rd_data_reg_sel & 0xef;
+	sound_ym.wd_data = status;
+	sound_ym.wd_data = status | 0x10;
+  
+	udelay(10);
+  
+	/* Power up the DSP */
+	sound_ym.rd_data_reg_sel = 14;
+	sound_ym.wd_data = sound_ym.rd_data_reg_sel & 0xef;
+
+	return 0;
+}
+
+static int dsp56k_upload(u_char *bin, int len)
+{
+	int i;
+	u_char *p;
+	
+	dsp56k_reset();
+  
+	p = bootstrap;
+	for (i = 0; i < sizeof_bootstrap/3; i++) {
+		/* tx_wait(10); */
+		dsp56k_host_interface.data.b[1] = *p++;
+		dsp56k_host_interface.data.b[2] = *p++;
+		dsp56k_host_interface.data.b[3] = *p++;
+	}
+	for (; i < 512; i++) {
+		/* tx_wait(10); */
+		dsp56k_host_interface.data.b[1] = 0;
+		dsp56k_host_interface.data.b[2] = 0;
+		dsp56k_host_interface.data.b[3] = 0;
+	}
+  
+	for (i = 0; i < len; i++) {
+		tx_wait(10);
+		get_user(dsp56k_host_interface.data.b[1], bin++);
+		get_user(dsp56k_host_interface.data.b[2], bin++);
+		get_user(dsp56k_host_interface.data.b[3], bin++);
+	}
+
+	tx_wait(10);
+	dsp56k_host_interface.data.l = 3;    /* Magic execute */
+
+	return 0;
+}
+
+static long dsp56k_read(struct inode *inode, struct file *file,
+			char *buf, unsigned long count)
+{
+	int dev = MINOR(inode->i_rdev) & 0x0f;
+
+	switch(dev)
+	{
+	case DSP56K_DEV_56001:
+	{
+
+		long n;
+
+		/* Don't do anything if nothing is to be done */
+		if (!count) return 0;
+
+		n = 0;
+		switch (dsp56k.rx_wsize) {
+		case 1:  /* 8 bit */
+		{
+			handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_RECEIVE,
+				  put_user(dsp56k_host_interface.data.b[3], buf+n++));
+			return n;
+		}
+		case 2:  /* 16 bit */
+		{
+			short *data;
+
+			count /= 2;
+			data = (short*) buf;
+			handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_RECEIVE,
+				  put_user(dsp56k_host_interface.data.w[1], data+n++));
+			return 2*n;
+		}
+		case 3:  /* 24 bit */
+		{
+			count /= 3;
+			handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_RECEIVE,
+				  put_user(dsp56k_host_interface.data.b[1], buf+n++);
+				  put_user(dsp56k_host_interface.data.b[2], buf+n++);
+				  put_user(dsp56k_host_interface.data.b[3], buf+n++));
+			return 3*n;
+		}
+		case 4:  /* 32 bit */
+		{
+			long *data;
+
+			count /= 4;
+			data = (long*) buf;
+			handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_RECEIVE,
+				  put_user(dsp56k_host_interface.data.l, data+n++));
+			return 4*n;
+		}
+		}
+		return -EFAULT;
+	}
+
+	default:
+		printk("DSP56k driver: Unknown minor device: %d\n", dev);
+		return -ENXIO;
+	}
+}
+
+static long dsp56k_write(struct inode *inode, struct file *file,
+			 const char *buf, unsigned long count)
+{
+	int dev = MINOR(inode->i_rdev) & 0x0f;
+
+	switch(dev)
+	{
+	case DSP56K_DEV_56001:
+	{
+		long n;
+
+		/* Don't do anything if nothing is to be done */
+		if (!count) return 0;
+
+		n = 0;
+		switch (dsp56k.tx_wsize) {
+		case 1:  /* 8 bit */
+		{
+			handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_TRANSMIT,
+				  get_user(dsp56k_host_interface.data.b[3], buf+n++));
+			return n;
+		}
+		case 2:  /* 16 bit */
+		{
+			short *data;
+
+			count /= 2;
+			data = (short*) buf;
+			handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_TRANSMIT,
+				  get_user(dsp56k_host_interface.data.w[1], data+n++));
+			return 2*n;
+		}
+		case 3:  /* 24 bit */
+		{
+			count /= 3;
+			handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_TRANSMIT,
+				  get_user(dsp56k_host_interface.data.b[1], buf+n++);
+				  get_user(dsp56k_host_interface.data.b[2], buf+n++);
+				  get_user(dsp56k_host_interface.data.b[3], buf+n++));
+			return 3*n;
+		}
+		case 4:  /* 32 bit */
+		{
+			long *data;
+
+			count /= 4;
+			data = (long*) buf;
+			handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_TRANSMIT,
+				  get_user(dsp56k_host_interface.data.l, data+n++));
+			return 4*n;
+		}
+		}
+
+		return -EFAULT;
+	}
+	default:
+		printk("DSP56k driver: Unknown minor device: %d\n", dev);
+		return -ENXIO;
+	}
+}
+
+static int dsp56k_ioctl(struct inode *inode, struct file *file,
+			unsigned int cmd, unsigned long arg)
+{
+	int dev = MINOR(inode->i_rdev) & 0x0f;
+
+	switch(dev)
+	{
+	case DSP56K_DEV_56001:
+
+		switch(cmd) {
+		case DSP56K_UPLOAD:
+		{
+			char *bin;
+			int r, len;
+			struct dsp56k_upload *binary = (struct dsp56k_upload *) arg;
+    
+			if(get_user(len, &binary->len) < 0)
+				return -EFAULT;
+			if(get_user(bin, &binary->bin) < 0)
+				return -EFAULT;
+		
+			if (len == 0) {
+				return -EINVAL;      /* nothing to upload?!? */
+			}
+			if (len > DSP56K_MAX_BINARY_LENGTH) {
+				return -EINVAL;
+			}
+    
+			r = dsp56k_upload(bin, len);
+			if (r < 0) {
+				return r;
+			}
+    
+			break;
+		}
+		case DSP56K_SET_TX_WSIZE:
+			if (arg > 4 || arg < 1)
+				return -EINVAL;
+			dsp56k.tx_wsize = (int) arg;
+			break;
+		case DSP56K_SET_RX_WSIZE:
+			if (arg > 4 || arg < 1)
+				return -EINVAL;
+			dsp56k.rx_wsize = (int) arg;
+			break;
+		case DSP56K_HOST_FLAGS:
+		{
+			int dir, out, status;
+			struct dsp56k_host_flags *hf = (struct dsp56k_host_flags*) arg;
+    
+			if(get_user(dir, &hf->dir) < 0)
+				return -EFAULT;
+			if(get_user(out, &hf->out) < 0)
+				return -EFAULT;
+
+			if ((dir & 0x1) && (out & 0x1))
+				dsp56k_host_interface.icr |= DSP56K_ICR_HF0;
+			else if (dir & 0x1)
+				dsp56k_host_interface.icr &= ~DSP56K_ICR_HF0;
+			if ((dir & 0x2) && (out & 0x2))
+				dsp56k_host_interface.icr |= DSP56K_ICR_HF1;
+			else if (dir & 0x2)
+				dsp56k_host_interface.icr &= ~DSP56K_ICR_HF1;
+
+			status = 0;
+			if (dsp56k_host_interface.icr & DSP56K_ICR_HF0) status |= 0x1;
+			if (dsp56k_host_interface.icr & DSP56K_ICR_HF1) status |= 0x2;
+			if (dsp56k_host_interface.isr & DSP56K_ISR_HF2) status |= 0x4;
+			if (dsp56k_host_interface.isr & DSP56K_ISR_HF3) status |= 0x8;
+
+			if(put_user(status, &hf->status) < 0)
+				return -EFAULT;
+			break;
+		}
+		case DSP56K_HOST_CMD:
+			if (arg > 31 || arg < 0)
+				return -EINVAL;
+			dsp56k_host_interface.cvr = (u_char)((arg & DSP56K_CVR_HV_MASK) |
+							     DSP56K_CVR_HC);
+			break;
+		default:
+			return -EINVAL;
+		}
+		return 0;
+
+	default:
+		printk("DSP56k driver: Unknown minor device: %d\n", dev);
+		return -ENXIO;
+	}
+}
+
+/* As of 2.1.26 this should be dsp56k_poll,
+ * but how do I then check device minor number?
+ * Do I need this function at all???
+ */
+#ifdef 0
+static int dsp56k_select(struct inode *inode, struct file *file, int sel_type,
+			 select_table *wait)
+{
+	int dev = MINOR(inode->i_rdev) & 0x0f;
+
+	switch(dev)
+	{
+	case DSP56K_DEV_56001:
+
+		switch(sel_type) {
+		case SEL_IN:		/* read */
+			return 1;
+		case SEL_OUT:		/* write */
+			return 1;
+		default:
+			return 1;
+		}
+
+	default:
+		printk("DSP56k driver: Unknown minor device: %d\n", dev);
+		return -ENXIO;
+	}
+}
+#endif
+
+static int dsp56k_open(struct inode *inode, struct file *file)
+{
+	int dev = MINOR(inode->i_rdev) & 0x0f;
+
+	switch(dev)
+	{
+	case DSP56K_DEV_56001:
+
+		if (dsp56k.in_use)
+			return -EBUSY;
+
+		dsp56k.in_use = 1;
+		dsp56k.timeout = TIMEOUT;
+		dsp56k.maxio = MAXIO;
+		dsp56k.rx_wsize = dsp56k.tx_wsize = 4; 
+
+		DSP56K_TX_INT_OFF;
+		DSP56K_RX_INT_OFF;
+
+		/* Zero host flags */
+		dsp56k_host_interface.icr &= ~DSP56K_ICR_HF0;
+		dsp56k_host_interface.icr &= ~DSP56K_ICR_HF1;
+
+		break;
+
+	default:
+		printk("DSP56k driver: Unknown minor device: %d\n", dev);
+		return -ENXIO;
+	}
+
+#ifdef MODULE
+	MOD_INC_USE_COUNT;
+#endif /* MODULE */
+
+	return 0;
+}
+
+static void dsp56k_release(struct inode *inode, struct file *file)
+{
+	int dev = MINOR(inode->i_rdev) & 0x0f;
+
+	switch(dev)
+	{
+	case DSP56K_DEV_56001:
+
+		dsp56k.in_use = 0;
+
+		break;
+	default:
+		printk("DSP56k driver: Unknown minor device: %d\n", dev);
+		return;
+	}
+
+#ifdef MODULE
+	MOD_DEC_USE_COUNT;
+#endif /* MODULE */
+}
+
+static struct file_operations dsp56k_fops = {
+	NULL,    /* no special dsp56k_lseek */
+	dsp56k_read,
+	dsp56k_write,
+	NULL,    /* no special dsp56k_readdir */
+	NULL,    /* dsp56k_poll? */
+	dsp56k_ioctl,
+	NULL,    /* no special dsp56k_mmap */
+	dsp56k_open,
+	dsp56k_release,
+	NULL,    /* no special dsp56k_fsync */
+	NULL,    /* no special dsp56k_fasync */
+	NULL,    /* no special dsp56k_check_media_change */
+	NULL     /* no special dsp56k_revalidate */
+};
+
+
+/****** Init and module functions ******/
+
+static int init_error = 0;
+
+void dsp56k_init(void)
+{
+	if(!ATARIHW_PRESENT(DSP56K)) {
+		init_error = 1;
+		printk("DSP56k driver: Hardware not present\n");
+		return;
+	}
+
+#ifndef MODULE
+	if(register_chrdev(DSP56K_MAJOR, "dsp56k", &dsp56k_fops)) {
+		printk("DSP56k driver: Unable to register driver\n");
+		return;
+	}
+#endif /* !MODULE */
+
+	dsp56k.in_use = 0;
+
+	printk("DSP56k driver installed\n");
+}
+
+#ifdef MODULE
+int init_module(void)
+{
+	int r;
+
+	init_error = 0;
+	dsp56k_init();
+	if(init_error)
+		return -EPERM;
+
+	r = register_chrdev(DSP56K_MAJOR, "dsp56k", &dsp56k_fops);
+	if(r) {
+		printk("DSP56k driver: Unable to register driver\n");
+		return r;
+	}
+	
+	return 0;
+}
+
+void cleanup_module(void)
+{
+	unregister_chrdev(DSP56K_MAJOR, "dsp56k");
+}
+#endif /* MODULE */
+/*
+ * The DSP56001 Device Driver, saviour of the Free World(tm)
+ *
+ * Authors: Fredrik Noring   <noring@lysator.liu.se>
+ *          lars brinkhoff   <f93labr@dd.chalmers.se>
+ *          Tomas Berndtsson <tobe@lysator.liu.se>
+ *
+ * First version May 1996
+ *
+ * History:
+ *  97-01-29   Tomas Berndtsson,
+ *               Integrated with Linux 2.1.21 kernel sources.
+ *  97-02-15   Tomas Berndtsson,
+ *               Fixed for kernel 2.1.26
+ *
+ * BUGS:
+ *  Hmm... there must be something here :)
+ *
+ * Copyright (C) 1996,1997 Fredrik Noring, lars brinkhoff & Tomas Berndtsson
+ *
+ * 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.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/malloc.h>	/* for kmalloc() and kfree() */
+#include <linux/sched.h>	/* for struct wait_queue etc */
+#include <linux/major.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/delay.h>	/* guess what */
+#include <linux/fs.h>
+#include <linux/mm.h>
+
+#include <asm/segment.h>
+#include <asm/atarihw.h>
+#include <asm/traps.h>
+#include <asm/uaccess.h>	/* For put_user and get_user */
+
+#include <asm/dsp56k.h>
+
+/* minor devices */
+#define DSP56K_DEV_56001        0    /* The only device so far */
+
+#define TIMEOUT    10   /* Host port timeout in number of tries */
+#define MAXIO    2048   /* Maximum number of words before sleep */
+#define DSP56K_MAX_BINARY_LENGTH (3*64*1024)
+
+#define DSP56K_TX_INT_ON	dsp56k_host_interface.icr |=  DSP56K_ICR_TREQ
+#define DSP56K_RX_INT_ON	dsp56k_host_interface.icr |=  DSP56K_ICR_RREQ
+#define DSP56K_TX_INT_OFF	dsp56k_host_interface.icr &= ~DSP56K_ICR_TREQ
+#define DSP56K_RX_INT_OFF	dsp56k_host_interface.icr &= ~DSP56K_ICR_RREQ
+
+#define DSP56K_TRANSMIT		(dsp56k_host_interface.isr & DSP56K_ISR_TXDE)
+#define DSP56K_RECEIVE		(dsp56k_host_interface.isr & DSP56K_ISR_RXDF)
+
+#define max(a,b) ((a) > (b) ? (a) : (b))
+#define min(a,b) ((a) < (b) ? (a) : (b))
+
+#define wait_some(n) \
+{ \
+	current->state = TASK_INTERRUPTIBLE; \
+	current->timeout = jiffies + n; \
+	schedule(); \
+}
+
+#define handshake(count, maxio, timeout, ENABLE, f) \
+{ \
+	long i, t, m; \
+	while (count > 0) { \
+		m = min(count, maxio); \
+		for (i = 0; i < m; i++) { \
+			for (t = 0; t < timeout && !ENABLE; t++) \
+				wait_some(2); \
+			if(!ENABLE) \
+				return -EIO; \
+			f; \
+		} \
+		count -= m; \
+		if (m == maxio) wait_some(2); \
+	} \
+}
+
+#define tx_wait(n) \
+{ \
+	int t; \
+	for(t = 0; t < n && !DSP56K_TRANSMIT; t++) \
+		wait_some(1); \
+	if(!DSP56K_TRANSMIT) { \
+		return -EIO; \
+	} \
+}
+
+#define rx_wait(n) \
+{ \
+	int t; \
+	for(t = 0; t < n && !DSP56K_RECEIVE; t++) \
+		wait_some(1); \
+	if(!DSP56K_RECEIVE) { \
+		return -EIO; \
+	} \
+}
+
+/* DSP56001 bootstrap code */
+static char bootstrap[] = {
+	0x0c, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x60, 0xf4, 0x00, 0x00, 0x00, 0x4f, 0x61, 0xf4,
+	0x00, 0x00, 0x7e, 0xa9, 0x06, 0x2e, 0x80, 0x00, 0x00, 0x47,
+	0x07, 0xd8, 0x84, 0x07, 0x59, 0x84, 0x08, 0xf4, 0xa8, 0x00,
+	0x00, 0x04, 0x08, 0xf4, 0xbf, 0x00, 0x0c, 0x00, 0x00, 0xfe,
+	0xb8, 0x0a, 0xf0, 0x80, 0x00, 0x7e, 0xa9, 0x08, 0xf4, 0xa0,
+	0x00, 0x00, 0x01, 0x08, 0xf4, 0xbe, 0x00, 0x00, 0x00, 0x0a,
+	0xa9, 0x80, 0x00, 0x7e, 0xad, 0x08, 0x4e, 0x2b, 0x44, 0xf4,
+	0x00, 0x00, 0x00, 0x03, 0x44, 0xf4, 0x45, 0x00, 0x00, 0x01,
+	0x0e, 0xa0, 0x00, 0x0a, 0xa9, 0x80, 0x00, 0x7e, 0xb5, 0x08,
+	0x50, 0x2b, 0x0a, 0xa9, 0x80, 0x00, 0x7e, 0xb8, 0x08, 0x46,
+	0x2b, 0x44, 0xf4, 0x45, 0x00, 0x00, 0x02, 0x0a, 0xf0, 0xaa,
+	0x00, 0x7e, 0xc9, 0x20, 0x00, 0x45, 0x0a, 0xf0, 0xaa, 0x00,
+	0x7e, 0xd0, 0x06, 0xc6, 0x00, 0x00, 0x7e, 0xc6, 0x0a, 0xa9,
+	0x80, 0x00, 0x7e, 0xc4, 0x08, 0x58, 0x6b, 0x0a, 0xf0, 0x80,
+	0x00, 0x7e, 0xad, 0x06, 0xc6, 0x00, 0x00, 0x7e, 0xcd, 0x0a,
+	0xa9, 0x80, 0x00, 0x7e, 0xcb, 0x08, 0x58, 0xab, 0x0a, 0xf0,
+	0x80, 0x00, 0x7e, 0xad, 0x06, 0xc6, 0x00, 0x00, 0x7e, 0xd4,
+	0x0a, 0xa9, 0x80, 0x00, 0x7e, 0xd2, 0x08, 0x58, 0xeb, 0x0a,
+	0xf0, 0x80, 0x00, 0x7e, 0xad};
+static int sizeof_bootstrap = 375;
+
+
+static struct dsp56k_device {
+	int in_use;
+	long maxio, timeout;
+	int tx_wsize, rx_wsize;
+} dsp56k;
+
+static int dsp56k_reset(void)
+{
+	u_char status;
+	
+	/* Power down the DSP */
+	sound_ym.rd_data_reg_sel = 14;
+	status = sound_ym.rd_data_reg_sel & 0xef;
+	sound_ym.wd_data = status;
+	sound_ym.wd_data = status | 0x10;
+  
+	udelay(10);
+  
+	/* Power up the DSP */
+	sound_ym.rd_data_reg_sel = 14;
+	sound_ym.wd_data = sound_ym.rd_data_reg_sel & 0xef;
+
+	return 0;
+}
+
+static int dsp56k_upload(u_char *bin, int len)
+{
+	int i;
+	u_char *p;
+	
+	dsp56k_reset();
+  
+	p = bootstrap;
+	for (i = 0; i < sizeof_bootstrap/3; i++) {
+		/* tx_wait(10); */
+		dsp56k_host_interface.data.b[1] = *p++;
+		dsp56k_host_interface.data.b[2] = *p++;
+		dsp56k_host_interface.data.b[3] = *p++;
+	}
+	for (; i < 512; i++) {
+		/* tx_wait(10); */
+		dsp56k_host_interface.data.b[1] = 0;
+		dsp56k_host_interface.data.b[2] = 0;
+		dsp56k_host_interface.data.b[3] = 0;
+	}
+  
+	for (i = 0; i < len; i++) {
+		tx_wait(10);
+		get_user(dsp56k_host_interface.data.b[1], bin++);
+		get_user(dsp56k_host_interface.data.b[2], bin++);
+		get_user(dsp56k_host_interface.data.b[3], bin++);
+	}
+
+	tx_wait(10);
+	dsp56k_host_interface.data.l = 3;    /* Magic execute */
+
+	return 0;
+}
+
+static long dsp56k_read(struct inode *inode, struct file *file,
+			char *buf, unsigned long count)
+{
+	int dev = MINOR(inode->i_rdev) & 0x0f;
+
+	switch(dev)
+	{
+	case DSP56K_DEV_56001:
+	{
+
+		long n;
+
+		/* Don't do anything if nothing is to be done */
+		if (!count) return 0;
+
+		n = 0;
+		switch (dsp56k.rx_wsize) {
+		case 1:  /* 8 bit */
+		{
+			handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_RECEIVE,
+				  put_user(dsp56k_host_interface.data.b[3], buf+n++));
+			return n;
+		}
+		case 2:  /* 16 bit */
+		{
+			short *data;
+
+			count /= 2;
+			data = (short*) buf;
+			handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_RECEIVE,
+				  put_user(dsp56k_host_interface.data.w[1], data+n++));
+			return 2*n;
+		}
+		case 3:  /* 24 bit */
+		{
+			count /= 3;
+			handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_RECEIVE,
+				  put_user(dsp56k_host_interface.data.b[1], buf+n++);
+				  put_user(dsp56k_host_interface.data.b[2], buf+n++);
+				  put_user(dsp56k_host_interface.data.b[3], buf+n++));
+			return 3*n;
+		}
+		case 4:  /* 32 bit */
+		{
+			long *data;
+
+			count /= 4;
+			data = (long*) buf;
+			handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_RECEIVE,
+				  put_user(dsp56k_host_interface.data.l, data+n++));
+			return 4*n;
+		}
+		}
+		return -EFAULT;
+	}
+
+	default:
+		printk("DSP56k driver: Unknown minor device: %d\n", dev);
+		return -ENXIO;
+	}
+}
+
+static long dsp56k_write(struct inode *inode, struct file *file,
+			 const char *buf, unsigned long count)
+{
+	int dev = MINOR(inode->i_rdev) & 0x0f;
+
+	switch(dev)
+	{
+	case DSP56K_DEV_56001:
+	{
+		long n;
+
+		/* Don't do anything if nothing is to be done */
+		if (!count) return 0;
+
+		n = 0;
+		switch (dsp56k.tx_wsize) {
+		case 1:  /* 8 bit */
+		{
+			handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_TRANSMIT,
+				  get_user(dsp56k_host_interface.data.b[3], buf+n++));
+			return n;
+		}
+		case 2:  /* 16 bit */
+		{
+			short *data;
+
+			count /= 2;
+			data = (short*) buf;
+			handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_TRANSMIT,
+				  get_user(dsp56k_host_interface.data.w[1], data+n++));
+			return 2*n;
+		}
+		case 3:  /* 24 bit */
+		{
+			count /= 3;
+			handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_TRANSMIT,
+				  get_user(dsp56k_host_interface.data.b[1], buf+n++);
+				  get_user(dsp56k_host_interface.data.b[2], buf+n++);
+				  get_user(dsp56k_host_interface.data.b[3], buf+n++));
+			return 3*n;
+		}
+		case 4:  /* 32 bit */
+		{
+			long *data;
+
+			count /= 4;
+			data = (long*) buf;
+			handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_TRANSMIT,
+				  get_user(dsp56k_host_interface.data.l, data+n++));
+			return 4*n;
+		}
+		}
+
+		return -EFAULT;
+	}
+	default:
+		printk("DSP56k driver: Unknown minor device: %d\n", dev);
+		return -ENXIO;
+	}
+}
+
+static int dsp56k_ioctl(struct inode *inode, struct file *file,
+			unsigned int cmd, unsigned long arg)
+{
+	int dev = MINOR(inode->i_rdev) & 0x0f;
+
+	switch(dev)
+	{
+	case DSP56K_DEV_56001:
+
+		switch(cmd) {
+		case DSP56K_UPLOAD:
+		{
+			char *bin;
+			int r, len;
+			struct dsp56k_upload *binary = (struct dsp56k_upload *) arg;
+    
+			if(get_user(len, &binary->len) < 0)
+				return -EFAULT;
+			if(get_user(bin, &binary->bin) < 0)
+				return -EFAULT;
+		
+			if (len == 0) {
+				return -EINVAL;      /* nothing to upload?!? */
+			}
+			if (len > DSP56K_MAX_BINARY_LENGTH) {
+				return -EINVAL;
+			}
+    
+			r = dsp56k_upload(bin, len);
+			if (r < 0) {
+				return r;
+			}
+    
+			break;
+		}
+		case DSP56K_SET_TX_WSIZE:
+			if (arg > 4 || arg < 1)
+				return -EINVAL;
+			dsp56k.tx_wsize = (int) arg;
+			break;
+		case DSP56K_SET_RX_WSIZE:
+			if (arg > 4 || arg < 1)
+				return -EINVAL;
+			dsp56k.rx_wsize = (int) arg;
+			break;
+		case DSP56K_HOST_FLAGS:
+		{
+			int dir, out, status;
+			struct dsp56k_host_flags *hf = (struct dsp56k_host_flags*) arg;
+    
+			if(get_user(dir, &hf->dir) < 0)
+				return -EFAULT;
+			if(get_user(out, &hf->out) < 0)
+				return -EFAULT;
+
+			if ((dir & 0x1) && (out & 0x1))
+				dsp56k_host_interface.icr |= DSP56K_ICR_HF0;
+			else if (dir & 0x1)
+				dsp56k_host_interface.icr &= ~DSP56K_ICR_HF0;
+			if ((dir & 0x2) && (out & 0x2))
+				dsp56k_host_interface.icr |= DSP56K_ICR_HF1;
+			else if (dir & 0x2)
+				dsp56k_host_interface.icr &= ~DSP56K_ICR_HF1;
+
+			status = 0;
+			if (dsp56k_host_interface.icr & DSP56K_ICR_HF0) status |= 0x1;
+			if (dsp56k_host_interface.icr & DSP56K_ICR_HF1) status |= 0x2;
+			if (dsp56k_host_interface.isr & DSP56K_ISR_HF2) status |= 0x4;
+			if (dsp56k_host_interface.isr & DSP56K_ISR_HF3) status |= 0x8;
+
+			if(put_user(status, &hf->status) < 0)
+				return -EFAULT;
+			break;
+		}
+		case DSP56K_HOST_CMD:
+			if (arg > 31 || arg < 0)
+				return -EINVAL;
+			dsp56k_host_interface.cvr = (u_char)((arg & DSP56K_CVR_HV_MASK) |
+							     DSP56K_CVR_HC);
+			break;
+		default:
+			return -EINVAL;
+		}
+		return 0;
+
+	default:
+		printk("DSP56k driver: Unknown minor device: %d\n", dev);
+		return -ENXIO;
+	}
+}
+
+/* As of 2.1.26 this should be dsp56k_poll,
+ * but how do I then check device minor number?
+ * Do I need this function at all???
+ */
+#ifdef 0
+static int dsp56k_select(struct inode *inode, struct file *file, int sel_type,
+			 select_table *wait)
+{
+	int dev = MINOR(inode->i_rdev) & 0x0f;
+
+	switch(dev)
+	{
+	case DSP56K_DEV_56001:
+
+		switch(sel_type) {
+		case SEL_IN:		/* read */
+			return 1;
+		case SEL_OUT:		/* write */
+			return 1;
+		default:
+			return 1;
+		}
+
+	default:
+		printk("DSP56k driver: Unknown minor device: %d\n", dev);
+		return -ENXIO;
+	}
+}
+#endif
+
+static int dsp56k_open(struct inode *inode, struct file *file)
+{
+	int dev = MINOR(inode->i_rdev) & 0x0f;
+
+	switch(dev)
+	{
+	case DSP56K_DEV_56001:
+
+		if (dsp56k.in_use)
+			return -EBUSY;
+
+		dsp56k.in_use = 1;
+		dsp56k.timeout = TIMEOUT;
+		dsp56k.maxio = MAXIO;
+		dsp56k.rx_wsize = dsp56k.tx_wsize = 4; 
+
+		DSP56K_TX_INT_OFF;
+		DSP56K_RX_INT_OFF;
+
+		/* Zero host flags */
+		dsp56k_host_interface.icr &= ~DSP56K_ICR_HF0;
+		dsp56k_host_interface.icr &= ~DSP56K_ICR_HF1;
+
+		break;
+
+	default:
+		printk("DSP56k driver: Unknown minor device: %d\n", dev);
+		return -ENXIO;
+	}
+
+#ifdef MODULE
+	MOD_INC_USE_COUNT;
+#endif /* MODULE */
+
+	return 0;
+}
+
+static void dsp56k_release(struct inode *inode, struct file *file)
+{
+	int dev = MINOR(inode->i_rdev) & 0x0f;
+
+	switch(dev)
+	{
+	case DSP56K_DEV_56001:
+
+		dsp56k.in_use = 0;
+
+		break;
+	default:
+		printk("DSP56k driver: Unknown minor device: %d\n", dev);
+		return;
+	}
+
+#ifdef MODULE
+	MOD_DEC_USE_COUNT;
+#endif /* MODULE */
+}
+
+static struct file_operations dsp56k_fops = {
+	NULL,    /* no special dsp56k_lseek */
+	dsp56k_read,
+	dsp56k_write,
+	NULL,    /* no special dsp56k_readdir */
+	NULL,    /* dsp56k_poll? */
+	dsp56k_ioctl,
+	NULL,    /* no special dsp56k_mmap */
+	dsp56k_open,
+	dsp56k_release,
+	NULL,    /* no special dsp56k_fsync */
+	NULL,    /* no special dsp56k_fasync */
+	NULL,    /* no special dsp56k_check_media_change */
+	NULL     /* no special dsp56k_revalidate */
+};
+
+
+/****** Init and module functions ******/
+
+static int init_error = 0;
+
+void dsp56k_init(void)
+{
+	if(!ATARIHW_PRESENT(DSP56K)) {
+		init_error = 1;
+		printk("DSP56k driver: Hardware not present\n");
+		return;
+	}
+
+#ifndef MODULE
+	if(register_chrdev(DSP56K_MAJOR, "dsp56k", &dsp56k_fops)) {
+		printk("DSP56k driver: Unable to register driver\n");
+		return;
+	}
+#endif /* !MODULE */
+
+	dsp56k.in_use = 0;
+
+	printk("DSP56k driver installed\n");
+}
+
+#ifdef MODULE
+int init_module(void)
+{
+	int r;
+
+	init_error = 0;
+	dsp56k_init();
+	if(init_error)
+		return -EPERM;
+
+	r = register_chrdev(DSP56K_MAJOR, "dsp56k", &dsp56k_fops);
+	if(r) {
+		printk("DSP56k driver: Unable to register driver\n");
+		return r;
+	}
+	
+	return 0;
+}
+
+void cleanup_module(void)
+{
+	unregister_chrdev(DSP56K_MAJOR, "dsp56k");
+}
+#endif /* MODULE */
diff -u --recursive --new-file v2.1.35/linux/drivers/char/esp.c linux/drivers/char/esp.c
--- v2.1.35/linux/drivers/char/esp.c	Fri Apr  4 08:52:19 1997
+++ linux/drivers/char/esp.c	Tue Apr 22 22:42:47 1997
@@ -55,6 +55,7 @@
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
 #include <linux/mm.h>
+#include <linux/init.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
@@ -2312,7 +2313,8 @@
  * number, and identifies which options were configured into this
  * driver.
  */
-static void show_serial_version(void)
+ 
+static _INLINE_ void show_serial_version(void)
 {
  	printk(KERN_INFO "%s version %s (DMA %u, trigger level %u)\n",
 		serial_name, serial_version, dma, trigger);
@@ -2380,7 +2382,7 @@
 /*
  * The serial driver boot-time initialization code!
  */
-int espserial_init(void)
+__initfunc(int espserial_init(void))
 {
 	int i, offset;
 	int region_start;
@@ -2565,6 +2567,7 @@
 	/* printk("Unloading %s: version %s\n", serial_name, serial_version); */
 	save_flags(flags);
 	cli();
+	remove_bh(ESP_BH);
 	if ((e1 = tty_unregister_driver(&esp_driver)))
 		printk("SERIAL: failed to unregister serial driver (%d)\n",
 		       e1);
diff -u --recursive --new-file v2.1.35/linux/drivers/char/istallion.c linux/drivers/char/istallion.c
--- v2.1.35/linux/drivers/char/istallion.c	Mon Mar 17 14:54:25 1997
+++ linux/drivers/char/istallion.c	Tue Apr 22 22:42:47 1997
@@ -45,6 +45,7 @@
 #include <linux/malloc.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
+#include <linux/init.h>
 #include <asm/system.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -540,13 +541,13 @@
 static void	stli_flushbuffer(struct tty_struct *tty);
 static void	stli_hangup(struct tty_struct *tty);
 
-static int	stli_initbrds(void);
+static inline int stli_initbrds(void);
 static int	stli_brdinit(stlibrd_t *brdp);
-static int	stli_initecp(stlibrd_t *brdp);
-static int	stli_initonb(stlibrd_t *brdp);
+static inline int stli_initecp(stlibrd_t *brdp);
+static inline int stli_initonb(stlibrd_t *brdp);
 static int	stli_eisamemprobe(stlibrd_t *brdp);
-static int	stli_findeisabrds(void);
-static int	stli_initports(stlibrd_t *brdp);
+static inline int stli_findeisabrds(void);
+static inline int stli_initports(stlibrd_t *brdp);
 static int	stli_startbrd(stlibrd_t *brdp);
 static long	stli_memread(struct inode *ip, struct file *fp, char *buf, unsigned long count);
 static long	stli_memwrite(struct inode *ip, struct file *fp, const char *buf, unsigned long count);
@@ -2781,7 +2782,7 @@
  *	we need to do here is set up the appropriate per port data structures.
  */
 
-static int stli_initports(stlibrd_t *brdp)
+static inline int stli_initports(stlibrd_t *brdp)
 {
 	stliport_t	*portp;
 	int		i, panelnr, panelport;
@@ -3335,7 +3336,7 @@
  *	board types.
  */
 
-static int stli_initecp(stlibrd_t *brdp)
+static inline int stli_initecp(stlibrd_t *brdp)
 {
 	cdkecpsig_t	sig;
 	cdkecpsig_t	*sigsp;
@@ -3472,7 +3473,7 @@
  *	This handles only these board types.
  */
 
-static int stli_initonb(stlibrd_t *brdp)
+static inline int stli_initonb(stlibrd_t *brdp)
 {
 	cdkonbsig_t	sig;
 	cdkonbsig_t	*sigsp;
@@ -3737,7 +3738,7 @@
  *	Probe and initialize the specified board.
  */
 
-static int stli_brdinit(stlibrd_t *brdp)
+__initfunc(static int stli_brdinit(stlibrd_t *brdp))
 {
 #if DEBUG
 	printk("stli_brdinit(brdp=%x)\n", (int) brdp);
@@ -3791,7 +3792,7 @@
  *	might be. This is a bit if hack, but it is the best we can do.
  */
 
-static int stli_eisamemprobe(stlibrd_t *brdp)
+__initfunc(static int stli_eisamemprobe(stlibrd_t *brdp))
 {
 	cdkecpsig_t	ecpsig, *ecpsigp;
 	cdkonbsig_t	onbsig, *onbsigp;
@@ -3890,7 +3891,7 @@
  *	do is go probing around in the usual places hoping we can find it.
  */
 
-static int stli_findeisabrds()
+static inline int stli_findeisabrds()
 {
 	stlibrd_t	*brdp;
 	unsigned int	iobase, eid;
@@ -3979,7 +3980,7 @@
  *	can find.
  */
 
-static int stli_initbrds()
+static inline int stli_initbrds()
 {
 	stlibrd_t	*brdp, *nxtbrdp;
 	stlconf_t	*confp;
@@ -4471,7 +4472,7 @@
 
 /*****************************************************************************/
 
-int stli_init()
+__initfunc(int stli_init())
 {
 	printk(KERN_INFO "%s: version %s\n", stli_drvname, stli_drvversion);
 
diff -u --recursive --new-file v2.1.35/linux/drivers/char/keyb_m68k.c linux/drivers/char/keyb_m68k.c
--- v2.1.35/linux/drivers/char/keyb_m68k.c	Fri Apr  4 08:52:19 1997
+++ linux/drivers/char/keyb_m68k.c	Tue Apr 22 22:42:47 1997
@@ -27,6 +27,7 @@
 #include <linux/tty_flip.h>
 #include <linux/mm.h>
 #include <linux/random.h>
+#include <linux/init.h>
 
 #include <asm/bitops.h>
 #include <asm/machdep.h>
@@ -848,7 +849,7 @@
 	}
 }
 
-int kbd_init(void)
+__initfunc(int kbd_init(void))
 {
 	int i;
 	struct kbd_struct kbd0;
diff -u --recursive --new-file v2.1.35/linux/drivers/char/keyboard.c linux/drivers/char/keyboard.c
--- v2.1.35/linux/drivers/char/keyboard.c	Fri Apr  4 08:52:19 1997
+++ linux/drivers/char/keyboard.c	Tue Apr 22 22:42:47 1997
@@ -28,6 +28,7 @@
 #include <linux/string.h>
 #include <linux/ioport.h>
 #include <linux/random.h>
+#include <linux/init.h>
 
 #include <asm/bitops.h>
 
@@ -1192,7 +1193,7 @@
 	}
 }
 
-int kbd_init(void)
+__initfunc(int kbd_init(void))
 {
 	int i;
 	struct kbd_struct kbd0;
@@ -1306,7 +1307,7 @@
 	outb(data, address);               /* write out the data*/
 }
 
-static int initialize_kbd(void)
+__initfunc(static int initialize_kbd(void))
 {
 	unsigned long flags;
 
diff -u --recursive --new-file v2.1.35/linux/drivers/char/lp.c linux/drivers/char/lp.c
--- v2.1.35/linux/drivers/char/lp.c	Mon Apr 14 16:28:11 1997
+++ linux/drivers/char/lp.c	Tue Apr 22 22:42:47 1997
@@ -23,6 +23,7 @@
 #include <linux/ioport.h>
 #include <linux/fcntl.h>
 #include <linux/delay.h>
+#include <linux/init.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -678,7 +679,7 @@
 	return 0;
 }
 
-int lp_init(void)
+__initfunc(int lp_init(void))
 {
 	int count = 0;
 	struct parport *pb;
@@ -693,24 +694,27 @@
 	pb = parport_enumerate();
 
 	while (pb) {
-		if (parport[0] == -1 || lp_searchfor(parport, count) ||
-		    (parport[0] == -3 &&
-		     pb->probe_info.class == PARPORT_CLASS_PRINTER)) {
-			lp_table[count].dev =
-			    parport_register_device(pb, dev_name, NULL, 
-					    lp_wakeup,
-					    lp_interrupt, PARPORT_DEV_TRAN,
-					    (void *) &lp_table[count]);
-			lp_table[count].flags |= LP_EXIST;
-			printk(KERN_INFO "lp%d: using %s at 0x%x, ", count,
-			       pb->name, pb->base);
-			if (pb->irq == -1)
-				printk("polling.\n");
-			else
-				printk("irq %d.\n", pb->irq);
+		/* We only understand PC-style ports. */
+		if (pb->modes & PARPORT_MODE_SPP) {
+			if (parport[0] == -1 || lp_searchfor(parport, count) ||
+			    (parport[0] == -3 &&
+			     pb->probe_info.class == PARPORT_CLASS_PRINTER)) {
+				lp_table[count].dev =
+				  parport_register_device(pb, dev_name, NULL, 
+						lp_wakeup,
+						lp_interrupt, PARPORT_DEV_TRAN,
+						(void *) &lp_table[count]);
+				lp_table[count].flags |= LP_EXIST;
+				printk(KERN_INFO "lp%d: using %s at 0x%x, ", 
+				       count, pb->name, pb->base);
+				if (pb->irq == -1)
+					printk("polling.\n");
+				else
+					printk("irq %d.\n", pb->irq);
+			}
+			if (++count == LP_NO)
+				break;
 		}
-		if (++count == LP_NO)
-			break;
 		pb = pb->next;
   	}
 
diff -u --recursive --new-file v2.1.35/linux/drivers/char/lp_m68k.c linux/drivers/char/lp_m68k.c
--- v2.1.35/linux/drivers/char/lp_m68k.c	Fri Apr  4 08:52:19 1997
+++ linux/drivers/char/lp_m68k.c	Thu Apr 17 13:20:45 1997
@@ -34,8 +34,8 @@
  *
  */
 
-#include <linux/module.h>
 #include <linux/config.h>
+#include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/major.h>
@@ -139,40 +139,35 @@
 
 static int lp_error;
 
-void lp_interrupt(int irq, void *dummy, struct pt_regs *fp)
+void lp_interrupt(int dev)
 {
-    unsigned long flags;
-    int dev;
-
-    for (dev = 0; dev < MAX_LP; dev++) {
-	if ((lp_table[dev] != NULL) && (lp_table[dev]->lp_my_interrupt(dev) != 0))
-	  if (lp_table[dev]->do_print)
-	  {
-		  if (lp_table[dev]->copy_size)
-		  {
-			  save_flags(flags);
-			  cli();
-			  if (lp_char_interrupt(lp_table[dev]->lp_buffer[lp_table[dev]->bytes_written], dev)) {
-				  --lp_table[dev]->copy_size;
-				  ++lp_table[dev]->bytes_written;
-				  restore_flags(flags);
-			  }
-			  else
-			  {
-				  lp_table[dev]->do_print = 0;
-				  restore_flags(flags);
-				  lp_error = 1;
-				  wake_up_interruptible(&lp_table[dev]->lp_wait_q);
-			  }
-		  }
-		  else
-		  {
-			  lp_table[dev]->do_print = 0;
-			  lp_error = 0;
-			  wake_up_interruptible(&lp_table[dev]->lp_wait_q);
-		  }
+    if (dev >= 0 && dev < MAX_LP && lp_table[dev]->do_print)
+    {
+	if (lp_table[dev]->copy_size)
+	{
+    		unsigned long flags;
+		save_flags(flags);
+		cli();
+		if (lp_char_interrupt(lp_table[dev]->lp_buffer[lp_table[dev]->bytes_written], dev)) {
+			--lp_table[dev]->copy_size;
+			++lp_table[dev]->bytes_written;
+			restore_flags(flags);
+		}
+		else
+		{
+			lp_table[dev]->do_print = 0;
+			restore_flags(flags);
+			lp_error = 1;
+			wake_up_interruptible(&lp_table[dev]->lp_wait_q);
+		}
+	}
+	else
+	{
+		lp_table[dev]->do_print = 0;
+		lp_error = 0;
+		wake_up_interruptible(&lp_table[dev]->lp_wait_q);
+	}
 
-	  }
     }
 }
 
@@ -366,6 +361,7 @@
 static int lp_open(struct inode *inode, struct file *file)
 {
 	int dev = MINOR(inode->i_rdev);
+	int ret;
 
 	if (dev >= MAX_LP)
 		return -ENODEV;
@@ -386,10 +382,14 @@
 
 	lp_table[dev]->flags |= LP_BUSY;
 
-	MOD_INC_USE_COUNT;
-	lp_table[dev]->lp_open();
-
-	return 0;
+	ret = lp_table[dev]->lp_open(dev);
+	if (ret != 0) {
+		lp_table[dev]->flags &= ~LP_BUSY;
+	}
+	else {
+		MOD_INC_USE_COUNT;
+	}
+	return ret;
 }
 
 static int lp_release(struct inode *inode, struct file *file)
@@ -397,7 +397,7 @@
 	int dev =MINOR(inode->i_rdev);
 
 	lp_table[dev]->flags &= ~LP_BUSY;
-	lp_table[dev]->lp_release();
+	lp_table[dev]->lp_release(dev);
 	MOD_DEC_USE_COUNT;
 	return 0;
 }
@@ -458,18 +458,12 @@
 	lp_release
 };
 
-#ifdef CONFIG_MODULES
-static struct symbol_table parallel_syms = {
-#include <linux/symtab_begin.h>
-	X(lp_table),
-	X(lp_irq),
-	X(lp_interrupt),
-	X(lp_init),
-	X(register_parallel),
-	X(unregister_parallel),
-#include <linux/symtab_end.h>
-};
-#endif
+EXPORT_SYMBOL(lp_table);
+EXPORT_SYMBOL(lp_irq);
+EXPORT_SYMBOL(lp_interrupt);
+EXPORT_SYMBOL(lp_init);
+EXPORT_SYMBOL(register_parallel);
+EXPORT_SYMBOL(unregister_parallel);
 
 int lp_init(void)
 {
@@ -482,14 +476,6 @@
 		printk(KERN_ERR "unable to get major %d for line printer\n", LP_MAJOR);
 		return -ENXIO;
 	}
-
-#ifdef CONFIG_MODULES
-	if (register_symtab(&parallel_syms)) {
-		unregister_chrdev(LP_MAJOR, "lp");
-		printk(KERN_CRIT "unable to register parallel symtab\n");
-		return -ENXIO;
-	}
-#endif
 
 #if WHICH_DRIVER == FORCE_POLLING
 	lp_irq = 0;
diff -u --recursive --new-file v2.1.35/linux/drivers/char/mem.c linux/drivers/char/mem.c
--- v2.1.35/linux/drivers/char/mem.c	Sat Jan 25 13:46:13 1997
+++ linux/drivers/char/mem.c	Thu Apr 17 13:20:45 1997
@@ -19,6 +19,7 @@
 #include <linux/mman.h>
 #include <linux/mm.h>
 #include <linux/random.h>
+#include <linux/init.h>
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
@@ -491,7 +492,7 @@
 	NULL		/* fsync */
 };
 
-int chr_dev_init(void)
+__initfunc(int chr_dev_init(void))
 {
 	if (register_chrdev(MEM_MAJOR,"mem",&memory_fops))
 		printk("unable to get major %d for memory devs\n", MEM_MAJOR);
diff -u --recursive --new-file v2.1.35/linux/drivers/char/misc.c linux/drivers/char/misc.c
--- v2.1.35/linux/drivers/char/misc.c	Fri Apr  4 08:52:19 1997
+++ linux/drivers/char/misc.c	Tue Apr 22 22:42:47 1997
@@ -39,6 +39,7 @@
 #include <linux/malloc.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
+#include <linux/init.h>
 #ifdef CONFIG_APM
 #include <linux/apm_bios.h>
 #endif
@@ -184,7 +185,7 @@
 static struct proc_dir_entry *proc_misc;	
 #endif
 
-int misc_init(void)
+__initfunc(int misc_init(void))
 {
 #ifndef MODULE
 #ifdef CONFIG_PROC_FS
diff -u --recursive --new-file v2.1.35/linux/drivers/char/msbusmouse.c linux/drivers/char/msbusmouse.c
--- v2.1.35/linux/drivers/char/msbusmouse.c	Fri Apr  4 08:52:19 1997
+++ linux/drivers/char/msbusmouse.c	Tue Apr 22 22:42:47 1997
@@ -41,6 +41,7 @@
 #include <linux/miscdevice.h>
 #include <linux/random.h>
 #include <linux/poll.h>
+#include <linux/init.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -183,7 +184,7 @@
 	MICROSOFT_BUSMOUSE, "msbusmouse", &ms_bus_mouse_fops
 };
 
-int ms_bus_mouse_init(void)
+__initfunc(int ms_bus_mouse_init(void))
 {
 	int mse_byte, i;
 
diff -u --recursive --new-file v2.1.35/linux/drivers/char/pcwd.c linux/drivers/char/pcwd.c
--- v2.1.35/linux/drivers/char/pcwd.c	Fri Apr  4 08:52:19 1997
+++ linux/drivers/char/pcwd.c	Tue Apr 22 22:42:47 1997
@@ -48,6 +48,7 @@
 #include <linux/fs.h>
 #include <linux/mm.h>
 #include <linux/watchdog.h>
+#include <linux/init.h>
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
@@ -96,7 +97,7 @@
  * This routine checks the "current_readport" to see if the card lies there.
  * If it does, it returns accordingly.
  */
-static int pcwd_checkcard(void)
+__initfunc(static int pcwd_checkcard(void))
 {
 	int card_dat, prev_card_dat, found = 0, count = 0, done = 0;
 
@@ -400,13 +401,13 @@
 	return 0;
 }
 
-static void get_support(void)
+static inline void get_support(void)
 {
 	if (inb(current_readport) != 0xF0)
 		supports_temp = 1;
 }
 
-static int get_revision(void)
+static inline int get_revision(void)
 {
 	if ((inb(current_readport + 2) == 0xFF) ||
 	    (inb(current_readport + 3) == 0xFF))
@@ -415,7 +416,7 @@
 	return(PCWD_REVISION_C);
 }
 
-static int send_command(int cmd)
+__initfunc(static int send_command(int cmd))
 {
 	int i;
 
@@ -428,7 +429,7 @@
 	return(i);
 }
 
-static char *get_firmware(void)
+static inline char *get_firmware(void)
 {
 	int i, found = 0, count = 0, one, ten, hund, minor;
 	char *ret;
@@ -498,7 +499,7 @@
 #ifdef	MODULE
 int init_module(void)
 #else
-int pcwatchdog_init(void)
+__initfunc(int pcwatchdog_init(void))
 #endif
 {
 	int i, found = 0;
diff -u --recursive --new-file v2.1.35/linux/drivers/char/pcxx.c linux/drivers/char/pcxx.c
--- v2.1.35/linux/drivers/char/pcxx.c	Sun Apr 13 10:18:20 1997
+++ linux/drivers/char/pcxx.c	Tue Apr 22 22:42:47 1997
@@ -69,6 +69,7 @@
 #include <linux/tty_driver.h>
 #include <linux/malloc.h>
 #include <linux/string.h>
+#include <linux/init.h>
 
 #ifndef MODULE
 #include <linux/ctype.h> /* We only need it for parsing the "digi="-line */
@@ -217,6 +218,7 @@
 	timer_active &= ~(1 << DIGI_TIMER);
 	timer_table[DIGI_TIMER].fn = NULL;
 	timer_table[DIGI_TIMER].expires = 0;
+	remove_bh(DIGI_BH);
 
 	if ((e1 = tty_unregister_driver(&pcxe_driver)))
 		printk("SERIAL: failed to unregister serial driver (%d)\n", e1);
@@ -1084,7 +1086,7 @@
  * function to initialize the driver with the given parameters, which are either
  * the default values from this file or the parameters given at boot.
  */
-int pcxe_init(void)
+__initfunc(int pcxe_init(void))
 {
 	ulong memory_seg=0, memory_size=0;
 	int lowwater, enabled_cards=0, i, crd, shrinkmem=0, topwin = 0xff00L, botwin=0x100L;
diff -u --recursive --new-file v2.1.35/linux/drivers/char/psaux.c linux/drivers/char/psaux.c
--- v2.1.35/linux/drivers/char/psaux.c	Fri Apr  4 08:52:19 1997
+++ linux/drivers/char/psaux.c	Tue Apr 22 22:42:47 1997
@@ -46,6 +46,7 @@
 #include <linux/miscdevice.h>
 #include <linux/random.h>
 #include <linux/poll.h>
+#include <linux/init.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -529,7 +530,7 @@
 	PSMOUSE_MINOR, "ps2aux", &psaux_fops
 };
 
-int psaux_init(void)
+__initfunc(int psaux_init(void))
 {
 	int qp_found = 0;
 
@@ -653,7 +654,7 @@
  * See if we can find a 82C710 device. Read mouse address.
  */
 
-static int probe_qp(void)
+__initfunc(static int probe_qp(void))
 {
 	outb_p(0x55, 0x2fa);			/* Any value except 9, ff or 36 */
 	outb_p(0xaa, 0x3fa);			/* Inverse of 55 */
diff -u --recursive --new-file v2.1.35/linux/drivers/char/pty.c linux/drivers/char/pty.c
--- v2.1.35/linux/drivers/char/pty.c	Tue Mar  4 10:25:23 1997
+++ linux/drivers/char/pty.c	Tue Apr 22 22:42:47 1997
@@ -13,6 +13,7 @@
 #include <linux/string.h>
 #include <linux/major.h>
 #include <linux/mm.h>
+#include <linux/init.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -224,7 +225,7 @@
         tty->termios->c_cflag |= (CS8 | CREAD);
 }
 
-int pty_init(void)
+__initfunc(int pty_init(void))
 {
 	memset(&pty_state, 0, sizeof(pty_state));
 	memset(&pty_driver, 0, sizeof(struct tty_driver));
diff -u --recursive --new-file v2.1.35/linux/drivers/char/random.c linux/drivers/char/random.c
--- v2.1.35/linux/drivers/char/random.c	Thu Mar 27 14:40:03 1997
+++ linux/drivers/char/random.c	Tue Apr 22 22:42:47 1997
@@ -234,6 +234,7 @@
 #include <linux/malloc.h>
 #include <linux/random.h>
 #include <linux/poll.h>
+#include <linux/init.h>
 
 #include <asm/uaccess.h>
 #include <asm/irq.h>
@@ -451,7 +452,7 @@
 	init_std_data(&random_state);
 }
 
-void rand_initialize(void)
+__initfunc(void rand_initialize(void))
 {
 	int i;
 
@@ -1388,8 +1389,9 @@
 	return (((unsigned long long) high << 31) | low); 
 }
 
-static void initialize_benchmark(struct random_benchmark *bench,
-				 const char *descr, int unit)
+__initfunc(static void
+initialize_benchmark(struct random_benchmark *bench,
+	             const char *descr, int unit))
 {
 	bench->times = 0;
 	bench->accum = 0;
diff -u --recursive --new-file v2.1.35/linux/drivers/char/riscom8.c linux/drivers/char/riscom8.c
--- v2.1.35/linux/drivers/char/riscom8.c	Fri Dec 27 02:03:22 1996
+++ linux/drivers/char/riscom8.c	Tue Apr 22 22:42:47 1997
@@ -40,6 +40,7 @@
 #include <linux/serial.h>
 #include <linux/fcntl.h>
 #include <linux/major.h>
+#include <linux/init.h>
 
 #include <asm/uaccess.h>
 
@@ -231,7 +232,7 @@
 }
 
 /* Reset and setup CD180 chip */
-static void rc_init_CD180(struct riscom_board const * bp)
+__initfunc(static void rc_init_CD180(struct riscom_board const * bp))
 {
 	unsigned long flags;
 	
@@ -256,7 +257,7 @@
 }
 
 /* Main probing routine, also sets irq. */
-static int rc_probe(struct riscom_board *bp)
+__initfunc(static int rc_probe(struct riscom_board *bp))
 {
 	unsigned char val1, val2;
 	int irqs = 0;
@@ -264,7 +265,7 @@
 	
 	bp->irq = 0;
 
-	if (rc_check_io_range(bp)) 
+	if (rc_check_io_range(bp))
 		return 1;
 	
 	/* Are the I/O ports here ? */
@@ -1718,7 +1719,7 @@
 	}
 }
 
-static int rc_init_drivers(void)
+static inline int rc_init_drivers(void)
 {
 	int error;
 	int i;
@@ -1799,9 +1800,15 @@
 
 static void rc_release_drivers(void)
 {
+	unsigned long flags;
+
+	save_flags(flags);
+	cli();
+	remove_bh(RISCOM8_BH);
 	free_page((unsigned long)tmp_buf);
 	tty_unregister_driver(&riscom_driver);
 	tty_unregister_driver(&riscom_callout_driver);
+	restore_flags(flags);
 }
 
 #ifndef MODULE
@@ -1830,7 +1837,7 @@
 /* 
  * This routine must be called by kernel at boot time 
  */
-int riscom8_init(void) 
+__initfunc(int riscom8_init(void))
 {
 	int i;
 	int found = 0;
diff -u --recursive --new-file v2.1.35/linux/drivers/char/rtc.c linux/drivers/char/rtc.c
--- v2.1.35/linux/drivers/char/rtc.c	Wed Apr 16 14:15:00 1997
+++ linux/drivers/char/rtc.c	Tue Apr 22 22:42:47 1997
@@ -50,6 +50,7 @@
 #include <linux/ioport.h>
 #include <linux/fcntl.h>
 #include <linux/mc146818rtc.h>
+#include <linux/init.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -531,7 +532,7 @@
 	&rtc_fops
 };
 
-int rtc_init(void)
+__initfunc(int rtc_init(void))
 {
 	unsigned long flags;
 
diff -u --recursive --new-file v2.1.35/linux/drivers/char/serial.c linux/drivers/char/serial.c
--- v2.1.35/linux/drivers/char/serial.c	Fri Apr  4 08:52:19 1997
+++ linux/drivers/char/serial.c	Tue Apr 22 22:42:47 1997
@@ -45,6 +45,7 @@
 #include <linux/ioport.h>
 #include <linux/mm.h>
 #include <linux/malloc.h>
+#include <linux/init.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
@@ -2917,7 +2918,7 @@
  * number, and identifies which options were configured into this
  * driver.
  */
-static void show_serial_version(void)
+static _INLINE_ void show_serial_version(void)
 {
  	printk(KERN_INFO "%s version %s with", serial_name, serial_version);
 #ifdef CONFIG_HUB6
@@ -3216,7 +3217,7 @@
 /*
  * The serial driver boot-time initialization code!
  */
-int rs_init(void)
+__initfunc(int rs_init(void))
 {
 	int i;
 	struct serial_state * state;
@@ -3410,6 +3411,7 @@
 	timer_active &= ~(1 << RS_TIMER);
 	timer_table[RS_TIMER].fn = NULL;
 	timer_table[RS_TIMER].expires = 0;
+        remove_bh(SERIAL_BH);
 	if ((e1 = tty_unregister_driver(&serial_driver)))
 		printk("SERIAL: failed to unregister serial driver (%d)\n",
 		       e1);
diff -u --recursive --new-file v2.1.35/linux/drivers/char/softdog.c linux/drivers/char/softdog.c
--- v2.1.35/linux/drivers/char/softdog.c	Fri Apr  4 08:52:19 1997
+++ linux/drivers/char/softdog.c	Tue Apr 22 22:42:47 1997
@@ -34,6 +34,7 @@
 #include <linux/miscdevice.h>
 #include <linux/watchdog.h>
 #include <linux/reboot.h>
+#include <linux/init.h>
 #include <asm/uaccess.h>
 
 #define WATCHDOG_MINOR	130
@@ -172,7 +173,7 @@
 	&softdog_fops
 };
 
-void watchdog_init(void)
+__initfunc(void watchdog_init(void))
 {
 	misc_register(&softdog_miscdev);
 	init_timer(&watchdog_ticktock);
diff -u --recursive --new-file v2.1.35/linux/drivers/char/stallion.c linux/drivers/char/stallion.c
--- v2.1.35/linux/drivers/char/stallion.c	Mon Mar 17 14:54:25 1997
+++ linux/drivers/char/stallion.c	Tue Apr 22 22:42:47 1997
@@ -45,6 +45,7 @@
 #include <linux/malloc.h>
 #include <linux/ioport.h>
 #include <linux/config.h>
+#include <linux/init.h>
 #include <asm/system.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -389,10 +390,10 @@
 static void	stl_hangup(struct tty_struct *tty);
 static int	stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg);
 
-static int	stl_initbrds(void);
+static inline int stl_initbrds(void);
 static int	stl_brdinit(stlbrd_t *brdp);
-static int	stl_initeio(stlbrd_t *brdp);
-static int	stl_initech(stlbrd_t *brdp);
+static inline int stl_initeio(stlbrd_t *brdp);
+static inline int stl_initech(stlbrd_t *brdp);
 static int	stl_initports(stlbrd_t *brdp, stlpanel_t *panelp);
 static int	stl_mapirq(int irq);
 static void	stl_getserial(stlport_t *portp, struct serial_struct *sp);
@@ -414,7 +415,7 @@
 static stlport_t *stl_getport(int brdnr, int panelnr, int portnr);
 
 #ifdef	CONFIG_PCI
-static int	stl_findpcibrds(void);
+static inline int stl_findpcibrds(void);
 #endif
 
 /*
@@ -1745,7 +1746,7 @@
  *	interrupt across multiple boards.
  */
 
-static int stl_mapirq(int irq)
+__initfunc(static int stl_mapirq(int irq))
 {
 	int	rc, i;
 
@@ -1775,7 +1776,7 @@
  *	Initialize all the ports on a panel.
  */
 
-static int stl_initports(stlbrd_t *brdp, stlpanel_t *panelp)
+__initfunc(static int stl_initports(stlbrd_t *brdp, stlpanel_t *panelp))
 {
 	stlport_t	*portp;
 	int		chipmask, i;
@@ -1827,7 +1828,7 @@
  *	Try to find and initialize an EasyIO board.
  */
 
-static int stl_initeio(stlbrd_t *brdp)
+static inline int stl_initeio(stlbrd_t *brdp)
 {
 	stlpanel_t	*panelp;
 	unsigned int	status;
@@ -1929,7 +1930,7 @@
  *	dealing with all types of ECH board.
  */
 
-static int stl_initech(stlbrd_t *brdp)
+static inline int stl_initech(stlbrd_t *brdp)
 {
 	stlpanel_t	*panelp;
 	unsigned int	status, nxtid, ioaddr, conflict;
@@ -2096,7 +2097,7 @@
  *	since the initial search and setup is very different.
  */
 
-static int stl_brdinit(stlbrd_t *brdp)
+__initfunc(static int stl_brdinit(stlbrd_t *brdp))
 {
 	int	i;
 
@@ -2141,7 +2142,7 @@
 
 #ifdef	CONFIG_PCI
 
-static int stl_findpcibrds()
+static inline int stl_findpcibrds()
 {
 	stlbrd_t	*brdp;
 	unsigned char	busnr, devnr, irq;
@@ -2228,7 +2229,7 @@
  *	since the initial search and setup is too different.
  */
 
-static int stl_initbrds()
+static inline int stl_initbrds()
 {
 	stlbrd_t	*brdp;
 	stlconf_t	*confp;
@@ -2514,7 +2515,7 @@
 
 /*****************************************************************************/
 
-int stl_init(void)
+__initfunc(int stl_init(void))
 {
 	printk(KERN_INFO "%s: version %s\n", stl_drvname, stl_drvversion);
 
diff -u --recursive --new-file v2.1.35/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c
--- v2.1.35/linux/drivers/char/tty_io.c	Sun Apr 13 10:18:21 1997
+++ linux/drivers/char/tty_io.c	Tue Apr 22 22:42:47 1997
@@ -71,6 +71,7 @@
 #ifdef CONFIG_PROC_FS
 #include <linux/proc_fs.h>
 #endif
+#include <linux/init.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -1704,7 +1705,7 @@
  * Ok, now we can initialize the rest of the tty devices and can count
  * on memory allocations, interrupts etc..
  */
-int tty_init(void)
+__initfunc(int tty_init(void))
 {
 	if (sizeof(struct tty_struct) > PAGE_SIZE)
 		panic("size of tty structure > PAGE_SIZE!");
diff -u --recursive --new-file v2.1.35/linux/drivers/char/vc_screen.c linux/drivers/char/vc_screen.c
--- v2.1.35/linux/drivers/char/vc_screen.c	Sun Jan 26 02:07:17 1997
+++ linux/drivers/char/vc_screen.c	Tue Apr 22 22:42:48 1997
@@ -30,6 +30,7 @@
 #include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/mm.h>
+#include <linux/init.h>
 #include <asm/uaccess.h>
 #include "vt_kern.h"
 #include "selection.h"
@@ -251,7 +252,7 @@
 	NULL		/* fsync */
 };
 
-int vcs_init(void)
+__initfunc(int vcs_init(void))
 {
 	int error;
 
diff -u --recursive --new-file v2.1.35/linux/drivers/char/vt.c linux/drivers/char/vt.c
--- v2.1.35/linux/drivers/char/vt.c	Mon Apr 14 16:28:11 1997
+++ linux/drivers/char/vt.c	Thu Apr 17 09:20:38 1997
@@ -311,7 +311,7 @@
 	int sz;
 	int delta;
 	char *first_free, *fj, *fnw;
-	int j, k, i = 0;
+	int i, j, k;
 
 	/* we mostly copy too much here (512bytes), but who cares ;) */
 	if (copy_from_user(&tmp, user_kdgkb, sizeof(struct kbsentry)))
@@ -319,6 +319,7 @@
 	tmp.kb_string[sizeof(tmp.kb_string)-1] = '\0';
 	if (tmp.kb_func >= MAX_NR_FUNC)
 		return -EINVAL;
+	i = tmp.kb_func;
 
 	switch (cmd) {
 	case KDGKBSENT:
diff -u --recursive --new-file v2.1.35/linux/drivers/char/wdt.c linux/drivers/char/wdt.c
--- v2.1.35/linux/drivers/char/wdt.c	Fri Apr  4 08:52:19 1997
+++ linux/drivers/char/wdt.c	Tue Apr 22 22:42:48 1997
@@ -43,6 +43,7 @@
 #include <asm/system.h>
 #include <linux/notifier.h>
 #include <linux/reboot.h>
+#include <linux/init.h>
 
 static int wdt_is_open=0;
 
@@ -352,22 +353,7 @@
 
 #ifdef MODULE
 
-int init_module(void)
-{
-	printk("WDT501-P module at %X(Interrupt %d)\n", io,irq);
-	if(request_irq(irq, wdt_interrupt, SA_INTERRUPT, "wdt501p", NULL))
-	{
-		printk("IRQ %d is not free.\n", irq);
-		return -EIO;
-	}
-	misc_register(&wdt_miscdev);
-#ifdef CONFIG_WDT_501	
-	misc_register(&temp_miscdev);
-#endif	
-	request_region(io, 8, "wdt501");
-	notifier_chain_register(&boot_notifier_list, &wdt_notifier);
-	return 0;
-}
+#define wdt_init init_module
 
 void cleanup_module(void)
 {
@@ -380,9 +366,9 @@
 	free_irq(irq, NULL);
 }
 
-#else
+#endif
 
-int wdt_init(void)
+__initfunc(int wdt_init(void))
 {
 	printk("WDT500/501-P driver at %X(Interrupt %d)\n", io,irq);
 	if(request_irq(irq, wdt_interrupt, SA_INTERRUPT, "wdt501p", NULL))
@@ -399,4 +385,3 @@
 	return 0;
 }
 
-#endif
diff -u --recursive --new-file v2.1.35/linux/drivers/isdn/sc/init.c linux/drivers/isdn/sc/init.c
--- v2.1.35/linux/drivers/isdn/sc/init.c	Thu Feb 27 10:57:30 1997
+++ linux/drivers/isdn/sc/init.c	Thu Apr 17 09:23:17 1997
@@ -305,7 +305,7 @@
 			/*
 			 * No interrupt could be used
 			 */
-			pr_debug("Failed to aquire an IRQ line\n");
+			pr_debug("Failed to acquire an IRQ line\n");
 			continue;
 		}
 
diff -u --recursive --new-file v2.1.35/linux/drivers/net/3c501.c linux/drivers/net/3c501.c
--- v2.1.35/linux/drivers/net/3c501.c	Fri Apr  4 08:52:20 1997
+++ linux/drivers/net/3c501.c	Tue Apr 22 22:42:48 1997
@@ -102,12 +102,13 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
+#include <linux/init.h>
 
 #define BLOCKOUT_2
 
 /* A zero-terminated list of I/O addresses to be probed.
    The 3c501 can be at many locations, but here are the popular ones. */
-static unsigned int netcard_portlist[] =
+static unsigned int netcard_portlist[] __initdata =
    { 0x280, 0x300, 0};
 
 
@@ -208,7 +209,7 @@
 struct netdev_entry el1_drv = {"3c501", el1_probe1, EL1_IO_EXTENT, netcard_portlist};
 #else
 
-int el1_probe(struct device *dev)
+__initfunc(int el1_probe(struct device *dev))
 {
 	int i;
 	int base_addr = dev ? dev->base_addr : 0;
@@ -235,7 +236,7 @@
  *	The actual probe.
  */
 
-static int el1_probe1(struct device *dev, int ioaddr)
+__initfunc(static int el1_probe1(struct device *dev, int ioaddr))
 {
 	const char *mname;		/* Vendor name */
 	unsigned char station_addr[6];
diff -u --recursive --new-file v2.1.35/linux/drivers/net/3c503.c linux/drivers/net/3c503.c
--- v2.1.35/linux/drivers/net/3c503.c	Tue Dec 31 00:29:59 1996
+++ linux/drivers/net/3c503.c	Tue Apr 22 22:42:48 1997
@@ -42,6 +42,7 @@
 #include <linux/delay.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
+#include <linux/init.h>
 
 #include <asm/io.h>
 #include <asm/system.h>
@@ -56,7 +57,7 @@
 int el2_probe1(struct device *dev, int ioaddr);
 
 /* A zero-terminated list of I/O addresses to be probed in PIO mode. */
-static unsigned int netcard_portlist[] =
+static unsigned int netcard_portlist[] __initdata =
 	{ 0x300,0x310,0x330,0x350,0x250,0x280,0x2a0,0x2e0,0};
 
 #define EL2_IO_EXTENT	16
@@ -89,8 +90,8 @@
    If the ethercard isn't found there is an optional probe for
    ethercard jumpered to programmed-I/O mode.
    */
-int
-el2_probe(struct device *dev)
+__initfunc(int
+el2_probe(struct device *dev))
 {
     int *addr, addrs[] = { 0xddffe, 0xd9ffe, 0xcdffe, 0xc9ffe, 0};
     int base_addr = dev->base_addr;
@@ -124,8 +125,8 @@
 #ifndef HAVE_DEVLIST
 /*  Try all of the locations that aren't obviously empty.  This touches
     a lot of locations, and is much riskier than the code above. */
-int
-el2_pio_probe(struct device *dev)
+__initfunc(int
+el2_pio_probe(struct device *dev))
 {
     int i;
     int base_addr = dev ? dev->base_addr : 0;
@@ -150,8 +151,8 @@
 /* Probe for the Etherlink II card at I/O port base IOADDR,
    returning non-zero on success.  If found, set the station
    address and memory parameters in DEVICE. */
-int
-el2_probe1(struct device *dev, int ioaddr)
+__initfunc(int
+el2_probe1(struct device *dev, int ioaddr))
 {
     int i, iobase_reg, membase_reg, saved_406, wordlength;
     static unsigned version_printed = 0;
diff -u --recursive --new-file v2.1.35/linux/drivers/net/3c505.c linux/drivers/net/3c505.c
--- v2.1.35/linux/drivers/net/3c505.c	Mon Apr 14 16:28:11 1997
+++ linux/drivers/net/3c505.c	Tue Apr 22 22:42:48 1997
@@ -108,6 +108,7 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
+#include <linux/init.h>
 
 #include "3c505.h"
 
@@ -178,7 +179,7 @@
  * Last element MUST BE 0!
  *****************************************************************/
 
-static const int addr_list[] = {0x300, 0x280, 0x310, 0};
+static const int addr_list[] __initdata = {0x300, 0x280, 0x310, 0};
 
 /* Dma Memory related stuff */
 
@@ -1305,7 +1306,7 @@
  *
  ******************************************************/
 
-static void elp_init(struct device *dev)
+static inline void elp_init(struct device *dev)
 {
 	elp_device *adapter = dev->priv;
 
@@ -1338,7 +1339,7 @@
  * Called only by elp_autodetect
  ************************************************************/
 
-static int elp_sense(struct device *dev)
+__initfunc(static int elp_sense(struct device *dev))
 {
 	int timeout;
 	int addr = dev->base_addr;
@@ -1405,7 +1406,7 @@
  * Called only by eplus_probe
  *************************************************************/
 
-static int elp_autodetect(struct device *dev)
+__initfunc(static int elp_autodetect(struct device *dev))
 {
 	int idx = 0;
 
@@ -1449,7 +1450,7 @@
  * work at all if it was in a weird state).
  */
 
-int elplus_probe(struct device *dev)
+__initfunc(int elplus_probe(struct device *dev))
 {
 	elp_device *adapter;
 	int i, tries, tries1, timeout, okay;
diff -u --recursive --new-file v2.1.35/linux/drivers/net/3c507.c linux/drivers/net/3c507.c
--- v2.1.35/linux/drivers/net/3c507.c	Fri Apr  4 08:52:20 1997
+++ linux/drivers/net/3c507.c	Tue Apr 22 22:42:48 1997
@@ -59,6 +59,7 @@
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/malloc.h>
+#include <linux/init.h>
 
 
 /* use 0 for production, 1 for verification, 2..7 for debug */
@@ -68,7 +69,7 @@
 static unsigned int net_debug = NET_DEBUG;
 
 /* A zero-terminated list of common I/O addresses to be probed. */
-static unsigned int netcard_portlist[] =
+static unsigned int netcard_portlist[] __initdata =
 	{ 0x300, 0x320, 0x340, 0x280, 0};
 
 /*
@@ -301,7 +302,7 @@
 	device and return success.
 	*/
 
-int el16_probe(struct device *dev)
+__initfunc(int el16_probe(struct device *dev))
 {
 	int base_addr = dev ? dev->base_addr : 0;
 	int i;
@@ -322,7 +323,7 @@
 	return ENODEV;
 }
 
-int el16_probe1(struct device *dev, int ioaddr)
+__initfunc(int el16_probe1(struct device *dev, int ioaddr))
 {
 	static unsigned char init_ID_done = 0, version_printed = 0;
 	int i, irq, irqval;
diff -u --recursive --new-file v2.1.35/linux/drivers/net/3c509.c linux/drivers/net/3c509.c
--- v2.1.35/linux/drivers/net/3c509.c	Fri Apr  4 08:52:20 1997
+++ linux/drivers/net/3c509.c	Tue Apr 22 22:42:48 1997
@@ -48,6 +48,7 @@
 #include <linux/skbuff.h>
 #include <linux/config.h>	/* for CONFIG_MCA */
 #include <linux/delay.h>	/* for udelay() */
+#include <linux/init.h>
 
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -132,7 +133,7 @@
 
 
 
-int el3_probe(struct device *dev)
+__initfunc(int el3_probe(struct device *dev))
 {
 	short lrs_state = 0xff, i;
 	ushort ioaddr, irq, if_port;
@@ -312,7 +313,7 @@
 /* Read a word from the EEPROM using the regular EEPROM access register.
    Assume that we are in register window zero.
  */
-static ushort read_eeprom(short ioaddr, int index)
+__initfunc(static ushort read_eeprom(short ioaddr, int index))
 {
 	outw(EEPROM_READ + index, ioaddr + 10);
 	/* Pause for at least 162 us. for the read to take place. */
@@ -321,7 +322,7 @@
 }
 
 /* Read a word from the EEPROM when in the ISA ID probe state. */
-static ushort id_read_eeprom(int index)
+__initfunc(static ushort id_read_eeprom(int index))
 {
 	int bit, word = 0;
 
diff -u --recursive --new-file v2.1.35/linux/drivers/net/3c523.c linux/drivers/net/3c523.c
--- v2.1.35/linux/drivers/net/3c523.c	Fri Apr  4 08:52:20 1997
+++ linux/drivers/net/3c523.c	Tue Apr 22 22:42:48 1997
@@ -100,6 +100,7 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
+#include <linux/init.h>
 
 #include "3c523.h"
 
@@ -115,9 +116,9 @@
 /*
     Tables to which we can map values in the configuration registers.
 */
-static int irq_table[] = {12, 7, 3, 9};
-static int csr_table[] = {0x300, 0x1300, 0x2300, 0x3300};
-static int shm_table[] = {0x0c0000, 0x0c8000, 0x0d0000, 0x0d8000};
+static int irq_table[] __initdata = {12, 7, 3, 9};
+static int csr_table[] __initdata = {0x300, 0x1300, 0x2300, 0x3300};
+static int shm_table[] __initdata = {0x0c0000, 0x0c8000, 0x0d0000, 0x0d8000};
 
 /******************* how to calculate the buffers *****************************
 
@@ -308,9 +309,9 @@
  * Check to see if there's an 82586 out there.
  */
 
-static
+__initfunc(static
 int
-check586( struct device *dev, char *where, unsigned size) {
+check586( struct device *dev, char *where, unsigned size)) {
   struct priv *p = (struct priv *) dev->priv;
   char *iscp_addrs[2];
   int i = 0;
@@ -382,8 +383,8 @@
 }
 
 /*****************************************************************/
-static int
-elmc_getinfo( char* buf, int slot, void* d ) {
+__initfunc(static int
+elmc_getinfo( char* buf, int slot, void* d )) {
 	int len = 0;
 	struct device* dev = (struct device*) d;
 	int i;
@@ -411,8 +412,8 @@
 } /* elmc_getinfo() */
 
 /*****************************************************************/
-int
-elmc_probe(struct device *dev) {
+__initfunc(int
+elmc_probe(struct device *dev)) {
     static int slot = 0;
     int base_addr = dev ? dev->base_addr : 0;
     int irq = dev ? dev->irq : 0;
diff -u --recursive --new-file v2.1.35/linux/drivers/net/3c59x.c linux/drivers/net/3c59x.c
--- v2.1.35/linux/drivers/net/3c59x.c	Thu Mar 27 14:40:03 1997
+++ linux/drivers/net/3c59x.c	Tue Apr 22 22:42:48 1997
@@ -36,6 +36,7 @@
 #include <linux/ioport.h>
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
+#include <linux/init.h>
 
 #ifdef CONFIG_PCI
 #include <linux/pci.h>
@@ -84,7 +85,7 @@
 #endif
 
 #ifdef CONFIG_PCI
-static int product_ids[] = {0x5900, 0x5950, 0x5951, 0x5952, 0, 0};
+static int product_ids[] __initdata = {0x5900, 0x5950, 0x5951, 0x5952, 0, 0};
 #endif
 
 static const char *product_names[] = {
@@ -326,7 +327,7 @@
 }
 
 #else
-int tc59x_probe(struct device *dev)
+__initfunc(int tc59x_probe(struct device *dev))
 {
 	int cards_found = 0;
 
@@ -339,7 +340,7 @@
 }
 #endif  /* not MODULE */
 
-static int vortex_scan(struct device *dev)
+__initfunc(static int vortex_scan(struct device *dev))
 {
 	int cards_found = 0;
 
@@ -420,8 +421,8 @@
 	return cards_found;
 }
 
-static int vortex_found_device(struct device *dev, int ioaddr, int irq,
-							   int product_index, int options)
+__initfunc(static int vortex_found_device(struct device *dev, int ioaddr, int irq,
+							   int product_index, int options))
 {
 	struct vortex_private *vp;
 
@@ -480,7 +481,7 @@
 	return 0;
 }
 
-static int vortex_probe1(struct device *dev)
+__initfunc(static int vortex_probe1(struct device *dev))
 {
 	int ioaddr = dev->base_addr;
 	struct vortex_private *vp = (struct vortex_private *)dev->priv;
diff -u --recursive --new-file v2.1.35/linux/drivers/net/8390.c linux/drivers/net/8390.c
--- v2.1.35/linux/drivers/net/8390.c	Fri Apr  4 08:52:20 1997
+++ linux/drivers/net/8390.c	Tue Apr 22 22:42:48 1997
@@ -58,6 +58,7 @@
 #include <linux/fcntl.h>
 #include <linux/in.h>
 #include <linux/interrupt.h>
+#include <linux/init.h>
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -771,7 +772,7 @@
 }
 
 /* Initialize the rest of the 8390 device structure. */
-int ethdev_init(struct device *dev)
+__initfunc(int ethdev_init(struct device *dev))
 {
     if (ei_debug > 1)
 		printk(version);
diff -u --recursive --new-file v2.1.35/linux/drivers/net/Config.in linux/drivers/net/Config.in
--- v2.1.35/linux/drivers/net/Config.in	Sun Apr 13 10:18:21 1997
+++ linux/drivers/net/Config.in	Tue Apr 15 21:47:23 1997
@@ -73,7 +73,7 @@
     if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
       tristate 'Ansel Communications EISA 3200 support (EXPERIMENTAL)' CONFIG_AC3200
     fi
-    
+
     tristate 'Apricot Xen-II on board ethernet' CONFIG_APRICOT
     tristate 'CS89x0 support' CONFIG_CS89x0
     tristate 'Generic DECchip & DIGITAL EtherWORKS PCI/EISA' CONFIG_DE4X5
diff -u --recursive --new-file v2.1.35/linux/drivers/net/Space.c linux/drivers/net/Space.c
--- v2.1.35/linux/drivers/net/Space.c	Sun Apr 13 10:18:21 1997
+++ linux/drivers/net/Space.c	Thu Apr 17 13:20:45 1997
@@ -30,6 +30,7 @@
 #include <linux/config.h>
 #include <linux/netdevice.h>
 #include <linux/errno.h>
+#include <linux/init.h>
 
 #define	NEXT_DEV	NULL
 
@@ -93,7 +94,7 @@
 extern int de600_probe(struct device *);
 extern int de620_probe(struct device *);
 
-static int ethif_probe(struct device *dev)
+__initfunc(static int ethif_probe(struct device *dev))
 {
     u_long base_addr = dev->base_addr;
 
diff -u --recursive --new-file v2.1.35/linux/drivers/net/a2065.c linux/drivers/net/a2065.c
--- v2.1.35/linux/drivers/net/a2065.c	Fri Apr  4 08:52:20 1997
+++ linux/drivers/net/a2065.c	Tue Apr 22 22:42:48 1997
@@ -47,6 +47,7 @@
 #include <linux/malloc.h>
 #include <linux/string.h>
 #include <linux/config.h>
+#include <linux/init.h>
 
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -55,7 +56,7 @@
 
 #include <asm/amigaints.h>
 #include <asm/amigahw.h>
-#include <asm/zorro.h>
+#include <linux/zorro.h>
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -302,14 +303,16 @@
 			lp->stats.rx_errors++;
 			continue;
 		} else if (bits & LE_R1_ERR) {
-			/* Count only the end frame as a tx error, not the beginning */
+			/* Count only the end frame as a rx error,
+			 * not the beginning
+			 */
 			if (bits & LE_R1_BUF) lp->stats.rx_fifo_errors++;
 			if (bits & LE_R1_CRC) lp->stats.rx_crc_errors++;
 			if (bits & LE_R1_OFL) lp->stats.rx_over_errors++;
 			if (bits & LE_R1_FRA) lp->stats.rx_frame_errors++;
 			if (bits & LE_R1_EOP) lp->stats.rx_errors++;
 		} else {
-			len = rd->mblength;
+			len = (rd->mblength & 0xfff) - 4;
 			skb = dev_alloc_skb (len+2);
 
 			if (skb == 0) {
@@ -582,6 +585,16 @@
 		return status;
 	}
 
+	if (skb == NULL) {
+		dev_tint (dev);
+		printk ("skb is NULL\n");
+		return 0;
+	}
+
+	if (skb->len <= 0) {
+		printk ("skb len is %d\n", skb->len);
+		return 0;
+	}
 	/* Block a timer-based transmit from overlapping. */
 #ifdef OLD_METHOD
 	dev->tbusy = 1;
@@ -698,18 +711,13 @@
 	struct lance_private *lp = (struct lance_private *) dev->priv;
 	volatile struct lance_init_block *ib = lp->init_block;
 	volatile struct lance_regs *ll = lp->ll;
-	char shown;
 
-	shown = 0;
 	while (dev->tbusy)
-		if (!shown++)
-			printk ("Waiting for tbusy to go down\n");
+		schedule();
 	set_bit (0, (void *) &dev->tbusy);
 
-	shown = 0;
 	while (lp->tx_old != lp->tx_new)
-		if (!shown)
-			printk ("Waiting for buffer to empty\n");
+		schedule();
 
 	ll->rap = LE_CSR0;
 	ll->rdp = LE_C0_STOP;
@@ -727,7 +735,7 @@
 }
 
 
-int a2065_probe(struct device *dev)
+__initfunc(int a2065_probe(struct device *dev))
 {
 	int key1, key2 = 0;
 	struct ConfigDev *cd;
diff -u --recursive --new-file v2.1.35/linux/drivers/net/ac3200.c linux/drivers/net/ac3200.c
--- v2.1.35/linux/drivers/net/ac3200.c	Tue Dec 31 00:29:59 1996
+++ linux/drivers/net/ac3200.c	Tue Apr 22 22:42:48 1997
@@ -25,6 +25,7 @@
 #include <linux/string.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
+#include <linux/init.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
@@ -54,7 +55,7 @@
 								 */
 
 /* Decoding of the configuration register. */
-static unsigned char config2irqmap[8] = {15, 12, 11, 10, 9, 7, 5, 3};
+static unsigned char config2irqmap[8] __initdata = {15, 12, 11, 10, 9, 7, 5, 3};
 static int addrmap[8] =
 {0xFF0000, 0xFE0000, 0xFD0000, 0xFFF0000, 0xFFE0000, 0xFFC0000,  0xD0000, 0 };
 static const char *port_name[4] = { "10baseT", "invalid", "AUI", "10base2"};
@@ -88,7 +89,7 @@
 	or the unique value in the station address PROM.
 	*/
 
-int ac3200_probe(struct device *dev)
+__initfunc(int ac3200_probe(struct device *dev))
 {
 	unsigned short ioaddr = dev->base_addr;
 
@@ -111,7 +112,7 @@
 	return ENODEV;
 }
 
-static int ac_probe1(int ioaddr, struct device *dev)
+__initfunc(static int ac_probe1(int ioaddr, struct device *dev))
 {
 	int i;
 
diff -u --recursive --new-file v2.1.35/linux/drivers/net/apricot.c linux/drivers/net/apricot.c
--- v2.1.35/linux/drivers/net/apricot.c	Fri Apr  4 08:52:20 1997
+++ linux/drivers/net/apricot.c	Tue Apr 22 22:42:48 1997
@@ -34,6 +34,7 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
+#include <linux/init.h>
 
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -675,7 +676,7 @@
     printk ("type %2.2X%2.2X\n", (unsigned char)add[12], (unsigned char)add[13]);
 }
 
-int apricot_probe(struct device *dev)
+__initfunc(int apricot_probe(struct device *dev))
 {
     int i;
     struct i596_private *lp;
@@ -1001,7 +1002,7 @@
 }
 
 #ifdef HAVE_DEVLIST
-static unsigned int apricot_portlist[] = {0x300, 0};
+static unsigned int apricot_portlist[] __initdata = {0x300, 0};
 struct netdev_entry apricot_drv =
 {"apricot", apricot_probe, APRICOT_TOTAL_SIZE, apricot_portlist};
 #endif
diff -u --recursive --new-file v2.1.35/linux/drivers/net/arcnet.c linux/drivers/net/arcnet.c
--- v2.1.35/linux/drivers/net/arcnet.c	Fri Apr  4 08:52:20 1997
+++ linux/drivers/net/arcnet.c	Tue Apr 22 22:42:48 1997
@@ -162,6 +162,7 @@
 #include <linux/if_arp.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
+#include <linux/init.h>
 
 #include <asm/system.h>
 #include <asm/bitops.h>
@@ -711,7 +712,7 @@
  * need to be passed a specific shmem address, IRQ, and node ID (stored in
  * dev->base_addr)
  */
-int arcnet_probe(struct device *dev)
+__initfunc(int arcnet_probe(struct device *dev))
 {
 	BUGLVL(D_NORMAL) printk(version);
 	BUGMSG(D_NORMAL,"Compiled for ARCnet RIM I (autoprobe disabled)\n");
@@ -749,11 +750,13 @@
  *
  * FIXME: grab all devices in one shot and eliminate the big static array.
  */
-int arcnet_probe(struct device *dev)
+
+static int ports[(0x3f0 - 0x200) / 16 + 1] __initdata;
+static u_long shmems[(0xFF800 - 0xA0000) / 2048 + 1] __initdata;
+
+__initfunc(int arcnet_probe(struct device *dev))
 {
 	static int init_once = 0;
-	static int ports[(0x3f0 - 0x200) / 16 + 1];
-	static u_long shmems[(0xFF800 - 0xA0000) / 2048 + 1];
 	static int numports=sizeof(ports)/sizeof(ports[0]),
 	    	   numshmems=sizeof(shmems)/sizeof(shmems[0]);
 
@@ -1126,7 +1129,7 @@
 /* Set up the struct device associated with this card.  Called after
  * probing succeeds.
  */
-int arcnet_found(struct device *dev,int port,int airq, u_long shmem)
+__initfunc(int arcnet_found(struct device *dev,int port,int airq, u_long shmem))
 {
 	u_long first_mirror,last_mirror;
 	struct arcnet_local *lp;
diff -u --recursive --new-file v2.1.35/linux/drivers/net/ariadne.c linux/drivers/net/ariadne.c
--- v2.1.35/linux/drivers/net/ariadne.c	Fri Apr  4 08:52:20 1997
+++ linux/drivers/net/ariadne.c	Tue Apr 22 22:42:48 1997
@@ -49,11 +49,12 @@
 #include <linux/etherdevice.h>
 #include <linux/interrupt.h>
 #include <linux/skbuff.h>
+#include <linux/init.h>
 
 #include <asm/bitops.h>
 #include <asm/amigaints.h>
 #include <asm/amigahw.h>
-#include <asm/zorro.h>
+#include <linux/zorro.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 
@@ -145,7 +146,7 @@
 }
 
 
-int ariadne_probe(struct device *dev)
+__initfunc(int ariadne_probe(struct device *dev))
 {
     int key;
     struct ConfigDev *cd;
@@ -365,7 +366,7 @@
     if (ariadne_debug > 1) {
 	printk("%s: Shutting down ethercard, status was %2.2x.\n", dev->name,
 	       board->Lance.RDP);
-	printk("%s: %d packets missed\n", dev->name,
+	printk("%s: %lu packets missed\n", dev->name,
 	       priv->stats.rx_missed_errors);
     }
 
diff -u --recursive --new-file v2.1.35/linux/drivers/net/at1700.c linux/drivers/net/at1700.c
--- v2.1.35/linux/drivers/net/at1700.c	Fri Apr  4 08:52:20 1997
+++ linux/drivers/net/at1700.c	Tue Apr 22 22:42:48 1997
@@ -48,13 +48,14 @@
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <linux/errno.h>
+#include <linux/init.h>
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 
 /* This unusual address order is used to verify the CONFIG register. */
-static int at1700_probe_list[] =
+static int at1700_probe_list[] __initdata =
 {0x260, 0x280, 0x2a0, 0x240, 0x340, 0x320, 0x380, 0x300, 0};
 
 /* use 0 for production, 1 for verification, >2 for debug */
@@ -136,8 +137,8 @@
 struct netdev_entry at1700_drv =
 {"at1700", at1700_probe1, AT1700_IO_EXTENT, at1700_probe_list};
 #else
-int
-at1700_probe(struct device *dev)
+__initfunc(int
+at1700_probe(struct device *dev))
 {
 	int i;
 	int base_addr = dev ? dev->base_addr : 0;
@@ -167,7 +168,7 @@
    that can be done is checking a few bits and then diving right into an
    EEPROM read. */
 
-int at1700_probe1(struct device *dev, short ioaddr)
+__initfunc(int at1700_probe1(struct device *dev, short ioaddr))
 {
 	char irqmap[8] = {3, 4, 5, 9, 10, 11, 14, 15};
 	unsigned int i, irq;
@@ -275,7 +276,7 @@
 	return 0;
 }
 
-static int read_eeprom(int ioaddr, int location)
+__initfunc(static int read_eeprom(int ioaddr, int location))
 {
 	int i;
 	unsigned short retval = 0;
diff -u --recursive --new-file v2.1.35/linux/drivers/net/atari_bionet.c linux/drivers/net/atari_bionet.c
--- v2.1.35/linux/drivers/net/atari_bionet.c	Fri Apr  4 08:52:20 1997
+++ linux/drivers/net/atari_bionet.c	Tue Apr 22 22:42:48 1997
@@ -80,12 +80,7 @@
 static char *version =
 	"bionet.c:v1.0 06-feb-96 (c) Hartmut Laue.\n";
 
-#ifdef MODULE
 #include <linux/module.h>
-#else
-#define MOD_INC_USE_COUNT
-#define MOD_DEC_USE_COUNT
-#endif
 
 #include <linux/errno.h>
 #include <linux/kernel.h>
@@ -100,6 +95,7 @@
 #include <linux/string.h>
 #include <linux/delay.h>
 #include <linux/timer.h>
+#include <linux/init.h>
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -326,8 +322,8 @@
 
 /* Check for a network adaptor of this type, and return '0' if one exists.
  */
-int
-bionet_probe(struct device *dev) {
+__initfunc(int
+bionet_probe(struct device *dev)) {
 	unsigned char station_addr[6];
 	static unsigned version_printed = 0;
 	static int no_more_found = 0; /* avoid "Probing for..." printed 4 times */
@@ -596,22 +592,13 @@
 
 #ifdef MODULE
 
-#include <linux/version.h>
-
-/* We should include the kernel identification string in the module.
- */
-static char kernel_version[] = UTS_RELEASE;
-
-#undef	NEXT_DEV
-#define NEXT_DEV	(&bio_dev)
-
 static char bio_name[16];
 static struct device bio_dev =
 	{
 		bio_name,	/* filled in by register_netdev() */
 		0, 0, 0, 0,	/* memory */
 		0, 0,		/* base, irq */
-		0, 0, 0, NEXT_DEV, bionet_probe,
+		0, 0, 0, NULL, bionet_probe,
 	};
 
 int
diff -u --recursive --new-file v2.1.35/linux/drivers/net/atari_pamsnet.c linux/drivers/net/atari_pamsnet.c
--- v2.1.35/linux/drivers/net/atari_pamsnet.c	Fri Apr  4 08:52:20 1997
+++ linux/drivers/net/atari_pamsnet.c	Tue Apr 22 22:42:48 1997
@@ -77,12 +77,7 @@
 static char *version =
 	"pamsnet.c:v0.2beta 30-mar-96 (c) Torsten Lang.\n";
 
-#ifdef MODULE
 #include <linux/module.h>
-#else
-#define MOD_INC_USE_COUNT
-#define MOD_DEC_USE_COUNT
-#endif
 
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -107,6 +102,7 @@
 
 #include <linux/delay.h>
 #include <linux/timer.h>
+#include <linux/init.h>
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -565,8 +561,8 @@
 /* Check for a network adaptor of this type, and return '0' if one exists.
  */
 
-extern int
-pamsnet_probe (dev)
+__initfunc(extern int
+pamsnet_probe (dev))
 	struct device *dev;
 {
 	int i;
@@ -868,21 +864,12 @@
 
 #ifdef MODULE
 
-#include <linux/version.h>
-
-/* We should include the kernel identification string in the module.
- */
-static char kernel_version[] = UTS_RELEASE;
-
-#undef	NEXT_DEV
-#define NEXT_DEV	(&pam_dev)
-
 static struct device pam_dev =
 	{
 		"        ",	/* filled in by register_netdev() */
 		0, 0, 0, 0,	/* memory */
 		0, 0,		/* base, irq */
-		0, 0, 0, NEXT_DEV, pamsnet_probe,
+		0, 0, 0, NULL, pamsnet_probe,
 	};
 
 int
diff -u --recursive --new-file v2.1.35/linux/drivers/net/atarilance.c linux/drivers/net/atarilance.c
--- v2.1.35/linux/drivers/net/atarilance.c	Sun Feb  2 05:18:36 1997
+++ linux/drivers/net/atarilance.c	Tue Apr 22 22:42:48 1997
@@ -55,6 +55,7 @@
 #include <linux/errno.h>
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
+#include <linux/init.h>
 
 #include <asm/setup.h>
 #include <asm/irq.h>
@@ -369,7 +370,7 @@
 }
 
 
-int atarilance_probe( struct device *dev )
+__initfunc(int atarilance_probe( struct device *dev ))
 
 {	int i;
 	static int found = 0;
@@ -392,7 +393,7 @@
 
 /* Derived from hwreg_present() in atari/config.c: */
 
-static int addr_accessible( volatile void *regp, int wordflag, int writeflag )
+__initfunc(static int addr_accessible( volatile void *regp, int wordflag, int writeflag ))
 
 {	int		ret;
 	long	flags;
@@ -442,8 +443,8 @@
 }
 
 
-static unsigned long lance_probe1( struct device *dev,
-								   struct lance_addr *init_rec )
+__initfunc(static unsigned long lance_probe1( struct device *dev,
+								   struct lance_addr *init_rec ))
 
 {	volatile unsigned short *memaddr =
 		(volatile unsigned short *)init_rec->memaddr;
diff -u --recursive --new-file v2.1.35/linux/drivers/net/atp.c linux/drivers/net/atp.c
--- v2.1.35/linux/drivers/net/atp.c	Fri Apr  4 08:52:20 1997
+++ linux/drivers/net/atp.c	Tue Apr 22 22:42:48 1997
@@ -96,6 +96,7 @@
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <linux/errno.h>
+#include <linux/init.h>
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -149,8 +150,8 @@
    If dev->base_addr == 2, allocate space for the device and return success
    (detachable devices only).
    */
-int
-atp_init(struct device *dev)
+__initfunc(int
+atp_init(struct device *dev))
 {
 	int *port, ports[] = {0x378, 0x278, 0x3bc, 0};
 	int base_addr = dev->base_addr;
@@ -172,7 +173,7 @@
 	return ENODEV;
 }
 
-static int atp_probe1(struct device *dev, short ioaddr)
+__initfunc(static int atp_probe1(struct device *dev, short ioaddr))
 {
 	int saved_ctrl_reg, status;
 
@@ -258,7 +259,7 @@
 }
 
 /* Read the station address PROM, usually a word-wide EEPROM. */
-static void get_node_ID(struct device *dev)
+__initfunc(static void get_node_ID(struct device *dev))
 {
 	short ioaddr = dev->base_addr;
 	int sa_offset = 0;
@@ -290,7 +291,7 @@
  * DO :	 _________X_______X
  */
 
-static unsigned short eeprom_op(short ioaddr, unsigned int cmd)
+__initfunc(static unsigned short eeprom_op(short ioaddr, unsigned int cmd))
 {
 	unsigned eedata_out = 0;
 	int num_bits = EE_CMD_SIZE;
diff -u --recursive --new-file v2.1.35/linux/drivers/net/baycom.c linux/drivers/net/baycom.c
--- v2.1.35/linux/drivers/net/baycom.c	Thu Feb 27 10:57:30 1997
+++ linux/drivers/net/baycom.c	Tue Apr 22 22:42:48 1997
@@ -89,6 +89,7 @@
 #include <linux/netdevice.h>
 #include <linux/hdlcdrv.h>
 #include <linux/baycom.h>
+#include <linux/init.h>
 
 /* --------------------------------------------------------------------- */
 
@@ -936,7 +937,7 @@
 
 /* --------------------------------------------------------------------- */
 
-int baycom_init(void)
+__initfunc(int baycom_init(void))
 {
 	int i, j, found = 0;
 	char set_hw = 1;
@@ -1038,7 +1039,7 @@
  * * indicates sofware DCD
  */
 
-void baycom_setup(char *str, int *ints)
+__initfunc(void baycom_setup(char *str, int *ints))
 {
 	int i;
 
diff -u --recursive --new-file v2.1.35/linux/drivers/net/bpqether.c linux/drivers/net/bpqether.c
--- v2.1.35/linux/drivers/net/bpqether.c	Fri Apr  4 08:52:20 1997
+++ linux/drivers/net/bpqether.c	Tue Apr 22 22:42:48 1997
@@ -82,6 +82,7 @@
 #include <linux/firewall.h>
 #include <linux/module.h>
 #include <linux/net_alias.h>
+#include <linux/init.h>
 
 #include <net/ip.h>
 #include <net/arp.h>
@@ -632,7 +633,7 @@
  * Initialize driver. To be called from af_ax25 if not compiled as a
  * module
  */
-int bpq_init(void)
+__initfunc(int bpq_init(void))
 {
 	struct device *dev;
 
diff -u --recursive --new-file v2.1.35/linux/drivers/net/cs89x0.c linux/drivers/net/cs89x0.c
--- v2.1.35/linux/drivers/net/cs89x0.c	Mon Apr  7 11:35:29 1997
+++ linux/drivers/net/cs89x0.c	Tue Apr 22 22:42:48 1997
@@ -78,6 +78,7 @@
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <linux/errno.h>
+#include <linux/init.h>
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -86,7 +87,7 @@
 
 /* First, a few definitions that the brave might change. */
 /* A zero-terminated list of I/O addresses to be probed. */
-static unsigned int netcard_portlist[] =
+static unsigned int netcard_portlist[] __initdata =
    { 0x300, 0x320, 0x340, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 0};
 
 static unsigned int net_debug = NET_DEBUG;
@@ -145,8 +146,8 @@
 struct netdev_entry netcard_drv =
 {"netcard", cs89x0_probe1, NETCARD_IO_EXTENT, netcard_portlist};
 #else
-int
-cs89x0_probe(struct device *dev)
+__initfunc(int
+cs89x0_probe(struct device *dev))
 {
 	int i;
 	int base_addr = dev ? dev->base_addr : 0;
@@ -195,8 +196,8 @@
 	outw(value, dev->base_addr + portno);
 }
 
-static int
-wait_eeprom_ready(struct device *dev)
+__initfunc(static int
+wait_eeprom_ready(struct device *dev))
 {
 	int timeout = jiffies;
 	/* check to see if the EEPROM is ready, a timeout is used -
@@ -208,8 +209,8 @@
 	return 0;
 }
 
-int
-get_eeprom_data(struct device *dev, int off, int len, int *buffer)
+__initfunc(static int
+get_eeprom_data(struct device *dev, int off, int len, int *buffer))
 {
 	int i;
 
@@ -226,8 +227,8 @@
         return 0;
 }
 
-int
-get_eeprom_cksum(int off, int len, int *buffer)
+__initfunc(static int
+get_eeprom_cksum(int off, int len, int *buffer))
 {
 	int i, cksum;
 
@@ -244,7 +245,7 @@
    probes on the ISA bus.  A good device probes avoids doing writes, and
    verifies that the correct device exists and functions.  */
 
-static int cs89x0_probe1(struct device *dev, int ioaddr)
+__initfunc(static int cs89x0_probe1(struct device *dev, int ioaddr))
 {
 	struct net_local *lp;
 	static unsigned version_printed = 0;
@@ -392,8 +393,8 @@
 
 
 
-void
-reset_chip(struct device *dev)
+__initfunc(void
+reset_chip(struct device *dev))
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	int ioaddr = dev->base_addr;
diff -u --recursive --new-file v2.1.35/linux/drivers/net/de4x5.c linux/drivers/net/de4x5.c
--- v2.1.35/linux/drivers/net/de4x5.c	Mon Apr  7 11:35:29 1997
+++ linux/drivers/net/de4x5.c	Tue Apr 22 22:42:48 1997
@@ -266,6 +266,7 @@
 #include <linux/bios32.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
+#include <linux/init.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/dma.h>
@@ -861,8 +862,8 @@
 ** more info. Until I fix (un)register_netdevice() we won't be able to use it
 ** though.
 */
-int
-de4x5_probe(struct device *dev)
+__initfunc(int
+de4x5_probe(struct device *dev))
 {
     int status = -ENODEV;
     u_long iobase = dev->base_addr;
@@ -882,8 +883,8 @@
     return status;
 }
 
-static int
-de4x5_hw_init(struct device *dev, u_long iobase)
+__initfunc(static int
+de4x5_hw_init(struct device *dev, u_long iobase))
 {
     struct bus_type *lp = &bus;
     int i, status=0;
@@ -1797,8 +1798,8 @@
 ** EISA bus I/O device probe. Probe from slot 1 since slot 0 is usually
 ** the motherboard. Upto 15 EISA devices are supported.
 */
-static void
-eisa_probe(struct device *dev, u_long ioaddr)
+__initfunc(static void
+eisa_probe(struct device *dev, u_long ioaddr))
 {
     int i, maxSlots, status, device;
     u_short vendor;
@@ -1874,8 +1875,8 @@
 #define PCI_DEVICE    (dev_num << 3)
 #define PCI_LAST_DEV  32
 
-static void
-pci_probe(struct device *dev, u_long ioaddr)
+__initfunc(static void
+pci_probe(struct device *dev, u_long ioaddr))
 {
     u_char irq;
     u_char pb, pbus, dev_num, dnum, dev_fn;
@@ -1974,8 +1975,8 @@
 ** are not available then insert a new device structure at the end of
 ** the current list.
 */
-static struct device *
-alloc_device(struct device *dev, u_long iobase)
+__initfunc(static struct device *
+alloc_device(struct device *dev, u_long iobase))
 {
     struct device *adev = NULL;
     int fixed = 0, new_dev = 0;
@@ -2027,8 +2028,8 @@
 ** If at end of eth device list and can't use current entry, malloc
 ** one up. If memory could not be allocated, print an error message.
 */
-static struct device *
-insert_device(struct device *dev, u_long iobase, int (*init)(struct device *))
+__initfunc(static struct device *
+insert_device(struct device *dev, u_long iobase, int (*init)(struct device *)))
 {
     struct device *new;
 
@@ -2055,8 +2056,8 @@
     return new;
 }
 
-static int
-de4x5_dev_index(char *s)
+__initfunc(static int
+de4x5_dev_index(char *s))
 {
     int i=0, j=0;
 
@@ -2070,8 +2071,8 @@
     return i;
 }
 
-static void
-link_modules(struct device *dev, struct device *tmp)
+__initfunc(static void
+link_modules(struct device *dev, struct device *tmp))
 {
     struct device *p=dev;
 
diff -u --recursive --new-file v2.1.35/linux/drivers/net/de600.c linux/drivers/net/de600.c
--- v2.1.35/linux/drivers/net/de600.c	Mon Apr 14 16:28:11 1997
+++ linux/drivers/net/de600.c	Tue Apr 22 22:42:48 1997
@@ -103,6 +103,7 @@
 #include <linux/ptrace.h>
 #include <asm/system.h>
 #include <linux/errno.h>
+#include <linux/init.h>
 
 #include <linux/inet.h>
 #include <linux/netdevice.h>
@@ -624,8 +625,8 @@
 	 */
 }
 
-int
-de600_probe(struct device *dev)
+__initfunc(int
+de600_probe(struct device *dev))
 {
 	int	i;
 	static struct net_device_stats de600_netstats;
diff -u --recursive --new-file v2.1.35/linux/drivers/net/de620.c linux/drivers/net/de620.c
--- v2.1.35/linux/drivers/net/de620.c	Fri Apr  4 08:52:20 1997
+++ linux/drivers/net/de620.c	Tue Apr 22 22:42:48 1997
@@ -131,6 +131,7 @@
 #include <linux/ptrace.h>
 #include <asm/system.h>
 #include <linux/errno.h>
+#include <linux/init.h>
 
 #include <linux/inet.h>
 #include <linux/netdevice.h>
@@ -822,8 +823,8 @@
  *
  * Check if there is a DE-620 connected
  */
-int
-de620_probe(struct device *dev)
+__initfunc(int
+de620_probe(struct device *dev))
 {
 	static struct net_device_stats de620_netstats;
 	int i;
@@ -915,8 +916,8 @@
  */
 #define sendit(dev,data) de620_set_register(dev, W_EIP, data | EIPRegister);
 
-static unsigned short
-ReadAWord(struct device *dev, int from)
+__initfunc(static unsigned short
+ReadAWord(struct device *dev, int from))
 {
 	unsigned short data;
 	int nbits;
@@ -958,8 +959,8 @@
 	return data;
 }
 
-static int
-read_eeprom(struct device *dev)
+__initfunc(static int
+read_eeprom(struct device *dev))
 {
 	unsigned short wrd;
 
diff -u --recursive --new-file v2.1.35/linux/drivers/net/defxx.c linux/drivers/net/defxx.c
--- v2.1.35/linux/drivers/net/defxx.c	Sun Feb  2 05:18:39 1997
+++ linux/drivers/net/defxx.c	Tue Apr 22 22:42:48 1997
@@ -215,6 +215,7 @@
 #include <linux/pci.h>
 #include <linux/bios32.h>
 #include <linux/delay.h>
+#include <linux/init.h>
 #include <asm/byteorder.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -437,9 +438,9 @@
  *   the device structure.
  */
 
-int dfx_probe(
+__initfunc(int dfx_probe(
 	struct device *dev
-	)
+	))
 
 	{
 	int				i;				/* used in for loops */
@@ -636,10 +637,10 @@
  *   None
  */
 
-struct device *dfx_alloc_device(
+__initfunc(struct device *dfx_alloc_device(
 	struct device	*dev,
 	u16				iobase
-	)
+	))
 
 	{
 	struct device *tmp_dev;		/* pointer to a device structure */
@@ -731,9 +732,9 @@
  *   enabled yet.
  */
 
-void dfx_bus_init(
+__initfunc(void dfx_bus_init(
 	struct device *dev
-	)
+	))
 
 	{
 	DFX_board_t *bp = (DFX_board_t *)dev->priv;
@@ -865,9 +866,9 @@
  *   None
  */
 
-void dfx_bus_config_check(
+__initfunc(void dfx_bus_config_check(
 	DFX_board_t *bp
-	)
+	))
 
 	{
 	int	status;				/* return code from adapter port control call */
@@ -969,9 +970,9 @@
  *   returning from this routine.
  */
 
-int dfx_driver_init(
+__initfunc(int dfx_driver_init(
 	struct device *dev
-	)
+	))
 
 	{
 	DFX_board_t *bp = (DFX_board_t *)dev->priv;
diff -u --recursive --new-file v2.1.35/linux/drivers/net/depca.c linux/drivers/net/depca.c
--- v2.1.35/linux/drivers/net/depca.c	Sun Feb  2 05:18:39 1997
+++ linux/drivers/net/depca.c	Tue Apr 22 22:42:48 1997
@@ -219,6 +219,7 @@
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
+#include <linux/init.h>
 #include <asm/uaccess.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -418,9 +419,9 @@
 void          cleanup_module(void);
 static int    autoprobed = 1, loading_module = 1;
 # else
-static u_char de1xx_irq[] = {2,3,4,5,7,9,0};
-static u_char de2xx_irq[] = {5,9,10,11,15,0};
-static u_char de422_irq[] = {5,9,10,11,0};
+static u_char de1xx_irq[] __initdata = {2,3,4,5,7,9,0};
+static u_char de2xx_irq[] __initdata = {5,9,10,11,15,0};
+static u_char de422_irq[] __initdata = {5,9,10,11,0};
 static u_char *depca_irq;
 static int    autoprobed = 0, loading_module = 0;
 #endif /* MODULE */
@@ -441,7 +442,7 @@
 
 
 
-int depca_probe(struct device *dev)
+__initfunc(int depca_probe(struct device *dev))
 {
   int tmp = num_depcas, status = -ENODEV;
   u_long iobase = dev->base_addr;
@@ -471,8 +472,8 @@
   return status;
 }
 
-static int
-depca_hw_init(struct device *dev, u_long ioaddr)
+__initfunc(static int
+depca_hw_init(struct device *dev, u_long ioaddr))
 {
   struct depca_private *lp;
   int i, j, offset, netRAM, mem_len, status=0;
@@ -1207,7 +1208,7 @@
 /*
 ** ISA bus I/O device probe
 */
-static void isa_probe(struct device *dev, u_long ioaddr)
+__initfunc(static void isa_probe(struct device *dev, u_long ioaddr))
 {
   int i = num_depcas, maxSlots;
   s32 ports[] = DEPCA_IO_PORTS;
@@ -1245,7 +1246,7 @@
 ** EISA bus I/O device probe. Probe from slot 1 since slot 0 is usually
 ** the motherboard. Upto 15 EISA devices are supported.
 */
-static void eisa_probe(struct device *dev, u_long ioaddr)
+__initfunc(static void eisa_probe(struct device *dev, u_long ioaddr))
 {
   int i, maxSlots;
   u_long iobase;
@@ -1291,8 +1292,8 @@
 ** are not available then insert a new device structure at the end of
 ** the current list.
 */
-static struct device *
-alloc_device(struct device *dev, u_long iobase)
+__initfunc(static struct device *
+alloc_device(struct device *dev, u_long iobase))
 {
     struct device *adev = NULL;
     int fixed = 0, new_dev = 0;
@@ -1336,8 +1337,8 @@
 ** If at end of eth device list and can't use current entry, malloc
 ** one up. If memory could not be allocated, print an error message.
 */
-static struct device *
-insert_device(struct device *dev, u_long iobase, int (*init)(struct device *))
+__initfunc(static struct device *
+insert_device(struct device *dev, u_long iobase, int (*init)(struct device *)))
 {
     struct device *new;
 
@@ -1362,8 +1363,8 @@
     return dev;
 }
 
-static int
-depca_dev_index(char *s)
+__initfunc(static int
+depca_dev_index(char *s))
 {
     int i=0, j=0;
 
@@ -1382,7 +1383,7 @@
 ** and Boot (readb) ROM. This will also give us a clue to the network RAM
 ** base address.
 */
-static void DepcaSignature(char *name, u_long paddr)
+__initfunc(static void DepcaSignature(char *name, u_long paddr))
 {
   u_int i,j,k;
   const char *signatures[] = DEPCA_SIGNATURE;
@@ -1434,7 +1435,7 @@
 ** PROM address counter is correctly positioned at the start of the
 ** ethernet address for later read out.
 */
-static int DevicePresent(u_long ioaddr)
+__initfunc(static int DevicePresent(u_long ioaddr))
 {
   union {
     struct {
@@ -1486,7 +1487,7 @@
 ** reason: access the upper half of the PROM with x=0; access the lower half
 ** with x=1.
 */
-static int get_hw_addr(struct device *dev)
+__initfunc(static int get_hw_addr(struct device *dev))
 {
   u_long ioaddr = dev->base_addr;
   int i, k, tmp, status = 0;
@@ -1574,7 +1575,7 @@
 /*
 ** Look for a particular board name in the EISA configuration space
 */
-static int EISA_signature(char *name, s32 eisa_id)
+__initfunc(static int EISA_signature(char *name, s32 eisa_id))
 {
   u_int i;
   const char *signatures[] = DEPCA_SIGNATURE;
diff -u --recursive --new-file v2.1.35/linux/drivers/net/dgrs.c linux/drivers/net/dgrs.c
--- v2.1.35/linux/drivers/net/dgrs.c	Mon Feb  3 03:05:51 1997
+++ linux/drivers/net/dgrs.c	Tue Apr 22 22:42:49 1997
@@ -88,6 +88,7 @@
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/bios32.h>
+#include <linux/init.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/byteorder.h>
@@ -990,8 +991,8 @@
 /*
  *	Download the board firmware
  */
-static int
-dgrs_download(struct device *dev0)
+__initfunc(static int
+dgrs_download(struct device *dev0))
 {
 	DGRS_PRIV	*priv0 = (DGRS_PRIV *) dev0->priv;
 	int		is;
@@ -1149,8 +1150,8 @@
 /*
  *	Probe (init) a board
  */
-int
-dgrs_probe1(struct device *dev)
+__initfunc(int
+dgrs_probe1(struct device *dev))
 {
 	DGRS_PRIV	*priv = (DGRS_PRIV *) dev->priv;
 	int		i;
@@ -1223,8 +1224,8 @@
 	return (0);
 }
 
-int
-dgrs_initclone(struct device *dev)
+__initfunc(int
+dgrs_initclone(struct device *dev))
 {
 	DGRS_PRIV	*priv = (DGRS_PRIV *) dev->priv;
 	int		i;
@@ -1238,7 +1239,7 @@
 	return (0);
 }
 
-static int
+__initfunc(static int
 dgrs_found_device(
 	struct device	*dev,
 	int		io,
@@ -1246,7 +1247,7 @@
 	int		irq,
 	ulong		plxreg,
 	ulong		plxdma
-)
+))
 {
 	DGRS_PRIV	*priv;
 	int		i;
@@ -1357,8 +1358,8 @@
 /*
  *	Scan for all boards
  */
-static int
-dgrs_scan(struct device *dev)
+__initfunc(static int
+dgrs_scan(struct device *dev))
 {
 	int	cards_found = 0;
 	uint	io;
@@ -1462,7 +1463,7 @@
 	 */
 	if (EISA_bus)
 	{
-		static int      is2iv[8] = { 0, 3, 5, 7, 10, 11, 12, 15 };
+		static int      is2iv[8] __initdata = { 0, 3, 5, 7, 10, 11, 12, 15 };
 
 		for (io = 0x1000; io < 0x9000; io += 0x1000)
 		{
@@ -1600,8 +1601,8 @@
 
 #else
 
-int
-dgrs_probe(struct device *dev)
+__initfunc(int
+dgrs_probe(struct device *dev))
 {
 	int	cards_found;
 
diff -u --recursive --new-file v2.1.35/linux/drivers/net/dgrs_firmware.c linux/drivers/net/dgrs_firmware.c
--- v2.1.35/linux/drivers/net/dgrs_firmware.c	Sat Dec 21 07:23:21 1996
+++ linux/drivers/net/dgrs_firmware.c	Tue Apr 22 22:42:49 1997
@@ -1,7 +1,7 @@
 int dgrs_firmnum = 550;
 char dgrs_firmver[] = "$Version$";
 char dgrs_firmdate[] = "11/16/96 03:45:15";
-unsigned char dgrs_code[] = {
+unsigned char dgrs_code[] __initdata = {
 	213,5,192,8,0,0,0,0,0,0,0,0,
 	0,0,0,0,0,0,0,0,0,0,0,0,
 	0,0,0,0,0,0,0,0,64,40,35,41,
diff -u --recursive --new-file v2.1.35/linux/drivers/net/dlci.c linux/drivers/net/dlci.c
--- v2.1.35/linux/drivers/net/dlci.c	Thu Feb 27 10:57:30 1997
+++ linux/drivers/net/dlci.c	Tue Apr 22 22:42:49 1997
@@ -40,6 +40,7 @@
 #include <linux/in.h>
 #include <linux/malloc.h>
 #include <linux/string.h>
+#include <linux/init.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -606,7 +607,7 @@
 	return(0);
 }
 
-int dlci_setup(void)
+__initfunc(int dlci_setup(void))
 {
 	int i;
 
diff -u --recursive --new-file v2.1.35/linux/drivers/net/dummy.c linux/drivers/net/dummy.c
--- v2.1.35/linux/drivers/net/dummy.c	Fri Apr  4 08:52:20 1997
+++ linux/drivers/net/dummy.c	Tue Apr 22 22:42:49 1997
@@ -42,6 +42,7 @@
 #include <linux/in.h>
 #include <linux/malloc.h>
 #include <linux/string.h>
+#include <linux/init.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -72,7 +73,7 @@
 {
 }
 
-int dummy_init(struct device *dev)
+__initfunc(int dummy_init(struct device *dev))
 {
 	/* Initialize the device structure. */
 	dev->hard_start_xmit	= dummy_xmit;
@@ -115,7 +116,7 @@
 
 #ifdef MODULE
 
-static int dummy_probe(struct device *dev)
+__initfunc(static int dummy_probe(struct device *dev))
 {
 	dummy_init(dev);
 	return 0;
diff -u --recursive --new-file v2.1.35/linux/drivers/net/e2100.c linux/drivers/net/e2100.c
--- v2.1.35/linux/drivers/net/e2100.c	Tue Dec 31 00:30:01 1996
+++ linux/drivers/net/e2100.c	Tue Apr 22 22:42:49 1997
@@ -43,6 +43,7 @@
 #include <linux/ioport.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
+#include <linux/init.h>
 
 #include <asm/io.h>
 #include <asm/system.h>
@@ -115,7 +116,7 @@
 	station address).
  */
 
-int e2100_probe(struct device *dev)
+__initfunc(int e2100_probe(struct device *dev))
 {
 	int *port;
 	int base_addr = dev->base_addr;
@@ -135,7 +136,7 @@
 	return ENODEV;
 }
 
-int e21_probe1(struct device *dev, int ioaddr)
+__initfunc(int e21_probe1(struct device *dev, int ioaddr))
 {
 	int i, status;
 	unsigned char *station_addr = dev->dev_addr;
diff -u --recursive --new-file v2.1.35/linux/drivers/net/eepro.c linux/drivers/net/eepro.c
--- v2.1.35/linux/drivers/net/eepro.c	Fri Apr  4 08:52:20 1997
+++ linux/drivers/net/eepro.c	Tue Apr 22 22:42:49 1997
@@ -101,6 +101,7 @@
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <linux/errno.h>
+#include <linux/init.h>
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -109,7 +110,7 @@
 
 /* First, a few definitions that the brave might change. */
 /* A zero-terminated list of I/O addresses to be probed. */
-static unsigned int eepro_portlist[] =
+static unsigned int eepro_portlist[] __initdata =
    { 0x200, 0x240, 0x280, 0x2C0, 0x300, 0x320, 0x340, 0x360, 0};
 
 /* use 0 for production, 1 for verification, >2 for debug */
@@ -305,8 +306,8 @@
 struct netdev_entry netcard_drv =
 {"eepro", eepro_probe1, EEPRO_IO_EXTENT, eepro_portlist};
 #else
-int
-eepro_probe(struct device *dev)
+__initfunc(int
+eepro_probe(struct device *dev))
 {
 	int i;
 	int base_addr = dev ? dev->base_addr : 0;
@@ -332,7 +333,7 @@
    probes on the ISA bus.  A good device probes avoids doing writes, and
    verifies that the correct device exists and functions.  */
 
-int eepro_probe1(struct device *dev, short ioaddr)
+__initfunc(int eepro_probe1(struct device *dev, short ioaddr))
 {
 	unsigned short station_addr[6], id, counter;
 	int i;
diff -u --recursive --new-file v2.1.35/linux/drivers/net/eepro100.c linux/drivers/net/eepro100.c
--- v2.1.35/linux/drivers/net/eepro100.c	Mon Apr 14 16:28:12 1997
+++ linux/drivers/net/eepro100.c	Tue Apr 22 22:42:49 1997
@@ -55,6 +55,7 @@
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/bios32.h>
+#include <linux/init.h>
 #include <asm/processor.h>		/* Processor type for cache alignment. */
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -458,7 +459,7 @@
 static struct device *root_speedo_dev = NULL;
 #endif
 
-int eepro100_init(struct device *dev)
+__initfunc(int eepro100_init(struct device *dev))
 {
 	int cards_found = 0;
 
@@ -521,7 +522,7 @@
 	return cards_found;
 }
 
-static void speedo_found1(struct device *dev, int ioaddr, int irq, int options)
+__initfunc(static void speedo_found1(struct device *dev, int ioaddr, int irq, int options))
 {
 	static int did_version = 0;			/* Already printed version info. */
 	struct speedo_private *sp;
@@ -714,7 +715,7 @@
 #define EE_READ_CMD		(6 << 6)
 #define EE_ERASE_CMD	(7 << 6)
 
-static int read_eeprom(int ioaddr, int location)
+__initfunc(static int read_eeprom(int ioaddr, int location))
 {
 	int i;
 	unsigned short retval = 0;
@@ -1710,7 +1711,7 @@
 	}
 }
 #else   /* not MODULE */
-int eepro100_probe(struct device *dev)
+__initfunc(int eepro100_probe(struct device *dev))
 {
 	int cards_found = 0;
 
diff -u --recursive --new-file v2.1.35/linux/drivers/net/eexpress.c linux/drivers/net/eexpress.c
--- v2.1.35/linux/drivers/net/eexpress.c	Fri Apr  4 08:52:21 1997
+++ linux/drivers/net/eexpress.c	Thu Apr 17 09:29:32 1997
@@ -4,6 +4,8 @@
  *  based on original code by Donald Becker, with changes by
  *  Alan Cox and Pauline Middelink.
  *
+ * Support for 8-bit mode by Zoltan Szilagyi <zoltans@cs.arizona.edu>
+ *
  * Many modifications, and currently maintained, by
  *  Philip Blundell <Philip.Blundell@pobox.com>
  */
@@ -16,12 +18,6 @@
  * things seem to be getting better slowly.
  */
 
-/* It would be nice to seperate out all the 82586-specific code, so that it
- * could be shared between drivers (as with 8390.c).  But this would be quite
- * a messy job.  The main motivation for doing this would be to bring 3c507
- * support back up to scratch.
- */
-
 /* If your card is confused about what sort of interface it has (eg it
  * persistently reports "10baseT" when none is fitted), running 'SOFTSET /BART'
  * or 'SOFTSET /LISA' from DOS seems to help.
@@ -60,13 +56,28 @@
 
 /* Known bugs:
  *
- * - 8-bit mode is not supported, and makes things go wrong.
- * - Multicast and promiscuous modes are not supported.
  * - The card seems to want to give us two interrupts every time something
  *   happens, where just one would be better.
- * - The statistics may not be getting reported properly.
  */
 
+/*
+ *
+ * Note by Zoltan Szilagyi 10-12-96:
+ *
+ * I've succeeded in eliminating the "CU wedged" messages, and hence the
+ * lockups, which were only occuring with cards running in 8-bit mode ("force
+ * 8-bit operation" in Intel's SoftSet utility). This version of the driver
+ * sets the 82586 and the ASIC to 8-bit mode at startup; it also stops the
+ * CU before submitting a packet for transmission, and then restarts it as soon
+ * as the process of handing the packet is complete. This is definitely an
+ * unnecessary slowdown if the card is running in 16-bit mode; therefore one
+ * should detect 16-bit vs 8-bit mode from the EEPROM settings and act 
+ * accordingly. In 8-bit mode with this bugfix I'm getting about 150 K/s for
+ * ftp's, which is significantly better than I get in DOS, so the overhead of
+ * stopping and restarting the CU with each transmit is not prohibitive in
+ * practice.
+ */
+  
 #include <linux/module.h>
 
 #include <linux/kernel.h>
@@ -104,9 +115,11 @@
 struct net_local
 {
 	struct net_device_stats stats;
+	unsigned long last_tx;       /* jiffies when last transmit started */
 	unsigned long init_time;     /* jiffies when eexp_hw_init586 called */
 	unsigned short rx_first;     /* first rx buf, same as RX_BUF_START */
 	unsigned short rx_last;      /* last rx buf */
+	unsigned short rx_ptr;       /* first rx buf to look at */
 	unsigned short tx_head;      /* next free tx buf */
 	unsigned short tx_reap;      /* first in-use tx buf */
 	unsigned short tx_tail;      /* previous tx buf to tx_head */
@@ -114,11 +127,13 @@
 	unsigned short last_tx_restart;   /* set to tx_link when we
 					     restart the CU */
 	unsigned char started;
-	unsigned char promisc;
 	unsigned short rx_buf_start;
 	unsigned short rx_buf_end;
 	unsigned short num_tx_bufs;
 	unsigned short num_rx_bufs;
+	unsigned char width;         /* 0 for 16bit, 1 for 8bit */
+	unsigned char was_promisc;
+	unsigned char old_mc_count;
 };
 
 /* This is the code and data that is downloaded to the EtherExpress card's
@@ -126,11 +141,6 @@
  */
 
 static unsigned short start_code[] = {
-/* 0xfff6 */
-	0x0000,                 /* set bus to 16 bits */
-	0x0000,0x0000,
-	0x0000,0x0000,          /* address of ISCP (lo,hi) */
-
 /* 0x0000 */
 	0x0001,                 /* ISCP: busy - cleared after reset */
 	0x0008,0x0000,0x0000,   /* offset,address (lo,hi) of SCB */
@@ -144,9 +154,9 @@
 	0x0000,0x0000,          /* pad */
 	0x0000,0x0000,
 
-/* 0x0020 -- start of 82586 CU program */
-#define CONF_LINK 0x0020
-	0x0000,Cmd_Config,
+/* 0x20 -- start of 82586 CU program */
+#define CONF_LINK 0x20
+	0x0000,Cmd_Config,      
 	0x0032,                 /* link to next command */
 	0x080c,                 /* 12 bytes follow : fifo threshold=8 */
 	0x2e40,                 /* don't rx bad frames
@@ -156,27 +166,43 @@
 				 */
 	0x6000,                 /* default backoff method & priority
 				 * interframe spacing = 0x60 */
-	0xf200,                 /* slot time=0x200
+	0xf200,                 /* slot time=0x200 
 				 * max collision retry = 0xf */
-	0x0000,                 /* no HDLC : normal CRC : enable broadcast
+#define CONF_PROMISC  0x2e
+	0x0000,                 /* no HDLC : normal CRC : enable broadcast 
 				 * disable promiscuous/multicast modes */
 	0x003c,                 /* minimum frame length = 60 octets) */
 
-	0x0000,Cmd_INT|Cmd_SetAddr,
+	0x0000,Cmd_SetAddr,
 	0x003e,                 /* link to next command */
+#define CONF_HWADDR  0x38
 	0x0000,0x0000,0x0000,   /* hardware address placed here */
 
-	0x0000,Cmd_TDR,0x0048,
-/* 0x0044 -- TDR result placed here */
-	0x0000, 0x0000,
-
-/* Eventually, a set-multicast will go in here */
+	0x0000,Cmd_MCast,
+	0x0076,                 /* link to next command */
+#define CONF_NR_MULTICAST 0x44
+	0x0000,                 /* number of multicast addresses */
+#define CONF_MULTICAST 0x46
+	0x0000, 0x0000, 0x0000, /* some addresses */
+	0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000,
+
+#define CONF_DIAG_RESULT  0x76
+	0x0000, Cmd_Diag,
+	0x007c,                 /* link to next command */
+
+	0x0000,Cmd_TDR|Cmd_INT,
+	0x0084,
+#define CONF_TDR_RESULT  0x82
+	0x0000,
 
 	0x0000,Cmd_END|Cmd_Nop, /* end of configure sequence */
-	0x0048,
-
-	0x0000
-
+	0x0084                  /* dummy link */
 };
 
 /* maps irq number to EtherExpress magic value */
@@ -213,6 +239,13 @@
 static void eexp_hw_rxinit    (struct device *dev);
 
 static void eexp_hw_init586   (struct device *dev);
+static void eexp_setup_filter (struct device *dev);
+
+static char *eexp_ifmap[]={"AUI", "BNC", "RJ45"};
+enum eexp_iftype {AUI=0, BNC=1, TPE=2};
+
+#define STARTED_RU      2
+#define STARTED_CU      1
 
 /*
  * Primitive hardware access functions.
@@ -270,7 +303,8 @@
 
 int express_probe(struct device *dev)
 {
-	unsigned short *port,ports[] = { 0x0300,0x0270,0x0320,0x0340,0 };
+	unsigned short *port;
+	static unsigned short ports[] = { 0x300,0x310,0x270,0x320,0x340,0 };
 	unsigned short ioaddr = dev->base_addr;
 
 	if (ioaddr&0xfe00)
@@ -302,6 +336,7 @@
 {
 	int irq = dev->irq;
 	unsigned short ioaddr = dev->base_addr;
+	struct net_local *lp = (struct net_local *)dev->priv;
 
 #if NET_DEBUG > 6
 	printk(KERN_DEBUG "%s: eexp_open()\n", dev->name);
@@ -316,8 +351,16 @@
 		return -EAGAIN;
 
 	request_region(ioaddr, EEXP_IO_EXTENT, "EtherExpress");
+	request_region(ioaddr+0x4000, 16, "EtherExpress shadow");
+	request_region(ioaddr+0x8000, 16, "EtherExpress shadow");
+	request_region(ioaddr+0xc000, 16, "EtherExpress shadow");
 	dev->tbusy = 0;
 	dev->interrupt = 0;
+	
+	if (lp->width) {
+		printk("%s: forcing ASIC to 8-bit mode\n", dev->name);
+		outb(inb(dev->base_addr+Config)&~4, dev->base_addr+Config);
+	}
 
 	eexp_hw_init586(dev);
 	dev->start = 1;
@@ -331,6 +374,7 @@
 /*
  * close and disable the interface, leaving the 586 in reset.
  */
+
 static int eexp_close(struct device *dev)
 {
 	unsigned short ioaddr = dev->base_addr;
@@ -464,9 +508,23 @@
 	/* If dev->tbusy is set, all our tx buffers are full but the kernel
 	 * is calling us anyway.  Check that nothing bad is happening.
 	 */
-	if (dev->tbusy)
-		unstick_cu(dev);
-
+	if (dev->tbusy) {
+		int status = scb_status(dev);
+  		unstick_cu(dev);
+		if ((jiffies - lp->last_tx) < HZ)
+			return 1;
+		printk(KERN_INFO "%s: transmit timed out, %s?", dev->name,
+		       (SCB_complete(status)?"lost interrupt":
+			"board on fire"));
+		lp->stats.tx_errors++;
+		dev->tbusy = 0;
+		lp->last_tx = jiffies;
+		if (!SCB_complete(status)) {
+			scb_command(dev, SCB_CUabort);
+			outb(0,dev->base_addr+SIGNAL_CA);
+		}
+	}
+  
 	if (set_bit(0,(void *)&dev->tbusy))
 	{
 		lp->stats.tx_dropped++;
@@ -477,6 +535,8 @@
 			ETH_ZLEN;
 		unsigned short *data = (unsigned short *)buf->data;
 
+		lp->stats.tx_bytes += length;
+
 	        eexp_hw_tx_pio(dev,data,length);
 	}
 	dev_kfree_skb(buf, FREE_WRITE);
@@ -491,11 +551,86 @@
  * check to make sure we've not become wedged.
  */
 
+/*
+ * Handle an EtherExpress interrupt
+ * If we've finished initializing, start the RU and CU up.
+ * If we've already started, reap tx buffers, handle any received packets,
+ * check to make sure we've not become wedged.
+ */
+
+static unsigned short eexp_start_irq(struct device *dev,
+				     unsigned short status)
+{
+	unsigned short ack_cmd = SCB_ack(status);
+	struct net_local *lp = (struct net_local *)dev->priv;
+	unsigned short ioaddr = dev->base_addr;
+	if ((dev->flags & IFF_UP) && !(lp->started & STARTED_CU)) {
+		short diag_status, tdr_status;
+		while (SCB_CUstat(status)==2)
+			status = scb_status(dev);
+#if NET_DEBUG > 4
+		printk("%s: CU went non-active (status %04x)\n",
+		       dev->name, status);
+#endif
+
+		outw(CONF_DIAG_RESULT & ~31, ioaddr + SM_PTR);
+		diag_status = inw(ioaddr + SHADOW(CONF_DIAG_RESULT));
+		if (diag_status & 1<<11) {
+			printk(KERN_WARNING "%s: 82586 failed self-test\n", 
+			       dev->name);
+		} else if (!(diag_status & 1<<13)) {
+			printk(KERN_WARNING "%s: 82586 self-test failed to complete\n", dev->name);
+		}
+
+		outw(CONF_TDR_RESULT & ~31, ioaddr + SM_PTR);
+		tdr_status = inw(ioaddr + SHADOW(CONF_TDR_RESULT));
+		if (tdr_status & (TDR_SHORT|TDR_OPEN)) {
+			printk(KERN_WARNING "%s: TDR reports cable %s at %d tick%s\n", dev->name, (tdr_status & TDR_SHORT)?"short":"broken", tdr_status & TDR_TIME, ((tdr_status & TDR_TIME) != 1) ? "s" : "");
+		} 
+		else if (tdr_status & TDR_XCVRPROBLEM) {
+			printk(KERN_WARNING "%s: TDR reports transceiver problem\n", dev->name);
+		}
+		else if (tdr_status & TDR_LINKOK) {
+#if NET_DEBUG > 4
+			printk(KERN_DEBUG "%s: TDR reports link OK\n", dev->name);
+#endif
+		} else {
+			printk("%s: TDR is ga-ga (status %04x)\n", dev->name,
+			       tdr_status);
+		}
+			
+		lp->started |= STARTED_CU;
+		scb_wrcbl(dev, lp->tx_link);
+		/* if the RU isn't running, start it now */
+		if (!(lp->started & STARTED_RU)) {
+			ack_cmd |= SCB_RUstart;
+			scb_wrrfa(dev, lp->rx_buf_start);
+			lp->rx_ptr = lp->rx_buf_start;
+		}
+		ack_cmd |= SCB_CUstart | 0x2000;
+	}
+
+	if ((dev->flags & IFF_UP) && !(lp->started & STARTED_RU) && SCB_RUstat(status)==4) 
+		lp->started|=STARTED_RU;
+
+	return ack_cmd;
+}
+
+static void eexp_cmd_clear(struct device *dev)
+{
+	unsigned long int oldtime = jiffies;
+	while (scb_rdcmd(dev) && ((jiffies-oldtime)<10));
+	if (scb_rdcmd(dev)) {
+		printk("%s: command didn't clear\n", dev->name);
+	}
+}
+	
 static void eexp_irq(int irq, void *dev_info, struct pt_regs *regs)
 {
 	struct device *dev = irq2dev_map[irq];
 	struct net_local *lp;
 	unsigned short ioaddr,status,ack_cmd;
+	unsigned short old_read_ptr, old_write_ptr;
 
 	if (dev==NULL)
 	{
@@ -507,6 +642,9 @@
 	lp = (struct net_local *)dev->priv;
 	ioaddr = dev->base_addr;
 
+	old_read_ptr = inw(ioaddr+READ_PTR);
+	old_write_ptr = inw(ioaddr+WRITE_PTR);
+
 	outb(SIRQ_dis|irqrmap[irq],ioaddr+SET_IRQ);
 
 	dev->interrupt = 1;
@@ -517,75 +655,73 @@
 	printk(KERN_DEBUG "%s: interrupt (status %x)\n", dev->name, status);
 #endif
 
-	ack_cmd = SCB_ack(status);
+	if (lp->started == (STARTED_CU | STARTED_RU)) {
 
-	if (lp->started==0 && SCB_complete(status))
-	{
-		while (SCB_CUstat(status)==2)
-				status = scb_status(dev);
-#if NET_DEBUG > 4
-		printk(KERN_DEBUG "%s: CU went non-active (status = %08x)\n",
-		       dev->name, status);
-#endif
+		do {
+			eexp_cmd_clear(dev);
 
-		/* now get the TDR status */
-		{
-			short tdr_status;
-			outw(0x40, dev->base_addr + SM_PTR);
-			tdr_status = inw(dev->base_addr + 0x8004);
-			if (tdr_status & TDR_SHORT) {
-					printk(KERN_WARNING "%s: TDR reports cable short at %d tick%s\n", dev->name, tdr_status & TDR_TIME, ((tdr_status & TDR_TIME) != 1) ? "s" : "");
-			}
-			else if (tdr_status & TDR_OPEN) {
-					printk(KERN_WARNING "%s: TDR reports cable broken at %d tick%s\n", dev->name, tdr_status & TDR_TIME, ((tdr_status & TDR_TIME) != 1) ? "s" : "");
-			}
-			else if (tdr_status & TDR_XCVRPROBLEM) {
-					printk(KERN_WARNING "%s: TDR reports transceiver problem\n", dev->name);
-			}
-#if NET_DEBUG > 4
-			else if (tdr_status & TDR_LINKOK) {
-					printk(KERN_DEBUG "%s: TDR reports link OK\n", dev->name);
-			}
-#endif
-		}
+			ack_cmd = SCB_ack(status);
+			scb_command(dev, ack_cmd);
+			outb(0,ioaddr+SIGNAL_CA);
 
-		lp->started=1;
-		scb_wrcbl(dev, lp->tx_link);
-		scb_wrrfa(dev, lp->rx_buf_start);
-		ack_cmd |= SCB_CUstart | SCB_RUstart | 0x2000;
-	}
-	else if (lp->started)
-	{
-		unsigned short txstatus;
-		txstatus = eexp_hw_lasttxstat(dev);
-	}
+			eexp_cmd_clear(dev);
 
-	if (SCB_rxdframe(status))
-	{
-		eexp_hw_rx_pio(dev);
-	}
+			if (SCB_complete(status)) {
+				if (!eexp_hw_lasttxstat(dev)) {
+					printk("%s: tx interrupt but no status\n", dev->name);
+				}
+			}
+			
+			if (SCB_rxdframe(status)) 
+				eexp_hw_rx_pio(dev);
 
-	if ((lp->started&2)!=0 && SCB_RUstat(status)!=4)
-	{
-		printk(KERN_WARNING "%s: RU stopped: status %04x\n",
-			dev->name,status);
-		lp->stats.rx_errors++;
-		eexp_hw_rxinit(dev);
-		scb_wrrfa(dev, lp->rx_buf_start);
-		ack_cmd |= SCB_RUstart;
+			status = scb_status(dev);
+		} while (status & 0xc000);
+
+		if (SCB_RUdead(status)) 
+		{
+			printk(KERN_WARNING "%s: RU stopped: status %04x\n",
+			       dev->name,status);
+#if 0
+			printk(KERN_WARNING "%s: cur_rfd=%04x, cur_rbd=%04x\n", dev->name, lp->cur_rfd, lp->cur_rbd);
+			outw(lp->cur_rfd, ioaddr+READ_PTR);
+			printk(KERN_WARNING "%s: [%04x]\n", dev->name, inw(ioaddr+DATAPORT));
+			outw(lp->cur_rfd+6, ioaddr+READ_PTR);
+			printk(KERN_WARNING "%s: rbd is %04x\n", dev->name, rbd= inw(ioaddr+DATAPORT));
+			outw(rbd, ioaddr+READ_PTR);
+			printk(KERN_WARNING "%s: [%04x %04x] ", dev->name, inw(ioaddr+DATAPORT), inw(ioaddr+DATAPORT));
+			outw(rbd+8, ioaddr+READ_PTR);
+			printk("[%04x]\n", inw(ioaddr+DATAPORT));
+#endif
+			lp->stats.rx_errors++;
+#if 1
+		        eexp_hw_rxinit(dev);
+#else
+			lp->cur_rfd = lp->first_rfd;
+#endif
+			scb_wrrfa(dev, lp->rx_buf_start);
+			scb_command(dev, SCB_RUstart);
+			outb(0,ioaddr+SIGNAL_CA);
+		} 
+	} else {
+		if (status & 0x8000) 
+			ack_cmd = eexp_start_irq(dev, status);
+		else
+			ack_cmd = SCB_ack(status);
+		scb_command(dev, ack_cmd);
+		outb(0,ioaddr+SIGNAL_CA);
 	}
-	else if (lp->started==1 && SCB_RUstat(status)==4)
-		lp->started|=2;
 
-	scb_command(dev, ack_cmd);
-	outb(0,ioaddr+SIGNAL_CA);
+	eexp_cmd_clear(dev);
 
-	outb(SIRQ_en|irqrmap[irq],ioaddr+SET_IRQ);
+	outb(SIRQ_en|irqrmap[irq],ioaddr+SET_IRQ); 
 
 	dev->interrupt = 0;
-#if NET_DEBUG > 6
-        printk(KERN_DEBUG "%s: leaving eexp_irq()\n", dev->name);
+#if NET_DEBUG > 6 
+	printk("%s: leaving eexp_irq()\n", dev->name);
 #endif
+	outw(old_read_ptr, ioaddr+READ_PTR);
+	outw(old_write_ptr, ioaddr+WRITE_PTR);
 	return;
 }
 
@@ -594,6 +730,25 @@
  */
 
 /*
+ * Set the cable type to use.
+ */
+
+static void eexp_hw_set_interface(struct device *dev)
+{
+	unsigned char oldval = inb(dev->base_addr + 0x300e);
+	oldval &= ~0x82;
+	switch (dev->if_port) {
+	case TPE:
+		oldval |= 0x2;
+	case BNC:
+		oldval |= 0x80;
+		break;
+	}
+	outb(oldval, dev->base_addr+0x300e);
+	udelay(20000);
+}
+
+/*
  * Check all the receive buffers, and hand any received packets
  * to the upper levels. Basic sanity check on each frame
  * descriptor, though we don't bother trying to fix broken ones.
@@ -602,41 +757,49 @@
 static void eexp_hw_rx_pio(struct device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
-	unsigned short rx_block = lp->rx_first;
+	unsigned short rx_block = lp->rx_ptr;
 	unsigned short boguscount = lp->num_rx_bufs;
 	unsigned short ioaddr = dev->base_addr;
+	unsigned short status;
 
 #if NET_DEBUG > 6
 	printk(KERN_DEBUG "%s: eexp_hw_rx()\n", dev->name);
 #endif
 
-	while (boguscount--)
-	{
-		unsigned short status, rfd_cmd, rx_next, pbuf, pkt_len;
-
+ 	do {
+ 		unsigned short rfd_cmd, rx_next, pbuf, pkt_len;
+  
 		outw(rx_block, ioaddr + READ_PTR);
 		status = inw(ioaddr + DATAPORT);
-		rfd_cmd = inw(ioaddr + DATAPORT);
-		rx_next = inw(ioaddr + DATAPORT);
-		pbuf = inw(ioaddr + DATAPORT);
 
 		if (FD_Done(status))
 		{
+			rfd_cmd = inw(ioaddr + DATAPORT);
+			rx_next = inw(ioaddr + DATAPORT);
+			pbuf = inw(ioaddr + DATAPORT);
+ 
 			outw(pbuf, ioaddr + READ_PTR);
 			pkt_len = inw(ioaddr + DATAPORT);
 
-			if (rfd_cmd!=0x0000 || pbuf!=rx_block+0x16
-				|| (pkt_len & 0xc000)!=0xc000)
+			if (rfd_cmd!=0x0000)
+  			{
+				printk(KERN_WARNING "%s: rfd_cmd not zero:0x%04x\n",
+				       dev->name, rfd_cmd);
+				continue;
+			}
+			else if (pbuf!=rx_block+0x16)
 			{
-				/* This should never happen.  If it does,
-				 * we almost certainly have a driver bug.
-				 */
-				printk(KERN_WARNING "%s: Rx frame at %04x corrupted, status %04x, cmd %04x, "
-					"next %04x, pbuf %04x, len %04x\n",dev->name,rx_block,
-					status,rfd_cmd,rx_next,pbuf,pkt_len);
+				printk(KERN_WARNING "%s: rfd and rbd out of sync 0x%04x 0x%04x\n", 
+				       dev->name, rx_block+0x16, pbuf);
 				continue;
 			}
-			else if (!FD_OK(status))
+			else if ((pkt_len & 0xc000)!=0xc000) 
+			{
+				printk(KERN_WARNING "%s: EOF or F not set on received buffer (%04x)\n",
+				       dev->name, pkt_len & 0xc000);
+  				continue;
+  			}
+  			else if (!FD_OK(status)) 
 			{
 				lp->stats.rx_errors++;
 				if (FD_CRC(status))
@@ -668,13 +831,15 @@
 				skb->protocol = eth_type_trans(skb,dev);
 				netif_rx(skb);
 				lp->stats.rx_packets++;
+				lp->stats.rx_bytes += pkt_len;
 			}
 			outw(rx_block, ioaddr+WRITE_PTR);
 			outw(0, ioaddr+DATAPORT);
 			outw(0, ioaddr+DATAPORT);
+			rx_block = rx_next;
 		}
-		rx_block = rx_next;
-	}
+	} while (FD_Done(status) && boguscount--);
+	lp->rx_ptr = rx_block;
 }
 
 /*
@@ -690,7 +855,17 @@
 	struct net_local *lp = (struct net_local *)dev->priv;
 	unsigned short ioaddr = dev->base_addr;
 
-	outw(lp->tx_head, ioaddr + WRITE_PTR);
+	if (lp->width) {
+		/* Stop the CU so that there is no chance that it
+		   jumps off to a bogus address while we are writing the
+		   pointer to the next transmit packet in 8-bit mode -- 
+		   this eliminates the "CU wedged" errors in 8-bit mode.
+		   (Zoltan Szilagyi 10-12-96) */ 
+		scb_command(dev, SCB_CUsuspend);
+		outw(0xFFFF, ioaddr+SIGNAL_CA);
+	}
+
+ 	outw(lp->tx_head, ioaddr + WRITE_PTR);
 
 	outw(0x0000, ioaddr + DATAPORT);
         outw(Cmd_INT|Cmd_Xmit, ioaddr + DATAPORT);
@@ -719,6 +894,16 @@
 		lp->tx_head += TX_BUF_SIZE;
 	if (lp->tx_head != lp->tx_reap)
 		dev->tbusy = 0;
+
+	if (lp->width) {
+		/* Restart the CU so that the packet can actually
+		   be transmitted. (Zoltan Szilagyi 10-12-96) */
+		scb_command(dev, SCB_CUresume);
+		outw(0xFFFF, ioaddr+SIGNAL_CA);
+	}
+
+	lp->stats.tx_packets++;
+	lp->last_tx = jiffies;
 }
 
 /*
@@ -731,14 +916,13 @@
 static int eexp_hw_probe(struct device *dev, unsigned short ioaddr)
 {
 	unsigned short hw_addr[3];
+	unsigned char buswidth;
 	unsigned int memory_size;
-	static char *ifmap[]={"AUI", "BNC", "RJ45"};
-	enum iftype {AUI=0, BNC=1, TP=2};
 	int i;
 	unsigned short xsum = 0;
 	struct net_local *lp;
 
-	printk("%s: EtherExpress 16 at %#x",dev->name,ioaddr);
+	printk("%s: EtherExpress 16 at %#x ",dev->name,ioaddr);
 
 	outb(ASIC_RST, ioaddr+EEPROM_Ctrl);
 	outb(0, ioaddr+EEPROM_Ctrl);
@@ -769,7 +953,7 @@
 		dev->dev_addr[i] = ((unsigned char *)hw_addr)[5-i];
 
 	{
-		char irqmap[]={0, 9, 3, 4, 5, 10, 11, 0};
+		static char irqmap[]={0, 9, 3, 4, 5, 10, 11, 0};
 		unsigned short setupval = eexp_hw_readeeprom(ioaddr,0);
 
 		/* Use the IRQ from EEPROM if none was given */
@@ -777,7 +961,9 @@
 			dev->irq = irqmap[setupval>>13];
 
 		dev->if_port = !(setupval & 0x1000) ? AUI :
-			eexp_hw_readeeprom(ioaddr,5) & 0x1 ? TP : BNC;
+			eexp_hw_readeeprom(ioaddr,5) & 0x1 ? TPE : BNC;
+
+		buswidth = !((setupval & 0x400) >> 10);
 	}
 
 	dev->priv = lp = kmalloc(sizeof(struct net_local), GFP_KERNEL);
@@ -786,8 +972,11 @@
 
 	memset(dev->priv, 0, sizeof(struct net_local));
 
-	printk("; using IRQ %d, %s connector", dev->irq,ifmap[dev->if_port]);
-
+ 	printk("(IRQ %d, %s connector, %d-bit bus", dev->irq, 
+ 	       eexp_ifmap[dev->if_port], buswidth?8:16);
+ 
+ 	eexp_hw_set_interface(dev);
+  
 	/* Find out how much RAM we have on the card */
 	outw(0, dev->base_addr + WRITE_PTR);
 	for (i = 0; i < 32768; i++)
@@ -795,10 +984,10 @@
 
         for (memory_size = 0; memory_size < 64; memory_size++)
 	{
-		outw(memory_size<<10, dev->base_addr + WRITE_PTR);
 		outw(memory_size<<10, dev->base_addr + READ_PTR);
 		if (inw(dev->base_addr+DATAPORT))
 			break;
+		outw(memory_size<<10, dev->base_addr + WRITE_PTR);
 		outw(memory_size | 0x5000, dev->base_addr+DATAPORT);
 		outw(memory_size<<10, dev->base_addr + READ_PTR);
 		if (inw(dev->base_addr+DATAPORT) != (memory_size | 0x5000))
@@ -820,16 +1009,17 @@
 	case 32:
 		lp->rx_buf_end += 0x4000;
 	case 16:
-		printk(", %dk RAM.\n", memory_size);
+		printk(", %dk RAM)\n", memory_size);
 		break;
 	default:
-		printk("; bad memory size (%dk).\n", memory_size);
+		printk(") bad memory size (%dk).\n", memory_size);
 		kfree(dev->priv);
 		return ENODEV;
 		break;
 	}
 
 	lp->rx_buf_start = TX_BUF_START + (lp->num_tx_bufs*TX_BUF_SIZE);
+	lp->width = buswidth;
 
 	dev->open = eexp_open;
 	dev->stop = eexp_close;
@@ -905,8 +1095,8 @@
 
 	do
 	{
-		outw(tx_block, dev->base_addr + SM_PTR);
-		status = inw(SHADOW(tx_block));
+		outw(tx_block & ~31, dev->base_addr + SM_PTR);
+		status = inw(dev->base_addr + SHADOW(tx_block));
 		if (!Stat_Done(status))
 		{
 			lp->tx_link = tx_block;
@@ -918,12 +1108,29 @@
 			lp->stats.collisions += Stat_NoColl(status);
 			if (!Stat_OK(status))
 			{
-				if (Stat_Abort(status))
-					lp->stats.tx_aborted_errors++;
-				if (Stat_TNoCar(status) || Stat_TNoCTS(status))
+				char *whatsup = NULL;
+				lp->stats.tx_errors++;
+  				if (Stat_Abort(status)) 
+  					lp->stats.tx_aborted_errors++;
+				if (Stat_TNoCar(status)) {
+					whatsup = "aborted, no carrier";
 					lp->stats.tx_carrier_errors++;
-				if (Stat_TNoDMA(status))
-					lp->stats.tx_fifo_errors++;
+				}
+				if (Stat_TNoCTS(status)) {
+					whatsup = "aborted, lost CTS";
+  					lp->stats.tx_carrier_errors++;
+				}
+				if (Stat_TNoDMA(status)) {
+					whatsup = "FIFO underran";
+  					lp->stats.tx_fifo_errors++;
+				}
+				if (Stat_TXColl(status)) {
+					whatsup = "aborted, too many collisions";
+					lp->stats.tx_aborted_errors++;
+				}
+				if (whatsup)
+					printk(KERN_INFO "%s: transmit %s\n",
+					       dev->name, whatsup);
 			}
 			else
 				lp->stats.tx_packets++;
@@ -1043,7 +1250,7 @@
 	unsigned short ioaddr = dev->base_addr;
 
 	lp->num_rx_bufs = 0;
-	lp->rx_first = rx_block;
+	lp->rx_first = lp->rx_ptr = rx_block;
 	do
 	{
 		lp->num_rx_bufs++;
@@ -1052,9 +1259,9 @@
 
 		outw(0, ioaddr + DATAPORT);  outw(0, ioaddr+DATAPORT);
 		outw(rx_block + RX_BUF_SIZE, ioaddr+DATAPORT);
-		outw(rx_block + 0x16, ioaddr+DATAPORT);
+		outw(0xffff, ioaddr+DATAPORT);
 
-		outw(0xdead, ioaddr+DATAPORT);
+		outw(0x0000, ioaddr+DATAPORT);
 		outw(0xdead, ioaddr+DATAPORT);
 		outw(0xdead, ioaddr+DATAPORT);
 		outw(0xdead, ioaddr+DATAPORT);
@@ -1062,19 +1269,30 @@
 		outw(0xdead, ioaddr+DATAPORT);
 		outw(0xdead, ioaddr+DATAPORT);
 
-		outw(0x8000, ioaddr+DATAPORT);
-		outw(0xffff, ioaddr+DATAPORT);
+		outw(0x0000, ioaddr+DATAPORT);
+		outw(rx_block + RX_BUF_SIZE + 0x16, ioaddr+DATAPORT);
 		outw(rx_block + 0x20, ioaddr+DATAPORT);
 		outw(0, ioaddr+DATAPORT);
-		outw(0x8000 | (RX_BUF_SIZE-0x20), ioaddr+DATAPORT);
+		outw(RX_BUF_SIZE-0x20, ioaddr+DATAPORT);
 
 		lp->rx_last = rx_block;
 		rx_block += RX_BUF_SIZE;
 	} while (rx_block <= lp->rx_buf_end-RX_BUF_SIZE);
 
-	outw(lp->rx_last + 4, ioaddr+WRITE_PTR);
-	outw(lp->rx_first, ioaddr+DATAPORT);
 
+	/* Make first Rx frame descriptor point to first Rx buffer
+           descriptor */
+	outw(lp->rx_first + 6, ioaddr+WRITE_PTR);
+	outw(lp->rx_first + 0x16, ioaddr+DATAPORT);
+
+	/* Close Rx frame descriptor ring */
+  	outw(lp->rx_last + 4, ioaddr+WRITE_PTR);
+  	outw(lp->rx_first, ioaddr+DATAPORT);
+  
+	/* Close Rx buffer descriptor ring */
+	outw(lp->rx_last + 0x16 + 2, ioaddr+WRITE_PTR);
+	outw(lp->rx_first + 0x16, ioaddr+DATAPORT);
+	
 }
 
 /*
@@ -1083,6 +1301,7 @@
  * us.  We can't start the receive/transmission system up before we know that
  * the hardware is configured correctly.
  */
+
 static void eexp_hw_init586(struct device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
@@ -1097,24 +1316,19 @@
 
 	set_loopback(dev);
 
-	/* Bash the startup code a bit */
-	start_code[28] = (dev->flags & IFF_PROMISC)?(start_code[28] | 1):
-		(start_code[28] & ~1);
-	lp->promisc = dev->flags & IFF_PROMISC;
-	memcpy(&start_code[33], &dev->dev_addr[0], 6);
-
 	outb(SIRQ_dis|irqrmap[dev->irq],ioaddr+SET_IRQ);
 
 	/* Download the startup code */
 	outw(lp->rx_buf_end & ~31, ioaddr + SM_PTR);
-	outw(start_code[0], ioaddr + 0x8006);
-	outw(start_code[1], ioaddr + 0x8008);
-	outw(start_code[2], ioaddr + 0x800a);
-	outw(start_code[3], ioaddr + 0x800c);
-	outw(start_code[4], ioaddr + 0x800e);
-	for (i = 10; i < (sizeof(start_code)); i+=32) {
+	outw(lp->width?0x0001:0x0000, ioaddr + 0x8006);
+	outw(0x0000, ioaddr + 0x8008);
+	outw(0x0000, ioaddr + 0x800a);
+	outw(0x0000, ioaddr + 0x800c);
+	outw(0x0000, ioaddr + 0x800e);
+
+	for (i = 0; i < (sizeof(start_code)); i+=32) {
 		int j;
-		outw(i-10, ioaddr + SM_PTR);
+		outw(i, ioaddr + SM_PTR);
 		for (j = 0; j < 16; j+=2)
 			outw(start_code[(i+j)/2],
 			     ioaddr+0x4000+j);
@@ -1123,6 +1337,24 @@
 			     ioaddr+0x8000+j);
 	}
 
+	/* Do we want promiscuous mode or multicast? */
+	outw(CONF_PROMISC & ~31, ioaddr+SM_PTR);
+	i = inw(ioaddr+SHADOW(CONF_PROMISC));
+	outw((dev->flags & IFF_PROMISC)?(i|1):(i & ~1), 
+	     ioaddr+SHADOW(CONF_PROMISC));
+	lp->was_promisc = dev->flags & IFF_PROMISC;
+#if 0
+	eexp_setup_filter(dev);
+#endif
+
+	/* Write our hardware address */
+	outw(CONF_HWADDR & ~31, ioaddr+SM_PTR);
+	outw(((unsigned short *)dev->dev_addr)[0], ioaddr+SHADOW(CONF_HWADDR));
+	outw(((unsigned short *)dev->dev_addr)[1], 
+	     ioaddr+SHADOW(CONF_HWADDR+2));
+	outw(((unsigned short *)dev->dev_addr)[2],
+	     ioaddr+SHADOW(CONF_HWADDR+4));
+
 	eexp_hw_txinit(dev);
 	eexp_hw_rxinit(dev);
 
@@ -1193,6 +1425,38 @@
 	return;
 }
 
+static void eexp_setup_filter(struct device *dev)
+{
+	struct dev_mc_list *dmi = dev->mc_list;
+	unsigned short ioaddr = dev->base_addr;
+	int count = dev->mc_count;
+	int i;
+	if (count > 8) {
+		printk(KERN_INFO "%s: too many multicast addresses (%d)\n",
+		       dev->name, count);
+		count = 8;
+	}
+	
+	outw(CONF_NR_MULTICAST & ~31, ioaddr+SM_PTR);
+	outw(count, ioaddr+SHADOW(CONF_NR_MULTICAST));
+	for (i = 0; i < count; i++) {
+		unsigned short *data = (unsigned short *)dmi->dmi_addr;
+		if (!dmi) {
+			printk(KERN_INFO "%s: too few multicast addresses\n", dev->name);
+			break;
+		}
+		if (dmi->dmi_addrlen != ETH_ALEN) {
+			printk(KERN_INFO "%s: invalid multicast address length given.\n", dev->name);
+			continue;
+		}
+		outw((CONF_MULTICAST+(6*i)) & ~31, ioaddr+SM_PTR);
+		outw(data[0], ioaddr+SHADOW(CONF_MULTICAST+(6*i)));
+		outw((CONF_MULTICAST+(6*i)+2) & ~31, ioaddr+SM_PTR);
+		outw(data[1], ioaddr+SHADOW(CONF_MULTICAST+(6*i)+2));
+		outw((CONF_MULTICAST+(6*i)+4) & ~31, ioaddr+SM_PTR);
+		outw(data[2], ioaddr+SHADOW(CONF_MULTICAST+(6*i)+4));
+	}
+}
 
 /*
  * Set or clear the multicast filter for this adaptor.
@@ -1200,12 +1464,49 @@
 static void
 eexp_set_multicast(struct device *dev)
 {
+        unsigned short ioaddr = dev->base_addr;
+        struct net_local *lp = (struct net_local *)dev->priv;
+        int kick = 0, i;
+        if ((dev->flags & IFF_PROMISC) != lp->was_promisc) {
+                outw(CONF_PROMISC & ~31, ioaddr+SM_PTR);
+                i = inw(ioaddr+SHADOW(CONF_PROMISC));
+                outw((dev->flags & IFF_PROMISC)?(i|1):(i & ~1),
+                     ioaddr+SHADOW(CONF_PROMISC));
+                lp->was_promisc = dev->flags & IFF_PROMISC;
+                kick = 1;
+        }
+        if (!(dev->flags & IFF_PROMISC)) {
+                eexp_setup_filter(dev);
+                if (lp->old_mc_count != dev->mc_count) {
+                        kick = 1;
+                        lp->old_mc_count = dev->mc_count;
+                }
+        }
+        if (kick) {
+                unsigned long oj;
+                scb_command(dev, SCB_CUsuspend);
+                outb(0, ioaddr+SIGNAL_CA);
+                outb(0, ioaddr+SIGNAL_CA);
+#if 0
+                printk("%s: waiting for CU to go suspended\n", dev->name);
+#endif
+                oj = jiffies;
+                while ((SCB_CUstat(scb_status(dev)) == 2) &&
+                       ((jiffies-oj) < 100));
+		if (SCB_CUstat(scb_status(dev)) == 2)
+			printk("%s: warning, CU didn't stop\n", dev->name);
+                lp->started &= ~(STARTED_CU);
+                scb_wrcbl(dev, CONF_LINK);
+                scb_command(dev, SCB_CUstart);
+                outb(0, ioaddr+SIGNAL_CA);
+        }
 }
 
 
 /*
  * MODULE stuff
  */
+
 #ifdef MODULE
 
 #define EEXP_MAX_CARDS     4    /* max number of cards to support */
diff -u --recursive --new-file v2.1.35/linux/drivers/net/eql.c linux/drivers/net/eql.c
--- v2.1.35/linux/drivers/net/eql.c	Sun Feb  2 05:18:39 1997
+++ linux/drivers/net/eql.c	Tue Apr 22 22:42:49 1997
@@ -130,6 +130,7 @@
 #include <asm/dma.h>
 #include <asm/uaccess.h>
 #include <linux/errno.h>              
+#include <linux/init.h>
 
 #include <linux/netdevice.h>
 #include <linux/if.h>
@@ -208,7 +209,7 @@
    ---------------------------------------------------------
    */
 
-int eql_init(struct device *dev)
+__initfunc(int eql_init(struct device *dev))
 {
 	static unsigned version_printed = 0;
 	/* static unsigned num_masters     = 0; */
diff -u --recursive --new-file v2.1.35/linux/drivers/net/es3210.c linux/drivers/net/es3210.c
--- v2.1.35/linux/drivers/net/es3210.c	Tue Dec 31 00:30:01 1996
+++ linux/drivers/net/es3210.c	Tue Apr 22 22:42:49 1997
@@ -53,6 +53,7 @@
 #include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/string.h>
+#include <linux/init.h>
 #include <asm/io.h>
 #include <asm/system.h>
 
@@ -114,8 +115,8 @@
 
 #define ES_DEBUG	0
 
-static unsigned char lo_irq_map[] = {3, 4, 5, 6, 7, 9, 10};
-static unsigned char hi_irq_map[] = {11, 12, 0, 14, 0, 0, 0, 15};
+static unsigned char lo_irq_map[] __initdata = {3, 4, 5, 6, 7, 9, 10};
+static unsigned char hi_irq_map[] __initdata = {11, 12, 0, 14, 0, 0, 0, 15};
 
 /*
  *	Probe for the card. The best way is to read the EISA ID if it
@@ -123,7 +124,7 @@
  *	PROM for a match against the Racal-Interlan assigned value.
  */
 
-int es_probe(struct device *dev)
+__initfunc(int es_probe(struct device *dev))
 {
 	unsigned short ioaddr = dev->base_addr;
 
@@ -150,7 +151,7 @@
 	return ENODEV;
 }
 
-int es_probe1(struct device *dev, int ioaddr)
+__initfunc(int es_probe1(struct device *dev, int ioaddr))
 {
 	int i;
 	unsigned long eisa_id;
diff -u --recursive --new-file v2.1.35/linux/drivers/net/eth16i.c linux/drivers/net/eth16i.c
--- v2.1.35/linux/drivers/net/eth16i.c	Sun Feb  2 05:18:39 1997
+++ linux/drivers/net/eth16i.c	Tue Apr 22 22:42:49 1997
@@ -87,6 +87,7 @@
 #include <linux/malloc.h>
 #include <linux/string.h>
 #include <linux/errno.h>
+#include <linux/init.h>
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -275,22 +276,22 @@
 #define RESET                  ID_ROM_0
 
 /* This is the I/O address list to be probed when seeking the card */
-static unsigned int eth16i_portlist[] = {
+static unsigned int eth16i_portlist[] __initdata = {
 	0x260, 0x280, 0x2A0, 0x240, 0x340, 0x320, 0x380, 0x300, 0
 };
 
-static unsigned int eth32i_portlist[] = {
+static unsigned int eth32i_portlist[] __initdata = {
 	0x1000, 0x2000, 0x3000, 0x4000, 0x5000, 0x6000, 0x7000, 0x8000,
 	0x9000, 0xA000, 0xB000, 0xC000, 0xD000, 0xE000, 0xF000, 0
 };
 
 /* This is the Interrupt lookup table for Eth16i card */
-static unsigned int eth16i_irqmap[] = {
+static unsigned int eth16i_irqmap[] __initdata = {
 	9, 10, 5, 15
 };
 
 /* This is the Interrupt lookup table for Eth32i card */
-static unsigned int eth32i_irqmap[] = {
+static unsigned int eth32i_irqmap[] __initdata = {
 	3, 5, 7, 9, 10, 11, 12, 15
 };
 
@@ -350,7 +351,7 @@
    {"eth16i", eth16i_probe1, ETH16I_IO_EXTENT, eth16i_probe_list};
 
 #else  /* Not HAVE_DEVLIST */
-int eth16i_probe(struct device *dev)
+__initfunc(int eth16i_probe(struct device *dev))
 {
 	int i;
 	int ioaddr;
@@ -384,7 +385,7 @@
 }
 #endif	/* Not HAVE_DEVLIST */
 
-static int eth16i_probe1(struct device *dev, short ioaddr)
+__initfunc(static int eth16i_probe1(struct device *dev, short ioaddr))
 {
 	static unsigned version_printed = 0;
 	unsigned int irq = 0;
diff -u --recursive --new-file v2.1.35/linux/drivers/net/ewrk3.c linux/drivers/net/ewrk3.c
--- v2.1.35/linux/drivers/net/ewrk3.c	Sun Feb  2 05:18:40 1997
+++ linux/drivers/net/ewrk3.c	Tue Apr 22 22:42:49 1997
@@ -149,6 +149,7 @@
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
+#include <linux/init.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/dma.h>
@@ -344,7 +345,7 @@
 
 
 
-int ewrk3_probe(struct device *dev)
+__initfunc(int ewrk3_probe(struct device *dev))
 {
   int tmp = num_ewrk3s, status = -ENODEV;
   u_long iobase = dev->base_addr;
@@ -375,8 +376,8 @@
   return status;
 }
 
-static int
-ewrk3_hw_init(struct device *dev, u_long iobase)
+__initfunc(static int
+ewrk3_hw_init(struct device *dev, u_long iobase))
 {
   struct ewrk3_private *lp;
   int i, status=0;
@@ -1289,7 +1290,7 @@
 /*
 ** ISA bus I/O device probe
 */
-static void isa_probe(struct device *dev, u_long ioaddr)
+__initfunc(static void isa_probe(struct device *dev, u_long ioaddr))
 {
   int i = num_ewrk3s, maxSlots;
   u_long iobase;
@@ -1327,7 +1328,7 @@
 ** EISA bus I/O device probe. Probe from slot 1 since slot 0 is usually
 ** the motherboard.
 */
-static void eisa_probe(struct device *dev, u_long ioaddr)
+__initfunc(static void eisa_probe(struct device *dev, u_long ioaddr))
 {
   int i, maxSlots;
   u_long iobase;
@@ -1372,8 +1373,8 @@
 ** are not available then insert a new device structure at the end of
 ** the current list.
 */
-static struct device *
-alloc_device(struct device *dev, u_long iobase)
+__initfunc(static struct device *
+alloc_device(struct device *dev, u_long iobase))
 {
     struct device *adev = NULL;
     int fixed = 0, new_dev = 0;
@@ -1417,8 +1418,8 @@
 ** If at end of eth device list and can't use current entry, malloc
 ** one up. If memory could not be allocated, print an error message.
 */
-static struct device *
-insert_device(struct device *dev, u_long iobase, int (*init)(struct device *))
+__initfunc(static struct device *
+insert_device(struct device *dev, u_long iobase, int (*init)(struct device *)))
 {
     struct device *new;
 
@@ -1443,8 +1444,8 @@
     return dev;
 }
 
-static int
-ewrk3_dev_index(char *s)
+__initfunc(static int
+ewrk3_dev_index(char *s))
 {
     int i=0, j=0;
 
@@ -1494,7 +1495,7 @@
 /*
 ** Look for a particular board name in the on-board EEPROM.
 */
-static void EthwrkSignature(char *name, char *eeprom_image)
+__initfunc(static void EthwrkSignature(char *name, char *eeprom_image))
 {
   u_long i,j,k;
   char *signatures[] = EWRK3_SIGNATURE;
@@ -1531,7 +1532,7 @@
 ** ethernet address for later read out.
 */
 
-static int DevicePresent(u_long iobase)
+__initfunc(static int DevicePresent(u_long iobase))
 {
   union {
     struct {
@@ -1568,7 +1569,7 @@
   return status;
 }
 
-static u_char get_hw_addr(struct device *dev, u_char *eeprom_image, char chipType)
+__initfunc(static u_char get_hw_addr(struct device *dev, u_char *eeprom_image, char chipType))
 {
   int i, j, k;
   u_short chksum;
@@ -1614,7 +1615,7 @@
 /*
 ** Look for a particular board name in the EISA configuration space
 */
-static int EISA_signature(char *name, s32 eisa_id)
+__initfunc(static int EISA_signature(char *name, s32 eisa_id))
 {
   u_long i;
   char *signatures[] = EWRK3_SIGNATURE;
diff -u --recursive --new-file v2.1.35/linux/drivers/net/fmv18x.c linux/drivers/net/fmv18x.c
--- v2.1.35/linux/drivers/net/fmv18x.c	Fri Apr  4 08:52:21 1997
+++ linux/drivers/net/fmv18x.c	Tue Apr 22 22:42:49 1997
@@ -46,6 +46,7 @@
 #include <linux/in.h>
 #include <linux/malloc.h>
 #include <linux/string.h>
+#include <linux/init.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -57,7 +58,7 @@
 #include <linux/skbuff.h>
 #include <linux/delay.h>
 
-static int fmv18x_probe_list[] =
+static int fmv18x_probe_list[] __initdata =
 {0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x300, 0x340, 0};
 
 /* use 0 for production, 1 for verification, >2 for debug */
@@ -129,8 +130,8 @@
 struct netdev_entry fmv18x_drv =
 {"fmv18x", fmv18x_probe1, FMV18X_IO_EXTENT, fmv18x_probe_list};
 #else
-int
-fmv18x_probe(struct device *dev)
+__initfunc(int
+fmv18x_probe(struct device *dev))
 {
 	int i;
 	int base_addr = dev ? dev->base_addr : 0;
@@ -160,7 +161,7 @@
    that can be done is checking a few bits and then diving right into MAC
    address check. */
 
-int fmv18x_probe1(struct device *dev, short ioaddr)
+__initfunc(int fmv18x_probe1(struct device *dev, short ioaddr))
 {
 	char irqmap[4] = {3, 7, 10, 15};
 	unsigned int i, irq;
diff -u --recursive --new-file v2.1.35/linux/drivers/net/hdlcdrv.c linux/drivers/net/hdlcdrv.c
--- v2.1.35/linux/drivers/net/hdlcdrv.c	Thu Mar 27 14:40:03 1997
+++ linux/drivers/net/hdlcdrv.c	Tue Apr 22 22:42:49 1997
@@ -277,7 +277,6 @@
 	memcpy(cp, s->hdlcrx.buffer, pkt_len - 1);
 	skb->protocol = htons(ETH_P_AX25);
 	skb->mac.raw = skb->data;
-	IS_SKB(skb);
 	netif_rx(skb);
 	s->stats.rx_packets++;
 }
diff -u --recursive --new-file v2.1.35/linux/drivers/net/hp-plus.c linux/drivers/net/hp-plus.c
--- v2.1.35/linux/drivers/net/hp-plus.c	Tue Dec 31 00:30:01 1996
+++ linux/drivers/net/hp-plus.c	Tue Apr 22 22:42:49 1997
@@ -30,6 +30,7 @@
 #include <linux/ioport.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
+#include <linux/init.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
@@ -38,7 +39,7 @@
 #include "8390.h"
 
 /* A zero-terminated list of I/O addresses to be probed. */
-static unsigned int hpplus_portlist[] =
+static unsigned int hpplus_portlist[] __initdata =
 {0x200, 0x240, 0x280, 0x2C0, 0x300, 0x320, 0x340, 0};
 
 /*
@@ -121,7 +122,7 @@
 {"hpplus", hpp_probe1, HP_IO_EXTENT, hpplus_portlist};
 #else
 
-int hp_plus_probe(struct device *dev)
+__initfunc(int hp_plus_probe(struct device *dev))
 {
 	int i;
 	int base_addr = dev ? dev->base_addr : 0;
@@ -144,7 +145,7 @@
 #endif
 
 /* Do the interesting part of the probe at a single address. */
-int hpp_probe1(struct device *dev, int ioaddr)
+__initfunc(int hpp_probe1(struct device *dev, int ioaddr))
 {
 	int i;
 	unsigned char checksum = 0;
diff -u --recursive --new-file v2.1.35/linux/drivers/net/hp.c linux/drivers/net/hp.c
--- v2.1.35/linux/drivers/net/hp.c	Tue Dec 31 00:30:01 1996
+++ linux/drivers/net/hp.c	Tue Apr 22 22:42:49 1997
@@ -30,6 +30,7 @@
 #include <linux/ioport.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
+#include <linux/init.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
@@ -37,7 +38,7 @@
 #include "8390.h"
 
 /* A zero-terminated list of I/O addresses to be probed. */
-static unsigned int hppclan_portlist[] =
+static unsigned int hppclan_portlist[] __initdata =
 { 0x300, 0x320, 0x340, 0x280, 0x2C0, 0x200, 0x240, 0};
 
 #define HP_IO_EXTENT	32
@@ -70,8 +71,8 @@
 static void hp_init_card(struct device *dev);
 
 /* The map from IRQ number to HP_CONFIGURE register setting. */
-/* My default is IRQ5	   0  1	 2  3  4  5  6	7  8  9 10 11 */
-static char irqmap[16] = { 0, 0, 4, 6, 8,10, 0,14, 0, 4, 2,12,0,0,0,0};
+/* My default is IRQ5	             0  1  2  3  4  5  6  7  8  9 10 11 */
+static char irqmap[16] __initdata= { 0, 0, 4, 6, 8,10, 0,14, 0, 4, 2,12,0,0,0,0};
 
 
 /*	Probe for an HP LAN adaptor.
@@ -82,7 +83,7 @@
 {"hp", hp_probe1, HP_IO_EXTENT, hppclan_portlist};
 #else
 
-int hp_probe(struct device *dev)
+__initfunc(int hp_probe(struct device *dev))
 {
 	int i;
 	int base_addr = dev ? dev->base_addr : 0;
@@ -104,7 +105,7 @@
 }
 #endif
 
-int hp_probe1(struct device *dev, int ioaddr)
+__initfunc(int hp_probe1(struct device *dev, int ioaddr))
 {
 	int i, board_id, wordmode;
 	const char *name;
diff -u --recursive --new-file v2.1.35/linux/drivers/net/hp100.c linux/drivers/net/hp100.c
--- v2.1.35/linux/drivers/net/hp100.c	Fri Apr  4 08:52:21 1997
+++ linux/drivers/net/hp100.c	Tue Apr 22 22:42:49 1997
@@ -93,6 +93,7 @@
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/bios32.h>
+#include <linux/init.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
 
@@ -209,7 +210,7 @@
  *  probe functions
  */
 
-int hp100_probe( struct device *dev )
+__initfunc(int hp100_probe( struct device *dev ))
 {
   int base_addr = dev ? dev -> base_addr : 0;
   int ioaddr;
@@ -297,7 +298,7 @@
   return -ENODEV;
 }
 
-static int hp100_probe1( struct device *dev, int ioaddr, int bus )
+__initfunc(static int hp100_probe1( struct device *dev, int ioaddr, int bus ))
 {
   int i;
   u_char uc, uc_1;
diff -u --recursive --new-file v2.1.35/linux/drivers/net/hydra.c linux/drivers/net/hydra.c
--- v2.1.35/linux/drivers/net/hydra.c	Sun Feb  2 05:18:40 1997
+++ linux/drivers/net/hydra.c	Tue Apr 22 22:42:49 1997
@@ -27,6 +27,7 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
+#include <linux/init.h>
 
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -34,7 +35,7 @@
 
 #include <asm/amigaints.h>
 #include <asm/amigahw.h>
-#include <asm/zorro.h>
+#include <linux/zorro.h>
 
 #include "hydra.h"
 
@@ -156,7 +157,7 @@
 
 #endif
 
-int hydra_probe(struct device *dev)
+__initfunc(int hydra_probe(struct device *dev))
 {
 	struct hydra_private *priv;
 	u32 board;
@@ -193,7 +194,9 @@
 			dev->stop = &hydra_close;
 			dev->hard_start_xmit = &hydra_start_xmit;
 			dev->get_stats = &hydra_get_stats;
-	 		dev->set_multicast_list = &hydra_set_multicast_list;
+#ifdef HAVE_MULTICAST
+	 		dev->set_multicast_list = &set_multicast_list;
+#endif
 	 		
 	 		/*
 	 		 *	Cannot yet do multicast
@@ -643,6 +646,7 @@
 	return(&priv->stats);
 }
 
+#ifdef HAVE_MULTICAST
 static void set_multicast_list(struct device *dev, int num_addrs, void *addrs)
 {
 	struct hydra_private *priv = (struct hydra_private *)dev->priv;
@@ -652,6 +656,7 @@
 	/* (personally i don't care about multicasts at all :) */
 	return;
 }
+#endif
 
 
 #ifdef MODULE
diff -u --recursive --new-file v2.1.35/linux/drivers/net/ibmtr.c linux/drivers/net/ibmtr.c
--- v2.1.35/linux/drivers/net/ibmtr.c	Fri Apr  4 08:52:21 1997
+++ linux/drivers/net/ibmtr.c	Tue Apr 22 22:42:49 1997
@@ -119,6 +119,7 @@
 #include <linux/netdevice.h>
 #include <linux/trdevice.h>
 #include <linux/stddef.h>
+#include <linux/init.h>
 #include <net/checksum.h>
 
 #include <asm/io.h>
@@ -134,11 +135,11 @@
 #if TR_NEWFORMAT
 /* this allows displaying full adapter information */
 
-const char *channel_def[] = { 
+const char *channel_def[] __initdata = { 
 	"ISA", "MCA", "ISA P&P" 
 };
 
-char *adapter_def(char type)
+__initfunc(char *adapter_def(char type))
 {
 	switch (type) 
 	{
@@ -178,13 +179,13 @@
 void		ibmtr_readlog(struct device *dev);
 void		ibmtr_reset_timer(struct timer_list *tmr, struct device *dev);
 
-static unsigned int ibmtr_portlist[] = {
+static unsigned int ibmtr_portlist[] __initdata = {
 	0xa20, 0xa24, 0
 };
 
 static __u32 ibmtr_mem_base = 0xd0000;
 
-static void PrtChanID(char *pcid, short stride) 
+__initfunc(static void PrtChanID(char *pcid, short stride) )
 {
 	short i, j;
 	for (i=0, j=0; i<24; i++, j+=stride)
@@ -192,7 +193,7 @@
 	printk("\n");
 }
 
-static void HWPrtChanID (__u32 pcid, short stride)
+__initfunc(static void HWPrtChanID (__u32 pcid, short stride))
 {
 	short i, j;
 	for (i=0, j=0; i<24; i++, j+=stride)
@@ -213,7 +214,7 @@
  *	which references it.
  */
  
-int ibmtr_probe(struct device *dev)
+__initfunc(int ibmtr_probe(struct device *dev))
 {
         int i;
         int base_addr = dev ? dev->base_addr : 0;
@@ -252,7 +253,7 @@
         return -ENODEV;
 }
 
-static int ibmtr_probe1(struct device *dev, int PIOaddr)
+__initfunc(static int ibmtr_probe1(struct device *dev, int PIOaddr))
 {
 	unsigned char segment=0, intr=0, irq=0, i=0, j=0, cardpresent=NOTOK,temp=0;
 	__u32 t_mmio=0;
@@ -597,7 +598,7 @@
 
 /* query the adapter for the size of shared RAM  */
 
-unsigned char get_sram_size(struct tok_info *adapt_info)
+__initfunc(static unsigned char get_sram_size(struct tok_info *adapt_info))
 {
 
 	unsigned char avail_sram_code;
@@ -617,7 +618,7 @@
 		return 1<<((readb(adapt_info->mmio+ ACA_OFFSET + ACA_RW + RRR_ODD)>>2)+4);
 }
 
-int trdev_init(struct device *dev)
+__initfunc(static int trdev_init(struct device *dev))
 {
 	struct tok_info *ti=(struct tok_info *)dev->priv;
 
diff -u --recursive --new-file v2.1.35/linux/drivers/net/lance.c linux/drivers/net/lance.c
--- v2.1.35/linux/drivers/net/lance.c	Thu Mar 27 14:40:04 1997
+++ linux/drivers/net/lance.c	Tue Apr 22 22:42:49 1997
@@ -46,6 +46,7 @@
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/bios32.h>
+#include <linux/init.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/dma.h>
@@ -54,7 +55,7 @@
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 
-static unsigned int lance_portlist[] = {0x300, 0x320, 0x340, 0x360, 0};
+static unsigned int lance_portlist[] __initdata = {0x300, 0x320, 0x340, 0x360, 0};
 void lance_probe1(int ioaddr);
 
 #ifdef HAVE_DEVLIST
@@ -308,7 +309,7 @@
    before the memory management system is started, and thus well before the
    other probes. */
 
-int lance_init(void)
+__initfunc(int lance_init(void))
 {
 	int *port;
 
@@ -371,7 +372,7 @@
 	return 0;
 }
 
-void lance_probe1(int ioaddr)
+__initfunc(void lance_probe1(int ioaddr))
 {
 	struct device *dev;
 	struct lance_private *lp;
diff -u --recursive --new-file v2.1.35/linux/drivers/net/lapbether.c linux/drivers/net/lapbether.c
--- v2.1.35/linux/drivers/net/lapbether.c	Thu Mar 27 14:40:04 1997
+++ linux/drivers/net/lapbether.c	Tue Apr 22 22:42:49 1997
@@ -47,6 +47,7 @@
 #include <linux/module.h>
 #include <linux/net_alias.h>
 #include <linux/lapb.h>
+#include <linux/init.h>
 
 static char bcast_addr[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
 
@@ -410,7 +411,7 @@
 	return 0;
 }
 
-static int lapbeth_dev_init(struct device *dev)
+__initfunc(static int lapbeth_dev_init(struct device *dev))
 {
 	return 0;
 }
diff -u --recursive --new-file v2.1.35/linux/drivers/net/loopback.c linux/drivers/net/loopback.c
--- v2.1.35/linux/drivers/net/loopback.c	Mon Apr 14 16:28:12 1997
+++ linux/drivers/net/loopback.c	Tue Apr 22 22:42:49 1997
@@ -39,6 +39,7 @@
 #include <linux/errno.h>
 #include <linux/fcntl.h>
 #include <linux/in.h>
+#include <linux/init.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -114,7 +115,7 @@
 }
 
 /* Initialize the rest of the LOOPBACK device. */
-int loopback_init(struct device *dev)
+__initfunc(int loopback_init(struct device *dev))
 {
 	dev->mtu		= LOOPBACK_MTU;
 	dev->tbusy		= 0;
diff -u --recursive --new-file v2.1.35/linux/drivers/net/ltpc.c linux/drivers/net/ltpc.c
--- v2.1.35/linux/drivers/net/ltpc.c	Fri Apr  4 08:52:21 1997
+++ linux/drivers/net/ltpc.c	Tue Apr 22 22:42:49 1997
@@ -201,6 +201,7 @@
 #include <asm/bitops.h>
 #include <asm/dma.h>
 #include <linux/errno.h>
+#include <linux/init.h>
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -956,12 +957,12 @@
 
 static unsigned short irqhitmask;
 
-static void lt_probe_handler(int irq, void *dev_id, struct pt_regs *reg_ptr)
+__initfunc(static void lt_probe_handler(int irq, void *dev_id, struct pt_regs *reg_ptr))
 {
 	irqhitmask |= 1<<irq;
 }
 
-int ltpc_probe(struct device *dev)
+__initfunc(int ltpc_probe(struct device *dev))
 {
 	int err;
 	unsigned char dma=0;
diff -u --recursive --new-file v2.1.35/linux/drivers/net/mkiss.c linux/drivers/net/mkiss.c
--- v2.1.35/linux/drivers/net/mkiss.c	Thu Mar 27 14:40:04 1997
+++ linux/drivers/net/mkiss.c	Tue Apr 22 22:42:49 1997
@@ -35,6 +35,7 @@
 #include <linux/errno.h>
 #include <linux/netdevice.h>
 #include <linux/major.h>
+#include <linux/init.h>
 
 #include <linux/timer.h>
 
@@ -816,7 +817,7 @@
 }
 
 /* Initialize AX25 control device -- register AX25 line discipline */
-int mkiss_init_ctrl_dev(void)
+__initfunc(int mkiss_init_ctrl_dev(void))
 {
 	int status;
 
@@ -1038,7 +1039,7 @@
 /* * 			Init MKISS driver 			      * */
 /* ******************************************************************** */
 
-static int mkiss_init(void)
+__initfunc(static int mkiss_init(void))
 {
 	memset(&mkiss_driver, 0, sizeof(struct tty_driver));
 
diff -u --recursive --new-file v2.1.35/linux/drivers/net/myri_code.h linux/drivers/net/myri_code.h
--- v2.1.35/linux/drivers/net/myri_code.h	Thu Dec 19 01:03:34 1996
+++ linux/drivers/net/myri_code.h	Thu Apr 17 13:20:45 1997
@@ -2,7 +2,7 @@
 /* Generated by  cat $MYRI_HOME/lib/lanai/mcp4.dat > myri_code4.h */
 
 static unsigned int lanai4_code_off = 0x0000; /* half-word offset */ 
-static unsigned char lanai4_code[76256] = {
+static unsigned char lanai4_code[76256] __initdata = {
 0xF2,0x0E, 
 0xFE,0x00, 0xC2,0x90, 0x00,0x00, 0x07,0x88, 0x00,0x08, 0xE0,0x01, 0x01,0x4C, 0x97,0x93, 
 0xFF,0xFC, 0xE0,0x00, 0x00,0x14, 0x00,0x00, 0x00,0x01, 0x00,0x00, 0x00,0x00, 0x92,0x93, 
@@ -4775,7 +4775,7 @@
 /* This is the LANai data */ 
 
 static unsigned int lanai4_data_off = 0x94F0; /* half-word offset */
-static unsigned char lanai4_data[20472] = {
+static unsigned char lanai4_data[20472] __initdata = {
 0x00,0x00, 
 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
diff -u --recursive --new-file v2.1.35/linux/drivers/net/myri_sbus.c linux/drivers/net/myri_sbus.c
--- v2.1.35/linux/drivers/net/myri_sbus.c	Mon Apr 14 16:28:12 1997
+++ linux/drivers/net/myri_sbus.c	Thu Apr 17 13:20:45 1997
@@ -19,6 +19,7 @@
 #include <linux/in.h>
 #include <linux/malloc.h>
 #include <linux/string.h>
+#include <linux/init.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -171,7 +172,7 @@
 	return 0;
 }
 
-static int myri_load_lanai(struct myri_eth *mp)
+static inline int myri_load_lanai(struct myri_eth *mp)
 {
 	struct device		*dev = mp->dev;
 	struct myri_shmem	*shmem = mp->shmem;
@@ -893,7 +894,7 @@
 }
 #endif
 
-static int myri_ether_init(struct device *dev, struct linux_sbus_device *sdev, int num)
+static inline int myri_ether_init(struct device *dev, struct linux_sbus_device *sdev, int num)
 {
 	static unsigned version_printed = 0;
 	struct myri_eth *mp;
@@ -1105,7 +1106,7 @@
 	return 0;
 }
 
-int myri_sbus_probe(struct device *dev)
+__initfunc(int myri_sbus_probe(struct device *dev))
 {
 	struct linux_sbus *bus;
 	struct linux_sbus_device *sdev = 0;
diff -u --recursive --new-file v2.1.35/linux/drivers/net/ne.c linux/drivers/net/ne.c
--- v2.1.35/linux/drivers/net/ne.c	Thu Feb 27 10:57:30 1997
+++ linux/drivers/net/ne.c	Tue Apr 22 22:42:49 1997
@@ -41,6 +41,7 @@
 #include <linux/errno.h>
 #include <linux/pci.h>
 #include <linux/bios32.h>
+#include <linux/init.h>
 #include <asm/system.h>
 #include <asm/io.h>
 
@@ -64,14 +65,14 @@
 
 /* A zero-terminated list of I/O addresses to be probed at boot. */
 #ifndef MODULE
-static unsigned int netcard_portlist[] =
-{ 0x300, 0x280, 0x320, 0x340, 0x360, 0};
+static unsigned int netcard_portlist[] __initdata =
+{ 0x300, 0x280, 0x320, 0x340, 0x360, 0x380, 0};
 #endif
 
 #ifdef CONFIG_PCI
 /* Ack! People are making PCI ne2000 clones! Oh the horror, the horror... */
 static struct { unsigned short vendor, dev_id;}
-pci_clone_list[] = {
+pci_clone_list[] __initdata = {
 	{PCI_VENDOR_ID_REALTEK,		PCI_DEVICE_ID_REALTEK_8029},
 	{PCI_VENDOR_ID_WINBOND2,	PCI_DEVICE_ID_WINBOND2_89C940},
 	{PCI_VENDOR_ID_COMPEX,		PCI_DEVICE_ID_COMPEX_RL2000},
@@ -83,7 +84,7 @@
 #ifdef SUPPORT_NE_BAD_CLONES
 /* A list of bad clones that we none-the-less recognize. */
 static struct { const char *name8, *name16; unsigned char SAprefix[4];}
-bad_clone_list[] = {
+bad_clone_list[] __initdata = {
     {"DE100", "DE200", {0x00, 0xDE, 0x01,}},
     {"DE120", "DE220", {0x00, 0x80, 0xc8,}},
     {"DFI1000", "DFI2000", {'D', 'F', 'I',}}, /* Original, eh?  */
@@ -166,7 +167,7 @@
  * the card.
  */
 
-int ne_probe(struct device *dev)
+__initfunc(int ne_probe(struct device *dev))
 {
     int base_addr = dev ? dev->base_addr : 0;
 
@@ -198,7 +199,7 @@
 #endif
 
 #ifdef CONFIG_PCI
-static int ne_probe_pci(struct device *dev)
+__initfunc(static int ne_probe_pci(struct device *dev))
 {
 	int i;
 
@@ -240,7 +241,7 @@
 }
 #endif  /* CONFIG_PCI */
 
-static int ne_probe1(struct device *dev, int ioaddr)
+__initfunc(static int ne_probe1(struct device *dev, int ioaddr))
 {
     int i;
     unsigned char SA_prom[32];
diff -u --recursive --new-file v2.1.35/linux/drivers/net/ni52.c linux/drivers/net/ni52.c
--- v2.1.35/linux/drivers/net/ni52.c	Thu Feb 27 10:57:30 1997
+++ linux/drivers/net/ni52.c	Tue Apr 22 22:42:49 1997
@@ -114,6 +114,7 @@
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
+#include <linux/init.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
 
@@ -359,7 +360,7 @@
 /**********************************************
  * probe the ni5210-card
  */
-int ni52_probe(struct device *dev)
+__initfunc(int ni52_probe(struct device *dev))
 {
 #ifndef MODULE
 	int *port;
@@ -410,7 +411,7 @@
 	return ENODEV;
 }
 
-static int ni52_probe1(struct device *dev,int ioaddr)
+__initfunc(static int ni52_probe1(struct device *dev,int ioaddr))
 {
 	int i,size;
 
@@ -455,7 +456,7 @@
 	else
 	{
 		static long memaddrs[] = { 0xc8000,0xca000,0xcc000,0xce000,0xd0000,0xd2000,
-															0xd4000,0xd6000,0xd8000,0xda000,0xdc000, 0 };
+					0xd4000,0xd6000,0xd8000,0xda000,0xdc000, 0 };
 		for(i=0;;i++)
 		{
 			if(!memaddrs[i]) {
diff -u --recursive --new-file v2.1.35/linux/drivers/net/ni65.c linux/drivers/net/ni65.c
--- v2.1.35/linux/drivers/net/ni65.c	Sun Feb  2 05:18:40 1997
+++ linux/drivers/net/ni65.c	Tue Apr 22 22:42:49 1997
@@ -69,6 +69,7 @@
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
+#include <linux/init.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/dma.h>
@@ -232,8 +233,8 @@
 static struct net_device_stats *ni65_get_stats(struct device *);
 static void set_multicast_list(struct device *dev);
 
-static int irqtab[] = { 9,12,15,5 }; /* irq config-translate */
-static int dmatab[] = { 0,3,5,6,7 }; /* dma config-translate and autodetect */
+static int irqtab[] __initdata = { 9,12,15,5 }; /* irq config-translate */
+static int dmatab[] __initdata = { 0,3,5,6,7 }; /* dma config-translate and autodetect */
 
 static int debuglevel = 1;
 
@@ -327,7 +328,7 @@
 #ifdef MODULE
 static
 #endif
-int ni65_probe(struct device *dev)
+__initfunc(int ni65_probe(struct device *dev))
 {
 	int *port;
 	static int ports[] = {0x360,0x300,0x320,0x340, 0};
@@ -349,7 +350,7 @@
 /*
  * this is the real card probe ..
  */
-static int ni65_probe1(struct device *dev,int ioaddr)
+__initfunc(static int ni65_probe1(struct device *dev,int ioaddr))
 {
 	int i,j;
 	struct priv *p;
diff -u --recursive --new-file v2.1.35/linux/drivers/net/pcnet32.c linux/drivers/net/pcnet32.c
--- v2.1.35/linux/drivers/net/pcnet32.c	Fri Apr  4 08:52:21 1997
+++ linux/drivers/net/pcnet32.c	Tue Apr 22 22:42:49 1997
@@ -26,6 +26,7 @@
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/bios32.h>
+#include <linux/init.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/dma.h>
@@ -34,7 +35,7 @@
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 
-static unsigned int pcnet32_portlist[] = {0x300, 0x320, 0x340, 0x360, 0};
+static unsigned int pcnet32_portlist[] __initdata = {0x300, 0x320, 0x340, 0x360, 0};
 
 #ifdef PCNET32_DEBUG
 static int pcnet32_debug = PCNET32_DEBUG;
@@ -168,7 +169,7 @@
 
 
 
-int pcnet32_probe (struct device *dev)
+__initfunc(int pcnet32_probe (struct device *dev))
 {
     unsigned int  ioaddr = dev ? dev->base_addr: 0;
     unsigned char irq_line = dev ? dev->irq : 0;
@@ -246,7 +247,7 @@
 
 
 /* pcnet32_probe1 */
-int pcnet32_probe1(struct device *dev, unsigned int ioaddr, unsigned char irq_line, int shared)
+__initfunc(static int pcnet32_probe1(struct device *dev, unsigned int ioaddr, unsigned char irq_line, int shared))
 {
     struct pcnet32_private *lp;
     int i;
diff -u --recursive --new-file v2.1.35/linux/drivers/net/pi2.c linux/drivers/net/pi2.c
--- v2.1.35/linux/drivers/net/pi2.c	Fri Apr  4 08:52:21 1997
+++ linux/drivers/net/pi2.c	Tue Apr 22 22:42:49 1997
@@ -112,6 +112,7 @@
 #include <linux/timer.h>
 #include <linux/if_arp.h>
 #include <linux/pi2.h>
+#include <linux/init.h>
 #include "z8530.h"
 #include <net/ax25.h>
 
@@ -564,7 +565,6 @@
 		   pkt_len - 1);
 	    skb->protocol=htons(ETH_P_AX25);
 	    skb->mac.raw=skb->data;
-	    IS_SKB(skb);
 	    netif_rx(skb);
 	    lp->stats.rx_packets++;
 	}			/* end good frame */
@@ -652,7 +652,6 @@
 		memcpy(cfix, lp->rcvbuf->data, pkt_len - 1);
 		skb->protocol=ntohs(ETH_P_AX25);
 		skb->mac.raw=skb->data;
-		IS_SKB(skb);
 		netif_rx(skb);
 		lp->stats.rx_packets++;
 		/* packet queued - initialize buffer for next frame */
@@ -933,7 +932,7 @@
 /* Probe for a PI card. */
 /* This routine also initializes the timer chip */
 
-static int hw_probe(int ioaddr)
+__initfunc(static int hw_probe(int ioaddr))
 {
     int time = 1000;		/* Number of milliseconds for test */
     unsigned long start_time, end_time;
@@ -1188,13 +1187,12 @@
 }
 
 
-int pi_init(void)
+__initfunc(int pi_init(void))
 {
     int *port;
     int ioaddr = 0;
     int card_type = 0;
-    int ports[] =
-    {0x380, 0x300, 0x320, 0x340, 0x360, 0x3a0, 0};
+    int ports[] = {0x380, 0x300, 0x320, 0x340, 0x360, 0x3a0, 0};
 
     printk(KERN_INFO "PI: V0.8 ALPHA April 23 1995 David Perry (dp@hydra.carleton.ca)\n");
 
diff -u --recursive --new-file v2.1.35/linux/drivers/net/plip.c linux/drivers/net/plip.c
--- v2.1.35/linux/drivers/net/plip.c	Sun Apr 13 10:18:21 1997
+++ linux/drivers/net/plip.c	Tue Apr 22 22:42:49 1997
@@ -1,4 +1,4 @@
-/* $Id: plip.c,v 1.1.1.1.2.6 1997/03/26 17:52:20 phil Exp $ */
+/* $Id: plip.c,v 1.3.6.2 1997/04/16 15:07:56 phil Exp $ */
 /* PLIP: A parallel port "network" driver for Linux. */
 /* This driver is for parallel port with 5-bit cable (LapLink (R) cable). */
 /*
@@ -95,6 +95,7 @@
 #include <linux/errno.h>
 #include <linux/delay.h>
 #include <linux/lp.h>
+#include <linux/init.h>
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -223,8 +224,8 @@
    then calls us here.
 
    */
-int
-plip_init_dev(struct device *dev, struct parport *pb)
+__initfunc(int
+plip_init_dev(struct device *dev, struct parport *pb))
 {
 	struct net_local *nl;
 	struct ppd *pardev;
@@ -1190,8 +1191,8 @@
 	return 0;
 }
 
-int
-plip_init(void)
+__initfunc(int
+plip_init(void))
 {
 	struct parport *pb = parport_enumerate();
 	int devices=0;
diff -u --recursive --new-file v2.1.35/linux/drivers/net/ppp.c linux/drivers/net/ppp.c
--- v2.1.35/linux/drivers/net/ppp.c	Tue Mar  4 10:25:23 1997
+++ linux/drivers/net/ppp.c	Tue Apr 22 22:42:50 1997
@@ -85,6 +85,7 @@
 #include <linux/skbuff.h>
 #include <linux/inet.h>
 #include <linux/ioctl.h>
+#include <linux/init.h>
 
 typedef struct sk_buff	     sk_buff;
 #define skb_data(skb)	     ((__u8 *) (skb)->data)
@@ -334,8 +335,8 @@
  * accessing the ppp protocol.
  */
 
-static int
-ppp_first_time (void)
+__initfunc(static int
+ppp_first_time (void))
 {
 	static struct tty_ldisc	ppp_ldisc;
 	int    status;
diff -u --recursive --new-file v2.1.35/linux/drivers/net/pt.c linux/drivers/net/pt.c
--- v2.1.35/linux/drivers/net/pt.c	Fri Apr  4 08:52:21 1997
+++ linux/drivers/net/pt.c	Tue Apr 22 22:42:50 1997
@@ -92,6 +92,7 @@
 #include <linux/timer.h>
 #include <linux/if_arp.h>
 #include <linux/pt.h>
+#include <linux/init.h>
 #include "z8530.h"
 #include <net/ax25.h>
 
@@ -480,7 +481,7 @@
 
 
 
-int pt_init(void)
+__initfunc(int pt_init(void))
 {
     int *port;
     int ioaddr = 0;
@@ -542,7 +543,7 @@
 /*
  * Probe for PT card.  Also initialises the timers
  */
-static int hw_probe(int ioaddr)
+__initfunc(static int hw_probe(int ioaddr))
 {
     int time = 1000;		/* Number of milliseconds to test */
     int a = 1;
@@ -1380,7 +1381,6 @@
                  skb->protocol = ntohs(ETH_P_AX25);
                  skb->mac.raw=skb->data;
                  lp->stats.rx_bytes+=skb->len;
-                 IS_SKB(skb);
                  netif_rx(skb);
                  lp->stats.rx_packets++;
                  if (!lp->dmachan)
diff -u --recursive --new-file v2.1.35/linux/drivers/net/scc.c linux/drivers/net/scc.c
--- v2.1.35/linux/drivers/net/scc.c	Mon Apr 14 16:28:12 1997
+++ linux/drivers/net/scc.c	Tue Apr 22 22:42:50 1997
@@ -153,6 +153,7 @@
 #include <linux/if_ether.h>
 #include <linux/if_arp.h>
 #include <linux/socket.h>
+#include <linux/init.h>
 
 #include <linux/scc.h>
 #include "z8530.h"
@@ -2153,7 +2154,7 @@
 /* * 			Init SCC driver 			      * */
 /* ******************************************************************** */
 
-int scc_init (void)
+__initfunc(int scc_init (void))
 {
 	int chip, chan, k, result;
 	char devname[10];
diff -u --recursive --new-file v2.1.35/linux/drivers/net/sdla.c linux/drivers/net/sdla.c
--- v2.1.35/linux/drivers/net/sdla.c	Thu Feb 27 10:57:30 1997
+++ linux/drivers/net/sdla.c	Tue Apr 22 22:42:50 1997
@@ -46,6 +46,7 @@
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/errno.h>
+#include <linux/init.h>
 
 #include <asm/system.h>
 #include <asm/bitops.h>
@@ -64,9 +65,10 @@
 
 static const char* devname = "sdla";
 
-static unsigned int valid_port[] = { 0x250, 0x270, 0x280, 0x300, 0x350, 0x360, 0x380, 0x390};
+static unsigned int valid_port[] __initdata = { 0x250, 0x270, 0x280, 0x300, 0x350, 0x360, 0x380, 0x390};
 
-static unsigned int valid_mem[]  = {0xA0000, 0xA2000, 0xA4000, 0xA6000, 0xA8000, 0xAA000, 0xAC000, 0xAE000, 
+static unsigned int valid_mem[]  __initdata = {
+				    0xA0000, 0xA2000, 0xA4000, 0xA6000, 0xA8000, 0xAA000, 0xAC000, 0xAE000, 
                                     0xB0000, 0xB2000, 0xB4000, 0xB6000, 0xB8000, 0xBA000, 0xBC000, 0xBE000,
                                     0xC0000, 0xC2000, 0xC4000, 0xC6000, 0xC8000, 0xCA000, 0xCC000, 0xCE000,
                                     0xD0000, 0xD2000, 0xD4000, 0xD6000, 0xD8000, 0xDA000, 0xDC000, 0xDE000,
@@ -1621,7 +1623,7 @@
 	return(&flp->stats);
 }
 
-int sdla_init(struct device *dev)
+__initfunc(int sdla_init(struct device *dev))
 {
 	struct frad_local *flp;
 
@@ -1669,7 +1671,7 @@
 	return(0);
 }
 
-void sdla_setup(void)
+__initfunc(void sdla_setup(void))
 {
 	printk("%s.\n", version);
 	register_frad(devname);
diff -u --recursive --new-file v2.1.35/linux/drivers/net/sdla_fr.c linux/drivers/net/sdla_fr.c
--- v2.1.35/linux/drivers/net/sdla_fr.c	Fri Apr  4 08:52:21 1997
+++ linux/drivers/net/sdla_fr.c	Tue Apr 22 22:42:50 1997
@@ -25,6 +25,7 @@
 #include <linux/router.h>	/* WAN router definitions */
 #include <linux/wanpipe.h>	/* WANPIPE common user API definitions */
 #include <linux/if_arp.h>	/* ARPHRD_* defines */
+#include <linux/init.h>		/* __initfunc et al. */
 #include <asm/byteorder.h>	/* htons(), etc. */
 #include <asm/io.h>		/* for inb(), outb(), etc. */
 
@@ -135,7 +136,7 @@
  * Return:	0	o.k.
  *		< 0	failure.
  */
-int wpf_init (sdla_t* card, wandev_conf_t* conf)
+__initfunc(int wpf_init (sdla_t* card, wandev_conf_t* conf))
 {
 	union
 	{
diff -u --recursive --new-file v2.1.35/linux/drivers/net/sdla_ppp.c linux/drivers/net/sdla_ppp.c
--- v2.1.35/linux/drivers/net/sdla_ppp.c	Fri Apr  4 08:52:21 1997
+++ linux/drivers/net/sdla_ppp.c	Tue Apr 22 22:42:50 1997
@@ -25,6 +25,7 @@
 #include <linux/router.h>	/* WAN router definitions */
 #include <linux/wanpipe.h>	/* WANPIPE common user API definitions */
 #include <linux/if_arp.h>	/* ARPHRD_* defines */
+#include <linux/init.h>		/* __initfunc et al. */
 #include <asm/byteorder.h>	/* htons(), etc. */
 
 #define	_GNUC_
@@ -107,7 +108,7 @@
  * Return:	0	o.k.
  *		< 0	failure.
  */
-int wpp_init (sdla_t* card, wandev_conf_t* conf)
+__initfunc(int wpp_init (sdla_t* card, wandev_conf_t* conf))
 {
 	union
 	{
diff -u --recursive --new-file v2.1.35/linux/drivers/net/sdla_x25.c linux/drivers/net/sdla_x25.c
--- v2.1.35/linux/drivers/net/sdla_x25.c	Fri Apr  4 08:52:21 1997
+++ linux/drivers/net/sdla_x25.c	Tue Apr 22 22:42:50 1997
@@ -24,6 +24,7 @@
 #include <linux/malloc.h>	/* kmalloc(), kfree() */
 #include <linux/router.h>	/* WAN router definitions */
 #include <linux/wanpipe.h>	/* WANPIPE common user API definitions */
+#include <linux/init.h>		/* __initfunc et al. */
 #include <asm/byteorder.h>	/* htons(), etc. */
 
 #define	_GNUC_
@@ -168,7 +169,7 @@
  * Return:	0	o.k.
  *		< 0	failure.
  */
-int wpx_init (sdla_t* card, wandev_conf_t* conf)
+__initfunc(int wpx_init (sdla_t* card, wandev_conf_t* conf))
 {
 	union
 	{
diff -u --recursive --new-file v2.1.35/linux/drivers/net/sdladrv.c linux/drivers/net/sdladrv.c
--- v2.1.35/linux/drivers/net/sdladrv.c	Sun Feb  2 05:18:41 1997
+++ linux/drivers/net/sdladrv.c	Tue Apr 22 22:42:50 1997
@@ -90,6 +90,7 @@
 #include <linux/sched.h>	/* for jiffies, HZ, etc. */
 #include <linux/sdladrv.h>	/* API definitions */
 #include <linux/sdlasfm.h>	/* SDLA firmware module definitions */
+#include <linux/init.h>
 #include <asm/io.h>		/* for inb(), outb(), etc. */
 #define _INB(port)		(inb(port))
 #define _OUTB(port, byte)	(outb((byte),(port)))
@@ -289,7 +290,8 @@
 #ifdef MODULE
 int init_module (void)
 #else
-int wanpipe_init(void)
+__initfunc(int wanpipe_init(void))
+#endif
 {
 	printk(KERN_INFO "%s v%u.%u %s\n",
 		fullname, MOD_VERSION, MOD_RELEASE, copyright);
diff -u --recursive --new-file v2.1.35/linux/drivers/net/seeq8005.c linux/drivers/net/seeq8005.c
--- v2.1.35/linux/drivers/net/seeq8005.c	Fri Apr  4 08:52:21 1997
+++ linux/drivers/net/seeq8005.c	Tue Apr 22 22:42:50 1997
@@ -40,6 +40,7 @@
 #include <linux/in.h>
 #include <linux/malloc.h>
 #include <linux/string.h>
+#include <linux/init.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -53,7 +54,7 @@
 
 /* First, a few definitions that the brave might change. */
 /* A zero-terminated list of I/O addresses to be probed. */
-static unsigned int seeq8005_portlist[] =
+static unsigned int seeq8005_portlist[] __initdata =
    { 0x300, 0x320, 0x340, 0x360, 0};
 
 /* use 0 for production, 1 for verification, >2 for debug */
@@ -106,8 +107,8 @@
 struct netdev_entry seeq8005_drv =
 {"seeq8005", seeq8005_probe1, SEEQ8005_IO_EXTENT, seeq8005_portlist};
 #else
-int
-seeq8005_probe(struct device *dev)
+__initfunc(int
+seeq8005_probe(struct device *dev))
 {
 	int i;
 	int base_addr = dev ? dev->base_addr : 0;
@@ -133,7 +134,7 @@
    probes on the ISA bus.  A good device probes avoids doing writes, and
    verifies that the correct device exists and functions.  */
 
-static int seeq8005_probe1(struct device *dev, int ioaddr)
+__initfunc(static int seeq8005_probe1(struct device *dev, int ioaddr))
 {
 	static unsigned version_printed = 0;
 	int i,j;
diff -u --recursive --new-file v2.1.35/linux/drivers/net/shaper.c linux/drivers/net/shaper.c
--- v2.1.35/linux/drivers/net/shaper.c	Mon Apr 14 16:28:12 1997
+++ linux/drivers/net/shaper.c	Tue Apr 22 22:42:50 1997
@@ -68,6 +68,7 @@
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/if_arp.h>
+#include <linux/init.h>
 #include <net/dst.h>
 #include "shaper.h"
 
@@ -545,7 +546,7 @@
  *	Add a shaper device to the system
  */
  
-int shaper_probe(struct device *dev)
+__initfunc(int shaper_probe(struct device *dev))
 {
 	/*
 	 *	Set up the shaper.
diff -u --recursive --new-file v2.1.35/linux/drivers/net/slhc.c linux/drivers/net/slhc.c
--- v2.1.35/linux/drivers/net/slhc.c	Fri Dec 27 02:03:23 1996
+++ linux/drivers/net/slhc.c	Tue Apr 22 22:42:50 1997
@@ -77,6 +77,7 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <linux/mm.h>
+#include <linux/init.h>
 #include <net/checksum.h>
 #include <net/slhc_vj.h>
 #include <asm/unaligned.h>
@@ -743,7 +744,7 @@
 
 #else /* MODULE */
 
-void slhc_install(void)
+__initfunc(void slhc_install(void))
 {
 }
 
diff -u --recursive --new-file v2.1.35/linux/drivers/net/slip.c linux/drivers/net/slip.c
--- v2.1.35/linux/drivers/net/slip.c	Fri Apr  4 08:52:22 1997
+++ linux/drivers/net/slip.c	Tue Apr 22 22:42:50 1997
@@ -70,6 +70,7 @@
 #include <linux/skbuff.h>
 #include <linux/if_arp.h>
 #include <linux/if_slip.h>
+#include <linux/init.h>
 #include "slip.h"
 #ifdef CONFIG_INET
 #include <linux/ip.h>
@@ -1087,7 +1088,7 @@
 #ifdef MODULE
 static int slip_init_ctrl_dev(void)
 #else	/* !MODULE */
-int slip_init_ctrl_dev(struct device *dummy)
+__initfunc(int slip_init_ctrl_dev(struct device *dummy))
 #endif	/* !MODULE */
 {
 	int status;
diff -u --recursive --new-file v2.1.35/linux/drivers/net/smc-mca.c linux/drivers/net/smc-mca.c
--- v2.1.35/linux/drivers/net/smc-mca.c	Sun Jan 19 05:47:25 1997
+++ linux/drivers/net/smc-mca.c	Tue Apr 22 22:42:50 1997
@@ -32,6 +32,7 @@
 #include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/string.h>
+#include <linux/init.h>
 #include <asm/io.h>
 #include <asm/system.h>
 
@@ -66,7 +67,7 @@
 #define EN0_ERWCNT      0x08  /* Early receive warning count. */
 
 
-int ultramca_probe(struct device *dev)
+__initfunc(int ultramca_probe(struct device *dev))
 {
 	unsigned short ioaddr;
 	unsigned char reg4, num_pages;
diff -u --recursive --new-file v2.1.35/linux/drivers/net/smc-ultra.c linux/drivers/net/smc-ultra.c
--- v2.1.35/linux/drivers/net/smc-ultra.c	Mon Jan 13 22:58:19 1997
+++ linux/drivers/net/smc-ultra.c	Tue Apr 22 22:42:50 1997
@@ -53,6 +53,7 @@
 #include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/string.h>
+#include <linux/init.h>
 #include <asm/io.h>
 #include <asm/system.h>
 
@@ -61,7 +62,7 @@
 #include "8390.h"
 
 /* A zero-terminated list of I/O addresses to be probed. */
-static unsigned int ultra_portlist[] =
+static unsigned int ultra_portlist[] __initdata =
 {0x200, 0x220, 0x240, 0x280, 0x300, 0x340, 0x380, 0};
 
 int ultra_probe(struct device *dev);
@@ -104,7 +105,7 @@
 {"ultra", ultra_probe1, NETCARD_IO_EXTENT, netcard_portlist};
 #else
 
-int ultra_probe(struct device *dev)
+__initfunc(int ultra_probe(struct device *dev))
 {
 	int i;
 	int base_addr = dev ? dev->base_addr : 0;
@@ -126,7 +127,7 @@
 }
 #endif
 
-int ultra_probe1(struct device *dev, int ioaddr)
+__initfunc(int ultra_probe1(struct device *dev, int ioaddr))
 {
 	int i;
 	int checksum = 0;
diff -u --recursive --new-file v2.1.35/linux/drivers/net/smc9194.c linux/drivers/net/smc9194.c
--- v2.1.35/linux/drivers/net/smc9194.c	Fri Apr  4 08:52:22 1997
+++ linux/drivers/net/smc9194.c	Tue Apr 22 22:42:50 1997
@@ -66,6 +66,7 @@
 #include <linux/malloc.h>
 #include <linux/string.h>
 #include <linux/ioport.h>
+#include <linux/init.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <linux/errno.h>
@@ -108,7 +109,7 @@
  .for a slightly different card, you can add it to the array.  Keep in
  .mind that the array must end in zero.
 */
-static unsigned int smc_portlist[] =
+static unsigned int smc_portlist[] __initdata =
    { 0x200, 0x220, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x2E0,
 	  0x300, 0x320, 0x340, 0x360, 0x380, 0x3A0, 0x3C0, 0x3E0, 0};
 
@@ -750,7 +751,7 @@
  |
  ---------------------------------------------------------------------------
 */
-int smc_init(struct device *dev)
+__initfunc(int smc_init(struct device *dev))
 {
 	int i;
 	int base_addr = dev ? dev->base_addr : 0;
@@ -795,7 +796,7 @@
  . interrupt, so an auto-detect routine can detect it, and find the IRQ,
  ------------------------------------------------------------------------
 */
-int smc_findirq( int ioaddr )
+__initfunc(int smc_findirq( int ioaddr ))
 {
 	int	timeout = 20;
 
@@ -877,7 +878,7 @@
  .---------------------------------------------------------------------
  */
 
-static int smc_probe( int ioaddr )
+__initfunc(static int smc_probe( int ioaddr ))
 {
 	unsigned int	bank;
 	word	revision_register;
@@ -942,7 +943,7 @@
  . o  GRAB the region
  .-----------------------------------------------------------------
 */
-static int  smc_initcard(struct device *dev, int ioaddr)
+__initfunc(static int  smc_initcard(struct device *dev, int ioaddr))
 {
 	int i;
 
diff -u --recursive --new-file v2.1.35/linux/drivers/net/sunhme.c linux/drivers/net/sunhme.c
--- v2.1.35/linux/drivers/net/sunhme.c	Mon Apr 14 16:28:12 1997
+++ linux/drivers/net/sunhme.c	Thu Apr 17 13:20:46 1997
@@ -20,6 +20,7 @@
 #include <linux/in.h>
 #include <linux/malloc.h>
 #include <linux/string.h>
+#include <linux/init.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -2058,7 +2059,7 @@
 	dev->tbusy = 0;
 }
 
-static int happy_meal_ether_init(struct device *dev, struct linux_sbus_device *sdev)
+static inline int happy_meal_ether_init(struct device *dev, struct linux_sbus_device *sdev)
 {
 	static unsigned version_printed = 0;
 	struct happy_meal *hp;
@@ -2201,7 +2202,7 @@
 	return 0;
 }
 
-int happy_meal_probe(struct device *dev)
+__initfunc(int happy_meal_probe(struct device *dev))
 {
 	struct linux_sbus *bus;
 	struct linux_sbus_device *sdev = 0;
diff -u --recursive --new-file v2.1.35/linux/drivers/net/sunlance.c linux/drivers/net/sunlance.c
--- v2.1.35/linux/drivers/net/sunlance.c	Mon Apr 14 16:28:12 1997
+++ linux/drivers/net/sunlance.c	Thu Apr 17 13:20:46 1997
@@ -1,4 +1,4 @@
-/* $Id: sunlance.c,v 1.61 1997/04/10 06:40:54 davem Exp $
+/* $Id: sunlance.c,v 1.62 1997/04/16 10:27:25 jj Exp $
  * lance.c: Linux/Sparc/Lance driver
  *
  *	Written 1995, 1996 by Miguel de Icaza
@@ -75,6 +75,7 @@
 #include <linux/in.h>
 #include <linux/malloc.h>
 #include <linux/string.h>
+#include <linux/init.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -934,9 +935,10 @@
 	dev->tbusy = 0;
 }
 
-int sparc_lance_init (struct device *dev, struct linux_sbus_device *sdev,
-		      struct Linux_SBus_DMA *ledma,
-		      struct linux_sbus_device *lebuffer)
+__initfunc(static int 
+sparc_lance_init (struct device *dev, struct linux_sbus_device *sdev,
+		  struct Linux_SBus_DMA *ledma,
+		  struct linux_sbus_device *lebuffer))
 {
 	static unsigned version_printed = 0;
 	int    i;
@@ -1097,7 +1099,7 @@
 }
 
 /* On 4m, find the associated dma for the lance chip */
-static struct Linux_SBus_DMA *
+static inline struct Linux_SBus_DMA *
 find_ledma (struct linux_sbus_device *dev)
 {
 	struct Linux_SBus_DMA *p;
@@ -1109,7 +1111,7 @@
 }
 
 /* Find all the lance cards on the system and initialize them */
-int sparc_lance_probe (struct device *dev)
+__initfunc(int sparc_lance_probe (struct device *dev))
 {
 	struct linux_sbus *bus;
 	struct linux_sbus_device *sdev = 0;
diff -u --recursive --new-file v2.1.35/linux/drivers/net/sunqe.c linux/drivers/net/sunqe.c
--- v2.1.35/linux/drivers/net/sunqe.c	Mon Apr 14 16:28:12 1997
+++ linux/drivers/net/sunqe.c	Thu Apr 17 13:20:46 1997
@@ -21,6 +21,7 @@
 #include <linux/in.h>
 #include <linux/malloc.h>
 #include <linux/string.h>
+#include <linux/init.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -902,7 +903,7 @@
 }
 
 /* Four QE's per QEC card. */
-static int qec_ether_init(struct device *dev, struct linux_sbus_device *sdev)
+static inline int qec_ether_init(struct device *dev, struct linux_sbus_device *sdev)
 {
 	static unsigned version_printed = 0;
 	struct device *qe_devs[4];
@@ -1149,7 +1150,7 @@
 	return res;
 }
 
-int qec_probe(struct device *dev)
+__initfunc(int qec_probe(struct device *dev))
 {
 	struct linux_sbus *bus;
 	struct linux_sbus_device *sdev = 0;
diff -u --recursive --new-file v2.1.35/linux/drivers/net/tulip.c linux/drivers/net/tulip.c
--- v2.1.35/linux/drivers/net/tulip.c	Sun Feb  2 05:18:42 1997
+++ linux/drivers/net/tulip.c	Tue Apr 22 22:42:50 1997
@@ -62,6 +62,7 @@
 #include <linux/pci.h>
 #include <linux/bios32.h>
 #include <linux/delay.h>
+#include <linux/init.h>
 #include <asm/byteorder.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -473,8 +474,8 @@
    card_type returns 1 if the card is 'etherarray'
 */
 
-static int
-card_type(struct tulip_private *tp, int device_id, int vendor_id)
+__initfunc(static int
+card_type(struct tulip_private *tp, int device_id, int vendor_id))
 {
 	int n;
 
@@ -488,8 +489,8 @@
 	return(cardVendor[n].array ? 1: 0);
 }
 
-static int
-read_eeprom(int ioaddr, struct eeprom *eepp)
+__initfunc(static int
+read_eeprom(int ioaddr, struct eeprom *eepp))
 {
     int i, n;
     unsigned short val = 0;
@@ -1188,9 +1189,9 @@
 	}
 }
 
-int
+__initfunc(int
 tulip_hwinit(struct device *dev, int ioaddr,
-			 int irq, int device_id)
+			 int irq, int device_id))
 {
 	/* See note below on the Znyx 315 etherarray. */
 	static unsigned char last_phys_addr[6] = {0x00, 'L', 'i', 'n', 'u', 'x'};
@@ -1319,7 +1320,7 @@
 	return(0);
 }
 
-int tulip_probe(struct device *dev)
+__initfunc(int tulip_probe(struct device *dev))
 {
 	static struct device *tulip_head=NULL;
 	u_char pci_bus, pci_device_fn, pci_latency, pci_irq;
diff -u --recursive --new-file v2.1.35/linux/drivers/net/tunnel.c linux/drivers/net/tunnel.c
--- v2.1.35/linux/drivers/net/tunnel.c	Fri Apr  4 08:52:22 1997
+++ linux/drivers/net/tunnel.c	Tue Apr 22 22:42:50 1997
@@ -64,6 +64,7 @@
 #include <linux/in.h>
 #include <net/ip.h>
 #include <linux/if_arp.h>
+#include <linux/init.h>
 
 /*#define TUNNEL_DEBUG*/
 
@@ -213,7 +214,7 @@
  *	The new tunnel device structure is passed to us.
  */
  
-int tunnel_init(struct device *dev)
+__initfunc(int tunnel_init(struct device *dev))
 {
 	/* Oh, just say we're here, in case anyone cares */
 	static int tun_msg=0;
diff -u --recursive --new-file v2.1.35/linux/drivers/net/wavelan.c linux/drivers/net/wavelan.c
--- v2.1.35/linux/drivers/net/wavelan.c	Fri Apr  4 08:52:22 1997
+++ linux/drivers/net/wavelan.c	Thu Apr 17 14:40:36 1997
@@ -112,7 +112,7 @@
  * Read from card's Host Adaptor Status Register.
  */
 static inline u_short
-hasr_read(u_short	ioaddr)
+hasr_read(u_long	ioaddr)
 {
   return(inw(HASR(ioaddr)));
 } /* hasr_read */
@@ -122,7 +122,7 @@
  * Write to card's Host Adapter Command Register.
  */
 static inline void
-hacr_write(u_short	ioaddr,
+hacr_write(u_long	ioaddr,
 	   u_short	hacr)
 {
   outw(hacr, HACR(ioaddr));
@@ -134,7 +134,7 @@
  * those times when it is needed.
  */
 static inline void
-hacr_write_slow(u_short	ioaddr,
+hacr_write_slow(u_long	ioaddr,
 		u_short	hacr)
 {
   hacr_write(ioaddr, hacr);
@@ -147,7 +147,7 @@
  * Set the channel attention bit.
  */
 static inline void
-set_chan_attn(u_short	ioaddr,
+set_chan_attn(u_long	ioaddr,
 	      u_short	hacr)
 {
   hacr_write(ioaddr, hacr | HACR_CA);
@@ -158,7 +158,7 @@
  * Reset, and then set host adaptor into default mode.
  */
 static inline void
-wv_hacr_reset(u_short	ioaddr)
+wv_hacr_reset(u_long	ioaddr)
 {
   hacr_write_slow(ioaddr, HACR_RESET);
   hacr_write(ioaddr, HACR_DEFAULT);
@@ -169,7 +169,7 @@
  * Set the i/o transfer over the ISA bus to 8 bits mode
  */
 static inline void
-wv_16_off(u_short	ioaddr,
+wv_16_off(u_long	ioaddr,
 	  u_short	hacr)
 {
   hacr &= ~HACR_16BITS;
@@ -181,7 +181,7 @@
  * Set the i/o transfer over the ISA bus to 8 bits mode
  */
 static inline void
-wv_16_on(u_short	ioaddr,
+wv_16_on(u_long		ioaddr,
 	 u_short	hacr)
 {
   hacr |= HACR_16BITS;
@@ -196,7 +196,7 @@
 wv_ints_off(device *	dev)
 {
   net_local *	lp = (net_local *)dev->priv;
-  u_short	ioaddr = dev->base_addr;
+  u_long	ioaddr = dev->base_addr;
   u_long	x;
 
   x = wv_splhi();
@@ -215,7 +215,7 @@
 wv_ints_on(device *	dev)
 {
   net_local *	lp = (net_local *)dev->priv;
-  u_short	ioaddr = dev->base_addr;
+  u_long	ioaddr = dev->base_addr;
   u_long	x;
 
   x = wv_splhi();
@@ -239,7 +239,7 @@
  * Read bytes from the PSA.
  */
 static void
-psa_read(u_short	ioaddr,
+psa_read(u_long		ioaddr,
 	 u_short	hacr,
 	 int		o,	/* offset in PSA */
 	 u_char *	b,	/* buffer to fill */
@@ -262,7 +262,7 @@
  * Write the Paramter Storage Area to the WaveLAN card's memory
  */
 static void
-psa_write(u_short	ioaddr,
+psa_write(u_long	ioaddr,
 	  u_short	hacr,
 	  int		o,	/* Offset in psa */
 	  u_char *	b,	/* Buffer in memory */
@@ -329,7 +329,7 @@
  * Write 1 byte to the MMC.
  */
 static inline void
-mmc_out(u_short		ioaddr,
+mmc_out(u_long		ioaddr,
 	u_short		o,
 	u_char		d)
 {
@@ -347,7 +347,7 @@
  * We start by the end because it is the way it should be !
  */
 static inline void
-mmc_write(u_short	ioaddr,
+mmc_write(u_long	ioaddr,
 	  u_char	o,
 	  u_char *	b,
 	  int		n)
@@ -365,7 +365,7 @@
  * Optimised version for 1 byte, avoid using memory...
  */
 static inline u_char
-mmc_in(u_short	ioaddr,
+mmc_in(u_long	ioaddr,
        u_short	o)
 {
   while(inw(HASR(ioaddr)) & HASR_MMC_BUSY)
@@ -386,7 +386,7 @@
  * We start by the end because it is the way it should be !
  */
 static inline void
-mmc_read(u_short	ioaddr,
+mmc_read(u_long		ioaddr,
 	 u_char		o,
 	 u_char *	b,
 	 int		n)
@@ -400,11 +400,27 @@
 
 /*------------------------------------------------------------------*/
 /*
+ * Get the type of encryption available...
+ */
+static inline int
+mmc_encr(u_long		ioaddr)	/* i/o port of the card */
+{
+  int	temp;
+
+  temp = mmc_in(ioaddr, mmroff(0, mmr_des_avail));
+  if((temp != MMR_DES_AVAIL_DES) && (temp != MMR_DES_AVAIL_AES))
+    return 0;
+  else
+    return temp;
+}
+
+/*------------------------------------------------------------------*/
+/*
  * Wait for the frequency EEprom to complete a command...
  * I hope this one will be optimally inlined...
  */
 static inline void
-fee_wait(u_short	ioaddr,	/* i/o port of the card */
+fee_wait(u_long		ioaddr,	/* i/o port of the card */
 	 int		delay,	/* Base delay to wait for */
 	 int		number)	/* Number of time to wait */
 {
@@ -420,7 +436,7 @@
  * Read bytes from the Frequency EEprom (frequency select cards).
  */
 static void
-fee_read(u_short	ioaddr,	/* i/o port of the card */
+fee_read(u_long		ioaddr,	/* i/o port of the card */
 	 u_short	o,	/* destination offset */
 	 u_short *	b,	/* data buffer */
 	 int		n)	/* number of registers */
@@ -445,6 +461,8 @@
     }
 }
 
+#ifdef WIRELESS_EXT	/* If wireless extension exist in the kernel */
+
 /*------------------------------------------------------------------*/
 /*
  * Write bytes from the Frequency EEprom (frequency select cards).
@@ -453,7 +471,7 @@
  * Jean II
  */
 static void
-fee_write(u_short	ioaddr,	/* i/o port of the card */
+fee_write(u_long	ioaddr,	/* i/o port of the card */
 	  u_short	o,	/* destination offset */
 	  u_short *	b,	/* data buffer */
 	  int		n)	/* number of registers */
@@ -528,6 +546,7 @@
   fee_wait(ioaddr, 10, 100);
 #endif	/* EEPROM_IS_PROTECTED */
 }
+#endif	/* WIRELESS_EXT */
 
 /************************ I82586 SUBROUTINES *************************/
 /*
@@ -540,7 +559,7 @@
  * Why inlining this function make it fail ???
  */
 static /*inline*/ void
-obram_read(u_short	ioaddr,
+obram_read(u_long	ioaddr,
 	   u_short	o,
 	   u_char *	b,
 	   int		n)
@@ -554,7 +573,7 @@
  * Write bytes to the on-board RAM.
  */
 static inline void
-obram_write(u_short	ioaddr,
+obram_write(u_long	ioaddr,
 	    u_short	o,
 	    u_char *	b,
 	    int		n)
@@ -571,7 +590,7 @@
 wv_ack(device *		dev)
 {
   net_local *	lp = (net_local *)dev->priv;
-  u_short	ioaddr = dev->base_addr;
+  u_long	ioaddr = dev->base_addr;
   u_short	scb_cs;
   int		i;
 
@@ -614,7 +633,7 @@
 		   const char *	str)
 {
   net_local *	lp = (net_local *)dev->priv;
-  u_short	ioaddr = dev->base_addr;
+  u_long	ioaddr = dev->base_addr;
   u_short	scb_cmd;
   ach_t		cb;
   int		i;
@@ -660,7 +679,7 @@
  */
 static inline int
 wv_config_complete(device *	dev,
-		   u_short	ioaddr,
+		   u_long	ioaddr,
 		   net_local *	lp)
 {
   unsigned short	mcs_addr;
@@ -722,7 +741,7 @@
  */
 static int
 wv_complete(device *	dev,
-	    u_short	ioaddr,
+	    u_long	ioaddr,
 	    net_local *	lp)
 {
   int	nreaped = 0;
@@ -992,7 +1011,7 @@
 static void
 wv_mmc_show(device *	dev)
 {
-  u_short	ioaddr = dev->base_addr;
+  u_long	ioaddr = dev->base_addr;
   net_local *	lp = (net_local *)dev->priv;
   mmr_t		m;
 
@@ -1077,7 +1096,7 @@
  * Print the last block of the i82586 memory
  */
 static void
-wv_scb_show(unsigned short	ioaddr)
+wv_scb_show(u_long	ioaddr)
 {
   scb_t		scb;
 
@@ -1162,7 +1181,7 @@
 	       int		i,
 	       u_short		p)
 {
-  unsigned short	ioaddr;
+  u_long		ioaddr;
   ac_tx_t		actx;
 
   ioaddr = dev->base_addr;
@@ -1529,7 +1548,7 @@
  * (called in wavelan_ioctl)
  */
 static inline int
-wv_set_frequency(u_short	ioaddr,	/* i/o port of the card */
+wv_set_frequency(u_long		ioaddr,	/* i/o port of the card */
 		 iw_freq *	frequency)
 {
   const int	BAND_NUM = 10;	/* Number of bands */
@@ -1550,7 +1569,7 @@
     }
 
   /* Setting by channel (same as wfreqsel) */
-  /* Warning : each channel is 11MHz wide, so some of the channels
+  /* Warning : each channel is 22MHz wide, so some of the channels
    * will interfere... */
   if((frequency->e == 0) &&
      (frequency->m >= 0) && (frequency->m < BAND_NUM))
@@ -1729,7 +1748,7 @@
  * Give the list of available frequencies
  */
 static inline int
-wv_frequency_list(u_short	ioaddr,	/* i/o port of the card */
+wv_frequency_list(u_long	ioaddr,	/* i/o port of the card */
 		  iw_freq *	list,	/* List of frequency to fill */
 		  int		max)	/* Maximum number of frequencies */
 {
@@ -1826,7 +1845,7 @@
 	      struct ifreq *	rq,	/* Data passed */
 	      int		cmd)	/* Ioctl number */
 {
-  unsigned short	ioaddr = dev->base_addr;
+  u_long		ioaddr = dev->base_addr;
   net_local *		lp = (net_local *)dev->priv;	/* lp is not unused */
   struct iwreq *	wrq = (struct iwreq *) rq;
   psa_t			psa;
@@ -1866,9 +1885,7 @@
 	  m.w.mmw_netw_id_h = (wrq->u.nwid.nwid & 0xFF00) >> 8;
 	  mmc_write(ioaddr, (char *)&m.w.mmw_netw_id_l - (char *)&m,
 		    (unsigned char *)&m.w.mmw_netw_id_l, 2);
-	  m.w.mmw_loopt_sel = 0x00;
-	  mmc_write(ioaddr, (char *)&m.w.mmw_loopt_sel - (char *)&m,
-		    (unsigned char *)&m.w.mmw_loopt_sel, 1);
+	  mmc_out(ioaddr, mmwoff(0, mmw_loopt_sel), 0x00);
 	}
       else
 	{
@@ -1878,10 +1895,8 @@
 		    (char *)&psa.psa_nwid_select - (char *)&psa,
 		    (unsigned char *)&psa.psa_nwid_select, 1);
 
-	  /* Disable nwid in the mmc (no check) */
-	  m.w.mmw_loopt_sel = MMW_LOOPT_SEL_DIS_NWID;
-	  mmc_write(ioaddr, (char *)&m.w.mmw_loopt_sel - (char *)&m,
-		    (unsigned char *)&m.w.mmw_loopt_sel, 1);
+	  /* Disable nwid in the mmc (no filtering) */
+	  mmc_out(ioaddr, mmwoff(0, mmw_loopt_sel), MMW_LOOPT_SEL_DIS_NWID);
 	}
       break;
 
@@ -1950,6 +1965,82 @@
       wrq->u.sensitivity = psa.psa_thr_pre_set & 0x3F;
       break;
 
+     case SIOCSIWENCODE:
+       /* Set encryption key */
+       if(!mmc_encr(ioaddr))
+	 {
+	   ret = -EOPNOTSUPP;
+	   break;
+	 }
+
+       if(wrq->u.encoding.method)
+	 {	/* enable encryption */
+	   int		i;
+	   long long	key = wrq->u.encoding.code;
+
+	   for(i = 7; i >= 0; i--)
+	     {
+	       psa.psa_encryption_key[i] = key & 0xFF;
+	       key >>= 8;
+	     }
+           psa.psa_encryption_select = 1;
+	   psa_write(ioaddr, lp->hacr,
+		     (char *) &psa.psa_encryption_select - (char *) &psa,
+		     (unsigned char *) &psa.psa_encryption_select, 8+1);
+
+           mmc_out(ioaddr, mmwoff(0, mmw_encr_enable),
+		   MMW_ENCR_ENABLE_EN | MMW_ENCR_ENABLE_MODE);
+           mmc_write(ioaddr, mmwoff(0, mmw_encr_key),
+		     (unsigned char *) &psa.psa_encryption_key, 8);
+	 }
+       else
+	 {	/* disable encryption */
+	   psa.psa_encryption_select = 0;
+	   psa_write(ioaddr, lp->hacr,
+		     (char *) &psa.psa_encryption_select - (char *) &psa,
+		     (unsigned char *) &psa.psa_encryption_select, 1);
+
+	   mmc_out(ioaddr, mmwoff(0, mmw_encr_enable), 0);
+	 }
+       break;
+
+     case SIOCGIWENCODE:
+       /* Read the encryption key */
+       if(!mmc_encr(ioaddr))
+	 {
+	   ret = -EOPNOTSUPP;
+	   break;
+	 }
+
+       /* only super-user can see encryption key */
+       if(!suser())
+	 {
+	   ret = -EPERM;
+	   break;
+	 }
+       else
+	 {
+	   int		i;
+	   long long	key = 0;
+
+	   psa_read(ioaddr, lp->hacr,
+		    (char *) &psa.psa_encryption_select - (char *) &psa,
+		    (unsigned char *) &psa.psa_encryption_select, 1+8);
+	   for(i = 0; i < 8; i++)
+	     {
+	       key <<= 8;
+	       key += psa.psa_encryption_key[i];
+	     }
+	   wrq->u.encoding.code = key;
+
+	   /* encryption is enabled */
+	   if(psa.psa_encryption_select)
+	     wrq->u.encoding.method = mmc_encr(ioaddr);
+	   else
+	     wrq->u.encoding.method = 0;
+	 }
+       break;
+
     case SIOCGIWRANGE:
       /* Basic checking... */
       if(wrq->u.data.pointer != (caddr_t) 0)
@@ -2207,7 +2298,7 @@
 static iw_stats *
 wavelan_get_wireless_stats(device *	dev)
 {
-  unsigned short	ioaddr = dev->base_addr;
+  u_long		ioaddr = dev->base_addr;
   net_local *		lp = (net_local *) dev->priv;
   mmr_t			m;
   iw_stats *		wstats;
@@ -2281,7 +2372,7 @@
 	       int		sksize)
 {
   net_local *		lp = (net_local *) dev->priv;
-  u_short		ioaddr = dev->base_addr;
+  u_long		ioaddr = dev->base_addr;
   struct sk_buff *	skb;
 
 #ifdef DEBUG_RX_TRACE
@@ -2353,8 +2444,9 @@
    */
   netif_rx(skb);
 
+  /* Keep stats up to date */
   lp->stats.rx_packets++;
-  lp->stats.rx_bytes+=sksize;
+  lp->stats.rx_bytes += skb->len;
 
 #ifdef DEBUG_RX_TRACE
   printk(KERN_DEBUG "%s: <-wv_packet_read()\n", dev->name);
@@ -2370,7 +2462,7 @@
 static inline void
 wv_receive(device *	dev)
 {
-  u_short	ioaddr = dev->base_addr;
+  u_long	ioaddr = dev->base_addr;
   net_local *	lp = (net_local *)dev->priv;
   int		nreaped = 0;
 
@@ -2556,7 +2648,7 @@
 		short	length)
 {
   net_local *		lp = (net_local *) dev->priv;
-  u_short		ioaddr = dev->base_addr;
+  u_long		ioaddr = dev->base_addr;
   unsigned short	txblock;
   unsigned short	txpred;
   unsigned short	tx_addr;
@@ -2649,6 +2741,9 @@
 	      (unsigned char *) &nop.nop_h.ac_link,
 	      sizeof(nop.nop_h.ac_link));
 
+  /* Keep stats up to date */
+  lp->stats.tx_bytes += length;
+
   /* If watchdog not already active, activate it... */
   if(lp->watchdog.prev == (timer_list *) NULL)
     {
@@ -2701,20 +2796,6 @@
     return 1;
 
   /*
-   * If some higher layer thinks we've missed
-   * a tx-done interrupt we are passed NULL.
-   * Caution: dev_tint() handles the cli()/sti() itself.
-   */
-  if(skb == (struct sk_buff *)0)
-    {
-#ifdef DEBUG_TX_ERROR
-      printk(KERN_INFO "%s: wavelan_packet_xmit(): skb == NULL\n", dev->name);
-#endif
-      dev_tint(dev);
-      return 0;
-    }
-
-  /*
    * Block a timer-based transmit from overlapping.
    * In other words, prevent reentering this routine.
    */
@@ -2761,7 +2842,7 @@
 static inline int
 wv_mmc_init(device *	dev)
 {
-  u_short	ioaddr = dev->base_addr;
+  u_long	ioaddr = dev->base_addr;
   net_local *	lp = (net_local *)dev->priv;
   psa_t		psa;
   mmw_t		m;
@@ -2790,6 +2871,9 @@
       /* As NWID is not set : no NWID checking */
       psa.psa_nwid_select = 0;
 
+      /* Disable encryption */
+      psa.psa_encryption_select = 0;
+
       /* Set to standard values
        * 0x04 for AT,
        * 0x01 for MCA,
@@ -2807,7 +2891,7 @@
 #ifdef USE_PSA_CONFIG
       /* Write the psa */
       psa_write(ioaddr, lp->hacr, (char *)psa.psa_nwid - (char *)&psa,
-		(unsigned char *)psa.psa_nwid, 3);
+		(unsigned char *)psa.psa_nwid, 4);
       psa_write(ioaddr, lp->hacr, (char *)&psa.psa_thr_pre_set - (char *)&psa,
 		(unsigned char *)&psa.psa_thr_pre_set, 1);
       psa_write(ioaddr, lp->hacr, (char *)&psa.psa_quality_thr - (char *)&psa,
@@ -2829,6 +2913,14 @@
   else
     m.mmw_loopt_sel = MMW_LOOPT_SEL_DIS_NWID;
 
+  memcpy(&m.mmw_encr_key, &psa.psa_encryption_key, 
+	 sizeof(m.mmw_encr_key));
+
+  if(psa.psa_encryption_select)
+    m.mmw_encr_enable = MMW_ENCR_ENABLE_EN | MMW_ENCR_ENABLE_MODE;
+  else
+    m.mmw_encr_enable = 0;
+
   m.mmw_thr_pre_set = psa.psa_thr_pre_set & 0x3F;
   m.mmw_quality_thr = psa.psa_quality_thr & 0x0F;
 
@@ -2920,7 +3012,7 @@
 wv_ru_start(device *	dev)
 {
   net_local *	lp = (net_local *) dev->priv;
-  u_short	ioaddr = dev->base_addr;
+  u_long	ioaddr = dev->base_addr;
   u_short	scb_cs;
   fd_t		fd;
   rbd_t		rbd;
@@ -3014,7 +3106,7 @@
 wv_cu_start(device *	dev)
 {
   net_local *	lp = (net_local *) dev->priv;
-  u_short	ioaddr = dev->base_addr;
+  u_long	ioaddr = dev->base_addr;
   int		i;
   u_short	txblock;
   u_short	first_nop;
@@ -3115,7 +3207,7 @@
 wv_82586_start(device *	dev)
 {
   net_local *	lp = (net_local *) dev->priv;
-  u_short	ioaddr = dev->base_addr;
+  u_long	ioaddr = dev->base_addr;
   scp_t		scp;		/* system configuration pointer */
   iscp_t	iscp;		/* intermediate scp */
   scb_t		scb;		/* system control block */
@@ -3245,7 +3337,7 @@
 wv_82586_config(device *	dev)
 {
   net_local *		lp = (net_local *) dev->priv;
-  u_short		ioaddr = dev->base_addr;
+  u_long		ioaddr = dev->base_addr;
   unsigned short	txblock;
   unsigned short	txpred;
   unsigned short	tx_addr;
@@ -3441,7 +3533,7 @@
 wv_82586_stop(device *	dev)
 {
   net_local *	lp = (net_local *) dev->priv;
-  u_short	ioaddr = dev->base_addr;
+  u_long	ioaddr = dev->base_addr;
   u_short	scb_cmd;
 
 #ifdef DEBUG_CONFIG_TRACE
@@ -3476,7 +3568,7 @@
 wv_hw_reset(device *	dev)
 {
   net_local *	lp = (net_local *)dev->priv;
-  u_short	ioaddr = dev->base_addr;
+  u_long	ioaddr = dev->base_addr;
 
 #ifdef DEBUG_CONFIG_TRACE
   printk(KERN_DEBUG "%s: ->wv_hw_reset(dev=0x%x)\n", dev->name,
@@ -3521,7 +3613,7 @@
  * (called in wavelan_probe() and init_module())
  */
 static int
-wv_check_ioaddr(u_short		ioaddr,
+wv_check_ioaddr(u_long		ioaddr,
 		u_char *	mac)
 {
   int		i;		/* Loop counter */
@@ -3568,7 +3660,7 @@
 		  struct pt_regs *	regs)
 {
   device *	dev;
-  u_short	ioaddr;
+  u_long	ioaddr;
   net_local *	lp;
   u_short	hasr;
   u_short	status;
@@ -3715,7 +3807,7 @@
 {
   device *		dev;
   net_local *		lp;
-  unsigned short	ioaddr;
+  u_long		ioaddr;
   unsigned long		x;
   unsigned int		nreaped;
 
@@ -3910,7 +4002,7 @@
 static int
 wavelan_config(device *	dev)
 {
-  u_short	ioaddr = dev->base_addr;
+  u_long	ioaddr = dev->base_addr;
   u_char	irq_mask;
   int		irq;
   net_local *	lp;
diff -u --recursive --new-file v2.1.35/linux/drivers/net/wavelan.p.h linux/drivers/net/wavelan.p.h
--- v2.1.35/linux/drivers/net/wavelan.p.h	Mon Mar 17 14:54:27 1997
+++ linux/drivers/net/wavelan.p.h	Thu Apr 17 14:40:36 1997
@@ -35,6 +35,12 @@
 
 /* ------------------------ SPECIFIC NOTES ------------------------ */
 /*
+ * wavelan.o is darn too big
+ * -------------------------
+ *	That's true ! There is a very simple way to reduce the driver
+ *	object by 33% (yes !). Comment out the following line :
+ *		#include <linux/wireless.h>
+ *
  * MAC address and hardware detection :
  * ----------------------------------
  *	The detection code of the wavelan chech that the first 3
@@ -80,14 +86,12 @@
  * caracteristics of the hardware in a standard way and support for
  * applications for taking advantage of it (like Mobile IP).
  *
- * By default, these wireless extensions are disabled, because they
- * need a patch to the Linux Kernel. This simple patch may be found
- * with the driver + some utilities to access those wireless
- * extensions (iwconfig...). Hopefully, those wireless extensions will
- * make their way in the kernel someday.
+ * You will need to enable the CONFIG_NET_RADIO define in the kernel
+ * configuration to enable the wireless extensions (this is the one
+ * giving access to the radio network device choice).
  *
- * You also will need to enable the CONFIG_NET_RADIO in the kernel
- * configuration to enable the wireless extensions.
+ * It might also be a good idea as well to fetch the wireless tools to
+ * configure the device and play a bit.
  */
 
 /* ---------------------------- FILES ---------------------------- */
@@ -161,6 +165,7 @@
  *	Ajay Bakre (bakre@paul.rutgers.edu),
  *	Donald Becker (becker@cesdis.gsfc.nasa.gov),
  *	Loeke Brederveld (Loeke.Brederveld@Utrecht.NCR.com),
+ *	Brent Elphick <belphick@uwaterloo.ca>,
  *	Anders Klemets (klemets@it.kth.se),
  *	Vladimir V. Kolpakov (w@stier.koenig.ru),
  *	Marc Meertens (Marc.Meertens@Utrecht.NCR.com),
@@ -185,6 +190,7 @@
  *	John Rosenberg (johnr@cs.usyd.edu.au),
  *	George Rossi (george@phm.gov.au),
  *	Arthur Scott (arthur@cs.usyd.edu.au),
+ *	Stanislav Sinyagin <stas@isf.ru>
  *	Peter Storey,
  * for their assistance and advice.
  *
@@ -254,16 +260,22 @@
  *	- Update to wireless extensions changes
  *	- Silly bug in card initial configuration (psa_conf_status)
  *
- * Changes made for release in 2.1.27 :
- * ----------------------------------
+ * Changes made for release in 2.1.27 & 2.0.30 :
+ * -------------------------------------------
  *	- Small bug in debug code (probably not the last one...)
  *	- Remove extern kerword for wavelan_probe()
  *	- Level threshold is now a standard wireless extension (version 4 !)
  *	- modules parameters types (new module interface)
  *
+ * Changes made for release in 2.1.36 :
+ * ----------------------------------
+ *	- byte count stats (courtesy of David Hinds)
+ *	- Remove dev_tint stuff (courtesy of David Hinds)
+ *	- Encryption setting from Brent Elphick (thanks a lot !)
+ *	- 'ioaddr' to 'u_long' for the Alpha (thanks to Stanislav Sinyagin)
+ *
  * Wishes & dreams :
  * ---------------
- *	- Encryption stuff
  *	- Roaming
  */
 
@@ -347,7 +359,7 @@
 /************************ CONSTANTS & MACROS ************************/
 
 #ifdef DEBUG_VERSION_SHOW
-static const char	*version	= "wavelan.c : v15 (wireless extensions) 12/2/97\n";
+static const char	*version	= "wavelan.c : v16 (wireless extensions) 17/4/97\n";
 #endif
 
 /* Watchdog temporisation */
@@ -436,69 +448,65 @@
 	wv_psa_to_irq(u_char);
 /* ------------------- HOST ADAPTER SUBROUTINES ------------------- */
 static inline u_short		/* data */
-	hasr_read(u_short);	/* Read the host interface : base address */
+	hasr_read(u_long);	/* Read the host interface : base address */
 static inline void
-	hacr_write(u_short,	/* Write to host interface : base address */
+	hacr_write(u_long,	/* Write to host interface : base address */
 		   u_short),	/* data */
-	hacr_write_slow(u_short,
+	hacr_write_slow(u_long,
 		   u_short),
-	set_chan_attn(u_short,	/* ioaddr */
+	set_chan_attn(u_long,	/* ioaddr */
 		      u_short),	/* hacr */
-	wv_hacr_reset(u_short),	/* ioaddr */
-	wv_16_off(u_short,	/* ioaddr */
+	wv_hacr_reset(u_long),	/* ioaddr */
+	wv_16_off(u_long,	/* ioaddr */
 		  u_short),	/* hacr */
-	wv_16_on(u_short,	/* ioaddr */
+	wv_16_on(u_long,	/* ioaddr */
 		 u_short),	/* hacr */
 	wv_ints_off(device *),
 	wv_ints_on(device *);
 /* ----------------- MODEM MANAGEMENT SUBROUTINES ----------------- */
 static void
-	psa_read(u_short,	/* Read the Parameter Storage Area */
+	psa_read(u_long,	/* Read the Parameter Storage Area */
 		 u_short,	/* hacr */
 		 int,		/* offset in PSA */
 		 u_char *,	/* buffer to fill */
 		 int),		/* size to read */
-	psa_write(u_short, 	/* Write to the PSA */
+	psa_write(u_long, 	/* Write to the PSA */
 		  u_short,	/* hacr */
 		  int,		/* Offset in psa */
 		  u_char *,	/* Buffer in memory */
 		  int);		/* Length of buffer */
 static inline void
-	mmc_out(u_short,	/* Write 1 byte to the Modem Manag Control */
+	mmc_out(u_long,		/* Write 1 byte to the Modem Manag Control */
 		u_short,
 		u_char),
-	mmc_write(u_short,	/* Write n bytes to the MMC */
+	mmc_write(u_long,	/* Write n bytes to the MMC */
 		  u_char,
 		  u_char *,
 		  int);
 static inline u_char		/* Read 1 byte from the MMC */
-	mmc_in(u_short,
+	mmc_in(u_long,
 	       u_short);
 static inline void
-	mmc_read(u_short,	/* Read n bytes from the MMC */
+	mmc_read(u_long,	/* Read n bytes from the MMC */
 		 u_char,
 		 u_char *,
 		 int),
-	fee_wait(u_short,	/* Wait for frequency EEprom : base address */
+	fee_wait(u_long,	/* Wait for frequency EEprom : base address */
 		 int,		/* Base delay to wait for */
 		 int);		/* Number of time to wait */
 static void
-	fee_read(u_short,	/* Read the frequency EEprom : base address */
+	fee_read(u_long,	/* Read the frequency EEprom : base address */
 		 u_short,	/* destination offset */
 		 u_short *,	/* data buffer */
-		 int),		/* number of registers */
-	fee_write(u_short,	/* Write to frequency EEprom : base address */
-		  u_short,	/* destination offset */
-		  u_short *,	/* data buffer */
-		  int);		/* number of registers */
+		 int);		/* number of registers */
 /* ---------------------- I82586 SUBROUTINES ----------------------- */
 static /*inline*/ void
-	obram_read(u_short,	/* ioaddr */
+	obram_read(u_long,	/* ioaddr */
 		   u_short,	/* o */
 		   u_char *,	/* b */
 		   int);	/* n */
 static inline void
-	obram_write(u_short,	/* ioaddr */
+	obram_write(u_long,	/* ioaddr */
 		    u_short,	/* o */
 		    u_char *,	/* b */
 		    int);	/* n */
@@ -508,11 +516,11 @@
 	wv_synchronous_cmd(device *,
 			   const char *),
 	wv_config_complete(device *,
-			   u_short,
+			   u_long,
 			   net_local *);
 static int
 	wv_complete(device *,
-		    u_short,
+		    u_long,
 		    net_local *);
 static inline void
 	wv_82586_reconfig(device *);
@@ -554,7 +562,7 @@
 	wv_82586_stop(device *);
 static int
 	wv_hw_reset(device *),		/* Reset the wavelan hardware */
-	wv_check_ioaddr(u_short,	/* ioaddr */
+	wv_check_ioaddr(u_long,		/* ioaddr */
 			u_char *);	/* mac address (read) */
 /* ---------------------- INTERRUPT HANDLING ---------------------- */
 static void
diff -u --recursive --new-file v2.1.35/linux/drivers/net/wd.c linux/drivers/net/wd.c
--- v2.1.35/linux/drivers/net/wd.c	Tue Dec 31 00:30:05 1996
+++ linux/drivers/net/wd.c	Tue Apr 22 22:42:50 1997
@@ -33,6 +33,7 @@
 #include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/string.h>
+#include <linux/init.h>
 #include <asm/io.h>
 #include <asm/system.h>
 
@@ -41,7 +42,7 @@
 #include "8390.h"
 
 /* A zero-terminated list of I/O addresses to be probed. */
-static unsigned int wd_portlist[] =
+static unsigned int wd_portlist[] __initdata =
 {0x300, 0x280, 0x380, 0x240, 0};
 
 int wd_probe(struct device *dev);
@@ -85,7 +86,7 @@
 {"wd", wd_probe1, WD_IO_EXTENT, wd_portlist};
 #else
 
-int wd_probe(struct device *dev)
+__initfunc(int wd_probe(struct device *dev))
 {
 	int i;
 	int base_addr = dev ? dev->base_addr : 0;
@@ -107,7 +108,7 @@
 }
 #endif
 
-int wd_probe1(struct device *dev, int ioaddr)
+__initfunc(int wd_probe1(struct device *dev, int ioaddr))
 {
 	int i;
 	int checksum = 0;
diff -u --recursive --new-file v2.1.35/linux/drivers/net/x25_asy.c linux/drivers/net/x25_asy.c
--- v2.1.35/linux/drivers/net/x25_asy.c	Fri Apr  4 08:52:22 1997
+++ linux/drivers/net/x25_asy.c	Tue Apr 22 22:42:50 1997
@@ -24,6 +24,7 @@
 #include <linux/if_arp.h>
 #include <linux/x25.h>
 #include <linux/lapb.h>
+#include <linux/init.h>
 #include "x25_asy.h"
 
 typedef struct x25_ctrl {
@@ -808,7 +809,7 @@
 #ifdef MODULE
 static int x25_asy_init_ctrl_dev(void)
 #else	/* !MODULE */
-int x25_asy_init_ctrl_dev(struct device *dummy)
+__initfunc(int x25_asy_init_ctrl_dev(struct device *dummy))
 #endif	/* !MODULE */
 {
 	int status;
diff -u --recursive --new-file v2.1.35/linux/drivers/net/znet.c linux/drivers/net/znet.c
--- v2.1.35/linux/drivers/net/znet.c	Sun Feb  2 05:18:43 1997
+++ linux/drivers/net/znet.c	Tue Apr 22 22:42:50 1997
@@ -69,6 +69,7 @@
 #include <linux/errno.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
+#include <linux/init.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -199,7 +200,7 @@
    BIOS area.  We just scan for the signature, and pull the vital parameters
    out of the structure. */
 
-int znet_probe(struct device *dev)
+__initfunc(int znet_probe(struct device *dev))
 {
 	int i;
 	struct netidblk *netinfo;
diff -u --recursive --new-file v2.1.35/linux/drivers/pci/pci.c linux/drivers/pci/pci.c
--- v2.1.35/linux/drivers/pci/pci.c	Fri Apr  4 08:52:22 1997
+++ linux/drivers/pci/pci.c	Tue Apr 22 15:32:00 1997
@@ -261,6 +261,7 @@
 	DEVICE(	INTEL,		INTEL_82371SB_1,"82371SB Natoma/Triton II PIIX3"),
 	DEVICE( INTEL,		INTEL_82371SB_2,"82371SB Natoma/Triton II PIIX3"),
 	DEVICE( INTEL,		INTEL_82437VX,	"82437VX Triton II"),
+	DEVICE( INTEL,		INTEL_82371AB,	"82371AB 430TX PIIX4"),
 	DEVICE( INTEL,		INTEL_P6,	"Orion P6"),
 	DEVICE(	KTI,		KTI_ET32P2,	"ET32P2"),
 	DEVICE( ADAPTEC,	ADAPTEC_7850,	"AIC-7850"),
diff -u --recursive --new-file v2.1.35/linux/drivers/pnp/BUGS-parport linux/drivers/pnp/BUGS-parport
--- v2.1.35/linux/drivers/pnp/BUGS-parport	Sun Apr 13 10:18:21 1997
+++ linux/drivers/pnp/BUGS-parport	Thu Apr 17 14:48:53 1997
@@ -1,8 +1,6 @@
 Currently known (or at least suspected) bugs in parport:
 
-o /proc/parport is buggy under 2.0.29 (ls /proc/parport/0 gives no such
-  file or directory).  David has suggested a fix for this.  [/proc/parport
-  has been temporarily taken out]
+o /proc/parport is untested under 2.0.XX
 
 o SCSI aborts for PPA under 2.0.29 [reported by jmr].  Under investigation.
 
diff -u --recursive --new-file v2.1.35/linux/drivers/pnp/Makefile linux/drivers/pnp/Makefile
--- v2.1.35/linux/drivers/pnp/Makefile	Sun Apr 13 10:18:21 1997
+++ linux/drivers/pnp/Makefile	Thu Apr 17 14:48:53 1997
@@ -23,14 +23,20 @@
 MIX_OBJS :=
 
 ifeq ($(CONFIG_PNP_PARPORT),y)
-  L_OBJS += parport_share.o parport_procfs.o
+  L_OBJS += parport_share.o
+  ifeq ($(CONFIG_PROC_FS),y)
+    L_OBJS += parport_procfs.o
+  endif
   ifeq ($(CONFIG_PNP_PARPORT_AUTOPROBE),y)
     L_OBJS += parport_probe.o
   endif
   LX_OBJS += parport_init.o
 else
   ifeq ($(CONFIG_PNP_PARPORT),m)
-    MI_OBJS += parport_share.o parport_procfs.o
+    MI_OBJS += parport_share.o
+    ifneq ($(CONFIG_PROC_FS),n) 
+      MI_OBJS += parport_procfs.o
+    endif
     ifeq ($(CONFIG_PNP_PARPORT_AUTOPROBE),y)
       MI_OBJS += parport_probe.o
     endif
diff -u --recursive --new-file v2.1.35/linux/drivers/pnp/TODO-parport linux/drivers/pnp/TODO-parport
--- v2.1.35/linux/drivers/pnp/TODO-parport	Sun Apr 13 10:18:21 1997
+++ linux/drivers/pnp/TODO-parport	Thu Apr 17 14:48:53 1997
@@ -2,31 +2,9 @@
 
 0. Fix the bugs (see BUGS-parport).
 
-1. Write a /proc interface for parport.  As a starting point, we could
-   probably have something like this:
+1. Proper documentation.
 
-   /proc/parport/N/hardware
-
-        Details of the port hardware - chipset, capabilities and so on.
-        Read-only.
-
-   /proc/parport/N/irq
-
-        IRQ number of the port.  Read-write.
-
-   /proc/parport/N/devices
-
-        List of devices connected to this bus, with the currently active
-        one marked in some way.  Probably you'd have the device in the
-        first column, and '*' (for the current device) or '-' (for a
-        lurker) in the second column.
-
-   NOTE: The directory structure has been coded -- but the files are
-         missing ...
-
-2. Proper documentation.
-
-3. Overhaul lp.c:
+2. Overhaul lp.c:
 
    a) It's a mess, and there is a lot of code duplication.
 
@@ -40,4 +18,4 @@
       bits when they have something to say.  We should read out and deal 
       with (maybe just log) whatever the printer wants to tell the world.
 
-4. Assimilate more drivers.
+3. Assimilate more drivers.
diff -u --recursive --new-file v2.1.35/linux/drivers/pnp/parport_init.c linux/drivers/pnp/parport_init.c
--- v2.1.35/linux/drivers/pnp/parport_init.c	Mon Apr 14 16:28:12 1997
+++ linux/drivers/pnp/parport_init.c	Tue Apr 22 09:32:11 1997
@@ -1,4 +1,4 @@
-/* $Id: parport_init.c,v 1.1.2.4 1997/04/01 18:19:10 phil Exp $
+/* $Id: parport_init.c,v 1.3.2.4 1997/04/16 21:20:44 phil Exp $
  * Parallel-port initialisation code.
  * 
  * Authors: David Campbell <campbell@tirian.che.curtin.edu.au>
@@ -26,8 +26,8 @@
 #include "parport_ll_io.h"
 
 static int io[PARPORT_MAX] = { 0, };
-static int irq[PARPORT_MAX] = { -1, };
-static int dma[PARPORT_MAX] = { -1, };
+static int irq[PARPORT_MAX] = { PARPORT_IRQ_NONE, };
+static int dma[PARPORT_MAX] = { PARPORT_DMA_NONE, };
 
 /******************************************************
  *  DMA detection section:
@@ -76,7 +76,7 @@
 	return dma;
 }
 
-static int parport_detect_dma_transfer(int dma,int size)
+static int parport_detect_dma_transfer(int dma,int size,int *resid)
 {
 	int i,n,retv;
 	int count=0;
@@ -88,10 +88,11 @@
 			clear_dma_ff(i);
 			n = get_dma_residue(i);
 			if (n != size) {
+				*resid = n;
 				retv = i;
 				if (count > 0) {
 					retv = -1;	/* Multiple DMA's */
-					printk("Multiple DMA detected.\n");
+					printk(KERN_ERR "parport: multiple DMA detected.  Huh?\n");
 				}
 				count++;
 			}
@@ -118,7 +119,7 @@
 		return dma;
 }
 
-/* Only called if port support ECP mode.
+/* Only called if port supports ECP mode.
  *
  * The only restriction on DMA channels is that it has to be
  * between 0 to 7 (inclusive). Used only in an ECP mode, DMAs are
@@ -146,12 +147,11 @@
 	char *buff;
 
 	retv = programmable_dma_support(pb);
-	if( retv != -1 )
+	if (retv != -1)
 		return retv;
 	
-	buff = kmalloc(16, GFP_KERNEL | GFP_DMA);
-	if( !buff ){
-	    printk("parport: memory squezze\n");
+	if (!(buff = kmalloc(2048, GFP_KERNEL | GFP_DMA))) {
+	    printk(KERN_ERR "parport: memory squeeze\n");
 	    return -1;
 	}
 	
@@ -160,24 +160,26 @@
 
 	w_ecr(pb, 0xc0);	   /* ECP MODE */
  	w_ctr(pb, dsr_read );
-	dma=parport_prepare_dma(buff,8);
+	dma=parport_prepare_dma(buff,1000);
 	w_ecr(pb, 0xd8);	   /* ECP FIFO + enable DMA */
 	parport_enable_dma(dma);
-	udelay(30);           /* Give some for DMA tranfer */
-	retv = parport_detect_dma_transfer(dma,8);
+	udelay(500);           /* Give some for DMA tranfer */
+	retv = parport_detect_dma_transfer(dma,1000,&pb->speed);
+	pb->speed = pb->speed * 2000;  /* 500uSec * 2000 = 1sec */
 	
 	/*
 	 * National Semiconductors only supports DMA tranfers
 	 * in ECP MODE
 	 */
-	if( retv == -1 ){
+	if (retv == -1) {
 		w_ecr(pb, 0x60);	   /* ECP MODE */
 		w_ctr(pb, dsr_read );
-		dma=parport_prepare_dma(buff,8);
+		dma=parport_prepare_dma(buff,1000);
 		w_ecr(pb, 0x68);	   /* ECP FIFO + enable DMA */
 		parport_enable_dma(dma);
-		udelay(30);           /* Give some for DMA tranfer */
-		retv = parport_detect_dma_transfer(dma,8);
+		udelay(500);           /* Give some for DMA tranfer */
+		retv = parport_detect_dma_transfer(dma,1000,&pb->speed);
+		pb->speed = pb->speed * 2000;  /* 500uSec * 2000 = 1sec */
 	}
 	
 	kfree(buff);
@@ -198,10 +200,10 @@
 {
 	int r;
 
-    if( !(r_str(pb) & 0x01) )
+	if (!(r_str(pb) & 0x01))
 		return 1;
 
-	/* To clear timeout some chip requiere double read */
+	/* To clear timeout some chips require double read */
 	r_str(pb);
 	r = r_str(pb);
 	w_str(pb, r | 0x01); /* Some reset by writing 1 */
@@ -213,23 +215,18 @@
 
 
 /*
- * Checks for por existence, all ports support SPP MODE
+ * Checks for port existence, all ports support SPP MODE
  */
 static int parport_SPP_supported(struct parport *pb)
 {
-	int r,rr;
-	
 	/* Do a simple read-write test to make sure the port exists. */
+
 	w_dtr(pb, 0xaa);
-	r = r_dtr(pb);
+	if (r_dtr(pb) != 0xaa) return 0;
 	
 	w_dtr(pb, 0x55);
-	rr = r_dtr(pb);
-	
-	if (r != 0xaa || rr != 0x55) {
-		return 0;
-	}
-	
+	if (r_dtr(pb) != 0x55) return 0;
+
 	return PARPORT_MODE_SPP;
 }
 
@@ -249,23 +246,20 @@
 {
 	int r;
 
-	if( pb->base == 0x3BC )
-		return 0;
-	
 	r= r_ctr(pb);	
-	if( (r_ecr(pb) & 0x03) == (r & 0x03) ){
+	if ((r_ecr(pb) & 0x03) == (r & 0x03)) {
 		w_ctr(pb, r ^ 0x03 ); /* Toggle bits 0-1 */
 
 		r= r_ctr(pb);	
-		if( (r_ecr(pb) & 0x03) == (r & 0x03) )
+		if ((r_ecr(pb) & 0x03) == (r & 0x03))
 			return 0; /* Sure that no ECR register exists */
 	}
 	
-	if( (r_ecr(pb) & 0x03 ) != 0x01 )
+	if ((r_ecr(pb) & 0x03 ) != 0x01)
 		return 0;
 
 	w_ecr(pb,0x34);
-	if( r_ecr(pb) != 0x35 )
+	if (r_ecr(pb) != 0x35)
 		return 0;
 
 	w_ecr(pb,pb->ecr);
@@ -278,20 +272,22 @@
 {
 	int i;
 	
-	if( !(pb->modes & PARPORT_MODE_ECR) )
+	/* If there is no ECR, we have no hope of supporting ECP. */
+	if (!(pb->modes & PARPORT_MODE_ECR))
 		return 0;
+
 	/*
-	 * Usign LGS chipset it uses ECR register, but
+	 * Using LGS chipset it uses ECR register, but
 	 * it doesn't support ECP or FIFO MODE
 	 */
 	
-	w_ecr(pb,0xc0); /* TEST FIFO */
-	for( i=0 ; i < 1024 && (r_ecr(pb) & 0x01) ; i++ )
+	w_ecr(pb, 0xc0); /* TEST FIFO */
+	for (i=0; i < 1024 && (r_ecr(pb) & 0x01); i++)
 		w_fifo(pb, 0xaa);
 
-	w_ecr(pb,pb->ecr);
+	w_ecr(pb, pb->ecr);
 
-	if( i >= 1024 )
+	if (i == 1024)
 		return 0;
 	
 	return PARPORT_MODE_ECP;
@@ -311,11 +307,8 @@
  */
 static int parport_EPP_supported(struct parport *pb)
 {
-	if( pb->base == 0x3BC )
-		return 0;
-
 	/* If EPP timeout bit clear then EPP available */
-	if( !epp_clear_timeout(pb) )
+	if (!epp_clear_timeout(pb))
 		return 0;  /* No way to clear timeout */
 
 	w_ctr(pb, r_ctr(pb) | 0x20);
@@ -325,7 +318,7 @@
 	r_epp(pb);
 	udelay(30);  /* Wait for possible EPP timeout */
 	
-	if( r_str(pb) & 0x01 ){
+	if (r_str(pb) & 0x01) {
 		epp_clear_timeout(pb);
 		return PARPORT_MODE_EPP;
 	}
@@ -337,7 +330,7 @@
 {
 	int mode;
 
-	if( !(pb->modes & PARPORT_MODE_ECR) )
+	if (!(pb->modes & PARPORT_MODE_ECR))
 		return 0;
 	
 	/* Search for SMC style EPP+ECP mode */
@@ -345,47 +338,55 @@
 	
 	mode = parport_EPP_supported(pb);
 
-	w_ecr(pb,pb->ecr);
+	w_ecr(pb, pb->ecr);
 	
-	if( mode )
+	if (mode)
 		return PARPORT_MODE_ECPEPP;
 	
 	return 0;
 }
 
-/* Detect LP_PS2 support
- * Bit 5 (0x20) sets the PS/2 data direction, setting this high
- * allows us to read data from the data lines, old style SPP ports
- * will return 0xff.  This may not be reliable if there is a
- * peripheral attached to the port. 
+/* Detect PS/2 support.
+ *
+ * Bit 5 (0x20) sets the PS/2 data direction; setting this high
+ * allows us to read data from the data lines.  In theory we would get back
+ * 0xff but any peripheral attached to the port may drag some or all of the
+ * lines down to zero.  So if we get back anything that isn't the contents
+ * of the data register we deem PS/2 support to be present. 
+ *
+ * Some SPP ports have "half PS/2" ability - you can't turn off the line
+ * drivers, but an external peripheral with sufficiently beefy drivers of
+ * its own can overpower them and assert its own levels onto the bus, from
+ * where they can then be read back as normal.  Ports with this property
+ * and the right type of device attached are likely to fail the SPP test,
+ * (as they will appear to have stuck bits) and so the fact that they might
+ * be misdetected here is rather academic. 
  */
+
 static int parport_PS2_supported(struct parport *pb)
 {
-	int r,rr;
-
+	int ok = 0;
+  
 	epp_clear_timeout(pb);
 
-	w_ctr(pb, pb->ctr | 0x20);	/* Tri-state the buffer */
+	w_ctr(pb, pb->ctr | 0x20);   /* try to tri-state the buffer */
 	
-	w_dtr(pb, 0xAA);
-	r = r_dtr(pb);
-
 	w_dtr(pb, 0x55);
-	rr = r_dtr(pb);
-	
-	w_ctr(pb, pb->ctr);	/* Reset CTR register */
+	if (r_dtr(pb) != 0x55) ok++;
 
-	if (r != 0xAA || rr != 0x55 )
-		return PARPORT_MODE_PS2;
+	w_dtr(pb, 0xaa);
+	if (r_dtr(pb) != 0xaa) ok++;
 	
-	return 0;
+	w_ctr(pb, pb->ctr);          /* cancel input mode */
+
+	return ok?PARPORT_MODE_PS2:0;
 }
 
 static int parport_ECPPS2_supported(struct parport *pb)
 {
 	int mode;
 
-	if( !(pb->modes & PARPORT_MODE_ECR) )
+	if (!(pb->modes & PARPORT_MODE_ECR))
 		return 0;
 	
 	w_ecr(pb, 0x20);
@@ -402,15 +403,19 @@
 
 /******************************************************
  *  IRQ detection section:
- */
-/*
+ *
  * This code is for detecting ECP interrupts (due to problems with the
  * monolithic interrupt probing routines).
  *
  * In short this is a voting system where the interrupt with the most
  * "votes" is the elected interrupt (it SHOULD work...)
+ *
+ * This is horribly x86-specific at the moment.  I'm not convinced it
+ * belongs at all.
  */
+
 static int intr_vote[16];
+
 static void parport_vote_intr_func(int irq, void *dev_id, struct pt_regs *regs)
 {
 	intr_vote[irq]++;
@@ -434,17 +439,16 @@
 
 static int close_intr_election(long tmp)
 {
-	long max_vote = 0;
-	int irq = -1;
+	int irq = PARPORT_IRQ_NONE;
 	int i;
 
 	/* We ignore the timer - irq 0 */
 	for (i = 1; i < 16; i++)
 		if (tmp & (1 << i)) {
-			if (intr_vote[i] > max_vote) {
-				if (max_vote)
-					return -1;
-				max_vote = intr_vote[i];
+			if (intr_vote[i]) {
+				if (irq != PARPORT_IRQ_NONE)
+					/* More than one interrupt */
+					return PARPORT_IRQ_NONE;
 				irq = i;
 			}
 			free_irq(i, intr_vote);
@@ -488,7 +492,7 @@
 	irqs = open_intr_election();
 		
 	w_ecr(pb, 0x00);	    /* Reset FIFO */
-	w_ctr(pb, pb->ctr );    /* Force direction = 0 */
+	w_ctr(pb, pb->ctr );	    /* Force direction = 0 */
 	w_ecr(pb, 0xd0);	    /* TEST FIFO + nErrIntrEn */
 
 	/* If Full FIFO sure that WriteIntrThresold is generated */
@@ -497,8 +501,6 @@
 	}
 		
 	pb->irq = close_intr_election(irqs);
-	if (pb->irq == 0)
-		pb->irq = -1;	/* No interrupt detected */
 	
 	w_ecr(pb, pb->ecr);
 
@@ -506,7 +508,7 @@
 }
 
 /*
- * It's called only if supports EPP on National Semiconductors
+ * This detection seems that only works in National Semiconductors
  * This doesn't work in SMC, LGS, and Winbond 
  */
 static int irq_probe_EPP(struct parport *pb)
@@ -535,8 +537,6 @@
 	udelay(20);
 
 	pb->irq = close_intr_election(irqs);
-	if (pb->irq == 0)
-		pb->irq = -1;	/* No interrupt detected */
 	
 	w_ctr(pb,pb->ctr);
 	
@@ -572,7 +572,7 @@
 
 	pb->irq = probe_irq_off(irqs);
 	if (pb->irq <= 0)
-		pb->irq = -1;	/* No interrupt detected */
+		pb->irq = PARPORT_IRQ_NONE;	/* No interrupt detected */
 	
 	w_ctr(pb,pb->ctr);
 	
@@ -583,18 +583,18 @@
  * such as sound cards and network cards seem to like using the
  * printer IRQs.
  *
- * When LP_ECP is available we can autoprobe for IRQs.
+ * When ECP is available we can autoprobe for IRQs.
  * NOTE: If we can autoprobe it, we can register the IRQ.
  */
 static int parport_irq_probe(struct parport *pb)
 {
-	if( pb->modes & PARPORT_MODE_ECR )
+	if (pb->modes & PARPORT_MODE_ECR)
 		pb->irq = programmable_irq_support(pb);
 
-	if( pb->modes & PARPORT_MODE_ECP )
+	if (pb->modes & PARPORT_MODE_ECP)
 		pb->irq = irq_probe_ECP(pb);
 			
-	if( pb->irq == -1 && (pb->modes & PARPORT_MODE_ECPEPP)){
+	if (pb->irq == PARPORT_IRQ_NONE && (pb->modes & PARPORT_MODE_ECPEPP)) {
 		w_ecr(pb,0x80);
 		pb->irq = irq_probe_EPP(pb);
 		w_ecr(pb,pb->ecr);
@@ -602,12 +602,12 @@
 
 	epp_clear_timeout(pb);
 
-	if( pb->irq == -1 && (pb->modes & PARPORT_MODE_EPP))
+	if (pb->irq == PARPORT_IRQ_NONE && (pb->modes & PARPORT_MODE_EPP))
 		pb->irq = irq_probe_EPP(pb);
 
 	epp_clear_timeout(pb);
 
-	if( pb->irq == -1 )
+	if (pb->irq == PARPORT_IRQ_NONE)
 		pb->irq = irq_probe_SPP(pb);
 
 	return pb->irq;
@@ -618,12 +618,12 @@
 {
 	/* Check some parameters */
 	if (dma < -2) {
-		printk("parport: Invalid DMA[%d] at base 0x%lx\n",dma,base);
+		printk(KERN_ERR "parport: Invalid DMA[%d] at base 0x%lx\n",dma,base);
 		return 0;
 	}
 
 	if (irq < -2) {
-		printk("parport: Invalid IRQ[%d] at base 0x%lx\n",irq,base);
+		printk(KERN_ERR "parport: Invalid IRQ[%d] at base 0x%lx\n",irq,base);
 		return 0;
 	}
 	
@@ -643,7 +643,7 @@
 
 	pb->name = kmalloc(15, GFP_KERNEL);
 	if (!pb->name) {
-		printk("parport: memory squeeze\n");
+		printk(KERN_ERR "parport: memory squeeze\n");
 		return 0;
 	}
 	sprintf(pb->name, "parport%d", count);
@@ -657,12 +657,15 @@
 	}
 
 	pb->modes |= PARPORT_MODE_SPP; 	/* All ports support SPP mode. */
-	pb->modes |= parport_ECR_present(pb);	
-	pb->modes |= parport_ECP_supported(pb);
 	pb->modes |= parport_PS2_supported(pb);
-	pb->modes |= parport_ECPPS2_supported(pb);
-	pb->modes |= parport_EPP_supported(pb);
-	pb->modes |= parport_ECPEPP_supported(pb);
+
+	if (pb->base != 0x3bc) {
+		pb->modes |= parport_ECR_present(pb);	
+		pb->modes |= parport_ECP_supported(pb);
+		pb->modes |= parport_ECPPS2_supported(pb);
+		pb->modes |= parport_EPP_supported(pb);
+		pb->modes |= parport_ECPEPP_supported(pb);
+	}
 
 	/* Now register regions */
 	if ((pb->modes & (PARPORT_MODE_EPP | PARPORT_MODE_ECPEPP)) && 
@@ -678,17 +681,17 @@
 
 	/* DMA check */
 	if (pb->modes & PARPORT_MODE_ECP) {
-		if (pb->dma == -1)
+		if (pb->dma == PARPORT_DMA_NONE)
 			pb->dma = parport_dma_probe(pb);
 		else if (pb->dma == -2)
-			pb->dma = -1;
+			pb->dma = PARPORT_DMA_NONE;
 	}
 
 	/* IRQ check */
-	if (pb->irq == -1)
+	if (pb->irq == PARPORT_IRQ_NONE)
 		pb->irq = parport_irq_probe(pb);
 	else if (pb->irq == -2)
-		pb->irq = -1;
+		pb->irq = PARPORT_IRQ_NONE;
 
 	return 1;
 }
@@ -700,7 +703,7 @@
 {
 	if (ints[0] == 0 || ints[1] == 0) {
 		/* Disable parport if "parport=" or "parport=0" in cmdline */
-		io[0] = -2; 
+		io[0] = PARPORT_DISABLE; 
 		return;
 	}
 	if (parport_setup_ptr < PARPORT_MAX) {
@@ -738,17 +741,20 @@
 	struct parport *pb;
 
 	printk(KERN_INFO "Parallel port sharing: %s\n",
-	       "$Revision: 1.1.2.4 $");
+	       "$Revision: 1.3.2.4 $");
 
-	if (io[0] == -2) return 1; 
+	if (io[0] == PARPORT_DISABLE) return 1; 
 
-	/* Register /proc/parport */
-	parport_proc_register(NULL);
+#ifdef CONFIG_PROC_FS
+	parport_proc_init();
+#endif
 
 	/* Run probes to ensure parport does exist */
 #define PORT(a,b,c) \
 		if ((pb = parport_register_port((a), (b), (c))))  \
 		        parport_destroy(pb); 
+
+
 	if (io[0]) {
 		/* If the user specified any ports, use them */
 		int i;
@@ -757,16 +763,22 @@
 		}
 	} else {
 		/* Go for the standard ports. */
-		PORT(0x378, -1, -1);
-		PORT(0x278, -1, -1);
-		PORT(0x3bc, -1, -1);
+		PORT(0x378, PARPORT_IRQ_NONE, PARPORT_DMA_NONE);
+		PORT(0x278, PARPORT_IRQ_NONE, PARPORT_DMA_NONE);
+		PORT(0x3bc, PARPORT_IRQ_NONE, PARPORT_DMA_NONE);
 #undef PORT
 	}
 
+#if defined(CONFIG_PNP_PARPORT_AUTOPROBE) || defined(CONFIG_PROC_FS)
+	for (pb = parport_enumerate(); pb; pb = pb->next) {
 #ifdef CONFIG_PNP_PARPORT_AUTOPROBE
-	for (pb = parport_enumerate(); pb; pb = pb->next)
 		parport_probe_one(pb);
 #endif
+#ifdef CONFIG_PROC_FS
+		parport_proc_register(pb);
+#endif
+	}
+#endif
 
 	return 0;
 }
@@ -784,7 +796,7 @@
 		kfree(port);
 	}
 	
-	parport_proc_unregister(NULL);
+	parport_proc_cleanup();
 }
 #endif
 
diff -u --recursive --new-file v2.1.35/linux/drivers/pnp/parport_procfs.c linux/drivers/pnp/parport_procfs.c
--- v2.1.35/linux/drivers/pnp/parport_procfs.c	Mon Apr 14 16:28:13 1997
+++ linux/drivers/pnp/parport_procfs.c	Thu Apr 17 14:48:53 1997
@@ -1,4 +1,4 @@
-/* $Id: parport_procfs.c,v 1.1.2.2 1997/03/26 17:50:36 phil Exp $
+/* $Id: parport_procfs.c,v 1.3.2.6 1997/04/16 21:30:38 phil Exp $
  * Parallel port /proc interface code.
  * 
  * Authors: David Campbell <campbell@tirian.che.curtin.edu.au>
@@ -21,108 +21,320 @@
 #include <linux/kernel.h>
 #include <linux/malloc.h>
 
-#ifdef CONFIG_PROC_FS
 #include <linux/proc_fs.h>
-#endif
 
 #include <linux/parport.h>
+#include "parport_ll_io.h"
+
+#undef PARPORT_INCLUDE_BENCH
 
-#if defined(CONFIG_PROC_FS) && defined(NOT_DEFINED)
+struct proc_dir_entry *base=NULL;
 
-/************************************************/
-static long proc_readparport(struct inode * inode, struct file * file,
-							 char * buf, unsigned long count)
+void parport_null_intr_func(int irq, void *dev_id, struct pt_regs *regs);
+
+static int irq_write_proc(struct file *file, const char *buffer,
+					  unsigned long count, void *data)
 {
-	printk("proc_readparport\n");
-	return 0;
+	int newirq;
+	struct parport *pp = (struct parport *)data;
+	
+	if (count > 4 )  /* more than 4 digits for a irq 0x?? 0?? ??  */
+		return(-EOVERFLOW);
+
+	if (buffer[0] < 32 || !strncmp(buffer, "none", 4)) {
+		newirq = PARPORT_IRQ_NONE;
+	} else {
+		if (buffer[0] == '0') {
+			if( buffer[1] == 'x' )
+				newirq = simple_strtoul(&buffer[2],0,16);
+			else
+				newirq = simple_strtoul(&buffer[1],0,8);
+		} else {
+			newirq = simple_strtoul(buffer,0,10);
+		}
+	}
+
+	if (pp->irq != PARPORT_IRQ_NONE && !(pp->flags & PARPORT_FLAG_COMA)) 
+		free_irq(pp->irq, pp);
+
+	pp->irq = newirq;
+
+	if (pp->irq != PARPORT_IRQ_NONE && !(pp->flags & PARPORT_FLAG_COMA)) { 
+		struct ppd *pd = pp->cad;
+
+		if (pd == NULL) {
+			pd = pp->devices;
+			if (pd != NULL) 
+				request_irq(pp->irq, pd->irq_func ? 
+					    pd->irq_func :
+					    parport_null_intr_func,
+					    SA_INTERRUPT, pd->name, pd->port);
+		} else {
+			request_irq(pp->irq, pd->irq_func ? pd->irq_func :
+				    parport_null_intr_func,
+				    SA_INTERRUPT, pp->name, pd->port);
+		}
+	}
+
+	return count;
 }
 
-static long proc_writeparport(struct inode * inode, struct file * file,
-							  const char * buf, unsigned long count)
+static int irq_read_proc(char *page, char **start, off_t off,
+					 int count, int *eof, void *data)
 {
-	printk("proc_writeparport\n");
+	struct parport *pp = (struct parport *)data;
+	int len;
 	
-	return 0;
+	if (pp->irq == PARPORT_IRQ_NONE)
+		len = sprintf(page, "none\n");
+	else
+		len = sprintf(page, "%d\n", pp->irq);
+	
+	*start = 0;
+	*eof   = 1;
+	return len;
 }
 
-static long long proc_parportlseek(struct inode * inode, struct file * file, 
-				long long offset, int orig)
+static int devices_read_proc(char *page, char **start, off_t off,
+					 int count, int *eof, void *data)
 {
-    switch (orig) {
-    case 0:
-	file->f_pos = offset;
-	return(file->f_pos);
-    case 1:
-	file->f_pos += offset;
-	return(file->f_pos);
-    case 2:
-	return(-EINVAL);
-    default:
-	return(-EINVAL);
-    }
-}
-
-static struct file_operations proc_dir_operations = {
-    proc_parportlseek,	/* lseek   */
-    proc_readparport,	/* read	   */
-    proc_writeparport,	/* write   */
-    proc_readdir,	    /* readdir */
-    NULL,		/* poll    */
-    NULL,		/* ioctl   */
-    NULL,		/* mmap	   */
-    NULL,		/* no special open code	   */
-    NULL,		/* no special release code */
-    NULL		/* can't fsync */
-};
-
-/************************************************/
-static struct inode_operations parport_proc_dir_inode_operations = {
-	&proc_dir_operations,	/* default net directory file-ops */
-	NULL,			/* create */
-	proc_lookup,	/* lookup */
-	NULL,			/* link */
-	NULL,			/* unlink */
-	NULL,			/* symlink */
-	NULL,			/* mkdir */
-	NULL,			/* rmdir */
-	NULL,			/* mknod */
-	NULL,			/* rename */
-	NULL,			/* readlink */
-	NULL,			/* follow_link */
-	NULL,			/* readpage */
-	NULL,			/* writepage */
-	NULL,			/* bmap */
-	NULL,			/* truncate */
-	NULL			/* permission */
-};
-
-static struct proc_dir_entry proc_root_parport = {
-	PROC_PARPORT, 7, "parport",
-	S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0,
-	0, &parport_proc_dir_inode_operations,
-	NULL, NULL,
-	NULL, &proc_root, NULL,
-	NULL, NULL
-};
+	struct parport *pp = (struct parport *)data;
+	struct ppd *pd1;
+	int len=0;
+
+	for (pd1 = pp->devices; pd1 ; pd1 = pd1->next) {
+		if (pd1 == pp->cad)
+			len += sprintf(page+len, "+");
+		else
+			len += sprintf(page+len, " ");
+
+		len += sprintf(page+len, "%s",pd1->name);
+
+		if (pd1 == pp->lurker)
+			len += sprintf(page+len, " LURK");
+		
+		len += sprintf(page+len,"\n");
+	}
+		
+	*start = 0;
+	*eof   = 1;
+	return len;
+}
+
+static int hardware_read_proc(char *page, char **start, off_t off,
+							  int count, int *eof, void *data)
+{
+	struct parport *pp = (struct parport *)data;
+	int len=0;
+	
+	len += sprintf(page+len, "base:\t0x%x\n",pp->base);
+	if (pp->irq == PARPORT_IRQ_NONE)
+		len += sprintf(page+len, "irq:\tnone\n");
+	else
+		len += sprintf(page+len, "irq:\t%d\n",pp->irq);
+	len += sprintf(page+len, "dma:\t%d\n",pp->dma);
+
+	len += sprintf(page+len, "modes:\t");
+	{
+#define printmode(x) {if(pp->modes&PARPORT_MODE_##x){len+=sprintf(page+len,"%s%s",f?",":"",#x);f++;}}
+		int f = 0;
+		printmode(SPP);
+		printmode(PS2);
+		printmode(EPP);
+		printmode(ECP);
+		printmode(ECPEPP);
+		printmode(ECPPS2);
+#undef printmode
+	}
+	len += sprintf(page+len, "\n");
+
+	len += sprintf(page+len, "mode:\t");
+	if (pp->modes & PARPORT_MODE_ECR) {
+		switch (r_ecr(pp) >> 5) {
+		case 0:
+			len += sprintf(page+len, "SPP");
+			if( pp->modes & PARPORT_MODE_PS2 )
+				len += sprintf(page+len, ",PS2");
+			if( pp->modes & PARPORT_MODE_EPP )
+				len += sprintf(page+len, ",EPP");
+			break;
+		case 1:
+			len += sprintf(page+len, "ECPPS2");
+			break;
+		case 2:
+			len += sprintf(page+len, "DATAFIFO");
+			break;
+		case 3:
+			len += sprintf(page+len, "ECP");
+			break;
+		case 4:
+			len += sprintf(page+len, "ECPEPP");
+			break;
+		case 5:
+			len += sprintf(page+len, "Reserved?");
+			break;
+		case 6:
+			len += sprintf(page+len, "TEST");
+			break;
+		case 7:
+			len += sprintf(page+len, "Configuration");
+			break;
+		}
+	} else {
+		len += sprintf(page+len, "SPP");
+		if (pp->modes & PARPORT_MODE_PS2)
+			len += sprintf(page+len, ",PS2");
+		if (pp->modes & PARPORT_MODE_EPP)
+			len += sprintf(page+len, ",EPP");
+	}
+	len += sprintf(page+len, "\n");
+	
+#if 0
+	/* Now no detection, please fix with an external function */
+	len += sprintf(page+len, "chipset:\tunknown\n");
 #endif
+#ifdef PARPORT_INCLUDE_BENCHMARK
+	if (pp->speed)
+		len += sprintf(page+len, "bench:\t%d Bytes/s\n",pp->speed);
+	else
+		len += sprintf(page+len, "bench:\tunknown\n");
+#endif	
+
+	*start = 0;
+	*eof   = 1;
+	return len;
+}
+
+static struct proc_dir_entry *new_proc_entry(const char *name, mode_t mode,
+					     struct proc_dir_entry *parent,
+					     unsigned short ino)
+{
+	struct proc_dir_entry *ent;
+
+	ent = kmalloc(sizeof(struct proc_dir_entry), GFP_KERNEL);
+	if (!ent)
+		return NULL;
+	memset(ent, 0, sizeof(struct proc_dir_entry));
+	
+	if (mode == S_IFDIR)
+		mode |= S_IRUGO | S_IXUGO;
+	else if (mode == 0)
+		mode = S_IFREG | S_IRUGO;
+
+
+	ent->low_ino = ino;
+	ent->name = name;
+	ent->namelen = strlen(name);
+	ent->mode = mode;
+	if (S_ISDIR(mode)) 
+		ent->nlink = 2;
+	else
+		ent->nlink = 1;
+
+	proc_register(parent, ent);
+	
+	return ent;
+}
+
+
+int parport_proc_init()
+{
+	base = new_proc_entry("parport", S_IFDIR, &proc_root,PROC_PARPORT);
+
+	if (base)
+		return 1;
+	else {
+		printk(KERN_ERR "parport: Error creating proc entry /proc/parport\n");
+		return 0;
+	}
+}
+
+int parport_proc_cleanup()
+{
+	if (base)
+		proc_unregister(&proc_root,base->low_ino);
+
+	base = NULL;
+	
+	return 0;
+}
 
 int parport_proc_register(struct parport *pp)
 {
-#if defined(CONFIG_PROC_FS) && defined(NOT_DEFINED)
-	return proc_register(&proc_root, &proc_root_parport);
-#else
+	struct proc_dir_entry *ent;
+	static int conta=0;
+	char *name;
+
+	memset(&pp->pdir,0,sizeof(struct parport_dir));
+
+	if (!base) {
+		printk(KERN_ERR "parport: Error entry /proc/parport, not generated?\n");
+		return 1;
+	}
+	
+	name = pp->pdir.name;
+	sprintf(name,"%d",conta++);
+
+	ent = new_proc_entry(name, S_IFDIR, base,0);
+	if (!ent) {
+		printk(KERN_ERR "parport: Error registering proc_entry /proc/%s\n",name);
+		return 1;
+	}
+	pp->pdir.entry = ent;
+
+	ent = new_proc_entry("irq", S_IFREG | S_IRUGO | S_IWUSR, pp->pdir.entry,0);
+	if (!ent) {
+		printk(KERN_ERR "parport: Error registering proc_entry /proc/%s/irq\n",name);
+		return 1;
+	}
+	ent->read_proc = irq_read_proc;
+	ent->write_proc= irq_write_proc;
+	ent->data      = pp;
+	pp->pdir.irq   = ent;
+	
+	ent = new_proc_entry("devices", 0, pp->pdir.entry,0);
+	if (!ent) {
+		printk(KERN_ERR "parport: Error registering proc_entry /proc/%s/devices\n",name);
+		return 1;
+	}
+	ent->read_proc   = devices_read_proc;
+	ent->data        = pp;
+	pp->pdir.devices = ent;
+	
+	ent = new_proc_entry("hardware", 0, pp->pdir.entry,0);
+	if (!ent) {
+		printk(KERN_ERR "parport: Error registering proc_entry /proc/%s/hardware\n",name);
+		return 1;
+	}
+	ent->read_proc    = hardware_read_proc;
+	ent->data         = pp;
+	pp->pdir.hardware = ent;
 	return 0;
-#endif
 }
 
-void parport_proc_unregister(struct parport *pp)
+int parport_proc_unregister(struct parport *pp)
 {
-#if defined(CONFIG_PROC_FS) && defined(NOT_DEFINED)
-	if( pp ){
-		proc_unregister(&proc_root_parport, pp->proc_dir->low_ino);
-		kfree(pp->proc_dir);
-	}else{
-		proc_unregister(&proc_root, proc_root_parport.low_ino);
+	if (pp->pdir.entry) {
+		if (pp->pdir.irq) {
+			proc_unregister(pp->pdir.entry, pp->pdir.irq->low_ino);
+			kfree(pp->pdir.irq);
+		}
+		
+		if (pp->pdir.devices) {
+			proc_unregister(pp->pdir.entry,
+					pp->pdir.devices->low_ino);
+			kfree(pp->pdir.devices);
+		}
+		
+		if (pp->pdir.hardware) {
+			proc_unregister(pp->pdir.entry,
+					pp->pdir.hardware->low_ino);
+			kfree(pp->pdir.hardware);
+		}
+		
+		proc_unregister(base, pp->pdir.entry->low_ino);
+		kfree(pp->pdir.entry);
 	}
-#endif
+	
+	return 0;
 }
diff -u --recursive --new-file v2.1.35/linux/drivers/pnp/parport_share.c linux/drivers/pnp/parport_share.c
--- v2.1.35/linux/drivers/pnp/parport_share.c	Mon Apr 14 16:28:13 1997
+++ linux/drivers/pnp/parport_share.c	Thu Apr 17 14:48:53 1997
@@ -1,4 +1,4 @@
-/* $Id: parport_share.c,v 1.1.2.4 1997/04/01 18:19:11 phil Exp $
+/* $Id: parport_share.c,v 1.3.2.5 1997/04/16 21:20:44 phil Exp $
  * Parallel-port resource manager code.
  * 
  * Authors: David Campbell <campbell@tirian.che.curtin.edu.au>
@@ -21,6 +21,8 @@
 #include <linux/kernel.h>
 #include <linux/malloc.h>
 
+#undef PARPORT_PARANOID
+
 #include "parport_ll_io.h"
 
 static struct parport *portlist = NULL, *portlist_tail = NULL;
@@ -36,7 +38,7 @@
 	return portlist;
 }
 
-static void parport_null_intr_func(int irq, void *dev_id, struct pt_regs *regs)
+void parport_null_intr_func(int irq, void *dev_id, struct pt_regs *regs)
 {
 	/* NULL function - Does nothing */
 	return;
@@ -85,7 +87,7 @@
 	}
 	memcpy(tmp, &new, sizeof(struct parport));
 
-	if (new.irq != -1) {
+	if (new.irq != PARPORT_IRQ_NONE) {
 		if (request_irq(new.irq, parport_null_intr_func,
 			  SA_INTERRUPT, new.name, tmp) != 0) {
 			printk(KERN_INFO "%s: unable to claim IRQ %d\n", 
@@ -197,11 +199,10 @@
 				return NULL;
 			}
 		}
-		if (port->irq != -1) {
-			if (request_irq(port->irq, 
-							parport_null_intr_func,
-							SA_INTERRUPT, port->name,
-							port) != 0) {
+		if (port->irq != PARPORT_IRQ_NONE) {
+			if (request_irq(port->irq, parport_null_intr_func,
+					SA_INTERRUPT, port->name,
+					port) != 0) {
 				release_region(port->base, port->size);
 				if( port->modes & PARPORT_MODE_ECR )
 					release_region(port->base+0x400, 3);
@@ -213,7 +214,6 @@
 		port->flags &= ~PARPORT_FLAG_COMA;
 	}
 
-
 	tmp = kmalloc(sizeof(struct ppd), GFP_KERNEL);
 	tmp->name = (char *) name;
 	tmp->port = port;
@@ -251,8 +251,7 @@
 	port = dev->port;
 
 	if (port->cad == dev) {
-		printk(KERN_INFO "%s: refused to unregister currently active device %s\n",
-			   port->name, dev->name);
+		printk(KERN_INFO "%s: refused to unregister currently active device %s\n", port->name, dev->name);
 		return;
 	}
 
@@ -299,8 +298,9 @@
 			if (dev->port->modes & PARPORT_MODE_ECR)
 				dev->port->cad->ecr = dev->port->ecr = 
 					r_ecr(dev->port);
-			dev->port->cad->ctr = dev->port->ctr =
-				r_ctr(dev->port);
+			if (dev->port->modes & PARPORT_MODE_SPP)
+				dev->port->cad->ctr = dev->port->ctr =
+					r_ctr(dev->port);
 		} else
 			return -EAGAIN;
 	}
@@ -326,7 +326,8 @@
 	/* Restore control registers */
 	if (dev->port->modes & PARPORT_MODE_ECR)
 		if (dev->ecr != dev->port->ecr) w_ecr(dev->port, dev->ecr);
-	if (dev->ctr != dev->port->ctr) w_ctr(dev->port, dev->ctr);
+	if (dev->port->modes & PARPORT_MODE_SPP)
+		if (dev->ctr != dev->port->ctr) w_ctr(dev->port, dev->ctr);
 
 	return 0;
 }
@@ -337,8 +338,7 @@
 
 	/* Make sure that dev is the current device */
 	if (dev->port->cad != dev) {
-		printk(KERN_WARNING "%s: %s tried to release parport when not owner\n",
-			   dev->port->name, dev->name);
+		printk(KERN_WARNING "%s: %s tried to release parport when not owner\n", dev->port->name, dev->name);
 		return;
 	}
 	dev->port->cad = NULL;
@@ -346,12 +346,13 @@
 	/* Save control registers */
 	if (dev->port->modes & PARPORT_MODE_ECR)
 		dev->ecr = dev->port->ecr = r_ecr(dev->port);
-	dev->ctr = dev->port->ctr = r_ctr(dev->port);
+	if (dev->port->modes & PARPORT_MODE_SPP)
+		dev->ctr = dev->port->ctr = r_ctr(dev->port);
 	
 	if (dev->port->irq >= 0) {
 		free_irq(dev->port->irq, dev->port);
 		request_irq(dev->port->irq, parport_null_intr_func,
-					SA_INTERRUPT, dev->port->name, dev->port);
+			    SA_INTERRUPT, dev->port->name, dev->port);
  	}
 
 	/* Walk the list, offering a wakeup callback to everybody other
@@ -384,16 +385,22 @@
 	if (dev->port->lurker && (dev->port->lurker != dev)) {
 		if (dev->port->lurker->wakeup) {
 			dev->port->lurker->wakeup(dev->port->lurker->private);
-			return;
+		} 
+#ifdef PARPORT_PARANOID
+		else {  /* can't happen */
+			printk(KERN_DEBUG
+			  "%s (%s): lurker's wakeup callback went away!\n",
+			       dev->port->name, dev->name);
 		}
-		printk(KERN_DEBUG
-		       "%s (%s): lurker's wakeup callback went away!\n",
-		       dev->port->name, dev->name);
+#endif
 	}
 }
 
 /* The following read funktions are an implementation of a status readback
  * and device id request confirming to IEEE1284-1994.
+ *
+ * These probably ought to go in some seperate file, so people like the SPARC
+ * don't have to pull them in.
  */
 
 /* Wait for Status line(s) to change in 35 ms - see IEEE1284-1994 page 24 to
diff -u --recursive --new-file v2.1.35/linux/drivers/sbus/char/Config.in linux/drivers/sbus/char/Config.in
--- v2.1.35/linux/drivers/sbus/char/Config.in	Mon Apr 14 16:28:13 1997
+++ linux/drivers/sbus/char/Config.in	Thu Apr 17 13:20:46 1997
@@ -10,6 +10,7 @@
 	bool 'bwtwo support' SUN_FB_BWTWO
 	bool 'leo/zx support' SUN_FB_LEO
 	bool 'weitek P9X00 support' TADPOLE_FB_WEITEK
+	bool 'creator support' SUN_FB_CREATOR
 	if [ "$TADPOLE_FB_WEITEK" = "n" ]; then
 		fbs=$SUN_FB_CGSIX
 		fbs=$fbs$SUN_FB_TCX
@@ -34,6 +35,7 @@
 	define_bool SUN_FB_BWTWO y
 	define_bool SUN_FB_LEO y
 	define_bool TADPOLE_FB_WEITEK y
+	define_bool SUN_FB_CREATOR y
 fi
 
 comment 'Misc Linux/SPARC drivers'
diff -u --recursive --new-file v2.1.35/linux/drivers/sbus/char/Makefile linux/drivers/sbus/char/Makefile
--- v2.1.35/linux/drivers/sbus/char/Makefile	Mon Apr 14 16:28:13 1997
+++ linux/drivers/sbus/char/Makefile	Thu Apr 17 13:20:46 1997
@@ -31,6 +31,9 @@
 ifdef TADPOLE_FB_WEITEK
  FB_OBJS +=	weitek.o
 endif
+ifdef SUN_FB_CREATOR
+ FB_OBJS += creator.o
+endif
 #ifdef SUN_FB_FAST_ONE
 # FB_OBJS +=	sun_8bit_fast1.o
 #endif
diff -u --recursive --new-file v2.1.35/linux/drivers/sbus/char/bpp.c linux/drivers/sbus/char/bpp.c
--- v2.1.35/linux/drivers/sbus/char/bpp.c	Thu Mar 27 14:40:05 1997
+++ linux/drivers/sbus/char/bpp.c	Thu Apr 17 13:20:46 1997
@@ -29,6 +29,7 @@
 #endif
 
 #if defined(__sparc__)
+# include <linux/init.h>
 # include <linux/delay.h>         /* udelay() */
 
 # include <asm/oplib.h>           /* OpenProm Library */
diff -u --recursive --new-file v2.1.35/linux/drivers/sbus/char/bwtwo.c linux/drivers/sbus/char/bwtwo.c
--- v2.1.35/linux/drivers/sbus/char/bwtwo.c	Mon Apr 14 16:28:13 1997
+++ linux/drivers/sbus/char/bwtwo.c	Tue Apr 15 21:47:23 1997
@@ -1,4 +1,4 @@
-/* $Id: bwtwo.c,v 1.12 1997/04/10 03:02:40 davem Exp $
+/* $Id: bwtwo.c,v 1.13 1997/04/14 17:04:55 jj Exp $
  * bwtwo.c: bwtwo console driver
  *
  * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
@@ -86,7 +86,7 @@
 	/* This routine should also map the register if asked for,
 	 * but we don't do that yet.
 	 */
-	map_offset = get_phys ((uint) fb->base);
+	map_offset = get_phys ((unsigned long) fb->base);
 	r = io_remap_page_range (vma->vm_start, map_offset, map_size,
 				 vma->vm_page_prot, fb->space);
 	if (r) return -EAGAIN;
@@ -143,10 +143,10 @@
 	0x10, 0x20,	0
 };
 
-__initfunc(void bwtwo_setup (fbinfo_t *fb, int slot, unsigned long bwtwo, int bw2_io,
+__initfunc(void bwtwo_setup (fbinfo_t *fb, int slot, u32 bwtwo, int bw2_io,
 			     struct linux_sbus_device *sbdp))
 {
-	printk ("bwtwo%d at 0x%8.8x\n", slot, (uint)bwtwo);
+	printk ("bwtwo%d at 0x%8.8x\n", slot, bwtwo);
 	fb->type.fb_cmsize = 0;
 	fb->mmap = bwtwo_mmap;
 	fb->loadcmap = 0;
@@ -156,7 +156,7 @@
 	fb->unblank = bwtwo_unblank;
 
 	fb->info.bwtwo.regs =
-		sparc_alloc_io ((u32)(bwtwo + BWTWO_REGISTER_OFFSET),
+		sparc_alloc_io (bwtwo + BWTWO_REGISTER_OFFSET,
 				0, sizeof (struct bwtwo_regs),
 		"bwtwo_regs", bw2_io, 0);
 
@@ -201,7 +201,7 @@
 	}
 
 	if(!fb->base)
-		fb->base = (unsigned long) sparc_alloc_io((u32)bwtwo, 0,
+		fb->base = (unsigned long) sparc_alloc_io(bwtwo, 0,
 		  ((fb->type.fb_depth*fb->type.fb_height*fb->type.fb_width)/8),
 		  "bwtwo_fbase", bw2_io, 0);
 
diff -u --recursive --new-file v2.1.35/linux/drivers/sbus/char/cgfourteen.c linux/drivers/sbus/char/cgfourteen.c
--- v2.1.35/linux/drivers/sbus/char/cgfourteen.c	Mon Apr 14 16:28:13 1997
+++ linux/drivers/sbus/char/cgfourteen.c	Tue Apr 15 21:47:23 1997
@@ -1,4 +1,4 @@
-/* $Id: cgfourteen.c,v 1.18 1997/03/24 17:44:27 jj Exp $
+/* $Id: cgfourteen.c,v 1.19 1997/04/14 17:04:57 jj Exp $
  * cgfourteen.c: Sun SparcStation console support.
  *
  * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
@@ -183,22 +183,22 @@
 		        printk ("Wee!  They are mapping the register, report this to miguel@gnu.ai.mit.edu\n");
 			printk ("Mapping fb->info.regs!\n");
 			map_size = 0x7000;
-			map_offset = get_phys ((uint) fb->info.cg14.regs);
+			map_offset = get_phys ((unsigned long) fb->info.cg14.regs);
 			break;
 			
 		case CG3_MMAP_OFFSET:
 			map_size = size-page;
-			map_offset = get_phys ((uint) fb->base);
+			map_offset = get_phys ((unsigned long) fb->base);
 			break;
 
 		case MDI_PLANAR_X16_MAP:
 			map_size = ram_size/2;
-			map_offset = get_phys ((uint) fb->base) | 0x2000000;
+			map_offset = get_phys ((unsigned long) fb->base) | 0x2000000;
 			break;
 			
 		case MDI_PLANAR_C16_MAP:
 			map_size = ram_size/2;
-			map_offset = get_phys ((uint) fb->base) | 0x2800000;
+			map_offset = get_phys ((unsigned long) fb->base) | 0x2800000;
 			break;
 			
 		case MDI_CHUNKY_XBGR_MAP:
@@ -208,50 +208,50 @@
 			
 		case MDI_CHUNKY_BGR_MAP:
 			map_size = ram_size;
-			map_offset = get_phys ((uint) fb->base) | 0x1000000;
+			map_offset = get_phys ((unsigned long) fb->base) | 0x1000000;
 			break;
 			
 		case MDI_PLANAR_X32_MAP:
 			map_size = ram_size/4;
-			map_offset = get_phys ((uint) fb->base) | 0x3000000;
+			map_offset = get_phys ((unsigned long) fb->base) | 0x3000000;
 			break;
 		case MDI_PLANAR_B32_MAP:
 			map_size = ram_size/4;
-			map_offset = get_phys ((uint) fb->base) | 0x3400000;
+			map_offset = get_phys ((unsigned long) fb->base) | 0x3400000;
 			break;
 		case MDI_PLANAR_G32_MAP:
 			map_size = ram_size/4;
-			map_offset = get_phys ((uint) fb->base) | 0x3800000;
+			map_offset = get_phys ((unsigned long) fb->base) | 0x3800000;
 			break;
 		case MDI_PLANAR_R32_MAP:
 			map_size = ram_size/4;
-			map_offset = get_phys ((uint) fb->base) | 0x3c00000;
+			map_offset = get_phys ((unsigned long) fb->base) | 0x3c00000;
 			break;
 
 		case MDI_CURSOR_MAP:
 			map_size = PAGE_SIZE;
-			map_offset = get_phys ((uint) fb->info.cg14.cursor_regs);
+			map_offset = get_phys ((unsigned long) fb->info.cg14.cursor_regs);
 			break;
 			
 		case CG14_REGS:
 		        printk ("Wee!  They are mapping the register, report this to miguel@gnu.ai.mit.edu\n");
 			map_size = PAGE_SIZE;
-			map_offset = get_phys ((uint) fb->info.cg14.regs);
+			map_offset = get_phys ((unsigned long) fb->info.cg14.regs);
 			break;
 			
 		case CG14_XLUT:
 			map_size = PAGE_SIZE;
-			map_offset = get_phys ((uint) fb->info.cg14.regs+0x3000);
+			map_offset = get_phys ((unsigned long) fb->info.cg14.regs+0x3000);
 			break;
 			
 		case CG14_CLUT1:
 			map_size = PAGE_SIZE;
-			map_offset = get_phys ((uint) fb->info.cg14.regs+0x4000);
+			map_offset = get_phys ((unsigned long) fb->info.cg14.regs+0x4000);
 			break;
 			
 		case CG14_CLUT2:
 			map_size = PAGE_SIZE;
-			map_offset = get_phys ((uint) fb->info.cg14.regs+0x5000);
+			map_offset = get_phys ((unsigned long) fb->info.cg14.regs+0x5000);
 			break;
 			
 		default:
@@ -424,11 +424,11 @@
 	*mcr = (*mcr & ~(CG14_MCR_PIXMODE_MASK));
 }
 
-__initfunc(void cg14_setup (fbinfo_t *fb, int slot, int con_node, unsigned long cg14, int cg14_io))
+__initfunc(void cg14_setup (fbinfo_t *fb, int slot, int con_node, u32 cg14, int cg14_io))
 {
 	struct cg14_info *cg14info;
 	uint bases [2];
-	uint cg14regs = 0;
+	unsigned long cg14regs = 0;
 	struct cg14_regs *regs = 0;
 
 	if (!cg14) {
@@ -468,5 +468,5 @@
 	/* If the bit is turned on, the card has 8 mb of ram, otherwise just 4 */
 	cg14info->ramsize = (regs->vca & CG14_VCA_8MB_MASK ? 8 : 4) * 1024 * 1024;
 	printk ("cgfourteen%d at 0x%8.8x with %d megs of RAM rev=%d, impl=%d\n",
-		slot, (uint)cg14, cg14info->ramsize/(1024*1024), regs->rev >> 4, regs->rev & 0xf);
+		slot, cg14, cg14info->ramsize/(1024*1024), regs->rev >> 4, regs->rev & 0xf);
 }
diff -u --recursive --new-file v2.1.35/linux/drivers/sbus/char/cgsix.c linux/drivers/sbus/char/cgsix.c
--- v2.1.35/linux/drivers/sbus/char/cgsix.c	Mon Apr 14 16:28:13 1997
+++ linux/drivers/sbus/char/cgsix.c	Tue Apr 15 21:47:23 1997
@@ -1,4 +1,4 @@
-/* $Id: cgsix.c,v 1.26 1997/04/10 03:02:40 davem Exp $
+/* $Id: cgsix.c,v 1.27 1997/04/14 17:04:55 jj Exp $
  * cgsix.c: cgsix frame buffer driver
  *
  * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
@@ -264,17 +264,14 @@
 			map_size = PAGE_SIZE;
 			map_offset = get_phys ((unsigned long)fb->info.cg6.bt);
 			break;
-			
 		case CG6_DHC:
 			map_size = PAGE_SIZE * 40;
 			map_offset = get_phys ((unsigned long)fb->info.cg6.dhc);
 			break;
-			
 		case CG6_ROM:
 			map_size = PAGE_SIZE * 16;
 			map_offset = get_phys ((unsigned long)fb->info.cg6.rom);
 			break;
-
 		case CG6_RAM:
 			map_size = size-page;
 			map_offset = get_phys ((unsigned long) fb->base);
@@ -422,12 +419,12 @@
 	cg6->bt->control |= 0x03 << 24;
 }
 
-__initfunc(void cg6_setup (fbinfo_t *fb, int slot, unsigned long cg6, int cg6_io))
+__initfunc(void cg6_setup (fbinfo_t *fb, int slot, u32 cg6, int cg6_io))
 {
 	struct cg6_info *cg6info;
 	unsigned int rev, cpu, conf;
 
-	printk ("cgsix%d at 0x%8.8x ", slot, (uint) cg6);
+	printk ("cgsix%d at 0x%8.8x ", slot, cg6);
 	
 	/* Fill in parameters we left out */
 	fb->type.fb_cmsize = 256;
@@ -447,23 +444,23 @@
 	cg6info = (struct cg6_info *) &fb->info.cg6;
 
 	/* Map the hardware registers */
-	cg6info->bt = sparc_alloc_io ((u32)(cg6+CG6_BROOKTREE_OFFSET), 0,
+	cg6info->bt = sparc_alloc_io (cg6+CG6_BROOKTREE_OFFSET, 0,
 		 sizeof (struct bt_regs), "cgsix_dac", cg6_io, 0);
-	cg6info->fhc = sparc_alloc_io ((u32)(cg6+CG6_FHC_OFFSET), 0,
+	cg6info->fhc = sparc_alloc_io (cg6+CG6_FHC_OFFSET, 0,
 		 sizeof (int), "cgsix_fhc", cg6_io, 0);
-	cg6info->thc = sparc_alloc_io ((u32)(cg6+CG6_THC_OFFSET), 0,
+	cg6info->thc = sparc_alloc_io (cg6+CG6_THC_OFFSET, 0,
 		 sizeof (struct cg6_thc), "cgsix_thc", cg6_io, 0);
-	cg6info->tec = sparc_alloc_io ((u32)(cg6+CG6_TEC_OFFSET), 0,
+	cg6info->tec = sparc_alloc_io (cg6+CG6_TEC_OFFSET, 0,
 		 sizeof (struct cg6_tec), "cgsix_tec", cg6_io, 0);
-	cg6info->dhc = sparc_alloc_io ((u32)(cg6+CG6_DHC_OFFSET), 0,
+	cg6info->dhc = sparc_alloc_io (cg6+CG6_DHC_OFFSET, 0,
 		 0x40000, "cgsix_dhc", cg6_io, 0);
-	cg6info->fbc = sparc_alloc_io ((u32)(cg6+CG6_FBC_OFFSET), 0,
+	cg6info->fbc = sparc_alloc_io (cg6+CG6_FBC_OFFSET, 0,
 		 0x1000, "cgsix_fbc", cg6_io, 0);
-	cg6info->rom = sparc_alloc_io ((u32)(cg6+CG6_ROM_OFFSET), 0,
+	cg6info->rom = sparc_alloc_io (cg6+CG6_ROM_OFFSET, 0,
 		 0x10000, "cgsix_rom", cg6_io, 0);
 	if (!fb->base) {
 		fb->base = (unsigned long)
-			sparc_alloc_io ((u32)(cg6+CG6_RAM_OFFSET), 0,
+			sparc_alloc_io (cg6+CG6_RAM_OFFSET, 0,
 					fb->type.fb_size, "cgsix_ram", cg6_io, 0);
 	}
 	if (slot == sun_prom_console_id)
diff -u --recursive --new-file v2.1.35/linux/drivers/sbus/char/cgthree.c linux/drivers/sbus/char/cgthree.c
--- v2.1.35/linux/drivers/sbus/char/cgthree.c	Mon Apr 14 16:28:13 1997
+++ linux/drivers/sbus/char/cgthree.c	Thu Apr 17 13:20:46 1997
@@ -1,4 +1,4 @@
-/* $Id: cgthree.c,v 1.16 1997/04/10 03:02:41 davem Exp $
+/* $Id: cgthree.c,v 1.18 1997/04/16 17:51:09 jj Exp $
  * cgtree.c: cg3 frame buffer driver
  *
  * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
@@ -109,7 +109,7 @@
 		switch (vma->vm_offset+page){
 		case CG3_MMAP_OFFSET:
 			map_size = size-page;
-			map_offset = get_phys ((uint) fb->base);
+			map_offset = get_phys ((unsigned long) fb->base);
 			if (map_size > fb->type.fb_size)
 				map_size = fb->type.fb_size;
 			break;
@@ -178,7 +178,7 @@
 };
 
 
-__initfunc(void cg3_setup (fbinfo_t *fb, int slot, unsigned long cg3, int cg3_io,
+__initfunc(void cg3_setup (fbinfo_t *fb, int slot, u32 cg3, int cg3_io,
 			   struct linux_sbus_device *sbdp))
 {
 	struct cg3_info *cg3info = (struct cg3_info *) &fb->info.cg3;
@@ -200,10 +200,10 @@
 				}
 			}
 		}
-		printk ("cgRDI%d at 0x%8.8x\n", slot, (uint)cg3);
+		printk ("cgRDI%d at 0x%8.8x\n", slot, cg3);
 		cg3info->cgrdi = 1;
 	} else {
-		printk ("cgthree%d at 0x%8.8x\n", slot, (uint)cg3);
+		printk ("cgthree%d at 0x%8.8x\n", slot, cg3);
 		cg3info->cgrdi = 0;
 	}
 	
@@ -218,7 +218,7 @@
 	fb->unblank = cg3_unblank;
 
 	/* Map the card registers */
-	cg3info->regs = sparc_alloc_io ((u32)(cg3+CG3_REGS), 0,
+	cg3info->regs = sparc_alloc_io (cg3+CG3_REGS, 0,
 		 sizeof (struct cg3_regs),"cg3_regs", cg3_io, 0);
 
 	if (!prom_getbool(sbdp->prom_node, "width")) {
@@ -258,8 +258,8 @@
 	}
 
 	if (!fb->base){
-		fb->base=(uint) sparc_alloc_io ((u32)(cg3+CG3_RAM), 0,
-				    fb->type.fb_size, "cg3_ram", cg3_io, 0);
+		fb->base=(unsigned long) sparc_alloc_io (cg3+CG3_RAM, 0,
+				         fb->type.fb_size, "cg3_ram", cg3_io, 0);
 	}
 }
 
diff -u --recursive --new-file v2.1.35/linux/drivers/sbus/char/creator.c linux/drivers/sbus/char/creator.c
--- v2.1.35/linux/drivers/sbus/char/creator.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/sbus/char/creator.c	Tue Apr 22 22:39:12 1997
@@ -0,0 +1,98 @@
+/*
+ * creator.c: Linux/Sun Ultra Creator console support.
+ *
+ * Copyright (C) 1997 MIguel de Icaza (miguel@nuclecu.unam.mx)
+ *
+ */
+#include <linux/kd.h>
+#include <linux/tty.h>
+#include <linux/malloc.h>
+#include <linux/proc_fs.h>
+
+#include <asm/sbus.h>
+#include <asm/io.h>
+#include <asm/fbio.h>
+#include <asm/pgtable.h>
+#include <asm/uaccess.h>
+
+#include "../../char/vt_kern.h"
+#include "../../char/selection.h"
+#include "../../char/console_struct.h"
+#include "fb.h"
+
+__initfunc(void creator_setup (fbinfo_t *fb, int slot, int con_node, unsigned long creator, int creator_io))
+{
+        uint bases [2];
+        unsigned long *p;
+
+        if (!creator) {
+                prom_getproperty (con_node, "address", (char *) &bases[0], 4);
+                prom_printf ("Bases: %x %x\n", bases [0], bases [1]);
+                p = (unsigned long *) creator = bases[0];
+                fb->base = creator;
+                fb->base = 0xff168000;
+        }
+
+        fb->type.fb_cmsize = 256;
+        fb->mmap =  0;
+        fb->loadcmap = 0;
+        fb->setcursor = 0;
+        fb->setcursormap = 0;
+        fb->setcurshape = 0;
+        fb->ioctl = 0;
+        fb->switch_from_graph = 0;
+        fb->postsetup = sun_cg_postsetup;
+        fb->reset = 0;
+        fb->blank = 0;
+        fb->unblank = 0;
+        fb->type.fb_depth = 8;
+}
+/*
+ * creator.c: Linux/Sun Ultra Creator console support.
+ *
+ * Copyright (C) 1997 MIguel de Icaza (miguel@nuclecu.unam.mx)
+ *
+ */
+#include <linux/kd.h>
+#include <linux/tty.h>
+#include <linux/malloc.h>
+#include <linux/proc_fs.h>
+
+#include <asm/sbus.h>
+#include <asm/io.h>
+#include <asm/fbio.h>
+#include <asm/pgtable.h>
+#include <asm/uaccess.h>
+
+#include "../../char/vt_kern.h"
+#include "../../char/selection.h"
+#include "../../char/console_struct.h"
+#include "fb.h"
+
+__initfunc(void creator_setup (fbinfo_t *fb, int slot, int con_node, unsigned long creator, int creator_io))
+{
+        uint bases [2];
+        unsigned long *p;
+
+        if (!creator) {
+                prom_getproperty (con_node, "address", (char *) &bases[0], 4);
+                prom_printf ("Bases: %x %x\n", bases [0], bases [1]);
+                p = (unsigned long *) creator = bases[0];
+                fb->base = creator;
+                fb->base = 0xff168000;
+        }
+
+        fb->type.fb_cmsize = 256;
+        fb->mmap =  0;
+        fb->loadcmap = 0;
+        fb->setcursor = 0;
+        fb->setcursormap = 0;
+        fb->setcurshape = 0;
+        fb->ioctl = 0;
+        fb->switch_from_graph = 0;
+        fb->postsetup = sun_cg_postsetup;
+        fb->reset = 0;
+        fb->blank = 0;
+        fb->unblank = 0;
+        fb->type.fb_depth = 8;
+}
diff -u --recursive --new-file v2.1.35/linux/drivers/sbus/char/fb.h linux/drivers/sbus/char/fb.h
--- v2.1.35/linux/drivers/sbus/char/fb.h	Mon Apr 14 16:28:13 1997
+++ linux/drivers/sbus/char/fb.h	Thu Apr 17 13:20:46 1997
@@ -1,4 +1,4 @@
-/* $Id: fb.h,v 1.24 1997/03/24 17:44:15 jj Exp $
+/* $Id: fb.h,v 1.26 1997/04/17 02:29:33 miguel Exp $
  * fb.h: contains the definitions of the structures that various sun
  *       frame buffer can use to do console driver stuff.
  *
@@ -183,8 +183,8 @@
 extern int ints_per_line;
 
 /* used in the mmap routines */
-extern unsigned int get_phys (unsigned int addr);
-extern int get_iospace (unsigned int addr);
+extern unsigned int get_phys (unsigned long addr);
+extern int get_iospace (unsigned long addr);
 extern void render_screen(void);
 
 extern void sun_hw_hide_cursor(void);
@@ -197,12 +197,14 @@
 
 #define FB_DEV(x) (MINOR(x) / 32)
 
-extern void cg3_setup (fbinfo_t *, int, unsigned long, int, struct linux_sbus_device *);
-extern void cg6_setup (fbinfo_t *, int, unsigned long, int);
-extern void cg14_setup (fbinfo_t *, int, int, unsigned long, int);
-extern void bwtwo_setup (fbinfo_t *, int, unsigned long, int,
+extern void cg3_setup (fbinfo_t *, int, u32, int, struct linux_sbus_device *);
+extern void cg6_setup (fbinfo_t *, int, u32, int);
+extern void cg14_setup (fbinfo_t *, int, int, u32, int);
+extern void bwtwo_setup (fbinfo_t *, int, u32, int,
 			 struct linux_sbus_device *);
-extern void leo_setup (fbinfo_t *, int, unsigned long, int);
-extern void tcx_setup (fbinfo_t *, int, int, unsigned long, struct linux_sbus_device *);
+extern void leo_setup (fbinfo_t *, int, u32, int);
+extern void tcx_setup (fbinfo_t *, int, int, u32, struct linux_sbus_device *);
+extern void creator_setup (fbinfo_t *, int, int, unsigned long, int);
+extern int io_remap_page_range(unsigned long from, unsigned long offset, unsigned long size, pgprot_t prot, int space);
 
 #endif __SPARC_FB_H_
diff -u --recursive --new-file v2.1.35/linux/drivers/sbus/char/leo.c linux/drivers/sbus/char/leo.c
--- v2.1.35/linux/drivers/sbus/char/leo.c	Mon Apr 14 16:28:13 1997
+++ linux/drivers/sbus/char/leo.c	Tue Apr 15 21:47:23 1997
@@ -1,4 +1,4 @@
-/* $Id: leo.c,v 1.14 1997/04/10 17:06:09 jj Exp $
+/* $Id: leo.c,v 1.15 1997/04/14 17:04:54 jj Exp $
  * leo.c: SUNW,leo 24/8bit frame buffer driver
  *
  * Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -156,19 +156,19 @@
 		switch (vma->vm_offset+page){
 		case LEO_SS0_MAP:
 			map_size = 0x800000;
-			map_offset = get_phys ((uint)fb->base);
+			map_offset = get_phys ((unsigned long)fb->base);
 			break;
 		case LEO_LC_SS0_USR_MAP:
 			map_size = PAGE_SIZE;
-			map_offset = get_phys ((uint)fb->info.leo.lc_ss0_usr);
+			map_offset = get_phys ((unsigned long)fb->info.leo.lc_ss0_usr);
 			break;
 		case LEO_LD_SS0_MAP:
 			map_size = PAGE_SIZE;
-			map_offset = get_phys ((uint)fb->info.leo.ld_ss0);
+			map_offset = get_phys ((unsigned long)fb->info.leo.ld_ss0);
 			break;
 		case LEO_LX_CURSOR_MAP:
 			map_size = PAGE_SIZE;
-			map_offset = get_phys ((uint)fb->info.leo.cursor);
+			map_offset = get_phys ((unsigned long)fb->info.leo.cursor);
 			break;
 		case LEO_SS1_MAP:	
 			map_size = 0x800000;
@@ -176,11 +176,11 @@
 			break;
 		case LEO_LC_SS1_USR_MAP:
 			map_size = PAGE_SIZE;
-			map_offset = get_phys ((uint)fb->info.leo.lc_ss1_usr);
+			map_offset = get_phys ((unsigned long)fb->info.leo.lc_ss1_usr);
 			break;
 		case LEO_LD_SS1_MAP:
 			map_size = PAGE_SIZE;
-			map_offset = get_phys ((uint)fb->info.leo.ld_ss1);
+			map_offset = get_phys ((unsigned long)fb->info.leo.ld_ss1);
 			break;
 		case LEO_UNK_MAP:	
 			map_size = PAGE_SIZE;
@@ -188,19 +188,19 @@
 			break;
 		case LEO_LX_KRN_MAP:
 			map_size = PAGE_SIZE;
-			map_offset = get_phys ((uint)fb->info.leo.lx_krn);
+			map_offset = get_phys ((unsigned long)fb->info.leo.lx_krn);
 			break;
 		case LEO_LC_SS0_KRN_MAP:
 			map_size = PAGE_SIZE;
-			map_offset = get_phys ((uint)fb->info.leo.lc_ss0_krn);
+			map_offset = get_phys ((unsigned long)fb->info.leo.lc_ss0_krn);
 			break;
 		case LEO_LC_SS1_KRN_MAP:
 			map_size = PAGE_SIZE;
-			map_offset = get_phys ((uint)fb->info.leo.lc_ss1_krn);
+			map_offset = get_phys ((unsigned long)fb->info.leo.lc_ss1_krn);
 			break;
 		case LEO_LD_GBL_MAP:
 			map_size = PAGE_SIZE;
-			map_offset = get_phys ((uint)fb->info.leo.ld_gbl);
+			map_offset = get_phys ((unsigned long)fb->info.leo.ld_gbl);
 			break;
 		case LEO_UNK2_MAP:
 			map_size = 0x100000;
@@ -509,14 +509,14 @@
 	return memory_start + (256*4*3) + 256 + 256*3;
 }
 
-__initfunc(void leo_setup (fbinfo_t *fb, int slot, unsigned long leo, int leo_io))
+__initfunc(void leo_setup (fbinfo_t *fb, int slot, u32 leo, int leo_io))
 {
 	struct leo_info *leoinfo;
 	int i;
 	struct fb_wid_item wi;
 	struct fb_wid_list wl;
 	
-	printk ("leo%d at 0x%8.8x ", slot, (uint) leo);
+	printk ("leo%d at 0x%8.8x ", slot, leo);
 	
 	/* Fill in parameters we left out */
 	fb->type.fb_size = 0x800000; /* 8MB */
@@ -543,25 +543,25 @@
 
 	leoinfo->offset = leo;
 	/* Map the hardware registers */
-	leoinfo->lc_ss0_krn = sparc_alloc_io((u32)(leo + LEO_OFF_LC_SS0_KRN), 0,
+	leoinfo->lc_ss0_krn = sparc_alloc_io(leo + LEO_OFF_LC_SS0_KRN, 0,
 		 PAGE_SIZE,"leo_lc_ss0_krn", fb->space, 0);
-	leoinfo->lc_ss0_usr = sparc_alloc_io((u32)(leo + LEO_OFF_LC_SS0_USR), 0,
+	leoinfo->lc_ss0_usr = sparc_alloc_io(leo + LEO_OFF_LC_SS0_USR, 0,
 		 PAGE_SIZE,"leo_lc_ss0_usr", fb->space, 0);
-	leoinfo->lc_ss1_krn = sparc_alloc_io((u32)(leo + LEO_OFF_LC_SS1_KRN), 0,
+	leoinfo->lc_ss1_krn = sparc_alloc_io(leo + LEO_OFF_LC_SS1_KRN, 0,
 		 PAGE_SIZE,"leo_lc_ss1_krn", fb->space, 0);
-	leoinfo->lc_ss1_usr = sparc_alloc_io((u32)(leo + LEO_OFF_LC_SS1_USR), 0,
+	leoinfo->lc_ss1_usr = sparc_alloc_io(leo + LEO_OFF_LC_SS1_USR, 0,
 		 PAGE_SIZE,"leo_lc_ss1_usr", fb->space, 0);
-	leoinfo->ld_ss0 = sparc_alloc_io((u32)(leo + LEO_OFF_LD_SS0), 0,
+	leoinfo->ld_ss0 = sparc_alloc_io(leo + LEO_OFF_LD_SS0, 0,
 		 PAGE_SIZE,"leo_ld_ss0", fb->space, 0);
-	leoinfo->ld_ss1 = sparc_alloc_io((u32)(leo + LEO_OFF_LD_SS1), 0,
+	leoinfo->ld_ss1 = sparc_alloc_io(leo + LEO_OFF_LD_SS1, 0,
 		 PAGE_SIZE,"leo_ld_ss1", fb->space, 0);
-	leoinfo->ld_gbl = sparc_alloc_io((u32)(leo + LEO_OFF_LD_GBL), 0,
+	leoinfo->ld_gbl = sparc_alloc_io(leo + LEO_OFF_LD_GBL, 0,
 		 PAGE_SIZE,"leo_ld_gbl", fb->space, 0);
-	leoinfo->lx_krn = sparc_alloc_io((u32)(leo + LEO_OFF_LX_KRN), 0,
+	leoinfo->lx_krn = sparc_alloc_io(leo + LEO_OFF_LX_KRN, 0,
 		 PAGE_SIZE,"leo_lx_krn", fb->space, 0);
-	leoinfo->cursor = sparc_alloc_io((u32)(leo + LEO_OFF_LX_CURSOR), 0,
+	leoinfo->cursor = sparc_alloc_io(leo + LEO_OFF_LX_CURSOR, 0,
 		 sizeof(struct leo_cursor),"leo_lx_crsr", fb->space, 0);
-	fb->base = (long)sparc_alloc_io((u32)(leo + LEO_OFF_SS0), 0,
+	fb->base = (long)sparc_alloc_io(leo + LEO_OFF_SS0, 0,
 		 0x800000,"leo_ss0", fb->space, 0);
 	
 	leoinfo->ld_ss0->unk = 0xffff;
diff -u --recursive --new-file v2.1.35/linux/drivers/sbus/char/linux_logo.h linux/drivers/sbus/char/linux_logo.h
--- v2.1.35/linux/drivers/sbus/char/linux_logo.h	Fri Dec 13 01:37:32 1996
+++ linux/drivers/sbus/char/linux_logo.h	Wed Dec 31 16:00:00 1969
@@ -1,1037 +0,0 @@
-/* This is a linux logo to be displayed on boot.
- *
- * You can put anything here, but:
- * LINUX_LOGO_COLORS has to be less than 224
- * image size has to be 80x80
- * values have to start from 0x20
- * (i.e. RGB(linux_logo_red[0],
- *	     linux_logo_green[0],
- *	     linux_logo_blue[0]) is color 0x20)
- * BW image has to be 80x80 as well, with MS bit
- * on the left
- * Serial_console ascii image can be any size,
- * but should contain %s to display the version
- */
- 
-#include <linux/init.h>
-
-#define LINUX_LOGO_COLORS 221
-
-unsigned char linux_logo_red[] __initdata = {
-  0xF3, 0xF6, 0xF8, 0xF7, 0xEF, 0xE7, 0xE5, 0xE3,
-  0xCA, 0xD4, 0xDD, 0xC8, 0xC7, 0xC4, 0xC2, 0xE5,
-  0xF1, 0xED, 0xEE, 0xE6, 0xC6, 0xDA, 0xDD, 0xE5,
-  0xD9, 0xC6, 0xE3, 0xD0, 0xC6, 0xBA, 0xB0, 0xB6,
-  0xBB, 0xBE, 0xB9, 0xB8, 0xB3, 0xB2, 0xB0, 0xAD,
-  0xAC, 0xA9, 0xA8, 0xA6, 0xA4, 0xA1, 0xA0, 0x9D,
-  0xA0, 0x9F, 0x9E, 0x9C, 0x9B, 0x99, 0x9A, 0x99,
-  0x98, 0x95, 0x96, 0x94, 0x93, 0x92, 0x8F, 0x8D,
-  0x8C, 0x8A, 0x87, 0x86, 0x83, 0x81, 0x0D, 0x03,
-  0x66, 0x44, 0x24, 0x08, 0xD6, 0xE6, 0xE9, 0xE6,
-  0xE7, 0xCA, 0xDC, 0xDB, 0xD5, 0xD0, 0xC9, 0xE2,
-  0xD5, 0xC6, 0xC4, 0xB3, 0xB2, 0xB9, 0xA9, 0x9A,
-  0xB2, 0x9D, 0xE8, 0xEC, 0xF5, 0xF5, 0xF4, 0xF4,
-  0xEC, 0xEE, 0xF0, 0xF5, 0xE0, 0xD6, 0xC5, 0xC2,
-  0xD9, 0xD5, 0xD8, 0xD6, 0xF6, 0xF4, 0xED, 0xEC,
-  0xEB, 0xF1, 0xF6, 0xF5, 0xF5, 0xEE, 0xEF, 0xEC,
-  0xE7, 0xE3, 0xE6, 0xD6, 0xDD, 0xC3, 0xD6, 0xD7,
-  0xCD, 0xCA, 0xC3, 0xAC, 0x95, 0x99, 0xB7, 0xA3,
-  0x8B, 0x88, 0x95, 0x8A, 0x94, 0xD2, 0xCC, 0xC4,
-  0xA8, 0x8E, 0x8F, 0xAE, 0xB8, 0xAC, 0xB6, 0xB4,
-  0xAD, 0xA5, 0xA0, 0x9B, 0x8B, 0xA3, 0x94, 0x87,
-  0x85, 0x89, 0x53, 0x80, 0x7D, 0x7C, 0x7A, 0x78,
-  0x76, 0x71, 0x73, 0x6E, 0x6B, 0x67, 0x65, 0x62,
-  0x4B, 0x5B, 0x5F, 0x53, 0x56, 0x52, 0x4F, 0x46,
-  0x42, 0x0F, 0x75, 0x78, 0x7D, 0x72, 0x5F, 0x6E,
-  0x7A, 0x75, 0x6A, 0x58, 0x48, 0x4F, 0x00, 0x2B,
-  0x37, 0x3E, 0x32, 0x33, 0x25, 0x2C, 0x3B, 0x11,
-  0x1D, 0x14, 0x06, 0x02, 0x00
-};
-
-unsigned char linux_logo_green[] __initdata = {
-  0xF3, 0xF6, 0xF8, 0xF7, 0xEF, 0xE7, 0xE5, 0xE3,
-  0xCA, 0xD4, 0xDD, 0xC8, 0xC7, 0xC4, 0xC2, 0xD3,
-  0xDA, 0xD4, 0xD7, 0xCC, 0xC1, 0xCC, 0xCB, 0xC9,
-  0xC5, 0xBC, 0xBC, 0xBB, 0xB7, 0xA5, 0xB0, 0xB6,
-  0xBB, 0xBE, 0xB9, 0xB8, 0xB3, 0xB2, 0xAD, 0xAD,
-  0xAC, 0xA9, 0xA8, 0xA6, 0xA4, 0xA1, 0xA0, 0x95,
-  0xA0, 0x9F, 0x9E, 0x9C, 0x9B, 0x99, 0x9A, 0x99,
-  0x98, 0x95, 0x96, 0x94, 0x93, 0x92, 0x8F, 0x8D,
-  0x8C, 0x8A, 0x87, 0x86, 0x83, 0x81, 0x08, 0x02,
-  0x53, 0x2E, 0x19, 0x06, 0xC6, 0xC8, 0xCF, 0xBD,
-  0xB3, 0xB6, 0xB4, 0xAB, 0xA5, 0xA3, 0x9B, 0xB6,
-  0xA7, 0x99, 0x92, 0xA4, 0x9E, 0x9D, 0x98, 0x8C,
-  0x8A, 0x86, 0xCD, 0xCC, 0xC9, 0xD7, 0xCA, 0xC4,
-  0xCA, 0xC3, 0xC7, 0xC3, 0xC8, 0xB4, 0x91, 0x8E,
-  0x8A, 0x82, 0x87, 0x85, 0xBD, 0xBF, 0xB6, 0xBC,
-  0xAE, 0xB7, 0xBC, 0xB8, 0xBF, 0xB6, 0xBC, 0xB5,
-  0xAB, 0xA6, 0xAD, 0xB2, 0xA5, 0x87, 0x9C, 0x96,
-  0x95, 0x8E, 0x87, 0x8F, 0x86, 0x86, 0x8E, 0x80,
-  0x7A, 0x70, 0x7B, 0x78, 0x78, 0x7F, 0x77, 0x6F,
-  0x70, 0x76, 0x59, 0x77, 0x68, 0x64, 0x7B, 0x7C,
-  0x75, 0x6D, 0x77, 0x69, 0x65, 0x5F, 0x5B, 0x54,
-  0x4F, 0x5B, 0x39, 0x80, 0x7D, 0x7C, 0x7A, 0x78,
-  0x76, 0x71, 0x73, 0x6E, 0x6B, 0x67, 0x65, 0x62,
-  0x4B, 0x5B, 0x5F, 0x53, 0x56, 0x52, 0x4F, 0x46,
-  0x42, 0x0B, 0x69, 0x66, 0x64, 0x57, 0x4A, 0x4E,
-  0x55, 0x4B, 0x46, 0x3B, 0x30, 0x33, 0x00, 0x2B,
-  0x37, 0x3E, 0x32, 0x33, 0x25, 0x2C, 0x29, 0x0D,
-  0x1D, 0x14, 0x06, 0x02, 0x00
-};
-
-unsigned char linux_logo_blue[] __initdata = {
-  0xF3, 0xF6, 0xF8, 0xF7, 0xEF, 0xEE, 0xE5, 0xDE,
-  0xD7, 0xD3, 0xDD, 0xC8, 0xC7, 0xC4, 0xC2, 0xB5,
-  0xB0, 0xA6, 0xAC, 0x9B, 0xB5, 0xB5, 0xAE, 0x84,
-  0x90, 0xA9, 0x81, 0x8D, 0x96, 0x86, 0xB0, 0xB6,
-  0xBB, 0xBE, 0xB9, 0xB8, 0xB3, 0xB2, 0xA7, 0xAD,
-  0xAC, 0xA9, 0xA8, 0xA6, 0xA4, 0xA1, 0xA5, 0x87,
-  0xA0, 0x9F, 0x9E, 0x9C, 0x9B, 0x9A, 0x9A, 0x99,
-  0x98, 0x95, 0x96, 0x94, 0x93, 0x92, 0x8F, 0x8D,
-  0x8C, 0x8A, 0x87, 0x86, 0x83, 0x81, 0xC8, 0xD7,
-  0x9B, 0x8E, 0x8C, 0xB2, 0x77, 0x77, 0x4E, 0x77,
-  0x69, 0x71, 0x78, 0x6B, 0x65, 0x66, 0x64, 0x59,
-  0x5C, 0x5A, 0x48, 0x72, 0x7B, 0x6B, 0x67, 0x6E,
-  0x42, 0x5B, 0x29, 0x36, 0x25, 0x10, 0x17, 0x14,
-  0x19, 0x16, 0x13, 0x0E, 0x08, 0x2E, 0x2E, 0x3D,
-  0x24, 0x24, 0x24, 0x24, 0x13, 0x12, 0x14, 0x14,
-  0x0E, 0x08, 0x0D, 0x0F, 0x08, 0x0D, 0x0E, 0x08,
-  0x08, 0x0C, 0x06, 0x06, 0x07, 0x16, 0x07, 0x0E,
-  0x08, 0x0A, 0x07, 0x0D, 0x2D, 0x3E, 0x09, 0x4E,
-  0x68, 0x52, 0x56, 0x58, 0x4B, 0x22, 0x20, 0x20,
-  0x27, 0x39, 0x28, 0x19, 0x1E, 0x1E, 0x08, 0x06,
-  0x07, 0x09, 0x08, 0x08, 0x05, 0x1D, 0x1F, 0x17,
-  0x18, 0x06, 0x79, 0x80, 0x7D, 0x7C, 0x7A, 0x78,
-  0x76, 0x71, 0x73, 0x6E, 0x6B, 0x68, 0x65, 0x62,
-  0x4B, 0x5B, 0x5F, 0x55, 0x56, 0x52, 0x4F, 0x46,
-  0x42, 0x5A, 0x14, 0x23, 0x3D, 0x2B, 0x21, 0x14,
-  0x06, 0x04, 0x03, 0x07, 0x09, 0x13, 0x2A, 0x3A,
-  0x37, 0x3E, 0x32, 0x33, 0x25, 0x2C, 0x07, 0x09,
-  0x1D, 0x14, 0x06, 0x02, 0x00
-};
-
-unsigned char linux_logo[] __initdata = {
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58, 0x57,
-  0x58, 0x58, 0x59, 0x5C, 0x5D, 0x5F, 0x60, 0x61,
-  0x62, 0x61, 0x61, 0x62, 0x62, 0x62, 0x63, 0x63,
-  0x61, 0x61, 0x61, 0x61, 0x61, 0x60, 0x5E, 0x5E,
-  0x5E, 0x5D, 0x5D, 0x5C, 0x5D, 0x5B, 0x58, 0x58,
-  0x58, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x58,
-  0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58, 0x57,
-  0x54, 0x56, 0x57, 0x67, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x67, 0x4C,
-  0x4A, 0x49, 0x4A, 0x49, 0x4A, 0x49, 0x49, 0x4A,
-  0x4A, 0x4B, 0x4B, 0x4B, 0x4C, 0x50, 0x51, 0x52,
-  0x54, 0x54, 0x56, 0x57, 0x57, 0x57, 0x57, 0x58,
-  0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x58, 0x56, 0x56, 0x53,
-  0x52, 0x53, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0xFB, 0xFB,
-  0x4B, 0x4B, 0x4B, 0x4A, 0x49, 0x4A, 0x4A, 0x49,
-  0x49, 0x49, 0x48, 0x49, 0x49, 0x4A, 0x4A, 0x4B,
-  0x4C, 0x4D, 0x52, 0x54, 0x56, 0x55, 0x57, 0x58,
-  0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50,
-  0x50, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xF8, 0xF0, 0xF4, 0xFB,
-  0xFC, 0x67, 0x53, 0x50, 0x4D, 0x4C, 0x4C, 0x4C,
-  0x4B, 0x4A, 0x4A, 0x48, 0x49, 0x48, 0x48, 0x49,
-  0x49, 0x49, 0x4B, 0x4C, 0x50, 0x52, 0x53, 0x56,
-  0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x55, 0x54, 0x53, 0x51, 0x51, 0x50, 0x4C, 0x4D,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xF4, 0xD2, 0xD7, 0xF5,
-  0xFC, 0xFC, 0x5D, 0x5D, 0x5C, 0x5C, 0x59, 0x58,
-  0x58, 0x56, 0x52, 0x4C, 0x4B, 0x4A, 0x4A, 0x48,
-  0x48, 0x48, 0x48, 0x48, 0x49, 0x4B, 0x4D, 0x51,
-  0x54, 0x56, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x55, 0x54,
-  0x53, 0x52, 0x51, 0x4D, 0x4D, 0x4D, 0x50, 0x50,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xF4, 0x64, 0xD9, 0xF5,
-  0xF9, 0xFC, 0xFC, 0x64, 0x63, 0x62, 0x61, 0x61,
-  0x61, 0x60, 0x5E, 0x5B, 0x5A, 0x54, 0x52, 0x4C,
-  0x4B, 0x49, 0x49, 0x47, 0x47, 0x48, 0x49, 0x4B,
-  0x4C, 0x51, 0x53, 0x56, 0x57, 0x58, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x58, 0x57, 0x57, 0x55, 0x53, 0x53,
-  0x51, 0x50, 0x50, 0x50, 0x50, 0x50, 0x53, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xF4, 0xF5, 0xF9, 0xFC,
-  0xFC, 0xFC, 0xFC, 0x64, 0x64, 0x64, 0x64, 0x64,
-  0x64, 0x64, 0x64, 0x63, 0x61, 0x61, 0x5E, 0x59,
-  0x55, 0x52, 0x4C, 0x4A, 0x49, 0x47, 0x48, 0x48,
-  0x49, 0x4B, 0x4D, 0x51, 0x54, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x58, 0x55, 0x54, 0x54, 0x52, 0x51,
-  0x51, 0x51, 0x51, 0x51, 0x53, 0x54, 0x59, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xF7, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0x60, 0x60, 0x60, 0x61,
-  0x62, 0x63, 0x64, 0x64, 0x65, 0x65, 0x64, 0x63,
-  0x61, 0x5E, 0x59, 0x56, 0x4D, 0x4B, 0x48, 0x48,
-  0x48, 0x48, 0x49, 0x4B, 0x50, 0x53, 0x56, 0x56,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x56, 0x54, 0x53, 0x52, 0x51, 0x51,
-  0x51, 0x52, 0x53, 0x55, 0x59, 0x5D, 0x5E, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFB, 0xFB, 0xFB, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0x4C, 0x4E, 0x51, 0x52,
-  0x57, 0x5A, 0x5E, 0x60, 0x61, 0x63, 0x65, 0xCB,
-  0x64, 0x64, 0x63, 0x60, 0x5C, 0x57, 0x50, 0x4B,
-  0x48, 0x47, 0x47, 0x47, 0x4A, 0x4C, 0x52, 0x53,
-  0x54, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x55, 0x54, 0x53, 0x53, 0x51, 0x52, 0x52, 0x53,
-  0x53, 0x57, 0x5A, 0x5D, 0x5E, 0x5E, 0x60, 0xFC,
-  0xFC, 0xFC, 0xFB, 0xF9, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFA, 0xF9, 0xF5, 0xFB, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0x45, 0x3F, 0x3F,
-  0x45, 0x48, 0x4B, 0x4D, 0x54, 0x5A, 0x5E, 0x61,
-  0x63, 0xCB, 0xCB, 0x65, 0x64, 0x62, 0x5E, 0x57,
-  0x50, 0x4B, 0x48, 0x47, 0x47, 0x48, 0x4B, 0x4D,
-  0x51, 0x56, 0x56, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x55,
-  0x54, 0x54, 0x53, 0x53, 0x52, 0x53, 0x54, 0x57,
-  0x59, 0x5C, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0xFC,
-  0xFC, 0xFA, 0xFC, 0xFA, 0xE0, 0xFC, 0xFC, 0xFC,
-  0xFB, 0xFB, 0xFB, 0xDF, 0xD8, 0xF9, 0xE0, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0x4C, 0x4A, 0x48,
-  0x48, 0x3E, 0x44, 0x43, 0x3F, 0x47, 0x4B, 0x52,
-  0x5A, 0x5E, 0x62, 0x64, 0xCB, 0xCB, 0x64, 0x61,
-  0x5E, 0x57, 0x4D, 0x49, 0x47, 0x47, 0x48, 0x4A,
-  0x4C, 0x52, 0x54, 0x56, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x55,
-  0x54, 0x53, 0x53, 0x54, 0x54, 0x55, 0x58, 0x5B,
-  0x5C, 0x5D, 0x5E, 0x5D, 0x5D, 0x5B, 0x58, 0xFC,
-  0xFC, 0xD8, 0x4C, 0x60, 0xFC, 0xF5, 0xFC, 0xFC,
-  0xFC, 0xF7, 0x5F, 0x48, 0x48, 0x2C, 0xF8, 0xF9,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x4B, 0x4A, 0x49,
-  0x49, 0x49, 0x49, 0x47, 0x3E, 0x44, 0x42, 0x3F,
-  0x3E, 0x4B, 0x54, 0x5C, 0x61, 0x64, 0xCB, 0xCB,
-  0x64, 0x61, 0x5D, 0x53, 0x4B, 0x49, 0x47, 0x47,
-  0x49, 0x4B, 0x50, 0x53, 0x56, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x55, 0x55, 0x54,
-  0x53, 0x53, 0x54, 0x56, 0x58, 0x5A, 0x5B, 0x5D,
-  0x5D, 0x5D, 0x5C, 0x5A, 0x54, 0x52, 0x4C, 0xFC,
-  0xF7, 0x4E, 0x2D, 0x29, 0x4E, 0xFC, 0xFC, 0xFC,
-  0xFB, 0x5F, 0x26, 0x24, 0x20, 0x2E, 0x65, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x45, 0x3F, 0x45,
-  0x3E, 0x47, 0x47, 0x47, 0x47, 0x47, 0x3E, 0x44,
-  0x43, 0x40, 0x44, 0x49, 0x51, 0x5C, 0x62, 0x64,
-  0xCB, 0xCB, 0x63, 0x60, 0x58, 0x50, 0x49, 0x48,
-  0x48, 0x48, 0x4A, 0x4D, 0x53, 0x54, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x55, 0x54, 0x54, 0x54,
-  0x54, 0x54, 0x55, 0x57, 0x59, 0x5B, 0x5C, 0x5D,
-  0x5C, 0x5A, 0x54, 0x51, 0x4C, 0x4C, 0x54, 0xFC,
-  0xF9, 0x23, 0xDB, 0x2D, 0x23, 0xFA, 0xFB, 0xFA,
-  0xF5, 0x27, 0x21, 0xD9, 0xF8, 0x20, 0x21, 0xFB,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x5D, 0x58, 0x55,
-  0x50, 0x48, 0x45, 0x43, 0x44, 0x44, 0x45, 0x45,
-  0x3E, 0x3F, 0x43, 0x41, 0x3F, 0x48, 0x52, 0x5D,
-  0x63, 0x65, 0xCB, 0x65, 0x61, 0x5D, 0x52, 0x4B,
-  0x48, 0x47, 0x47, 0x49, 0x4C, 0x51, 0x54, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x55, 0x54, 0x54, 0x54,
-  0x54, 0x58, 0x5A, 0x59, 0x5B, 0x5B, 0x5B, 0x5A,
-  0x55, 0x52, 0x4D, 0x4D, 0x55, 0x5B, 0x5D, 0xFC,
-  0xF1, 0xF9, 0xFC, 0xD4, 0x21, 0xCC, 0xF7, 0xF8,
-  0xF2, 0x21, 0xD9, 0xFC, 0xF2, 0xFB, 0x21, 0x45,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0xD1, 0xD0, 0xCD,
-  0xCC, 0x63, 0x5E, 0x58, 0x50, 0x47, 0x43, 0x3F,
-  0x3F, 0x3F, 0x3F, 0x3F, 0x40, 0x41, 0x3F, 0x4A,
-  0x56, 0x5E, 0x64, 0xCB, 0x65, 0x63, 0x5E, 0x56,
-  0x4C, 0x48, 0x47, 0x47, 0x49, 0x4C, 0x51, 0x54,
-  0x58, 0x57, 0x57, 0x57, 0x57, 0x55, 0x54, 0x54,
-  0x57, 0x5A, 0x5A, 0x5C, 0x5B, 0x5A, 0x58, 0x54,
-  0x51, 0x4C, 0x55, 0x5D, 0x5D, 0x5B, 0x54, 0xFC,
-  0xF0, 0xF9, 0xFC, 0x65, 0x45, 0xCD, 0xFB, 0xFB,
-  0xF8, 0x26, 0xFB, 0xFC, 0xFC, 0xFC, 0x21, 0x27,
-  0xFB, 0xFC, 0xFC, 0xFC, 0xFB, 0xD7, 0x35, 0x34,
-  0x2F, 0x35, 0x36, 0x2F, 0x2F, 0x36, 0x2F, 0x2F,
-  0x36, 0x36, 0x35, 0x35, 0x43, 0x42, 0x41, 0x2E,
-  0x45, 0x4C, 0x5B, 0x62, 0x65, 0xCC, 0x64, 0x60,
-  0x58, 0x4D, 0x49, 0x47, 0x47, 0x49, 0x4C, 0x51,
-  0x58, 0x57, 0x57, 0x57, 0x57, 0x57, 0x55, 0x57,
-  0x58, 0x5A, 0x5A, 0x5B, 0x5A, 0x55, 0x54, 0x51,
-  0x53, 0x5C, 0x5D, 0x5D, 0x54, 0x4B, 0x4D, 0xFC,
-  0xFC, 0x44, 0xFC, 0xFB, 0x7B, 0xAB, 0xA8, 0xAE,
-  0xAB, 0x7F, 0xFC, 0xFC, 0xFB, 0xFB, 0x22, 0x2A,
-  0xFC, 0xFC, 0xFC, 0xFC, 0x36, 0x2F, 0x30, 0x30,
-  0x32, 0x30, 0x32, 0x30, 0x30, 0x30, 0x30, 0x30,
-  0x30, 0x30, 0x30, 0x30, 0x2F, 0x2F, 0x40, 0x41,
-  0x2E, 0x40, 0x48, 0x56, 0x5F, 0x64, 0xCC, 0x65,
-  0x61, 0x59, 0x50, 0x49, 0x47, 0x47, 0x49, 0x4C,
-  0x5A, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58,
-  0x5A, 0x5A, 0x5A, 0x58, 0x55, 0x52, 0x51, 0x5A,
-  0x5D, 0x5D, 0x57, 0x4C, 0x51, 0x54, 0x5D, 0xFC,
-  0xFC, 0x2A, 0xFC, 0xC9, 0xAA, 0x8B, 0x8A, 0x8C,
-  0xAB, 0x8C, 0x8C, 0xFB, 0xFB, 0x23, 0x20, 0xF1,
-  0xFC, 0xFC, 0xFC, 0x3B, 0x33, 0x33, 0x32, 0x32,
-  0x31, 0x32, 0x30, 0x32, 0x32, 0x32, 0x32, 0x30,
-  0x31, 0x31, 0x31, 0x32, 0x33, 0x33, 0x3C, 0x41,
-  0x41, 0x2E, 0x2D, 0x45, 0x4D, 0x5D, 0x63, 0xCC,
-  0x65, 0x62, 0x5D, 0x51, 0x49, 0x47, 0x47, 0x4A,
-  0x59, 0x57, 0x57, 0x57, 0x57, 0x58, 0x58, 0x58,
-  0x5A, 0x5A, 0x58, 0x55, 0x53, 0x53, 0x5C, 0x5E,
-  0x59, 0x51, 0x4E, 0x54, 0x59, 0x5E, 0x62, 0xFC,
-  0xFC, 0xDB, 0xAA, 0xA1, 0x95, 0x9C, 0x8C, 0x88,
-  0x82, 0x83, 0x83, 0x8C, 0x88, 0xAE, 0xB9, 0xFB,
-  0xFC, 0xFC, 0xFC, 0x3C, 0x3B, 0x72, 0x38, 0x33,
-  0x33, 0x33, 0x31, 0x33, 0x31, 0x31, 0x31, 0x31,
-  0x33, 0x33, 0x38, 0x33, 0x72, 0x3B, 0x44, 0x2E,
-  0x41, 0x2E, 0x2E, 0x2D, 0x43, 0x4B, 0x5B, 0x63,
-  0xCB, 0xCC, 0x63, 0x5D, 0x51, 0x49, 0x47, 0x49,
-  0x5C, 0x58, 0x57, 0x57, 0x57, 0x57, 0x58, 0x58,
-  0x58, 0x58, 0x57, 0x53, 0x58, 0x5D, 0x5E, 0x55,
-  0x51, 0x53, 0x58, 0x5E, 0x60, 0x63, 0x64, 0xFC,
-  0xFC, 0xC0, 0xA6, 0x9D, 0x8B, 0x9C, 0x8C, 0x8C,
-  0x6E, 0x83, 0x88, 0x8C, 0x8C, 0x8C, 0x83, 0xE8,
-  0xFB, 0xFC, 0xFC, 0xFC, 0x33, 0x70, 0x70, 0x6F,
-  0x6F, 0x6F, 0x6F, 0x3A, 0x6F, 0x6D, 0x6F, 0x6F,
-  0x70, 0x6F, 0x6F, 0x70, 0x6F, 0x32, 0x5A, 0x48,
-  0x41, 0x2D, 0x2D, 0x2D, 0x2C, 0x41, 0x49, 0x5A,
-  0x62, 0xCB, 0xCB, 0x63, 0x5D, 0x50, 0x49, 0x4A,
-  0x5C, 0x58, 0x58, 0x57, 0x55, 0x57, 0x57, 0x57,
-  0x57, 0x55, 0x56, 0x59, 0x5E, 0x5C, 0x52, 0x53,
-  0x55, 0x5B, 0x5E, 0x61, 0x63, 0x64, 0x63, 0xFC,
-  0xE8, 0xBF, 0xA4, 0x99, 0x9C, 0x8C, 0x88, 0x88,
-  0x6E, 0x88, 0x8C, 0x8C, 0x8C, 0xC2, 0xA6, 0xC4,
-  0xFC, 0xFC, 0xFC, 0xFC, 0x36, 0x3A, 0x6F, 0x70,
-  0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
-  0x70, 0x70, 0x70, 0x70, 0x37, 0x32, 0xCD, 0x5E,
-  0x4C, 0x43, 0x2C, 0x2D, 0x2D, 0x2C, 0x2E, 0x47,
-  0x57, 0x61, 0x65, 0xCC, 0x63, 0x5C, 0x50, 0x4D,
-  0x5C, 0x5A, 0x57, 0x55, 0x55, 0x55, 0x58, 0x58,
-  0x55, 0x54, 0x5B, 0x5E, 0x5D, 0x53, 0x53, 0x55,
-  0x5D, 0x5E, 0x61, 0x61, 0x61, 0x61, 0x5E, 0xFC,
-  0xEA, 0xBE, 0xA4, 0x9B, 0x8B, 0x85, 0x8C, 0x6E,
-  0x8C, 0x8C, 0x8C, 0xA3, 0xAA, 0xA4, 0xA4, 0xE9,
-  0xFB, 0xFC, 0xFC, 0xFC, 0x36, 0x6D, 0x70, 0x73,
-  0x70, 0x70, 0x70, 0x73, 0x73, 0x73, 0x73, 0x70,
-  0x70, 0x70, 0x73, 0x70, 0x37, 0x38, 0xD1, 0xCF,
-  0x61, 0x4D, 0x44, 0x2C, 0x2D, 0x2E, 0x2C, 0x2E,
-  0x3E, 0x56, 0x61, 0xCB, 0xCC, 0x62, 0x5B, 0x57,
-  0x59, 0x58, 0x55, 0x54, 0x54, 0x55, 0x58, 0x58,
-  0x58, 0x5B, 0x5E, 0x5B, 0x53, 0x55, 0x55, 0x5C,
-  0x5E, 0x61, 0x61, 0x60, 0x5D, 0x5A, 0x4E, 0xFC,
-  0xFC, 0xEA, 0xAA, 0x9C, 0x8A, 0x85, 0x82, 0x8C,
-  0x8C, 0xA8, 0xEB, 0xA8, 0xA4, 0xA4, 0xAA, 0xFC,
-  0xFC, 0xFC, 0x64, 0xFB, 0x39, 0x31, 0x72, 0x78,
-  0x73, 0x78, 0x73, 0x74, 0x74, 0x74, 0x74, 0x73,
-  0x78, 0x70, 0x73, 0x73, 0x33, 0xCC, 0xD2, 0xD1,
-  0xCE, 0x62, 0x53, 0x3F, 0x2D, 0x2D, 0x41, 0x2C,
-  0x2E, 0x3E, 0x56, 0x62, 0xCB, 0xCB, 0x61, 0x5D,
-  0x54, 0x54, 0x54, 0x54, 0x56, 0x58, 0x58, 0x58,
-  0x5C, 0x5E, 0x5A, 0x55, 0x58, 0x58, 0x5B, 0x5E,
-  0x61, 0x5E, 0x5D, 0x5A, 0x52, 0x55, 0xCD, 0xFC,
-  0xFC, 0x34, 0xC9, 0xE8, 0xA8, 0xAE, 0xC2, 0xE8,
-  0xC3, 0xA6, 0xA7, 0xA6, 0xAA, 0x78, 0x2E, 0x42,
-  0xFC, 0xFC, 0xD2, 0x64, 0xF8, 0x31, 0x72, 0x73,
-  0x73, 0x73, 0x73, 0x74, 0x75, 0x75, 0x74, 0x73,
-  0x73, 0x73, 0x73, 0x72, 0x33, 0x5C, 0x64, 0xD2,
-  0xD1, 0xCF, 0x63, 0x54, 0x3F, 0x2C, 0x41, 0x41,
-  0x2C, 0x2E, 0x47, 0x58, 0x63, 0xCB, 0xCB, 0x62,
-  0x52, 0x53, 0x53, 0x56, 0x58, 0x58, 0x5A, 0x5B,
-  0x5E, 0x5A, 0x57, 0x58, 0x58, 0x58, 0x60, 0x60,
-  0x5D, 0x5A, 0x55, 0x4E, 0x64, 0xD2, 0xD1, 0xFC,
-  0xFC, 0x41, 0x3E, 0xC1, 0xC0, 0xA3, 0xA6, 0xA7,
-  0xA7, 0xA9, 0xAA, 0xB8, 0x2E, 0x3F, 0x2C, 0x41,
-  0xFC, 0xFC, 0xF7, 0xCE, 0xCD, 0x36, 0x72, 0x73,
-  0x74, 0x75, 0x78, 0x75, 0x75, 0x75, 0x74, 0x74,
-  0x74, 0x74, 0x78, 0x72, 0x6D, 0x49, 0x59, 0xCB,
-  0xD1, 0xD1, 0xD2, 0xCB, 0x56, 0x3F, 0x2C, 0x41,
-  0x40, 0x2D, 0x2E, 0x49, 0x5B, 0x64, 0xCC, 0x64,
-  0x51, 0x53, 0x53, 0x55, 0x58, 0x59, 0x5B, 0x5E,
-  0x59, 0x58, 0x58, 0x58, 0x55, 0x60, 0x60, 0x5C,
-  0x5A, 0x53, 0x5B, 0xD0, 0xD3, 0xD3, 0xD3, 0xFB,
-  0xFC, 0x40, 0x41, 0x45, 0xC4, 0xC0, 0xBE, 0xBE,
-  0xC1, 0xC0, 0x3C, 0x47, 0x2E, 0x21, 0x22, 0x20,
-  0x65, 0xFC, 0xFC, 0xFC, 0xFC, 0x6D, 0x72, 0x75,
-  0x78, 0x76, 0x75, 0x79, 0x76, 0x76, 0x76, 0x76,
-  0x75, 0x75, 0x75, 0x72, 0x6D, 0x2E, 0x48, 0x5D,
-  0xCE, 0xD1, 0xD4, 0xD3, 0xCB, 0x56, 0x43, 0x2C,
-  0x42, 0x43, 0x2E, 0x2E, 0x4A, 0x5D, 0x64, 0x64,
-  0x50, 0x52, 0x56, 0x58, 0x5C, 0x5D, 0x5E, 0x5D,
-  0x5A, 0x58, 0x58, 0x55, 0x61, 0x60, 0x58, 0x58,
-  0x4E, 0x61, 0xD1, 0xD4, 0xD4, 0xD1, 0xEE, 0xFC,
-  0xFC, 0x2B, 0x29, 0x2E, 0x3F, 0xB0, 0xAD, 0x81,
-  0x46, 0x2D, 0x46, 0x2C, 0x24, 0x22, 0x22, 0x23,
-  0x25, 0xFC, 0xFC, 0xFC, 0xFC, 0x6E, 0x73, 0x76,
-  0x76, 0x79, 0x79, 0x79, 0x76, 0x76, 0x79, 0x76,
-  0x79, 0x79, 0x79, 0x74, 0x3F, 0x41, 0x2C, 0x48,
-  0x5F, 0xCF, 0xD5, 0xD7, 0xD6, 0xCD, 0x57, 0x40,
-  0x2E, 0x3F, 0x44, 0x2E, 0x41, 0x4C, 0x60, 0x61,
-  0x51, 0x53, 0x58, 0x5C, 0x5D, 0x5E, 0x5D, 0x5C,
-  0x58, 0x57, 0x54, 0x5F, 0x5E, 0x55, 0x55, 0x52,
-  0x64, 0xD4, 0xD5, 0xD4, 0xD1, 0x5D, 0xFA, 0xFB,
-  0xF4, 0x21, 0x24, 0x41, 0x40, 0x44, 0x2E, 0x2E,
-  0x42, 0x41, 0x2A, 0x24, 0x22, 0x22, 0x22, 0x22,
-  0x23, 0xD9, 0xFC, 0xFC, 0xFC, 0xFC, 0xE5, 0xB8,
-  0x8F, 0x8F, 0x7A, 0x8F, 0x7A, 0x8F, 0x7A, 0x8F,
-  0x8F, 0x8F, 0xB8, 0xE5, 0x3F, 0x3E, 0x43, 0x2C,
-  0x48, 0x61, 0xD1, 0xD7, 0xD9, 0xD7, 0xD0, 0x57,
-  0x41, 0x2E, 0x3E, 0x44, 0x2D, 0x40, 0x52, 0x5D,
-  0x53, 0x55, 0x59, 0x5D, 0x5E, 0x5E, 0x5D, 0x5A,
-  0x57, 0x53, 0x5E, 0x5E, 0x54, 0x53, 0x54, 0x65,
-  0xD5, 0xD6, 0xD4, 0xCE, 0x53, 0xFB, 0xF9, 0xFC,
-  0x24, 0x22, 0x23, 0x23, 0x41, 0x42, 0x2E, 0x40,
-  0x2B, 0x21, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
-  0x23, 0x23, 0xFC, 0xFC, 0xFC, 0xFC, 0xE7, 0xBD,
-  0xB5, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93,
-  0x93, 0xB5, 0xC6, 0xEB, 0x2D, 0x47, 0x4A, 0x47,
-  0x2C, 0x3E, 0x61, 0xD4, 0xDC, 0xDC, 0xDA, 0xCF,
-  0x54, 0x41, 0x41, 0x3E, 0x45, 0x2C, 0x3F, 0x4A,
-  0x58, 0x5A, 0x5C, 0x5F, 0x60, 0x5E, 0x5D, 0x57,
-  0x51, 0x5D, 0x5D, 0x51, 0x53, 0x53, 0xCB, 0xD5,
-  0xD6, 0xD5, 0x63, 0x55, 0xFC, 0xFC, 0xFC, 0x2C,
-  0x23, 0x22, 0x23, 0x22, 0x20, 0x2D, 0x2C, 0x26,
-  0x21, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
-  0x22, 0x21, 0xF0, 0xFC, 0xFC, 0xFC, 0xE2, 0xC6,
-  0xB5, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93,
-  0x93, 0x93, 0xC7, 0xE3, 0x3E, 0x2E, 0x49, 0x52,
-  0x4C, 0x41, 0x44, 0x62, 0xD6, 0xDE, 0xDE, 0xD9,
-  0xD0, 0x51, 0x2E, 0x40, 0x47, 0x44, 0x2C, 0x42,
-  0x5D, 0x5D, 0x5F, 0x60, 0x60, 0x5D, 0x57, 0x51,
-  0x58, 0x5D, 0x4E, 0x52, 0x55, 0x64, 0xD5, 0xD6,
-  0xD4, 0x61, 0x59, 0x6B, 0xFC, 0xFC, 0xFC, 0x21,
-  0x23, 0x22, 0x23, 0x22, 0x23, 0x21, 0x23, 0x22,
-  0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
-  0x22, 0x21, 0x24, 0xFC, 0xFC, 0xFC, 0xE2, 0xC7,
-  0xB5, 0x90, 0x93, 0x93, 0x93, 0x90, 0x93, 0x93,
-  0x90, 0xB5, 0xC8, 0xE4, 0x5F, 0x45, 0x2E, 0x4D,
-  0x57, 0x57, 0x44, 0x43, 0x63, 0xDA, 0xDF, 0xDF,
-  0xD9, 0xCE, 0x4C, 0x2C, 0x3F, 0x3E, 0x40, 0x40,
-  0x60, 0x5E, 0x61, 0x61, 0x5E, 0x5B, 0x53, 0x52,
-  0x5C, 0x52, 0x52, 0x55, 0x61, 0xD4, 0xD5, 0xD1,
-  0x5E, 0x5B, 0x5C, 0xFB, 0xFC, 0xFC, 0x2A, 0x21,
-  0x23, 0x22, 0x23, 0x22, 0x22, 0x22, 0x23, 0x22,
-  0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
-  0x22, 0x22, 0x22, 0xFB, 0xFC, 0xFC, 0xB3, 0xC8,
-  0xB5, 0x90, 0x92, 0xB5, 0x93, 0x93, 0xB5, 0x93,
-  0x92, 0xB5, 0xC8, 0xB9, 0xD0, 0x5E, 0x44, 0x40,
-  0x52, 0x58, 0x57, 0x48, 0x40, 0x63, 0xD9, 0xE0,
-  0xE0, 0xD9, 0xCB, 0x49, 0x2D, 0x3F, 0x45, 0x3F,
-  0x63, 0x61, 0x62, 0x60, 0x5E, 0x55, 0x4D, 0x59,
-  0x53, 0x4E, 0x54, 0x5D, 0xD2, 0xD4, 0xD2, 0x5E,
-  0x5C, 0x5D, 0xFC, 0xFC, 0xFC, 0xF8, 0x29, 0x23,
-  0x23, 0x23, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
-  0x23, 0x22, 0x22, 0x23, 0x23, 0x23, 0x22, 0x22,
-  0x22, 0x22, 0x22, 0xF0, 0xFC, 0xFC, 0xB3, 0xC7,
-  0xB5, 0x93, 0xB5, 0x93, 0x93, 0x91, 0x93, 0x93,
-  0x91, 0xB5, 0xC7, 0xAD, 0xD6, 0xD2, 0x5E, 0x3F,
-  0x3F, 0x57, 0x57, 0x58, 0x4A, 0x41, 0x64, 0xDC,
-  0xF1, 0xDF, 0xDA, 0x61, 0x45, 0x2E, 0x43, 0x47,
-  0xCB, 0x63, 0x62, 0x5F, 0x58, 0x51, 0x53, 0x54,
-  0x4C, 0x52, 0x5C, 0xCD, 0xD3, 0xD2, 0x60, 0x5D,
-  0x5D, 0xFB, 0xFC, 0xFC, 0xFC, 0xDB, 0x49, 0x24,
-  0x21, 0x23, 0x23, 0x22, 0x26, 0x26, 0x2A, 0x24,
-  0x22, 0x23, 0x22, 0x21, 0x24, 0x26, 0x26, 0x2A,
-  0x29, 0x2B, 0x24, 0x25, 0xFC, 0xFC, 0xB3, 0xC5,
-  0x91, 0x91, 0x92, 0x91, 0x92, 0x92, 0x93, 0x93,
-  0x91, 0x93, 0xC6, 0xAD, 0xDC, 0xD9, 0xD4, 0x60,
-  0x43, 0x45, 0x58, 0x58, 0x57, 0x4B, 0x43, 0xCC,
-  0xDD, 0xF1, 0xD8, 0xD5, 0x5D, 0x43, 0x41, 0x47,
-  0xCD, 0x63, 0x62, 0x5D, 0x54, 0x4C, 0x55, 0x4B,
-  0x51, 0x58, 0x62, 0xD0, 0xD0, 0x62, 0x5D, 0x5D,
-  0x67, 0xFC, 0xFC, 0xFC, 0xFC, 0x58, 0x4E, 0x28,
-  0x2A, 0x20, 0x23, 0x22, 0x23, 0x2A, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x23, 0x25, 0x2A, 0x2E, 0x2D,
-  0x2E, 0x2E, 0x2E, 0x23, 0xFA, 0xFC, 0xB2, 0xBD,
-  0xB5, 0x90, 0x91, 0x93, 0x92, 0x90, 0x91, 0x93,
-  0x92, 0x91, 0xBD, 0xAD, 0xDE, 0xE0, 0xD8, 0xD7,
-  0x61, 0x40, 0x48, 0x58, 0x58, 0x58, 0x48, 0x44,
-  0xCF, 0xDE, 0xE0, 0xDD, 0xD0, 0x52, 0x41, 0x45,
-  0xCD, 0x63, 0x61, 0x58, 0x4D, 0x51, 0x4C, 0x4B,
-  0x54, 0x5D, 0xCC, 0xCE, 0x63, 0x61, 0x5D, 0x5D,
-  0xFB, 0xFC, 0xFC, 0xFC, 0xFC, 0x4B, 0x27, 0x21,
-  0x22, 0x22, 0x23, 0x22, 0x22, 0x24, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x20,
-  0x27, 0x2B, 0x41, 0x2B, 0x23, 0xFC, 0xB2, 0xB6,
-  0x93, 0x90, 0x92, 0xB5, 0x92, 0x90, 0xB5, 0x90,
-  0x92, 0x93, 0xBC, 0xAD, 0xDC, 0xF1, 0xF3, 0xF0,
-  0xD9, 0x61, 0x41, 0x4A, 0x58, 0x57, 0x57, 0x44,
-  0x49, 0xD2, 0xDD, 0xD8, 0xDA, 0x63, 0x4A, 0x45,
-  0xCC, 0x63, 0x5E, 0x52, 0x4B, 0x4C, 0x49, 0x51,
-  0x5C, 0x61, 0xCD, 0x65, 0x63, 0x5E, 0x4E, 0xCF,
-  0xFB, 0xFB, 0xF0, 0xFC, 0xD2, 0x2A, 0x22, 0x23,
-  0x22, 0x22, 0x23, 0x22, 0x22, 0x21, 0x22, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x23, 0x22, 0x26, 0x41, 0x27, 0xF9, 0x81, 0xB7,
-  0xB5, 0x91, 0x92, 0xB5, 0x91, 0xB5, 0x93, 0xB5,
-  0x93, 0xB6, 0xB7, 0xB9, 0xCB, 0xD8, 0xF3, 0xF2,
-  0xF2, 0xDB, 0x61, 0x2D, 0x51, 0x58, 0x57, 0x58,
-  0x41, 0x51, 0xD4, 0xDB, 0xDC, 0xD1, 0x5B, 0x4C,
-  0xCB, 0x62, 0x59, 0x4C, 0x4A, 0x49, 0x4B, 0x55,
-  0x60, 0x64, 0xCC, 0x64, 0x5E, 0x55, 0x60, 0xE1,
-  0xFB, 0xF8, 0xFC, 0xFC, 0x21, 0x22, 0x22, 0x23,
-  0x22, 0x22, 0x23, 0x22, 0x22, 0x21, 0x22, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x23, 0x22, 0x21, 0x24, 0x2D, 0x21, 0xB4, 0xBB,
-  0xB6, 0xB5, 0xB6, 0xB7, 0xB7, 0xB7, 0xB7, 0xB6,
-  0xB6, 0xB6, 0xBB, 0xB9, 0x45, 0xCB, 0xDF, 0xF3,
-  0xF3, 0xF3, 0xDB, 0x5E, 0x2C, 0x51, 0x58, 0x58,
-  0x52, 0x2D, 0x5C, 0xD4, 0xD9, 0xD5, 0x63, 0x58,
-  0x64, 0x60, 0x53, 0x49, 0x4A, 0x49, 0x52, 0x5C,
-  0x63, 0xCD, 0xCD, 0x63, 0x5C, 0x4E, 0x65, 0xFC,
-  0xFC, 0xF5, 0xFC, 0xD2, 0x23, 0x22, 0x22, 0x23,
-  0x22, 0x22, 0x23, 0x22, 0x22, 0x21, 0x22, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x23, 0x22, 0x21, 0x22, 0x25, 0x29, 0xB3, 0xC7,
-  0xB5, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6,
-  0xB6, 0xB5, 0xC7, 0xAD, 0x57, 0x3F, 0xCB, 0xF0,
-  0xF3, 0xF3, 0xF2, 0xD9, 0x58, 0x41, 0x4C, 0x58,
-  0x57, 0x47, 0x42, 0x62, 0xD4, 0xD4, 0xCC, 0x60,
-  0x63, 0x5D, 0x50, 0x47, 0x48, 0x4B, 0x58, 0x60,
-  0xCC, 0xCE, 0xCD, 0x60, 0x53, 0x5C, 0x62, 0xFB,
-  0xF9, 0xFC, 0xFC, 0x21, 0x23, 0x22, 0x22, 0x23,
-  0x22, 0x22, 0x23, 0x23, 0x23, 0x21, 0x22, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x23, 0x22, 0x23, 0x23, 0x22, 0x23, 0x81, 0xC7,
-  0xB7, 0xB7, 0xBC, 0xB7, 0xBC, 0xBC, 0xBC, 0xB7,
-  0xB7, 0xB7, 0xC8, 0x80, 0x58, 0x57, 0x40, 0xCE,
-  0xF3, 0xF2, 0xF2, 0xF0, 0xD5, 0x4C, 0x3F, 0x4B,
-  0x52, 0x50, 0x2D, 0x4B, 0x64, 0xD2, 0xCC, 0x61,
-  0x60, 0x58, 0x4A, 0x47, 0x47, 0x4C, 0x59, 0x64,
-  0xD0, 0xD0, 0x64, 0x59, 0x49, 0x5D, 0xFB, 0xFC,
-  0xD9, 0xFC, 0xD6, 0x23, 0x22, 0x22, 0x22, 0x23,
-  0x22, 0x22, 0x23, 0x23, 0x21, 0x21, 0x22, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x23, 0x22, 0x23, 0x23, 0x22, 0x23, 0xB4, 0xC8,
-  0xBD, 0xB7, 0xBD, 0xBC, 0xBD, 0xC5, 0xBC, 0xC5,
-  0xBC, 0xBD, 0xC7, 0xAC, 0x58, 0x57, 0x58, 0x2C,
-  0xD1, 0xF0, 0xF3, 0xF3, 0xE0, 0xCD, 0x45, 0x3E,
-  0x48, 0x4B, 0x3F, 0x41, 0x56, 0x64, 0x65, 0x62,
-  0x5D, 0x52, 0x47, 0x48, 0x48, 0x53, 0x60, 0xCC,
-  0xD2, 0xD0, 0x63, 0x52, 0x4E, 0x53, 0xFB, 0xFB,
-  0xFC, 0xFC, 0x23, 0x23, 0x22, 0x23, 0x22, 0x23,
-  0x22, 0x22, 0x23, 0x23, 0x20, 0x21, 0x22, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x23, 0x22, 0x23, 0x22, 0x23, 0x22, 0xB4, 0xC7,
-  0xC5, 0xBC, 0xC5, 0xBD, 0xC5, 0xC5, 0xBD, 0xC5,
-  0xBC, 0xC6, 0xC7, 0xB9, 0x58, 0x57, 0x58, 0x57,
-  0x2D, 0xD4, 0xF1, 0xF2, 0xF0, 0xD9, 0x5D, 0x47,
-  0x48, 0x3F, 0x42, 0x2C, 0x48, 0x5C, 0x5F, 0x60,
-  0x58, 0x50, 0x47, 0x4A, 0x49, 0x55, 0x63, 0xD0,
-  0xD2, 0xCD, 0x5D, 0x49, 0x4E, 0xE1, 0xFC, 0xF0,
-  0xFC, 0xF8, 0x22, 0x22, 0x22, 0x23, 0x22, 0x23,
-  0x22, 0x22, 0x23, 0x20, 0x21, 0x21, 0x22, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0x22,
-  0x23, 0x22, 0x23, 0x23, 0x23, 0x22, 0xC4, 0xC8,
-  0xBD, 0xBD, 0xC6, 0xBD, 0xC6, 0xC6, 0xC5, 0xC6,
-  0xBD, 0xC6, 0xC7, 0xE4, 0x54, 0x57, 0x58, 0x57,
-  0x57, 0x43, 0xD7, 0xE0, 0xF1, 0xD8, 0xCD, 0x4B,
-  0x4A, 0x47, 0x42, 0x2C, 0x3F, 0x4D, 0x58, 0x5C,
-  0x52, 0x4B, 0x48, 0x4B, 0x4A, 0x58, 0xCB, 0xD3,
-  0xD2, 0xCD, 0x58, 0x47, 0x4A, 0xFC, 0xFC, 0xFB,
-  0xFC, 0x2B, 0x22, 0x22, 0x22, 0x23, 0x22, 0x23,
-  0x22, 0x22, 0x23, 0x26, 0x21, 0x21, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
-  0x22, 0x23, 0x22, 0x23, 0x22, 0x23, 0xE5, 0xC8,
-  0xBA, 0xC5, 0xC6, 0xC6, 0xC6, 0xC7, 0xC6, 0xC7,
-  0xC5, 0xC6, 0xC8, 0xE5, 0x2E, 0x54, 0x58, 0x57,
-  0x57, 0x4C, 0x4D, 0xDA, 0xD8, 0xD8, 0xD4, 0x5C,
-  0x4B, 0x4B, 0x3F, 0x42, 0x44, 0x4A, 0x51, 0x58,
-  0x4B, 0x48, 0x4B, 0x51, 0x4D, 0x5F, 0xD0, 0xD1,
-  0xD0, 0x64, 0x51, 0x44, 0x6B, 0xFC, 0xFB, 0xFC,
-  0xFC, 0x21, 0x23, 0x22, 0x22, 0x23, 0x22, 0x23,
-  0x22, 0x22, 0x23, 0x26, 0x21, 0x23, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
-  0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0xE5, 0xED,
-  0xE7, 0xBA, 0xC8, 0xC6, 0xC6, 0xC6, 0xC6, 0xC7,
-  0xC7, 0xE5, 0xED, 0xE6, 0x61, 0x41, 0x52, 0x58,
-  0x58, 0x57, 0x45, 0x5E, 0xD7, 0xDD, 0xD5, 0x60,
-  0x4B, 0x4C, 0x48, 0x4D, 0x4D, 0x50, 0x4D, 0x56,
-  0x4A, 0x3E, 0x53, 0x53, 0x52, 0x63, 0xD3, 0xD0,
-  0xCE, 0x60, 0x4A, 0x45, 0xFC, 0xFC, 0xF7, 0xFC,
-  0xFC, 0x21, 0x23, 0x23, 0x22, 0x23, 0x22, 0x23,
-  0x22, 0x23, 0x21, 0x2A, 0x20, 0x23, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x23, 0x22, 0x23, 0x22, 0x21, 0x23, 0xEB, 0xF6,
-  0xF6, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED,
-  0xF6, 0xF6, 0xF6, 0xE6, 0xDB, 0x58, 0x45, 0x4B,
-  0x58, 0x57, 0x4D, 0x4B, 0x64, 0xD4, 0xD0, 0x5C,
-  0x48, 0x51, 0x4C, 0x5D, 0x5E, 0x5C, 0x56, 0x59,
-  0x3E, 0x4A, 0x58, 0x54, 0x52, 0x65, 0xD3, 0xD0,
-  0xCF, 0x5D, 0x48, 0xFC, 0xFC, 0xFC, 0xFA, 0xFC,
-  0xFC, 0x21, 0x22, 0x23, 0x22, 0x23, 0x22, 0x23,
-  0x22, 0x23, 0x21, 0x2A, 0x21, 0x23, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x23, 0x22, 0x23, 0x22, 0x21, 0x4F, 0xE6, 0xC6,
-  0xC6, 0xBD, 0xC6, 0xBD, 0xBD, 0xBD, 0xBD, 0xC6,
-  0xC5, 0xBA, 0xC7, 0xE6, 0xF2, 0xD4, 0x49, 0x4B,
-  0x3E, 0x4D, 0x52, 0x3E, 0x52, 0x63, 0x64, 0x56,
-  0x48, 0x54, 0x4D, 0x61, 0xCC, 0xCC, 0x60, 0x60,
-  0x47, 0x4D, 0x5C, 0x53, 0x58, 0xCF, 0xD1, 0xCF,
-  0xD0, 0x59, 0x45, 0xFC, 0xFC, 0xFC, 0xEF, 0xF9,
-  0xFC, 0x21, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22,
-  0x23, 0x22, 0x23, 0x2A, 0x21, 0x23, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x23, 0x22, 0x23, 0x22, 0x23, 0x4F, 0xE4, 0xB9,
-  0xAF, 0x80, 0x80, 0x8E, 0x8E, 0x8E, 0x8E, 0x8F,
-  0x80, 0xB4, 0xB9, 0xE4, 0x7F, 0xDE, 0x61, 0x52,
-  0x54, 0x48, 0x3F, 0x43, 0x4D, 0x56, 0x59, 0x4B,
-  0x3E, 0x58, 0x53, 0x61, 0xD3, 0xD4, 0xCF, 0xCD,
-  0x4C, 0x58, 0x5F, 0x53, 0x5E, 0xD3, 0xD0, 0xCE,
-  0xCE, 0x52, 0x3F, 0xFC, 0xFC, 0xFC, 0xF7, 0x65,
-  0xFA, 0x22, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22,
-  0x23, 0x22, 0x21, 0x2A, 0x23, 0x23, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x23, 0x22, 0x23, 0x22, 0x21, 0xB1, 0xE4, 0xE6,
-  0x7C, 0xB1, 0x7C, 0xB1, 0xB2, 0xB2, 0xB3, 0x3D,
-  0xB3, 0x3C, 0xE5, 0xB3, 0xB0, 0xF1, 0xD0, 0x58,
-  0x5D, 0x4D, 0x40, 0x41, 0x48, 0x51, 0x4C, 0x3F,
-  0x3F, 0x4D, 0x5A, 0x5A, 0xD5, 0xD9, 0xD7, 0xD4,
-  0x57, 0x5E, 0x61, 0x4C, 0x63, 0xD4, 0xCF, 0xCE,
-  0xCB, 0x4D, 0x4A, 0xFC, 0xFC, 0xFC, 0xFC, 0xF0,
-  0xFB, 0x22, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22,
-  0x23, 0x22, 0x23, 0x2A, 0x21, 0x23, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x22, 0x23, 0x22, 0x23, 0x23, 0xB1, 0x81, 0x7D,
-  0x39, 0x35, 0x35, 0x36, 0x36, 0x36, 0x36, 0x36,
-  0x36, 0x36, 0x7C, 0xB2, 0xB0, 0xDF, 0xD2, 0x57,
-  0x60, 0x59, 0x5B, 0x59, 0x52, 0x4C, 0x4A, 0x40,
-  0x42, 0x4A, 0x53, 0x4D, 0xD2, 0xDE, 0xDE, 0xD9,
-  0x5E, 0x5E, 0x60, 0x4A, 0xCD, 0xD1, 0xCF, 0xCE,
-  0x63, 0x49, 0x5C, 0xFB, 0xE8, 0x89, 0x9F, 0xFC,
-  0xD6, 0x21, 0x21, 0x23, 0x22, 0x22, 0x23, 0x22,
-  0x23, 0x22, 0x21, 0x2A, 0x22, 0x23, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x7F, 0xB9,
-  0x71, 0x6C, 0x38, 0x38, 0x33, 0x33, 0x33, 0x38,
-  0x38, 0x71, 0xAD, 0xE4, 0xD3, 0xDA, 0xCC, 0x52,
-  0x63, 0x60, 0xCE, 0xD4, 0xCF, 0x60, 0x4C, 0x40,
-  0x3F, 0x45, 0x4B, 0x5A, 0xCB, 0xD8, 0xDE, 0xDC,
-  0x5E, 0x5E, 0x5F, 0x4C, 0xD2, 0xD2, 0xCF, 0xCF,
-  0x61, 0x45, 0x5E, 0xA7, 0x9D, 0x95, 0x8B, 0x99,
-  0xFC, 0x41, 0x21, 0x23, 0x23, 0x22, 0x23, 0x22,
-  0x23, 0x22, 0x23, 0x2A, 0x23, 0x23, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x77, 0x77, 0xF6,
-  0xFC, 0x7D, 0x7D, 0x7E, 0x7E, 0x7E, 0x7E, 0x7D,
-  0x7D, 0xFC, 0x47, 0x64, 0xD0, 0xD0, 0x5D, 0x4B,
-  0x62, 0xCC, 0xD1, 0xDE, 0xDE, 0xD4, 0x5E, 0x43,
-  0x3F, 0x3E, 0x48, 0x53, 0x58, 0xDB, 0xD8, 0xDC,
-  0x5E, 0x5E, 0x5E, 0x53, 0xD4, 0xD2, 0xD0, 0xD0,
-  0x5E, 0x49, 0xA7, 0xA6, 0x89, 0x95, 0x8B, 0x9C,
-  0x9C, 0xFB, 0xD4, 0x22, 0x22, 0x22, 0x22, 0x23,
-  0x22, 0x23, 0x23, 0x2A, 0x22, 0x23, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
-  0x23, 0x22, 0x23, 0x23, 0x98, 0x8C, 0x8C, 0x88,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xF8,
-  0xE9, 0x9C, 0x48, 0x5C, 0xD0, 0xCB, 0x48, 0x49,
-  0x5B, 0xCB, 0xCD, 0xE0, 0xF1, 0xDD, 0xD0, 0x4A,
-  0x41, 0x47, 0x45, 0x4C, 0x48, 0xD7, 0xDE, 0xDC,
-  0x5E, 0x5E, 0x5A, 0x58, 0xD1, 0xD0, 0xD0, 0xD2,
-  0x5C, 0x55, 0xA7, 0xA6, 0x87, 0x86, 0x89, 0x94,
-  0x9C, 0xA9, 0xFC, 0xF4, 0x22, 0x23, 0x22, 0x23,
-  0x22, 0x23, 0x22, 0x2A, 0x21, 0x23, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
-  0x22, 0x23, 0x22, 0x23, 0xA4, 0x89, 0x8C, 0xAA,
-  0xFB, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xF7,
-  0x85, 0x88, 0x8D, 0x59, 0x64, 0x63, 0x47, 0x3E,
-  0x4C, 0x60, 0x61, 0xE0, 0xF0, 0xDF, 0xD9, 0x5D,
-  0x2E, 0x3E, 0x3E, 0x47, 0x4D, 0xCD, 0xDE, 0xDC,
-  0x5D, 0x5C, 0x51, 0x5D, 0xD1, 0xD2, 0xD2, 0xD4,
-  0x5A, 0xBE, 0xA7, 0x98, 0x8A, 0x8A, 0xA0, 0x8B,
-  0x86, 0x86, 0xF7, 0xFC, 0xF7, 0x26, 0x23, 0x23,
-  0x22, 0x22, 0x22, 0x22, 0x21, 0x22, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
-  0x22, 0x21, 0x21, 0x21, 0xA1, 0x98, 0x9F, 0xBF,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xA7,
-  0x8C, 0x86, 0x8D, 0x59, 0x5E, 0x5D, 0x3F, 0x3E,
-  0x47, 0x53, 0x63, 0xD9, 0xF0, 0xF1, 0xDE, 0xD0,
-  0x43, 0x3E, 0x47, 0x45, 0x4A, 0x5B, 0xDC, 0xDA,
-  0x5D, 0x59, 0x49, 0x5F, 0xD1, 0xD2, 0xD3, 0xB9,
-  0xA5, 0xA7, 0x98, 0x9B, 0x96, 0x9D, 0x89, 0x89,
-  0x8B, 0x9C, 0x9D, 0xFC, 0xFC, 0xFC, 0x26, 0x22,
-  0x23, 0x23, 0x22, 0x22, 0x21, 0x22, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
-  0x22, 0x22, 0x29, 0x2D, 0x99, 0x99, 0xA2, 0xAA,
-  0xC4, 0xFB, 0xFC, 0xFC, 0xFC, 0xF6, 0xBF, 0xA2,
-  0x9C, 0x9C, 0x8E, 0xDC, 0xCD, 0x51, 0x41, 0x3E,
-  0x45, 0x49, 0x58, 0xCD, 0xE0, 0xE0, 0xD8, 0xDA,
-  0x4C, 0x4A, 0x45, 0x45, 0x48, 0x47, 0xDA, 0xDA,
-  0x5C, 0x58, 0x44, 0x69, 0xA9, 0x98, 0xA4, 0xA6,
-  0xA1, 0xA4, 0x99, 0x9E, 0x9D, 0x8B, 0x8A, 0x97,
-  0x87, 0x9A, 0x8A, 0xC2, 0xFC, 0xFC, 0xFC, 0x4D,
-  0x21, 0x21, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0x22,
-  0x21, 0x22, 0x2D, 0x34, 0xA4, 0xA2, 0xA2, 0xA9,
-  0xBF, 0xC0, 0xC3, 0xC1, 0xC0, 0xBE, 0xA6, 0x9D,
-  0x99, 0x87, 0xA2, 0xF1, 0xDC, 0x64, 0x42, 0x45,
-  0x47, 0x3E, 0x49, 0x4C, 0xDD, 0xDF, 0xD8, 0xDB,
-  0x5E, 0x4C, 0x48, 0x45, 0x45, 0x41, 0xD1, 0xD6,
-  0x5A, 0x55, 0x3F, 0xA7, 0xA1, 0x98, 0x9F, 0x99,
-  0x9F, 0x9D, 0x9A, 0x95, 0x8B, 0x97, 0x89, 0x8A,
-  0x88, 0x94, 0x9C, 0x8C, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xF4, 0x21, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
-  0x23, 0x23, 0x2C, 0x2C, 0xA8, 0xA2, 0xA4, 0xA4,
-  0xA9, 0xAA, 0xAA, 0xAA, 0xA9, 0xA6, 0x98, 0x9C,
-  0x8B, 0x88, 0x98, 0x8D, 0xD8, 0xD6, 0x4E, 0x47,
-  0x47, 0x49, 0x47, 0x3F, 0xDA, 0xDD, 0xDE, 0xDD,
-  0xCC, 0x4A, 0x4B, 0x3E, 0x45, 0x43, 0x61, 0xD4,
-  0x56, 0x51, 0x44, 0xA4, 0x9B, 0x8B, 0x9C, 0x9A,
-  0xA0, 0xA2, 0x98, 0x98, 0x8B, 0x8B, 0x98, 0x98,
-  0x84, 0x8B, 0x94, 0x8A, 0xA4, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xF2, 0x21, 0x22, 0x21, 0x22, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0x23,
-  0x23, 0x22, 0x2C, 0x2D, 0xC0, 0xA4, 0xA2, 0xA4,
-  0xA4, 0xA6, 0xA6, 0xA6, 0xA4, 0xA2, 0x9F, 0x89,
-  0x8B, 0x9C, 0x9C, 0x8B, 0x68, 0xDB, 0x5F, 0x4B,
-  0x3E, 0x49, 0x4B, 0x3E, 0xCC, 0xDA, 0xDC, 0xDD,
-  0xD3, 0x49, 0x52, 0x48, 0x45, 0x45, 0x53, 0xD0,
-  0x51, 0x4A, 0x44, 0xA4, 0x9B, 0x8B, 0x9C, 0xA0,
-  0x9B, 0x86, 0x89, 0x98, 0x89, 0x8A, 0x96, 0x8A,
-  0x9C, 0x89, 0x89, 0x9C, 0x8C, 0xF6, 0xFC, 0xFC,
-  0xFC, 0xFC, 0x21, 0x22, 0x21, 0x22, 0x23, 0x22,
-  0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x22, 0x23,
-  0x22, 0x21, 0x2B, 0x34, 0xC0, 0xA8, 0xA4, 0xA2,
-  0xA2, 0x98, 0xA1, 0xA0, 0x98, 0x9F, 0x95, 0x8A,
-  0x94, 0xA1, 0x8A, 0x84, 0x9B, 0x68, 0xCC, 0x49,
-  0x4A, 0x47, 0x4C, 0x4B, 0x51, 0xD3, 0xDA, 0xDC,
-  0xD5, 0x56, 0x56, 0x4A, 0x3E, 0x45, 0x48, 0x63,
-  0x4A, 0x47, 0x3E, 0xA7, 0x98, 0x9D, 0x9E, 0x8B,
-  0x95, 0x9B, 0x89, 0x86, 0x9B, 0x8B, 0x89, 0x84,
-  0x9A, 0xA1, 0x95, 0x9A, 0x8C, 0xA4, 0xFC, 0xFC,
-  0xFC, 0xFA, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22,
-  0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x22, 0x23,
-  0x21, 0x23, 0x2C, 0xF6, 0xBF, 0xA9, 0xA2, 0x99,
-  0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9B, 0x87, 0x8B,
-  0x9C, 0x86, 0x9C, 0x8A, 0x87, 0x87, 0x89, 0x51,
-  0x54, 0x47, 0x4B, 0x50, 0x4B, 0xCF, 0xD6, 0xDC,
-  0xD5, 0x60, 0x54, 0x52, 0x48, 0x45, 0x40, 0x5A,
-  0x45, 0x43, 0x47, 0xA7, 0x98, 0x9B, 0x95, 0x95,
-  0x9A, 0x87, 0x98, 0x98, 0x8A, 0x86, 0x87, 0x9E,
-  0x9B, 0x95, 0x9D, 0x9D, 0x99, 0x85, 0xA6, 0xFA,
-  0xF2, 0x21, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22,
-  0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x22, 0x22,
-  0x21, 0x24, 0xFB, 0xF7, 0xBF, 0xA6, 0xA2, 0x99,
-  0x97, 0x89, 0x86, 0x89, 0x9C, 0x96, 0x9E, 0x94,
-  0x89, 0x99, 0x98, 0x89, 0x9E, 0x9B, 0x89, 0x8B,
-  0x58, 0x4B, 0x4A, 0x52, 0x48, 0xCC, 0xD3, 0xDA,
-  0xD3, 0x65, 0x4C, 0x58, 0x49, 0x3E, 0x2E, 0x4D,
-  0x40, 0x41, 0x45, 0xA9, 0xA1, 0x9B, 0x9E, 0x9C,
-  0x95, 0x8A, 0x94, 0x89, 0x96, 0x87, 0x9C, 0x9A,
-  0x84, 0x9D, 0x9C, 0x9E, 0x9A, 0x9C, 0x9D, 0xBB,
-  0x23, 0x23, 0x22, 0x22, 0x21, 0x22, 0x23, 0x22,
-  0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x23, 0x23,
-  0x24, 0xFC, 0xFC, 0xF6, 0xBF, 0xA6, 0x9F, 0x99,
-  0x89, 0x95, 0x87, 0x94, 0x9D, 0x9E, 0x97, 0x9E,
-  0x95, 0x9B, 0x89, 0x95, 0x95, 0x9B, 0x89, 0x87,
-  0x5D, 0x56, 0x3E, 0x51, 0x3E, 0x60, 0xCF, 0xD3,
-  0xD2, 0xCD, 0x5C, 0x49, 0x4B, 0x3E, 0x2C, 0x48,
-  0x3E, 0x43, 0x3E, 0xA9, 0xA1, 0x9B, 0x97, 0x94,
-  0x95, 0x9A, 0x9C, 0x87, 0x87, 0x9B, 0x9C, 0x95,
-  0x9D, 0x89, 0x9A, 0x89, 0x9E, 0x9E, 0x8C, 0xA6,
-  0x20, 0x23, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22,
-  0x22, 0x22, 0x22, 0x22, 0x21, 0x21, 0x20, 0x40,
-  0xFC, 0xFC, 0xFC, 0xEC, 0xBE, 0xA4, 0x9F, 0x99,
-  0x95, 0x9F, 0xA0, 0x88, 0x9D, 0x8B, 0x97, 0x95,
-  0x87, 0x95, 0x96, 0x95, 0x97, 0x94, 0x94, 0x98,
-  0xD3, 0x4C, 0x47, 0x4D, 0x42, 0x4C, 0x60, 0xCC,
-  0xCE, 0xD0, 0x65, 0x4B, 0x47, 0x44, 0x2B, 0x45,
-  0x4B, 0x47, 0x49, 0xA7, 0xA1, 0x9A, 0x97, 0x89,
-  0x95, 0x97, 0x97, 0x9E, 0x89, 0x95, 0x89, 0x9C,
-  0x87, 0x95, 0x97, 0x99, 0x95, 0x99, 0x9F, 0xA4,
-  0xC4, 0x21, 0x21, 0x23, 0x21, 0x23, 0x23, 0x23,
-  0x23, 0x23, 0x23, 0x23, 0x21, 0x20, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xEA, 0xAA, 0xA6, 0xA2, 0x99,
-  0x8B, 0x9A, 0x95, 0x9E, 0x9E, 0x9A, 0x94, 0x87,
-  0x94, 0x94, 0x89, 0x94, 0x9B, 0x9B, 0xA7, 0xDC,
-  0xDB, 0x65, 0x2E, 0x3E, 0x43, 0x44, 0x49, 0x58,
-  0x63, 0xD3, 0xD3, 0x5E, 0x42, 0x42, 0x2D, 0x40,
-  0x54, 0x4C, 0x4A, 0xA7, 0xA0, 0x99, 0x9B, 0x94,
-  0xA0, 0x8A, 0x9B, 0x9D, 0x87, 0x95, 0x94, 0x8B,
-  0x8A, 0x98, 0x9C, 0x8A, 0x9B, 0x99, 0xA2, 0xA6,
-  0xBF, 0xEC, 0x2A, 0x20, 0x21, 0x23, 0x21, 0x20,
-  0x20, 0x20, 0x20, 0x4C, 0xF9, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xEB, 0xAA, 0xA4, 0x9F, 0x9C,
-  0x8B, 0x9B, 0x88, 0x84, 0x9E, 0x9D, 0x96, 0x94,
-  0x94, 0x9A, 0x9B, 0x9B, 0xA4, 0xD5, 0xCD, 0xDE,
-  0xF1, 0xDA, 0x4C, 0x2D, 0x41, 0x2B, 0x42, 0x4C,
-  0x5E, 0xD4, 0xD7, 0xCD, 0x49, 0x2E, 0x2E, 0x41,
-  0x5E, 0x57, 0xA7, 0xA6, 0xA7, 0xA4, 0xA2, 0x98,
-  0x9D, 0x9C, 0xA1, 0x99, 0x9D, 0x88, 0x8B, 0x9C,
-  0x8A, 0x9C, 0x9C, 0x94, 0x9C, 0x89, 0xA0, 0xA6,
-  0xAA, 0xEB, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFB, 0xE9, 0xAA, 0xA6, 0xA2, 0x8B,
-  0x8B, 0x8A, 0x86, 0x9B, 0x9C, 0x98, 0xA0, 0x9B,
-  0x9B, 0x84, 0xA7, 0xB4, 0x61, 0xD1, 0xD2, 0xE0,
-  0xF1, 0xDC, 0x61, 0x2D, 0x2E, 0x3F, 0x56, 0x62,
-  0x5D, 0xD4, 0xD9, 0xD3, 0x54, 0x41, 0x41, 0x44,
-  0xCB, 0x60, 0x52, 0xA9, 0xA9, 0xA9, 0xA7, 0xA6,
-  0xA6, 0xA4, 0xA4, 0xA2, 0xA2, 0x9D, 0x95, 0x89,
-  0x9C, 0x8A, 0x9E, 0x9C, 0x8A, 0x9E, 0xA0, 0xA8,
-  0xC0, 0xE9, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xE9, 0xAA, 0xA6, 0xA0, 0x99,
-  0x9C, 0x8B, 0x9A, 0x84, 0x9B, 0x9B, 0x98, 0x98,
-  0xA9, 0xB9, 0x49, 0x57, 0xCB, 0xD4, 0xD3, 0xF1,
-  0xD8, 0xDA, 0xCE, 0x3F, 0x41, 0x4B, 0x5D, 0xCB,
-  0x5E, 0xD6, 0xDB, 0xD6, 0x5D, 0x43, 0x3F, 0x49,
-  0xD1, 0xCC, 0x4F, 0xDD, 0xC3, 0xBB, 0xBF, 0xAA,
-  0xAA, 0xA9, 0xAA, 0xA8, 0xA8, 0xA6, 0xA6, 0xA2,
-  0x9C, 0x9F, 0x9B, 0x9A, 0x9D, 0xA2, 0xA8, 0xAA,
-  0xC1, 0xEA, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xEA, 0xC0, 0xAA, 0xA6, 0xA2,
-  0xA2, 0x99, 0xA0, 0xA0, 0xA4, 0xA7, 0xA9, 0xC0,
-  0x67, 0x49, 0x54, 0x60, 0xD0, 0xD4, 0xCC, 0xDF,
-  0xD9, 0xD5, 0xD2, 0x3E, 0x47, 0x56, 0x60, 0xCD,
-  0x5D, 0xD9, 0xD9, 0xD6, 0x61, 0x3F, 0x47, 0x52,
-  0xD6, 0xD3, 0x62, 0x4D, 0x40, 0x4A, 0x57, 0xCA,
-  0xC3, 0xC1, 0xC1, 0xC0, 0xBF, 0xBF, 0xAA, 0xAA,
-  0xA6, 0xA4, 0xA4, 0xA4, 0xA6, 0xA8, 0xBE, 0xC1,
-  0xC9, 0xEB, 0xFB, 0xFB, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xEB, 0xC3, 0xC0, 0xAA, 0xA8,
-  0xA6, 0xA6, 0xA6, 0xA9, 0xAA, 0xC0, 0xE8, 0xD0,
-  0xD2, 0x4C, 0x5E, 0x64, 0xD0, 0xD1, 0x5F, 0xD9,
-  0xD5, 0xD1, 0xD0, 0x48, 0x52, 0x5C, 0x64, 0xCD,
-  0x5C, 0xDC, 0xD7, 0xD5, 0x62, 0x3F, 0x4C, 0x53,
-  0xDA, 0xD7, 0xCE, 0x56, 0x40, 0x4B, 0x52, 0x56,
-  0xCE, 0xDF, 0x6A, 0xEB, 0xE9, 0xC9, 0xC3, 0xC0,
-  0xC0, 0xBF, 0xBE, 0xAA, 0xBF, 0xC0, 0xC3, 0xC9,
-  0xEA, 0xF6, 0xEE, 0x58, 0x57, 0x5E, 0xD6, 0xD0,
-  0xD2, 0x61, 0xCB, 0xD6, 0xD6, 0xD4, 0xDF, 0xF3,
-  0xF2, 0xDD, 0xD7, 0xEB, 0xC9, 0xC1, 0xC0, 0xBF,
-  0xAA, 0xAA, 0xAA, 0xBE, 0xC3, 0xF0, 0xD2, 0xD2,
-  0xD2, 0x51, 0x62, 0xCC, 0xD0, 0xCC, 0x61, 0xD3,
-  0xCF, 0xCE, 0xD2, 0x48, 0x5A, 0x61, 0xCC, 0xCE,
-  0x5F, 0xD9, 0xD5, 0xD1, 0x63, 0x44, 0x56, 0x56,
-  0xDC, 0xD9, 0xD4, 0x5E, 0x42, 0x4A, 0x4C, 0x57,
-  0x5D, 0xD8, 0xE0, 0xD8, 0xDC, 0xCB, 0x66, 0xEC,
-  0xE8, 0xC3, 0xC3, 0xC3, 0xC3, 0xC9, 0xE8, 0xEA,
-  0xF6, 0x50, 0x3E, 0x58, 0x57, 0x5A, 0xD6, 0xD4,
-  0xCC, 0x4B, 0x53, 0x5C, 0x64, 0xD1, 0xDF, 0xF3,
-  0xF1, 0xDE, 0xD9, 0xF6, 0xEB, 0xC9, 0xC1, 0xC1,
-  0xC0, 0xC0, 0xC1, 0xC9, 0xF0, 0xD6, 0xCD, 0xD6,
-  0xD3, 0x53, 0xCB, 0xCF, 0xCD, 0x5F, 0x5F, 0xCE,
-  0xCF, 0xCD, 0xD0, 0x47, 0x5F, 0xCB, 0xCE, 0xCD,
-  0x63, 0xD6, 0xD3, 0xD1, 0x63, 0x3F, 0x58, 0x58,
-  0xDB, 0xDC, 0xDA, 0x65, 0x3E, 0x49, 0x49, 0x4D,
-  0x49, 0xDC, 0xDF, 0xE0, 0xDE, 0xD5, 0x47, 0x47,
-  0x46, 0x6B, 0xEB, 0xEA, 0xE9, 0xEA, 0xEB, 0xF6,
-  0xD0, 0x57, 0x57, 0x47, 0x47, 0x5B, 0xD4, 0xD4,
-  0xCD, 0x44, 0x3E, 0x4B, 0x50, 0x4B, 0x51, 0xD5,
-  0xDB, 0xD8, 0xDE, 0x4B, 0xF6, 0xF6, 0xEA, 0xE9,
-  0xE8, 0xEA, 0xEB, 0x67, 0x5E, 0xCC, 0xD6, 0xDC,
-  0xD5, 0x58, 0xCE, 0xCE, 0x62, 0x50, 0xCC, 0xD3,
-  0xD2, 0xCD, 0xCD, 0x4B, 0x64, 0xCE, 0xCE, 0x64,
-  0xCC, 0xD3, 0xD2, 0xD2, 0x61, 0x47, 0x5D, 0x5C,
-  0xDD, 0xDD, 0xD9, 0xD1, 0x4C, 0x47, 0x49, 0x4A,
-  0x4B, 0xD1, 0xD8, 0xE0, 0xDF, 0xDD, 0x5D, 0x4A,
-  0x48, 0x52, 0x51, 0x3F, 0xF6, 0xEC, 0xE0, 0xE0,
-  0xD3, 0x5E, 0x5F, 0x50, 0x4B, 0x50, 0xCB, 0xCE,
-  0x64, 0x45, 0x4C, 0x57, 0x57, 0x58, 0x52, 0xD6,
-  0xD3, 0xDE, 0xDF, 0xD1, 0x3E, 0x4B, 0xF6, 0xF6,
-  0xEC, 0x66, 0x53, 0x43, 0x56, 0xD1, 0xD9, 0xDE,
-  0xD4, 0x5E, 0xCE, 0xCC, 0x5B, 0x2C, 0xD4, 0xD5,
-  0xD2, 0xD0, 0x63, 0x5D, 0xCD, 0xD0, 0xCD, 0x5E,
-  0xD0, 0xCF, 0xCE, 0xD2, 0x5E, 0x50, 0x60, 0x5D,
-  0xDE, 0xDD, 0xDC, 0xD7, 0x5D, 0x45, 0x47, 0x3E,
-  0x4B, 0x5E, 0xDE, 0xDF, 0xE0, 0xD8, 0xCF, 0x3E,
-  0x45, 0x51, 0x58, 0x42, 0xCB, 0xDA, 0xDE, 0xD8,
-  0xD2, 0x61, 0xCC, 0xCF, 0xD6, 0xDA, 0xDA, 0xD5,
-  0xD0, 0x50, 0x44, 0x57, 0x57, 0x58, 0x45, 0xD1,
-  0xD1, 0xD7, 0xDF, 0xDF, 0xD7, 0xCF, 0x64, 0x60,
-  0xCE, 0xCE, 0xCE, 0x63, 0xCF, 0xDA, 0xDE, 0xD9,
-  0xCF, 0x63, 0xCD, 0x63, 0x4D, 0x4B, 0xD6, 0xD5,
-  0xCE, 0xD3, 0x60, 0xCB, 0xD0, 0xD0, 0x65, 0x47,
-  0xD0, 0xCC, 0xCC, 0xD1, 0x59, 0x5D, 0x63, 0x5E,
-  0xDD, 0xDD, 0xDE, 0xDC, 0xCB, 0x40, 0x48, 0x45,
-  0x3E, 0x3E, 0xD9, 0xDF, 0xE0, 0xDF, 0xDA, 0x51,
-  0x4C, 0x48, 0x56, 0x4C, 0x5B, 0xD2, 0xDA, 0xDB,
-  0xCB, 0x5F, 0xD0, 0xCC, 0xDC, 0xF0, 0xF3, 0xE0,
-  0xDD, 0xCC, 0x41, 0x50, 0x57, 0x57, 0x4B, 0x5D,
-  0xD3, 0xD1, 0xDE, 0xDF, 0xDE, 0xD7, 0xD0, 0xD0,
-  0xD5, 0xD6, 0xD6, 0xCE, 0xD7, 0xDC, 0xDA, 0xD5,
-  0x60, 0x63, 0x64, 0x5E, 0x47, 0x61, 0xD5, 0xD2,
-  0xCF, 0xD0, 0x59, 0xCD, 0xD1, 0xCF, 0x61, 0x4D,
-  0xCC, 0xCE, 0xCD, 0xD0, 0x52, 0x61, 0x64, 0x60,
-  0xDA, 0xDE, 0xDE, 0xDD, 0xD1, 0x4B, 0x4A, 0x45,
-  0x3E, 0x41, 0xCD, 0xDE, 0xE0, 0xF1, 0xDE, 0x63,
-  0x4A, 0x4A, 0x4A, 0x4B, 0x50, 0xCB, 0xD4, 0xD7,
-  0x5E, 0x54, 0x62, 0xD3, 0xD4, 0xF0, 0xF3, 0xF3,
-  0xF2, 0xDE, 0x61, 0x40, 0x49, 0x56, 0x4D, 0x3E,
-  0x4B, 0xCE, 0xD9, 0xD8, 0xD9, 0xD5, 0xCF, 0xD2,
-  0xD6, 0xD6, 0xD1, 0xD1, 0xD7, 0xD5, 0xCF, 0xD0,
-  0x54, 0x64, 0x63, 0x56, 0x2C, 0xCB, 0xD1, 0xCC,
-  0xD3, 0xCD, 0x54, 0xCF, 0xD1, 0xCE, 0x5E, 0x5C,
-  0xCE, 0xCE, 0xCE, 0xCB, 0x4B, 0x63, 0xCC, 0x61,
-  0xD4, 0xDC, 0xDE, 0xDE, 0xDA, 0x5D, 0x45, 0x45,
-  0x48, 0x3F, 0x52, 0xD9, 0xD8, 0xDF, 0xDF, 0xD2,
-  0x52, 0x4B, 0x3E, 0x2E, 0x47, 0x60, 0xCF, 0xD3,
-  0x59, 0x48, 0x50, 0x5E, 0xCC, 0xDE, 0xF2, 0xF2,
-  0xF3, 0xF3, 0xDD, 0x5D, 0x3E, 0x48, 0x47, 0x47,
-  0x58, 0xD1, 0xDA, 0xDA, 0xD5, 0xD1, 0xCD, 0xD2,
-  0xD3, 0xCF, 0xD3, 0xD1, 0xCD, 0xD3, 0xD2, 0x5E,
-  0x52, 0x64, 0x60, 0x4B, 0x45, 0x61, 0xCD, 0xD3,
-  0xD3, 0x64, 0x61, 0xD0, 0xD0, 0x64, 0x45, 0x63,
-  0xD0, 0xCE, 0xD0, 0x60, 0x56, 0xCB, 0xCC, 0x62,
-  0xCE, 0xDA, 0xDE, 0xD8, 0xDD, 0xCC, 0x45, 0x49,
-  0x3E, 0x47, 0x42, 0xD1, 0xDC, 0xD8, 0xD8, 0xD3,
-  0x5D, 0x4C, 0x49, 0x3F, 0x47, 0x59, 0xCD, 0xCF,
-  0x59, 0x2E, 0x48, 0x47, 0x52, 0x63, 0xF0, 0xF2,
-  0xF3, 0xF3, 0xF2, 0xDA, 0x52, 0x4B, 0x52, 0x58,
-  0x5E, 0x63, 0xD0, 0xD0, 0xD0, 0xCF, 0xCE, 0xCE,
-  0xCF, 0x65, 0x61, 0xD6, 0xD6, 0xD6, 0xCB, 0x4B,
-  0x61, 0x62, 0x5D, 0x43, 0x4B, 0x61, 0xD0, 0xD4,
-  0xD1, 0x61, 0xCE, 0xD2, 0xCD, 0x5E, 0x4A, 0xCE,
-  0xD0, 0xCC, 0xD0, 0x59, 0x61, 0xCC, 0xCC, 0x62,
-  0xD1, 0xD5, 0xDE, 0xD8, 0xDD, 0xCF, 0x4B, 0x4A,
-  0x45, 0x3E, 0x2D, 0xCB, 0xDC, 0xDE, 0xD8, 0xD5,
-  0x60, 0x54, 0x51, 0x4C, 0x4D, 0x5C, 0xCC, 0xCE,
-  0x5A, 0x2C, 0x50, 0x53, 0x3E, 0x59, 0xD8, 0xF3,
-  0xF2, 0xF3, 0xF3, 0xE0, 0x5E, 0x4A, 0x4C, 0x53,
-  0x5E, 0x63, 0xCC, 0xCC, 0xCC, 0xCD, 0xCF, 0xD3,
-  0x62, 0x53, 0xD6, 0xD6, 0xD6, 0xD6, 0x5B, 0x48,
-  0x64, 0x63, 0x59, 0x44, 0x57, 0x63, 0xD2, 0xD3,
-  0xD0, 0x5E, 0xD0, 0xD1, 0xCB, 0x58, 0x4C, 0xCF,
-  0xCF, 0xCE, 0xCE, 0x57, 0x63, 0xCC, 0xCD, 0x57,
-};
-
-unsigned char linux_logo_bw[] __initdata = {
-  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x3F,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F,
-  0xFE, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xFE, 0x3F, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xFE, 0x7F, 0xFF, 0xC7, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xC3,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF,
-  0xFB, 0xE3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xFD, 0xFF, 0xFF, 0xE1, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xF1,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xFF,
-  0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xF9, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xF9, 0xCF, 0xC3, 0xF8, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x87, 0x81, 0xF9,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xA7,
-  0x99, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xF9, 0xF3, 0xBC, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xF9, 0xE3, 0xBC, 0xF9, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xB0, 0x3C, 0xF9,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xB0,
-  0x19, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xF9, 0xC0, 0x03, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xF9, 0x80, 0x01, 0xF8, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x80, 0x01, 0xF8,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x80,
-  0x01, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xF9, 0xC0, 0x21, 0xD8, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xF9, 0xB1, 0x80, 0xEC, 0xC0, 0x1F,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xF1, 0x90, 0x00, 0xE4,
-  0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xF1, 0x8C,
-  0xC0, 0x7C, 0x04, 0x81, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xE3, 0x80, 0x00, 0x7C, 0x40, 0x11, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xE3, 0x80, 0x00, 0x7F, 0xD2, 0x29,
-  0xFF, 0xFF, 0xFF, 0xFF, 0x87, 0x00, 0x00, 0x3F,
-  0x80, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0x0E, 0x00,
-  0x00, 0x3F, 0x80, 0x19, 0xFF, 0xFF, 0xFF, 0xFF,
-  0x1E, 0x00, 0x00, 0x1F, 0x80, 0x19, 0xFF, 0xFF,
-  0xFF, 0xFE, 0x1C, 0x00, 0x00, 0x1E, 0x80, 0x19,
-  0xFF, 0xFF, 0xFF, 0xFE, 0x3C, 0x00, 0x00, 0x1E,
-  0x80, 0x11, 0xFF, 0xFF, 0xFF, 0xFC, 0x7C, 0x00,
-  0x00, 0x0F, 0x80, 0x11, 0xFF, 0xFF, 0xFF, 0xFC,
-  0xF8, 0x00, 0x00, 0x0E, 0x80, 0x11, 0xFF, 0xFF,
-  0xFF, 0xFC, 0xF8, 0x00, 0x00, 0x06, 0x00, 0x11,
-  0xFF, 0xFF, 0xFF, 0xF8, 0xF8, 0x00, 0x00, 0x06,
-  0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xF9, 0xF0, 0x00,
-  0x00, 0x02, 0x00, 0x09, 0xFF, 0xFF, 0xFF, 0xF1,
-  0xF0, 0x00, 0x00, 0x02, 0x80, 0x10, 0xFF, 0xFF,
-  0xFF, 0xF1, 0xE0, 0x00, 0x00, 0x00, 0x97, 0x10,
-  0xFF, 0xFF, 0xFF, 0xE3, 0xE0, 0x00, 0x00, 0x00,
-  0xDF, 0xF0, 0xFF, 0xFF, 0xFF, 0xE3, 0xC0, 0x00,
-  0x00, 0x00, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xC7,
-  0xC0, 0x00, 0x00, 0x01, 0xFF, 0xF8, 0xFF, 0xFF,
-  0xFF, 0xC7, 0x80, 0x00, 0x00, 0x01, 0xFF, 0xF8,
-  0xFF, 0xFF, 0xFF, 0x8F, 0x80, 0x00, 0x00, 0x01,
-  0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0x8F, 0x80, 0x00,
-  0x00, 0x01, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0x9F,
-  0x80, 0x00, 0x00, 0x01, 0xFF, 0xF8, 0xFF, 0xFF,
-  0xFF, 0x9F, 0x80, 0x00, 0x00, 0x01, 0x80, 0x18,
-  0xFF, 0xFF, 0xFF, 0x9E, 0x80, 0x00, 0x00, 0x03,
-  0xA8, 0x11, 0xFF, 0xFF, 0xFF, 0x9F, 0x80, 0x00,
-  0x00, 0x02, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x99,
-  0x80, 0x00, 0x00, 0x00, 0x00, 0x09, 0xFF, 0xFF,
-  0xFF, 0x00, 0x80, 0x00, 0x00, 0x01, 0xC0, 0x01,
-  0xFF, 0xFF, 0xFE, 0x20, 0x60, 0x00, 0x00, 0x00,
-  0xFF, 0xC3, 0xFF, 0xFF, 0xF8, 0x00, 0x30, 0x00,
-  0x00, 0x00, 0xFF, 0x0F, 0xFF, 0xFF, 0xC0, 0x40,
-  0x38, 0x00, 0x00, 0x00, 0xFE, 0x47, 0xFF, 0xFF,
-  0x81, 0x00, 0x1C, 0x00, 0x00, 0x00, 0xFC, 0x23,
-  0xFF, 0xFF, 0x90, 0x00, 0x1E, 0x00, 0x00, 0x00,
-  0x78, 0x11, 0xFF, 0xFF, 0x80, 0x00, 0x0F, 0x80,
-  0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00,
-  0x07, 0xC0, 0x00, 0x00, 0x00, 0x08, 0xFF, 0xFF,
-  0xC0, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x04,
-  0x7F, 0xFF, 0x80, 0x00, 0x03, 0xC0, 0x00, 0x10,
-  0x00, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x01, 0x80,
-  0x00, 0x30, 0x00, 0x00, 0x0F, 0xFF, 0x80, 0x00,
-  0x00, 0x00, 0x00, 0x70, 0x00, 0x01, 0x4F, 0xFF,
-  0x80, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00,
-  0x0F, 0xFF, 0xC0, 0x00, 0x00, 0x80, 0x03, 0xF0,
-  0x00, 0x00, 0x8F, 0xFF, 0x80, 0x00, 0x00, 0x40,
-  0x0F, 0xF0, 0x00, 0x04, 0x1F, 0xFF, 0x80, 0x00,
-  0x00, 0x7F, 0xFF, 0xF0, 0x00, 0x10, 0x1F, 0xFF,
-  0xC0, 0x00, 0x00, 0x7F, 0xFF, 0xF0, 0x00, 0x40,
-  0xFF, 0xFF, 0x98, 0x00, 0x00, 0xFF, 0xFF, 0xF0,
-  0x00, 0x83, 0xFF, 0xFF, 0x81, 0xE0, 0x01, 0xFF,
-  0xFF, 0xF8, 0x02, 0x07, 0xFF, 0xFF, 0x80, 0x3F,
-  0x07, 0xE0, 0x00, 0x1C, 0x0C, 0x1F, 0xFF, 0xFF,
-  0xF8, 0x03, 0xFF, 0x80, 0x00, 0x1F, 0x78, 0x1F,
-  0xFF, 0xFF, 0xFF, 0x80, 0x7F, 0x00, 0x07, 0x0F,
-  0xF0, 0x7F, 0xFF, 0xFF, 0xFF, 0xFE, 0x0C, 0x07,
-  0xFF, 0x83, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-  0x00, 0x1F, 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x07, 0xFF,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-};
-
-/* Painted by Johnny Stenback <jst@uwasa.fi> */
-
-unsigned char *linux_serial_image __initdata = "\n"
-"         .u$e.\n"
-"       .$$$$$:S\n"
-"       $\"*$/\"*$$\n"
-"       $.`$ . ^F\n"
-"       4k+#+T.$F\n"
-"       4P+++\"$\"$\n"
-"       :R\"+  t$$B\n"
-"    ___#       $$$\n"
-"    |  |       R$$k\n"
-"   dd. | Linux  $!$\n"
-"   ddd |  Sparc $9$F\n"
-" '!!!!!$       !!#!`\n"
-"  !!!!!*     .!!!!!`\n"
-"'!!!!!!!W..e$$!!!!!!`    %s\n"
-" \"~^^~         ^~~^\n"
-"\n";
diff -u --recursive --new-file v2.1.35/linux/drivers/sbus/char/suncons.c linux/drivers/sbus/char/suncons.c
--- v2.1.35/linux/drivers/sbus/char/suncons.c	Mon Apr 14 16:28:13 1997
+++ linux/drivers/sbus/char/suncons.c	Thu Apr 17 13:20:46 1997
@@ -1,4 +1,4 @@
-/* $Id: suncons.c,v 1.58 1997/04/04 00:50:04 davem Exp $
+/* $Id: suncons.c,v 1.61 1997/04/17 02:29:36 miguel Exp $
  *
  * suncons.c: Sun SparcStation console support.
  *
@@ -87,7 +87,7 @@
 #define cmapsz 8192
 
 #include "suncons_font.h"
-#include "linux_logo.h"
+#include <asm/linux_logo.h>
 
 fbinfo_t *fbinfo;
 int fbinfos;
@@ -382,7 +382,7 @@
 
     count = video_num_columns * video_num_lines;
     contents = (unsigned short *) video_mem_base;
-    
+
     for (;count--; contents++)
 	sun_blitc (*contents, (unsigned long) contents);
 }
@@ -434,11 +434,7 @@
 	putconsxy(0, q);
 	ush = (unsigned short *) video_mem_base + video_num_columns * 2 + 20 + 11 * (linux_num_cpus - 1);
 
-#ifdef __sparc_v9__
-	p = "Linux/UltraSPARC version " UTS_RELEASE;
-#else
-	p = "Linux/SPARC version " UTS_RELEASE;
-#endif
+	p = linux_logo_banner;
 	for (; *p; p++, ush++) {
 		*ush = (attr << 8) + *p;
 		sun_blitc (*ush, (unsigned long) ush);
@@ -764,35 +760,15 @@
 }
 
 unsigned int
-get_phys (unsigned int addr)
+get_phys (unsigned long addr)
 {
-	switch (sparc_cpu_model){
-	case sun4c:
-		return sun4c_get_pte (addr) << PAGE_SHIFT;
-	case sun4m:
-		return ((srmmu_get_pte (addr) & 0xffffff00) << 4);
-	case sun4u:
-		/* FIXME: */ return 0;
-	default:
-		panic ("get_phys called for unsupported cpu model\n");
-		return 0;
-	}
+	return __get_phys(addr);
 }
 
 int
-get_iospace (unsigned int addr)
+get_iospace (unsigned long addr)
 {
-	switch (sparc_cpu_model){
-	case sun4c:
-		return -1; /* Don't check iospace on sun4c */
-	case sun4m:
-		return (srmmu_get_pte (addr) >> 28);
-	case sun4u:
-		/* FIXME: */ return 0;
-	default:
-		panic ("get_iospace called for unsupported cpu model\n");
-		return -1;
-	}
+	return __get_iospace(addr);
 }
 
 __initfunc(unsigned long sun_cg_postsetup(fbinfo_t *fb, unsigned long start_mem))
@@ -803,7 +779,7 @@
 
 static char *known_cards [] __initdata = {
 	"cgsix", "cgthree", "cgRDI", "cgthree+", "bwtwo", "SUNW,tcx",
-	"cgfourteen", "SUNW,leo", 0
+	"cgfourteen", "SUNW,leo", "SUNW,ffb", 0
 };
 static char *v0_known_cards [] __initdata = {
 	"cgsix", "cgthree", "cgRDI", "cgthree+", "bwtwo", 0
@@ -848,6 +824,16 @@
 	return n;
 }
 
+__initfunc(static int creator_present (void))
+{
+	int root, n;
+
+	root = prom_getchild (prom_root_node);
+	if ((n = prom_searchsiblings (root, "SUNW,ffb")) == 0)
+		return 0;
+	return n;
+}
+
 __initfunc(static void
 	   sparc_framebuffer_setup(int primary, int con_node,
 				   int type, struct linux_sbus_device *sbdp, 
@@ -941,78 +927,86 @@
 		leo_setup (&fbinfo [n], n, base, io);
 		break;
 #endif
+#ifdef SUN_FB_CREATOR
+	case FBTYPE_CREATOR:
+		creator_setup (&fbinfo [n], n, con_node, base, io);
+		break;
+#endif
 	default:
 		fbinfo [n].type.fb_type = FBTYPE_NOTYPE;
 		return;
 	}
-	if (!n) {
-		con_type = type;
-		con_height = fbinfo [n].type.fb_height;
-		con_width = fbinfo [n].type.fb_width;
-		con_depth = (type == FBTYPE_SUN2BW) ? 1 : 8;
-		for (i = 0; scr_def [i].depth; i++){
-			if ((scr_def [i].resx != con_width) ||
-			    (scr_def [i].resy != con_height))
-				continue;
-			if (scr_def [i].depth != con_depth)
-		        	continue;
-			x_margin = scr_def [i].x_margin;
-			y_margin = scr_def [i].y_margin;
-			chars_per_line = (con_width * con_depth) / 8;
-			skip_bytes = chars_per_line * y_margin + x_margin;
-			ints_per_line = chars_per_line / 4;
-			ints_per_cursor = 14 * ints_per_line;
-			bytes_per_row = CHAR_HEIGHT * chars_per_line;
-			ORIG_VIDEO_COLS = con_width / 8 -
-						2 * x_margin / con_depth;
-			ORIG_VIDEO_LINES = (con_height - 2 * y_margin) / 16;
-			switch (chars_per_line) {
-			case 1280:
-				if (ORIG_VIDEO_COLS == 144)
-					color_fbuf_offset =
-						color_fbuf_offset_1280_144;
-				break;
-			case 1152:
-				if (ORIG_VIDEO_COLS == 128)
-					color_fbuf_offset =
-						color_fbuf_offset_1152_128;
-				break;
-			case 1024:
-				if (ORIG_VIDEO_COLS == 128)
-					color_fbuf_offset =
-						color_fbuf_offset_1024_128;
-				break;
-			case 800:
-				if (ORIG_VIDEO_COLS == 96)
-					color_fbuf_offset =
-						color_fbuf_offset_800_96;
-				break;
-			case 640:
-				if (ORIG_VIDEO_COLS == 80)
-					color_fbuf_offset =
-						color_fbuf_offset_640_80;
-				break;
-			}
-			break;
-		}
-
-		if (!scr_def [i].depth){
-			x_margin = y_margin = 0;
-			prom_printf ("console: unknown video resolution %dx%d,"
-				     " depth %d\n",
-			      	     con_width, con_height, con_depth);
-			prom_halt ();
-		}
 
-		/* P3: I fear this strips 15inch 1024/768 PC-like
-		 * monitors out. */
-		if ((linebytes*8) / con_depth != con_width) {
-			prom_printf("console: unusual video, linebytes=%d, "
-			    	    "width=%d, height=%d depth=%d\n",
-			    	    linebytes, con_width, con_height,
-				    con_depth);
-			prom_halt ();
+	if (n)
+		return;
+	
+	/* Code below here is just executed for the first frame buffer */
+	con_type = type;
+	con_height = fbinfo [n].type.fb_height;
+	con_width = fbinfo [n].type.fb_width;
+	con_depth = (type == FBTYPE_SUN2BW) ? 1 : 8;
+	for (i = 0; scr_def [i].depth; i++){
+		if ((scr_def [i].resx != con_width) ||
+		    (scr_def [i].resy != con_height))
+			continue;
+		if (scr_def [i].depth != con_depth)
+			continue;
+		x_margin = scr_def [i].x_margin;
+		y_margin = scr_def [i].y_margin;
+		chars_per_line = (con_width * con_depth) / 8;
+		skip_bytes = chars_per_line * y_margin + x_margin;
+		ints_per_line = chars_per_line / 4;
+		ints_per_cursor = 14 * ints_per_line;
+		bytes_per_row = CHAR_HEIGHT * chars_per_line;
+		ORIG_VIDEO_COLS = con_width / 8 -
+			2 * x_margin / con_depth;
+		ORIG_VIDEO_LINES = (con_height - 2 * y_margin) / 16;
+		switch (chars_per_line) {
+		case 1280:
+			if (ORIG_VIDEO_COLS == 144)
+				color_fbuf_offset =
+					color_fbuf_offset_1280_144;
+			break;
+		case 1152:
+			if (ORIG_VIDEO_COLS == 128)
+				color_fbuf_offset =
+					color_fbuf_offset_1152_128;
+			break;
+		case 1024:
+			if (ORIG_VIDEO_COLS == 128)
+				color_fbuf_offset =
+					color_fbuf_offset_1024_128;
+			break;
+		case 800:
+			if (ORIG_VIDEO_COLS == 96)
+				color_fbuf_offset =
+					color_fbuf_offset_800_96;
+			break;
+		case 640:
+			if (ORIG_VIDEO_COLS == 80)
+				color_fbuf_offset =
+					color_fbuf_offset_640_80;
+			break;
 		}
+		break;
+	}
+	
+	if (!scr_def [i].depth){
+		x_margin = y_margin = 0;
+		prom_printf ("console: unknown video resolution %dx%d,"
+			     " depth %d\n",
+			     con_width, con_height, con_depth);
+		prom_halt ();
+	}
+	
+	/* P3: I fear this strips 15inch 1024/768 PC-like
+	 * monitors out. */
+	if ((linebytes*8) / con_depth != con_width) {
+		prom_printf("console: unusual video, linebytes=%d, "
+			    "width=%d, height=%d depth=%d\n",
+			    linebytes, con_width, con_height,
+			    con_depth);
+		prom_halt ();
 	}
 }
 
@@ -1022,9 +1016,9 @@
 	char prop[16];
 	struct linux_sbus_device *sbdp, *sbdprom;
 	struct linux_sbus *sbus;
-	int cg14 = 0;
+	int creator = 0, cg14 = 0;
 	char prom_name[40];	
-	int type;
+	int type, card_found = 0;
 	unsigned long con_base;
 	u32 tmp;
 	u32 prom_console_node = 0;
@@ -1109,18 +1103,22 @@
 				break;
 			}
 		}
-		if (!sbdprom) /* I'm just wondering if this if shouldn't be deleted.
-				 Is /obio/cgfourteen present only if /sbus/cgfourteen
-				 is not? If so, then the test here should be deleted.
-				 Otherwise, this comment should be deleted. */
-			cg14 = cg14_present ();
-		if (!sbdprom && !cg14) {
+		if (sbdprom)
+		    card_found = 1;
+		if (!card_found)
+		    card_found = cg14 = cg14_present ();
+		if (!card_found){
+			prom_printf ("Searching for a creator\n");
+			card_found = creator = creator_present ();
+		}
+		if (!card_found){
 			prom_printf ("Could not find a known video card on this machine\n");
 			prom_halt ();
 		}
 		
 		for_all_sbusdev(sbdp, sbus) {
-			if (!known_card (sbdp->prom_name, known_cards)) continue;
+			if (!known_card (sbdp->prom_name, known_cards))
+				continue;
 			con_node = sbdp->prom_node;
 			prom_apply_sbus_ranges (sbdp->my_bus, &sbdp->reg_addrs [0],
 						sbdp->num_registers, sbdp);
@@ -1170,6 +1168,11 @@
 			sparc_framebuffer_setup (!sbdprom, cg14, FBTYPE_MDICOLOR, 
 						 0, 0, 0, prom_console_node == cg14,
 						 prom_searchsiblings (prom_getchild (prom_root_node), "obio"));
+		}
+		if (creator){
+			sparc_framebuffer_setup (!sbdprom, creator, FBTYPE_CREATOR,
+						 0, 0, 0, prom_console_node == creator,
+						 prom_getchild (prom_root_node));
 		}
 		break;
 	default:
diff -u --recursive --new-file v2.1.35/linux/drivers/sbus/char/sunkbd.c linux/drivers/sbus/char/sunkbd.c
--- v2.1.35/linux/drivers/sbus/char/sunkbd.c	Mon Apr 14 16:28:13 1997
+++ linux/drivers/sbus/char/sunkbd.c	Tue Apr 22 22:39:21 1997
@@ -1149,7 +1149,7 @@
 
 extern void (*kd_mksound)(unsigned int hz, unsigned int ticks);
 
-int kbd_init(void)
+__initfunc(int kbd_init(void))
 {
 	int i, opt_node;
 	struct kbd_struct kbd0;
diff -u --recursive --new-file v2.1.35/linux/drivers/sbus/char/sunserial.c linux/drivers/sbus/char/sunserial.c
--- v2.1.35/linux/drivers/sbus/char/sunserial.c	Mon Apr 14 16:28:14 1997
+++ linux/drivers/sbus/char/sunserial.c	Tue Apr 15 21:47:23 1997
@@ -1,4 +1,4 @@
-/* $Id: sunserial.c,v 1.37 1997/04/12 23:33:14 ecd Exp $
+/* $Id: sunserial.c,v 1.38 1997/04/14 17:05:00 jj Exp $
  * serial.c: Serial port driver for the Sparc.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -1857,7 +1857,7 @@
 
 static void show_serial_version(void)
 {
-	char *revision = "$Revision: 1.37 $";
+	char *revision = "$Revision: 1.38 $";
 	char *version, *p;
 
 	version = strchr(revision, ' ');
@@ -1991,7 +1991,7 @@
 	if(!vaddr[0])
 		panic("get_zs whee no serial chip mappable");
 
-	return (struct sun_zslayout *) vaddr[0];
+	return (struct sun_zslayout *)(unsigned long) vaddr[0];
 }
 
 static inline void
@@ -2541,7 +2541,7 @@
 
 	for (info = zs_chain, i=0; info; info = info->zs_next, i++) {
 		info->magic = SERIAL_MAGIC;
-		info->port = (int) info->zs_channel;
+		info->port = (long) info->zs_channel;
 		info->line = i;
 		info->tty = 0;
 		info->irq = zilog_irq;
diff -u --recursive --new-file v2.1.35/linux/drivers/sbus/char/tcx.c linux/drivers/sbus/char/tcx.c
--- v2.1.35/linux/drivers/sbus/char/tcx.c	Mon Apr 14 16:28:14 1997
+++ linux/drivers/sbus/char/tcx.c	Tue Apr 15 21:47:23 1997
@@ -1,4 +1,4 @@
-/* $Id: tcx.c,v 1.11 1997/04/10 03:02:43 davem Exp $
+/* $Id: tcx.c,v 1.12 1997/04/14 17:04:51 jj Exp $
  * tcx.c: SUNW,tcx 24/8bit frame buffer driver
  *
  * Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -126,24 +126,24 @@
 		switch (vma->vm_offset+page){
 		case TCX_RAM8BIT:
 			map_size = fb->type.fb_size;
-			map_offset = get_phys ((uint) fb->base);
+			map_offset = get_phys ((unsigned long) fb->base);
 			break;
 		case TCX_TEC:
 			map_size = PAGE_SIZE;
-			map_offset = get_phys ((uint)fb->info.tcx.tec);
+			map_offset = get_phys ((unsigned long)fb->info.tcx.tec);
 			break;
 		case TCX_BTREGS:
 			map_size = PAGE_SIZE;
-			map_offset = get_phys ((uint)fb->info.tcx.bt);
+			map_offset = get_phys ((unsigned long)fb->info.tcx.bt);
 			break;
 		case TCX_THC:
 			map_size = PAGE_SIZE;
-			map_offset = get_phys ((uint)fb->info.tcx.thc);
+			map_offset = get_phys ((unsigned long)fb->info.tcx.thc);
 			break;
 		case TCX_CONTROLPLANE:
 			if (fb->info.tcx.tcx_cplane) {
 				map_size = fb->info.tcx.tcx_sizes [TCX_CONTROLPLANE_OFFSET];
-				map_offset = get_phys ((uint)fb->info.tcx.tcx_cplane);
+				map_offset = get_phys ((unsigned long)fb->info.tcx.tcx_cplane);
 			} else
 				map_size = 0;
 			break;
@@ -272,12 +272,12 @@
 	tcx->bt->control |= 0x03 << 24;
 }
 
-__initfunc(void tcx_setup (fbinfo_t *fb, int slot, int node, unsigned long tcx, struct linux_sbus_device *sbdp))
+__initfunc(void tcx_setup (fbinfo_t *fb, int slot, int node, u32 tcx, struct linux_sbus_device *sbdp))
 {
 	struct tcx_info *tcxinfo;
 	int i;
 
-	printk ("tcx%d at 0x%8.8x ", slot, (uint) tcx);
+	printk ("tcx%d at 0x%8.8x ", slot, tcx);
 	
 	/* Fill in parameters we left out */
 	fb->type.fb_cmsize = 256;
diff -u --recursive --new-file v2.1.35/linux/drivers/sbus/char/weitek.c linux/drivers/sbus/char/weitek.c
--- v2.1.35/linux/drivers/sbus/char/weitek.c	Mon Apr 14 16:28:15 1997
+++ linux/drivers/sbus/char/weitek.c	Tue Apr 15 21:47:23 1997
@@ -1,4 +1,4 @@
-/* $Id: weitek.c,v 1.8 1997/03/24 17:44:26 jj Exp $
+/* $Id: weitek.c,v 1.9 1997/04/14 17:04:57 jj Exp $
  * weitek.c: Tadpole P9100/P9000 console driver
  *
  * Copyright (C) 1996 David Redman (djhr@tadpole.co.uk)
@@ -54,13 +54,13 @@
 		switch (vma->vm_offset+page){
 		case WEITEK_VRAM_OFFSET:
 			map_size = size-page;
-			map_offset = get_phys ((uint) fb->base);
+			map_offset = get_phys ((unsigned long) fb->base);
 			if (map_size > fb->type.fb_size)
 				map_size = fb->type.fb_size;
 			break;
 		case WEITEK_GX_REG_OFFSET:
 			map_size = size-page;
-			map_offset = get_phys ((uint) fb->base);
+			map_offset = get_phys ((unsigned long) fb->base);
 			if (map_size > fb->type.fb_size)
 				map_size = fb->type.fb_size;
 			break;
@@ -95,11 +95,11 @@
 }
 #endif
 
-__initfunc(void weitek_setup(fbinfo_t *fb, int slot, unsigned long addr, int io))
+__initfunc(void weitek_setup(fbinfo_t *fb, int slot, u32 addr, int io))
 {
 	extern struct screen_info screen_info;
 	
-	printk ("weitek%d at 0x%8.8x\n", slot, (uint)addr);
+	printk ("weitek%d at 0x%8.8x\n", slot, addr);
 	
 	/* Fill in parameters we left out */
 	fb->type.fb_type	= FBTYPE_NOTSUN1;
diff -u --recursive --new-file v2.1.35/linux/drivers/sbus/sbus.c linux/drivers/sbus/sbus.c
--- v2.1.35/linux/drivers/sbus/sbus.c	Mon Apr 14 16:28:15 1997
+++ linux/drivers/sbus/sbus.c	Tue Apr 15 21:47:23 1997
@@ -74,10 +74,10 @@
 		sbus_dev->slot = sbus_dev->reg_addrs[0].which_io;
 		sbus_dev->offset = base;
 		sbus_dev->reg_addrs[0].phys_addr = 
-			(char *) sbus_devaddr(sbus_dev->slot, base);
+			sbus_devaddr(sbus_dev->slot, base);
 		for(grrr=1; grrr<sbus_dev->num_registers; grrr++) {
 			base = (unsigned long) sbus_dev->reg_addrs[grrr].phys_addr;
-			sbus_dev->reg_addrs[grrr].phys_addr = (char *) 
+			sbus_dev->reg_addrs[grrr].phys_addr =
 				sbus_devaddr(sbus_dev->slot, base);
 		}
 		/* That surely sucked */
diff -u --recursive --new-file v2.1.35/linux/drivers/scsi/53c7,8xx.c linux/drivers/scsi/53c7,8xx.c
--- v2.1.35/linux/drivers/scsi/53c7,8xx.c	Sun Oct  6 22:55:47 1996
+++ linux/drivers/scsi/53c7,8xx.c	Tue Apr 22 22:42:50 1997
@@ -253,6 +253,7 @@
 #include <linux/ioport.h>
 #include <linux/time.h>
 #include <linux/blk.h>
+#include <linux/init.h>
 #undef current
 
 #include "scsi.h"
@@ -877,7 +878,7 @@
  * Returns : 0 on success, -1 on failure.
  */
 
-static int 
+static inline int 
 NCR53c7x0_init (struct Scsi_Host *host) {
     NCR53c7x0_local_declare();
     int i, ccf, expected_ccf;
@@ -1187,10 +1188,10 @@
  *
  */
 
-static int 
+__initfunc(static int 
 normal_init (Scsi_Host_Template *tpnt, int board, int chip, 
     u32 base, int io_port, int irq, int dma, int pci_valid, 
-    unsigned char pci_bus, unsigned char pci_device_fn, long long options) {
+    unsigned char pci_bus, unsigned char pci_device_fn, long long options)) {
     struct Scsi_Host *instance;
     struct NCR53c7x0_hostdata *hostdata;
     char chip_str[80];
@@ -1400,9 +1401,9 @@
  *
  */
 
-static int 
+__initfunc(static int 
 ncr_pci_init (Scsi_Host_Template *tpnt, int board, int chip, 
-    unsigned char bus, unsigned char device_fn, long long options) {
+    unsigned char bus, unsigned char device_fn, long long options)) {
     unsigned short vendor_id, device_id, command;
 #ifdef LINUX_1_2
     unsigned long
@@ -1539,8 +1540,8 @@
  *
  */
 
-int 
-NCR53c7xx_detect(Scsi_Host_Template *tpnt) {
+__initfunc(int 
+NCR53c7xx_detect(Scsi_Host_Template *tpnt)) {
     int i;
     int current_override;
     int count;			/* Number of boards detected */
diff -u --recursive --new-file v2.1.35/linux/drivers/scsi/AM53C974.c linux/drivers/scsi/AM53C974.c
--- v2.1.35/linux/drivers/scsi/AM53C974.c	Mon Apr  7 11:35:29 1997
+++ linux/drivers/scsi/AM53C974.c	Tue Apr 22 22:42:50 1997
@@ -7,6 +7,7 @@
 #include <linux/pci.h>
 #include <linux/string.h>
 #include <linux/blk.h>
+#include <linux/init.h>
 
 #include <asm/io.h>
 #include <asm/system.h>
@@ -461,8 +462,8 @@
 #endif /* AM53C974_DEBUG */
 static void AM53C974_print(struct Scsi_Host *instance);
 static void AM53C974_keywait(void);
-static int AM53C974_bios_detect(Scsi_Host_Template *tpnt);
-static int AM53C974_nobios_detect(Scsi_Host_Template *tpnt);
+static __inline__ int AM53C974_bios_detect(Scsi_Host_Template *tpnt);
+static __inline__ int AM53C974_nobios_detect(Scsi_Host_Template *tpnt);
 static int AM53C974_init(Scsi_Host_Template *tpnt, pci_config_t pci_config);
 static void AM53C974_config_after_reset(struct Scsi_Host *instance);
 static __inline__ void initialize_SCp(Scsi_Cmnd *cmd);
@@ -739,7 +740,7 @@
 * 
 * Returns : number of host adapters detected
 **************************************************************************/
-int AM53C974_bios_detect(Scsi_Host_Template *tpnt)
+static __inline__ int AM53C974_bios_detect(Scsi_Host_Template *tpnt)
 {
 int count = 0;        /* number of boards detected */
 int pci_index;
@@ -804,7 +805,7 @@
 *
 * Origin: Robin Cutshaw (robin@xfree86.org)
 **************************************************************************/
-int AM53C974_nobios_detect(Scsi_Host_Template *tpnt)
+static __inline__ int AM53C974_nobios_detect(Scsi_Host_Template *tpnt)
 {
 int          count = 0;		/* number of boards detected */
 pci_config_t pci_config;
@@ -902,7 +903,7 @@
 * 
 * Returns : number of host adapters detected
 **************************************************************************/
-int AM53C974_detect(Scsi_Host_Template *tpnt)
+__initfunc(int AM53C974_detect(Scsi_Host_Template *tpnt))
 {
 int count;        /* number of boards detected */
 
@@ -931,7 +932,7 @@
 *       set up by the BIOS (as reflected by contents of register CNTLREG1).
 *       This is the only BIOS assistance we need.
 **************************************************************************/
-static int AM53C974_init(Scsi_Host_Template *tpnt, pci_config_t pci_config)
+__initfunc(static int AM53C974_init(Scsi_Host_Template *tpnt, pci_config_t pci_config))
 {
 AM53C974_local_declare();
 int                      i, j;
diff -u --recursive --new-file v2.1.35/linux/drivers/scsi/BusLogic.c linux/drivers/scsi/BusLogic.c
--- v2.1.35/linux/drivers/scsi/BusLogic.c	Fri Apr  4 08:52:23 1997
+++ linux/drivers/scsi/BusLogic.c	Tue Apr 22 22:42:50 1997
@@ -43,6 +43,7 @@
 #include <linux/stat.h>
 #include <linux/pci.h>
 #include <linux/bios32.h>
+#include <linux/init.h>
 #include <asm/dma.h>
 #include <asm/io.h>
 #include <asm/system.h>
@@ -222,7 +223,8 @@
   Host Adapter.
 */
 
-static boolean BusLogic_CreateMailboxes(BusLogic_HostAdapter_T *HostAdapter)
+__initfunc(static boolean
+BusLogic_CreateMailboxes(BusLogic_HostAdapter_T *HostAdapter))
 {
   /*
     FlashPoint Host Adapters do not use Outgoing and Incoming Mailboxes.
@@ -304,7 +306,8 @@
   BusLogic_CreateInitialCCBs allocates the initial CCBs for Host Adapter.
 */
 
-static boolean BusLogic_CreateInitialCCBs(BusLogic_HostAdapter_T *HostAdapter)
+__initfunc(static boolean
+BusLogic_CreateInitialCCBs(BusLogic_HostAdapter_T *HostAdapter))
 {
   int Allocated;
   for (Allocated = 0; Allocated < HostAdapter->InitialCCBs; Allocated++)
@@ -417,8 +420,8 @@
   structure for Host Adapter.
 */
 
-static boolean BusLogic_CreateTargetDeviceStatistics(BusLogic_HostAdapter_T
-						     *HostAdapter)
+__initfunc(static boolean
+BusLogic_CreateTargetDeviceStatistics(BusLogic_HostAdapter_T *HostAdapter))
 {
   HostAdapter->TargetDeviceStatistics =
     (BusLogic_TargetDeviceStatistics_T *)
@@ -708,7 +711,7 @@
   only from the list of standard BusLogic MultiMaster ISA I/O Addresses.
 */
 
-static void BusLogic_InitializeProbeInfoListISA(void)
+static inline void BusLogic_InitializeProbeInfoListISA(void)
 {
   int StandardAddressIndex;
   /*
@@ -746,8 +749,9 @@
   of increasing PCI Bus and Device Number.
 */
 
-static void BusLogic_SortProbeInfo(BusLogic_ProbeInfo_T *ProbeInfoList,
-				   int ProbeInfoCount)
+__initfunc(static void
+BusLogic_SortProbeInfo(BusLogic_ProbeInfo_T *ProbeInfoList,
+		       int ProbeInfoCount))
 {
   int LastInterchange = ProbeInfoCount-1, Bound, j;
   while (LastInterchange > 0)
@@ -781,7 +785,7 @@
   I/O Addresses.  It returns the number of PCI MultiMaster Host Adapters found.
 */
 
-static int BusLogic_InitializeMultiMasterProbeInfo(void)
+__initfunc(static int BusLogic_InitializeMultiMasterProbeInfo(void))
 {
   boolean StandardAddressSeen[BusLogic_ISA_StandardAddressesCount];
   BusLogic_ProbeInfo_T *PrimaryProbeInfo =
@@ -1012,7 +1016,7 @@
   number of FlashPoint Host Adapters found.
 */
 
-static int BusLogic_InitializeFlashPointProbeInfo(void)
+__initfunc(static int BusLogic_InitializeFlashPointProbeInfo(void))
 {
   int FlashPointIndex = BusLogic_ProbeInfoCount, FlashPointCount = 0;
   unsigned char Bus, DeviceFunction, IRQ_Channel;
@@ -1119,7 +1123,7 @@
   particular probe order.
 */
 
-static void BusLogic_InitializeProbeInfoList(void)
+static inline void BusLogic_InitializeProbeInfoList(void)
 {
   /*
     If BusLogic_Setup has provided an I/O Address probe list, do not override
@@ -1228,7 +1232,8 @@
   BusLogic_ProbeHostAdapter probes for a BusLogic Host Adapter.
 */
 
-static boolean BusLogic_ProbeHostAdapter(BusLogic_HostAdapter_T *HostAdapter)
+__initfunc(static boolean
+BusLogic_ProbeHostAdapter(BusLogic_HostAdapter_T *HostAdapter))
 {
   BusLogic_StatusRegister_T StatusRegister;
   BusLogic_InterruptRegister_T InterruptRegister;
@@ -1422,7 +1427,8 @@
   Host Adapter.  It also determines the IRQ Channel for non-PCI Host Adapters.
 */
 
-static boolean BusLogic_CheckHostAdapter(BusLogic_HostAdapter_T *HostAdapter)
+__initfunc(static boolean
+BusLogic_CheckHostAdapter(BusLogic_HostAdapter_T *HostAdapter))
 {
   BusLogic_Configuration_T Configuration;
   BusLogic_ExtendedSetupInformation_T ExtendedSetupInformation;
@@ -1485,8 +1491,8 @@
   from Host Adapter and initializes the Host Adapter structure.
 */
 
-static boolean BusLogic_ReadHostAdapterConfiguration(BusLogic_HostAdapter_T
-						     *HostAdapter)
+__initfunc(static boolean
+BusLogic_ReadHostAdapterConfiguration(BusLogic_HostAdapter_T *HostAdapter))
 {
   BusLogic_BoardID_T BoardID;
   BusLogic_Configuration_T Configuration;
@@ -1999,8 +2005,8 @@
   Host Adapter.
 */
 
-static boolean BusLogic_ReportHostAdapterConfiguration(BusLogic_HostAdapter_T
-						       *HostAdapter)
+__initfunc(static boolean
+BusLogic_ReportHostAdapterConfiguration(BusLogic_HostAdapter_T *HostAdapter))
 {
   unsigned short AllTargetsMask = (1 << HostAdapter->MaxTargetDevices) - 1;
   unsigned short SynchronousPermitted, FastPermitted;
@@ -2225,7 +2231,8 @@
   Host Adapter.
 */
 
-static boolean BusLogic_AcquireResources(BusLogic_HostAdapter_T *HostAdapter)
+__initfunc(static boolean
+BusLogic_AcquireResources(BusLogic_HostAdapter_T *HostAdapter))
 {
   BusLogic_HostAdapter_T *FirstHostAdapter =
     BusLogic_RegisteredHostAdapters[HostAdapter->IRQ_Channel];
@@ -2311,7 +2318,8 @@
   interrupts do not get through as a result.
 */
 
-static boolean BusLogic_TestInterrupts(BusLogic_HostAdapter_T *HostAdapter)
+__initfunc(static boolean
+BusLogic_TestInterrupts(BusLogic_HostAdapter_T *HostAdapter))
 {
   unsigned int InitialInterruptCount, FinalInterruptCount;
   int TestCount = 5, i;
@@ -2600,9 +2608,10 @@
   through explicit acquisition and release of the Host Adapter's Lock.
 */
 
-static void BusLogic_InitializeHostStructure(BusLogic_HostAdapter_T
-					       *HostAdapter,
-					     SCSI_Host_T *Host)
+__initfunc(static void
+BusLogic_InitializeHostStructure(BusLogic_HostAdapter_T
+				 *HostAdapter,
+				 SCSI_Host_T *Host))
 {
   Host->max_id = HostAdapter->MaxTargetDevices;
   Host->max_lun = HostAdapter->MaxLogicalUnits;
@@ -2673,7 +2682,7 @@
   registered.
 */
 
-int BusLogic_DetectHostAdapter(SCSI_Host_Template_T *HostTemplate)
+__initfunc(int BusLogic_DetectHostAdapter(SCSI_Host_Template_T *HostTemplate))
 {
   int BusLogicHostAdapterCount = 0, CommandLineEntryIndex = 0, ProbeIndex;
   char *MessageBuffer = NULL;
diff -u --recursive --new-file v2.1.35/linux/drivers/scsi/NCR5380.c linux/drivers/scsi/NCR5380.c
--- v2.1.35/linux/drivers/scsi/NCR5380.c	Tue Oct 29 06:21:11 1996
+++ linux/drivers/scsi/NCR5380.c	Tue Apr 22 22:42:51 1997
@@ -596,7 +596,7 @@
 }
 #endif /* def USLEEP */
 
-static void NCR5380_all_init (void) {
+static inline void NCR5380_all_init (void) {
     static int done = 0;
     if (!done) {
 #if (NDEBUG & NDEBUG_INIT)
@@ -625,12 +625,12 @@
  */
 
 
-static int probe_irq;
-static void probe_intr (int irq, void *dev_id, struct pt_regs * regs) {
+static int probe_irq __initdata;
+__initfunc(static void probe_intr (int irq, void *dev_id, struct pt_regs * regs)) {
     probe_irq = irq;
 };
 
-static int NCR5380_probe_irq (struct Scsi_Host *instance, int possible) {
+__initfunc(static int NCR5380_probe_irq (struct Scsi_Host *instance, int possible)) {
     NCR5380_local_declare();
     struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *)
 	 instance->hostdata;
@@ -685,7 +685,7 @@
  * Inputs : instance, pointer to this instance.  Unused.
  */
 
-static void NCR5380_print_options (struct Scsi_Host *instance) {
+__initfunc(static void NCR5380_print_options (struct Scsi_Host *instance)) {
     printk(" generic options"
 #ifdef AUTOPROBE_IRQ
     " AUTOPROBE_IRQ"
@@ -900,7 +900,7 @@
  * 
  */
 
-static void NCR5380_init (struct Scsi_Host *instance, int flags) {
+__initfunc(static void NCR5380_init (struct Scsi_Host *instance, int flags)) {
     NCR5380_local_declare();
     int i, pass;
     unsigned long timeout;
diff -u --recursive --new-file v2.1.35/linux/drivers/scsi/NCR53c406a.c linux/drivers/scsi/NCR53c406a.c
--- v2.1.35/linux/drivers/scsi/NCR53c406a.c	Fri Dec 27 02:03:23 1996
+++ linux/drivers/scsi/NCR53c406a.c	Tue Apr 22 22:42:51 1997
@@ -45,6 +45,7 @@
 #include <linux/interrupt.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
+#include <linux/init.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <asm/bitops.h>
@@ -238,7 +239,7 @@
     char *signature;
     int  sig_offset;
     int  sig_length;
-} signatures[] = {
+} signatures[] __initdata = {
     /*          1         2         3         4         5         6 */
     /* 123456789012345678901234567890123456789012345678901234567890 */
     { "Copyright (C) Acculogic, Inc.\r\n2.8M Diskette Extension Bios ver 4.04.03 03/01/1993", 61, 82 },
@@ -458,8 +459,8 @@
 }
 #endif USE_PIO
 
-int 
-NCR53c406a_detect(Scsi_Host_Template * tpnt){
+__initfunc(int 
+NCR53c406a_detect(Scsi_Host_Template * tpnt)){
     struct Scsi_Host *shpnt;
 #ifndef PORT_BASE
     int i;
@@ -590,7 +591,7 @@
 }
 
 /* called from init/main.c */
-void NCR53c406a_setup(char *str, int *ints)
+__initfunc(void NCR53c406a_setup(char *str, int *ints))
 {
     static size_t setup_idx = 0;
     size_t i;
@@ -1011,7 +1012,7 @@
     outb(SYNC_MODE, SYNCOFF);   /* synchronous mode */  
 }
 
-void calc_port_addr()
+__initfunc(void calc_port_addr())
 {
     /* Control Register Set 0 */
     TC_LSB		= (port_base+0x00);
diff -u --recursive --new-file v2.1.35/linux/drivers/scsi/a2091.c linux/drivers/scsi/a2091.c
--- v2.1.35/linux/drivers/scsi/a2091.c	Fri Dec 20 01:20:01 1996
+++ linux/drivers/scsi/a2091.c	Thu Apr 17 13:20:46 1997
@@ -9,7 +9,7 @@
 #include <asm/pgtable.h>
 #include <asm/amigaints.h>
 #include <asm/amigahw.h>
-#include <asm/zorro.h>
+#include <linux/zorro.h>
 #include <asm/irq.h>
 
 #include "scsi.h"
@@ -211,7 +211,7 @@
 	address = cd->cd_BoardAddr;
 	instance = scsi_register (tpnt, sizeof (struct WD33C93_hostdata));
 	instance->base = (unsigned char *)ZTWO_VADDR(address);
-	instance->irq = IRQ_AMIGA_PORTS & ~IRQ_MACHSPEC;
+	instance->irq = IRQ_AMIGA_PORTS;
 	instance->unique_id = key;
 	DMA(instance)->DAWR = DAWR_A2091;
 	wd33c93_init(instance, (wd33c93_regs *)&(DMA(instance)->SASR),
diff -u --recursive --new-file v2.1.35/linux/drivers/scsi/a3000.c linux/drivers/scsi/a3000.c
--- v2.1.35/linux/drivers/scsi/a3000.c	Fri Dec 20 01:20:02 1996
+++ linux/drivers/scsi/a3000.c	Thu Apr 17 13:20:46 1997
@@ -181,7 +181,7 @@
 
     a3000_host = scsi_register (tpnt, sizeof(struct WD33C93_hostdata));
     a3000_host->base = (unsigned char *)ZTWO_VADDR(0xDD0000);
-    a3000_host->irq = IRQ_AMIGA_PORTS & ~IRQ_MACHSPEC;
+    a3000_host->irq = IRQ_AMIGA_PORTS;
     DMA(a3000_host)->DAWR = DAWR_A3000;
     wd33c93_init(a3000_host, (wd33c93_regs *)&(DMA(a3000_host)->SASR),
 		 dma_setup, dma_stop, WD33C93_FS_12_15);
diff -u --recursive --new-file v2.1.35/linux/drivers/scsi/advansys.c linux/drivers/scsi/advansys.c
--- v2.1.35/linux/drivers/scsi/advansys.c	Thu Nov 14 16:45:57 1996
+++ linux/drivers/scsi/advansys.c	Tue Apr 22 22:42:51 1997
@@ -542,6 +542,7 @@
 #include <linux/malloc.h>
 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
 #include <linux/proc_fs.h>
+#include <linux/init.h>
 #endif /* version >= v1.3.0 */
 #include <asm/io.h>
 #include <asm/system.h>
@@ -2953,8 +2954,8 @@
  * it must not call SCSI mid-level functions including scsi_malloc()
  * and scsi_free().
  */
-int
-advansys_detect(Scsi_Host_Template *tpnt)
+__initfunc(int
+advansys_detect(Scsi_Host_Template *tpnt))
 {
 	static int			detect_called = ASC_FALSE;
 	int					iop;
@@ -5022,8 +5023,8 @@
 /*
  * Search for an AdvanSys PCI device in the PCI configuration space.
  */
-STATIC int
-asc_srch_pci_dev(PCI_DEVICE *pciDevice)
+__initfunc(STATIC int
+asc_srch_pci_dev(PCI_DEVICE *pciDevice))
 {
 	int ret;
 
@@ -5059,8 +5060,8 @@
 /*
  * Determine the access method to be used for 'pciDevice'.
  */
-STATIC uchar
-asc_scan_method(void)
+__initfunc(STATIC uchar
+asc_scan_method(void))
 {
 	ushort data;
 	PCI_DATA pciData;
@@ -5089,8 +5090,8 @@
  *
  * Return PCI_DEVICE_FOUND if found, otherwise return PCI_DEVICE_NOT_FOUND.
  */
-STATIC int
-asc_pci_find_dev(PCI_DEVICE *pciDevice)
+__initfunc(STATIC int
+asc_pci_find_dev(PCI_DEVICE *pciDevice))
 {
 	PCI_DATA pciData;
 	ushort vendorid, deviceid;
@@ -5138,8 +5139,8 @@
 /*
  * Read PCI configuration data into 'pciConfig'.
  */
-STATIC void
-asc_get_pci_cfg(PCI_DEVICE *pciDevice, PCI_CONFIG_SPACE *pciConfig)
+__initfunc(STATIC void
+asc_get_pci_cfg(PCI_DEVICE *pciDevice, PCI_CONFIG_SPACE *pciConfig))
 {
 	PCI_DATA pciData;
 	uchar counter;
@@ -5168,8 +5169,8 @@
  *
  * The configuration mechanism is checked for the correct access method.
  */
-STATIC ushort
-asc_get_cfg_word(PCI_DATA *pciData)
+__initfunc(STATIC ushort
+asc_get_cfg_word(PCI_DATA *pciData))
 {
 	ushort	tmp;
 	ulong	address;
@@ -5249,8 +5250,8 @@
  *
  * The configuration mechanism is checked for the correct access method.
  */
-STATIC uchar
-asc_get_cfg_byte(PCI_DATA *pciData)
+__initfunc(STATIC uchar
+asc_get_cfg_byte(PCI_DATA *pciData))
 {
 	uchar tmp;
 	ulong address;
@@ -5327,8 +5328,8 @@
 /*
  * Write a byte to the PCI configuration space.
  */
-void
-asc_put_cfg_byte(PCI_DATA *pciData, uchar byte_data)
+__initfunc(void
+asc_put_cfg_byte(PCI_DATA *pciData, uchar byte_data))
 {
 	ulong tmpl;
 	ulong address;
@@ -6375,10 +6376,10 @@
 /*
  * Read a PCI configuration byte.
  */
-uchar
+__initfunc(uchar
 DvcReadPCIConfigByte( 
         ASC_DVC_VAR asc_ptr_type *asc_dvc, 
-        ushort offset )
+        ushort offset ))
 {
     PCI_DATA	pciData;
 
@@ -6393,11 +6394,11 @@
 /*
  * Write a PCI configuration byte.
  */
-void
+__initfunc(void
 DvcWritePCIConfigByte(
         ASC_DVC_VAR asc_ptr_type *asc_dvc, 
         ushort offset, 
-        uchar  byte_data )
+        uchar  byte_data ))
 {
     PCI_DATA	pciData;
 
@@ -6413,11 +6414,11 @@
  * Return the BIOS address of the adapter at the specified
  * I/O port and with the specified bus type.
  */
-ushort
+__initfunc(ushort
 AscGetChipBiosAddress(
         PortAddr iop_base,
         ushort bus_type
-    )
+    ))
 {
     ushort  cfg_lsw ;
     ushort  bios_addr ;
@@ -6927,11 +6928,11 @@
 	return (sc);
 }
 
-uchar
+__initfunc(uchar
 AscGetChipVersion(
 					 PortAddr iop_base,
 					 ushort bus_type
-)
+))
 {
 	if ((bus_type & ASC_IS_EISA) != 0) {
 		PortAddr            eisa_iop;
@@ -6976,13 +6977,13 @@
 	return (0);
 }
 
-ulong
+__initfunc(ulong
 AscLoadMicroCode(
 					PortAddr iop_base,
 					ushort s_addr,
 					ushort dosfar * mcode_buf,
 					ushort mcode_size
-)
+))
 {
 	ulong               chksum;
 	ushort              mcode_word_size;
@@ -6999,10 +7000,10 @@
 	return (chksum);
 }
 
-int
+__initfunc(int
 AscFindSignature(
 					PortAddr iop_base
-)
+))
 {
 	ushort              sig_word;
 	if (AscGetChipSignatureByte(iop_base) == (uchar) ASC_1000_ID1B) {
@@ -7022,11 +7023,11 @@
 	ASC_IOADR_5, ASC_IOADR_6, ASC_IOADR_7, ASC_IOADR_8
 };
 
-PortAddr
+__initfunc(PortAddr
 AscSearchIOPortAddr(
 					   PortAddr iop_beg,
 					   ushort bus_type
-)
+))
 {
 	if (bus_type & ASC_IS_VL) {
 		while ((iop_beg = AscSearchIOPortAddr11(iop_beg)) != 0) {
@@ -7057,10 +7058,10 @@
 	return (0);
 }
 
-PortAddr
+__initfunc(PortAddr
 AscSearchIOPortAddr11(
 						 PortAddr s_addr
-)
+))
 {
 	int                 i;
 	PortAddr            iop_base;
@@ -7103,9 +7104,9 @@
 };
 #endif
 
-void
+__initfunc(void
 AscSetISAPNPWaitForKey(
-	void)
+	void))
 {
 	outp(ASC_ISA_PNP_PORT_ADDR, 0x02);
 	outp(ASC_ISA_PNP_PORT_WRITE, 0x02);
@@ -7768,7 +7769,7 @@
 	return (0);
 }
 
-uchar _mcode_buf[ ] = {
+uchar _mcode_buf[ ] __initdata = {
   0x01,  0x03,  0x01,  0x19,  0x0F,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
   0x0F,  0x0F,  0x0F,  0x0F,  0x0F,  0x0F,  0x0F,  0x0F,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
   0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
@@ -9192,10 +9193,10 @@
 	return;
 }
 
-ulong
+__initfunc(ulong
 AscGetEisaProductID(
 					   PortAddr iop_base
-)
+))
 {
 	PortAddr            eisa_iop;
 	ushort              product_id_high, product_id_low;
@@ -9207,10 +9208,10 @@
 	return (product_id);
 }
 
-PortAddr
+__initfunc(PortAddr
 AscSearchIOPortAddrEISA(
 						   PortAddr iop_base
-)
+))
 {
 	ulong               eisa_product_id;
 	if (iop_base == 0) {
@@ -9469,10 +9470,10 @@
 	return (speed_value);
 }
 
-ushort
+__initfunc(ushort
 AscInitGetConfig(
 					ASC_DVC_VAR asc_ptr_type * asc_dvc
-)
+))
 {
 	ushort              warn_code;
 	warn_code = 0;
@@ -9500,10 +9501,10 @@
 	return (warn_code);
 }
 
-ushort
+__initfunc(ushort
 AscInitSetConfig(
 					ASC_DVC_VAR asc_ptr_type * asc_dvc
-)
+))
 {
 	ushort              warn_code;
 	warn_code = 0;
@@ -9519,10 +9520,10 @@
 	return (warn_code);
 }
 
-ushort
+__initfunc(ushort
 AscInitFromAscDvcVar(
 						ASC_DVC_VAR asc_ptr_type * asc_dvc
-)
+))
 {
 	PortAddr            iop_base;
 	ushort              cfg_msw;
@@ -9603,10 +9604,10 @@
 	return (warn_code);
 }
 
-ushort
+__initfunc(ushort
 AscInitAsc1000Driver(
 						ASC_DVC_VAR asc_ptr_type * asc_dvc
-)
+))
 {
 	ushort              warn_code;
 	PortAddr            iop_base;
@@ -9642,10 +9643,10 @@
 	return (warn_code);
 }
 
-ushort
+__initfunc(ushort
 AscInitAscDvcVar(
 					ASC_DVC_VAR asc_ptr_type * asc_dvc
-)
+))
 {
 	int                 i;
 	PortAddr            iop_base;
diff -u --recursive --new-file v2.1.35/linux/drivers/scsi/aic7xxx.c linux/drivers/scsi/aic7xxx.c
--- v2.1.35/linux/drivers/scsi/aic7xxx.c	Thu Mar 27 14:40:05 1997
+++ linux/drivers/scsi/aic7xxx.c	Wed Apr 23 08:54:21 1997
@@ -457,6 +457,7 @@
  * sections.
  */
 #define PAUSE_SEQUENCER(p) \
+  synchronize_irq();					\
   outb(p->pause, HCNTRL + p->base);			\
   while ((inb(HCNTRL + p->base) & PAUSE) == 0)		\
     ;							\
diff -u --recursive --new-file v2.1.35/linux/drivers/scsi/atari_NCR5380.c linux/drivers/scsi/atari_NCR5380.c
--- v2.1.35/linux/drivers/scsi/atari_NCR5380.c	Mon Apr 14 16:28:16 1997
+++ linux/drivers/scsi/atari_NCR5380.c	Thu Apr 17 13:20:46 1997
@@ -753,10 +753,6 @@
 	 pos += sprintf(pos, fmt , ## args); } while(0)
 static
 char *lprint_Scsi_Cmnd (Scsi_Cmnd *cmd, char *pos, char *buffer, int length);
-static
-char *lprint_command (unsigned char *cmd, char *pos, char *buffer, int len);
-static
-char *lprint_opcode(int opcode, char *pos, char *buffer, int length);
 
 #ifndef NCR5380_proc_info
 static
@@ -769,6 +765,14 @@
     struct NCR5380_hostdata *hostdata;
     Scsi_Cmnd *ptr;
     unsigned long flags;
+    off_t begin = 0;
+#define check_offset()				\
+    do {					\
+	if (pos - buffer < offset - begin) {	\
+	    begin += pos - buffer;		\
+	    pos = buffer;			\
+	}					\
+    } while (0)
 
     for (instance = first_instance; instance && HOSTNO != hostno;
 	 instance = instance->next)
@@ -781,58 +785,54 @@
 	return(-ENOSYS);  /* Currently this is a no-op */
     }
     SPRINTF("NCR5380 core release=%d.\n", NCR5380_PUBLIC_RELEASE);
+    check_offset();
     save_flags(flags);
     cli();
     SPRINTF("NCR5380: coroutine is%s running.\n", main_running ? "" : "n't");
+    check_offset();
     if (!hostdata->connected)
 	SPRINTF("scsi%d: no currently connected command\n", HOSTNO);
     else
 	pos = lprint_Scsi_Cmnd ((Scsi_Cmnd *) hostdata->connected,
 				pos, buffer, length);
     SPRINTF("scsi%d: issue_queue\n", HOSTNO);
-    for (ptr = (Scsi_Cmnd *) hostdata->issue_queue; ptr; ptr = NEXT(ptr))
+    check_offset();
+    for (ptr = (Scsi_Cmnd *) hostdata->issue_queue; ptr; ptr = NEXT(ptr)) {
 	pos = lprint_Scsi_Cmnd (ptr, pos, buffer, length);
+	check_offset();
+    }
 
     SPRINTF("scsi%d: disconnected_queue\n", HOSTNO);
+    check_offset();
     for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr;
-	 ptr = NEXT(ptr))
+	 ptr = NEXT(ptr)) {
 	pos = lprint_Scsi_Cmnd (ptr, pos, buffer, length);
+	check_offset();
+    }
 
     restore_flags(flags);
-    *start = buffer;
-    if (pos - buffer < offset)
+    *start = buffer + (offset - begin);
+    if (pos - buffer < offset - begin)
 	return 0;
-    else if (pos - buffer - offset < length)
-	return pos - buffer - offset;
+    else if (pos - buffer - (offset - begin) < length)
+	return pos - buffer - (offset - begin);
     return length;
 }
 
 static char *
 lprint_Scsi_Cmnd (Scsi_Cmnd *cmd, char *pos, char *buffer, int length)
 {
+    int i, s;
+    unsigned char *command;
     SPRINTF("scsi%d: destination target %d, lun %d\n",
 	    H_NO(cmd), cmd->target, cmd->lun);
     SPRINTF("        command = ");
-    pos = lprint_command (cmd->cmnd, pos, buffer, length);
-    return (pos);
-}
-
-static char *
-lprint_command (unsigned char *command, char *pos, char *buffer, int length)
-{
-    int i, s;
-    pos = lprint_opcode(command[0], pos, buffer, length);
+    command = cmd->cmnd;
+    SPRINTF("%2d (0x%02x)", command[0], command[0]);
     for (i = 1, s = COMMAND_SIZE(command[0]); i < s; ++i)
-	SPRINTF("%02x ", command[i]);
+	SPRINTF(" %02x", command[i]);
     SPRINTF("\n");
-    return(pos);
-}
-
-static 
-char *lprint_opcode(int opcode, char *pos, char *buffer, int length)
-{
-    SPRINTF("%2d (0x%02x)", opcode, opcode);
-    return(pos);
+    return pos;
 }
 
 
diff -u --recursive --new-file v2.1.35/linux/drivers/scsi/atari_scsi.c linux/drivers/scsi/atari_scsi.c
--- v2.1.35/linux/drivers/scsi/atari_scsi.c	Mon Apr 14 16:28:16 1997
+++ linux/drivers/scsi/atari_scsi.c	Thu Apr 17 13:20:46 1997
@@ -239,13 +239,18 @@
 static int atari_read_overruns = 0;
 #endif
 
-int setup_can_queue = -1;
-int setup_cmd_per_lun = -1;
-int setup_sg_tablesize = -1;
+static int setup_can_queue = -1;
+MODULE_PARM(setup_can_queue, "i");
+static int setup_cmd_per_lun = -1;
+MODULE_PARM(setup_cmd_per_lun, "i");
+static int setup_sg_tablesize = -1;
+MODULE_PARM(setup_sg_tablesize, "i");
 #ifdef SUPPORT_TAGS
-int setup_use_tagged_queuing = -1;
+static int setup_use_tagged_queuing = -1;
+MODULE_PARM(setup_use_tagged_queuing, "i");
 #endif
-int setup_hostid = -1;
+static int setup_hostid = -1;
+MODULE_PARM(setup_hostid, "i");
 
 
 #if defined(REAL_DMA)
@@ -660,7 +665,7 @@
 	if (setup_use_tagged_queuing < 0)
 		setup_use_tagged_queuing = DEFAULT_USE_TAGGED_QUEUING;
 #endif
-
+#ifdef REAL_DMA
 	/* If running on a Falcon and if there's TT-Ram (i.e., more than one
 	 * memory block, since there's always ST-Ram in a Falcon), then allocate a
 	 * STRAM_BUFFER_SIZE byte dribble buffer for transfers from/to alternative
@@ -673,10 +678,14 @@
 		atari_dma_phys_buffer = VTOP( atari_dma_buffer );
 		atari_dma_orig_addr = 0;
 	}
-
+#endif
 	instance = scsi_register (host, sizeof (struct NCR5380_hostdata));
 	atari_scsi_host = instance;
-	instance->irq = IS_A_TT() ? IRQ_TT_MFP_SCSI : IRQ_MFP_FSCSI;
+       /* Set irq to 0, to avoid that the mid-level code disables our interrupt
+        * during queue_command calls. This is completely unnecessary, and even
+        * worse causes bad problems on the Falcon, where the int is shared with
+        * IDE and floppy! */
+       instance->irq = 0;
 
 	atari_scsi_reset_boot();
 	NCR5380_init (instance, 0);
@@ -693,8 +702,8 @@
 		tt_scsi_dma.dma_ctrl = 0;
 		atari_dma_residual = 0;
 #endif /* REAL_DMA */
-
-		if (is_medusa) {
+#ifdef REAL_DMA
+		if (is_medusa || is_hades) {
 			/* While the read overruns (described by Drew Eckhardt in
 			 * NCR5380.c) never happened on TTs, they do in fact on the Medusa
 			 * (This was the cause why SCSI didn't work right for so long
@@ -709,6 +718,7 @@
 			 */
 			atari_read_overruns = 4;
 		}
+#endif
 		
 	}
 	else { /* ! IS_A_TT */
diff -u --recursive --new-file v2.1.35/linux/drivers/scsi/dtc.c linux/drivers/scsi/dtc.c
--- v2.1.35/linux/drivers/scsi/dtc.c	Mon Mar 17 14:54:29 1997
+++ linux/drivers/scsi/dtc.c	Tue Apr 22 22:42:51 1997
@@ -84,8 +84,9 @@
 #include "NCR5380.h"
 #include "constants.h"
 #include "sd.h"
-#include<linux/stat.h>
-#include<linux/string.h>
+#include <linux/stat.h>
+#include <linux/string.h>
+#include <linux/init.h>
 
 
 #define DTC_PUBLIC_RELEASE 2
@@ -145,9 +146,9 @@
    int irq;
 } overrides
 #ifdef OVERRIDE
-[] = OVERRIDE;
+[] __initdata = OVERRIDE;
 #else
-[4] = {{0, IRQ_AUTO}, {0, IRQ_AUTO}, {0, IRQ_AUTO}, {0, IRQ_AUTO}};
+[4] __initdata = {{0, IRQ_AUTO}, {0, IRQ_AUTO}, {0, IRQ_AUTO}, {0, IRQ_AUTO}};
 #endif
 
 #define NO_OVERRIDES (sizeof(overrides) / sizeof(struct override))
@@ -155,7 +156,7 @@
 static struct base {
    unsigned int address;
    int noauto;
-} bases[] = {{0xcc000, 0}, {0xc8000, 0}, {0xdc000, 0}, {0xd8000, 0}};
+} bases[] __initdata = {{0xcc000, 0}, {0xc8000, 0}, {0xdc000, 0}, {0xd8000, 0}};
 
 #define NO_BASES (sizeof (bases) / sizeof (struct base))
 
@@ -176,7 +177,7 @@
  *
 */
 
-void dtc_setup(char *str, int *ints) {
+__initfunc(void dtc_setup(char *str, int *ints)) {
    static int commandline_current = 0;
    int i;
    if (ints[0] != 2)
@@ -208,7 +209,7 @@
 */
 
 
-int dtc_detect(Scsi_Host_Template * tpnt) {
+__initfunc(int dtc_detect(Scsi_Host_Template * tpnt)) {
    static int current_override = 0, current_base = 0;
    struct Scsi_Host *instance;
    unsigned int base;
diff -u --recursive --new-file v2.1.35/linux/drivers/scsi/esp.c linux/drivers/scsi/esp.c
--- v2.1.35/linux/drivers/scsi/esp.c	Mon Apr 14 16:28:16 1997
+++ linux/drivers/scsi/esp.c	Thu Apr 17 13:20:47 1997
@@ -20,6 +20,7 @@
 #include <linux/blk.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
+#include <linux/init.h>
 
 #include "scsi.h"
 #include "hosts.h"
@@ -639,7 +640,7 @@
 /* Detecting ESP chips on the machine.  This is the simple and easy
  * version.
  */
-int esp_detect(Scsi_Host_Template *tpnt)
+__initfunc(int esp_detect(Scsi_Host_Template *tpnt))
 {
 	struct Sparc_ESP *esp, *elink;
 	struct Scsi_Host *esp_host;
diff -u --recursive --new-file v2.1.35/linux/drivers/scsi/g_NCR5380.c linux/drivers/scsi/g_NCR5380.c
--- v2.1.35/linux/drivers/scsi/g_NCR5380.c	Mon Apr  7 11:35:29 1997
+++ linux/drivers/scsi/g_NCR5380.c	Tue Apr 22 22:42:51 1997
@@ -103,7 +103,8 @@
 #include "NCR5380.h"
 #include "constants.h"
 #include "sd.h"
-#include<linux/stat.h>
+#include <linux/stat.h>
+#include <linux/init.h>
 
 struct proc_dir_entry proc_scsi_g_ncr5380 = {
     PROC_SCSI_GENERIC_NCR5380, 9, "g_NCR5380",
@@ -124,9 +125,9 @@
     int board;	/* Use NCR53c400, Ricoh, etc. extensions ? */
 } overrides 
 #ifdef GENERIC_NCR5380_OVERRIDE 
-    [] = GENERIC_NCR5380_OVERRIDE
+    [] __initdata = GENERIC_NCR5380_OVERRIDE
 #else
-    [1] = {{0,},};
+    [1] __initdata = {{0,},};
 #endif
 
 #define NO_OVERRIDES (sizeof(overrides) / sizeof(struct override))
@@ -142,7 +143,7 @@
  *
  */
 
-static void internal_setup(int board, char *str, int *ints) {
+__initfunc(static void internal_setup(int board, char *str, int *ints)) {
     static int commandline_current = 0;
     switch (board) {
     case BOARD_NCR5380:
@@ -178,7 +179,7 @@
  * 	equal to the number of ints.
  */
 
-void generic_NCR5380_setup (char *str, int *ints) {
+__initfunc(void generic_NCR5380_setup (char *str, int *ints)) {
     internal_setup (BOARD_NCR5380, str, ints);
 }
 
@@ -191,7 +192,7 @@
  * 	equal to the number of ints.
  */
 
-void generic_NCR53C400_setup (char *str, int *ints) {
+__initfunc(void generic_NCR53C400_setup (char *str, int *ints)) {
     internal_setup (BOARD_NCR53C400, str, ints);
 }
 
@@ -207,7 +208,7 @@
  *
  */
 
-int generic_NCR5380_detect(Scsi_Host_Template * tpnt) {
+__initfunc(int generic_NCR5380_detect(Scsi_Host_Template * tpnt)) {
     static int current_override = 0;
     int count;
     int flags = 0;
diff -u --recursive --new-file v2.1.35/linux/drivers/scsi/gvp11.c linux/drivers/scsi/gvp11.c
--- v2.1.35/linux/drivers/scsi/gvp11.c	Fri Dec 20 01:20:02 1996
+++ linux/drivers/scsi/gvp11.c	Thu Apr 17 13:20:47 1997
@@ -9,7 +9,7 @@
 #include <asm/pgtable.h>
 #include <asm/amigaints.h>
 #include <asm/amigahw.h>
-#include <asm/zorro.h>
+#include <linux/zorro.h>
 #include <asm/irq.h>
 
 #include "scsi.h"
@@ -204,7 +204,7 @@
     struct Scsi_Host *instance;
     caddr_t address;
     enum GVP_ident epc;
-    int key;
+    int key = 0;
     struct ConfigDev *cd;
 
     if (!MACH_IS_AMIGA || called)
@@ -214,9 +214,18 @@
     tpnt->proc_dir = &proc_scsi_gvp11;
     tpnt->proc_info = &wd33c93_proc_info;
 
-    while ((key = zorro_find(MANUF_GVP, PROD_GVPIISCSI, 0, 0))) {
+    while ((key = zorro_find(MANUF_GVP, PROD_GVPIISCSI, 0, key))) {
 	cd = zorro_get_board(key);
 	address = cd->cd_BoardAddr;
+
+	/*
+	 * Rumors state that some GVP ram boards use the same product
+	 * code as the SCSI controllers. Therefore if the board-size
+	 * is not 64KB we asume it is a ram board and bail out.
+	 */
+	if (cd->cd_BoardSize != 0x10000)
+		continue;
+
 	/* check extended product code */
 	epc = *(unsigned short *)(ZTWO_VADDR(address) + 0x8000);
 	epc = epc & GVP_PRODMASK;
@@ -237,7 +246,7 @@
 
 	instance = scsi_register (tpnt, sizeof (struct WD33C93_hostdata));
 	instance->base = (unsigned char *)ZTWO_VADDR(address);
-	instance->irq = IRQ_AMIGA_PORTS & ~IRQ_MACHSPEC;
+	instance->irq = IRQ_AMIGA_PORTS;
 	instance->unique_id = key;
 
 	if (gvp11_xfer_mask)
@@ -307,11 +316,11 @@
 int gvp11_release(struct Scsi_Host *instance)
 {
 #ifdef MODULE
-DMA(instance)->CNTR = 0;
-zorro_unconfig_board(instance->unique_id, 0);
-if (--num_gvp11 == 0)
-  free_irq(IRQ_AMIGA_PORTS, gvp11_intr);
-  wd33c93_release();
+    DMA(instance)->CNTR = 0;
+    zorro_unconfig_board(instance->unique_id, 0);
+    if (--num_gvp11 == 0)
+	    free_irq(IRQ_AMIGA_PORTS, gvp11_intr);
+    wd33c93_release();
 #endif
-return 1;
+    return 1;
 }
diff -u --recursive --new-file v2.1.35/linux/drivers/scsi/hosts.c linux/drivers/scsi/hosts.c
--- v2.1.35/linux/drivers/scsi/hosts.c	Fri Dec 13 01:37:37 1996
+++ linux/drivers/scsi/hosts.c	Tue Apr 22 22:42:51 1997
@@ -30,6 +30,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/proc_fs.h>
+#include <linux/init.h>
 
 #include "scsi.h"
 
@@ -433,7 +434,7 @@
     return 0;
 }
 
-unsigned int scsi_init()
+__initfunc(unsigned int scsi_init(void))
 {
     static int called = 0;
     int i, pcount;
diff -u --recursive --new-file v2.1.35/linux/drivers/scsi/ncr53c8xx.c linux/drivers/scsi/ncr53c8xx.c
--- v2.1.35/linux/drivers/scsi/ncr53c8xx.c	Sun Apr 13 10:18:21 1997
+++ linux/drivers/scsi/ncr53c8xx.c	Tue Apr 22 08:30:20 1997
@@ -40,7 +40,7 @@
 */
 
 /*
-**	6 April 1997, version 1.18d
+**	16 April 1997, version 1.18e
 **
 **	Supported SCSI-II features:
 **	    Synchronous negotiation
@@ -1735,7 +1735,7 @@
 
 static char *ncr_name (ncb_p np)
 {
-	static char name[10];
+	static char name[16];
 	sprintf(name, "ncr53c%d-%d", np->chip, np->unit);
 	return (name);
 }
@@ -4520,7 +4520,7 @@
 **
 **==========================================================
 */
-int ncr_reset_bus (Scsi_Cmnd *cmd)
+int ncr_reset_bus (Scsi_Cmnd *cmd, int sync_reset)
 {
         struct Scsi_Host   *host      = cmd->host;
 /*	Scsi_Device        *device    = cmd->device; */
@@ -4572,11 +4572,12 @@
  */
 	ncr_wakeup(np, HS_RESET);
 /*
- * If the involved command was not in a driver queue, and is 
- * not in the waiting list, complete it with DID_RESET status,
+ * If the involved command was not in a driver queue, and the 
+ * scsi driver told us reset is synchronous, and the command is not 
+ * currently in the waiting list, complete it with DID_RESET status,
  * in order to keep it alive.
  */
-	if (!found && cmd && !remove_from_waiting_list(np, cmd)) {
+	if (!found && sync_reset && !retrieve_from_waiting_list(0, np, cmd)) {
 		cmd->result = ScsiResult(DID_RESET, 0);
 		cmd->scsi_done(cmd);
 	}
@@ -6363,27 +6364,13 @@
 		((INL(nc_dbc) & 0xf8000000) == SCR_WAIT_DISC)) {
 		/*
 		**      Unexpected data cycle while waiting for disconnect.
-		*/
-		if (INB(nc_sstat2) & LDSC) {
-			/*
-			**	It's an early reconnect.
-			**	Let's continue ...
-			*/
-			OUTONB (nc_dcntl, (STD|NOCOM));
-			/*
-			**	info message
-			*/
-			printf ("%s: INFO: LDSC while IID.\n",
-				ncr_name (np));
-			return;
-		};
-		printf ("%s: target %d doesn't release the bus.\n",
-			ncr_name (np), (int)INB (nc_ctest0)&0x0f);
-		/*
-		**	return without restarting the NCR.
-		**	timeout will do the real work.
-		*/
-		return;
+		**	LDSC and CON bits may help in order to understand 
+		**	what really happened. Print some info message and let 
+		**	the reset function reset the BUS and the NCR.
+		*/
+		printf("%s:%d: data cycle while waiting for disconnect, LDSC=%d CON=%d\n",
+			ncr_name (np), (int)(INB(nc_ctest0)&0x0f),
+			(0!=(INB(nc_sstat2)&LDSC)), (0!=(INB(nc_scntl1)&ISCON)));
 	};
 
 	/*----------------------------------------
@@ -7375,7 +7362,7 @@
 /*==========================================================
 **
 **
-**	Aquire a control block
+**	Acquire a control block
 **
 **
 **==========================================================
@@ -8617,25 +8604,93 @@
 **   Linux entry point of reset() function
 */
 
-#if	LINUX_VERSION_CODE >= LinuxVersionCode(1,3,98)
+#if defined SCSI_RESET_SYNCHRONOUS && defined SCSI_RESET_ASYNCHRONOUS
+
 int ncr53c8xx_reset(Scsi_Cmnd *cmd, unsigned int reset_flags)
+{
+	int sts;
+	unsigned long flags;
+
+	printk("ncr53c8xx_reset: pid=%lu reset_flags=%x serial_number=%ld serial_number_at_timeout=%ld\n",
+		cmd->pid, reset_flags, cmd->serial_number, cmd->serial_number_at_timeout);
+
+	save_flags(flags); cli();
+
+	/*
+	 * We have to just ignore reset requests in some situations.
+	 */
+#if defined SCSI_RESET_NOT_RUNNING
+	if (cmd->serial_number != cmd->serial_number_at_timeout) {
+		sts = SCSI_RESET_NOT_RUNNING;
+		goto out;
+	}
+#endif
+	/*
+	 * If the mid-level driver told us reset is synchronous, it seems 
+	 * that we must call the done() callback for the involved command, 
+	 * even if this command was not queued to the low-level driver, 
+	 * before returning SCSI_RESET_SUCCESS.
+	 */
+
+	sts = ncr_reset_bus(cmd,
+	(reset_flags & (SCSI_RESET_SYNCHRONOUS | SCSI_RESET_ASYNCHRONOUS)) == SCSI_RESET_SYNCHRONOUS);
+	/*
+	 * Since we always reset the controller, when we return success, 
+	 * we add this information to the return code.
+	 */
+#if defined SCSI_RESET_HOST_RESET
+	if (sts == SCSI_RESET_SUCCESS)
+		sts |= SCSI_RESET_HOST_RESET;
+#endif
+
+out:
+	restore_flags(flags);
+	return sts;
+}
 #else
 int ncr53c8xx_reset(Scsi_Cmnd *cmd)
-#endif
 {
 	printk("ncr53c8xx_reset: command pid %lu\n", cmd->pid);
-	return ncr_reset_bus(cmd);
+	return ncr_reset_bus(cmd, 1);
 }
+#endif
 
 /*
 **   Linux entry point of abort() function
 */
 
+#if defined SCSI_RESET_SYNCHRONOUS && defined SCSI_RESET_ASYNCHRONOUS
+
+int ncr53c8xx_abort(Scsi_Cmnd *cmd)
+{
+	int sts;
+	unsigned long flags;
+
+	printk("ncr53c8xx_abort: pid=%lu serial_number=%ld serial_number_at_timeout=%ld\n",
+		cmd->pid, cmd->serial_number, cmd->serial_number_at_timeout);
+
+	save_flags(flags); cli();
+
+	/*
+	 * We have to just ignore abort requests in some situations.
+	 */
+	if (cmd->serial_number != cmd->serial_number_at_timeout) {
+		sts = SCSI_ABORT_NOT_RUNNING;
+		goto out;
+	}
+
+	sts = ncr_abort_command(cmd);
+out:
+	restore_flags(flags);
+	return sts;
+}
+#else
 int ncr53c8xx_abort(Scsi_Cmnd *cmd)
 {
 	printk("ncr53c8xx_abort: command pid %lu\n", cmd->pid);
 	return ncr_abort_command(cmd);
 }
+#endif
 
 #ifdef MODULE
 int ncr53c8xx_release(struct Scsi_Host *host)
diff -u --recursive --new-file v2.1.35/linux/drivers/scsi/ncr53c8xx.h linux/drivers/scsi/ncr53c8xx.h
--- v2.1.35/linux/drivers/scsi/ncr53c8xx.h	Sun Apr 13 10:18:21 1997
+++ linux/drivers/scsi/ncr53c8xx.h	Wed Apr 23 11:01:37 1997
@@ -45,7 +45,7 @@
 /*
 **	Name and revision of the driver
 */
-#define SCSI_NCR_DRIVER_NAME		"ncr53c8xx - revision 1.18d"
+#define SCSI_NCR_DRIVER_NAME		"ncr53c8xx - revision 1.18f"
  
 /*
 **	If SCSI_NCR_SETUP_SPECIAL_FEATURES is defined,
diff -u --recursive --new-file v2.1.35/linux/drivers/scsi/pas16.c linux/drivers/scsi/pas16.c
--- v2.1.35/linux/drivers/scsi/pas16.c	Mon May  6 02:26:11 1996
+++ linux/drivers/scsi/pas16.c	Tue Apr 22 22:42:51 1997
@@ -120,7 +120,8 @@
 #include "constants.h"
 #include "sd.h"
 
-#include<linux/stat.h>
+#include <linux/stat.h>
+#include <linux/init.h>
 
 struct proc_dir_entry proc_scsi_pas16 = {
     PROC_SCSI_PAS16, 5, "pas16",
@@ -138,20 +139,21 @@
  * irq jumpers on the board).  The first value in the array will be
  * assigned to logical board 0, the next to board 1, etc.
  */
-int default_irqs[] = {  PAS16_DEFAULT_BOARD_1_IRQ,
-			PAS16_DEFAULT_BOARD_2_IRQ,
-			PAS16_DEFAULT_BOARD_3_IRQ,
-			PAS16_DEFAULT_BOARD_4_IRQ
-		     };
+int default_irqs[] __initdata = 
+	{  PAS16_DEFAULT_BOARD_1_IRQ,
+	   PAS16_DEFAULT_BOARD_2_IRQ,
+	   PAS16_DEFAULT_BOARD_3_IRQ,
+	   PAS16_DEFAULT_BOARD_4_IRQ
+	};
 
 static struct override {
     unsigned short io_port;
     int  irq;
 } overrides 
 #ifdef PAS16_OVERRIDE
-    [] = PAS16_OVERRIDE;
+    [] __initdata = PAS16_OVERRIDE;
 #else
-    [4] = {{0,IRQ_AUTO}, {0,IRQ_AUTO}, {0,IRQ_AUTO},
+    [4] __initdata = {{0,IRQ_AUTO}, {0,IRQ_AUTO}, {0,IRQ_AUTO},
 	{0,IRQ_AUTO}};
 #endif
 
@@ -160,11 +162,12 @@
 static struct base {
     unsigned short io_port;
     int noauto;
-} bases[] = { {PAS16_DEFAULT_BASE_1, 0},
-	      {PAS16_DEFAULT_BASE_2, 0},
-	      {PAS16_DEFAULT_BASE_3, 0},
-	      {PAS16_DEFAULT_BASE_4, 0}
-	    };
+} bases[] __initdata = 
+	{ {PAS16_DEFAULT_BASE_1, 0},
+	  {PAS16_DEFAULT_BASE_2, 0},
+	  {PAS16_DEFAULT_BASE_3, 0},
+	  {PAS16_DEFAULT_BASE_4, 0}
+	};
 
 #define NO_BASES (sizeof (bases) / sizeof (struct base))
 
@@ -210,7 +213,8 @@
  *
  */
 
-void	enable_board( int  board_num,  unsigned short port )
+__initfunc(static void
+	enable_board( int  board_num,  unsigned short port ))
 {
     outb( 0xbc + board_num, MASTER_ADDRESS_PTR );
     outb( port >> 2, MASTER_ADDRESS_PTR );
@@ -229,7 +233,8 @@
  *
  */
 
-void	init_board( unsigned short io_port, int irq, int force_irq )
+__initfunc (static void
+	init_board( unsigned short io_port, int irq, int force_irq ))
 {
 	unsigned int	tmp;
 	unsigned int	pas_irq_code;
@@ -277,7 +282,8 @@
  * Returns : 0 if board not found, 1 if found.
  */
 
-int     pas16_hw_detect( unsigned short  board_num )
+__initfunc(static int
+     pas16_hw_detect( unsigned short  board_num ))
 {
     unsigned char	board_rev, tmp;
     unsigned short	io_port = bases[ board_num ].io_port;
@@ -336,7 +342,7 @@
  *
  */
 
-void pas16_setup(char *str, int *ints) {
+__initfunc(void pas16_setup(char *str, int *ints)) {
     static int commandline_current = 0;
     int i;
     if (ints[0] != 2) 
@@ -367,7 +373,7 @@
  *
  */
 
-int pas16_detect(Scsi_Host_Template * tpnt) {
+__initfunc(int pas16_detect(Scsi_Host_Template * tpnt)) {
     static int current_override = 0;
     static unsigned short current_base = 0;
     struct Scsi_Host *instance;
diff -u --recursive --new-file v2.1.35/linux/drivers/scsi/ppa.c linux/drivers/scsi/ppa.c
--- v2.1.35/linux/drivers/scsi/ppa.c	Mon Apr 14 16:28:16 1997
+++ linux/drivers/scsi/ppa.c	Thu Apr 17 14:48:53 1997
@@ -1132,69 +1132,72 @@
 	nhosts = 0;
 
 	for (i = 0; pb; i++, pb=pb->next) {
-		int modes;
+		int modes = pb->modes;
 
-		/* transfer global values here */
-		if (ppa_speed >= 0)
-			ppa_hosts[i].speed = ppa_speed;
-		if (ppa_speed_fast >= 0)
-			ppa_hosts[i].speed_fast = ppa_speed_fast;
+		/* We only understand PC-style ports */
+		if (modes & PARPORT_MODE_SPP) {
 
-		ppa_hosts[i].dev =
-		    parport_register_device(pb, "ppa", NULL, ppa_wakeup,
-			      NULL, PARPORT_DEV_TRAN, (void *) &ppa_hosts[i]);
-
-		/* Claim the bus so it remembers what we do to the control
-		 * registers. [ CTR and ECP ]
-		 */
-		ppa_pb_claim(i);
-		w_ctr(i, 0x0c);
-		modes = ppa_hosts[i].dev->port->modes;
-
-		ppa_hosts[i].mode = PPA_NIBBLE;
-		if (modes & (PARPORT_MODE_EPP | PARPORT_MODE_ECPEPP)) {
-			ppa_hosts[i].mode = PPA_EPP_32;
-			printk("PPA: Parport [ EPP ]\n");
-		} else if (modes & PARPORT_MODE_ECP) {
-			w_ecr(i, 0x20);
-			ppa_hosts[i].mode = PPA_PS2;
-			printk("PPA: Parport [ ECP in PS2 submode ]\n");
-		} else if (modes & PARPORT_MODE_PS2) {
-			ppa_hosts[i].mode = PPA_PS2;
-			printk("PPA: Parport [ PS2 ]\n");
-		}
-		/* Done configuration */
-		ppa_pb_release(i);
-
-		rs = ppa_init(i);
-		if (rs) {
-			parport_unregister_device(ppa_hosts[i].dev);
-			continue;
-		}
-		/* now the glue ... */
-		switch (ppa_hosts[i].mode) {
-		case PPA_NIBBLE:
-		case PPA_PS2:
-			ports = 3;
-			break;
-		case PPA_EPP_8:
-		case PPA_EPP_16:
-		case PPA_EPP_32:
-			ports = 8;
-			break;
-		default:	/* Never gets here */
-			continue;
+			/* transfer global values here */
+			if (ppa_speed >= 0)
+				ppa_hosts[i].speed = ppa_speed;
+			if (ppa_speed_fast >= 0)
+				ppa_hosts[i].speed_fast = ppa_speed_fast;
+			
+			ppa_hosts[i].dev = parport_register_device(pb, "ppa", 
+				    NULL, ppa_wakeup, NULL,
+				    PARPORT_DEV_TRAN, (void *) &ppa_hosts[i]);
+			
+			/* Claim the bus so it remembers what we do to the
+			 * control registers. [ CTR and ECP ]
+			 */
+			ppa_pb_claim(i);
+			w_ctr(i, 0x0c);
+
+			ppa_hosts[i].mode = PPA_NIBBLE;
+			if (modes & (PARPORT_MODE_EPP | PARPORT_MODE_ECPEPP)) {
+				ppa_hosts[i].mode = PPA_EPP_32;
+				printk("PPA: Parport [ EPP ]\n");
+			} else if (modes & PARPORT_MODE_ECP) {
+				w_ecr(i, 0x20);
+				ppa_hosts[i].mode = PPA_PS2;
+				printk("PPA: Parport [ ECP in PS2 submode ]\n");
+			} else if (modes & PARPORT_MODE_PS2) {
+				ppa_hosts[i].mode = PPA_PS2;
+				printk("PPA: Parport [ PS2 ]\n");
+			}
+			/* Done configuration */
+			ppa_pb_release(i);
+
+			rs = ppa_init(i);
+			if (rs) {
+				parport_unregister_device(ppa_hosts[i].dev);
+				continue;
+			}
+			/* now the glue ... */
+			switch (ppa_hosts[i].mode) {
+			case PPA_NIBBLE:
+			case PPA_PS2:
+				ports = 3;
+				break;
+			case PPA_EPP_8:
+			case PPA_EPP_16:
+			case PPA_EPP_32:
+				ports = 8;
+				break;
+			default:	/* Never gets here */
+				continue;
+			}
+			
+			host->can_queue = PPA_CAN_QUEUE;
+			host->sg_tablesize = ppa_sg;
+			hreg = scsi_register(host, 0);
+			hreg->io_port = pb->base;
+			hreg->n_io_port = ports;
+			hreg->dma_channel = -1;
+			hreg->unique_id = i;
+			ppa_hosts[i].host = hreg->host_no;
+			nhosts++;
 		}
-
-		host->can_queue = PPA_CAN_QUEUE;
-		host->sg_tablesize = ppa_sg;
-		hreg = scsi_register(host, 0);
-		hreg->io_port = pb->base;
-		hreg->n_io_port = ports;
-		hreg->dma_channel = -1;
-		hreg->unique_id = i;
-		ppa_hosts[i].host = hreg->host_no;
-		nhosts++;
 	}
 	if (nhosts == 0)
 		return 0;
diff -u --recursive --new-file v2.1.35/linux/drivers/scsi/qlogicpti.c linux/drivers/scsi/qlogicpti.c
--- v2.1.35/linux/drivers/scsi/qlogicpti.c	Mon Apr 14 16:28:16 1997
+++ linux/drivers/scsi/qlogicpti.c	Thu Apr 17 13:20:47 1997
@@ -18,6 +18,7 @@
 #include <linux/blk.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
+#include <linux/init.h>
 
 #include <asm/byteorder.h>
 
@@ -342,7 +343,7 @@
 
 #define PTI_RESET_LIMIT 400
 
-static int qlogicpti_load_firmware(struct qlogicpti *qpti)
+__initfunc(static int qlogicpti_load_firmware(struct qlogicpti *qpti))
 {
 	struct qlogicpti_regs *qregs = qpti->qregs;
 	unsigned short csum = 0;
@@ -561,7 +562,7 @@
 static void qlogicpti_intr_handler(int irq, void *dev_id, struct pt_regs *regs);
 
 /* Detect all PTI Qlogic ISP's in the machine. */
-int qlogicpti_detect(Scsi_Host_Template *tpnt)
+__initfunc(int qlogicpti_detect(Scsi_Host_Template *tpnt))
 {
 	struct qlogicpti *qpti, *qlink;
 	struct Scsi_Host *qpti_host;
diff -u --recursive --new-file v2.1.35/linux/drivers/scsi/qlogicpti_asm.c linux/drivers/scsi/qlogicpti_asm.c
--- v2.1.35/linux/drivers/scsi/qlogicpti_asm.c	Fri Dec 13 01:37:38 1996
+++ linux/drivers/scsi/qlogicpti_asm.c	Thu Apr 17 13:20:47 1997
@@ -2,7 +2,7 @@
 
 unsigned short risc_code_addr01 = 0x1000;
 
-unsigned short risc_code01[] = {
+unsigned short risc_code01[] __initdata = {
 	0x0078, 0x1030, 0x0000, 0x231f, 0x0000, 0x12ff, 0x2043, 0x4f50,
 	0x5952, 0x4947, 0x4854, 0x2031, 0x3939, 0x312c, 0x3139, 0x3932,
 	0x2c31, 0x3939, 0x332c, 0x3139, 0x3934, 0x2051, 0x4c4f, 0x4749,
diff -u --recursive --new-file v2.1.35/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c
--- v2.1.35/linux/drivers/scsi/scsi.c	Mon Apr  7 11:35:30 1997
+++ linux/drivers/scsi/scsi.c	Tue Apr 22 22:42:51 1997
@@ -48,6 +48,7 @@
 #include <linux/blk.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
+#include <linux/init.h>
 
 #include <asm/system.h>
 #include <asm/irq.h>
@@ -2537,7 +2538,7 @@
  * initialization, bus scanning, and sd/st initialization routines.
  */
 
-int scsi_dev_init(void)
+__initfunc(int scsi_dev_init(void))
 {
     Scsi_Device * SDpnt;
     struct Scsi_Host * shpnt;
diff -u --recursive --new-file v2.1.35/linux/drivers/scsi/t128.c linux/drivers/scsi/t128.c
--- v2.1.35/linux/drivers/scsi/t128.c	Mon Mar 17 14:54:30 1997
+++ linux/drivers/scsi/t128.c	Tue Apr 22 22:42:51 1997
@@ -118,7 +118,8 @@
 #include "NCR5380.h"
 #include "constants.h"
 #include "sd.h"
-#include<linux/stat.h>
+#include <linux/stat.h>
+#include <linux/init.h>
 
 struct proc_dir_entry proc_scsi_t128 = {
     PROC_SCSI_T128, 4, "t128",
@@ -131,10 +132,10 @@
     int irq;
 } overrides 
 #ifdef T128_OVERRIDE
-    [] = T128_OVERRIDE;
+    [] __initdata = T128_OVERRIDE;
 #else
-    [4] = {{NULL,IRQ_AUTO}, {NULL,IRQ_AUTO}, {NULL,IRQ_AUTO},
-	{NULL,IRQ_AUTO}};
+    [4] __initdata = {{NULL,IRQ_AUTO}, {NULL,IRQ_AUTO}, 
+        {NULL,IRQ_AUTO}, {NULL,IRQ_AUTO}};
 #endif
 
 #define NO_OVERRIDES (sizeof(overrides) / sizeof(struct override))
@@ -142,7 +143,8 @@
 static struct base {
     unsigned char *address;
     int noauto;
-} bases[] = {{(unsigned char *) 0xcc000, 0}, {(unsigned char *) 0xc8000, 0},
+} bases[] __initdata = {
+    {(unsigned char *) 0xcc000, 0}, {(unsigned char *) 0xc8000, 0},
     {(unsigned char *) 0xdc000, 0}, {(unsigned char *) 0xd8000, 0}};
 
 #define NO_BASES (sizeof (bases) / sizeof (struct base))
@@ -150,7 +152,7 @@
 static const struct signature {
     const char *string;
     int offset;
-} signatures[] = {
+} signatures[] __initdata = {
 {"TSROM: SCSI BIOS, Version 1.12", 0x36},
 };
 
@@ -166,7 +168,7 @@
  *
  */
 
-void t128_setup(char *str, int *ints) {
+__initfunc(void t128_setup(char *str, int *ints)) {
     static int commandline_current = 0;
     int i;
     if (ints[0] != 2) 
@@ -197,7 +199,7 @@
  *
  */
 
-int t128_detect(Scsi_Host_Template * tpnt) {
+__initfunc(int t128_detect(Scsi_Host_Template * tpnt)) {
     static int current_override = 0, current_base = 0;
     struct Scsi_Host *instance;
     unsigned char *base;
diff -u --recursive --new-file v2.1.35/linux/drivers/scsi/wd33c93.c linux/drivers/scsi/wd33c93.c
--- v2.1.35/linux/drivers/scsi/wd33c93.c	Fri Dec 20 01:20:02 1996
+++ linux/drivers/scsi/wd33c93.c	Thu Apr 17 13:20:47 1997
@@ -28,9 +28,9 @@
  *
  *    -  Target Disconnection/Reconnection  is now supported. Any
  *          system with more than one device active on the SCSI bus
- *          will benefit from this. The driver defaults to what I'm
- *          'adaptive disconnect' - meaning that each command is
- *          evaluated individually as to whether or not it should
+ *          will benefit from this. The driver defaults to what I
+ *          call 'adaptive disconnect' - meaning that each command
+ *          is evaluated individually as to whether or not it should
  *          be run with the option to disconnect/reselect (if the
  *          device chooses), or as a "SCSI-bus-hog".
  *
@@ -87,23 +87,19 @@
 #include "hosts.h"
 
 
-#define PROC_INTERFACE     /* add code for /proc/scsi/wd33c93/xxx interface */
-#ifdef  PROC_INTERFACE
-#define PROC_STATISTICS    /* add code for keeping various real time stats */
-#endif
-
-#define SYNC_DEBUG         /* extra info on sync negotiation printed */
-#undef DEBUGGING_ON        /* enable command-line debugging bitmask */
-#define DEBUG_DEFAULTS 0   /* default debugging bitmask */
-
-#define WD33C93_VERSION    "1.23"
-#define WD33C93_DATE       "04/Nov/1996"
+#define WD33C93_VERSION    "1.24"
+#define WD33C93_DATE       "29/Jan/1997"
 
-#ifdef DEBUGGING_ON
-#define DB(f,a) if (hostdata->args & (f)) a;
-#else
-#define DB(f,a)
-#endif
+/*
+ * Note - the following defines have been moved to 'wd33c93.h':
+ *
+ *    PROC_INTERFACE
+ *    PROC_STATISTICS
+ *    SYNC_DEBUG
+ *    DEBUGGING_ON
+ *    DEBUG_DEFAULTS
+ *
+ */
 
 
 #include "wd33c93.h"
@@ -118,10 +114,11 @@
  * keywords (lower case required) and arguments:
  *
  * -  nosync:bitmask -bitmask is a byte where the 1st 7 bits correspond with
- *                    the 7 possible SCSI devices. Set a bit to prevent sync
- *                    negotiation on that device. To maintain backwards
- *                    compatibility, a command-line such as "wd33c93=255" will
- *                    be automatically translated to "wd33c93=nosync:0xff".
+ *                    the 7 possible SCSI devices. Set a bit to negotiate for
+ *                    asynchronous transfers on that device. To maintain
+ *                    backwards compatibility, a command-line such as
+ *                    "wd33c93=255" will be automatically translated to
+ *                    "wd33c93=nosync:0xff".
  * -  nodma:x        -x = 1 to disable DMA, x = 0 to enable it. Argument is
  *                    optional - if not present, same as "nodma:1".
  * -  period:ns      -ns is the minimum # of nanoseconds in a SCSI data transfer
@@ -166,7 +163,7 @@
 
 
 
-inline uchar read_wd33c93(wd33c93_regs *regp,uchar reg_num)
+static inline uchar read_wd33c93(wd33c93_regs *regp,uchar reg_num)
 {
    regp->SASR = reg_num;
    return(regp->SCMD);
@@ -176,21 +173,21 @@
 #define READ_AUX_STAT() (regp->SASR)
 
 
-inline void write_wd33c93(wd33c93_regs *regp,uchar reg_num, uchar value)
+static inline void write_wd33c93(wd33c93_regs *regp,uchar reg_num, uchar value)
 {
    regp->SASR = reg_num;
    regp->SCMD = value;
 }
 
 
-inline void write_wd33c93_cmd(wd33c93_regs *regp, uchar cmd)
+static inline void write_wd33c93_cmd(wd33c93_regs *regp, uchar cmd)
 {
    regp->SASR = WD_COMMAND;
    regp->SCMD = cmd;
 }
 
 
-inline uchar read_1_byte(wd33c93_regs *regp)
+static inline uchar read_1_byte(wd33c93_regs *regp)
 {
 uchar asr;
 uchar x = 0;
@@ -206,7 +203,7 @@
 }
 
 
-void write_wd33c93_count(wd33c93_regs *regp,unsigned long value)
+static void write_wd33c93_count(wd33c93_regs *regp,unsigned long value)
 {
    regp->SASR = WD_TRANSFER_COUNT_MSB;
    regp->SCMD = value >> 16;
@@ -215,7 +212,7 @@
 }
 
 
-unsigned long read_wd33c93_count(wd33c93_regs *regp)
+static unsigned long read_wd33c93_count(wd33c93_regs *regp)
 {
 unsigned long value;
 
@@ -265,7 +262,7 @@
    {1000,0x00},
    {0,   0} };
 
-int round_period(unsigned int period)
+static int round_period(unsigned int period)
 {
 int x;
 
@@ -278,7 +275,7 @@
    return 7;
 }
 
-uchar calc_sync_xfer(unsigned int period, unsigned int offset)
+static uchar calc_sync_xfer(unsigned int period, unsigned int offset)
 {
 uchar result;
 
@@ -290,14 +287,13 @@
 
 
 
-void wd33c93_execute(struct Scsi_Host *instance);
+static void wd33c93_execute(struct Scsi_Host *instance);
 
 int wd33c93_queuecommand (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
 {
-struct WD33C93_hostdata *hostdata;
-Scsi_Cmnd *tmp;
-
-   disable_irq(cmd->host->irq);
+   struct WD33C93_hostdata *hostdata;
+   Scsi_Cmnd *tmp;
+   unsigned long flags;
 
    hostdata = (struct WD33C93_hostdata *)cmd->host->hostdata;
 
@@ -351,6 +347,9 @@
     * sense data is not lost before REQUEST_SENSE executes.
     */
 
+   save_flags(flags);
+   cli();
+
    if (!(hostdata->input_Q) || (cmd->cmnd[0] == REQUEST_SENSE)) {
       cmd->host_scribble = (uchar *)hostdata->input_Q;
       hostdata->input_Q = cmd;
@@ -370,7 +369,7 @@
 
 DB(DB_QUEUE_COMMAND,printk(")Q-%ld ",cmd->pid))
 
-   enable_irq(cmd->host->irq);
+   restore_flags(flags);
    return 0;
 }
 
@@ -381,15 +380,18 @@
  * already connected, we give up immediately. Otherwise, look through
  * the input_Q, using the first command we find that's intended
  * for a currently non-busy target/lun.
+ *
+ * wd33c93_execute() is always called with interrupts disabled or from
+ * the wd33c93_intr itself, which means that a wd33c93 interrupt
+ * cannot occur while we are in here.
  */
-void wd33c93_execute (struct Scsi_Host *instance)
+static void wd33c93_execute (struct Scsi_Host *instance)
 {
 struct WD33C93_hostdata *hostdata;
 wd33c93_regs *regp;
 Scsi_Cmnd *cmd, *prev;
 int i;
 
-   disable_irq(instance->irq);
    hostdata = (struct WD33C93_hostdata *)instance->hostdata;
    regp = hostdata->regp;
 
@@ -399,7 +401,6 @@
 
 DB(DB_EXECUTE,printk(")EX-0 "))
 
-      enable_irq(instance->irq);
       return;
       }
 
@@ -423,7 +424,6 @@
 
 DB(DB_EXECUTE,printk(")EX-1 "))
 
-      enable_irq(instance->irq);
       return;
       }
 
@@ -500,6 +500,7 @@
 #endif
 
 no:
+
    write_wd33c93(regp, WD_SOURCE_ID, ((cmd->SCp.phase)?SRCID_ER:0));
 
    write_wd33c93(regp, WD_TARGET_LUN, cmd->lun);
@@ -525,17 +526,14 @@
  * sync_xfer[] entry is initialized to the default/safe value. SS_UNSET
  * means that the parameters are undetermined as yet, and that we
  * need to send an SDTR message to this device after selection is
- * complete. We set SS_FIRST to tell the interrupt routine to do so,
- * unless we've been asked not to try synchronous transfers on this
- * target (and _all_ luns within it): In this case we set SS_SET to
- * make the defaults final.
- */
-      if (hostdata->sync_stat[cmd->target] == SS_UNSET) {
-         if (hostdata->no_sync & (1 << cmd->target))
-            hostdata->sync_stat[cmd->target] = SS_SET;
-         else
+ * complete: We set SS_FIRST to tell the interrupt routine to do so.
+ * If we've been asked not to try synchronous transfers on this
+ * target (and _all_ luns within it), we'll still send the SDTR message
+ * later, but at that time we'll negotiate for async by specifying a
+ * sync fifo depth of 0.
+ */
+      if (hostdata->sync_stat[cmd->target] == SS_UNSET)
             hostdata->sync_stat[cmd->target] = SS_FIRST;
-         }
       hostdata->state = S_SELECTING;
       write_wd33c93_count(regp,0); /* guarantee a DATA_PHASE interrupt */
       write_wd33c93_cmd(regp, WD_CMD_SEL_ATN);
@@ -600,13 +598,11 @@
     */
       
 DB(DB_EXECUTE,printk("%s%ld)EX-2 ",(cmd->SCp.phase)?"d:":"",cmd->pid))
-
-   enable_irq(instance->irq);
 }
 
 
 
-void transfer_pio(wd33c93_regs *regp, uchar *buf, int cnt,
+static void transfer_pio(wd33c93_regs *regp, uchar *buf, int cnt,
                   int data_in_dir, struct WD33C93_hostdata *hostdata)
 {
 uchar asr;
@@ -642,7 +638,7 @@
 
 
 
-void transfer_bytes(wd33c93_regs *regp, Scsi_Cmnd *cmd, int data_in_dir)
+static void transfer_bytes(wd33c93_regs *regp, Scsi_Cmnd *cmd, int data_in_dir)
 {
 struct WD33C93_hostdata *hostdata;
 unsigned long length;
@@ -725,7 +721,7 @@
 Scsi_Cmnd *patch, *cmd;
 wd33c93_regs *regp;
 uchar asr, sr, phs, id, lun, *ucp, msg;
-unsigned long length;
+unsigned long length, flags;
 
    hostdata = (struct WD33C93_hostdata *)instance->hostdata;
    regp = hostdata->regp;
@@ -734,6 +730,8 @@
    if (!(asr & ASR_INT) || (asr & ASR_BSY))
       return;
 
+   save_flags(flags);
+
 #ifdef PROC_STATISTICS
    hostdata->int_cnt++;
 #endif
@@ -776,7 +774,6 @@
       case CSR_TIMEOUT:
 DB(DB_INTR,printk("TIMEOUT"))
 
-         disable_irq(instance->irq);
          if (hostdata->state == S_RUNNING_LEVEL2)
             hostdata->connected = NULL;
          else {
@@ -789,11 +786,22 @@
          hostdata->state = S_UNCONNECTED;
          cmd->scsi_done(cmd);
 
+	 /* From esp.c:
+	  * There is a window of time within the scsi_done() path
+	  * of execution where interrupts are turned back on full
+	  * blast and left that way.  During that time we could
+	  * reconnect to a disconnected command, then we'd bomb
+	  * out below.  We could also end up executing two commands
+	  * at _once_.  ...just so you know why the restore_flags()
+	  * is here...
+	  */
+
+	 restore_flags(flags);
+
 /* We are not connected to a target - check to see if there
  * are commands waiting to be executed.
  */
 
-	 enable_irq(instance->irq);
          wd33c93_execute(instance);
          break;
 
@@ -801,7 +809,6 @@
 /* Note: this interrupt should not occur in a LEVEL2 command */
 
       case CSR_SELECT:
-	 disable_irq(instance->irq);
 
 DB(DB_INTR,printk("SELECT"))
          hostdata->connected = cmd = (Scsi_Cmnd *)hostdata->selecting;
@@ -820,13 +827,23 @@
 
             hostdata->sync_stat[cmd->target] = SS_WAITING;
 
-      /* tack on a 2nd message to ask about synchronous transfers */
+/* Tack on a 2nd message to ask about synchronous transfers. If we've
+ * been asked to do only asynchronous transfers on this device, we
+ * request a fifo depth of 0, which is equivalent to async - should
+ * solve the problems some people have had with GVP's Guru ROM.
+ */
 
             hostdata->outgoing_msg[1] = EXTENDED_MESSAGE;
             hostdata->outgoing_msg[2] = 3;
             hostdata->outgoing_msg[3] = EXTENDED_SDTR;
+            if (hostdata->no_sync & (1 << cmd->target)) {
+               hostdata->outgoing_msg[4] = hostdata->default_sx_per/4;
+               hostdata->outgoing_msg[5] = 0;
+               }
+            else {
             hostdata->outgoing_msg[4] = OPTIMUM_SX_PER/4;
             hostdata->outgoing_msg[5] = OPTIMUM_SX_OFF;
+               }
             hostdata->outgoing_len = 6;
             }
          else
@@ -891,7 +908,6 @@
       case CSR_SRV_REQ  |PHS_MESS_IN:
 DB(DB_INTR,printk("MSG_IN="))
 
-         disable_irq(instance->irq);
          msg = read_1_byte(regp);
          sr = read_wd33c93(regp, WD_SCSI_STATUS);  /* clear interrupt */
 
@@ -1034,13 +1050,13 @@
                write_wd33c93_cmd(regp,WD_CMD_NEGATE_ACK);
                hostdata->state = S_CONNECTED;
             }
+         restore_flags(flags);
          break;
 
 
 /* Note: this interrupt will occur only after a LEVEL2 command */
 
       case CSR_SEL_XFER_DONE:
-         disable_irq(instance->irq);
 
 /* Make sure that reselection is enabled at this point - it may
  * have been turned off for the command that just completed.
@@ -1065,7 +1081,7 @@
 /* We are no longer  connected to a target - check to see if
  * there are commands waiting to be executed.
  */
-	    enable_irq(instance->irq);
+	    restore_flags(flags);
             wd33c93_execute(instance);
             }
          else {
@@ -1124,8 +1140,6 @@
  * so we treat it as a normal command-complete-disconnect.
  */
 
-         disable_irq(instance->irq);
-
 /* Make sure that reselection is enabled at this point - it may
  * have been turned off for the command that just completed.
  */
@@ -1149,13 +1163,13 @@
 /* We are no longer connected to a target - check to see if
  * there are commands waiting to be executed.
  */
-         enable_irq(instance->irq);
+	 /* look above for comments on scsi_done() */
+	 restore_flags(flags);
          wd33c93_execute(instance);
          break;
 
 
       case CSR_DISC:
-         disable_irq(instance->irq);
 
 /* Make sure that reselection is enabled at this point - it may
  * have been turned off for the command that just completed.
@@ -1177,6 +1191,7 @@
                else if (cmd->SCp.Status != GOOD)
                   cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16);
                cmd->scsi_done(cmd);
+	       restore_flags(flags);
                break;
             case S_PRE_TMP_DISC:
             case S_RUNNING_LEVEL2:
@@ -1198,7 +1213,6 @@
 /* We are no longer connected to a target - check to see if
  * there are commands waiting to be executed.
  */
-         enable_irq(instance->irq);
          wd33c93_execute(instance);
          break;
 
@@ -1206,8 +1220,6 @@
       case CSR_RESEL_AM:
 DB(DB_INTR,printk("RESEL"))
 
-         disable_irq(instance->irq);
-
    /* First we have to make sure this reselection didn't */
    /* happen during Arbitration/Selection of some other device. */
    /* If yes, put losing command back on top of input_Q. */
@@ -1306,15 +1318,13 @@
          printk("--UNKNOWN INTERRUPT:%02x:%02x:%02x--",asr,sr,phs);
       }
 
-   enable_irq(instance->irq);
-
 DB(DB_INTR,printk("} "))
 
 }
 
 
 
-void reset_wd33c93(struct Scsi_Host *instance)
+static void reset_wd33c93(struct Scsi_Host *instance)
 {
 struct WD33C93_hostdata *hostdata;
 wd33c93_regs *regp;
@@ -1595,7 +1605,7 @@
 /* check_setup_strings() returns index if key found, 0 if not
  */
 
-int check_setup_strings(char *key, int *flags, int *val, char *buf)
+static int check_setup_strings(char *key, int *flags, int *val, char *buf)
 {
 int x;
 char *cp;
@@ -1724,16 +1734,17 @@
    reset_wd33c93(instance);
    sti();
 
-   printk("wd33c93-%d: chip=%s/%d no_sync=0x%x no_dma=%d\n",instance->host_no,
+   printk("wd33c93-%d: chip=%s/%d no_sync=0x%x no_dma=%d",instance->host_no,
          (hostdata->chip==C_WD33C93)?"WD33c93":
          (hostdata->chip==C_WD33C93A)?"WD33c93A":
          (hostdata->chip==C_WD33C93B)?"WD33c93B":"unknown",
          hostdata->microcode,hostdata->no_sync,hostdata->no_dma);
 #ifdef DEBUGGING_ON
-   printk("           debug_flags=0x%02x setup_strings=",hostdata->args);
+   printk(" debug_flags=0x%02x\n",hostdata->args);
 #else
-   printk("           debugging=OFF setup_strings=");
+   printk(" debugging=OFF\n");
 #endif
+   printk("           setup_strings=");
    for (i=0; i<MAX_SETUP_STRINGS; i++)
       printk("%s,",setup_strings[i]);
    printk("\n");
diff -u --recursive --new-file v2.1.35/linux/drivers/scsi/wd33c93.h linux/drivers/scsi/wd33c93.h
--- v2.1.35/linux/drivers/scsi/wd33c93.h	Fri Dec 20 01:20:02 1996
+++ linux/drivers/scsi/wd33c93.h	Thu Apr 17 13:20:47 1997
@@ -2,7 +2,7 @@
  *    wd33c93.h -  Linux device driver definitions for the
  *                 Commodore Amiga A2091/590 SCSI controller card
  *
- *    IMPORTANT: This file is for version 1.23 - 04/Nov/1996
+ *    IMPORTANT: This file is for version 1.24 - 29/Jan/1997
  *
  * Copyright (c) 1996 John Shifflett, GeoLog Consulting
  *    john@geolog.com
@@ -24,6 +24,22 @@
 #define WD33C93_H
 
 
+#define PROC_INTERFACE     /* add code for /proc/scsi/wd33c93/xxx interface */
+#ifdef  PROC_INTERFACE
+#define PROC_STATISTICS    /* add code for keeping various real time stats */
+#endif
+
+#define SYNC_DEBUG         /* extra info on sync negotiation printed */
+#define DEBUGGING_ON       /* enable command-line debugging bitmask */
+#define DEBUG_DEFAULTS 0   /* default debugging bitmask */
+
+
+#ifdef DEBUGGING_ON
+#define DB(f,a) if (hostdata->args & (f)) a;
+#else
+#define DB(f,a)
+#endif
+
 #define uchar unsigned char
 
 
@@ -231,13 +247,17 @@
     uchar            sync_stat[8];     /* status of sync negotiation per target */
     uchar            no_sync;          /* bitmask: don't do sync on these targets */
     uchar            no_dma;           /* set this flag to disable DMA */
+#ifdef PROC_INTERFACE
     uchar            proc;             /* bitmask: what's in proc output */
+#ifdef PROC_STATISTICS
     unsigned long    cmd_cnt[8];       /* # of commands issued per target */
     unsigned long    int_cnt;          /* # of interrupts serviced */
     unsigned long    pio_cnt;          /* # of pio data transfers */
     unsigned long    dma_cnt;          /* # of DMA data transfers */
     unsigned long    disc_allowed_cnt[8]; /* # of disconnects allowed per target */
     unsigned long    disc_done_cnt[8]; /* # of disconnects done per target*/
+#endif
+#endif
     };
 
 
diff -u --recursive --new-file v2.1.35/linux/fs/affs/inode.c linux/fs/affs/inode.c
--- v2.1.35/linux/fs/affs/inode.c	Fri Dec 27 02:03:24 1996
+++ linux/fs/affs/inode.c	Thu Apr 17 13:20:47 1997
@@ -26,6 +26,7 @@
 #include <linux/amigaffs.h>
 #include <linux/major.h>
 #include <linux/blkdev.h>
+#include <linux/init.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
 
@@ -987,8 +988,7 @@
 	NULL
 };
 
-int
-init_affs_fs(void)
+__initfunc(int init_affs_fs(void))
 {
 	return register_filesystem(&affs_fs_type);
 }
diff -u --recursive --new-file v2.1.35/linux/fs/autofs/init.c linux/fs/autofs/init.c
--- v2.1.35/linux/fs/autofs/init.c	Fri Apr  4 08:52:24 1997
+++ linux/fs/autofs/init.c	Tue Apr 15 22:30:38 1997
@@ -10,7 +10,6 @@
  *
  * ------------------------------------------------------------------------- */
 
-#include <linux/modversions.h>
 #include <linux/module.h>
 #include <linux/auto_fs.h>
 
diff -u --recursive --new-file v2.1.35/linux/fs/binfmt_aout.c linux/fs/binfmt_aout.c
--- v2.1.35/linux/fs/binfmt_aout.c	Sun Jan 26 02:07:24 1997
+++ linux/fs/binfmt_aout.c	Thu Apr 17 13:20:47 1997
@@ -22,6 +22,7 @@
 #include <linux/malloc.h>
 #include <linux/binfmts.h>
 #include <linux/personality.h>
+#include <linux/init.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -89,7 +90,7 @@
 #       define START_DATA(u)	(u.start_data)
 #elif defined(__sparc__)
 #       define START_DATA(u)    (u.u_tsize)
-#elif defined(__i386__)
+#elif defined(__i386__) || defined(__mc68000__)
 #       define START_DATA(u)	(u.u_tsize << PAGE_SHIFT)
 #endif
 #ifdef __sparc__
@@ -555,7 +556,8 @@
 }
 
 
-int init_aout_binfmt(void) {
+__initfunc(int init_aout_binfmt(void))
+{
 	return register_binfmt(&aout_format);
 }
 
diff -u --recursive --new-file v2.1.35/linux/fs/binfmt_elf.c linux/fs/binfmt_elf.c
--- v2.1.35/linux/fs/binfmt_elf.c	Sun Jan 26 02:07:30 1997
+++ linux/fs/binfmt_elf.c	Thu Apr 17 13:20:47 1997
@@ -27,6 +27,7 @@
 #include <linux/shm.h>
 #include <linux/personality.h>
 #include <linux/elfcore.h>
+#include <linux/init.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -1124,7 +1125,7 @@
 #else
 	if (sizeof(elf_gregset_t) != sizeof(struct pt_regs))
 	{
-		printk("sizeof(elf_gregset_t) (%d) != sizeof(struct pt_regs) (%d)\n",
+		printk("sizeof(elf_gregset_t) (%ld) != sizeof(struct pt_regs) (%ld)\n",
 			sizeof(elf_gregset_t), sizeof(struct pt_regs));
 	}
 	else
@@ -1276,7 +1277,7 @@
 }
 #endif		/* USE_ELF_CORE_DUMP */
 
-int init_elf_binfmt(void)
+__initfunc(int init_elf_binfmt(void))
 {
 	return register_binfmt(&elf_format);
 }
diff -u --recursive --new-file v2.1.35/linux/fs/binfmt_em86.c linux/fs/binfmt_em86.c
--- v2.1.35/linux/fs/binfmt_em86.c	Mon Apr 14 16:28:17 1997
+++ linux/fs/binfmt_em86.c	Tue Apr 22 22:42:51 1997
@@ -14,6 +14,8 @@
 #include <linux/malloc.h>
 #include <linux/binfmts.h>
 #include <linux/elf.h>
+#include <linux/init.h>
+
 
 #define EM86_INTERP	"/usr/bin/em86"
 #define EM86_I_NAME	"em86"
@@ -100,11 +102,12 @@
 #ifndef MODULE
 	NULL, 0, load_em86, NULL, NULL
 #else
-	NULL, &mod_use_count_, load_em86, NULL, NULL
+	NULL, &__this_module, load_em86, NULL, NULL
 #endif
 };
 
-int init_em86_binfmt(void) {
+__initfunc(int init_em86_binfmt(void))
+{
 	return register_binfmt(&em86_format);
 }
 
diff -u --recursive --new-file v2.1.35/linux/fs/binfmt_java.c linux/fs/binfmt_java.c
--- v2.1.35/linux/fs/binfmt_java.c	Sun Jan 26 02:07:30 1997
+++ linux/fs/binfmt_java.c	Thu Apr 17 13:20:47 1997
@@ -13,6 +13,7 @@
 #include <linux/stat.h>
 #include <linux/malloc.h>
 #include <linux/binfmts.h>
+#include <linux/init.h>
 
 #define _PATH_JAVA	"/usr/bin/java"
 #define _PATH_APPLET	"/usr/bin/appletviewer"
@@ -165,7 +166,8 @@
 #endif
 };
 
-int init_java_binfmt(void) {
+__initfunc(int init_java_binfmt(void))
+{
 	register_binfmt(&java_format);
 	return register_binfmt(&applet_format);
 }
diff -u --recursive --new-file v2.1.35/linux/fs/binfmt_script.c linux/fs/binfmt_script.c
--- v2.1.35/linux/fs/binfmt_script.c	Tue Jan 28 00:02:45 1997
+++ linux/fs/binfmt_script.c	Thu Apr 17 13:20:47 1997
@@ -10,6 +10,7 @@
 #include <linux/stat.h>
 #include <linux/malloc.h>
 #include <linux/binfmts.h>
+#include <linux/init.h>
 
 static int do_load_script(struct linux_binprm *bprm,struct pt_regs *regs)
 {
@@ -103,7 +104,8 @@
 #endif
 };
 
-int init_script_binfmt(void) {
+__initfunc(int init_script_binfmt(void))
+{
 	return register_binfmt(&script_format);
 }
 
diff -u --recursive --new-file v2.1.35/linux/fs/buffer.c linux/fs/buffer.c
--- v2.1.35/linux/fs/buffer.c	Mon Apr 14 16:28:17 1997
+++ linux/fs/buffer.c	Tue Apr 22 23:02:26 1997
@@ -14,7 +14,12 @@
 /* Start bdflush() with kernel_thread not syscall - Paul Gortmaker, 12/95 */
 
 /* Removed a lot of unnecessary code and simplified things now that
-   the buffer cache isn't our primary cache - Andrew Tridgell 12/96 */
+ * the buffer cache isn't our primary cache - Andrew Tridgell 12/96
+ */
+
+/* Speed up hash, lru, and free list operations.  Use gfp() for allocating
+ * hash table, use SLAB cache for buffer heads. -DaveM
+ */
 
 #include <linux/sched.h>
 #include <linux/kernel.h>
@@ -23,6 +28,7 @@
 #include <linux/locks.h>
 #include <linux/errno.h>
 #include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/pagemap.h>
 #include <linux/swap.h>
 #include <linux/swapctl.h>
@@ -45,6 +51,7 @@
 #define MAX_UNUSED_BUFFERS 30 /* don't ever have more than this number of 
 				 unused buffer heads */
 #define HASH_PAGES         4  /* number of pages to use for the hash table */
+#define HASH_PAGES_ORDER   2
 #define NR_HASH (HASH_PAGES*PAGE_SIZE/sizeof(struct buffer_head *))
 #define HASH_MASK (NR_HASH-1)
 
@@ -54,6 +61,8 @@
 static struct buffer_head * lru_list[NR_LIST] = {NULL, };
 static struct buffer_head * free_list[NR_SIZES] = {NULL, };
 
+static kmem_cache_t *bh_cachep;
+
 static struct buffer_head * unused_list = NULL;
 static struct buffer_head * reuse_list = NULL;
 static struct wait_queue * buffer_wait = NULL;
@@ -65,7 +74,7 @@
 static int refilled = 0;       /* Set NZ when a buffer freelist is refilled 
 				  this is used by the loop device */
 
-/* this is used by some architectures to estimate available memory */
+/* This is used by some architectures to estimate available memory. */
 int buffermem = 0;
 
 /* Here is the parameter block for the bdflush process. If you add or
@@ -76,8 +85,9 @@
 
 #define N_PARAM 9
 
-/* the dummy values in this structure are left in there for compatibility
-   with old programs that play with the /proc entries */
+/* The dummy values in this structure are left in there for compatibility
+ * with old programs that play with the /proc entries.
+ */
 union bdflush_param{
 	struct {
 		int nfract;  /* Percentage of buffer cache dirty to 
@@ -131,29 +141,31 @@
 }
 
 /* Call sync_buffers with wait!=0 to ensure that the call does not
-   return until all buffer writes have completed.  Sync() may return
-   before the writes have finished; fsync() may not. */
-
+ * return until all buffer writes have completed.  Sync() may return
+ * before the writes have finished; fsync() may not.
+ */
 
 /* Godamity-damn.  Some buffers (bitmaps for filesystems)
-   spontaneously dirty themselves without ever brelse being called.
-   We will ultimately want to put these in a separate list, but for
-   now we search all of the lists for dirty buffers */
-
+ * spontaneously dirty themselves without ever brelse being called.
+ * We will ultimately want to put these in a separate list, but for
+ * now we search all of the lists for dirty buffers.
+ */
 static int sync_buffers(kdev_t dev, int wait)
 {
 	int i, retry, pass = 0, err = 0;
 	struct buffer_head * bh, *next;
 
 	/* One pass for no-wait, three for wait:
-	   0) write out all dirty, unlocked buffers;
-	   1) write out all dirty buffers, waiting if locked;
-	   2) wait for completion by waiting for all buffers to unlock. */
+	 * 0) write out all dirty, unlocked buffers;
+	 * 1) write out all dirty buffers, waiting if locked;
+	 * 2) wait for completion by waiting for all buffers to unlock.
+	 */
 	do {
 		retry = 0;
 repeat:
-	/* We search all lists as a failsafe mechanism, not because we expect
-	   there to be dirty buffers on any of the other lists. */
+		/* We search all lists as a failsafe mechanism, not because we expect
+		 * there to be dirty buffers on any of the other lists.
+		 */
 		bh = lru_list[BUF_DIRTY];
 		if (!bh)
 			goto repeat2;
@@ -167,7 +179,8 @@
 				continue;
 			if (buffer_locked(bh)) {
 				/* Buffer is locked; skip it unless wait is
-				   requested AND pass > 0. */
+				 * requested AND pass > 0.
+				 */
 				if (!wait || !pass) {
 					retry = 1;
 					continue;
@@ -175,18 +188,27 @@
 				wait_on_buffer (bh);
 				goto repeat;
 			}
+
 			/* If an unlocked buffer is not uptodate, there has
-			    been an IO error. Skip it. */
+			 * been an IO error. Skip it.
+			 */
 			if (wait && buffer_req(bh) && !buffer_locked(bh) &&
 			    !buffer_dirty(bh) && !buffer_uptodate(bh)) {
 				err = 1;
 				continue;
 			}
+
 			/* Don't write clean buffers.  Don't write ANY buffers
-			   on the third pass. */
+			 * on the third pass.
+			 */
 			if (!buffer_dirty(bh) || pass >= 2)
 				continue;
-			/* don't bother about locked buffers */
+
+			/* Don't bother about locked buffers.
+			 *
+			 * XXX We checked if it was locked above and there is no
+			 * XXX way we could have slept in between. -DaveM
+			 */
 			if (buffer_locked(bh))
 				continue;
 			bh->b_count++;
@@ -212,7 +234,8 @@
 				continue;
 			if (buffer_locked(bh)) {
 				/* Buffer is locked; skip it unless wait is
-				   requested AND pass > 0. */
+				 * requested AND pass > 0.
+				 */
 				if (!wait || !pass) {
 					retry = 1;
 					continue;
@@ -222,10 +245,11 @@
 			}
 		}
 
-	/* If we are waiting for the sync to succeed, and if any dirty
-	   blocks were written, then repeat; on the second pass, only
-	   wait for buffers being written (do not pass to write any
-	   more buffers on the second pass). */
+		/* If we are waiting for the sync to succeed, and if any dirty
+		 * blocks were written, then repeat; on the second pass, only
+		 * wait for buffers being written (do not pass to write any
+		 * more buffers on the second pass).
+		 */
 	} while (wait && retry && ++pass<=2);
 	return err;
 }
@@ -330,13 +354,12 @@
 
 static inline void remove_from_hash_queue(struct buffer_head * bh)
 {
-	if (bh->b_next)
-		bh->b_next->b_prev = bh->b_prev;
-	if (bh->b_prev)
-		bh->b_prev->b_next = bh->b_next;
-	if (hash(bh->b_dev,bh->b_blocknr) == bh)
-		hash(bh->b_dev,bh->b_blocknr) = bh->b_next;
-	bh->b_next = bh->b_prev = NULL;
+	if (bh->b_pprev) {
+		if(bh->b_next)
+			bh->b_next->b_pprev = bh->b_pprev;
+		*bh->b_pprev = bh->b_next;
+		bh->b_pprev = NULL;
+	}
 }
 
 static inline void remove_from_lru_list(struct buffer_head * bh)
@@ -389,46 +412,49 @@
 
 static inline void put_last_lru(struct buffer_head * bh)
 {
-	if (!bh)
-		return;
-	if (bh == lru_list[bh->b_list]) {
-		lru_list[bh->b_list] = bh->b_next_free;
-		return;
-	}
-	if(bh->b_dev == B_FREE)
-		panic("Wrong block for lru list");
-	remove_from_lru_list(bh);
-/* add to back of free list */
+	if (bh) {
+		struct buffer_head **bhp = &lru_list[bh->b_list];
 
-	if(!lru_list[bh->b_list]) {
-		lru_list[bh->b_list] = bh;
-		lru_list[bh->b_list]->b_prev_free = bh;
-	}
+		if (bh == *bhp) {
+			*bhp = bh->b_next_free;
+			return;
+		}
+
+		if(bh->b_dev == B_FREE)
+			panic("Wrong block for lru list");
+
+		/* Add to back of free list. */
+		remove_from_lru_list(bh);
+		if(!*bhp) {
+			*bhp = bh;
+			(*bhp)->b_prev_free = bh;
+		}
 
-	bh->b_next_free = lru_list[bh->b_list];
-	bh->b_prev_free = lru_list[bh->b_list]->b_prev_free;
-	lru_list[bh->b_list]->b_prev_free->b_next_free = bh;
-	lru_list[bh->b_list]->b_prev_free = bh;
+		bh->b_next_free = *bhp;
+		bh->b_prev_free = (*bhp)->b_prev_free;
+		(*bhp)->b_prev_free->b_next_free = bh;
+		(*bhp)->b_prev_free = bh;
+	}
 }
 
 static inline void put_last_free(struct buffer_head * bh)
 {
-	int isize;
-	if (!bh)
-		return;
+	if (bh) {
+		struct buffer_head **bhp = &free_list[BUFSIZE_INDEX(bh->b_size)];
 
-	isize = BUFSIZE_INDEX(bh->b_size);	
-	bh->b_dev = B_FREE;  /* So it is obvious we are on the free list */
-	/* add to back of free list */
-	if(!free_list[isize]) {
-		free_list[isize] = bh;
-		bh->b_prev_free = bh;
-	}
+		bh->b_dev = B_FREE;  /* So it is obvious we are on the free list. */
 
-	bh->b_next_free = free_list[isize];
-	bh->b_prev_free = free_list[isize]->b_prev_free;
-	free_list[isize]->b_prev_free->b_next_free = bh;
-	free_list[isize]->b_prev_free = bh;
+		/* Add to back of free list. */
+		if(!*bhp) {
+			*bhp = bh;
+			bh->b_prev_free = bh;
+		}
+
+		bh->b_next_free = *bhp;
+		bh->b_prev_free = (*bhp)->b_prev_free;
+		(*bhp)->b_prev_free->b_next_free = bh;
+		(*bhp)->b_prev_free = bh;
+	}
 }
 
 static inline void insert_into_queues(struct buffer_head * bh)
@@ -436,28 +462,34 @@
 	/* put at end of free list */
 	if(bh->b_dev == B_FREE) {
 		put_last_free(bh);
-		return;
-	}
-	if(!lru_list[bh->b_list]) {
-		lru_list[bh->b_list] = bh;
-		bh->b_prev_free = bh;
-	}
+	} else {
+		struct buffer_head **bhp = &lru_list[bh->b_list];
 
-	if (bh->b_next_free) panic("VFS: buffer LRU pointers corrupted");
-	bh->b_next_free = lru_list[bh->b_list];
-	bh->b_prev_free = lru_list[bh->b_list]->b_prev_free;
-	lru_list[bh->b_list]->b_prev_free->b_next_free = bh;
-	lru_list[bh->b_list]->b_prev_free = bh;
-	nr_buffers_type[bh->b_list]++;
-/* put the buffer in new hash-queue if it has a device */
-	bh->b_prev = NULL;
-	bh->b_next = NULL;
-	if (!(bh->b_dev))
-		return;
-	bh->b_next = hash(bh->b_dev,bh->b_blocknr);
-	hash(bh->b_dev,bh->b_blocknr) = bh;
-	if (bh->b_next)
-		bh->b_next->b_prev = bh;
+		if(!*bhp) {
+			*bhp = bh;
+			bh->b_prev_free = bh;
+		}
+
+		if (bh->b_next_free)
+			panic("VFS: buffer LRU pointers corrupted");
+
+		bh->b_next_free = *bhp;
+		bh->b_prev_free = (*bhp)->b_prev_free;
+		(*bhp)->b_prev_free->b_next_free = bh;
+		(*bhp)->b_prev_free = bh;
+
+		nr_buffers_type[bh->b_list]++;
+
+		/* Put the buffer in new hash-queue if it has a device. */
+		if (bh->b_dev) {
+			struct buffer_head **bhp = &hash(bh->b_dev, bh->b_blocknr);
+			if((bh->b_next = *bhp) != NULL)
+				(*bhp)->b_pprev = &bh->b_next;
+			*bhp = bh;
+			bh->b_pprev = bhp;	/* Exists in bh hashes. */
+		} else
+			bh->b_pprev = NULL;	/* Not in bh hashes. */
+	}
 }
 
 static inline struct buffer_head * find_buffer(kdev_t dev, int block, int size)
@@ -465,14 +497,14 @@
 	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_blocknr == block && tmp->b_dev == dev) {
 			if (tmp->b_size == size)
 				return tmp;
-			else {
-				printk("VFS: Wrong blocksize on device %s\n",
-					kdevname(dev));
-				return NULL;
-			}
+
+			printk("VFS: Wrong blocksize on device %s\n",
+			       kdevname(dev));
+			return NULL;
+		}
 	return NULL;
 }
 
@@ -492,8 +524,9 @@
 			return NULL;
 		bh->b_count++;
 		wait_on_buffer(bh);
-		if (bh->b_dev == dev && bh->b_blocknr == block
-					     && bh->b_size == size)
+		if (bh->b_dev == dev		&&
+		    bh->b_blocknr == block	&&
+		    bh->b_size == size)
 			return bh;
 		bh->b_count--;
 	}
@@ -501,27 +534,21 @@
 
 unsigned int get_hardblocksize(kdev_t dev)
 {
-  int blksize = 0;
-
-  /*
-   * Get the hard sector size for the given device.  If we don't know
-   * what it is, return 0.
-   */
-
-  if (hardsect_size[MAJOR(dev)] != NULL)
-    {
-      blksize = hardsect_size[MAJOR(dev)][MINOR(dev)];
-      if (blksize != 0)
-	{
-	  return blksize;
+	/*
+	 * Get the hard sector size for the given device.  If we don't know
+	 * what it is, return 0.
+	 */
+	if (hardsect_size[MAJOR(dev)] != NULL) {
+		int blksize = hardsect_size[MAJOR(dev)][MINOR(dev)];
+		if (blksize != 0)
+			return blksize;
 	}
-  }
 
-  /*
-   * We don't know what the hardware sector size for this device is.
-   * Return 0 indicating that we don't know.
-   */
-  return 0;
+	/*
+	 * We don't know what the hardware sector size for this device is.
+	 * Return 0 indicating that we don't know.
+	 */
+	return 0;
 }
 
 void set_blocksize(kdev_t dev, int size)
@@ -550,13 +577,15 @@
 	sync_buffers(dev, 2);
 	blksize_size[MAJOR(dev)][MINOR(dev)] = size;
 
-  /* We need to be quite careful how we do this - we are moving entries
-     around on the free list, and we can get in a loop if we are not careful.*/
-
+	/* We need to be quite careful how we do this - we are moving entries
+	 * around on the free list, and we can get in a loop if we are not careful.
+	 */
 	for(nlist = 0; nlist < NR_LIST; nlist++) {
 		bh = lru_list[nlist];
 		for (i = nr_buffers_type[nlist]*2 ; --i > 0 ; bh = bhnext) {
-			if(!bh) break;
+			if(!bh)
+				break;
+
 			bhnext = bh->b_next_free; 
 			if (bh->b_dev != dev)
 				 continue;
@@ -575,12 +604,12 @@
 	}
 }
 
-
-/* check if a buffer is OK to be reclaimed */
+/* Check if a buffer is OK to be reclaimed. */
 static inline int can_reclaim(struct buffer_head *bh, int size)
 {
-	if (bh->b_count || 
-	    buffer_protected(bh) || buffer_locked(bh))
+	if (bh->b_count			|| 
+	    buffer_protected(bh)	||
+	    buffer_locked(bh))
 		return 0;
 			 
 	if (atomic_read(&mem_map[MAP_NR((unsigned long) bh->b_data)].count) != 1 ||
@@ -595,8 +624,9 @@
 	return 1;
 }
 
-/* find a candidate buffer to be reclaimed */
-static struct buffer_head *find_candidate(struct buffer_head *list,int *list_len,int size)
+/* Find a candidate buffer to be reclaimed. */
+static struct buffer_head *find_candidate(struct buffer_head *list,
+					  int *list_len, int size)
 {
 	struct buffer_head *bh;
 	
@@ -604,19 +634,23 @@
 	     bh && (*list_len) > 0; 
 	     bh = bh->b_next_free, (*list_len)--) {
 		if (size != bh->b_size) {
-			/* this provides a mechanism for freeing blocks
-			   of other sizes, this is necessary now that we
-			   no longer have the lav code. */
+			/* This provides a mechanism for freeing blocks
+			 * of other sizes, this is necessary now that we
+			 * no longer have the lav code.
+			 */
 			try_to_free_buffer(bh,&bh,1);
+			if (!bh)
+				break;
 			continue;
 		}
 
 		if (buffer_locked(bh) && 
 		    (bh->b_list == BUF_LOCKED || bh->b_list == BUF_LOCKED1)) {
 			/* Buffers are written in the order they are placed 
-			   on the locked list. If we encounter a locked
-			   buffer here, this means that the rest of them
-			   are also locked */
+			 * on the locked list. If we encounter a locked
+			 * buffer here, this means that the rest of them
+			 * are also locked.
+			 */
 			(*list_len) = 0;
 			return NULL;
 		}
@@ -639,74 +673,81 @@
 
 	refilled = 1;
 	/* If there are too many dirty buffers, we wake up the update process
-	   now so as to ensure that there are still clean buffers available
-	   for user processes to use (and dirty) */
+	 * now so as to ensure that there are still clean buffers available
+	 * for user processes to use (and dirty).
+	 */
 	
-	/* We are going to try to locate this much memory */
-	needed =bdf_prm.b_un.nrefill * size;  
+	/* We are going to try to locate this much memory. */
+	needed = bdf_prm.b_un.nrefill * size;  
 
-	while (nr_free_pages > min_free_pages*2 && needed > 0 &&
-	       grow_buffers(GFP_BUFFER, size)) {
+	while ((nr_free_pages > min_free_pages*2)	&&
+	       (needed > 0)				&&
+	       grow_buffers(GFP_BUFFER, size))
 		needed -= PAGE_SIZE;
-	}
 
 repeat:
 	/* OK, we cannot grow the buffer cache, now try to get some
-	   from the lru list */
-
-	/* First set the candidate pointers to usable buffers.  This
-	   should be quick nearly all of the time. */
+	 * from the lru list.
+	 *
+	 * First set the candidate pointers to usable buffers.  This
+	 * should be quick nearly all of the time.
+	 */
 
-	if(needed <= 0) return;
+	if(needed <= 0)
+		return;
 
-	for(i=0; i<BUF_DIRTY; i++){
+	for(i=0; i<BUF_DIRTY; i++) {
 		buffers[i] = nr_buffers_type[i];
 		candidate[i] = find_candidate(lru_list[i], &buffers[i], size);
 	}
 	
-	/* Now see which candidate wins the election */
+	/* Now see which candidate wins the election. */
 	
 	winner = best_time = UINT_MAX;	
-	for(i=0; i<BUF_DIRTY; i++){
-		if(!candidate[i]) continue;
-		if(candidate[i]->b_lru_time < best_time){
+	for(i=0; i<BUF_DIRTY; i++) {
+		if(!candidate[i])
+			continue;
+		if(candidate[i]->b_lru_time < best_time) {
 			best_time = candidate[i]->b_lru_time;
 			winner = i;
 		}
 	}
 	
-	/* If we have a winner, use it, and then get a new candidate from that list */
+	/* If we have a winner, use it, and then get a new candidate from that list. */
 	if(winner != UINT_MAX) {
 		i = winner;
 		while (needed>0 && (bh=candidate[i])) {
 			candidate[i] = bh->b_next_free;
-			if(candidate[i] == bh) candidate[i] = NULL;  /* Got last one */		
+			if(candidate[i] == bh)
+				candidate[i] = NULL;  /* Got last one */		
 			remove_from_queues(bh);
 			bh->b_dev = B_FREE;
 			put_last_free(bh);
 			needed -= bh->b_size;
 			buffers[i]--;
-			if(buffers[i] == 0) candidate[i] = NULL;
+			if(buffers[i] == 0)
+				candidate[i] = NULL;
 		
 			if (candidate[i] && !can_reclaim(candidate[i],size))
-				candidate[i] = find_candidate(candidate[i],&buffers[i], size);
+				candidate[i] = find_candidate(candidate[i],
+							      &buffers[i], size);
 		}
 		if (needed >= 0)
 			goto repeat;
 	}
 	
-	if(needed <= 0) return;
+	if(needed <= 0)
+		return;
 	
 	/* Too bad, that was not enough. Try a little harder to grow some. */
-	
 	if (nr_free_pages > min_free_pages + 5) {
 		if (grow_buffers(GFP_BUFFER, size)) {
 			needed -= PAGE_SIZE;
 			goto repeat;
-		};
+		}
 	}
 	
-	/* and repeat until we find something good */
+	/* And repeat until we find something good. */
 	if (!grow_buffers(GFP_ATOMIC, size))
 		wakeup_bdflush(1);
 	needed -= PAGE_SIZE;
@@ -729,8 +770,9 @@
 	int isize = BUFSIZE_INDEX(size);
 
 	/* If there are too many dirty buffers, we wake up the update process
-	   now so as to ensure that there are still clean buffers available
-	   for user processes to use (and dirty) */
+	 * now so as to ensure that there are still clean buffers available
+	 * for user processes to use (and dirty).
+	 */
 repeat:
 	bh = get_hash_table(dev, block, size);
 	if (bh) {
@@ -743,9 +785,8 @@
 		return bh;
 	}
 
-	while(!free_list[isize]) {
+	while(!free_list[isize])
 		refill_freelist(size);
-	}
 	
 	if (find_buffer(dev,block,size))
 		 goto repeat;
@@ -753,8 +794,9 @@
 	bh = free_list[isize];
 	remove_from_free_list(bh);
 
-/* OK, FINALLY we know that this buffer is the only one of its kind, */
-/* and that it's unused (b_count=0), unlocked (buffer_locked=0), and clean */
+	/* OK, FINALLY we know that this buffer is the only one of its kind,
+	 * and that it's unused (b_count=0), unlocked (buffer_locked=0), and clean.
+	 */
 	bh->b_count=1;
 	bh->b_flushtime=0;
 	bh->b_state=(1<<BH_Touched);
@@ -769,7 +811,7 @@
 	int newtime;
 
 	if (buffer_dirty(buf)) {
-		/* Move buffer to dirty list if jiffies is clear */
+		/* Move buffer to dirty list if jiffies is clear. */
 		newtime = jiffies + (flag ? bdf_prm.b_un.age_super : 
 				     bdf_prm.b_un.age_buffer);
 		if(!buf->b_flushtime || buf->b_flushtime > newtime)
@@ -798,8 +840,9 @@
 		dispose = BUF_LOCKED;
 	else
 		dispose = BUF_CLEAN;
-	if(dispose == BUF_CLEAN) buf->b_lru_time = jiffies;
-	if(dispose != buf->b_list)  {
+	if(dispose == BUF_CLEAN)
+		buf->b_lru_time = jiffies;
+	if(dispose != buf->b_list) {
 		if(dispose == BUF_DIRTY)
 			 buf->b_lru_time = jiffies;
 		if(dispose == BUF_LOCKED && 
@@ -809,16 +852,21 @@
 		buf->b_list = dispose;
 		insert_into_queues(buf);
 		if (dispose == BUF_DIRTY) {
-		/* This buffer is dirty, maybe we need to start flushing. */
-		/* If too high a percentage of the buffers are dirty... */
-		if (nr_buffers_type[BUF_DIRTY] > nr_buffers * bdf_prm.b_un.nfract/100)
-			 wakeup_bdflush(0);
-		/* If this is a loop device, and
-		 * more than half of the buffers are dirty... */ 
-		/* (Prevents no-free-buffers deadlock with loop device.) */
-		if (MAJOR(buf->b_dev) == LOOP_MAJOR &&
-		    nr_buffers_type[BUF_DIRTY]*2>nr_buffers)
-			wakeup_bdflush(1);
+			int too_many = (nr_buffers * bdf_prm.b_un.nfract/100);
+
+			/* This buffer is dirty, maybe we need to start flushing.
+			 * If too high a percentage of the buffers are dirty...
+			 */
+			if (nr_buffers_type[BUF_DIRTY] > too_many)
+				wakeup_bdflush(0);
+
+			/* If this is a loop device, and
+			 * more than half of the buffers are dirty...
+			 * (Prevents no-free-buffers deadlock with loop device.)
+			 */
+			if (MAJOR(buf->b_dev) == LOOP_MAJOR &&
+			    nr_buffers_type[BUF_DIRTY]*2>nr_buffers)
+				wakeup_bdflush(1);
 		}
 	}
 }
@@ -830,7 +878,7 @@
 {
 	wait_on_buffer(buf);
 
-	/* If dirty, mark the time this buffer should be written back */
+	/* If dirty, mark the time this buffer should be written back. */
 	set_writetime(buf, 0);
 	refile_buffer(buf);
 
@@ -929,13 +977,13 @@
 		else bhlist[j++] = bh;
 	}
 
-	/* Request the read for these buffers, and then release them */
+	/* Request the read for these buffers, and then release them. */
 	if (j>1)  
 		ll_rw_block(READA, (j-1), bhlist+1); 
 	for(i=1; i<j; i++)
 		brelse(bhlist[i]);
 
-	/* Wait for this buffer, and then continue on */
+	/* Wait for this buffer, and then continue on. */
 	bh = bhlist[0];
 	wait_on_buffer(bh);
 	if (buffer_uptodate(bh))
@@ -948,7 +996,7 @@
 {
 	if (nr_unused_buffer_heads >= MAX_UNUSED_BUFFERS) {
 		nr_buffer_heads--;
-		kfree(bh);
+		kmem_cache_free(bh_cachep, bh);
 		return;
 	}
 	memset(bh,0,sizeof(*bh));
@@ -963,23 +1011,17 @@
 	struct buffer_head * bh;
 
 	while (!unused_list) {
-		/*
-		 * This is critical.  We can't swap out pages to get
+		/* This is critical.  We can't swap out pages to get
 		 * more buffer heads, because the swap-out may need
-		 * more buffer-heads itself.  Thus GFP_ATOMIC.
+		 * more buffer-heads itself.  Thus SLAB_ATOMIC.
 		 */
-		/* we now use kmalloc() here instead of gfp as we want
-                   to be able to easily release buffer heads - they
-                   took up quite a bit of memory (tridge) */
-		bh = (struct buffer_head *) kmalloc(sizeof(*bh),GFP_ATOMIC);
-		if (bh) {
+		if((bh = kmem_cache_alloc(bh_cachep, SLAB_ATOMIC)) != NULL) {
 			put_unused_buffer_head(bh);
 			nr_buffer_heads++;
 			return;
 		}
 
-		/*
-		 * Uhhuh. We're _really_ low on memory. Now we just
+		/* Uhhuh. We're _really_ low on memory. Now we just
 		 * wait for old buffer heads to become free due to
 		 * finishing IO..
 		 */
@@ -1414,12 +1456,11 @@
 		p = tmp;
 		tmp = tmp->b_this_page;
 		nr_buffers--;
-		if (p == *bhp)
-		  {
-		    *bhp = p->b_prev_free;
-		    if (p == *bhp) /* Was this the last in the list? */
-		      *bhp = NULL;
-		  }
+		if (p == *bhp) {
+			*bhp = p->b_prev_free;
+			if (p == *bhp) /* Was this the last in the list? */
+				*bhp = NULL;
+		}
 		remove_from_queues(p);
 		put_unused_buffer_head(p);
 	} while (tmp != bh);
@@ -1472,14 +1513,24 @@
 
 /*
  * allocate the hash table and init the free list
+ * Use gfp() for the hash table to decrease TLB misses, use
+ * SLAB cache for buffer heads.
  */
 void buffer_init(void)
 {
-	hash_table = (struct buffer_head **)vmalloc(NR_HASH*sizeof(struct buffer_head *));
+	hash_table = (struct buffer_head **)
+		__get_free_pages(GFP_ATOMIC, HASH_PAGES_ORDER, 0);
 	if (!hash_table)
 		panic("Failed to allocate buffer hash table\n");
 	memset(hash_table,0,NR_HASH*sizeof(struct buffer_head *));
 
+	bh_cachep = kmem_cache_create("buffer_head",
+				      sizeof(struct buffer_head),
+				      sizeof(unsigned long) * 4,
+				      SLAB_HWCACHE_ALIGN, NULL, NULL);
+	if(!bh_cachep)
+		panic("Cannot create buffer head SLAB cache\n");
+
 	lru_list[BUF_CLEAN] = 0;
 	grow_buffers(GFP_KERNEL, BLOCK_SIZE);
 }
@@ -1745,21 +1796,3 @@
 		}
 	}
 }
-
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-indent-level: 8
- * c-brace-imaginary-offset: 0
- * c-brace-offset: -8
- * c-argdecl-indent: 8
- * c-label-offset: -8
- * c-continued-statement-offset: 8
- * c-continued-brace-offset: 0
- * End:
- */
diff -u --recursive --new-file v2.1.35/linux/fs/dcache.c linux/fs/dcache.c
--- v2.1.35/linux/fs/dcache.c	Thu Feb 27 10:57:31 1997
+++ linux/fs/dcache.c	Wed Apr 23 10:54:35 1997
@@ -4,6 +4,8 @@
  *  (C) Copyright 1994 Linus Torvalds
  */
 
+/* Speeded up searches a bit and threaded the mess. -DaveM */
+
 /*
  * The directory cache is a "two-level" cache, each level doing LRU on
  * its entries.  Adding new entries puts them at the end of the LRU
@@ -22,6 +24,9 @@
 #include <linux/string.h>
 
 #include <asm/unaligned.h>
+#include <asm/spinlock.h>
+
+spinlock_t dcache_lock = SPIN_LOCK_UNLOCKED;
 
 /*
  * Don't bother caching long names.. They just take up space in the cache, and
@@ -30,18 +35,14 @@
  */
 #define DCACHE_NAME_LEN	15
 #define DCACHE_SIZE 1024
-#define DCACHE_HASH_QUEUES 256
-
-struct hash_list {
-	struct dir_cache_entry * next;
-	struct dir_cache_entry * prev;
-};
+#define DCACHE_HASH_QUEUES 256	/* keep this a pow2 */
 
 /*
  * The dir_cache_entry must be in this order: we do ugly things with the pointers
  */
 struct dir_cache_entry {
-	struct hash_list h;
+	struct dir_cache_entry *next;
+	struct dir_cache_entry **pprev;
 	kdev_t dc_dev;
 	unsigned long dir;
 	unsigned long version;
@@ -68,13 +69,34 @@
 static struct dir_cache_entry * level1_head;
 static struct dir_cache_entry * level2_head;
 
+/* The hash queues are layed out in a slightly different manner. */
+static struct dir_cache_entry *hash_table[DCACHE_HASH_QUEUES];
+
+#define hash_fn(dev,dir,namehash) \
+	((HASHDEV(dev) ^ (dir) ^ (namehash)) & (DCACHE_HASH_QUEUES - 1))
+
 /*
- * The hash-queues are also doubly-linked circular lists, but the head is
- * itself on the doubly-linked list, not just a pointer to the first entry.
+ * Stupid name"hash" algorithm. Write something better if you want to,
+ * but I doubt it matters that much.
  */
-#define hash_fn(dev,dir,namehash) ((HASHDEV(dev) ^ (dir) ^ (namehash)) % DCACHE_HASH_QUEUES)
+static unsigned long namehash(const char * name, int len)
+{
+	unsigned long hash = 0;
 
-static struct hash_list hash_table[DCACHE_HASH_QUEUES];
+	while ((len -= sizeof(unsigned long)) > 0) {
+		hash += get_unaligned((unsigned long *)name);
+		name += sizeof(unsigned long);
+	}
+	return hash +
+		(get_unaligned((unsigned long *)name) &
+		 ~(~0UL << ((len + sizeof(unsigned long)) << 3)));
+}
+
+static inline struct dir_cache_entry **get_hlist(struct inode *dir,
+						 const char *name, int len)
+{
+	return hash_table + hash_fn(dir->i_dev, dir->i_ino, namehash(name, len));
+}
 
 static inline void remove_lru(struct dir_cache_entry * de)
 {
@@ -106,78 +128,50 @@
 }
 
 /*
- * Stupid name"hash" algorithm. Write something better if you want to,
- * but I doubt it matters that much
- */
-static inline unsigned long namehash(const char * name, int len)
-{
-	if (len >= sizeof(unsigned long))
-		return len +
-			get_unaligned((unsigned long *) name) +
-			get_unaligned((unsigned long *) (name + len - sizeof(unsigned long)));
-	return len +
-		((const unsigned char *) name)[0]+
-		((const unsigned char *) name)[len-1];
-}
-
-/*
  * Hash queue manipulation. Look out for the casts..
+ *
+ * What casts? 8-) -DaveM
  */
 static inline void remove_hash(struct dir_cache_entry * de)
 {
-	struct dir_cache_entry * next = de->h.next;
-
-	if (next) {
-		struct dir_cache_entry * prev = de->h.prev;
-		next->h.prev = prev;
-		prev->h.next = next;
-		de->h.next = NULL;
+	if(de->pprev) {
+		if(de->next)
+			de->next->pprev = de->pprev;
+		*de->pprev = de->next;
+		de->pprev = NULL;
 	}
 }
 
-static inline void add_hash(struct dir_cache_entry * de, struct hash_list * hash)
+static inline void add_hash(struct dir_cache_entry * de, struct dir_cache_entry ** hash)
 {
-	struct dir_cache_entry * next = hash->next;
-	de->h.next = next;
-	de->h.prev = (struct dir_cache_entry *) hash;
-	next->h.prev = de;
-	hash->next = de;
+	if((de->next = *hash) != NULL)
+		(*hash)->pprev = &de->next;
+	*hash = de;
+	de->pprev = hash;
 }
 
 /*
  * Find a directory cache entry given all the necessary info.
  */
-static inline struct dir_cache_entry * find_entry(struct inode * dir, const char * name, int len, struct hash_list * hash)
+static inline struct dir_cache_entry * find_entry(struct inode * dir, const char * name, int len, struct dir_cache_entry ** hash)
 {
-	struct dir_cache_entry * nextde = hash->next;
-
-	for (;;) {
-		struct dir_cache_entry * de;
+	struct dir_cache_entry *de;
 
-		if (nextde == (struct dir_cache_entry *) hash)
+	for(de = *hash; de; de = de->next)
+		if((de->name_len == (unsigned char) len)	&&
+		   (de->dc_dev == dir->i_dev)			&&
+		   (de->dir == dir->i_ino)			&&
+		   (de->version == dir->i_version)		&&
+		   (!memcmp(de->name, name, len)))
 			break;
-		de = nextde;
-		nextde = nextde->h.next;
-		if (de->name_len != (unsigned char) len)
-			continue;
-		if (de->dc_dev != dir->i_dev)
-			continue;
-		if (de->dir != dir->i_ino)
-			continue;
-		if (de->version != dir->i_version)
-			continue;
-		if (memcmp(de->name, name, len))
-			continue;
-		return de;
-	}
-	return NULL;
+	return de;
 }
 
 /*
  * Move a successfully used entry to level2. If already at level2,
  * move it to the end of the LRU queue..
  */
-static inline void move_to_level2(struct dir_cache_entry * old_de, struct hash_list * hash)
+static inline void move_to_level2(struct dir_cache_entry * old_de, struct dir_cache_entry ** hash)
 {
 	struct dir_cache_entry * de;
 
@@ -194,43 +188,49 @@
 
 int dcache_lookup(struct inode * dir, const char * name, int len, unsigned long * ino)
 {
-	struct hash_list * hash;
-	struct dir_cache_entry *de;
+	int ret = 0;
 
-	if (len > DCACHE_NAME_LEN)
-		return 0;
-	hash = hash_table + hash_fn(dir->i_dev, dir->i_ino, namehash(name,len));
-	de = find_entry(dir, name, len, hash);
-	if (!de)
-		return 0;
-	*ino = de->ino;
-	move_to_level2(de, hash);
-	return 1;
+	if(len <= DCACHE_NAME_LEN) {
+		struct dir_cache_entry **hash = get_hlist(dir, name, len);
+		struct dir_cache_entry *de;
+
+		spin_lock(&dcache_lock);
+		de = find_entry(dir, name, len, hash);
+		if(de) {
+			*ino = de->ino;
+			move_to_level2(de, hash);
+			ret = 1;
+		}
+		spin_unlock(&dcache_lock);
+	}
+	return ret;
 }
 
 void dcache_add(struct inode * dir, const char * name, int len, unsigned long ino)
 {
-	struct hash_list * hash;
-	struct dir_cache_entry *de;
-
-	if (len > DCACHE_NAME_LEN)
-		return;
-	hash = hash_table + hash_fn(dir->i_dev, dir->i_ino, namehash(name,len));
-	if ((de = find_entry(dir, name, len, hash)) != NULL) {
-		de->ino = ino;
-		update_lru(de);
-		return;
+	if (len <= DCACHE_NAME_LEN) {
+		struct dir_cache_entry **hash = get_hlist(dir, name, len);
+		struct dir_cache_entry *de;
+
+		spin_lock(&dcache_lock);
+		de = find_entry(dir, name, len, hash);
+		if (de) {
+			de->ino = ino;
+			update_lru(de);
+		} else {
+			de = level1_head;
+			level1_head = de->next_lru;
+			remove_hash(de);
+			de->dc_dev = dir->i_dev;
+			de->dir = dir->i_ino;
+			de->version = dir->i_version;
+			de->ino = ino;
+			de->name_len = len;
+			memcpy(de->name, name, len);
+			add_hash(de, hash);
+		}
+		spin_unlock(&dcache_lock);
 	}
-	de = level1_head;
-	level1_head = de->next_lru;
-	remove_hash(de);
-	de->dc_dev = dir->i_dev;
-	de->dir = dir->i_ino;
-	de->version = dir->i_version;
-	de->ino = ino;
-	de->name_len = len;
-	memcpy(de->name, name, len);
-	add_hash(de, hash);
 }
 
 unsigned long name_cache_init(unsigned long mem_start, unsigned long mem_end)
@@ -270,7 +270,7 @@
 	 * Empty hash queues..
 	 */
 	for (i = 0 ; i < DCACHE_HASH_QUEUES ; i++)
-		hash_table[i].next = hash_table[i].next =
-			(struct dir_cache_entry *) &hash_table[i];
+		hash_table[i] = NULL;
+
 	return mem_start;
 }
diff -u --recursive --new-file v2.1.35/linux/fs/exec.c linux/fs/exec.c
--- v2.1.35/linux/fs/exec.c	Mon Apr 14 16:28:17 1997
+++ linux/fs/exec.c	Thu Apr 17 13:20:47 1997
@@ -41,6 +41,7 @@
 #include <linux/personality.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
+#include <linux/init.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -65,7 +66,7 @@
 
 static struct linux_binfmt *formats = (struct linux_binfmt *) NULL;
 
-void binfmt_setup(void)
+__initfunc(void binfmt_setup(void))
 {
 #ifdef CONFIG_BINFMT_ELF
 	init_elf_binfmt();
@@ -533,7 +534,7 @@
 		if (IS_NOSUID(bprm->inode)
 		    || (current->flags & PF_PTRACED)
 		    || (current->fs->count > 1)
-		    || (current->sig->count > 1)
+		    || (atomic_read(&current->sig->count) > 1)
 		    || (current->files->count > 1)) {
 			if (!suser())
 				return -EPERM;
diff -u --recursive --new-file v2.1.35/linux/fs/ext2/super.c linux/fs/ext2/super.c
--- v2.1.35/linux/fs/ext2/super.c	Mon Apr  7 11:35:30 1997
+++ linux/fs/ext2/super.c	Thu Apr 17 13:20:47 1997
@@ -33,6 +33,7 @@
 #include <linux/string.h>
 #include <linux/locks.h>
 #include <linux/blkdev.h>
+#include <linux/init.h>
 
 static char error_buf[1024];
 
@@ -727,7 +728,7 @@
         ext2_read_super, "ext2", 1, NULL
 };
 
-int init_ext2_fs(void)
+__initfunc(int init_ext2_fs(void))
 {
         return register_filesystem(&ext2_fs_type);
 }
diff -u --recursive --new-file v2.1.35/linux/fs/filesystems.c linux/fs/filesystems.c
--- v2.1.35/linux/fs/filesystems.c	Mon Apr  7 11:35:30 1997
+++ linux/fs/filesystems.c	Tue Apr 22 22:49:38 1997
@@ -27,6 +27,9 @@
 #include <linux/major.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
+#ifdef CONFIG_KERNELD
+#include <linux/kerneld.h>
+#endif
 
 extern void device_setup(void);
 extern void binfmt_setup(void);
@@ -42,7 +45,7 @@
 	if (!callable)
 		goto out;
 	callable = 0;
-
+	
 	device_setup();
 
 	binfmt_setup();
@@ -129,3 +132,32 @@
 	return err;
 }
 
+#ifndef CONFIG_NFSD
+#ifdef CONFIG_NFSD_MODULE
+int (*do_nfsservctl)(int, void *, void *) = NULL;
+#endif
+int
+asmlinkage sys_nfsservctl(int cmd, void *argp, void *resp)
+{
+#ifndef CONFIG_NFSD_MODULE
+	return -ENOSYS;
+#else
+	int ret = -ENOSYS;
+	
+	lock_kernel();
+	if (do_nfsservctl) {
+		ret = do_nfsservctl(cmd, argp, resp);
+		goto out;
+	}
+#ifdef CONFIG_KERNELD
+	if (request_module ("nfsd") == 0) {
+		if (do_nfsservctl)
+			ret = do_nfsservctl(cmd, argp, resp);
+	}
+#endif /* CONFIG_KERNELD */
+out:
+	unlock_kernel();
+	return ret;
+#endif /* CONFIG_NFSD_MODULE */
+}
+#endif /* CONFIG_NFSD */
diff -u --recursive --new-file v2.1.35/linux/fs/hpfs/hpfs_fs.c linux/fs/hpfs/hpfs_fs.c
--- v2.1.35/linux/fs/hpfs/hpfs_fs.c	Sun Jan 26 02:07:44 1997
+++ linux/fs/hpfs/hpfs_fs.c	Thu Apr 17 13:20:47 1997
@@ -23,6 +23,7 @@
 #include <linux/locks.h>
 #include <linux/stat.h>
 #include <linux/string.h>
+#include <linux/init.h>
 #include <asm/bitops.h>
 #include <asm/uaccess.h>
 
@@ -1748,7 +1749,7 @@
         hpfs_read_super, "hpfs", 1, NULL
 };
 
-int init_hpfs_fs(void)
+__initfunc(int init_hpfs_fs(void))
 {
         return register_filesystem(&hpfs_fs_type);
 }
diff -u --recursive --new-file v2.1.35/linux/fs/inode.c linux/fs/inode.c
--- v2.1.35/linux/fs/inode.c	Wed Apr 16 14:15:00 1997
+++ linux/fs/inode.c	Tue Apr 22 23:02:26 1997
@@ -1,231 +1,234 @@
 /*
- *  linux/fs/inode.c
+ * linux/fs/inode.c: Keeping track of inodes.
  *
- *  Copyright (C) 1991, 1992  Linus Torvalds
+ * Copyright (C) 1991, 1992  Linus Torvalds
+ * Copyright (C) 1997 David S. Miller
  */
 
-#include <linux/stat.h>
-#include <linux/sched.h>
 #include <linux/kernel.h>
+#include <linux/sched.h>
 #include <linux/mm.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 
-#include <asm/system.h>
-
-#define NR_IHASH 512
-
-/*
- * Be VERY careful when you access the inode hash table. There
- * are some rather scary race conditions you need to take care of:
- *  - P1 tries to open file "xx", calls "iget()" with the proper
- *    inode number, but blocks because it's not on the list.
- *  - P2 deletes file "xx", gets the inode (which P1 has just read,
- *    but P1 hasn't woken up to the fact yet)
- *  - P2 iput()'s the inode, which now has i_nlink = 0
- *  - P1 wakes up and has the inode, but now P2 has made that
- *    inode invalid (but P1 has no way of knowing that).
- *
- * The "updating" counter makes sure that when P1 blocks on the
- * iget(), P2 can't delete the inode from under it because P2
- * will wait until P1 has been able to update the inode usage
- * count so that the inode will stay in use until everybody has
- * closed it..
- */
-static struct inode_hash_entry {
-	struct inode * inode;
-	int updating;
-} hash_table[NR_IHASH];
-
-static struct inode * first_inode;
-static struct wait_queue * inode_wait = NULL;
-/* Keep these next two contiguous in memory for sysctl.c */
 int nr_inodes = 0, nr_free_inodes = 0;
 int max_inodes = NR_INODE;
 
-static inline int const hashfn(kdev_t dev, unsigned int i)
-{
-	return (HASHDEV(dev) ^ i) % NR_IHASH;
-}
+#define INODE_HASHSZ	1024
 
-static inline struct inode_hash_entry * const hash(kdev_t dev, int i)
-{
-	return hash_table + hashfn(dev, i);
-}
+static struct inode *inode_hash[INODE_HASHSZ];
 
-static inline void insert_inode_free(struct inode *inode)
-{
-	struct inode * prev, * next = first_inode;
+/* All the details of hashing and lookup. */
+#define hashfn(dev, i) ((HASHDEV(dev) + ((i) ^ ((i) >> 10))) & (INODE_HASHSZ - 1))
 
-	first_inode = inode;
-	prev = next->i_prev;
-	inode->i_next = next;
-	inode->i_prev = prev;
-	prev->i_next = inode;
-	next->i_prev = inode;
+__inline__ void insert_inode_hash(struct inode *inode)
+{
+	struct inode **htable = &inode_hash[hashfn(inode->i_dev, inode->i_ino)];
+	if((inode->i_hash_next = *htable) != NULL)
+		(*htable)->i_hash_pprev = &inode->i_hash_next;
+	*htable = inode;
+	inode->i_hash_pprev = htable;
 }
 
-static inline void remove_inode_free(struct inode *inode)
+#define hash_inode(inode) insert_inode_hash(inode)
+
+static inline void unhash_inode(struct inode *inode)
 {
-	if (first_inode == inode)
-		first_inode = first_inode->i_next;
-	if (inode->i_next)
-		inode->i_next->i_prev = inode->i_prev;
-	if (inode->i_prev)
-		inode->i_prev->i_next = inode->i_next;
-	inode->i_next = inode->i_prev = NULL;
+	if(inode->i_hash_pprev) {
+		if(inode->i_hash_next)
+			inode->i_hash_next->i_hash_pprev = inode->i_hash_pprev;
+		*(inode->i_hash_pprev) = inode->i_hash_next;
+		inode->i_hash_pprev = NULL;
+	}
 }
 
-void insert_inode_hash(struct inode *inode)
+static inline struct inode *find_inode(unsigned int hashent,
+				       kdev_t dev, unsigned long ino)
 {
-	struct inode_hash_entry *h;
-	h = hash(inode->i_dev, inode->i_ino);
+	struct inode *inode;
 
-	inode->i_hash_next = h->inode;
-	inode->i_hash_prev = NULL;
-	if (inode->i_hash_next)
-		inode->i_hash_next->i_hash_prev = inode;
-	h->inode = inode;
+	for(inode = inode_hash[hashent]; inode; inode = inode->i_hash_next)
+		if(inode->i_dev == dev && inode->i_ino == ino)
+			break;
+	return inode;
 }
 
-static inline void remove_inode_hash(struct inode *inode)
-{
-	struct inode_hash_entry *h;
-	h = hash(inode->i_dev, inode->i_ino);
-
-	if (h->inode == inode)
-		h->inode = inode->i_hash_next;
-	if (inode->i_hash_next)
-		inode->i_hash_next->i_hash_prev = inode->i_hash_prev;
-	if (inode->i_hash_prev)
-		inode->i_hash_prev->i_hash_next = inode->i_hash_next;
-	inode->i_hash_prev = inode->i_hash_next = NULL;
+/* Free list queue and management. */
+static struct free_inode_queue {
+	struct inode *head;
+	struct inode **last;
+} free_inodes = { NULL, &free_inodes.head };
+
+static inline void put_inode_head(struct inode *inode)
+{
+	if((inode->i_next = free_inodes.head) != NULL)
+		free_inodes.head->i_pprev = &inode->i_next;
+	else
+		free_inodes.last = &inode->i_next;
+	free_inodes.head = inode;
+	inode->i_pprev = &free_inodes.head;
+	nr_free_inodes++;
 }
 
-static inline void put_last_free(struct inode *inode)
+static inline void put_inode_last(struct inode *inode)
 {
-	remove_inode_free(inode);
-	inode->i_prev = first_inode->i_prev;
-	inode->i_prev->i_next = inode;
-	inode->i_next = first_inode;
-	inode->i_next->i_prev = inode;
+	inode->i_next = NULL;
+	inode->i_pprev = free_inodes.last;
+	*free_inodes.last = inode;
+	free_inodes.last = &inode->i_next;
+	nr_free_inodes++;
 }
 
-int grow_inodes(void)
+static inline void remove_free_inode(struct inode *inode)
 {
-	struct inode * inode;
-	int i;
-
-	if (!(inode = (struct inode*) get_free_page(GFP_KERNEL)))
-		return -ENOMEM;
-
-	i=PAGE_SIZE / sizeof(struct inode);
-	nr_inodes += i;
-	nr_free_inodes += i;
+	if(inode->i_pprev) {
+		if(inode->i_next)
+			inode->i_next->i_pprev = inode->i_pprev;
+		else
+			free_inodes.last = inode->i_pprev;
+		*inode->i_pprev = inode->i_next;
+		inode->i_pprev = NULL;
+		nr_free_inodes--;
+	}
+}
 
-	if (!first_inode)
-		inode->i_next = inode->i_prev = first_inode = inode++, i--;
+/* This is the in-use queue, if i_count > 0 (as far as we can tell)
+ * the sucker is here.
+ */
+static struct inode *inuse_list = NULL;
 
-	for ( ; i ; i-- )
-		insert_inode_free(inode++);
-	return 0;
+static inline void put_inuse(struct inode *inode)
+{
+	if((inode->i_next = inuse_list) != NULL)
+		inuse_list->i_pprev = &inode->i_next;
+	inuse_list = inode;
+	inode->i_pprev = &inuse_list;
 }
 
-unsigned long inode_init(unsigned long start, unsigned long end)
+static inline void remove_inuse(struct inode *inode)
 {
-	memset(hash_table, 0, sizeof(hash_table));
-	first_inode = NULL;
-	return start;
+	if(inode->i_pprev) {
+		if(inode->i_next)
+			inode->i_next->i_pprev = inode->i_pprev;
+		*inode->i_pprev = inode->i_next;
+		inode->i_pprev = NULL;
+	}
 }
 
+/* Locking and unlocking inodes, plus waiting for locks to clear. */
 static void __wait_on_inode(struct inode *);
 
-static inline void wait_on_inode(struct inode * inode)
+static inline void wait_on_inode(struct inode *inode)
 {
-	if (inode->i_lock)
+	if(inode->i_lock)
 		__wait_on_inode(inode);
 }
 
-static inline void lock_inode(struct inode * inode)
+static inline void lock_inode(struct inode *inode)
 {
-	wait_on_inode(inode);
+	if(inode->i_lock)
+		__wait_on_inode(inode);
 	inode->i_lock = 1;
 }
 
-static inline void unlock_inode(struct inode * inode)
+static inline void unlock_inode(struct inode *inode)
 {
 	inode->i_lock = 0;
 	wake_up(&inode->i_wait);
 }
 
-/*
- * Note that we don't want to disturb any wait-queues when we discard
- * an inode.
- *
- * Argghh. Got bitten by a gcc problem with inlining: no way to tell
- * the compiler that the inline asm function 'memset' changes 'inode'.
- * I've been searching for the bug for days, and was getting desperate.
- * Finally looked at the assembler output... Grrr.
- *
- * The solution is the weird use of 'volatile'. Ho humm. Have to report
- * it to the gcc lists, and hope we can do this more cleanly some day..
- */
-void clear_inode(struct inode * inode)
+static void __wait_on_inode(struct inode * inode)
+{
+	struct wait_queue wait = { current, NULL };
+
+	add_wait_queue(&inode->i_wait, &wait);
+repeat:
+	current->state = TASK_UNINTERRUPTIBLE;
+	if (inode->i_lock) {
+		schedule();
+		goto repeat;
+	}
+	remove_wait_queue(&inode->i_wait, &wait);
+	current->state = TASK_RUNNING;
+}
+
+/* Clear an inode of all it's identity, this is exported to the world. */
+void clear_inode(struct inode *inode)
 {
-	struct wait_queue * wait;
+	struct wait_queue *wait;
 
+	/* So we don't disappear. */
 	inode->i_count++;
+
 	truncate_inode_pages(inode, 0);
 	wait_on_inode(inode);
-	if (IS_WRITABLE(inode)) {
-		if (inode->i_sb && inode->i_sb->dq_op)
-			inode->i_sb->dq_op->drop(inode);
-	}
-	remove_inode_hash(inode);
-	remove_inode_free(inode);
-	wait = ((volatile struct inode *) inode)->i_wait;
-	inode->i_count--;
-	if (inode->i_count)
-		nr_free_inodes++;
-	memset(inode,0,sizeof(*inode));
-	((volatile struct inode *) inode)->i_wait = wait;
-	insert_inode_free(inode);
-}
+	if(IS_WRITABLE(inode) && inode->i_sb && inode->i_sb->dq_op)
+		inode->i_sb->dq_op->drop(inode);
 
+	if(--inode->i_count > 0)
+		remove_inuse(inode);
+	else
+		remove_free_inode(inode);
+	unhash_inode(inode);
+	wait = inode->i_wait;
+	memset(inode, 0, sizeof(*inode)); barrier();
+	inode->i_wait = wait;
+	put_inode_head(inode);	/* Pages zapped, put at the front. */
+}
+
+/* These check the validity of a mount/umount type operation, we essentially
+ * check if there are any inodes hanging around which prevent this operation
+ * from occurring.  We also clear out clean inodes referencing this device.
+ */
 int fs_may_mount(kdev_t dev)
 {
-	struct inode * inode, * next;
-	int i;
+	struct inode *inode;
+	int pass = 0;
 
-	next = first_inode;
-	for (i = nr_inodes ; i > 0 ; i--) {
-		inode = next;
-		next = inode->i_next;	/* clear_inode() changes the queues.. */
-		if (inode->i_dev != dev)
-			continue;
-		if (inode->i_count || inode->i_dirt || inode->i_lock)
+	inode = free_inodes.head;
+repeat:
+	while(inode) {
+		struct inode *next = inode->i_next;
+		if(inode->i_dev != dev)
+			goto next;
+		if(inode->i_count || inode->i_dirt || inode->i_lock)
 			return 0;
 		clear_inode(inode);
+	next:
+		inode = next;
+	}
+	if(pass == 0) {
+		inode = inuse_list;
+		pass = 1;
+		goto repeat;
 	}
-	return 1;
+	return 1; /* Tis' cool bro. */
 }
 
-int fs_may_umount(kdev_t dev, struct inode * mount_root)
+int fs_may_umount(kdev_t dev, struct inode *iroot)
 {
-	struct inode * inode;
-	int i;
+	struct inode *inode;
+	int pass = 0;
 
-	inode = first_inode;
-	for (i=0 ; i < nr_inodes ; i++, inode = inode->i_next) {
-		if (inode->i_dev != dev || !inode->i_count)
+	inode = free_inodes.head;
+repeat:
+	for(; inode; inode = inode->i_next) {
+		if(inode->i_dev != dev || !inode->i_count)
 			continue;
-		if (inode == mount_root && inode->i_count ==
-		    (inode->i_mount != inode ? 1 : 2))
+		if(inode == iroot &&
+		   (inode->i_count == (inode->i_mount == inode ? 2 : 1)))
 			continue;
 		return 0;
 	}
-	return 1;
+	if(pass == 0) {
+		inode = inuse_list;
+		pass = 1;
+		goto repeat;
+	}
+	return 1; /* Tis' cool bro. */
 }
 
+/* This belongs in file_table.c, not here... */
 int fs_may_remount_ro(kdev_t dev)
 {
 	struct file * file;
@@ -239,79 +242,70 @@
 		if (S_ISREG(file->f_inode->i_mode) && (file->f_mode & 2))
 			return 0;
 	}
-	return 1;
+	return 1; /* Tis' cool bro. */
 }
 
-static void write_inode(struct inode * inode)
+/* Reading/writing inodes. */
+static void write_inode(struct inode *inode)
 {
-	if (!inode->i_dirt)
-		return;
-	wait_on_inode(inode);
-	if (!inode->i_dirt)
-		return;
-	if (!inode->i_sb || !inode->i_sb->s_op || !inode->i_sb->s_op->write_inode) {
-		inode->i_dirt = 0;
-		return;
+	if(inode->i_dirt) {
+		wait_on_inode(inode);
+		if(inode->i_dirt) {
+			if(inode->i_sb		&&
+			   inode->i_sb->s_op	&&
+			   inode->i_sb->s_op->write_inode) {
+				inode->i_lock = 1;
+				inode->i_sb->s_op->write_inode(inode);
+				unlock_inode(inode);
+			} else {
+				inode->i_dirt = 0;
+			}
+		}
 	}
-	inode->i_lock = 1;	
-	inode->i_sb->s_op->write_inode(inode);
-	unlock_inode(inode);
 }
 
-static inline void read_inode(struct inode * inode)
+static inline void read_inode(struct inode *inode)
 {
-	lock_inode(inode);
-	if (inode->i_sb && inode->i_sb->s_op && inode->i_sb->s_op->read_inode)
+	if(inode->i_sb		&&
+	   inode->i_sb->s_op	&&
+	   inode->i_sb->s_op->read_inode) {
+		lock_inode(inode);
 		inode->i_sb->s_op->read_inode(inode);
-	unlock_inode(inode);
+		unlock_inode(inode);
+	}
 }
 
-/* POSIX UID/GID verification for setting inode attributes */
 int inode_change_ok(struct inode *inode, struct iattr *attr)
 {
-	/*
-	 *	If force is set do it anyway.
-	 */
-	 
-	if (attr->ia_valid & ATTR_FORCE)
-		return 0;
-
-	/* Make sure a caller can chown */
-	if ((attr->ia_valid & ATTR_UID) &&
-	    (current->fsuid != inode->i_uid ||
-	     attr->ia_uid != inode->i_uid) && !fsuser())
-		return -EPERM;
-
-	/* Make sure caller can chgrp */
-	if ((attr->ia_valid & ATTR_GID) &&
-	    (!in_group_p(attr->ia_gid) && attr->ia_gid != inode->i_gid) &&
-	    !fsuser())
-		return -EPERM;
+	if(!(attr->ia_valid & ATTR_FORCE)) {
+		unsigned short fsuid = current->fsuid;
+		uid_t iuid = inode->i_uid;
+		int not_fsuser = !fsuser();
+
+		if(((attr->ia_valid & ATTR_UID) &&
+		    ((fsuid != iuid) ||
+		     (attr->ia_uid != iuid)) && not_fsuser)	||
+
+		   ((attr->ia_valid & ATTR_GID) &&
+		    (!in_group_p(attr->ia_gid) &&
+		     (attr->ia_gid != inode->i_gid)))		||
 
-	/* Make sure a caller can chmod */
-	if (attr->ia_valid & ATTR_MODE) {
-		if ((current->fsuid != inode->i_uid) && !fsuser())
+		   ((attr->ia_valid & (ATTR_ATIME_SET | ATTR_MTIME_SET)) &&
+		    (fsuid != iuid) && not_fsuser))
 			return -EPERM;
-		/* Also check the setgid bit! */
-		if (!fsuser() && !in_group_p((attr->ia_valid & ATTR_GID) ? attr->ia_gid :
-					     inode->i_gid))
-			attr->ia_mode &= ~S_ISGID;
-	}
 
-	/* Check for setting the inode time */
-	if ((attr->ia_valid & ATTR_ATIME_SET) &&
-	    ((current->fsuid != inode->i_uid) && !fsuser()))
-		return -EPERM;
-	if ((attr->ia_valid & ATTR_MTIME_SET) &&
-	    ((current->fsuid != inode->i_uid) && !fsuser()))
-		return -EPERM;
+		if(attr->ia_valid & ATTR_MODE) {
+			gid_t grp;
+			if(fsuid != iuid && not_fsuser)
+				return -EPERM;
+			grp = attr->ia_valid & ATTR_GID ? attr->ia_gid : inode->i_gid;
+			if(not_fsuser && !in_group_p(grp))
+				attr->ia_mode &= ~S_ISGID;
+		}
+	}
 	return 0;
 }
 
-/*
- * Set the appropriate attributes from an attribute structure into
- * the inode structure.
- */
 void inode_setattr(struct inode *inode, struct iattr *attr)
 {
 	if (attr->ia_valid & ATTR_UID)
@@ -334,17 +328,8 @@
 	inode->i_dirt = 1;
 }
 
-/*
- * notify_change is called for inode-changing operations such as
- * chown, chmod, utime, and truncate.  It is guaranteed (unlike
- * write_inode) to be called from the context of the user requesting
- * the change.
- */
-
-int notify_change(struct inode * inode, struct iattr *attr)
+int notify_change(struct inode *inode, struct iattr *attr)
 {
-	int retval;
-
 	attr->ia_ctime = CURRENT_TIME;
 	if (attr->ia_valid & (ATTR_ATIME | ATTR_MTIME)) {
 		if (!(attr->ia_valid & ATTR_ATIME_SET))
@@ -353,303 +338,320 @@
 			attr->ia_mtime = attr->ia_ctime;
 	}
 
-	if (inode->i_sb && inode->i_sb->s_op  &&
+	if (inode->i_sb		&&
+	    inode->i_sb->s_op	&&
 	    inode->i_sb->s_op->notify_change) 
 		return inode->i_sb->s_op->notify_change(inode, attr);
 
-	if ((retval = inode_change_ok(inode, attr)) != 0)
-		return retval;
+	if(inode_change_ok(inode, attr) != 0)
+		return -EPERM;
 
 	inode_setattr(inode, attr);
 	return 0;
 }
 
-/*
- * bmap is needed for demand-loading and paging: if this function
- * doesn't exist for a filesystem, then those things are impossible:
- * executables cannot be run from the filesystem etc...
- *
- * This isn't as bad as it sounds: the read-routines might still work,
- * so the filesystem would be otherwise ok (for example, you might have
- * a DOS filesystem, which doesn't lend itself to bmap very well, but
- * you could still transfer files to/from the filesystem)
- */
-int bmap(struct inode * inode, int block)
+int bmap(struct inode *inode, int block)
 {
-	if (inode->i_op && inode->i_op->bmap)
-		return inode->i_op->bmap(inode,block);
+	if(inode->i_op && inode->i_op->bmap)
+		return inode->i_op->bmap(inode, block);
 	return 0;
 }
 
 void invalidate_inodes(kdev_t dev)
 {
-	struct inode * inode, * next;
-	int i;
+	struct inode *inode;
+	int pass = 0;
 
-	next = first_inode;
-	for(i = nr_inodes ; i > 0 ; i--) {
-		inode = next;
-		next = inode->i_next;		/* clear_inode() changes the queues.. */
-		if (inode->i_dev != dev)
-			continue;
-		if (inode->i_count || inode->i_dirt || inode->i_lock) {
-			printk("VFS: inode busy on removed device %s\n",
-			       kdevname(dev));
-			continue;
-		}
+	inode = free_inodes.head;
+repeat:
+	while(inode) {
+		struct inode *next = inode->i_next;
+		if(inode->i_dev != dev)
+			goto next;
 		clear_inode(inode);
+	next:
+		inode = next;
+	}
+	if(pass == 0) {
+		inode = inuse_list;
+		pass = 1;
+		goto repeat;
 	}
 }
 
 void sync_inodes(kdev_t dev)
 {
-	int i;
-	struct inode * inode;
+	struct inode *inode;
+	int pass = 0;
 
-	inode = first_inode;
-	for(i = 0; i < nr_inodes*2; i++, inode = inode->i_next) {
-		if (dev && inode->i_dev != dev)
-			continue;
+	inode = free_inodes.head;
+repeat:
+	while(inode) {
+		struct inode *next = inode->i_next;
+		if(dev && inode->i_dev != dev)
+			goto next;
 		wait_on_inode(inode);
-		if (inode->i_dirt)
-			write_inode(inode);
+		write_inode(inode);
+	next:
+		inode = next;
+	}
+	if(pass == 0) {
+		inode = inuse_list;
+		pass = 1;
+		goto repeat;
 	}
 }
 
-void iput(struct inode * inode)
+static struct wait_queue *inode_wait, *update_wait;
+
+void iput(struct inode *inode)
 {
-	if (!inode)
+	if(!inode)
 		return;
 	wait_on_inode(inode);
-	if (!inode->i_count) {
-		printk("VFS: iput: trying to free free inode\n");
-		printk("VFS: device %s, inode %lu, mode=0%07o\n",
-			kdevname(inode->i_rdev), inode->i_ino, inode->i_mode);
+	if(!inode->i_count) {
+		printk("VFS: Freeing free inode, tell DaveM\n");
 		return;
 	}
-	if (inode->i_pipe)
+	if(inode->i_pipe)
 		wake_up_interruptible(&PIPE_WAIT(*inode));
-repeat:
-	if (inode->i_count>1) {
+we_slept:
+	if(inode->i_count > 1) {
 		inode->i_count--;
-		return;
+	} else {
+		wake_up(&inode_wait);
+		if(inode->i_pipe) {
+			free_page((unsigned long)PIPE_BASE(*inode));
+			PIPE_BASE(*inode) = NULL;
+		}
+		if(inode->i_sb		&&
+		   inode->i_sb->s_op	&&
+		   inode->i_sb->s_op->put_inode) {
+			inode->i_sb->s_op->put_inode(inode);
+			if(!inode->i_nlink)
+				return;
+		}
+		if(inode->i_dirt) {
+			write_inode(inode);
+			wait_on_inode(inode);
+			goto we_slept;
+		}
+		if(IS_WRITABLE(inode)		&&
+		   inode->i_sb			&&
+		   inode->i_sb->dq_op) {
+			inode->i_lock = 1;
+			inode->i_sb->dq_op->drop(inode);
+			unlock_inode(inode);
+			goto we_slept;
+		}
+		/* There is a serious race leading to here, watch out. */
+		if(--inode->i_count == 0) {
+			remove_inuse(inode);
+			put_inode_last(inode);	/* Place at end of LRU free queue */
+		}
 	}
+}
 
-	wake_up(&inode_wait);
-	if (inode->i_pipe) {
-		unsigned long page = (unsigned long) PIPE_BASE(*inode);
-		PIPE_BASE(*inode) = NULL;
-		free_page(page);
-	}
+static kmem_cache_t *inode_cachep;
 
-	if (inode->i_sb && inode->i_sb->s_op && inode->i_sb->s_op->put_inode) {
-		inode->i_sb->s_op->put_inode(inode);
-		if (!inode->i_nlink)
+static void grow_inodes(void)
+{
+	int i = 16;
+
+	while(i--) {
+		struct inode *inode;
+		
+		inode = kmem_cache_alloc(inode_cachep, SLAB_KERNEL);
+		if(!inode)
 			return;
+		memset(inode, 0, sizeof(*inode));
+		put_inode_head(inode);
+		nr_inodes++;
 	}
+}
 
-	if (inode->i_dirt) {
-		write_inode(inode);	/* we can sleep - so do again */
-		wait_on_inode(inode);
-		goto repeat;
-	}
+/* We have to be really careful, it's really easy to run yourself into
+ * inefficient sequences of events.  The first problem is that when you
+ * steal a non-referenced inode you run the risk of zaping a considerable
+ * number of page cache entries, which might get refernced once again.
+ * But if you are growing the inode set to quickly, you suck up ram
+ * and cause other problems.
+ *
+ * We approach the problem in the following way, we take two things into
+ * consideration.  Firstly we take a look at how much we have "committed"
+ * to this inode already (i_nrpages), this accounts for the cost of getting
+ * those pages back if someone should reference that inode soon.  We also
+ * attempt to factor in i_blocks, which says "how much of a problem could
+ * this potentially be".  It still needs some tuning though.  -DaveM
+ */
+#define BLOCK_FACTOR_SHIFT	5	/* It is not factored in as much. */
+static struct inode *find_best_candidate_weighted(struct inode *inode)
+{
+	struct inode *best = NULL;
 
-	if (IS_WRITABLE(inode)) {
-		if (inode->i_sb && inode->i_sb->dq_op) {
-			/* Here we can sleep also. Let's do it again
-			 * Dmitry Gorodchanin 02/11/96 
-			 */
-			inode->i_lock = 1;
-			inode->i_sb->dq_op->drop(inode);
-			unlock_inode(inode);
-			goto repeat;
-		}
+	if(inode) {
+		unsigned long bestscore = 1000;
+		int limit = nr_free_inodes >> 2;
+		do {
+			if(!(inode->i_lock | inode->i_dirt)) {
+				int myscore = inode->i_nrpages;
+
+				myscore += (inode->i_blocks >> BLOCK_FACTOR_SHIFT);
+				if(myscore < bestscore) {
+					bestscore = myscore;
+					best = inode;
+				}
+			}
+			inode = inode->i_next;
+		} while(inode && --limit);
 	}
-	
-	inode->i_count--;
+	return best;
+}
 
-	if (inode->i_mmap) {
-		printk("iput: inode %lu on device %s still has mappings.\n",
-			inode->i_ino, kdevname(inode->i_dev));
-		inode->i_mmap = NULL;
+static inline struct inode *find_best_free(struct inode *inode)
+{
+	if(inode) {
+		int limit = nr_free_inodes >> 5;
+		do {
+			if(!inode->i_nrpages)
+				return inode;
+			inode = inode->i_next;
+		} while(inode && --limit);
 	}
-
-	nr_free_inodes++;
-	return;
+	return NULL;
 }
 
-struct inode * get_empty_inode(void)
+struct inode *get_empty_inode(void)
 {
 	static int ino = 0;
-	struct inode * inode, * best;
-	unsigned long badness;
-	int i;
+	struct inode *inode;
 
-	if (nr_inodes < max_inodes && nr_free_inodes < (nr_inodes >> 1))
-		grow_inodes();
 repeat:
-	inode = first_inode;
-	best = NULL;
-	badness = 1000;
-	for (i = nr_inodes/2; i > 0; i--,inode = inode->i_next) {
-		if (!inode->i_count) {
-			unsigned long i = 999;
-			if (!(inode->i_lock | inode->i_dirt))
-				i = inode->i_nrpages;
-			if (i < badness) {
-				best = inode;
-				if (!i)
-					goto found_good;
-				badness = i;
-			}
-		}
-	}
-	if (nr_inodes < max_inodes) {
-		if (grow_inodes() == 0)
-			goto repeat;
-		best = NULL;
-	}
-	if (!best) {
-		printk("VFS: No free inodes - contact Linus\n");
-		sleep_on(&inode_wait);
+	inode = find_best_free(free_inodes.head);
+	if(!inode)
+		goto pressure;
+got_it:
+	inode->i_count++;
+	truncate_inode_pages(inode, 0);
+	wait_on_inode(inode);
+	if(IS_WRITABLE(inode) && inode->i_sb && inode->i_sb->dq_op)
+		inode->i_sb->dq_op->drop(inode);
+	unhash_inode(inode);
+	remove_free_inode(inode);
+
+	memset(inode, 0, sizeof(*inode));
+	inode->i_count = 1;
+	inode->i_nlink = 1;
+	inode->i_version = ++event;
+	sema_init(&inode->i_sem, 1);
+	inode->i_ino = ++ino;
+	inode->i_dev = 0;
+	put_inuse(inode);
+	return inode;
+pressure:
+	if(nr_inodes < max_inodes) {
+		grow_inodes();
 		goto repeat;
 	}
-	if (best->i_lock) {
-		wait_on_inode(best);
+	inode = find_best_candidate_weighted(free_inodes.head);
+	if(!inode) {
+		printk("VFS: No free inodes, contact DaveM\n");
+		sleep_on(&inode_wait);
 		goto repeat;
 	}
-	if (best->i_dirt) {
-		write_inode(best);
+	if(inode->i_lock) {
+		wait_on_inode(inode);
 		goto repeat;
-	}
-	if (best->i_count)
+	} else if(inode->i_dirt) {
+		write_inode(inode);
 		goto repeat;
-found_good:
-	clear_inode(best);
-	best->i_count = 1;
-	best->i_nlink = 1;
-	best->i_version = ++event;
-	sema_init(&best->i_sem, 1);
-	best->i_ino = ++ino;
-	best->i_dev = 0;
-	nr_free_inodes--;
-	if (nr_free_inodes < 0) {
-		printk ("VFS: get_empty_inode: bad free inode count.\n");
-		nr_free_inodes = 0;
 	}
-	return best;
+	goto got_it;
 }
 
-struct inode * get_pipe_inode(void)
+struct inode *get_pipe_inode(void)
 {
-	struct inode * inode;
 	extern struct inode_operations pipe_inode_operations;
+	struct inode *inode = get_empty_inode();
 
-	if (!(inode = get_empty_inode()))
-		return NULL;
-	if (!(PIPE_BASE(*inode) = (char*) __get_free_page(GFP_USER))) {
-		iput(inode);
-		return NULL;
-	}
-	inode->i_op = &pipe_inode_operations;
-	inode->i_count = 2;	/* sum of readers/writers */
-	PIPE_WAIT(*inode) = NULL;
-	PIPE_START(*inode) = PIPE_LEN(*inode) = 0;
-	PIPE_RD_OPENERS(*inode) = PIPE_WR_OPENERS(*inode) = 0;
-	PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 1;
-	PIPE_LOCK(*inode) = 0;
-	inode->i_pipe = 1;
-	inode->i_mode |= S_IFIFO | S_IRUSR | S_IWUSR;
-	inode->i_uid = current->fsuid;
-	inode->i_gid = current->fsgid;
-	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-	inode->i_blksize = PAGE_SIZE;
+	if(inode) {
+		unsigned long page = __get_free_page(GFP_USER);
+		if(!page) {
+			iput(inode);
+			inode = NULL;
+		} else {
+			PIPE_BASE(*inode) = (char *) page;
+			inode->i_op = &pipe_inode_operations;
+			inode->i_count = 2;
+			PIPE_WAIT(*inode) = NULL;
+			PIPE_START(*inode) = PIPE_LEN(*inode) = 0;
+			PIPE_RD_OPENERS(*inode) = PIPE_WR_OPENERS(*inode) = 0;
+			PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 1;
+			PIPE_LOCK(*inode) = 0;
+			inode->i_pipe = 1;
+			inode->i_mode |= S_IFIFO | S_IRUSR | S_IWUSR;
+			inode->i_uid = current->fsuid;
+			inode->i_gid = current->fsgid;
+			inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+			inode->i_blksize = PAGE_SIZE;
+		}
+	}
 	return inode;
 }
 
-struct inode *__iget(struct super_block * sb, int nr, int crossmntp)
+static int inode_updating[INODE_HASHSZ];
+
+struct inode *__iget(struct super_block *sb, int nr, int crossmntp)
 {
-	static struct wait_queue * update_wait = NULL;
-	struct inode_hash_entry * h;
-	struct inode * inode;
-	struct inode * empty = NULL;
-
-	if (!sb)
-		panic("VFS: iget with sb==NULL");
-	h = hash(sb->s_dev, nr);
-repeat:
-	for (inode = h->inode; inode ; inode = inode->i_hash_next)
-		if (inode->i_dev == sb->s_dev && inode->i_ino == nr)
-			goto found_it;
-	if (!empty) {
-		/*
-		 * If we sleep here before we have found an inode
-		 * we need to make sure nobody does anything bad
-		 * to the inode while we sleep, because otherwise
-		 * we may return an inode that is not valid any
-		 * more when we wake up..
-		 */
-		h->updating++;
-		empty = get_empty_inode();
-		if (!--h->updating)
-			wake_up(&update_wait);
-		if (empty)
-			goto repeat;
-		return (NULL);
-	}
-	inode = empty;
-	inode->i_sb = sb;
-	inode->i_dev = sb->s_dev;
-	inode->i_ino = nr;
-	inode->i_flags = sb->s_flags;
-	put_last_free(inode);
-	insert_inode_hash(inode);
-	read_inode(inode);
-	goto return_it;
+	unsigned int hashent = hashfn(sb->s_dev, nr);
+	struct inode *inode, *empty = NULL;
 
-found_it:
-	if (!inode->i_count)
-		nr_free_inodes--;
-	inode->i_count++;
-	wait_on_inode(inode);
-	if (inode->i_dev != sb->s_dev || inode->i_ino != nr) {
-		printk("Whee.. inode changed from under us. Tell Linus\n");
-		iput(inode);
-		goto repeat;
-	}
-	if (crossmntp && inode->i_mount) {
-		struct inode * tmp = inode->i_mount;
-		tmp->i_count++;
-		iput(inode);
-		inode = tmp;
+we_slept:
+	if((inode = find_inode(hashent, sb->s_dev, nr)) == NULL) {
+		if(empty == NULL) {
+			inode_updating[hashent]++;
+			empty = get_empty_inode();
+			if(!--inode_updating[hashent])
+				wake_up(&update_wait);
+			goto we_slept;
+		}
+		inode = empty;
+		inode->i_sb = sb;
+		inode->i_dev = sb->s_dev;
+		inode->i_ino = nr;
+		inode->i_flags = sb->s_flags;
+		hash_inode(inode);
+		read_inode(inode);
+	} else {
+		if(!inode->i_count++) {
+			remove_free_inode(inode);
+			put_inuse(inode);
+		}
 		wait_on_inode(inode);
+		if(crossmntp && inode->i_mount) {
+			struct inode *mp = inode->i_mount;
+			mp->i_count++;
+			iput(inode);
+			wait_on_inode(inode = mp);
+		}
+		if(empty)
+			iput(empty);
 	}
-	if (empty)
-		iput(empty);
-
-return_it:
-	while (h->updating)
+	while(inode_updating[hashent])
 		sleep_on(&update_wait);
 	return inode;
 }
 
-/*
- * The "new" scheduling primitives (new as of 0.97 or so) allow this to
- * be done without disabling interrupts (other than in the actual queue
- * updating things: only a couple of 386 instructions). This should be
- * much better for interrupt latency.
- */
-static void __wait_on_inode(struct inode * inode)
+void inode_init(void)
 {
-	struct wait_queue wait = { current, NULL };
+	int i;
 
-	add_wait_queue(&inode->i_wait, &wait);
-repeat:
-	current->state = TASK_UNINTERRUPTIBLE;
-	if (inode->i_lock) {
-		schedule();
-		goto repeat;
-	}
-	remove_wait_queue(&inode->i_wait, &wait);
-	current->state = TASK_RUNNING;
+	inode_cachep = kmem_cache_create("inode", sizeof(struct inode),
+					 sizeof(unsigned long) * 4,
+					 SLAB_HWCACHE_ALIGN, NULL, NULL);
+	if(!inode_cachep)
+		panic("Cannot create inode SLAB cache\n");
+
+	for(i = 0; i < INODE_HASHSZ; i++)
+		inode_hash[i] = NULL;
 }
diff -u --recursive --new-file v2.1.35/linux/fs/isofs/dir.c linux/fs/isofs/dir.c
--- v2.1.35/linux/fs/isofs/dir.c	Mon Apr 14 16:28:17 1997
+++ linux/fs/isofs/dir.c	Thu Apr 17 09:28:01 1997
@@ -155,6 +155,11 @@
 			filp->f_pos = ((filp->f_pos & ~(ISOFS_BLOCK_SIZE - 1))
 				       + ISOFS_BLOCK_SIZE);
 			offset = 0;
+			if( filp->f_pos >= inode->i_size )
+			  {
+			    return 0;
+			  }
+
 			block = isofs_bmap(inode, (filp->f_pos) >> bufbits);
 			if (!block)
 				return 0;
diff -u --recursive --new-file v2.1.35/linux/fs/isofs/inode.c linux/fs/isofs/inode.c
--- v2.1.35/linux/fs/isofs/inode.c	Mon Apr 14 16:28:17 1997
+++ linux/fs/isofs/inode.c	Thu Apr 17 13:20:47 1997
@@ -22,6 +22,7 @@
 #include <linux/malloc.h>
 #include <linux/errno.h>
 #include <linux/cdrom.h>
+#include <linux/init.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -920,7 +921,7 @@
 	isofs_read_super, "iso9660", 1, NULL
 };
 
-int init_iso9660_fs(void)
+__initfunc(int init_iso9660_fs(void))
 {
         return register_filesystem(&iso9660_fs_type);
 }
diff -u --recursive --new-file v2.1.35/linux/fs/isofs/namei.c linux/fs/isofs/namei.c
--- v2.1.35/linux/fs/isofs/namei.c	Sat Nov 30 02:24:01 1996
+++ linux/fs/isofs/namei.c	Thu Apr 17 09:28:01 1997
@@ -98,6 +98,12 @@
 			offset = 0;
 			f_pos = ((f_pos & ~(ISOFS_BLOCK_SIZE - 1))
 				 + ISOFS_BLOCK_SIZE);
+
+			if( f_pos >= dir->i_size )
+			  {
+			    return 0;
+			  }
+
 			block = isofs_bmap(dir,f_pos>>bufbits);
 			if (!block || !(bh = bread(dir->i_dev,block,bufsize)))
 				return 0;
diff -u --recursive --new-file v2.1.35/linux/fs/lockd/host.c linux/fs/lockd/host.c
--- v2.1.35/linux/fs/lockd/host.c	Mon Apr  7 11:35:30 1997
+++ linux/fs/lockd/host.c	Tue Apr 15 21:47:24 1997
@@ -21,7 +21,7 @@
 #define NLM_HOST_MAX		64
 #define NLM_HOST_NRHASH		32
 #define NLM_ADDRHASH(addr)	(ntohl(addr) & (NLM_HOST_NRHASH-1))
-#define NLM_PTRHASH(ptr)	((((u32) ptr) / 32) & (NLM_HOST_NRHASH-1))
+#define NLM_PTRHASH(ptr)	((((u32)(unsigned long) ptr) / 32) & (NLM_HOST_NRHASH-1))
 #define NLM_HOST_REBIND		(60 * HZ)
 #define NLM_HOST_EXPIRE		((nrhosts > NLM_HOST_MAX)? 300 * HZ : 120 * HZ)
 #define NLM_HOST_COLLECT	((nrhosts > NLM_HOST_MAX)? 120 * HZ :  60 * HZ)
@@ -81,8 +81,8 @@
 		return NULL;
 	}
 
-	dprintk("lockd: nlm_lookup_host(%08lx, p=%d, v=%d)\n",
-			sin? ntohl(sin->sin_addr.s_addr) : 0, proto, version);
+	dprintk("lockd: nlm_lookup_host(%08x, p=%d, v=%d)\n",
+			(unsigned)(sin? ntohl(sin->sin_addr.s_addr) : 0), proto, version);
 
 	if (clnt)
 		hash = NLM_PTRHASH(clnt);
@@ -164,8 +164,8 @@
 	struct rpc_clnt	*clnt;
 	struct rpc_xprt	*xprt;
 
-	dprintk("lockd: nlm_bind_host(%08lx)\n",
-			ntohl(host->h_addr.sin_addr.s_addr));
+	dprintk("lockd: nlm_bind_host(%08x)\n",
+			(unsigned)ntohl(host->h_addr.sin_addr.s_addr));
 
 	/* Lock host handle */
 	down(&host->h_sema);
diff -u --recursive --new-file v2.1.35/linux/fs/lockd/svc.c linux/fs/lockd/svc.c
--- v2.1.35/linux/fs/lockd/svc.c	Mon Apr  7 11:35:30 1997
+++ linux/fs/lockd/svc.c	Tue Apr 15 21:47:24 1997
@@ -130,8 +130,8 @@
 			break;
 		}
 
-		dprintk("lockd: request from %08lx\n",
-				ntohl(rqstp->rq_addr.sin_addr.s_addr));
+		dprintk("lockd: request from %08x\n",
+				(unsigned)ntohl(rqstp->rq_addr.sin_addr.s_addr));
 
 		/*
 		 * Look up the NFS client handle. The handle is needed for
diff -u --recursive --new-file v2.1.35/linux/fs/minix/inode.c linux/fs/minix/inode.c
--- v2.1.35/linux/fs/minix/inode.c	Fri Dec 27 02:03:25 1996
+++ linux/fs/minix/inode.c	Thu Apr 17 13:20:47 1997
@@ -18,6 +18,7 @@
 #include <linux/string.h>
 #include <linux/stat.h>
 #include <linux/locks.h>
+#include <linux/init.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -946,7 +947,7 @@
 	minix_read_super, "minix", 1, NULL
 };
 
-int init_minix_fs(void)
+__initfunc(int init_minix_fs(void))
 {
         return register_filesystem(&minix_fs_type);
 }
diff -u --recursive --new-file v2.1.35/linux/fs/msdos/msdosfs_syms.c linux/fs/msdos/msdosfs_syms.c
--- v2.1.35/linux/fs/msdos/msdosfs_syms.c	Thu Mar 27 14:40:06 1997
+++ linux/fs/msdos/msdosfs_syms.c	Thu Apr 17 13:20:48 1997
@@ -10,6 +10,7 @@
 
 #include <linux/mm.h>
 #include <linux/msdos_fs.h>
+#include <linux/init.h>
 
 /*
  * Support for umsdos fs
@@ -33,7 +34,7 @@
 	msdos_read_super, "msdos", 1, NULL
 };
 
-int init_msdos_fs(void)
+__initfunc(int init_msdos_fs(void))
 {
 	return register_filesystem(&msdos_fs_type);
 }
diff -u --recursive --new-file v2.1.35/linux/fs/ncpfs/inode.c linux/fs/ncpfs/inode.c
--- v2.1.35/linux/fs/ncpfs/inode.c	Fri Apr  4 08:52:24 1997
+++ linux/fs/ncpfs/inode.c	Thu Apr 17 13:20:48 1997
@@ -23,6 +23,7 @@
 #include <linux/locks.h>
 #include <linux/fcntl.h>
 #include <linux/malloc.h>
+#include <linux/init.h>
 #ifdef CONFIG_KERNELD
 #include <linux/kerneld.h>
 #endif
@@ -409,7 +410,7 @@
 	ncp_read_super, "ncpfs", 0, NULL
 };
 
-int init_ncp_fs(void)
+__initfunc(int init_ncp_fs(void))
 {
 	return register_filesystem(&ncp_fs_type);
 }
diff -u --recursive --new-file v2.1.35/linux/fs/nfs/dir.c linux/fs/nfs/dir.c
--- v2.1.35/linux/fs/nfs/dir.c	Mon Apr  7 11:35:30 1997
+++ linux/fs/nfs/dir.c	Tue Apr 15 21:47:24 1997
@@ -206,7 +206,7 @@
 		}
 		if (entry) {
 			dfprintk(DIRCACHE, "NFS: found dircache entry %d\n",
-						cache - dircache);
+						(int)(cache - dircache));
 			cache->locked = 1;
 			break;
 		}
@@ -223,7 +223,7 @@
 			goto again;
 		}
 		dfprintk(DIRCACHE, "NFS: using free dircache entry %d\n",
-				free - dircache);
+				(int)(free - dircache));
 		cache->cookie = cookie;
 		cache->locked = 1;
 		cache->valid  = 0;
@@ -298,7 +298,7 @@
 	ino_t		ino = inode->i_ino;
 	int		i;
 
-	dfprintk(DIRCACHE, "NFS: invalidate dircache for %x/%ld\n", dev, ino);
+	dfprintk(DIRCACHE, "NFS: invalidate dircache for %x/%ld\n", dev, (long)ino);
 	for (i = 0, cache = dircache; i < NFS_MAX_DIRCACHE; i++, cache++) {
 		if (!cache->locked && cache->dev == dev && cache->ino == ino)
 			cache->valid = 0;	/* brute force */
@@ -445,7 +445,7 @@
 		return;
 
 	dfprintk(LOOKUPCACHE, "NFS: lookup_cache_remove(%x/%ld)\n",
-				dev, fileid);
+				dev, (long)fileid);
 
 	for (i = 0; i < NFS_LOOKUP_CACHE_SIZE; i++) {
 		entry = nfs_lookup_cache + i;
diff -u --recursive --new-file v2.1.35/linux/fs/nfs/mount_clnt.c linux/fs/nfs/mount_clnt.c
--- v2.1.35/linux/fs/nfs/mount_clnt.c	Mon Apr 14 16:28:17 1997
+++ linux/fs/nfs/mount_clnt.c	Tue Apr 15 21:47:24 1997
@@ -49,8 +49,8 @@
 	char			hostname[32];
 	int			status;
 
-	dprintk("NFS:      nfs_mount(%08lx:%s)\n",
-			ntohl(addr->sin_addr.s_addr), path);
+	dprintk("NFS:      nfs_mount(%08x:%s)\n",
+			(unsigned)ntohl(addr->sin_addr.s_addr), path);
 
 	strcpy(hostname, in_ntoa(addr->sin_addr.s_addr));
 	if (!(mnt_clnt = mnt_create(hostname, addr)))
diff -u --recursive --new-file v2.1.35/linux/fs/nfs/nfs2xdr.c linux/fs/nfs/nfs2xdr.c
--- v2.1.35/linux/fs/nfs/nfs2xdr.c	Mon Apr 14 16:28:17 1997
+++ linux/fs/nfs/nfs2xdr.c	Wed Apr 16 14:20:12 1997
@@ -222,7 +222,7 @@
 	struct iovec *iov = req->rq_rvec;
 	int	status, count, recvd, hdrlen;
 
-	dprintk("RPC:      readres OK status %lx\n", ntohl(*p));
+	dprintk("RPC:      readres OK status %lx\n", (long)ntohl(*p));
 	if ((status = ntohl(*p++)))
 		return -nfs_stat_to_errno(status);
 	p = xdr_decode_fattr(p, res->fattr);
@@ -414,9 +414,16 @@
 		}
 		string -= len;
 		if ((void *) (entry+1) > (void *) string) {
+			/* This may actually happen because an nfs_entry
+			 * will take up more space than the XDR data. On
+			 * 32bit machines that's due to 8byte alignment,
+			 * on 64bit machines that's because the char * takes
+			 * up 2 longs.
+			 *
+			 * THIS IS BAD!
+			 */
 			printk(KERN_NOTICE "NFS: should not happen in %s!\n",
-					__FUNCTION__);
-			printk(KERN_NOTICE "NFS: len = %d, entry+1=%p, string=%p\n", len, entry+1, string);
+				__FUNCTION__);
 			break;
 		}
 
@@ -464,7 +471,7 @@
 {
 	int	status;
 
-	dprintk("RPC:      attrstat status %lx\n", ntohl(*p));
+	dprintk("RPC:      attrstat status %lx\n", (long)ntohl(*p));
 	if ((status = ntohl(*p++)))
 		return -nfs_stat_to_errno(status);
 	xdr_decode_fattr(p, fattr);
@@ -482,7 +489,7 @@
 {
 	int	status;
 
-	dprintk("RPC:      diropres status %lx\n", ntohl(*p));
+	dprintk("RPC:      diropres status %lx\n", (long)ntohl(*p));
 	if ((status = ntohl(*p++)))
 		return -nfs_stat_to_errno(status);
 	p = xdr_decode_fhandle(p, res->fh);
diff -u --recursive --new-file v2.1.35/linux/fs/nfsd/nfsctl.c linux/fs/nfsd/nfsctl.c
--- v2.1.35/linux/fs/nfsd/nfsctl.c	Mon Apr  7 11:35:31 1997
+++ linux/fs/nfsd/nfsctl.c	Tue Apr 22 22:49:38 1997
@@ -35,6 +35,8 @@
 # define copy_to_user		memcpy_tofs
 # define access_ok		!verify_area
 #endif
+#include <asm/smp.h>
+#include <asm/smp_lock.h>
 
 extern long sys_call_table[];
 
@@ -126,20 +128,30 @@
 	return err;
 }
 
+#ifdef CONFIG_NFSD
+#define handle_sys_nfsservctl sys_nfsservctl
+#endif
+
 int
-asmlinkage sys_nfsservctl(int cmd, struct nfsctl_arg *argp, union nfsctl_res *resp)
+asmlinkage handle_sys_nfsservctl(int cmd, struct nfsctl_arg *argp,
+			         union nfsctl_res *resp)
 {
 	struct nfsctl_arg *	arg = NULL;
 	union nfsctl_res *	res = NULL;
 	int			err;
 
+	lock_kernel ();
 	if (!initialized)
 		nfsd_init();
-	if (!suser())
-		return -EPERM;
+	if (!suser()) {
+		err = -EPERM;
+		goto done;
+	}
 	if (!access_ok(VERIFY_READ, argp, sizeof(*argp))
-	 || (resp && !access_ok(VERIFY_WRITE, resp, sizeof(*resp))))
-		return -EFAULT;
+	 || (resp && !access_ok(VERIFY_WRITE, resp, sizeof(*resp)))) {
+		err = -EFAULT;
+		goto done;
+	}
 	if (!(arg = kmalloc(sizeof(*arg), GFP_USER)) ||
 	    (resp && !(res = kmalloc(sizeof(*res), GFP_USER)))) {
 		err = -ENOMEM;	/* ??? */
@@ -191,6 +203,7 @@
 	if (res)
 		kfree(res);
 
+	unlock_kernel ();
 	return err;
 }
 
@@ -203,6 +216,8 @@
 
 static unsigned long	old_syscallvec;
 
+extern int (*do_nfsservctl)(int, void *, void *);
+
 /*
  * Initialize the module
  */
@@ -210,10 +225,8 @@
 init_module(void)
 {
 	printk("Installing knfsd (copyright (C) 1996 okir@monad.swb.de).\n");
-
-	old_syscallvec = sys_call_table[__NR_nfsservctl];
-	sys_call_table[__NR_nfsservctl] = (unsigned long) sys_nfsservctl;
 	nfsd_init();
+	do_nfsservctl = handle_sys_nfsservctl;
 	return 0;
 }
 
@@ -227,7 +240,7 @@
 		printk("nfsd: nfsd busy, remove delayed\n");
 		return;
 	}
-	sys_call_table[__NR_nfsservctl] = old_syscallvec;
+	do_nfsservctl = NULL;
 	nfsd_export_shutdown();
 	nfsd_cache_shutdown();
 #ifdef CONFIG_PROC_FS
diff -u --recursive --new-file v2.1.35/linux/fs/nfsd/nfssvc.c linux/fs/nfsd/nfssvc.c
--- v2.1.35/linux/fs/nfsd/nfssvc.c	Mon Apr 14 16:28:18 1997
+++ linux/fs/nfsd/nfssvc.c	Tue Apr 22 22:49:38 1997
@@ -116,7 +116,7 @@
 	/*
 	 * The main request loop
 	 */
-	do {
+	for (;;) {
 		/*
 		 * Find a socket with data available and call its
 		 * recvfrom routine.
@@ -150,7 +150,7 @@
 
 		/* Unlock export hash tables */
 		exp_unlock();
-	} while (err >= 0);
+	}
 
 	if (err != -EINTR) {
 		printk(KERN_WARNING "nfsd: terminating on error %d\n", -err);
diff -u --recursive --new-file v2.1.35/linux/fs/nfsd/vfs.c linux/fs/nfsd/vfs.c
--- v2.1.35/linux/fs/nfsd/vfs.c	Mon Apr 14 16:28:18 1997
+++ linux/fs/nfsd/vfs.c	Tue Apr 15 21:47:24 1997
@@ -26,7 +26,6 @@
 #include <linux/stat.h>
 #include <linux/fcntl.h>
 #include <linux/net.h>
-#include <linux/in.h>
 #include <linux/unistd.h>
 #include <linux/malloc.h>
 #include <linux/in.h>
diff -u --recursive --new-file v2.1.35/linux/fs/proc/root.c linux/fs/proc/root.c
--- v2.1.35/linux/fs/proc/root.c	Mon Apr  7 11:35:31 1997
+++ linux/fs/proc/root.c	Wed Apr 16 10:55:21 1997
@@ -365,7 +365,7 @@
 	char tmp[30];
 
 	iput(inode);
-	len = 1 + sprintf(tmp, "%d", current->pid);
+	len = sprintf(tmp, "%d", current->pid);
 	if (buflen < len)
 		len = buflen;
 	copy_to_user(buffer, tmp, len);
diff -u --recursive --new-file v2.1.35/linux/fs/romfs/inode.c linux/fs/romfs/inode.c
--- v2.1.35/linux/fs/romfs/inode.c	Mon Apr 14 16:28:18 1997
+++ linux/fs/romfs/inode.c	Thu Apr 17 13:20:48 1997
@@ -39,6 +39,7 @@
 #include <linux/romfs_fs.h>
 #include <linux/fs.h>
 #include <linux/locks.h>
+#include <linux/init.h>
 
 #include <asm/uaccess.h>
 
@@ -640,8 +641,7 @@
 	romfs_read_super, "romfs", 1, NULL
 };
 
-int
-init_romfs_fs(void)
+__initfunc(int init_romfs_fs(void))
 {
 	return register_filesystem(&romfs_fs_type);
 }
diff -u --recursive --new-file v2.1.35/linux/fs/smbfs/inode.c linux/fs/smbfs/inode.c
--- v2.1.35/linux/fs/smbfs/inode.c	Sun Jan 19 05:47:26 1997
+++ linux/fs/smbfs/inode.c	Thu Apr 17 13:20:48 1997
@@ -19,6 +19,7 @@
 #include <linux/locks.h>
 #include <linux/fcntl.h>
 #include <linux/malloc.h>
+#include <linux/init.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -432,8 +433,7 @@
 	smb_read_super, "smbfs", 0, NULL
 };
 
-int
-init_smb_fs(void)
+__initfunc(int init_smb_fs(void))
 {
 	return register_filesystem(&smb_fs_type);
 }
diff -u --recursive --new-file v2.1.35/linux/fs/sysv/inode.c linux/fs/sysv/inode.c
--- v2.1.35/linux/fs/sysv/inode.c	Fri Jan  3 01:33:26 1997
+++ linux/fs/sysv/inode.c	Thu Apr 17 13:20:48 1997
@@ -30,6 +30,7 @@
 #include <linux/stat.h>
 #include <linux/string.h>
 #include <linux/locks.h>
+#include <linux/init.h>
 
 #include <asm/uaccess.h>
 
@@ -979,7 +980,7 @@
 	{sysv_read_super, "coherent", 1, NULL}
 };
 
-int init_sysv_fs(void)
+__initfunc(int init_sysv_fs(void))
 {
 	int i;
 	int ouch;
diff -u --recursive --new-file v2.1.35/linux/fs/ufs/ufs_super.c linux/fs/ufs/ufs_super.c
--- v2.1.35/linux/fs/ufs/ufs_super.c	Sun Jan 26 02:07:46 1997
+++ linux/fs/ufs/ufs_super.c	Thu Apr 17 13:20:48 1997
@@ -8,7 +8,7 @@
  *
  * Copyright (C) 1996  Eddie C. Dost  (ecd@skynet.be)
  *
- * $Id: ufs_super.c,v 1.22 1997/01/16 14:17:41 davem Exp $
+ * $Id: ufs_super.c,v 1.23 1997/04/16 04:53:39 tdyas Exp $
  *
  */
 
@@ -27,6 +27,7 @@
 #include <linux/fs.h>
 #include <linux/ufs_fs.h>
 #include <linux/locks.h>
+#include <linux/init.h>
 
 #include <asm/uaccess.h>
 
@@ -51,8 +52,7 @@
 	ufs_read_super, "ufs", 1, NULL
 };
 
-int
-init_ufs_fs(void)
+__initfunc(int init_ufs_fs(void))
 {
 	return(register_filesystem(&ufs_fs_type));
 }
diff -u --recursive --new-file v2.1.35/linux/fs/umsdos/inode.c linux/fs/umsdos/inode.c
--- v2.1.35/linux/fs/umsdos/inode.c	Fri Dec 27 02:03:26 1996
+++ linux/fs/umsdos/inode.c	Thu Apr 17 13:20:48 1997
@@ -8,6 +8,7 @@
 
 #include <linux/module.h>
 
+#include <linux/init.h>
 #include <linux/fs.h>
 #include <linux/msdos_fs.h>
 #include <linux/kernel.h>
@@ -499,7 +500,7 @@
 	UMSDOS_read_super, "umsdos", 1, NULL
 };
 
-int init_umsdos_fs(void)
+__initfunc(int init_umsdos_fs(void))
 {
 	return register_filesystem(&umsdos_fs_type);
 }
diff -u --recursive --new-file v2.1.35/linux/fs/vfat/namei.c linux/fs/vfat/namei.c
--- v2.1.35/linux/fs/vfat/namei.c	Fri Jan  3 01:33:26 1997
+++ linux/fs/vfat/namei.c	Thu Apr 17 13:20:48 1997
@@ -20,6 +20,7 @@
 #include <linux/string.h>
 #include <linux/stat.h>
 #include <linux/mm.h>
+#include <linux/init.h>
 
 #include <asm/uaccess.h>
 
@@ -1587,7 +1588,7 @@
 EXPORT_SYMBOL(vfat_read_inode);
 EXPORT_SYMBOL(vfat_lookup);
 
-int init_vfat_fs(void)
+__initfunc(int init_vfat_fs(void))
 {
 	return register_filesystem(&vfat_fs_type);
 }
diff -u --recursive --new-file v2.1.35/linux/include/asm-alpha/atomic.h linux/include/asm-alpha/atomic.h
--- v2.1.35/linux/include/asm-alpha/atomic.h	Wed Apr 16 14:15:00 1997
+++ linux/include/asm-alpha/atomic.h	Thu Apr 17 13:20:48 1997
@@ -15,7 +15,7 @@
 typedef struct { int counter; } atomic_t;
 #endif
 
-#define ATOMIC_INIT	{ 0 }
+#define ATOMIC_INIT(i)	{ (i) }
 
 #define atomic_read(v)		((v)->counter)
 #define atomic_set(v,i)		((v)->counter = (i))
diff -u --recursive --new-file v2.1.35/linux/include/asm-alpha/init.h linux/include/asm-alpha/init.h
--- v2.1.35/linux/include/asm-alpha/init.h	Wed Apr 16 14:15:00 1997
+++ linux/include/asm-alpha/init.h	Tue Apr 22 22:38:40 1997
@@ -1,14 +1,15 @@
 #ifndef _ALPHA_INIT_H
 #define _ALPHA_INIT_H
 
-/* Throwing the initialization code and data out is not supported yet... */
+#define __init __attribute__ ((__section__ (".text.init")))
+#define __initdata __attribute__ ((__section__ (".data.init")))
+#define __initfunc(__arginit) \
+	__arginit __init; \
+	__arginit
 
-#define	__init
-#define __initdata
-#define __initfunc(__arginit) __arginit
 /* For assembly routines */
-#define __INIT
-#define __FINIT
-#define __INITDATA
+#define __INIT		.section	.text.init,"ax"
+#define __FINIT		.previous
+#define __INITDATA	.section	.data.init,"a"
 
 #endif
diff -u --recursive --new-file v2.1.35/linux/include/asm-alpha/processor.h linux/include/asm-alpha/processor.h
--- v2.1.35/linux/include/asm-alpha/processor.h	Sun Jan 26 02:07:46 1997
+++ linux/include/asm-alpha/processor.h	Tue Apr 22 22:38:40 1997
@@ -42,6 +42,7 @@
 
 	/* the fields below are Linux-specific: */
 	/* bit 1..5: IEEE_TRAP_ENABLE bits (see fpu.h) */
+	/* bit 6..8: UAC bits (see sysinfo.h) */
 	unsigned long flags;
 	/* perform syscall argument validation (get/set_fs) */
 	unsigned long fs;
diff -u --recursive --new-file v2.1.35/linux/include/asm-alpha/semaphore.h linux/include/asm-alpha/semaphore.h
--- v2.1.35/linux/include/asm-alpha/semaphore.h	Wed Apr 16 14:15:00 1997
+++ linux/include/asm-alpha/semaphore.h	Thu Apr 17 13:20:48 1997
@@ -15,8 +15,8 @@
 	struct wait_queue * wait;
 };
 
-#define MUTEX ((struct semaphore) { { 1 }, { 0 }, NULL })
-#define MUTEX_LOCKED ((struct semaphore) { { 0 }, { 0 }, NULL })
+#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);
diff -u --recursive --new-file v2.1.35/linux/include/asm-alpha/smp_lock.h linux/include/asm-alpha/smp_lock.h
--- v2.1.35/linux/include/asm-alpha/smp_lock.h	Fri Apr  4 08:52:24 1997
+++ linux/include/asm-alpha/smp_lock.h	Thu Apr 17 09:23:54 1997
@@ -6,7 +6,7 @@
 #define lock_kernel()				do { } while(0)
 #define unlock_kernel()				do { } while(0)
 #define release_kernel_lock(task, cpu, depth)	((depth) = 1)
-#define reaquire_kernel_lock(task, cpu, depth)	do { } while (0)
+#define reacquire_kernel_lock(task, cpu, depth)	do { } while (0)
 
 #else
 
diff -u --recursive --new-file v2.1.35/linux/include/asm-alpha/softirq.h linux/include/asm-alpha/softirq.h
--- v2.1.35/linux/include/asm-alpha/softirq.h	Mon Apr 14 16:28:18 1997
+++ linux/include/asm-alpha/softirq.h	Tue Apr 22 22:38:40 1997
@@ -31,6 +31,12 @@
 	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);
diff -u --recursive --new-file v2.1.35/linux/include/asm-alpha/spinlock.h linux/include/asm-alpha/spinlock.h
--- v2.1.35/linux/include/asm-alpha/spinlock.h	Wed Apr 16 14:15:00 1997
+++ linux/include/asm-alpha/spinlock.h	Tue Apr 22 22:38:40 1997
@@ -9,6 +9,7 @@
 #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)			setipl(7)
 #define spin_unlock_irq(lock)			setipl(0)
@@ -16,6 +17,33 @@
 #define spin_lock_irqsave(lock, flags)		swpipl(flags,7)
 #define spin_unlock_irqrestore(lock, flags)	setipl(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
 
 /* Simple spin lock operations.  There are two variants, one clears IRQ's
@@ -30,6 +58,9 @@
 } spinlock_t;
 
 #define SPIN_LOCK_UNLOCKED { 0, 0 }
+
+#define spin_lock_init(lock)	do { (lock)->lock = 0; (lock)->previous = 0; } while(0)
+#define spin_unlock_wait(lock)	do { barrier(); } while(((volatile spinlock_t *)lock)->lock)
 
 typedef struct { unsigned long a[100]; } __dummy_lock_t;
 #define __dummy_lock(lock) (*(__dummy_lock_t *)(lock))
diff -u --recursive --new-file v2.1.35/linux/include/asm-alpha/sysinfo.h linux/include/asm-alpha/sysinfo.h
--- v2.1.35/linux/include/asm-alpha/sysinfo.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-alpha/sysinfo.h	Tue Apr 22 22:38:40 1997
@@ -0,0 +1,36 @@
+/*
+ * include/asm-alpha/sysinfo.h
+ */
+
+#ifndef __ASM_ALPHA_SYSINFO_H
+#define __ASM_ALPHA_SYSINFO_H
+
+/* This defines the subset of the OSF/1 getsysinfo/setsysinfo calls
+   that we support.  */
+
+#define GSI_UACPROC			8
+#define GSI_IEEE_FP_CONTROL		45
+#define GSI_IEEE_STATE_AT_SIGNAL	46
+
+#define SSI_NVPAIRS			1
+#define SSI_IEEE_FP_CONTROL		14
+#define SSI_IEEE_STATE_AT_SIGNAL	15
+#define SSI_IEEE_IGNORE_STATE_AT_SIGNAL	16
+
+#define SSIN_UACPROC			6
+
+#define UAC_BITMASK			7
+#define UAC_NOPRINT			1
+#define UAC_NOFIX			2
+#define UAC_SIGBUS			4
+
+
+#ifdef __KERNEL__
+
+/* This is the shift that is applied to the UAC bits as stored in the 
+   per-thread flags.  */
+#define UAC_SHIFT			6
+
+#endif
+
+#endif /* __ASM_ALPHA_SYSINFO_H */
diff -u --recursive --new-file v2.1.35/linux/include/asm-i386/atomic.h linux/include/asm-i386/atomic.h
--- v2.1.35/linux/include/asm-i386/atomic.h	Mon Apr 14 16:28:18 1997
+++ linux/include/asm-i386/atomic.h	Thu Apr 17 13:20:48 1997
@@ -25,7 +25,7 @@
 typedef struct { int counter; } atomic_t;
 #endif
 
-#define ATOMIC_INIT	{ 0 }
+#define ATOMIC_INIT(i)	{ (i) }
 
 #define atomic_read(v)		((v)->counter)
 #define atomic_set(v,i)		(((v)->counter) = (i))
diff -u --recursive --new-file v2.1.35/linux/include/asm-i386/init.h linux/include/asm-i386/init.h
--- v2.1.35/linux/include/asm-i386/init.h	Wed Apr 16 14:15:00 1997
+++ linux/include/asm-i386/init.h	Thu Apr 17 13:20:48 1997
@@ -1,7 +1,6 @@
 #ifndef _I386_INIT_H
 #define _I386_INIT_H
 
-#ifndef MODULE
 #define __init __attribute__ ((__section__ (".text.init")))
 #define __initdata __attribute__ ((__section__ (".data.init")))
 #define __initfunc(__arginit) \
@@ -11,14 +10,5 @@
 #define __INIT		.section	".text.init",#alloc,#execinstr
 #define __FINIT	.previous
 #define __INITDATA	.section	".data.init",#alloc,#write
-#else
-#define	__init
-#define __initdata
-#define __initfunc(__arginit) __arginit
-/* For assembly routines */
-#define __INIT
-#define __FINIT
-#define __INITDATA
-#endif
 
 #endif
diff -u --recursive --new-file v2.1.35/linux/include/asm-i386/pgtable.h linux/include/asm-i386/pgtable.h
--- v2.1.35/linux/include/asm-i386/pgtable.h	Thu Feb  6 02:53:43 1997
+++ linux/include/asm-i386/pgtable.h	Wed Apr 23 11:00:45 1997
@@ -205,6 +205,7 @@
 #define _PAGE_ACCESSED	0x020
 #define _PAGE_DIRTY	0x040
 #define _PAGE_4M	0x080	/* 4 MB page, Pentium+.. */
+#define _PAGE_GLOBAL	0x100	/* Global TLB entry PPro+ */
 
 #define _PAGE_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY)
 #define _KERNPG_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
@@ -374,6 +375,8 @@
 	free_page((unsigned long) pte);
 }
 
+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);
@@ -390,7 +393,7 @@
 		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_val(*pmd) = _KERNPG_TABLE + __pa(BAD_PAGETABLE);
 		return NULL;
 	}
@@ -443,7 +446,7 @@
 }
 
 fix:
-	printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd));
+	printk(bad_pmd_string, pmd_val(*pmd));
 oom:
 	pmd_val(*pmd) = _PAGE_TABLE + __pa(BAD_PAGETABLE);
 	return NULL;
diff -u --recursive --new-file v2.1.35/linux/include/asm-i386/semaphore.h linux/include/asm-i386/semaphore.h
--- v2.1.35/linux/include/asm-i386/semaphore.h	Mon Apr 14 16:28:19 1997
+++ linux/include/asm-i386/semaphore.h	Thu Apr 17 13:20:48 1997
@@ -28,8 +28,8 @@
 	struct wait_queue * wait;
 };
 
-#define MUTEX ((struct semaphore) { { 1 }, 0, NULL })
-#define MUTEX_LOCKED ((struct semaphore) { { 0 }, 0, NULL })
+#define MUTEX ((struct semaphore) { ATOMIC_INIT(1), 0, NULL })
+#define MUTEX_LOCKED ((struct semaphore) { ATOMIC_INIT(0), 0, NULL })
 
 asmlinkage void __down_failed(void /* special register calling convention */);
 asmlinkage int  __down_failed_interruptible(void  /* params in registers */);
diff -u --recursive --new-file v2.1.35/linux/include/asm-i386/smp.h linux/include/asm-i386/smp.h
--- v2.1.35/linux/include/asm-i386/smp.h	Thu Feb 27 10:57:31 1997
+++ linux/include/asm-i386/smp.h	Tue Apr 15 21:47:24 1997
@@ -234,52 +234,6 @@
 	return GET_APIC_ID(*(unsigned long *)(apic_reg+APIC_ID));
 }
 
-/* These read/change the "processes available" counter in the scheduler. */
-extern __inline__ __volatile__ void inc_smp_counter(volatile int *ctr)
-{
-	int cpu = smp_processor_id();
-	while(set_bit(31, ctr))
-	{
-		while(test_bit(31,ctr))
-		{
-			if(clear_bit(cpu,&smp_invalidate_needed))
-			{
-				unsigned long tmpreg;
-				__asm__ __volatile__("movl %%cr3,%0\n\tmovl %0,%%cr3"
-						     : "=r" (tmpreg) : : "memory");
-				set_bit(cpu,&cpu_callin_map[0]);
-			}
-		}
-	}
-	*ctr = (*ctr + 1);
-	clear_bit(31, ctr);
-}
-
-extern __inline__ __volatile__ void dec_smp_counter(volatile int *ctr)
-{
-	int cpu = smp_processor_id();
-	while(set_bit(31, ctr))
-	{
-		while(test_bit(31,ctr))
-		{
-			if(clear_bit(cpu,&smp_invalidate_needed))
-			{
-				unsigned long tmpreg;
-				__asm__ __volatile__("movl %%cr3,%0\n\tmovl %0,%%cr3"
-						     : "=r" (tmpreg) : : "memory");
-				set_bit(cpu,&cpu_callin_map[0]);
-			}
-		}
-	}
-	*ctr = (*ctr - 1);
-	clear_bit(31, ctr);
-}
-
-extern __inline__ __volatile__ int read_smp_counter(volatile int *ctr)
-{
-	return (*ctr & 0x7fffffff);
-}
-
 #endif /* !ASSEMBLY */
 
 #define NO_PROC_ID		0xFF		/* No processor magic marker */
diff -u --recursive --new-file v2.1.35/linux/include/asm-i386/smp_lock.h linux/include/asm-i386/smp_lock.h
--- v2.1.35/linux/include/asm-i386/smp_lock.h	Fri Apr  4 08:52:25 1997
+++ linux/include/asm-i386/smp_lock.h	Thu Apr 17 13:29:54 1997
@@ -8,7 +8,7 @@
 #define lock_kernel()				do { } while(0)
 #define unlock_kernel()				do { } while(0)
 #define release_kernel_lock(task, cpu, depth)	((depth) = 1)
-#define reaquire_kernel_lock(task, cpu, depth)	do { } while(0)
+#define reacquire_kernel_lock(task, cpu, depth)	do { } while(0)
 
 #else
 
@@ -27,8 +27,8 @@
 	__sti(); \
 } while (0)
 
-/* Re-aquire the kernel lock */
-#define reaquire_kernel_lock(task, cpu, depth) \
+/* Re-acquire the kernel lock */
+#define reacquire_kernel_lock(task, cpu, depth) \
 do { if (depth) __asm__ __volatile__( \
 	"cli\n\t" \
 	"movl $0f,%%eax\n\t" \
diff -u --recursive --new-file v2.1.35/linux/include/asm-i386/softirq.h linux/include/asm-i386/softirq.h
--- v2.1.35/linux/include/asm-i386/softirq.h	Mon Apr 14 16:28:19 1997
+++ linux/include/asm-i386/softirq.h	Tue Apr 22 22:44:18 1997
@@ -14,6 +14,12 @@
 	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);
diff -u --recursive --new-file v2.1.35/linux/include/asm-i386/spinlock.h linux/include/asm-i386/spinlock.h
--- v2.1.35/linux/include/asm-i386/spinlock.h	Thu Mar 27 14:40:06 1997
+++ linux/include/asm-i386/spinlock.h	Tue Apr 22 23:23:36 1997
@@ -3,12 +3,16 @@
 
 #ifndef __SMP__
 
+/*
+ * Your basic spinlocks, allowing only a single CPU anywhere
+ */
 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()
@@ -18,9 +22,41 @@
 #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)	\
+	do { save_flags(flags); cli(); } while (0)
+#define read_unlock_irqrestore(lock, flags) \
+	restore_flags(flags)
+#define write_lock_irqsave(lock, flags)	\
+	do { save_flags(flags); cli(); } while (0)
+#define write_unlock_irqrestore(lock, flags) \
+	restore_flags(flags)
+
 #else
 
-/* Simple spin lock operations.  There are two variants, one clears IRQ's
+/*
+ * Simple spin lock operations.  There are two variants, one clears IRQ's
  * on the local processor, one does not.
  *
  * We make no fairness assumptions. They have a cost.
@@ -33,6 +69,9 @@
 
 #define SPIN_LOCK_UNLOCKED { 0, 0 }
 
+#define spin_lock_init(x)	do { (x)->lock = 0; (x)->previous = 0; } while(0)
+#define spin_unlock_wait(x)	do { barrier(); } while(((volatile spinlock_t *)(x))->lock)
+
 typedef struct { unsigned long a[100]; } __dummy_lock_t;
 #define __dummy_lock(lock) (*(__dummy_lock_t *)(lock))
 
@@ -91,6 +130,80 @@
 
 #define spin_unlock_irqrestore(lock, flags) \
 	do { spin_unlock(lock); __restore_flags(flags); } while (0)
+
+/*
+ * 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 {
+	volatile unsigned int lock;
+	unsigned long previous;
+} rwlock_t;
+
+#define RW_LOCK_UNLOCKED { 0, 0 }
+
+/*
+ * On x86, we implement read-write locks as a 32-bit counter
+ * with the high bit (sign) being the "write" bit.
+ *
+ * The inline assembly is non-obvious. Think about it.
+ */
+#define read_lock(rw)	\
+	asm volatile("\n1:\t" \
+		     "lock ; incl %0\n\t" \
+		     "js 2f\n" \
+		     ".text 2\n" \
+		     "2:\tlock ; decl %0\n" \
+		     "3:\tcmpl $0,%0\n\t" \
+		     "js 3b\n\t" \
+		     "jmp 1b\n" \
+		     ".text" \
+		     :"=m" (__dummy_lock(&(rw)->lock)))
+
+#define read_unlock(rw) \
+	asm volatile("lock ; decl %0" \
+		:"=m" (__dummy_lock(&(rw)->lock)))
+
+#define write_lock(rw) \
+	asm volatile("\n1:\t" \
+		     "lock ; btsl $31,%0\n\t" \
+		     "jc 3f\n\t" \
+		     "testl $0x7fffffff,%0\n\t" \
+		     "jne 4f\n" \
+		     "2:\n" \
+		     ".text 2\n" \
+		     "3:\ttestl $-1,%0\n\t" \
+		     "js 3b\n\t" \
+		     "lock ; btsl $31,%0\n\t" \
+		     "jc 3b\n" \
+		     "4:\ttestl $0x7fffffff,%0\n\t" \
+		     "jne 4b\n\t" \
+		     "jmp 2b\n" \
+		     ".text" \
+		     :"=m" (__dummy_lock(&(rw)->lock)))
+
+#define write_unlock(rw) \
+	asm volatile("lock ; btrl $31,%0":"=m" (__dummy_lock(&(rw)->lock)))
+
+#define read_lock_irq(lock)	do { __cli(); read_lock(lock); } while (0)
+#define read_unlock_irq(lock)	do { read_unlock(lock); __sti(); } while (0)
+#define write_lock_irq(lock)	do { __cli(); write_lock(lock); } while (0)
+#define write_unlock_irq(lock)	do { write_unlock(lock); __sti(); } while (0)
+
+#define read_lock_irqsave(lock, flags)	\
+	do { __save_flags(flags); __cli(); read_lock(lock); } while (0)
+#define read_unlock_irqrestore(lock, flags) \
+	do { read_unlock(lock); __restore_flags(flags); } while (0)
+#define write_lock_irqsave(lock, flags)	\
+	do { __save_flags(flags); __cli(); write_lock(lock); } while (0)
+#define write_unlock_irqrestore(lock, flags) \
+	do { write_unlock(lock); __restore_flags(flags); } while (0)
 
 #endif /* SMP */
 #endif /* __ASM_SPINLOCK_H */
diff -u --recursive --new-file v2.1.35/linux/include/asm-m68k/amigaints.h linux/include/asm-m68k/amigaints.h
--- v2.1.35/linux/include/asm-m68k/amigaints.h	Wed Sep 25 00:47:41 1996
+++ linux/include/asm-m68k/amigaints.h	Thu Apr 17 13:20:48 1997
@@ -18,53 +18,65 @@
 **
 */
 
-#define AMI_IRQS            (24)
+#define AUTO_IRQS           (8)
 #define AMI_STD_IRQS        (14)
 #define CIA_IRQS            (5)
+#define AMI_IRQS            (32) /* AUTO_IRQS+AMI_STD_IRQS+2*CIA_IRQS */
 
 /* vertical blanking interrupt */
-#define IRQ_AMIGA_VERTB     (IRQ_MACHSPEC | 0)
+#define IRQ_AMIGA_VERTB     0
 
 /* copper interrupt */
-#define IRQ_AMIGA_COPPER    (IRQ_MACHSPEC | 1)
+#define IRQ_AMIGA_COPPER    1
 
 /* Audio interrupts */
-#define IRQ_AMIGA_AUD0	    (IRQ_MACHSPEC | 2)
-#define IRQ_AMIGA_AUD1	    (IRQ_MACHSPEC | 3)
-#define IRQ_AMIGA_AUD2	    (IRQ_MACHSPEC | 4)
-#define IRQ_AMIGA_AUD3	    (IRQ_MACHSPEC | 5)
+#define IRQ_AMIGA_AUD0	    2
+#define IRQ_AMIGA_AUD1	    3
+#define IRQ_AMIGA_AUD2	    4
+#define IRQ_AMIGA_AUD3	    5
 
 /* Blitter done interrupt */
-#define IRQ_AMIGA_BLIT	    (IRQ_MACHSPEC | 6)
+#define IRQ_AMIGA_BLIT	    6
 
 /* floppy disk interrupts */
-#define IRQ_AMIGA_DSKSYN    (IRQ_MACHSPEC | 7)
-#define IRQ_AMIGA_DSKBLK    (IRQ_MACHSPEC | 8)
+#define IRQ_AMIGA_DSKSYN    7
+#define IRQ_AMIGA_DSKBLK    8
 
 /* builtin serial port interrupts */
-#define IRQ_AMIGA_RBF	    (IRQ_MACHSPEC | 9)
-#define IRQ_AMIGA_TBE	    (IRQ_MACHSPEC | 10)
+#define IRQ_AMIGA_RBF	    9
+#define IRQ_AMIGA_TBE	    10
 
 /* software interrupts */
-#define IRQ_AMIGA_SOFT      (IRQ_MACHSPEC | 11)
+#define IRQ_AMIGA_SOFT      11
 
 /* interrupts from external hardware */
-#define IRQ_AMIGA_PORTS	    (IRQ_MACHSPEC | 12)
-#define IRQ_AMIGA_EXTER	    (IRQ_MACHSPEC | 13)
+#define IRQ_AMIGA_PORTS	    12
+#define IRQ_AMIGA_EXTER	    13
 
 /* CIA interrupt sources */
-#define IRQ_AMIGA_CIAA      (IRQ_MACHSPEC | 14)
-#define IRQ_AMIGA_CIAA_TA   (IRQ_MACHSPEC | 14)
-#define IRQ_AMIGA_CIAA_TB   (IRQ_MACHSPEC | 15)
-#define IRQ_AMIGA_CIAA_ALRM (IRQ_MACHSPEC | 16)
-#define IRQ_AMIGA_CIAA_SP   (IRQ_MACHSPEC | 17)
-#define IRQ_AMIGA_CIAA_FLG  (IRQ_MACHSPEC | 18)
-#define IRQ_AMIGA_CIAB      (IRQ_MACHSPEC | 19)
-#define IRQ_AMIGA_CIAB_TA   (IRQ_MACHSPEC | 19)
-#define IRQ_AMIGA_CIAB_TB   (IRQ_MACHSPEC | 20)
-#define IRQ_AMIGA_CIAB_ALRM (IRQ_MACHSPEC | 21)
-#define IRQ_AMIGA_CIAB_SP   (IRQ_MACHSPEC | 22)
-#define IRQ_AMIGA_CIAB_FLG  (IRQ_MACHSPEC | 23)
+#define IRQ_AMIGA_CIAA      14
+#define IRQ_AMIGA_CIAA_TA   14
+#define IRQ_AMIGA_CIAA_TB   15
+#define IRQ_AMIGA_CIAA_ALRM 16
+#define IRQ_AMIGA_CIAA_SP   17
+#define IRQ_AMIGA_CIAA_FLG  18
+#define IRQ_AMIGA_CIAB      19
+#define IRQ_AMIGA_CIAB_TA   19
+#define IRQ_AMIGA_CIAB_TB   20
+#define IRQ_AMIGA_CIAB_ALRM 21
+#define IRQ_AMIGA_CIAB_SP   22
+#define IRQ_AMIGA_CIAB_FLG  23
+
+/* auto-vector interrupts */
+#define IRQ_AMIGA_AUTO      24
+#define IRQ_AMIGA_AUTO_0    24 /* This is just a dummy */
+#define IRQ_AMIGA_AUTO_1    25
+#define IRQ_AMIGA_AUTO_2    26
+#define IRQ_AMIGA_AUTO_3    27
+#define IRQ_AMIGA_AUTO_4    28
+#define IRQ_AMIGA_AUTO_5    29
+#define IRQ_AMIGA_AUTO_6    30
+#define IRQ_AMIGA_AUTO_7    31
 
 #define IRQ_FLOPPY	    IRQ_AMIGA_DSKBLK
 
diff -u --recursive --new-file v2.1.35/linux/include/asm-m68k/atarihw.h linux/include/asm-m68k/atarihw.h
--- v2.1.35/linux/include/asm-m68k/atarihw.h	Fri Dec 20 01:20:02 1996
+++ linux/include/asm-m68k/atarihw.h	Thu Apr 17 13:20:48 1997
@@ -79,6 +79,7 @@
     ATARIHW_DECLARE(SCU);		/* System Control Unit */
     ATARIHW_DECLARE(BLITTER);		/* Blitter */
     ATARIHW_DECLARE(VME);		/* VME Bus */
+    ATARIHW_DECLARE(DSP56K);		/* DSP56k processor in Falcon */
 };
 
 extern struct atari_hw_present atari_hw_present;
@@ -97,6 +98,7 @@
 void atari_stram_free (void *);
 
 extern int is_medusa;
+extern int is_hades;
 
 /* Do cache push/invalidate for DMA read/write. This function obeys the
  * snooping on some machines (Medusa) and processors: The Medusa itself can
@@ -356,8 +358,8 @@
 {
   u_char tracks;
   u_char input_source;
-#define CODEC_SOURCE_MATRIX     1
-#define CODEC_SOURCE_ADC        2
+#define CODEC_SOURCE_ADC        1
+#define CODEC_SOURCE_MATRIX     2
   u_char adc_source;
 #define ADC_SOURCE_RIGHT_PSG    1
 #define ADC_SOURCE_LEFT_PSG     2
@@ -673,17 +675,28 @@
 };
 # define tt_dmasnd ((*(volatile struct TT_DMASND *)TT_DMASND_BAS))
 
-#define	DMASND_CTRL_OFF		0x00
-#define	DMASND_CTRL_ON		0x01
-#define	DMASND_CTRL_REPEAT	0x02
-#define	DMASND_MODE_MONO	0x80
-#define	DMASND_MODE_STEREO	0x00
-#define DMASND_MODE_8BIT	0x00
-#define DMASND_MODE_16BIT	0x40	/* Falcon only */
-#define	DMASND_MODE_6KHZ	0x00	/* Falcon: mute */
-#define	DMASND_MODE_12KHZ	0x01
-#define	DMASND_MODE_25KHZ	0x02
-#define	DMASND_MODE_50KHZ	0x03
+#define DMASND_MFP_INT_REPLAY     0x01
+#define DMASND_MFP_INT_RECORD     0x02
+#define DMASND_TIMERA_INT_REPLAY  0x04
+#define DMASND_TIMERA_INT_RECORD  0x08
+
+#define	DMASND_CTRL_OFF		  0x00
+#define	DMASND_CTRL_ON		  0x01
+#define	DMASND_CTRL_REPEAT	  0x02
+#define DMASND_CTRL_RECORD_ON     0x10
+#define DMASND_CTRL_RECORD_OFF    0x00
+#define DMASND_CTRL_RECORD_REPEAT 0x20
+#define DMASND_CTRL_SELECT_REPLAY 0x00
+#define DMASND_CTRL_SELECT_RECORD 0x80
+#define	DMASND_MODE_MONO	  0x80
+#define	DMASND_MODE_STEREO	  0x00
+#define DMASND_MODE_8BIT	  0x00
+#define DMASND_MODE_16BIT	  0x40	/* Falcon only */
+#define	DMASND_MODE_6KHZ	  0x00	/* Falcon: mute */
+#define	DMASND_MODE_12KHZ	  0x01
+#define	DMASND_MODE_25KHZ	  0x02
+#define	DMASND_MODE_50KHZ	  0x03
+ 
 
 #define DMASNDSetBase(bufstart)						\
     do {								\
diff -u --recursive --new-file v2.1.35/linux/include/asm-m68k/atariints.h linux/include/asm-m68k/atariints.h
--- v2.1.35/linux/include/asm-m68k/atariints.h	Wed Sep 25 00:47:41 1996
+++ linux/include/asm-m68k/atariints.h	Thu Apr 17 13:20:48 1997
@@ -26,11 +26,11 @@
 **
 */
 
-#define STMFP_SOURCE_BASE   8
-#define TTMFP_SOURCE_BASE   24
-#define SCC_SOURCE_BASE	    40
-#define VME_SOURCE_BASE		56
-#define VME_MAX_SOURCES		16
+#define STMFP_SOURCE_BASE  8
+#define TTMFP_SOURCE_BASE  24
+#define SCC_SOURCE_BASE    40
+#define VME_SOURCE_BASE    56
+#define VME_MAX_SOURCES    16
 
 #define NUM_ATARI_SOURCES   (VME_SOURCE_BASE+VME_MAX_SOURCES-STMFP_SOURCE_BASE)
 
@@ -45,65 +45,65 @@
 #define IRQ_TYPE_FAST     1
 #define IRQ_TYPE_PRIO     2
 
-#define	IRQ_SPURIOUS      (IRQ_MACHSPEC | 0)
+#define	IRQ_SPURIOUS      (0)
 
 /* auto-vector interrupts */
-#define IRQ_AUTO_1        (IRQ_MACHSPEC | 1)
-#define IRQ_AUTO_2        (IRQ_MACHSPEC | 2)
-#define IRQ_AUTO_3        (IRQ_MACHSPEC | 3)
-#define IRQ_AUTO_4        (IRQ_MACHSPEC | 4)
-#define IRQ_AUTO_5        (IRQ_MACHSPEC | 5)
-#define IRQ_AUTO_6        (IRQ_MACHSPEC | 6)
-#define IRQ_AUTO_7        (IRQ_MACHSPEC | 7)
+#define IRQ_AUTO_1        (1)
+#define IRQ_AUTO_2        (2)
+#define IRQ_AUTO_3        (3)
+#define IRQ_AUTO_4        (4)
+#define IRQ_AUTO_5        (5)
+#define IRQ_AUTO_6        (6)
+#define IRQ_AUTO_7        (7)
 
 /* ST-MFP interrupts */
-#define IRQ_MFP_BUSY      (IRQ_MACHSPEC | 8)
-#define IRQ_MFP_DCD       (IRQ_MACHSPEC | 9)
-#define IRQ_MFP_CTS  	  (IRQ_MACHSPEC | 10)
-#define IRQ_MFP_GPU 	  (IRQ_MACHSPEC | 11)
-#define IRQ_MFP_TIMD      (IRQ_MACHSPEC | 12)
-#define IRQ_MFP_TIMC	  (IRQ_MACHSPEC | 13)
-#define IRQ_MFP_ACIA	  (IRQ_MACHSPEC | 14)
-#define IRQ_MFP_FDC       (IRQ_MACHSPEC | 15)
+#define IRQ_MFP_BUSY      (8)
+#define IRQ_MFP_DCD       (9)
+#define IRQ_MFP_CTS  	  (10)
+#define IRQ_MFP_GPU 	  (11)
+#define IRQ_MFP_TIMD      (12)
+#define IRQ_MFP_TIMC	  (13)
+#define IRQ_MFP_ACIA	  (14)
+#define IRQ_MFP_FDC       (15)
 #define IRQ_MFP_ACSI      IRQ_MFP_FDC
 #define IRQ_MFP_FSCSI     IRQ_MFP_FDC
 #define IRQ_MFP_IDE       IRQ_MFP_FDC
-#define IRQ_MFP_TIMB      (IRQ_MACHSPEC | 16)
-#define IRQ_MFP_SERERR    (IRQ_MACHSPEC | 17)
-#define IRQ_MFP_SEREMPT   (IRQ_MACHSPEC | 18)
-#define IRQ_MFP_RECERR    (IRQ_MACHSPEC | 19)
-#define IRQ_MFP_RECFULL   (IRQ_MACHSPEC | 20)
-#define IRQ_MFP_TIMA      (IRQ_MACHSPEC | 21)
-#define IRQ_MFP_RI        (IRQ_MACHSPEC | 22)
-#define IRQ_MFP_MMD       (IRQ_MACHSPEC | 23)
+#define IRQ_MFP_TIMB      (16)
+#define IRQ_MFP_SERERR    (17)
+#define IRQ_MFP_SEREMPT   (18)
+#define IRQ_MFP_RECERR    (19)
+#define IRQ_MFP_RECFULL   (20)
+#define IRQ_MFP_TIMA      (21)
+#define IRQ_MFP_RI        (22)
+#define IRQ_MFP_MMD       (23)
 
 /* TT-MFP interrupts */
-#define IRQ_TT_MFP_IO0       (IRQ_MACHSPEC | 24)
-#define IRQ_TT_MFP_IO1       (IRQ_MACHSPEC | 25)
-#define IRQ_TT_MFP_SCC	     (IRQ_MACHSPEC | 26)
-#define IRQ_TT_MFP_RI 	     (IRQ_MACHSPEC | 27)
-#define IRQ_TT_MFP_TIMD      (IRQ_MACHSPEC | 28)
-#define IRQ_TT_MFP_TIMC	     (IRQ_MACHSPEC | 29)
-#define IRQ_TT_MFP_DRVRDY    (IRQ_MACHSPEC | 30)
-#define IRQ_TT_MFP_SCSIDMA   (IRQ_MACHSPEC | 31)
-#define IRQ_TT_MFP_TIMB      (IRQ_MACHSPEC | 32)
-#define IRQ_TT_MFP_SERERR    (IRQ_MACHSPEC | 33)
-#define IRQ_TT_MFP_SEREMPT   (IRQ_MACHSPEC | 34)
-#define IRQ_TT_MFP_RECERR    (IRQ_MACHSPEC | 35)
-#define IRQ_TT_MFP_RECFULL   (IRQ_MACHSPEC | 36)
-#define IRQ_TT_MFP_TIMA      (IRQ_MACHSPEC | 37)
-#define IRQ_TT_MFP_RTC       (IRQ_MACHSPEC | 38)
-#define IRQ_TT_MFP_SCSI      (IRQ_MACHSPEC | 39)
+#define IRQ_TT_MFP_IO0       (24)
+#define IRQ_TT_MFP_IO1       (25)
+#define IRQ_TT_MFP_SCC	     (26)
+#define IRQ_TT_MFP_RI 	     (27)
+#define IRQ_TT_MFP_TIMD      (28)
+#define IRQ_TT_MFP_TIMC	     (29)
+#define IRQ_TT_MFP_DRVRDY    (30)
+#define IRQ_TT_MFP_SCSIDMA   (31)
+#define IRQ_TT_MFP_TIMB      (32)
+#define IRQ_TT_MFP_SERERR    (33)
+#define IRQ_TT_MFP_SEREMPT   (34)
+#define IRQ_TT_MFP_RECERR    (35)
+#define IRQ_TT_MFP_RECFULL   (36)
+#define IRQ_TT_MFP_TIMA      (37)
+#define IRQ_TT_MFP_RTC       (38)
+#define IRQ_TT_MFP_SCSI      (39)
 
 /* SCC interrupts */
-#define IRQ_SCCB_TX	     (IRQ_MACHSPEC | 40)
-#define IRQ_SCCB_STAT	     (IRQ_MACHSPEC | 42)
-#define IRQ_SCCB_RX	     (IRQ_MACHSPEC | 44)
-#define IRQ_SCCB_SPCOND	     (IRQ_MACHSPEC | 46)
-#define IRQ_SCCA_TX	     (IRQ_MACHSPEC | 48)
-#define IRQ_SCCA_STAT	     (IRQ_MACHSPEC | 50)
-#define IRQ_SCCA_RX	     (IRQ_MACHSPEC | 52)
-#define IRQ_SCCA_SPCOND	     (IRQ_MACHSPEC | 54)
+#define IRQ_SCCB_TX	     (40)
+#define IRQ_SCCB_STAT	     (42)
+#define IRQ_SCCB_RX	     (44)
+#define IRQ_SCCB_SPCOND	     (46)
+#define IRQ_SCCA_TX	     (48)
+#define IRQ_SCCA_STAT	     (50)
+#define IRQ_SCCA_RX	     (52)
+#define IRQ_SCCA_SPCOND	     (54)
 
 
 #define INT_CLK   24576	    /* CLK while int_clk =2.456MHz and divide = 100 */
@@ -164,7 +164,6 @@
 static inline void atari_enable_irq( unsigned irq )
 
 {
-	irq &= ~IRQ_MACHSPEC;
 	if (irq < STMFP_SOURCE_BASE || irq >= SCC_SOURCE_BASE) return;
 	set_mfp_bit( irq, MFP_MASK );
 }
@@ -172,7 +171,6 @@
 static inline void atari_disable_irq( unsigned irq )
 
 {
-	irq &= ~IRQ_MACHSPEC;
 	if (irq < STMFP_SOURCE_BASE || irq >= SCC_SOURCE_BASE) return;
 	clear_mfp_bit( irq, MFP_MASK );
 }
@@ -185,7 +183,6 @@
 extern inline void atari_turnon_irq( unsigned irq )
 
 {
-	irq &= ~IRQ_MACHSPEC;
 	if (irq < STMFP_SOURCE_BASE || irq >= SCC_SOURCE_BASE) return;
 	set_mfp_bit( irq, MFP_ENABLE );
 }
@@ -193,7 +190,6 @@
 extern inline void atari_turnoff_irq( unsigned irq )
 
 {
-	irq &= ~IRQ_MACHSPEC;
 	if (irq < STMFP_SOURCE_BASE || irq >= SCC_SOURCE_BASE) return;
 	clear_mfp_bit( irq, MFP_ENABLE );
 	clear_mfp_bit( irq, MFP_PENDING );
@@ -202,7 +198,6 @@
 extern inline void atari_clear_pending_irq( unsigned irq )
 
 {
-	irq &= ~IRQ_MACHSPEC;
 	if (irq < STMFP_SOURCE_BASE || irq >= SCC_SOURCE_BASE) return;
 	clear_mfp_bit( irq, MFP_PENDING );
 }
@@ -210,7 +205,6 @@
 extern inline int atari_irq_pending( unsigned irq )
 
 {
-	irq &= ~IRQ_MACHSPEC;
 	if (irq < STMFP_SOURCE_BASE || irq >= SCC_SOURCE_BASE) return( 0 );
 	return( get_mfp_bit( irq, MFP_PENDING ) );
 }
diff -u --recursive --new-file v2.1.35/linux/include/asm-m68k/atomic.h linux/include/asm-m68k/atomic.h
--- v2.1.35/linux/include/asm-m68k/atomic.h	Mon Apr 14 16:28:19 1997
+++ linux/include/asm-m68k/atomic.h	Thu Apr 17 13:20:48 1997
@@ -14,7 +14,7 @@
 #define ATOMIC_INIT	{ 0 }
 
 #define atomic_read(v)		((v)->counter)
-#define atomic_set(v)		(((v)->counter) = i)
+#define atomic_set(v, i)	(((v)->counter) = i)
 
 static __inline__ void atomic_add(int i, atomic_t *v)
 {
@@ -26,21 +26,27 @@
 	__asm__ __volatile__("subl %1,%0" : : "m" (*v), "id" (i));
 }
 
-static __inline__ void atomic_inc(atomic_t *v)
+static __inline__ void atomic_inc(volatile atomic_t *v)
 {
 	__asm__ __volatile__("addql #1,%0" : : "m" (*v));
 }
 
-static __inline__ void atomic_dec(atomic_t *v)
+static __inline__ void atomic_dec(volatile atomic_t *v)
 {
 	__asm__ __volatile__("subql #1,%0" : : "m" (*v));
 }
 
-static __inline__ int atomic_dec_and_test(atomic_t *v)
+static __inline__ int atomic_dec_and_test(volatile atomic_t *v)
 {
 	char c;
 	__asm__ __volatile__("subql #1,%1; seq %0" : "=d" (c) : "m" (*v));
 	return c != 0;
 }
+
+#define atomic_clear_mask(mask, v) \
+	__asm__ __volatile__("andl %1,%0" : : "m" (*v), "id" (~(mask)))
+
+#define atomic_set_mask(mask, v) \
+	__asm__ __volatile__("orl %1,%0" : : "m" (*v), "id" (mask));
 
 #endif /* __ARCH_M68K_ATOMIC __ */
diff -u --recursive --new-file v2.1.35/linux/include/asm-m68k/bootinfo.h linux/include/asm-m68k/bootinfo.h
--- v2.1.35/linux/include/asm-m68k/bootinfo.h	Fri Dec 20 01:20:02 1996
+++ linux/include/asm-m68k/bootinfo.h	Thu Apr 17 13:20:48 1997
@@ -141,8 +141,7 @@
 #define COMPAT_AMIGA_BOOTI_VERSION    MK_BI_VERSION( 1, 0 )
 #define COMPAT_ATARI_BOOTI_VERSION    MK_BI_VERSION( 1, 0 )
 
-#include <linux/config.h>
-#include <asm/zorro.h>
+#include <linux/zorro.h>
 
 #define COMPAT_NUM_AUTO    16
 
diff -u --recursive --new-file v2.1.35/linux/include/asm-m68k/byteorder.h linux/include/asm-m68k/byteorder.h
--- v2.1.35/linux/include/asm-m68k/byteorder.h	Fri Dec 20 01:20:02 1996
+++ linux/include/asm-m68k/byteorder.h	Thu Apr 17 13:20:48 1997
@@ -10,7 +10,6 @@
 #endif
 
 #ifdef __KERNEL__
-#include <linux/config.h>
 #include <asm/types.h>
 
 /*
diff -u --recursive --new-file v2.1.35/linux/include/asm-m68k/cache.h linux/include/asm-m68k/cache.h
--- v2.1.35/linux/include/asm-m68k/cache.h	Sun Jan 26 02:07:46 1997
+++ linux/include/asm-m68k/cache.h	Thu Apr 17 13:20:48 1997
@@ -5,7 +5,7 @@
 #define __ARCH_M68K_CACHE_H
 
 /* bytes per L1 cache line */
-#define        L1_CACHE_BYTES  32      /* a guess */
+#define        L1_CACHE_BYTES  16
 
 #define        L1_CACHE_ALIGN(x)       (((x)+(L1_CACHE_BYTES-1))&~(L1_CACHE_BYTES-1))
 
diff -u --recursive --new-file v2.1.35/linux/include/asm-m68k/checksum.h linux/include/asm-m68k/checksum.h
--- v2.1.35/linux/include/asm-m68k/checksum.h	Fri Dec 20 01:20:02 1996
+++ linux/include/asm-m68k/checksum.h	Thu Apr 17 13:20:48 1997
@@ -35,6 +35,9 @@
 
 unsigned int csum_partial_copy_fromuser(const char *src, char *dst, int len, int sum);
 
+extern unsigned int
+csum_partial_copy_from_user ( const char *src, char *dst,
+			      int len, int sum, int *csum_err);
 
 /*
  *	This is a version of ip_compute_csum() optimized for IP headers,
diff -u --recursive --new-file v2.1.35/linux/include/asm-m68k/dsp56k.h linux/include/asm-m68k/dsp56k.h
--- v2.1.35/linux/include/asm-m68k/dsp56k.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-m68k/dsp56k.h	Tue Apr 22 22:45:15 1997
@@ -0,0 +1,70 @@
+/*
+ * linux/include/asm-m68k/dsp56k.h - defines and declarations for
+ *                                   DSP56k device driver
+ *
+ * Copyright (C) 1996,1997 Fredrik Noring, lars brinkhoff & Tomas Berndtsson
+ *
+ * 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.
+ */
+
+
+/* Used for uploading DSP binary code */
+struct dsp56k_upload {
+	int len;
+	char *bin;
+};
+
+/* For the DSP host flags */
+struct dsp56k_host_flags {
+	int dir;     /* Bit field. 1 = write output bit, 0 = do nothing.
+		      * 0x0000 means reading only, 0x0011 means
+		      * writing the bits stored in `out' on HF0 and HF1.
+		      * Note that HF2 and HF3 can only be read.
+		      */
+	int out;     /* Bit field like above. */
+	int status;  /* Host register's current state is returned */
+};
+
+/* ioctl command codes */
+#define DSP56K_UPLOAD	        1    /* Upload DSP binary program       */
+#define DSP56K_SET_TX_WSIZE	2    /* Host transmit word size (1-4)   */
+#define DSP56K_SET_RX_WSIZE	3    /* Host receive word size (1-4)    */
+#define DSP56K_HOST_FLAGS	4    /* Host flag registers             */
+#define DSP56K_HOST_CMD         5    /* Trig Host Command (0-31)        */
+/*
+ * linux/include/asm-m68k/dsp56k.h - defines and declarations for
+ *                                   DSP56k device driver
+ *
+ * Copyright (C) 1996,1997 Fredrik Noring, lars brinkhoff & Tomas Berndtsson
+ *
+ * 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.
+ */
+
+
+/* Used for uploading DSP binary code */
+struct dsp56k_upload {
+	int len;
+	char *bin;
+};
+
+/* For the DSP host flags */
+struct dsp56k_host_flags {
+	int dir;     /* Bit field. 1 = write output bit, 0 = do nothing.
+		      * 0x0000 means reading only, 0x0011 means
+		      * writing the bits stored in `out' on HF0 and HF1.
+		      * Note that HF2 and HF3 can only be read.
+		      */
+	int out;     /* Bit field like above. */
+	int status;  /* Host register's current state is returned */
+};
+
+/* ioctl command codes */
+#define DSP56K_UPLOAD	        1    /* Upload DSP binary program       */
+#define DSP56K_SET_TX_WSIZE	2    /* Host transmit word size (1-4)   */
+#define DSP56K_SET_RX_WSIZE	3    /* Host receive word size (1-4)    */
+#define DSP56K_HOST_FLAGS	4    /* Host flag registers             */
+#define DSP56K_HOST_CMD         5    /* Trig Host Command (0-31)        */
diff -u --recursive --new-file v2.1.35/linux/include/asm-m68k/fpu.h linux/include/asm-m68k/fpu.h
--- v2.1.35/linux/include/asm-m68k/fpu.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-m68k/fpu.h	Tue Apr 22 22:45:15 1997
@@ -0,0 +1,40 @@
+#ifndef __M68K_FPU_H
+#define __M68K_FPU_H
+
+#include <linux/config.h>
+
+/*
+ * MAX floating point unit state size (FSAVE/FRESTORE)
+ */
+
+#if defined(CONFIG_M68020) || defined(CONFIG_M68030)
+#define FPSTATESIZE (216/sizeof(unsigned char))
+#elif defined(CONFIG_M68040)
+#define FPSTATESIZE (96/sizeof(unsigned char))
+#elif defined(CONFIG_M68060)
+#define FPSTATESIZE (12/sizeof(unsigned char))
+#else
+#define FPSTATESIZE error no_cpu_type_configured
+#endif
+
+#endif /* __M68K_FPU_H */
+#ifndef __M68K_FPU_H
+#define __M68K_FPU_H
+
+#include <linux/config.h>
+
+/*
+ * MAX floating point unit state size (FSAVE/FRESTORE)
+ */
+
+#if defined(CONFIG_M68020) || defined(CONFIG_M68030)
+#define FPSTATESIZE (216/sizeof(unsigned char))
+#elif defined(CONFIG_M68040)
+#define FPSTATESIZE (96/sizeof(unsigned char))
+#elif defined(CONFIG_M68060)
+#define FPSTATESIZE (12/sizeof(unsigned char))
+#else
+#define FPSTATESIZE error no_cpu_type_configured
+#endif
+
+#endif /* __M68K_FPU_H */
diff -u --recursive --new-file v2.1.35/linux/include/asm-m68k/hardirq.h linux/include/asm-m68k/hardirq.h
--- v2.1.35/linux/include/asm-m68k/hardirq.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-m68k/hardirq.h	Tue Apr 22 22:45:15 1997
@@ -0,0 +1,26 @@
+#ifndef __M68K_HARDIRQ_H
+#define __M68K_HARDIRQ_H
+
+extern unsigned int local_irq_count[NR_CPUS];
+#define in_interrupt()	(local_irq_count[smp_processor_id()] != 0)
+
+#define hardirq_trylock(cpu)	((cpu)==0)	/* always true */
+#define hardirq_endlock(cpu)	do { } while (0)
+
+#define hardirq_enter(cpu)	(local_irq_count[cpu]++)
+#define hardirq_exit(cpu)	(local_irq_count[cpu]--)
+
+#endif
+#ifndef __M68K_HARDIRQ_H
+#define __M68K_HARDIRQ_H
+
+extern unsigned int local_irq_count[NR_CPUS];
+#define in_interrupt()	(local_irq_count[smp_processor_id()] != 0)
+
+#define hardirq_trylock(cpu)	((cpu)==0)	/* always true */
+#define hardirq_endlock(cpu)	do { } while (0)
+
+#define hardirq_enter(cpu)	(local_irq_count[cpu]++)
+#define hardirq_exit(cpu)	(local_irq_count[cpu]--)
+
+#endif
diff -u --recursive --new-file v2.1.35/linux/include/asm-m68k/ide.h linux/include/asm-m68k/ide.h
--- v2.1.35/linux/include/asm-m68k/ide.h	Mon Apr 14 16:28:19 1997
+++ linux/include/asm-m68k/ide.h	Thu Apr 17 13:20:49 1997
@@ -40,6 +40,7 @@
 #endif /* CONFIG_AMIGA */
 
 #ifdef CONFIG_ATARI
+#include <linux/interrupt.h>	/* intr_count */
 #include <asm/atarihw.h>
 #include <asm/atarihdreg.h>
 #include <asm/atariints.h>
diff -u --recursive --new-file v2.1.35/linux/include/asm-m68k/ioctl.h linux/include/asm-m68k/ioctl.h
--- v2.1.35/linux/include/asm-m68k/ioctl.h	Wed Sep 25 00:47:41 1996
+++ linux/include/asm-m68k/ioctl.h	Thu Apr 17 13:20:49 1997
@@ -1,4 +1,4 @@
-/* $Id: ioctl.h,v 1.1 1996/08/24 12:43:44 root Exp $
+/* $Id: ioctl.h,v 1.3 1997/04/16 15:10:07 jes Exp $
  *
  * linux/ioctl.h for Linux by H.H. Bergman.
  */
diff -u --recursive --new-file v2.1.35/linux/include/asm-m68k/irq.h linux/include/asm-m68k/irq.h
--- v2.1.35/linux/include/asm-m68k/irq.h	Wed Sep 25 00:47:41 1996
+++ linux/include/asm-m68k/irq.h	Thu Apr 17 13:20:49 1997
@@ -1,9 +1,6 @@
 #ifndef _M68K_IRQ_H_
 #define _M68K_IRQ_H_
 
-extern void disable_irq(unsigned int);
-extern void enable_irq(unsigned int);
-
 #include <linux/config.h>
 
 /*
@@ -54,10 +51,24 @@
  * Adding an interrupt service routine for a source with this bit
  * set indicates a special machine specific interrupt source.
  * The machine specific files define these sources.
+ *
+ * The IRQ_MACHSPEC bit is now gone - the only thing it did was to
+ * introduce unnecessary overhead.
+ *
+ * All interrupt handling is actually machine specific so it is better
+ * to use function pointers, as used by the Sparc port, and select the
+ * interrupt handling functions when initializing the kernel. This way
+ * we save some unnecessary overhead at run-time. 
+ *                                                      01/11/97 - Jes
  */
 
-#define IRQ_MACHSPEC	(0x10000000L)
-#define IRQ_IDX(irq)	((irq) & ~IRQ_MACHSPEC)
+extern void (*enable_irq)(unsigned int);
+extern void (*disable_irq)(unsigned int);
+
+extern int sys_request_irq(unsigned int, 
+	void (*)(int, void *, struct pt_regs *), 
+	unsigned long, const char *, void *);
+extern void sys_free_irq(unsigned int, void *);
 
 /*
  * various flags for request_irq()
diff -u --recursive --new-file v2.1.35/linux/include/asm-m68k/machdep.h linux/include/asm-m68k/machdep.h
--- v2.1.35/linux/include/asm-m68k/machdep.h	Fri Dec 20 01:20:02 1996
+++ linux/include/asm-m68k/machdep.h	Thu Apr 17 13:20:49 1997
@@ -18,9 +18,7 @@
 extern void (*(*mach_default_handler)[]) (int, void *, struct pt_regs *);
 extern int (*mach_request_irq) (unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
                                 unsigned long flags, const char *devname, void *dev_id);
-extern int (*mach_free_irq) (unsigned int irq, void *dev_id);
-extern void (*mach_enable_irq) (unsigned int irq);
-extern void (*mach_disable_irq) (unsigned int irq);
+extern void (*mach_free_irq) (unsigned int irq, void *dev_id);
 extern void (*mach_get_model) (char *model);
 extern int (*mach_get_hardware_list) (char *buffer);
 extern int (*mach_get_irq_list) (char *buf);
@@ -31,18 +29,14 @@
 			   int *min, int *sec);
 extern int (*mach_hwclk)(int, struct hwclk_time*);
 extern int (*mach_set_clock_mmss)(unsigned long);
-extern void (*mach_mksound)( unsigned int count, unsigned int ticks );
 extern void (*mach_reset)( void );
 extern int (*mach_floppy_init) (void);
 extern unsigned long (*mach_hd_init) (unsigned long, unsigned long);
 extern void (*mach_hd_setup)(char *, int *);
-extern void (*waitbut)(void);
 extern struct fb_info *(*mach_fb_init)(long *);
 extern long mach_max_dma_address;
-extern void (*mach_debug_init)(void);
 extern void (*mach_video_setup)(char *, int *);
 extern void (*mach_floppy_setup)(char *, int *);
 extern void (*mach_floppy_eject)(void);
-extern void (*mach_syms_export)(void);
 
 #endif /* _M68K_MACHDEP_H */
diff -u --recursive --new-file v2.1.35/linux/include/asm-m68k/namei.h linux/include/asm-m68k/namei.h
--- v2.1.35/linux/include/asm-m68k/namei.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-m68k/namei.h	Tue Apr 22 22:45:15 1997
@@ -0,0 +1,42 @@
+/*
+ * linux/include/asm-m68k/namei.h
+ *
+ * Included from linux/fs/namei.c
+ */
+
+#ifndef __M68K_NAMEI_H
+#define __M68K_NAMEI_H
+
+/* These dummy routines maybe changed to something useful
+ * for /usr/gnemul/ emulation stuff.
+ * Look at asm-sparc/namei.h for details.
+ */
+
+#define translate_namei(pathname, base, follow_links, res_inode)	\
+	do { } while (0)
+
+#define translate_open_namei(pathname, flag, mode, res_inode, base) \
+	do { } while (0)
+
+#endif
+/*
+ * linux/include/asm-m68k/namei.h
+ *
+ * Included from linux/fs/namei.c
+ */
+
+#ifndef __M68K_NAMEI_H
+#define __M68K_NAMEI_H
+
+/* These dummy routines maybe changed to something useful
+ * for /usr/gnemul/ emulation stuff.
+ * Look at asm-sparc/namei.h for details.
+ */
+
+#define translate_namei(pathname, base, follow_links, res_inode)	\
+	do { } while (0)
+
+#define translate_open_namei(pathname, flag, mode, res_inode, base) \
+	do { } while (0)
+
+#endif
diff -u --recursive --new-file v2.1.35/linux/include/asm-m68k/page.h linux/include/asm-m68k/page.h
--- v2.1.35/linux/include/asm-m68k/page.h	Fri Nov 22 05:56:36 1996
+++ linux/include/asm-m68k/page.h	Thu Apr 17 13:20:50 1997
@@ -8,10 +8,58 @@
 
 #ifdef __KERNEL__
 
+#include<linux/config.h>
+
 #define STRICT_MM_TYPECHECKS
 
+/*
+ * We don't need to check for alignment etc.
+ */
+#if defined(CONFIG_OPTIMIZE_040) || defined(CONFIG_OPTIMIZE_060)
+static inline void copy_page(unsigned long to, unsigned long from)
+{
+  unsigned long tmp;
+
+  __asm__ __volatile__("1:\t"
+		       ".chip 68040\n\t"
+		       "move16 %1@+,%0@+\n\t"
+		       "move16 %1@+,%0@+\n\t"
+		       ".chip 68k\n\t"
+		       "dbra  %2,1b\n\t"
+		       : "=a" (to), "=a" (from), "=d" (tmp)
+		       : "0" (to), "1" (from) , "2" (PAGE_SIZE / 32 - 1)
+		       );
+}
+
+static inline void clear_page(unsigned long page)
+{
+	unsigned long data, sp, tmp;
+
+	sp = page;
+
+	data = 0;
+
+	*((unsigned long *)(page))++ = 0;
+	*((unsigned long *)(page))++ = 0;
+	*((unsigned long *)(page))++ = 0;
+	*((unsigned long *)(page))++ = 0;
+
+	__asm__ __volatile__("1:\t"
+			     ".chip 68040\n\t"
+			     "move16 %2@+,%0@+\n\t"
+			     ".chip 68k\n\t"
+			     "subqw  #8,%2\n\t"
+			     "subqw  #8,%2\n\t"
+			     "dbra   %1,1b\n\t"
+			     : "=a" (page), "=d" (tmp)
+			     : "a" (sp), "0" (page),
+			       "1" ((PAGE_SIZE - 16) / 16 - 1));
+}
+
+#else
 #define clear_page(page)	memset((void *)(page), 0, PAGE_SIZE)
 #define copy_page(to,from)	memcpy((void *)(to), (void *)(from), PAGE_SIZE)
+#endif
 
 #ifdef STRICT_MM_TYPECHECKS
 /*
diff -u --recursive --new-file v2.1.35/linux/include/asm-m68k/pgtable.h linux/include/asm-m68k/pgtable.h
--- v2.1.35/linux/include/asm-m68k/pgtable.h	Fri Dec 20 01:20:03 1996
+++ linux/include/asm-m68k/pgtable.h	Thu Apr 17 13:20:50 1997
@@ -10,6 +10,170 @@
  * the m68k page table tree.
  */
 
+/* For virtual address to physical address conversion */
+extern unsigned long mm_vtop(unsigned long addr) __attribute__ ((const));
+extern unsigned long mm_ptov(unsigned long addr) __attribute__ ((const));
+#define VTOP(addr)  (mm_vtop((unsigned long)(addr)))
+#define PTOV(addr)  (mm_ptov((unsigned long)(addr)))
+
+/*
+ * Cache handling functions
+ */
+
+#define flush_icache()					\
+do {							\
+	if (CPU_IS_040_OR_060)				\
+		asm __volatile__ ("nop\n\t"		\
+				  ".chip 68040\n\t"	\
+				  "cinva %%ic\n\t"	\
+				  ".chip 68k");		\
+	else {						\
+		unsigned long _tmp;			\
+		asm __volatile__ ("movec %%cacr,%0\n\t"	\
+		     "orw %1,%0\n\t"			\
+		     "movec %0,%%cacr"			\
+		     : "=&d" (_tmp)			\
+		     : "id" (FLUSH_I));			\
+	}						\
+} while (0)
+
+/*
+ * invalidate the cache for the specified memory range.
+ * It starts at the physical address specified for
+ * the given number of bytes.
+ */
+extern void cache_clear (unsigned long paddr, int len);
+/*
+ * push any dirty cache in the specified memory range.
+ * It starts at the physical address specified for
+ * the given number of bytes.
+ */
+extern void cache_push (unsigned long paddr, int len);
+
+/*
+ * push and invalidate pages in the specified user virtual
+ * memory range.
+ */
+extern void cache_push_v (unsigned long vaddr, int len);
+
+/* cache code */
+#define FLUSH_I_AND_D	(0x00000808)
+#define FLUSH_I 	(0x00000008)
+
+/* This is needed whenever the virtual mapping of the current
+   process changes.  */
+#define __flush_cache_all()						\
+    do {								\
+	if (CPU_IS_040_OR_060)						\
+		__asm__ __volatile__ ("nop\n\t"				\
+				      ".chip 68040\n\t"			\
+				      "cpusha %dc\n\t"			\
+				      ".chip 68k");			\
+	else {								\
+		unsigned long _tmp;					\
+		__asm__ __volatile__ ("movec %%cacr,%0\n\t"		\
+				      "orw %1,%0\n\t"			\
+				      "movec %0,%%cacr"			\
+				      : "=&d" (_tmp)			\
+				      : "di" (FLUSH_I_AND_D));		\
+	}								\
+    } while (0)
+
+#define __flush_cache_030()						\
+    do {								\
+	if (CPU_IS_020_OR_030) {					\
+		unsigned long _tmp;					\
+		__asm__ __volatile__ ("movec %%cacr,%0\n\t"		\
+				      "orw %1,%0\n\t"			\
+				      "movec %0,%%cacr"			\
+				      : "=&d" (_tmp)			\
+				      : "di" (FLUSH_I_AND_D));		\
+	}								\
+    } while (0)
+
+#define flush_cache_all() __flush_cache_all()
+
+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
+}
+
+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
+	        __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
+	        __flush_cache_030();
+	}
+}
+
+/* Push the page at kernel virtual address and clear the icache */
+extern inline void flush_page_to_ram (unsigned long address)
+{
+    if (CPU_IS_040_OR_060) {
+	__asm__ __volatile__ ("nop\n\t"
+			      ".chip 68040\n\t"
+			      "cpushp %%dc,(%0)\n\t"
+			      "cinvp %%ic,(%0)\n\t"
+			      ".chip 68k"
+			      : : "a" (VTOP(address)));
+    }
+    else {
+	unsigned long _tmp;
+	__asm volatile ("movec %%cacr,%0\n\t"
+			"orw %1,%0\n\t"
+			"movec %0,%%cacr"
+			: "=&d" (_tmp)
+			: "di" (FLUSH_I));
+    }
+}
+
+/* Push n pages at kernel virtual address and clear the icache */
+extern inline void flush_pages_to_ram (unsigned long address, int n)
+{
+    if (CPU_IS_040_OR_060) {
+	while (n--) {
+	    __asm__ __volatile__ ("nop\n\t"
+				  ".chip 68040\n\t"
+				  "cpushp %%dc,(%0)\n\t"
+				  "cinvp %%ic,(%0)\n\t"
+				  ".chip 68k"
+				  : : "a" (VTOP(address)));
+	    address += PAGE_SIZE;
+	}
+    }
+    else {
+	unsigned long _tmp;
+	__asm volatile ("movec %%cacr,%0\n\t"
+			"orw %1,%0\n\t"
+			"movec %0,%%cacr"
+			: "=&d" (_tmp)
+			: "di" (FLUSH_I));
+    }
+}
+
 /*
  * flush all atc entries (user-space entries only for the 680[46]0).
  */
@@ -31,7 +195,7 @@
 				     ".chip 68k"
 				     : : "a" (addr));
 	} else
-		__asm__ __volatile__("pflush #0,#0,(%0)" : : "a" (addr));
+		__asm__ __volatile__("pflush #0,#4,(%0)" : : "a" (addr));
 }
 
 #define flush_tlb() __flush_tlb()
@@ -69,17 +233,27 @@
 		__flush_tlb();
 }
 
+extern inline void flush_tlb_kernel_page(unsigned long addr)
+{
+	if (CPU_IS_040_OR_060) {
+		unsigned long old_fs = get_fs();
+		set_fs(KERNEL_DS);
+		__asm__ __volatile__(".chip 68040\n\t"
+				     "pflush (%0)\n\t"
+				     ".chip 68k"
+				     : : "a" (addr));
+		set_fs(old_fs);
+	} else
+		__asm__ __volatile__("pflush #4,#4,(%0)" : : "a" (addr));
+}
+
 /* Certain architectures need to do special things when pte's
  * within a page table are directly modified.  Thus, the following
  * hook is made available.
  */
 #define set_pte(pteptr, pteval)					\
 	do{							\
-	*(pteptr) = (pteval);					\
-	if (CPU_IS_060)						\
-		__asm__ __volatile__(".chip 68060\n\t"		\
-				     "pflusha\n\t"		\
-				     ".chip 68k");		\
+		*(pteptr) = (pteval);				\
 	} while(0)
 
 
@@ -160,9 +334,9 @@
  * and initialized in head.S */
 extern int m68k_pgtable_cachemode;
 
-#if defined(CONFIG_M68040_OR_M68060_ONLY)
+#if defined(CPU_M68040_OR_M68060_ONLY)
 #define mm_cachebits _PAGE_CACHE040
-#elif defined(CONFIG_M68020_OR_M68030_ONLY)
+#elif defined(CPU_M68020_OR_M68030_ONLY)
 #define mm_cachebits 0
 #else
 extern unsigned long mm_cachebits;
@@ -234,12 +408,6 @@
 #define PAGE_PTR(address) \
 ((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK)
 
-/* For virtual address to physical address conversion */
-extern unsigned long mm_vtop(unsigned long addr) __attribute__ ((const));
-extern unsigned long mm_ptov(unsigned long addr) __attribute__ ((const));
-#define VTOP(addr)  (mm_vtop((unsigned long)(addr)))
-#define PTOV(addr)  (mm_ptov((unsigned long)(addr)))
-
 /*
  * Conversion functions: convert a page and protection to a page entry,
  * and a page entry and page directory to the page they refer to.
@@ -393,19 +561,17 @@
  * if any.
  */
 
-extern inline void nocache_page (unsigned long vaddr)
+/* Prior to calling these routines, the page should have been flushed
+ * from both the cache and ATC, or the CPU might not notice that the
+ * cache setting for the page has been changed. -jskov
+ */
+static inline void nocache_page (unsigned long vaddr)
 {
 	if (CPU_IS_040_OR_060) {
 		pgd_t *dir;
 		pmd_t *pmdp;
 		pte_t *ptep;
 
-		if(CPU_IS_060)
-			__asm__ __volatile__ (".chip 68060\n\t"
-					      "cpushp (%0)\n\t"
-					      ".chip 68k"
-					      : : "a" (VTOP(vaddr)));
-
 		dir = pgd_offset_k(vaddr);
 		pmdp = pmd_offset(dir,vaddr);
 		ptep = pte_offset(pmdp,vaddr);
@@ -447,6 +613,8 @@
 		if (pmd_none(*pmd)) {
 			if (page) {
 				memset((void *) page, 0, PAGE_SIZE);
+				flush_page_to_ram((unsigned long)page);
+				flush_tlb_kernel_page((unsigned long)page);
 				nocache_page((unsigned long)page);
 				pmd_set(pmd,page);
 				return page + address;
@@ -510,6 +678,7 @@
 		pte_t * page = (pte_t *) get_free_page(GFP_KERNEL);
 		if (pmd_none(*pmd)) {
 			if (page) {
+				flush_tlb_kernel_page((unsigned long)page);
 				nocache_page((unsigned long)page);
 				pmd_set(pmd, page);
 				return page + address;
@@ -563,160 +732,6 @@
 extern inline pgd_t * pgd_alloc(void)
 {
 	return (pgd_t *)get_pointer_table ();
-}
-
-#define flush_icache()					\
-do {							\
-	if (CPU_IS_040_OR_060)				\
-		asm __volatile__ ("nop\n\t"		\
-				  ".chip 68040\n\t"	\
-				  "cinva %%ic\n\t"	\
-				  ".chip 68k");		\
-	else {						\
-		unsigned long _tmp;			\
-		asm __volatile__ ("movec %%cacr,%0\n\t"	\
-		     "orw %1,%0\n\t"			\
-		     "movec %0,%%cacr"			\
-		     : "=&d" (_tmp)			\
-		     : "id" (FLUSH_I));			\
-	}						\
-} while (0)
-
-/*
- * invalidate the cache for the specified memory range.
- * It starts at the physical address specified for
- * the given number of bytes.
- */
-extern void cache_clear (unsigned long paddr, int len);
-/*
- * push any dirty cache in the specified memory range.
- * It starts at the physical address specified for
- * the given number of bytes.
- */
-extern void cache_push (unsigned long paddr, int len);
-
-/*
- * push and invalidate pages in the specified user virtual
- * memory range.
- */
-extern void cache_push_v (unsigned long vaddr, int len);
-
-/* cache code */
-#define FLUSH_I_AND_D	(0x00000808)
-#define FLUSH_I 	(0x00000008)
-
-/* This is needed whenever the virtual mapping of the current
-   process changes.  */
-#define __flush_cache_all()						\
-    do {								\
-	if (CPU_IS_040_OR_060)						\
-		__asm__ __volatile__ ("nop\n\t"				\
-				      ".chip 68040\n\t"			\
-				      "cpusha %dc\n\t"			\
-				      ".chip 68k");			\
-	else {								\
-		unsigned long _tmp;					\
-		__asm__ __volatile__ ("movec %%cacr,%0\n\t"		\
-				      "orw %1,%0\n\t"			\
-				      "movec %0,%%cacr"			\
-				      : "=&d" (_tmp)			\
-				      : "di" (FLUSH_I_AND_D));		\
-	}								\
-    } while (0)
-
-#define __flush_cache_030()						\
-    do {								\
-	if (CPU_IS_020_OR_030) {					\
-		unsigned long _tmp;					\
-		__asm__ __volatile__ ("movec %%cacr,%0\n\t"		\
-				      "orw %1,%0\n\t"			\
-				      "movec %0,%%cacr"			\
-				      : "=&d" (_tmp)			\
-				      : "di" (FLUSH_I_AND_D));		\
-	}								\
-    } while (0)
-
-#define flush_cache_all() __flush_cache_all()
-
-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
-}
-
-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
-	        __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
-	        __flush_cache_030();
-	}
-}
-
-/* Push the page at kernel virtual address and clear the icache */
-extern inline void flush_page_to_ram (unsigned long address)
-{
-    if (CPU_IS_040_OR_060) {
-	__asm__ __volatile__ ("nop\n\t"
-			      ".chip 68040\n\t"
-			      "cpushp %%dc,(%0)\n\t"
-			      "cinvp %%ic,(%0)\n\t"
-			      ".chip 68k"
-			      : : "a" (VTOP(address)));
-    }
-    else {
-	unsigned long _tmp;
-	__asm volatile ("movec %%cacr,%0\n\t"
-			"orw %1,%0\n\t"
-			"movec %0,%%cacr"
-			: "=&d" (_tmp)
-			: "di" (FLUSH_I));
-    }
-}
-
-/* Push n pages at kernel virtual address and clear the icache */
-extern inline void flush_pages_to_ram (unsigned long address, int n)
-{
-    if (CPU_IS_040_OR_060) {
-	while (n--) {
-	    __asm__ __volatile__ ("nop\n\t"
-				  ".chip 68040\n\t"
-				  "cpushp %%dc,(%0)\n\t"
-				  "cinvp %%ic,(%0)\n\t"
-				  ".chip 68k"
-				  : : "a" (VTOP(address)));
-	    address += PAGE_SIZE;
-	}
-    }
-    else {
-	unsigned long _tmp;
-	__asm volatile ("movec %%cacr,%0\n\t"
-			"orw %1,%0\n\t"
-			"movec %0,%%cacr"
-			: "=&d" (_tmp)
-			: "di" (FLUSH_I));
-    }
 }
 
 /*
diff -u --recursive --new-file v2.1.35/linux/include/asm-m68k/poll.h linux/include/asm-m68k/poll.h
--- v2.1.35/linux/include/asm-m68k/poll.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-m68k/poll.h	Tue Apr 22 22:45:15 1997
@@ -0,0 +1,42 @@
+#ifndef __m68k_POLL_H
+#define __m68k_POLL_H
+
+#define POLLIN		  1
+#define POLLPRI		  2
+#define POLLOUT		  4
+#define POLLERR		  8
+#define POLLHUP		 16
+#define POLLNVAL	 32
+#define POLLRDNORM	 64
+#define POLLWRNORM	POLLOUT
+#define POLLRDBAND	128
+#define POLLWRBAND	256
+
+struct pollfd {
+	int fd;
+	short events;
+	short revents;
+};
+
+#endif
+#ifndef __m68k_POLL_H
+#define __m68k_POLL_H
+
+#define POLLIN		  1
+#define POLLPRI		  2
+#define POLLOUT		  4
+#define POLLERR		  8
+#define POLLHUP		 16
+#define POLLNVAL	 32
+#define POLLRDNORM	 64
+#define POLLWRNORM	POLLOUT
+#define POLLRDBAND	128
+#define POLLWRBAND	256
+
+struct pollfd {
+	int fd;
+	short events;
+	short revents;
+};
+
+#endif
diff -u --recursive --new-file v2.1.35/linux/include/asm-m68k/processor.h linux/include/asm-m68k/processor.h
--- v2.1.35/linux/include/asm-m68k/processor.h	Sun Jan 26 02:07:46 1997
+++ linux/include/asm-m68k/processor.h	Thu Apr 17 13:20:50 1997
@@ -8,6 +8,7 @@
 #define __ASM_M68K_PROCESSOR_H
 
 #include <asm/segment.h>
+#include <asm/fpu.h>
 
 /*
  * User space process size: 3.75GB. This is hardcoded into a few places,
@@ -18,16 +19,13 @@
 /* This decides where the kernel will search for a free chunk of vm
  * space during mmap's.
  */
-#define TASK_UNMAPPED_BASE	(TASK_SIZE / 3)
+#define TASK_UNMAPPED_BASE	0xC0000000UL
 
 /*
  * Bus types
  */
 #define EISA_bus 0
 #define MCA_bus 0
-
-/* MAX floating point unit state size (FSAVE/FRESTORE) */
-#define FPSTATESIZE   (216/sizeof(unsigned char))
 
 /* 
  * if you change this structure, you must change the code and offsets
diff -u --recursive --new-file v2.1.35/linux/include/asm-m68k/scatterlist.h linux/include/asm-m68k/scatterlist.h
--- v2.1.35/linux/include/asm-m68k/scatterlist.h	Mon Dec 30 03:01:10 1996
+++ linux/include/asm-m68k/scatterlist.h	Thu Apr 17 13:20:50 1997
@@ -6,12 +6,9 @@
     char * alt_address; /* Location of actual if address is a 
 			 * dma indirect buffer.  NULL otherwise */
     unsigned int length;
-
-#ifdef __sparc__
-    char * dvma_address; /* A place to hang host-specific addresses at. */
-#endif
 };
 
+/* This is bogus and should go away. */
 #define ISA_DMA_THRESHOLD (0x00ffffff)
 
 #endif /* !(_M68K_SCATTERLIST_H) */
diff -u --recursive --new-file v2.1.35/linux/include/asm-m68k/semaphore.h linux/include/asm-m68k/semaphore.h
--- v2.1.35/linux/include/asm-m68k/semaphore.h	Mon Apr 14 16:28:19 1997
+++ linux/include/asm-m68k/semaphore.h	Thu Apr 17 13:20:50 1997
@@ -2,6 +2,8 @@
 #define _M68K_SEMAPHORE_H
 
 #include <linux/linkage.h>
+#include <asm/system.h>
+#include <asm/atomic.h>
 
 /*
  * SMP- and interrupt-safe semaphores..
@@ -12,21 +14,27 @@
  */
 
 struct semaphore {
-	int count;
-	int waiting;
+	atomic_t count;
+	atomic_t waking;
 	struct wait_queue * wait;
 };
 
-#define MUTEX ((struct semaphore) { 1, 0, NULL })
-#define MUTEX_LOCKED ((struct semaphore) { 0, 0, NULL })
+#define MUTEX ((struct semaphore) { { 1 }, { 0 }, NULL })
+#define MUTEX_LOCKED ((struct semaphore) { { 0 }, { 0 }, NULL })
 
 asmlinkage void __down_failed(void /* special register calling convention */);
+asmlinkage int  __down_failed_interruptible(void  /* params in registers */);
 asmlinkage void __up_wakeup(void /* special register calling convention */);
 
 extern void __down(struct semaphore * sem);
 extern void __up(struct semaphore * sem);
 
-#define sema_init(sem, val)	((sem)->count = val)
+#define sema_init(sem, val)	atomic_set(&((sem)->count), val)
+
+static inline void wake_one_more(struct semaphore * sem)
+{
+	atomic_inc(&sem->waking);
+}
 
 static inline int waking_non_zero(struct semaphore *sem)
 {
@@ -54,12 +62,34 @@
 	__asm__ __volatile__(
 		"| atomic down operation\n\t"
 		"lea %%pc@(1f),%%a0\n\t"
-		"subql #1,%0\n\t"
+		"subql #1,%0@\n\t"
 		"jmi " SYMBOL_NAME_STR(__down_failed) "\n"
 		"1:"
 		: /* no outputs */
-		: "m" (sem->count), "a" (sem1)
+		: "a" (sem1)
 		: "%a0", "memory");
+}
+
+/*
+ * This version waits in interruptible state so that the waiting
+ * process can be killed.  The down_failed_interruptible routine
+ * returns negative for signalled and zero for semaphore acquired.
+ */
+extern inline int down_interruptible(struct semaphore * sem)
+{
+	register int ret __asm__ ("%d0");
+	register struct semaphore *sem1 __asm__ ("%a1") = sem;
+	__asm__ __volatile__(
+		"| atomic interruptible down operation\n\t"
+		"lea %%pc@(1f),%%a0\n\t"
+		"subql #1,%1@\n\t"
+		"jmi " SYMBOL_NAME_STR(__down_failed_interruptible) "\n\t"
+		"clrl %0\n"
+		"1:"
+		: "=d" (ret)
+		: "a" (sem1)
+		: "%d0", "%a0", "memory");
+	return ret;
 }
 
 /*
diff -u --recursive --new-file v2.1.35/linux/include/asm-m68k/serial.h linux/include/asm-m68k/serial.h
--- v2.1.35/linux/include/asm-m68k/serial.h	Fri Dec 20 01:20:03 1996
+++ linux/include/asm-m68k/serial.h	Thu Apr 17 13:20:50 1997
@@ -171,7 +171,10 @@
  */
 struct serial_icounter_struct {
 	int cts, dsr, rng, dcd;
-	int reserved[16];
+	int rx, tx;
+	int frame, overrun, parity, brk;
+	int buf_overrun;
+	int reserved[9];
 };
 
 
@@ -192,7 +195,9 @@
  * Counters of the input lines (CTS, DSR, RI, CD) interrupts
  */
 struct async_icount {
-	__u32	cts, dsr, rng, dcd;	
+	__u32	cts, dsr, rng, dcd, tx, rx;
+	__u32	frame, parity, overrun, brk;
+	__u32	buf_overrun;
 };
 
 struct async_struct {
@@ -281,7 +286,7 @@
 static __inline__ void rs_sched_event(struct async_struct *info, int event)
 {
 	info->event |= 1 << event;
-	queue_task_irq(&info->tqueue, &tq_serial);
+	queue_task(&info->tqueue, &tq_serial);
 	mark_bh(SERIAL_BH);
 }
 
@@ -299,7 +304,8 @@
 	}
 	*tty->flip.flag_buf_ptr++ = err;
 	*tty->flip.char_buf_ptr++ = ch;
-	queue_task_irq(&tty->flip.tqueue, &tq_timer);
+	info->icount.rx++;
+	queue_task(&tty->flip.tqueue, &tq_timer);
 }
 
 static __inline__ int rs_get_tx_char( struct async_struct *info )
@@ -308,6 +314,7 @@
 	
 	if (info->x_char) {
 		ch = info->x_char;
+		info->icount.tx++;
 		info->x_char = 0;
 		return( ch );
 	}
@@ -317,6 +324,7 @@
 
 	ch = info->xmit_buf[info->xmit_tail++];
 	info->xmit_tail &= SERIAL_XMIT_SIZE - 1;
+	info->icount.tx++;
 	if (--info->xmit_cnt < WAKEUP_CHARS)
 		rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);
 	return( ch );
@@ -348,8 +356,7 @@
 #ifdef SERIAL_DEBUG_OPEN
 			printk("scheduling hangup...");
 #endif
-			queue_task_irq(&info->tqueue_hangup,
-				       &tq_scheduler);
+			queue_task(&info->tqueue_hangup, &tq_scheduler);
 		}
 	}
 }
diff -u --recursive --new-file v2.1.35/linux/include/asm-m68k/setup.h linux/include/asm-m68k/setup.h
--- v2.1.35/linux/include/asm-m68k/setup.h	Fri Dec 20 01:20:03 1996
+++ linux/include/asm-m68k/setup.h	Thu Apr 17 13:20:50 1997
@@ -48,7 +48,7 @@
 #elif defined(CONFIG_ATARI) || defined(CONFIG_MAC)
 #  define MACH_IS_AMIGA (m68k_machtype == MACH_AMIGA)
 #else
-#  define CONFIG_AMIGA_ONLY
+#  define MACH_AMIGA_ONLY
 #  define MACH_IS_AMIGA (1)
 #  define MACH_TYPE (MACH_AMIGA)
 #endif
@@ -58,7 +58,7 @@
 #elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC)
 #  define MACH_IS_ATARI (m68k_machtype == MACH_ATARI)
 #else
-#  define CONFIG_ATARI_ONLY
+#  define MACH_ATARI_ONLY
 #  define MACH_IS_ATARI (1)
 #  define MACH_TYPE (MACH_ATARI)
 #endif
@@ -149,7 +149,7 @@
 #elif defined(CONFIG_M68030) || defined(CONFIG_M68040) || defined(CONFIG_M68060)
 #  define CPU_IS_020 (m68k_cputype & CPU_68020)
 #else
-#  define CONFIG_M68020_ONLY
+#  define CPU_M68020_ONLY
 #  define CPU_IS_020 (1)
 #endif
 
@@ -158,7 +158,7 @@
 #elif defined(CONFIG_M68020) || defined(CONFIG_M68040) || defined(CONFIG_M68060)
 #  define CPU_IS_030 (m68k_cputype & CPU_68030)
 #else
-#  define CONFIG_M68030_ONLY
+#  define CPU_M68030_ONLY
 #  define CPU_IS_030 (1)
 #endif
 
@@ -167,7 +167,7 @@
 #elif defined(CONFIG_M68020) || defined(CONFIG_M68030) || defined(CONFIG_M68060)
 #  define CPU_IS_040 (m68k_cputype & CPU_68040)
 #else
-#  define CONFIG_M68040_ONLY
+#  define CPU_M68040_ONLY
 #  define CPU_IS_040 (1)
 #endif
 
@@ -176,18 +176,18 @@
 #elif defined(CONFIG_M68020) || defined(CONFIG_M68030) || defined(CONFIG_M68040)
 #  define CPU_IS_060 (m68k_cputype & CPU_68060)
 #else
-#  define CONFIG_M68060_ONLY
+#  define CPU_M68060_ONLY
 #  define CPU_IS_060 (1)
 #endif
 
 #if !defined(CONFIG_M68020) && !defined(CONFIG_M68030)
 #  define CPU_IS_020_OR_030 (0)
 #else
-#  define CONFIG_M68020_OR_M68030
+#  define CPU_M68020_OR_M68030
 #  if defined(CONFIG_M68040) || defined(CONFIG_M68060)
 #    define CPU_IS_020_OR_030 (!m68k_is040or060)
 #  else
-#    define CONFIG_M68020_OR_M68030_ONLY
+#    define CPU_M68020_OR_M68030_ONLY
 #    define CPU_IS_020_OR_030 (1)
 #  endif
 #endif
@@ -195,11 +195,11 @@
 #if !defined(CONFIG_M68040) && !defined(CONFIG_M68060)
 #  define CPU_IS_040_OR_060 (0)
 #else
-#  define CONFIG_M68040_OR_M68060
+#  define CPU_M68040_OR_M68060
 #  if defined(CONFIG_M68020) || defined(CONFIG_M68030)
 #    define CPU_IS_040_OR_060 (m68k_is040or060)
 #  else
-#    define CONFIG_M68040_OR_M68060_ONLY
+#    define CPU_M68040_OR_M68060_ONLY
 #    define CPU_IS_040_OR_060 (1)
 #  endif
 #endif
diff -u --recursive --new-file v2.1.35/linux/include/asm-m68k/sigcontext.h linux/include/asm-m68k/sigcontext.h
--- v2.1.35/linux/include/asm-m68k/sigcontext.h	Fri Nov 22 05:56:36 1996
+++ linux/include/asm-m68k/sigcontext.h	Thu Apr 17 13:20:50 1997
@@ -1,6 +1,8 @@
 #ifndef _ASM_M68k_SIGCONTEXT_H
 #define _ASM_M68k_SIGCONTEXT_H
 
+#include<asm/fpu.h>
+
 struct sigcontext {
 	unsigned long  sc_mask; 	/* old sigmask */
 	unsigned long  sc_usp;		/* old user stack pointer */
@@ -13,7 +15,7 @@
 	unsigned short sc_formatvec;
 	unsigned long  sc_fpregs[2*3];  /* room for two fp registers */
 	unsigned long  sc_fpcntl[3];
-	unsigned char  sc_fpstate[216];
+	unsigned char  sc_fpstate[FPSTATESIZE];
 };
 
 #endif
diff -u --recursive --new-file v2.1.35/linux/include/asm-m68k/smp_lock.h linux/include/asm-m68k/smp_lock.h
--- v2.1.35/linux/include/asm-m68k/smp_lock.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-m68k/smp_lock.h	Tue Apr 22 22:45:15 1997
@@ -0,0 +1,28 @@
+#ifndef __M68K_SMPLOCK_H
+#define __M68K_SMPLOCK_H
+
+/*
+ * We don't do SMP so this is again one of these silly dummy files
+ * to keep the kernel source looking nice ;-(.
+ */
+
+#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)
+
+#endif
+#ifndef __M68K_SMPLOCK_H
+#define __M68K_SMPLOCK_H
+
+/*
+ * We don't do SMP so this is again one of these silly dummy files
+ * to keep the kernel source looking nice ;-(.
+ */
+
+#define lock_kernel()		do { } while(0)
+#define unlock_kernel()		do { } while(0)
+#define release_kernel_lock(task, cpu, depth)	((depth) = 1)
+#define reaquire_kernel_lock(task, cpu, depth)	do { } while(0)
+
+#endif
diff -u --recursive --new-file v2.1.35/linux/include/asm-m68k/softirq.h linux/include/asm-m68k/softirq.h
--- v2.1.35/linux/include/asm-m68k/softirq.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-m68k/softirq.h	Tue Apr 22 22:45:15 1997
@@ -0,0 +1,118 @@
+#ifndef __M68K_SOFTIRQ_H
+#define __M68K_SOFTIRQ_H
+
+/*
+ * Software interrupts.. no SMP here either.
+ */
+#define get_active_bhs()	(bh_mask & bh_active)
+#define clear_active_bhs(x)	atomic_clear_mask((x),&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;
+}
+
+extern int __m68k_bh_counter;
+
+extern inline void start_bh_atomic(void)
+{
+	__m68k_bh_counter++;
+	barrier();
+}
+
+extern inline void end_bh_atomic(void)
+{
+	barrier();
+	__m68k_bh_counter--;
+}
+
+/* These are for the irq's testing the lock */
+#define softirq_trylock()  (__m68k_bh_counter ? 0 : (__m68k_bh_counter=1))
+#define softirq_endlock()  (__m68k_bh_counter = 0)
+
+#endif
+#ifndef __M68K_SOFTIRQ_H
+#define __M68K_SOFTIRQ_H
+
+/*
+ * Software interrupts.. no SMP here either.
+ */
+#define get_active_bhs()	(bh_mask & bh_active)
+#define clear_active_bhs(x)	atomic_clear_mask((x),&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 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;
+}
+
+extern int __m68k_bh_counter;
+
+extern inline void start_bh_atomic(void)
+{
+	__m68k_bh_counter++;
+	barrier();
+}
+
+extern inline void end_bh_atomic(void)
+{
+	barrier();
+	__m68k_bh_counter--;
+}
+
+/* These are for the irq's testing the lock */
+#define softirq_trylock()  (__m68k_bh_counter ? 0 : (__m68k_bh_counter=1))
+#define softirq_endlock()  (__m68k_bh_counter = 0)
+
+#endif
diff -u --recursive --new-file v2.1.35/linux/include/asm-m68k/spinlock.h linux/include/asm-m68k/spinlock.h
--- v2.1.35/linux/include/asm-m68k/spinlock.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-m68k/spinlock.h	Tue Apr 22 22:45:15 1997
@@ -0,0 +1,74 @@
+#ifndef __M68K_SPINLOCK_H
+#define __M68K_SPINLOCK_H
+
+/*
+ * We don't do SMP on the m68k .... at least not yet.
+ */
+
+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) \
+	do { save_flags(flags); cli(); } while (0)
+#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)
+
+#endif
+#ifndef __M68K_SPINLOCK_H
+#define __M68K_SPINLOCK_H
+
+/*
+ * We don't do SMP on the m68k .... at least not yet.
+ */
+
+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(lock)	do { } while(0)
+#define spin_lock_irq(lock)	cli()
+#define spin_unlock_irq(lock)	sti()
+
+#define spin_lock_irqsave(lock, flags) \
+	do { save_flags(flags); cli(); } while (0)
+#define spin_unlock_irqrestore(lock, flags) \
+	restore_flags(flags)
+
+#endif
diff -u --recursive --new-file v2.1.35/linux/include/asm-m68k/system.h linux/include/asm-m68k/system.h
--- v2.1.35/linux/include/asm-m68k/system.h	Wed Sep 25 00:47:42 1996
+++ linux/include/asm-m68k/system.h	Thu Apr 17 13:20:50 1997
@@ -65,21 +65,24 @@
 
 #if defined(CONFIG_ATARI) && !defined(CONFIG_AMIGA) && !defined(CONFIG_MAC)
 /* block out HSYNC on the atari */
-#define sti() __asm__ __volatile__ ("andiw #0xfbff,%/sr": : : "memory")
+#define __sti() __asm__ __volatile__ ("andiw #0xfbff,%/sr": : : "memory")
 #else /* portable version */
-#define sti() __asm__ __volatile__ ("andiw #0xf8ff,%/sr": : : "memory")
+#define __sti() __asm__ __volatile__ ("andiw #0xf8ff,%/sr": : : "memory")
 #endif /* machine compilation types */ 
-#define cli() __asm__ __volatile__ ("oriw  #0x0700,%/sr": : : "memory")
+#define __cli() __asm__ __volatile__ ("oriw  #0x0700,%/sr": : : "memory")
 #define nop() __asm__ __volatile__ ("nop"::)
 #define mb()  __asm__ __volatile__ (""   : : :"memory")
 
-#define save_flags(x) \
+#define __save_flags(x) \
 __asm__ __volatile__("movew %/sr,%0":"=d" (x) : /* no input */ :"memory")
 
-#define restore_flags(x) \
+#define __restore_flags(x) \
 __asm__ __volatile__("movew %0,%/sr": /* no outputs */ :"d" (x) : "memory")
 
-#define iret() __asm__ __volatile__ ("rte": : :"memory", "sp", "cc")
+#define cli() __cli()
+#define sti() __sti()
+#define save_flags(x) __save_flags(x)
+#define restore_flags(x) __restore_flags(x)
 
 #ifndef CONFIG_RMW_INSNS
 static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
diff -u --recursive --new-file v2.1.35/linux/include/asm-m68k/termbits.h linux/include/asm-m68k/termbits.h
--- v2.1.35/linux/include/asm-m68k/termbits.h	Wed May  8 00:32:41 1996
+++ linux/include/asm-m68k/termbits.h	Thu Apr 17 13:20:50 1997
@@ -123,6 +123,7 @@
 #define  B230400 0010003
 #define  B460800 0010004
 #define CIBAUD	  002003600000	/* input baud rate (not used) */
+#define CMSPAR	  010000000000		/* mark or space (stick) parity */
 #define CRTSCTS	  020000000000		/* flow control */
 
 /* c_lflag bits */
diff -u --recursive --new-file v2.1.35/linux/include/asm-m68k/termios.h linux/include/asm-m68k/termios.h
--- v2.1.35/linux/include/asm-m68k/termios.h	Thu Mar 27 14:40:07 1997
+++ linux/include/asm-m68k/termios.h	Thu Apr 17 13:20:50 1997
@@ -53,6 +53,7 @@
 #define N_PPP		3
 #define N_STRIP		4
 #define N_AX25		5
+#define N_X25		6	/* X.25 async */
 
 #ifdef __KERNEL__
 
diff -u --recursive --new-file v2.1.35/linux/include/asm-m68k/uaccess.h linux/include/asm-m68k/uaccess.h
--- v2.1.35/linux/include/asm-m68k/uaccess.h	Fri Jan  3 08:48:37 1997
+++ linux/include/asm-m68k/uaccess.h	Thu Apr 17 13:20:50 1997
@@ -714,6 +714,9 @@
  __constant_copy_to_user(to, from, n) :		\
  __generic_copy_to_user(to, from, n))
 
+#define __copy_from_user(to, from, n) copy_from_user(to, from, n)
+#define __copy_to_user(to, from, n) copy_to_user(to, from, n)
+
 /*
  * Copy a null terminated string from userspace.
  */
diff -u --recursive --new-file v2.1.35/linux/include/asm-m68k/unistd.h linux/include/asm-m68k/unistd.h
--- v2.1.35/linux/include/asm-m68k/unistd.h	Fri Apr  4 08:52:25 1997
+++ linux/include/asm-m68k/unistd.h	Thu Apr 17 13:20:50 1997
@@ -171,7 +171,9 @@
 #define __NR_mremap		163
 #define __NR_setresuid		164
 #define __NR_getresuid		165
-#define __NR_nfsservctl		166
+#define __NR_query_module	167
+#define __NR_poll		168
+#define __NR_nfsservctl		169
 
 /* user-visible error numbers are in the range -1 - -122: see
    <asm-m68k/errno.h> */
@@ -179,7 +181,10 @@
 #define __syscall_return(type, res) \
 do { \
 	if ((unsigned long)(res) >= (unsigned long)(-125)) { \
-		errno = -(res); \
+	/* avoid using res which is declared to be in register d0; \
+	   errno might expand to a function call and clobber it.  */ \
+		int __err = -(res); \
+		errno = __err; \
 		res = -1; \
 	} \
 	return (type) (res); \
diff -u --recursive --new-file v2.1.35/linux/include/asm-m68k/user.h linux/include/asm-m68k/user.h
--- v2.1.35/linux/include/asm-m68k/user.h	Fri Nov 22 05:56:36 1996
+++ linux/include/asm-m68k/user.h	Thu Apr 17 13:20:50 1997
@@ -2,7 +2,7 @@
 #define _M68K_USER_H
 
 #include <asm/page.h>
-#include <linux/ptrace.h>
+
 /* 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).  There are quite a number of
@@ -74,7 +74,8 @@
 				   esp register.  */
   long int signal;     		/* Signal that caused the core dump. */
   int reserved;			/* No longer used */
-  struct pt_regs * u_ar0;	/* Used by gdb to help find the values for */
+  struct user_regs_struct *u_ar0;
+				/* Used by gdb to help find the values for */
 				/* the registers. */
   struct user_m68kfp_struct* u_fpstate;	/* Math Co-processor pointer. */
   unsigned long magic;		/* To uniquely identify a core file */
diff -u --recursive --new-file v2.1.35/linux/include/asm-m68k/zorro.h linux/include/asm-m68k/zorro.h
--- v2.1.35/linux/include/asm-m68k/zorro.h	Fri Dec 20 01:20:03 1996
+++ linux/include/asm-m68k/zorro.h	Wed Dec 31 16:00:00 1969
@@ -1,577 +0,0 @@
-/*
- * asm-m68k/zorro.h -- Amiga AutoConfig (Zorro) Expansion Device Definitions
- *
- * Copyright (C) 1995 Geert Uytterhoeven
- *
- * 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.
- */
-
-#ifndef _M68K_ZORRO_H
-#define _M68K_ZORRO_H
-
-#ifndef __ASSEMBLY__
-
-/*
- * Defined Board Manufacturers
- *
- * Please update arch/m68k/amiga/zorro.c if you make changes here
- * Many IDs were obtained from ExpName/Identify ((C) Richard Körber)
- * and by looking at the NetBSD-Amiga kernel sources
- */
-
-#define MANUF_PACIFIC          (0x00D3)	/* Pacific Peripherals */
-#define PROD_SE_2000_A500      (0x00)	/* SE 2000 A500 */
-#define PROD_PACIFIC_HD        (0x0A)	/* HD Controller */
-
-#define MANUF_KUPKE            (0x00DD)	/* Kupke */
-#define PROD_GOLEM_BOX_2       (0x00)	/* Golem RAM Box 2MB */
-
-#define MANUF_MEMPHIS          (0x0100)	/* Memphis */
-#define PROD_STORMBRINGER      (0x00)	/* Stormbringer */
-
-#define MANUF_COMMODORE2       (0x0201)	/* Commodore Braunschweig */
-#define PROD_A2088             (0x01)	/* CBM A2088 XT Bridgeboard */
-#define PROD_A2286             (0x02)	/* CBM A2286 AT Bridgeboard */
-#define PROD_A4091_2           (0x54)	/* CBM A4091 SCSI Controller */
-#define PROD_A2386SX           (0x67)	/* CBM A2386-SX Bridgeboard */
-
-#define MANUF_COMMODORE        (0x0202)	/* Commodore West Chester */
-#define PROD_A2090A            (0x01)	/* CBM A2090/A2090A HD Controller */
-#define PROD_A590              (0x02)	/* CBM A590 SCSI Controller */
-#define PROD_A2091             (0x03)	/* CBM A2091 SCSI Controller */
-#define PROD_A2090B            (0x04)	/* CBM A2090B 2090 Autoboot Card */
-#define PROD_ARCNET            (0x09)	/* CBM A2060 Arcnet Card */
-#define PROD_CBMRAM            (0x0A)	/* CBM A2052/58.RAM | 590/2091.RAM */
-#define PROD_A560RAM           (0x20)	/* CBM A560 Memory Module */
-#define PROD_A2232PROTO        (0x45)	/* CBM A2232 Serial Prototype */
-#define PROD_A2232             (0x46)	/* CBM A2232 Serial Production */
-#define PROD_A2620             (0x50)	/* CBM A2620 68020/RAM Card */
-#define PROD_A2630             (0x51)	/* CBM A2630 68030/RAM Card */
-#define PROD_A4091             (0x54)	/* CBM A4091 SCSI Controller */
-#define PROD_A2065_2           (0x5A)	/* A2065 Ethernet Card */
-#define PROD_ROMULATOR         (0x60)	/* CBM Romulator Card */
-#define PROD_A3000TESTFIX      (0x61)	/* CBM A3000 Test Fixture */
-#define PROD_A2386SX_2         (0x67)	/* A2386-SX Bridgeboard */
-#define PROD_A2065             (0x70)	/* CBM A2065 Ethernet Card */
-
-#define MANUF_COMMODORE3       (0x0203)	/* Commodore West Chester */
-#define PROD_A2090A_CM         (0x03)	/* A2090A Combitec/MacroSystem */
-
-#define MANUF_KCS              (0x02FF)	/* Kolff Computer Supplies */
-#define PROD_POWER_BOARD       (0x00)	/* KCS Power PC Board */
-
-#define MANUF_CARDCO           (0x03EC)	/* Cardco */
-#define PROD_KRONOS_2000_SCSI  (0x04)	/* Kronos 2000 SCSI Controller */
-#define PROD_A1000_SCSI        (0x0C)	/* A1000 SCSI Controller */
-#define PROD_ESCORT_SCSI       (0x0E)	/* Escort SCSI Controller */
-#define PROD_CC_A2410          (0xF5)	/* Cardco A2410 Hires Graphics Card */
-
-#define MANUF_A_SQUARED        (0x03ED)	/* A-Squared */
-#define PROD_LIVE_2000         (0x01)	/* Live! 2000 */
-
-#define MANUF_COMSPEC          (0x03EE)	/* ComSpec Communications */
-#define PROD_AX2000            (0x01)	/* AX2000 */
-
-#define MANUF_ANAKIN           (0x03F1)	/* Anakin */
-#define PROD_EASYL             (0x01)	/* Easyl Tablet */
-
-#define MANUF_MICROBOTICS      (0x03F2)	/* MicroBotics */
-#define PROD_STARBOARD_II      (0x00)	/* StarBoard II */
-#define PROD_STARDRIVE         (0x02)	/* StarDrive */
-#define PROD_8_UP_A            (0x03)	/* 8-Up (Rev A) */
-#define PROD_8_UP_Z            (0x04)	/* 8-Up (Rev Z) */
-#define PROD_VXL_RAM           (0x44)	/* VXL RAM */
-#define PROD_VXL_30            (0x45)	/* VXL-30 Turbo Board */
-#define PROD_MBX_1200          (0x81)	/* MBX 1200 */
-#define PROD_HARDFRAME_2000    (0x9E)	/* Hardframe 2000 */
-#define PROD_MBX_1200_2        (0xC1)	/* MBX 1200 */
-
-#define MANUF_ACCESS           (0x03F4)	/* Access Associates */
-
-#define MANUF_EXPANSION_TECH   (0x03F6)	/* Expansion Technologies */
-
-#define MANUF_ASDG             (0x03FF)	/* ASDG */
-#define PROD_ASDG_MEMORY       (0x01)	/* Memory Expansion */
-#define PROD_ASDG_MEMORY_2     (0x02)	/* Memory Expansion */
-#define PROD_LAN_ROVER         (0xFE)	/* Lan Rover Ethernet */
-#define PROD_TWIN_X            (0xFF)	/* Twin-X Serial Card */
-
-#define MANUF_IMTRONICS        (0x0404)	/* Imtronics */
-#define PROD_HURRICANE_2800    (0x39)	/* Hurricane 2800 68030 */
-#define PROD_HURRICANE_2800_2  (0x57)	/* Hurricane 2800 68030 */
-
-#define MANUF_UNIV_OF_LOWELL   (0x0406)	/* University of Lowell */
-#define PROD_A2410             (0x00)	/* CBM A2410 Hires Graphics Card */
-
-#define MANUF_AMERISTAR        (0x041D)	/* Ameristar */
-#define PROD_AMERISTAR2065     (0x01)	/* A2065 Ethernet Card */
-#define PROD_A560              (0x09)	/* Arcnet Card */
-#define PROD_A4066             (0x0A)	/* A4066 Ethernet Card */
-
-#define MANUF_SUPRA            (0x0420)	/* Supra */
-#define PROD_SUPRADRIVE_4x4    (0x01)	/* SupraDrive 4x4 SCSI Controller */
-#define PROD_SUPRA_2000        (0x03)	/* 2000 DMA HD */
-#define PROD_SUPRA_500         (0x05)	/* 500 HD/RAM */
-#define PROD_SUPRA_500RX       (0x09)	/* 500RX/2000 RAM */
-#define PROD_SUPRA_500RX_2     (0x0A)	/* 500RX/2000 RAM */
-#define PROD_SUPRA_2400ZI      (0x0B)	/* 2400zi Modem */
-#define PROD_WORDSYNC          (0x0C)	/* Supra Wordsync SCSI Controller */
-#define PROD_WORDSYNC_II       (0x0D)	/* Supra Wordsync II SCSI Controller */
-#define PROD_SUPRA_2400ZIPLUS  (0x10)	/* 2400zi+ Modem */
-
-#define MANUF_CSA              (0x0422)	/* CSA */
-#define PROD_MAGNUM            (0x11)	/* Magnum 40 SCSI Controller */
-#define PROD_12GAUGE           (0x15)	/* 12 Gauge SCSI Controller */
-
-#define MANUF_GVP3             (0x06E1)	/* Great Valley Products */
-#define PROD_IMPACT            (0x08)	/* Impact SCSI/Memory */
-
-#define MANUF_BYTEBOX          (0x07DA)	/* ByteBox */
-#define PROD_BYTEBOX_A500      (0x00)	/* A500 */
-
-#define MANUF_HACKER           (0x07DB)	/* Test only: no product definitions */
-
-#define MANUF_POWER_COMPUTING  (0x07DC)	/* Power Computing (DKB) */
-#define PROD_DKB_3128          (0x0E)	/* DKB 3128 RAM */
-#define PROD_VIPER_II_COBRA    (0x12)	/* Viper II Turbo Board (DKB Cobra) */
-
-#define MANUF_GVP              (0x07E1)	/* Great Valley Products */
-#define PROD_IMPACT_I_4K       (0x01)	/* Impact Series-I SCSI 4K */
-#define PROD_IMPACT_I_16K_2    (0x02)	/* Impact Series-I SCSI 16K/2 */
-#define PROD_IMPACT_I_16K_3    (0x03)	/* Impact Series-I SCSI 16K/3 */
-#define PROD_IMPACT_3001_IDE   (0x08)	/* Impact 3001 IDE */
-#define PROD_IMPACT_3001_RAM   (0x09)	/* Impact 3001 RAM */
-#define PROD_GVPIISCSI         (0x0B)	/* GVP Series II SCSI Controller */
-#define PROD_GVPIISCSI_2       (0x09)	/* evidence that the driver works
-					   for this product code also */
-#define PROD_GVPIIRAM          (0x0A)	/* GVP Series II RAM */
-#define PROD_GVP               (0x0B)	/* This code is used by a wide range of
-					   GVP products - use the epc to
-					   identify it correctly */
-#define PROD_GVP_A2000_030     (0x0D)	/* GVP A2000 68030 Turbo Board */
-#define PROD_IMPACT_3001_IDE_2 (0x0D)	/* Impact 3001 IDE */
-#define PROD_GFORCE_040_SCSI   (0x16)	/* GForce 040 with SCSI (new) */
-#define PROD_GVPIV_24          (0x20)	/* GVP IV-24 Graphics Board */
-#define PROD_GFORCE_040        (0xFF)	/* GForce 040 Turbo Board */
-/* #define PROD_GVPIO_EXT      (0xFF)*/	/* GVP I/O Extender */
-
-#define MANUF_SYNERGY          (0x07E5)	/* Synergy */
-
-#define MANUF_XETEC            (0x07E6)	/* Xetec */
-#define PROD_FASTCARD_SCSI     (0x01)	/* FastCard SCSI Controller */
-#define PROD_FASTCARD_RAM      (0x02)	/* FastCard RAM */
-
-#define MANUF_PPI              (0x07EA)	/* Progressive Peripherals Inc. */
-#define PROD_MERCURY           (0x00)	/* Mercury Turbo Board */
-#define PROD_PPS_A3000_040     (0x01)	/* PP&S A3000 68040 Turbo Board */
-#define PROD_PPS_A2000_040     (0x69)	/* PP&S A2000 68040 Turbo Board */
-#define PROD_ZEUS              (0x96)	/* Zeus SCSI Controller */
-#define PROD_PPS_A500_040      (0xBB)	/* PP&S A500 68040 Turbo Board */
-
-#define MANUF_XEBEC            (0x07EC)	/* Xebec */
-
-#define MANUF_SPIRIT           (0x07F2)	/* Spirit */
-#define PROD_HDA_506           (0x04)	/* HDA 506 Harddisk */
-#define PROD_OCTABYTE_RAM      (0x06)	/* OctaByte RAM */
-
-#define MANUF_BSC              (0x07FE)	/* BSC */
-#define PROD_ALF_3_SCSI        (0x03)	/* BSC ALF 3 SCSI Controller */
-
-#define MANUF_BSC3             (0x0801)	/* BSC */
-#define PROD_ALF_2_SCSI        (0x01)	/* ALF 2 SCSI Controller */
-#define PROD_ALF_3_SCSI_2      (0x03)	/* ALF 3 SCSI Controller */
-
-#define MANUF_C_LTD            (0x0802)	/* C Ltd. */
-#define PROD_KRONOS_SCSI       (0x04)	/* Kronos SCSI Controller */
-#define PROD_A1000_SCSI_2      (0x0C)	/* A1000 SCSI Controller */
-
-#define MANUF_JOCHHEIM         (0x0804)	/* Jochheim */
-#define PROD_JOCHHEIM_RAM      (0x01)	/* Jochheim RAM */
-
-#define MANUF_CHECKPOINT       (0x0807)	/* Checkpoint Technologies */
-#define PROD_SERIAL_SOLUTION   (0x00)	/* Serial Solution */
-
-#define MANUF_ICD              (0x0817)	/* ICD */
-#define PROD_ADVANTAGE_2000    (0x01)	/* Advantage 2000 SCSI Controller */
-
-#define MANUF_KUPKE2           (0x0819)	/* Kupke */
-#define PROD_KUPKE_SCSI_II     (0x02)	/* Golem SCSI-II Controller */
-#define PROD_GOLEM_BOX         (0x03)	/* Golem Box */
-#define PROD_KUPKE_SCSI_AT     (0x05)	/* SCSI/AT Controller */
-
-#define MANUF_HARDITAL         (0x0820)	/* Hardital Synthesis */
-#define PROD_TQM               (0x14)	/* TQM 68030+68882 Turbo Board */
-
-#define MANUF_BSC2             (0x082C)	/* BSC */
-#define PROD_OKTAGON_SCSI      (0x05)	/* BSC Oktagon 2008 SCSI Controller */
-#define PROD_TANDEM            (0x06)	/* BSC Tandem AT-2008/508 IDE */
-#define PROD_OKTAGON_RAM       (0x08)	/* BSC Oktagon 2008 RAM */
-#define PROD_MULTIFACE_I       (0x10)	/* Alfa Data MultiFace I */
-#define PROD_MULTIFACE_II      (0x11)	/* Alfa Data MultiFace II */
-#define PROD_MULTIFACE_III     (0x12)	/* Alfa Data MultiFace III */
-#define PROD_ISDN_MASTERCARD   (0x40)	/* BSC ISDN MasterCard */
-#define PROD_ISDN_MASTERCARD_2 (0x41)	/* BSC ISDN MasterCard II */
-
-#define MANUF_ADV_SYS_SOFT     (0x0836)	/* Advanced Systems & Software */
-#define PROD_NEXUS_SCSI        (0x01)	/* Nexus SCSI Controller */
-#define PROD_NEXUS_RAM         (0x08)	/* Nexus RAM */
-
-#define MANUF_IMPULSE          (0x0838)	/* Impulse */
-#define PROD_FIRECRACKER_24    (0x00)	/* FireCracker 24 */
-
-#define MANUF_IVS              (0x0840)	/* IVS */
-#define PROD_GRANDSLAM         (0x04)	/* GrandSlam RAM */
-#define PROD_IVS_OVERDRIVE     (0x10)	/* OverDrive HD */
-#define PROD_TRUMPCARD_CLASSIC (0x30)	/* Trumpcard Classic SCSI Controller */
-#define PROD_TRUMPCARD_PRO     (0x34)	/* Trumpcard Pro SCSI Controller */
-#define PROD_META_4            (0x40)	/* Meta-4 RAM */
-#define PROD_VECTOR            (0xF3)	/* Vector SCSI Controller */
-
-#define MANUF_VECTOR           (0x0841)	/* Vector */
-#define PROD_CONNECTION        (0xE3)	/* Connection Serial IO */
-
-#define MANUF_XPERT_PRODEV     (0x0845)	/* XPert/ProDev */
-#define PROD_VISIONA_RAM       (0x01)	/* Visiona Graphics Board */
-#define PROD_VISIONA_REG       (0x02)
-#define PROD_MERLIN_RAM        (0x03)	/* Merlin Graphics Board */
-#define PROD_MERLIN_REG        (0x04)
-
-#define MANUF_HYDRA_SYSTEMS    (0x0849)	/* Hydra Systems */
-#define PROD_AMIGANET          (0x01)	/* Amiganet Board */
-
-#define MANUF_SUNRIZE          (0x084F)	/* Sunrize Industries */
-#define PROD_AD516             (0x02)	/* AD516 Audio */
-
-#define MANUF_TRICERATOPS      (0x0850)	/* Triceratops */
-#define PROD_TRICERATOPS       (0x01)	/* Triceratops Multi I/O Board */
-
-#define MANUF_APPLIED_MAGIC    (0x0851)	/* Applied Magic Inc */
-#define PROD_DMI_RESOLVER      (0x01)	/* DMI Resolver Graphics Board */
-#define PROD_DIGITAL_BCASTER   (0x06)	/* Digital Broadcaster */
-
-#define MANUF_GFX_BASE         (0x085E)	/* GFX-Base */
-#define PROD_GDA_1_RAM         (0x00)	/* GDA-1 Graphics Board */
-#define PROD_GDA_1_REG         (0x01)
-
-#define MANUF_ROCTEC           (0x0860)	/* RocTec */
-#define PROD_RH_800C           (0x01)	/* RH 800C Hard Disk Controller */
-#define PROD_RH_800C_RAM       (0x01)	/* RH 800C RAM */
-
-#define MANUF_HELFRICH1        (0x0861)	/* Helfrich */
-#define PROD_RAINBOW3          (0x21)	/* Rainbow3 Graphics Board */
-
-#define MANUF_SW_RESULT_ENTS   (0x0866)	/* Software Result Enterprises */
-#define PROD_GG2PLUS           (0x01)	/* GG2+ Bus Converter */
-
-#define MANUF_MASOBOSHI        (0x086D)	/* Masoboshi */
-#define PROD_MASTER_CARD_RAM   (0x03)	/* Master Card RAM */
-#define PROD_MASTER_CARD_SCSI  (0x04)	/* Master Card SCSI Controller */
-#define PROD_MVD_819           (0x07)	/* MVD 819 */
-
-#define MANUF_DELACOMP         (0x0873)	/* DelaComp */
-#define PROD_DELACOMP_RAM_2000 (0x01)	/* RAM Expansion 2000 */
-
-#define MANUF_VILLAGE_TRONIC   (0x0877)	/* Village Tronic */
-#define PROD_DOMINO_RAM        (0x01)	/* Domino Graphics Board (RAM) */
-#define PROD_DOMINO_REG        (0x02)	/* Domino Graphics Board (REG) */
-#define PROD_PICASSO_II_RAM    (0x0B)	/* Picasso II Graphics Board */
-#define PROD_PICASSO_II_REG    (0x0C)
-#define PROD_PICASSO_II_REG_2  (0x0D)
-#define PROD_ARIADNE           (0xC9)	/* Ariadne Ethernet */
-
-#define MANUF_UTILITIES_ULTD   (0x087B)	/* Utilities Unlimited */
-#define PROD_EMPLANT_DELUXE    (0x15)	/* Emplant Deluxe SCSI Controller */
-#define PROD_EMPLANT_DELUXE2   (0x20)	/* Emplant Deluxe SCSI Controller */
-
-#define MANUF_AMITRIX          (0x0880)	/* Amitrix */
-#define PROD_AMITRIX_MULTI_IO  (0x01)	/* Multi-IO */
-#define PROD_AMITRIX_CD_RAM    (0x02)	/* CD-RAM Memory */
-
-#define MANUF_MTEC             (0x0890)	/* MTEC Germany */
-#define PROD_MTEC_68030        (0x03)	/* 68030 Turbo Board */
-#define PROD_MTEC_T1230        (0x20)	/* A1200 T68030/42 RTC Turbo Board */
-#define PROD_MTEC_RAM          (0x22)	/* MTEC 8MB RAM */
-
-#define MANUF_GVP2             (0x0891)	/* Great Valley Products */
-#define PROD_SPECTRUM_RAM      (0x01)	/* EGS 28/24 Spectrum Graphics Board */
-#define PROD_SPECTRUM_REG      (0x02)
-
-#define MANUF_HELFRICH2        (0x0893)	/* Helfrich */
-#define PROD_PICCOLO_RAM       (0x05)	/* Piccolo Graphics Board */
-#define PROD_PICCOLO_REG       (0x06)
-#define PROD_PEGGY_PLUS        (0x07)	/* PeggyPlus MPEG Decoder Board */
-#define PROD_VIDEOCRUNCHER     (0x08)	/* VideoCruncher */
-#define PROD_SD64_RAM          (0x0A)	/* SD64 Graphics Board */
-#define PROD_SD64_REG          (0x0B)
-
-#define MANUF_MACROSYSTEMS     (0x089B)	/* MacroSystems USA */
-#define PROD_WARP_ENGINE       (0x13)	/* Warp Engine 40xx SCSI Controller */
-
-#define MANUF_ELBOX            (0x089E)	/* ElBox Computer */
-#define PROD_ELBOX_1200        (0x06)	/* Elbox 1200/4 RAM */
-
-#define MANUF_HARMS_PROF       (0x0A00)	/* Harms Professional */
-#define PROD_HARMS_030_PLUS    (0x10)	/* 030 plus */
-#define PROD_3500_TURBO        (0xD0)	/* 3500 Turbo board */
-
-#define MANUF_MICRONIK         (0x0A50)	/* Micronik */
-#define PROD_RCA_120           (0x0A)	/* RCA 120 RAM */
-
-#define MANUF_IMTRONICS2       (0x1028)	/* Imtronics */
-#define PROD_HURRICANE_2800_3  (0x39)	/* Hurricane 2800 68030 */
-#define PROD_HURRICANE_2800_4  (0x57)	/* Hurricane 2800 68030 */
-
-#define MANUF_KUPKE3           (0x1248)	/* Kupke */
-#define PROD_GOLEM_3000        (0x01)	/* Golem HD 3000 */
-
-#define MANUF_INFORMATION      (0x157C)	/* Information */
-#define PROD_ISDN_ENGINE_I     (0x64)	/* ISDN Engine I */
-
-#define MANUF_VORTEX           (0x2017)	/* Vortex */
-#define PROD_GOLDEN_GATE_386SX (0x07)	/* Golden Gate 80386SX Board */
-#define PROD_GOLDEN_GATE_RAM   (0x08)	/* Golden Gate RAM */
-#define PROD_GOLDEN_GATE_486   (0x09)	/* Golden Gate 80486 Board */
-
-#define MANUF_DATAFLYER        (0x2062)	/* DataFlyer */
-#define PROD_DATAFLYER_4000SXS (0x01)	/* DataFlyer 4000SX SCSI Controller */
-#define PROD_DATAFLYER_4000SXR (0x02)	/* DataFlyer 4000SX RAM */
-
-#define MANUF_READYSOFT        (0x2100)	/* ReadySoft */
-#define PROD_AMAX              (0x01)	/* AMax II/IV */
-
-#define MANUF_PHASE5           (0x2140)	/* Phase5 */
-#define PROD_BLIZZARD_RAM      (0x01)	/* Blizzard RAM */
-#define PROD_BLIZZARD          (0x02)	/* Blizzard */
-#define PROD_BLIZZARD_1220_IV  (0x06)	/* Blizzard 1220-IV Turbo Board */
-#define PROD_FASTLANE_RAM      (0x0A)	/* FastLane RAM */
-#define PROD_FASTLANE_SCSI     (0x0B)	/* FastLane/Blizzard 1230-II SCSI/CyberSCSI */
-#define PROD_CYBERSTORM_SCSI   (0x0C)	/* Blizzard 1220/CyberStorm */
-#define PROD_BLIZZARD_1230_III (0x0D)	/* Blizzard 1230-III Turbo Board */
-#define PROD_BLIZZARD_1230_IV  (0x11)	/* Blizzard 1230-IV/1260 Turbo Board */
-#define PROD_BLIZZARD_2060SCSI (0x18)	/* Blizzard 2060 SCSI Controller */
-#define PROD_CYBERSTORM_II     (0x19)	/* CyberStorm Mk II */
-#define PROD_CYBERVISION       (0x22)	/* CyberVision64 Graphics Board */
-
-#define MANUF_DPS              (0x2169)	/* DPS */
-#define PROD_DPS_PAR           (0x01)	/* Personal Animation Recorder */
-
-#define MANUF_APOLLO2          (0x2200)	/* Apollo */
-#define PROD_A620              (0x00)	/* A620 68020 Accelerator */
-
-#define MANUF_APOLLO           (0x2222)	/* Apollo */
-#define PROD_AT_APOLLO         (0x22)	/* AT-Apollo */
-#define PROD_APOLLO_TURBO      (0x23)	/* Apollo Turbo Board */
-
-#define MANUF_UWE_GERLACH      (0x3FF7)	/* Uwe Gerlach */
-#define PROD_UG_RAM_ROM        (0xd4)	/* RAM/ROM */
-
-#define MANUF_MACROSYSTEMS2    (0x4754)	/* MacroSystems Germany */
-#define PROD_MAESTRO           (0x03)	/* Maestro */
-#define PROD_VLAB              (0x04)	/* VLab */
-#define PROD_MAESTRO_PRO       (0x05)	/* Maestro Pro */
-#define PROD_RETINA_Z2         (0x06)	/* Retina Z2 Graphics Board */
-#define PROD_MULTI_EVOLUTION   (0x08)	/* MultiEvolution */
-#define PROD_TOCCATA           (0x0C)	/* Toccata Sound Board */
-#define PROD_RETINA_Z3         (0x10)	/* Retina Z3 Graphics Board */
-#define PROD_VLAB_MOTION       (0x12)	/* VLab Motion */
-#define PROD_FALCON_040        (0xFD)	/* Falcon '040 Turbo Board */
-
-#define MANUF_COMBITEC         (0x6766)	/* Combitec */
-
-#define MANUF_SKI              (0x8000)	/* SKI Peripherals */
-#define PROD_SKI_SCSI_SERIAL   (0x80)	/* SCSI / Dual Serial */
-
-#define MANUF_CAMERON          (0xAA01)	/* Cameron */
-#define PROD_CAMERON_SCANNER   (0x10)	/* Scanner Interface */
-
-#define MANUF_REIS_WARE        (0xAA11)	/* Reis-Ware */
-#define PROD_RW_HANDYSCANNER   (0x11)	/* Handyscanner */
-
-
-/* Illegal Manufacturer IDs. These do NOT appear in arch/m68k/amiga/zorro.c! */
-
-#define MANUF_HACKER_INC       (0x07DB)	/* Hacker Inc. */
-#define PROD_HACKER_SCSI       (0x01)	/* Hacker Inc. SCSI Controller */
-
-#define MANUF_RES_MNGT_FORCE   (0x07DB)	/* Resource Management Force */
-#define PROD_QUICKNET          (0x02)	/* QuickNet Ethernet */
-
-#define MANUF_VECTOR2          (0x07DB)	/* Vector */
-#define PROD_CONNECTION_2      (0xE0)	/* Vector Connection */
-#define PROD_CONNECTION_3      (0xE1)	/* Vector Connection */
-#define PROD_CONNECTION_4      (0xE2)	/* Vector Connection */
-#define PROD_CONNECTION_5      (0xE3)	/* Vector Connection */
-
-
-/*
- * GVP's identifies most of their product through the 'extended
- * product code' (epc). The epc has to be and'ed with the GVP_PRODMASK
- * before the identification.
- */
-
-#define GVP_PRODMASK    (0xf8)
-#define GVP_SCSICLKMASK (0x01)
-
-enum GVP_ident {
-  GVP_GFORCE_040      = 0x20,
-  GVP_GFORCE_040_SCSI = 0x30,
-  GVP_A1291_SCSI      = 0x40,
-  GVP_COMBO_R4        = 0x60,
-  GVP_COMBO_R4_SCSI   = 0x70,
-  GVP_PHONEPAK        = 0x78,
-  GVP_IOEXT           = 0x98,
-  GVP_GFORCE_030      = 0xa0,
-  GVP_GFORCE_030_SCSI = 0xb0,
-  GVP_A530            = 0xc0,
-  GVP_A530_SCSI       = 0xd0,
-  GVP_COMBO_R3        = 0xe0,
-  GVP_COMBO_R3_SCSI   = 0xf0,
-  GVP_SERIESII        = 0xf8,
-};
-
-enum GVP_flags {
-  GVP_IO       = 0x01,
-  GVP_ACCEL    = 0x02,
-  GVP_SCSI     = 0x04,
-  GVP_24BITDMA = 0x08,
-  GVP_25BITDMA = 0x10,
-  GVP_NOBANK   = 0x20,
-  GVP_14MHZ    = 0x40,
-};
-
-
-struct Node {
-    struct  Node *ln_Succ;	/* Pointer to next (successor) */
-    struct  Node *ln_Pred;	/* Pointer to previous (predecessor) */
-    u_char  ln_Type;
-    char    ln_Pri;		/* Priority, for sorting */
-    char    *ln_Name;		/* ID string, null terminated */
-};
-
-struct ExpansionRom {
-    /* -First 16 bytes of the expansion ROM */
-    u_char	er_Type;	/* Board type, size and flags */
-    u_char	er_Product;	/* Product number, assigned by manufacturer */
-    u_char	er_Flags;	/* Flags */
-    u_char	er_Reserved03;	/* Must be zero ($ff inverted) */
-    u_short	er_Manufacturer; /* Unique ID,ASSIGNED BY COMMODORE-AMIGA! */
-    u_long	er_SerialNumber; /* Available for use by manufacturer */
-    u_short	er_InitDiagVec;	/* Offset to optional "DiagArea" structure */
-    u_char	er_Reserved0c;
-    u_char	er_Reserved0d;
-    u_char	er_Reserved0e;
-    u_char	er_Reserved0f;
-};
-
-/* er_Type board type bits */
-#define ERT_TYPEMASK	0xc0
-#define ERT_ZORROII	0xc0
-#define ERT_ZORROIII	0x80
-
-/* other bits defined in er_Type */
-#define ERTB_MEMLIST	5		/* Link RAM into free memory list */
-#define ERTF_MEMLIST	(1<<5)
-
-struct ConfigDev {
-    struct Node 	cd_Node;
-    u_char		cd_Flags;	/* (read/write) */
-    u_char		cd_Pad; 	/* reserved */
-    struct ExpansionRom cd_Rom; 	/* copy of board's expansion ROM */
-    void		*cd_BoardAddr;	/* where in memory the board was placed */
-    u_long		cd_BoardSize;	/* size of board in bytes */
-    u_short		cd_SlotAddr;	/* which slot number (PRIVATE) */
-    u_short		cd_SlotSize;	/* number of slots (PRIVATE) */
-    void		*cd_Driver;	/* pointer to node of driver */
-    struct ConfigDev	*cd_NextCD;	/* linked list of drivers to config */
-    u_long		cd_Unused[4];	/* for whatever the driver wants */
-};
-
-#else	/* __ASSEMBLY__ */
-
-LN_Succ		= 0
-LN_Pred		= LN_Succ+4
-LN_Type		= LN_Pred+4
-LN_Pri		= LN_Type+1
-LN_Name		= LN_Pri+1
-LN_sizeof	= LN_Name+4
-
-ER_Type		= 0
-ER_Product	= ER_Type+1
-ER_Flags	= ER_Product+1
-ER_Reserved03	= ER_Flags+1
-ER_Manufacturer	= ER_Reserved03+1
-ER_SerialNumber	= ER_Manufacturer+2
-ER_InitDiagVec	= ER_SerialNumber+4
-ER_Reserved0c	= ER_InitDiagVec+2
-ER_Reserved0d	= ER_Reserved0c+1
-ER_Reserved0e	= ER_Reserved0d+1
-ER_Reserved0f	= ER_Reserved0e+1
-ER_sizeof	= ER_Reserved0f+1
-
-CD_Node		= 0
-CD_Flags	= CD_Node+LN_sizeof
-CD_Pad		= CD_Flags+1
-CD_Rom		= CD_Pad+1
-CD_BoardAddr	= CD_Rom+ER_sizeof
-CD_BoardSize	= CD_BoardAddr+4
-CD_SlotAddr	= CD_BoardSize+4
-CD_SlotSize	= CD_SlotAddr+2
-CD_Driver	= CD_SlotSize+2
-CD_NextCD	= CD_Driver+4
-CD_Unused	= CD_NextCD+4
-CD_sizeof	= CD_Unused+(4*4)
-
-#endif	/* __ASSEMBLY__ */
-
-#ifndef __ASSEMBLY__
-
-#define ZORRO_NUM_AUTO		16
-
-#ifdef __KERNEL__
-
-extern int zorro_num_autocon;		/* # of autoconfig devices found */
-extern struct ConfigDev zorro_autocon[ZORRO_NUM_AUTO];
-
-
-/*
- * Zorro Functions
- */
-
-extern int zorro_find(int manuf, int prod, int part, int index);
-extern struct ConfigDev *zorro_get_board(int key);
-extern void zorro_config_board(int key, int part);
-extern void zorro_unconfig_board(int key, int part);
-
-
-/*
- * Bitmask indicating portions of available Zorro II RAM that are unused
- * by the system. Every bit represents a 64K chunk, for a maximum of 8MB
- * (128 chunks, physical 0x00200000-0x009fffff).
- *
- * If you want to use (= allocate) portions of this RAM, you should clear
- * the corresponding bits.
- */
-
-extern u_long zorro_unused_z2ram[4];
-
-#define Z2RAM_START		(0x00200000)
-#define Z2RAM_END		(0x00a00000)
-#define Z2RAM_SIZE		(0x00800000)
-#define Z2RAM_CHUNKSIZE		(0x00010000)
-#define Z2RAM_CHUNKMASK		(0x0000ffff)
-#define Z2RAM_CHUNKSHIFT	(16)
-
-
-/*
- * Verbose Board Identification
- */
-
-extern void zorro_identify(void);
-extern int zorro_get_list(char *buffer);
-
-#endif	/* !__ASSEMBLY__ */
-#endif	/* __KERNEL__ */
-
-#endif /* __ASMm68K_ZORRO_H */
diff -u --recursive --new-file v2.1.35/linux/include/asm-ppc/atomic.h linux/include/asm-ppc/atomic.h
--- v2.1.35/linux/include/asm-ppc/atomic.h	Mon Apr 14 16:28:19 1997
+++ linux/include/asm-ppc/atomic.h	Thu Apr 17 13:20:51 1997
@@ -6,7 +6,7 @@
 #define _ASM_PPC_ATOMIC_H_
 
 typedef struct { int counter; } atomic_t;
-#define ATOMIC_INIT	{ 0 }
+#define ATOMIC_INIT(i)	{ (i) }
 
 /*
  * Make sure gcc doesn't try to be clever and move things around
diff -u --recursive --new-file v2.1.35/linux/include/asm-ppc/semaphore.h linux/include/asm-ppc/semaphore.h
--- v2.1.35/linux/include/asm-ppc/semaphore.h	Mon Apr 14 16:28:19 1997
+++ linux/include/asm-ppc/semaphore.h	Thu Apr 17 13:20:51 1997
@@ -9,8 +9,8 @@
 	struct wait_queue * wait;
 };
 
-#define MUTEX ((struct semaphore) { 1, 0, NULL })
-#define MUTEX_LOCKED ((struct semaphore) { 0, 0, NULL })
+#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 void __up(struct semaphore * sem);
diff -u --recursive --new-file v2.1.35/linux/include/asm-sparc/atomic.h linux/include/asm-sparc/atomic.h
--- v2.1.35/linux/include/asm-sparc/atomic.h	Mon Apr 14 16:28:19 1997
+++ linux/include/asm-sparc/atomic.h	Thu Apr 17 13:20:51 1997
@@ -13,7 +13,7 @@
 typedef struct { int counter; } atomic_t;
 #endif
 
-#define ATOMIC_INIT	{ 0 }
+#define ATOMIC_INIT(i)	{ (i << 8) }
 
 #ifdef __KERNEL__
 #include <asm/system.h>
diff -u --recursive --new-file v2.1.35/linux/include/asm-sparc/errno.h linux/include/asm-sparc/errno.h
--- v2.1.35/linux/include/asm-sparc/errno.h	Sat Nov  9 00:29:22 1996
+++ linux/include/asm-sparc/errno.h	Tue Apr 15 21:47:24 1997
@@ -1,4 +1,4 @@
-/* $Id: errno.h,v 1.5 1996/07/13 02:05:13 tridge Exp $ */
+/* $Id: errno.h,v 1.6 1997/04/15 09:03:38 davem Exp $ */
 #ifndef _SPARC_ERRNO_H
 #define _SPARC_ERRNO_H
 
@@ -129,5 +129,8 @@
 #define	EILSEQ		122	/* Illegal byte sequence */
 #define	ELIBMAX		123	/* Atmpt to link in too many shared libs */
 #define	ELIBSCN		124	/* .lib section in a.out corrupted */
+
+#define	ENOMEDIUM	125	/* No medium found */
+#define	EMEDIUMTYPE	126	/* Wrong medium type */
 
 #endif
diff -u --recursive --new-file v2.1.35/linux/include/asm-sparc/fbio.h linux/include/asm-sparc/fbio.h
--- v2.1.35/linux/include/asm-sparc/fbio.h	Sat Nov  9 00:29:23 1996
+++ linux/include/asm-sparc/fbio.h	Thu Apr 17 13:20:51 1997
@@ -33,6 +33,9 @@
 
 #define FBTYPE_LASTPLUSONE      21	/* This is not last + 1 in fact... */
 
+/* Does not seem to be listed in the Sun file either */
+#define FBTYPE_CREATOR          22
+
 /* fbio ioctls */
 /* Returned by FBIOGTYPE */
 struct  fbtype {
diff -u --recursive --new-file v2.1.35/linux/include/asm-sparc/hardirq.h linux/include/asm-sparc/hardirq.h
--- v2.1.35/linux/include/asm-sparc/hardirq.h	Mon Apr 14 16:28:20 1997
+++ linux/include/asm-sparc/hardirq.h	Tue Apr 22 22:39:21 1997
@@ -10,12 +10,11 @@
 
 extern unsigned int local_irq_count[NR_CPUS];
 #define in_interrupt()	(local_irq_count[smp_processor_id()] != 0)
-#define hardirq_depth()	(local_irq_count[smp_processor_id()])
 
 #ifndef __SMP__
 
-#define hardirq_trylock(cpu)	(++local_irq_count[cpu], (cpu)==0)
-#define hardirq_endlock(cpu)	(--local_irq_count[cpu])
+#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]--)
diff -u --recursive --new-file v2.1.35/linux/include/asm-sparc/init.h linux/include/asm-sparc/init.h
--- v2.1.35/linux/include/asm-sparc/init.h	Thu Mar 27 14:40:07 1997
+++ linux/include/asm-sparc/init.h	Thu Apr 17 13:20:51 1997
@@ -1,8 +1,7 @@
 #ifndef _SPARC_INIT_H
 #define _SPARC_INIT_H
 
-#ifndef __init
-#if (defined (__svr4__) || defined (__ELF__)) && !defined (MODULE)
+#if (defined (__svr4__) || defined (__ELF__))
 #define __init __attribute__ ((__section__ (".text.init")))
 #define __initdata __attribute__ ((__section__ (".data.init")))
 #define __initfunc(__arginit) \
@@ -20,7 +19,6 @@
 #define __INIT
 #define __FINIT
 #define __INITDATA
-#endif
 #endif
 
 #endif
diff -u --recursive --new-file v2.1.35/linux/include/asm-sparc/irq.h linux/include/asm-sparc/irq.h
--- v2.1.35/linux/include/asm-sparc/irq.h	Mon Apr 14 16:28:20 1997
+++ linux/include/asm-sparc/irq.h	Tue Apr 22 22:39:21 1997
@@ -1,4 +1,4 @@
-/* $Id: irq.h,v 1.15 1997/04/14 05:39:28 davem Exp $
+/* $Id: irq.h,v 1.17 1997/04/18 05:44:52 davem Exp $
  * irq.h: IRQ registers on the Sparc.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -13,6 +13,38 @@
 
 #define NR_IRQS    15
 
+/* IRQ handler dispatch entry and exit. */
+#ifdef __SMP__
+extern __inline__ void irq_enter(int cpu, int irq)
+{
+	register int proc asm("g1");
+	proc = cpu;
+	__asm__ __volatile__("
+	mov	%%o7, %%g4
+	call	___irq_enter
+	 add	%%o7, 8, %%o7
+"	: "=&r" (proc)
+	: "0" (proc)
+	: "g2", "g3", "g4", "g5", "memory", "cc");
+}
+
+extern __inline__ void irq_exit(int cpu, int irq)
+{
+	register int proc asm("g7");
+	proc = cpu;
+	__asm__ __volatile__("
+	mov	%%o7, %%g4
+	call	___irq_exit
+	 add	%%o7, 8, %%o7
+"	: "=&r" (proc)
+	: "0" (proc)
+	: "g1", "g2", "g3", "g4", "g5", "memory", "cc");
+}
+#else
+#define irq_enter(cpu, irq)	(local_irq_count[cpu]++)
+#define irq_exit(cpu, irq)	(local_irq_count[cpu]--)
+#endif
+
 /* Dave Redman (djhr@tadpole.co.uk)
  * changed these to function pointers.. it saves cycles and will allow
  * the irq dependencies to be split into different files at a later date
@@ -22,9 +54,9 @@
 extern void (*enable_irq)(unsigned int);
 extern void (*disable_pil_irq)(unsigned int);
 extern void (*enable_pil_irq)(unsigned int);
-extern void (*clear_clock_irq)( void );
-extern void (*clear_profile_irq)( void );
-extern void (*load_profile_irq)( unsigned int timeout );
+extern void (*clear_clock_irq)(void);
+extern void (*clear_profile_irq)(int);
+extern void (*load_profile_irq)(int cpu, unsigned int timeout);
 extern void (*init_timers)(void (*lvl10_irq)(int, void *, struct pt_regs *));
 extern void claim_ticker14(void (*irq_handler)(int, void *, struct pt_regs *),
 			   int irq,
diff -u --recursive --new-file v2.1.35/linux/include/asm-sparc/linux_logo.h linux/include/asm-sparc/linux_logo.h
--- v2.1.35/linux/include/asm-sparc/linux_logo.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sparc/linux_logo.h	Tue Apr 22 22:39:21 1997
@@ -0,0 +1,2090 @@
+/* $Id: linux_logo.h,v 1.1 1997/04/16 17:51:24 jj Exp $
+ * include/asm-sparc/linux_logo.h: This is a linux logo
+ *                                 to be displayed on boot.
+ *
+ * Copyright (C) 1996 Larry Ewing (lewing@isc.tamu.edu)
+ * Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ *
+ * You can put anything here, but:
+ * LINUX_LOGO_COLORS has to be less than 224
+ * image size has to be 80x80
+ * values have to start from 0x20
+ * (i.e. RGB(linux_logo_red[0],
+ *	     linux_logo_green[0],
+ *	     linux_logo_blue[0]) is color 0x20)
+ * BW image has to be 80x80 as well, with MS bit
+ * on the left
+ * Serial_console ascii image can be any size,
+ * but should contain %s to display the version
+ */
+ 
+#include <linux/init.h>
+#include <linux/version.h>
+
+#define linux_logo_banner "Linux/SPARC version " UTS_RELEASE
+
+#define LINUX_LOGO_COLORS 221
+
+unsigned char linux_logo_red[] __initdata = {
+  0xF3, 0xF6, 0xF8, 0xF7, 0xEF, 0xE7, 0xE5, 0xE3,
+  0xCA, 0xD4, 0xDD, 0xC8, 0xC7, 0xC4, 0xC2, 0xE5,
+  0xF1, 0xED, 0xEE, 0xE6, 0xC6, 0xDA, 0xDD, 0xE5,
+  0xD9, 0xC6, 0xE3, 0xD0, 0xC6, 0xBA, 0xB0, 0xB6,
+  0xBB, 0xBE, 0xB9, 0xB8, 0xB3, 0xB2, 0xB0, 0xAD,
+  0xAC, 0xA9, 0xA8, 0xA6, 0xA4, 0xA1, 0xA0, 0x9D,
+  0xA0, 0x9F, 0x9E, 0x9C, 0x9B, 0x99, 0x9A, 0x99,
+  0x98, 0x95, 0x96, 0x94, 0x93, 0x92, 0x8F, 0x8D,
+  0x8C, 0x8A, 0x87, 0x86, 0x83, 0x81, 0x0D, 0x03,
+  0x66, 0x44, 0x24, 0x08, 0xD6, 0xE6, 0xE9, 0xE6,
+  0xE7, 0xCA, 0xDC, 0xDB, 0xD5, 0xD0, 0xC9, 0xE2,
+  0xD5, 0xC6, 0xC4, 0xB3, 0xB2, 0xB9, 0xA9, 0x9A,
+  0xB2, 0x9D, 0xE8, 0xEC, 0xF5, 0xF5, 0xF4, 0xF4,
+  0xEC, 0xEE, 0xF0, 0xF5, 0xE0, 0xD6, 0xC5, 0xC2,
+  0xD9, 0xD5, 0xD8, 0xD6, 0xF6, 0xF4, 0xED, 0xEC,
+  0xEB, 0xF1, 0xF6, 0xF5, 0xF5, 0xEE, 0xEF, 0xEC,
+  0xE7, 0xE3, 0xE6, 0xD6, 0xDD, 0xC3, 0xD6, 0xD7,
+  0xCD, 0xCA, 0xC3, 0xAC, 0x95, 0x99, 0xB7, 0xA3,
+  0x8B, 0x88, 0x95, 0x8A, 0x94, 0xD2, 0xCC, 0xC4,
+  0xA8, 0x8E, 0x8F, 0xAE, 0xB8, 0xAC, 0xB6, 0xB4,
+  0xAD, 0xA5, 0xA0, 0x9B, 0x8B, 0xA3, 0x94, 0x87,
+  0x85, 0x89, 0x53, 0x80, 0x7D, 0x7C, 0x7A, 0x78,
+  0x76, 0x71, 0x73, 0x6E, 0x6B, 0x67, 0x65, 0x62,
+  0x4B, 0x5B, 0x5F, 0x53, 0x56, 0x52, 0x4F, 0x46,
+  0x42, 0x0F, 0x75, 0x78, 0x7D, 0x72, 0x5F, 0x6E,
+  0x7A, 0x75, 0x6A, 0x58, 0x48, 0x4F, 0x00, 0x2B,
+  0x37, 0x3E, 0x32, 0x33, 0x25, 0x2C, 0x3B, 0x11,
+  0x1D, 0x14, 0x06, 0x02, 0x00
+};
+
+unsigned char linux_logo_green[] __initdata = {
+  0xF3, 0xF6, 0xF8, 0xF7, 0xEF, 0xE7, 0xE5, 0xE3,
+  0xCA, 0xD4, 0xDD, 0xC8, 0xC7, 0xC4, 0xC2, 0xD3,
+  0xDA, 0xD4, 0xD7, 0xCC, 0xC1, 0xCC, 0xCB, 0xC9,
+  0xC5, 0xBC, 0xBC, 0xBB, 0xB7, 0xA5, 0xB0, 0xB6,
+  0xBB, 0xBE, 0xB9, 0xB8, 0xB3, 0xB2, 0xAD, 0xAD,
+  0xAC, 0xA9, 0xA8, 0xA6, 0xA4, 0xA1, 0xA0, 0x95,
+  0xA0, 0x9F, 0x9E, 0x9C, 0x9B, 0x99, 0x9A, 0x99,
+  0x98, 0x95, 0x96, 0x94, 0x93, 0x92, 0x8F, 0x8D,
+  0x8C, 0x8A, 0x87, 0x86, 0x83, 0x81, 0x08, 0x02,
+  0x53, 0x2E, 0x19, 0x06, 0xC6, 0xC8, 0xCF, 0xBD,
+  0xB3, 0xB6, 0xB4, 0xAB, 0xA5, 0xA3, 0x9B, 0xB6,
+  0xA7, 0x99, 0x92, 0xA4, 0x9E, 0x9D, 0x98, 0x8C,
+  0x8A, 0x86, 0xCD, 0xCC, 0xC9, 0xD7, 0xCA, 0xC4,
+  0xCA, 0xC3, 0xC7, 0xC3, 0xC8, 0xB4, 0x91, 0x8E,
+  0x8A, 0x82, 0x87, 0x85, 0xBD, 0xBF, 0xB6, 0xBC,
+  0xAE, 0xB7, 0xBC, 0xB8, 0xBF, 0xB6, 0xBC, 0xB5,
+  0xAB, 0xA6, 0xAD, 0xB2, 0xA5, 0x87, 0x9C, 0x96,
+  0x95, 0x8E, 0x87, 0x8F, 0x86, 0x86, 0x8E, 0x80,
+  0x7A, 0x70, 0x7B, 0x78, 0x78, 0x7F, 0x77, 0x6F,
+  0x70, 0x76, 0x59, 0x77, 0x68, 0x64, 0x7B, 0x7C,
+  0x75, 0x6D, 0x77, 0x69, 0x65, 0x5F, 0x5B, 0x54,
+  0x4F, 0x5B, 0x39, 0x80, 0x7D, 0x7C, 0x7A, 0x78,
+  0x76, 0x71, 0x73, 0x6E, 0x6B, 0x67, 0x65, 0x62,
+  0x4B, 0x5B, 0x5F, 0x53, 0x56, 0x52, 0x4F, 0x46,
+  0x42, 0x0B, 0x69, 0x66, 0x64, 0x57, 0x4A, 0x4E,
+  0x55, 0x4B, 0x46, 0x3B, 0x30, 0x33, 0x00, 0x2B,
+  0x37, 0x3E, 0x32, 0x33, 0x25, 0x2C, 0x29, 0x0D,
+  0x1D, 0x14, 0x06, 0x02, 0x00
+};
+
+unsigned char linux_logo_blue[] __initdata = {
+  0xF3, 0xF6, 0xF8, 0xF7, 0xEF, 0xEE, 0xE5, 0xDE,
+  0xD7, 0xD3, 0xDD, 0xC8, 0xC7, 0xC4, 0xC2, 0xB5,
+  0xB0, 0xA6, 0xAC, 0x9B, 0xB5, 0xB5, 0xAE, 0x84,
+  0x90, 0xA9, 0x81, 0x8D, 0x96, 0x86, 0xB0, 0xB6,
+  0xBB, 0xBE, 0xB9, 0xB8, 0xB3, 0xB2, 0xA7, 0xAD,
+  0xAC, 0xA9, 0xA8, 0xA6, 0xA4, 0xA1, 0xA5, 0x87,
+  0xA0, 0x9F, 0x9E, 0x9C, 0x9B, 0x9A, 0x9A, 0x99,
+  0x98, 0x95, 0x96, 0x94, 0x93, 0x92, 0x8F, 0x8D,
+  0x8C, 0x8A, 0x87, 0x86, 0x83, 0x81, 0xC8, 0xD7,
+  0x9B, 0x8E, 0x8C, 0xB2, 0x77, 0x77, 0x4E, 0x77,
+  0x69, 0x71, 0x78, 0x6B, 0x65, 0x66, 0x64, 0x59,
+  0x5C, 0x5A, 0x48, 0x72, 0x7B, 0x6B, 0x67, 0x6E,
+  0x42, 0x5B, 0x29, 0x36, 0x25, 0x10, 0x17, 0x14,
+  0x19, 0x16, 0x13, 0x0E, 0x08, 0x2E, 0x2E, 0x3D,
+  0x24, 0x24, 0x24, 0x24, 0x13, 0x12, 0x14, 0x14,
+  0x0E, 0x08, 0x0D, 0x0F, 0x08, 0x0D, 0x0E, 0x08,
+  0x08, 0x0C, 0x06, 0x06, 0x07, 0x16, 0x07, 0x0E,
+  0x08, 0x0A, 0x07, 0x0D, 0x2D, 0x3E, 0x09, 0x4E,
+  0x68, 0x52, 0x56, 0x58, 0x4B, 0x22, 0x20, 0x20,
+  0x27, 0x39, 0x28, 0x19, 0x1E, 0x1E, 0x08, 0x06,
+  0x07, 0x09, 0x08, 0x08, 0x05, 0x1D, 0x1F, 0x17,
+  0x18, 0x06, 0x79, 0x80, 0x7D, 0x7C, 0x7A, 0x78,
+  0x76, 0x71, 0x73, 0x6E, 0x6B, 0x68, 0x65, 0x62,
+  0x4B, 0x5B, 0x5F, 0x55, 0x56, 0x52, 0x4F, 0x46,
+  0x42, 0x5A, 0x14, 0x23, 0x3D, 0x2B, 0x21, 0x14,
+  0x06, 0x04, 0x03, 0x07, 0x09, 0x13, 0x2A, 0x3A,
+  0x37, 0x3E, 0x32, 0x33, 0x25, 0x2C, 0x07, 0x09,
+  0x1D, 0x14, 0x06, 0x02, 0x00
+};
+
+unsigned char linux_logo[] __initdata = {
+  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+  0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57,
+  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58, 0x57,
+  0x58, 0x58, 0x59, 0x5C, 0x5D, 0x5F, 0x60, 0x61,
+  0x62, 0x61, 0x61, 0x62, 0x62, 0x62, 0x63, 0x63,
+  0x61, 0x61, 0x61, 0x61, 0x61, 0x60, 0x5E, 0x5E,
+  0x5E, 0x5D, 0x5D, 0x5C, 0x5D, 0x5B, 0x58, 0x58,
+  0x58, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x58,
+  0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57,
+  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+  0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57,
+  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58, 0x57,
+  0x54, 0x56, 0x57, 0x67, 0xFC, 0xFC, 0xFC, 0xFC,
+  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x67, 0x4C,
+  0x4A, 0x49, 0x4A, 0x49, 0x4A, 0x49, 0x49, 0x4A,
+  0x4A, 0x4B, 0x4B, 0x4B, 0x4C, 0x50, 0x51, 0x52,
+  0x54, 0x54, 0x56, 0x57, 0x57, 0x57, 0x57, 0x58,
+  0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57,
+  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+  0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57,
+  0x57, 0x57, 0x57, 0x57, 0x58, 0x56, 0x56, 0x53,
+  0x52, 0x53, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0xFB, 0xFB,
+  0x4B, 0x4B, 0x4B, 0x4A, 0x49, 0x4A, 0x4A, 0x49,
+  0x49, 0x49, 0x48, 0x49, 0x49, 0x4A, 0x4A, 0x4B,
+  0x4C, 0x4D, 0x52, 0x54, 0x56, 0x55, 0x57, 0x58,
+  0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57,
+  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+  0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57,
+  0x57, 0x57, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50,
+  0x50, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+  0xFC, 0xFC, 0xFC, 0xFC, 0xF8, 0xF0, 0xF4, 0xFB,
+  0xFC, 0x67, 0x53, 0x50, 0x4D, 0x4C, 0x4C, 0x4C,
+  0x4B, 0x4A, 0x4A, 0x48, 0x49, 0x48, 0x48, 0x49,
+  0x49, 0x49, 0x4B, 0x4C, 0x50, 0x52, 0x53, 0x56,
+  0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57,
+  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+  0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57,
+  0x55, 0x54, 0x53, 0x51, 0x51, 0x50, 0x4C, 0x4D,
+  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+  0xFC, 0xFC, 0xFC, 0xFC, 0xF4, 0xD2, 0xD7, 0xF5,
+  0xFC, 0xFC, 0x5D, 0x5D, 0x5C, 0x5C, 0x59, 0x58,
+  0x58, 0x56, 0x52, 0x4C, 0x4B, 0x4A, 0x4A, 0x48,
+  0x48, 0x48, 0x48, 0x48, 0x49, 0x4B, 0x4D, 0x51,
+  0x54, 0x56, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57,
+  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+  0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x55, 0x54,
+  0x53, 0x52, 0x51, 0x4D, 0x4D, 0x4D, 0x50, 0x50,
+  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+  0xFC, 0xFC, 0xFC, 0xFC, 0xF4, 0x64, 0xD9, 0xF5,
+  0xF9, 0xFC, 0xFC, 0x64, 0x63, 0x62, 0x61, 0x61,
+  0x61, 0x60, 0x5E, 0x5B, 0x5A, 0x54, 0x52, 0x4C,
+  0x4B, 0x49, 0x49, 0x47, 0x47, 0x48, 0x49, 0x4B,
+  0x4C, 0x51, 0x53, 0x56, 0x57, 0x58, 0x57, 0x57,
+  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+  0x57, 0x57, 0x58, 0x57, 0x57, 0x55, 0x53, 0x53,
+  0x51, 0x50, 0x50, 0x50, 0x50, 0x50, 0x53, 0xFC,
+  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+  0xFC, 0xFC, 0xFC, 0xFC, 0xF4, 0xF5, 0xF9, 0xFC,
+  0xFC, 0xFC, 0xFC, 0x64, 0x64, 0x64, 0x64, 0x64,
+  0x64, 0x64, 0x64, 0x63, 0x61, 0x61, 0x5E, 0x59,
+  0x55, 0x52, 0x4C, 0x4A, 0x49, 0x47, 0x48, 0x48,
+  0x49, 0x4B, 0x4D, 0x51, 0x54, 0x57, 0x57, 0x57,
+  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+  0x57, 0x57, 0x58, 0x55, 0x54, 0x54, 0x52, 0x51,
+  0x51, 0x51, 0x51, 0x51, 0x53, 0x54, 0x59, 0xFC,
+  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+  0xFC, 0xFC, 0xFC, 0xFC, 0xF7, 0xFC, 0xFC, 0xFC,
+  0xFC, 0xFC, 0xFC, 0xFC, 0x60, 0x60, 0x60, 0x61,
+  0x62, 0x63, 0x64, 0x64, 0x65, 0x65, 0x64, 0x63,
+  0x61, 0x5E, 0x59, 0x56, 0x4D, 0x4B, 0x48, 0x48,
+  0x48, 0x48, 0x49, 0x4B, 0x50, 0x53, 0x56, 0x56,
+  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+  0x57, 0x57, 0x56, 0x54, 0x53, 0x52, 0x51, 0x51,
+  0x51, 0x52, 0x53, 0x55, 0x59, 0x5D, 0x5E, 0xFC,
+  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+  0xFC, 0xFC, 0xFC, 0xFB, 0xFB, 0xFB, 0xFC, 0xFC,
+  0xFC, 0xFC, 0xFC, 0xFC, 0x4C, 0x4E, 0x51, 0x52,
+  0x57, 0x5A, 0x5E, 0x60, 0x61, 0x63, 0x65, 0xCB,
+  0x64, 0x64, 0x63, 0x60, 0x5C, 0x57, 0x50, 0x4B,
+  0x48, 0x47, 0x47, 0x47, 0x4A, 0x4C, 0x52, 0x53,
+  0x54, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+  0x55, 0x54, 0x53, 0x53, 0x51, 0x52, 0x52, 0x53,
+  0x53, 0x57, 0x5A, 0x5D, 0x5E, 0x5E, 0x60, 0xFC,
+  0xFC, 0xFC, 0xFB, 0xF9, 0xFC, 0xFC, 0xFC, 0xFC,
+  0xFC, 0xFC, 0xFC, 0xFA, 0xF9, 0xF5, 0xFB, 0xFC,
+  0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0x45, 0x3F, 0x3F,
+  0x45, 0x48, 0x4B, 0x4D, 0x54, 0x5A, 0x5E, 0x61,
+  0x63, 0xCB, 0xCB, 0x65, 0x64, 0x62, 0x5E, 0x57,
+  0x50, 0x4B, 0x48, 0x47, 0x47, 0x48, 0x4B, 0x4D,
+  0x51, 0x56, 0x56, 0x57, 0x57, 0x57, 0x57, 0x57,
+  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x55,
+  0x54, 0x54, 0x53, 0x53, 0x52, 0x53, 0x54, 0x57,
+  0x59, 0x5C, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0xFC,
+  0xFC, 0xFA, 0xFC, 0xFA, 0xE0, 0xFC, 0xFC, 0xFC,
+  0xFB, 0xFB, 0xFB, 0xDF, 0xD8, 0xF9, 0xE0, 0xFC,
+  0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0x4C, 0x4A, 0x48,
+  0x48, 0x3E, 0x44, 0x43, 0x3F, 0x47, 0x4B, 0x52,
+  0x5A, 0x5E, 0x62, 0x64, 0xCB, 0xCB, 0x64, 0x61,
+  0x5E, 0x57, 0x4D, 0x49, 0x47, 0x47, 0x48, 0x4A,
+  0x4C, 0x52, 0x54, 0x56, 0x57, 0x57, 0x57, 0x57,
+  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x55,
+  0x54, 0x53, 0x53, 0x54, 0x54, 0x55, 0x58, 0x5B,
+  0x5C, 0x5D, 0x5E, 0x5D, 0x5D, 0x5B, 0x58, 0xFC,
+  0xFC, 0xD8, 0x4C, 0x60, 0xFC, 0xF5, 0xFC, 0xFC,
+  0xFC, 0xF7, 0x5F, 0x48, 0x48, 0x2C, 0xF8, 0xF9,
+  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x4B, 0x4A, 0x49,
+  0x49, 0x49, 0x49, 0x47, 0x3E, 0x44, 0x42, 0x3F,
+  0x3E, 0x4B, 0x54, 0x5C, 0x61, 0x64, 0xCB, 0xCB,
+  0x64, 0x61, 0x5D, 0x53, 0x4B, 0x49, 0x47, 0x47,
+  0x49, 0x4B, 0x50, 0x53, 0x56, 0x57, 0x57, 0x57,
+  0x57, 0x57, 0x57, 0x57, 0x57, 0x55, 0x55, 0x54,
+  0x53, 0x53, 0x54, 0x56, 0x58, 0x5A, 0x5B, 0x5D,
+  0x5D, 0x5D, 0x5C, 0x5A, 0x54, 0x52, 0x4C, 0xFC,
+  0xF7, 0x4E, 0x2D, 0x29, 0x4E, 0xFC, 0xFC, 0xFC,
+  0xFB, 0x5F, 0x26, 0x24, 0x20, 0x2E, 0x65, 0xFC,
+  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x45, 0x3F, 0x45,
+  0x3E, 0x47, 0x47, 0x47, 0x47, 0x47, 0x3E, 0x44,
+  0x43, 0x40, 0x44, 0x49, 0x51, 0x5C, 0x62, 0x64,
+  0xCB, 0xCB, 0x63, 0x60, 0x58, 0x50, 0x49, 0x48,
+  0x48, 0x48, 0x4A, 0x4D, 0x53, 0x54, 0x57, 0x57,
+  0x57, 0x57, 0x57, 0x57, 0x55, 0x54, 0x54, 0x54,
+  0x54, 0x54, 0x55, 0x57, 0x59, 0x5B, 0x5C, 0x5D,
+  0x5C, 0x5A, 0x54, 0x51, 0x4C, 0x4C, 0x54, 0xFC,
+  0xF9, 0x23, 0xDB, 0x2D, 0x23, 0xFA, 0xFB, 0xFA,
+  0xF5, 0x27, 0x21, 0xD9, 0xF8, 0x20, 0x21, 0xFB,
+  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x5D, 0x58, 0x55,
+  0x50, 0x48, 0x45, 0x43, 0x44, 0x44, 0x45, 0x45,
+  0x3E, 0x3F, 0x43, 0x41, 0x3F, 0x48, 0x52, 0x5D,
+  0x63, 0x65, 0xCB, 0x65, 0x61, 0x5D, 0x52, 0x4B,
+  0x48, 0x47, 0x47, 0x49, 0x4C, 0x51, 0x54, 0x57,
+  0x57, 0x57, 0x57, 0x57, 0x55, 0x54, 0x54, 0x54,
+  0x54, 0x58, 0x5A, 0x59, 0x5B, 0x5B, 0x5B, 0x5A,
+  0x55, 0x52, 0x4D, 0x4D, 0x55, 0x5B, 0x5D, 0xFC,
+  0xF1, 0xF9, 0xFC, 0xD4, 0x21, 0xCC, 0xF7, 0xF8,
+  0xF2, 0x21, 0xD9, 0xFC, 0xF2, 0xFB, 0x21, 0x45,
+  0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0xD1, 0xD0, 0xCD,
+  0xCC, 0x63, 0x5E, 0x58, 0x50, 0x47, 0x43, 0x3F,
+  0x3F, 0x3F, 0x3F, 0x3F, 0x40, 0x41, 0x3F, 0x4A,
+  0x56, 0x5E, 0x64, 0xCB, 0x65, 0x63, 0x5E, 0x56,
+  0x4C, 0x48, 0x47, 0x47, 0x49, 0x4C, 0x51, 0x54,
+  0x58, 0x57, 0x57, 0x57, 0x57, 0x55, 0x54, 0x54,
+  0x57, 0x5A, 0x5A, 0x5C, 0x5B, 0x5A, 0x58, 0x54,
+  0x51, 0x4C, 0x55, 0x5D, 0x5D, 0x5B, 0x54, 0xFC,
+  0xF0, 0xF9, 0xFC, 0x65, 0x45, 0xCD, 0xFB, 0xFB,
+  0xF8, 0x26, 0xFB, 0xFC, 0xFC, 0xFC, 0x21, 0x27,
+  0xFB, 0xFC, 0xFC, 0xFC, 0xFB, 0xD7, 0x35, 0x34,
+  0x2F, 0x35, 0x36, 0x2F, 0x2F, 0x36, 0x2F, 0x2F,
+  0x36, 0x36, 0x35, 0x35, 0x43, 0x42, 0x41, 0x2E,
+  0x45, 0x4C, 0x5B, 0x62, 0x65, 0xCC, 0x64, 0x60,
+  0x58, 0x4D, 0x49, 0x47, 0x47, 0x49, 0x4C, 0x51,
+  0x58, 0x57, 0x57, 0x57, 0x57, 0x57, 0x55, 0x57,
+  0x58, 0x5A, 0x5A, 0x5B, 0x5A, 0x55, 0x54, 0x51,
+  0x53, 0x5C, 0x5D, 0x5D, 0x54, 0x4B, 0x4D, 0xFC,
+  0xFC, 0x44, 0xFC, 0xFB, 0x7B, 0xAB, 0xA8, 0xAE,
+  0xAB, 0x7F, 0xFC, 0xFC, 0xFB, 0xFB, 0x22, 0x2A,
+  0xFC, 0xFC, 0xFC, 0xFC, 0x36, 0x2F, 0x30, 0x30,
+  0x32, 0x30, 0x32, 0x30, 0x30, 0x30, 0x30, 0x30,
+  0x30, 0x30, 0x30, 0x30, 0x2F, 0x2F, 0x40, 0x41,
+  0x2E, 0x40, 0x48, 0x56, 0x5F, 0x64, 0xCC, 0x65,
+  0x61, 0x59, 0x50, 0x49, 0x47, 0x47, 0x49, 0x4C,
+  0x5A, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58,
+  0x5A, 0x5A, 0x5A, 0x58, 0x55, 0x52, 0x51, 0x5A,
+  0x5D, 0x5D, 0x57, 0x4C, 0x51, 0x54, 0x5D, 0xFC,
+  0xFC, 0x2A, 0xFC, 0xC9, 0xAA, 0x8B, 0x8A, 0x8C,
+  0xAB, 0x8C, 0x8C, 0xFB, 0xFB, 0x23, 0x20, 0xF1,
+  0xFC, 0xFC, 0xFC, 0x3B, 0x33, 0x33, 0x32, 0x32,
+  0x31, 0x32, 0x30, 0x32, 0x32, 0x32, 0x32, 0x30,
+  0x31, 0x31, 0x31, 0x32, 0x33, 0x33, 0x3C, 0x41,
+  0x41, 0x2E, 0x2D, 0x45, 0x4D, 0x5D, 0x63, 0xCC,
+  0x65, 0x62, 0x5D, 0x51, 0x49, 0x47, 0x47, 0x4A,
+  0x59, 0x57, 0x57, 0x57, 0x57, 0x58, 0x58, 0x58,
+  0x5A, 0x5A, 0x58, 0x55, 0x53, 0x53, 0x5C, 0x5E,
+  0x59, 0x51, 0x4E, 0x54, 0x59, 0x5E, 0x62, 0xFC,
+  0xFC, 0xDB, 0xAA, 0xA1, 0x95, 0x9C, 0x8C, 0x88,
+  0x82, 0x83, 0x83, 0x8C, 0x88, 0xAE, 0xB9, 0xFB,
+  0xFC, 0xFC, 0xFC, 0x3C, 0x3B, 0x72, 0x38, 0x33,
+  0x33, 0x33, 0x31, 0x33, 0x31, 0x31, 0x31, 0x31,
+  0x33, 0x33, 0x38, 0x33, 0x72, 0x3B, 0x44, 0x2E,
+  0x41, 0x2E, 0x2E, 0x2D, 0x43, 0x4B, 0x5B, 0x63,
+  0xCB, 0xCC, 0x63, 0x5D, 0x51, 0x49, 0x47, 0x49,
+  0x5C, 0x58, 0x57, 0x57, 0x57, 0x57, 0x58, 0x58,
+  0x58, 0x58, 0x57, 0x53, 0x58, 0x5D, 0x5E, 0x55,
+  0x51, 0x53, 0x58, 0x5E, 0x60, 0x63, 0x64, 0xFC,
+  0xFC, 0xC0, 0xA6, 0x9D, 0x8B, 0x9C, 0x8C, 0x8C,
+  0x6E, 0x83, 0x88, 0x8C, 0x8C, 0x8C, 0x83, 0xE8,
+  0xFB, 0xFC, 0xFC, 0xFC, 0x33, 0x70, 0x70, 0x6F,
+  0x6F, 0x6F, 0x6F, 0x3A, 0x6F, 0x6D, 0x6F, 0x6F,
+  0x70, 0x6F, 0x6F, 0x70, 0x6F, 0x32, 0x5A, 0x48,
+  0x41, 0x2D, 0x2D, 0x2D, 0x2C, 0x41, 0x49, 0x5A,
+  0x62, 0xCB, 0xCB, 0x63, 0x5D, 0x50, 0x49, 0x4A,
+  0x5C, 0x58, 0x58, 0x57, 0x55, 0x57, 0x57, 0x57,
+  0x57, 0x55, 0x56, 0x59, 0x5E, 0x5C, 0x52, 0x53,
+  0x55, 0x5B, 0x5E, 0x61, 0x63, 0x64, 0x63, 0xFC,
+  0xE8, 0xBF, 0xA4, 0x99, 0x9C, 0x8C, 0x88, 0x88,
+  0x6E, 0x88, 0x8C, 0x8C, 0x8C, 0xC2, 0xA6, 0xC4,
+  0xFC, 0xFC, 0xFC, 0xFC, 0x36, 0x3A, 0x6F, 0x70,
+  0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
+  0x70, 0x70, 0x70, 0x70, 0x37, 0x32, 0xCD, 0x5E,
+  0x4C, 0x43, 0x2C, 0x2D, 0x2D, 0x2C, 0x2E, 0x47,
+  0x57, 0x61, 0x65, 0xCC, 0x63, 0x5C, 0x50, 0x4D,
+  0x5C, 0x5A, 0x57, 0x55, 0x55, 0x55, 0x58, 0x58,
+  0x55, 0x54, 0x5B, 0x5E, 0x5D, 0x53, 0x53, 0x55,
+  0x5D, 0x5E, 0x61, 0x61, 0x61, 0x61, 0x5E, 0xFC,
+  0xEA, 0xBE, 0xA4, 0x9B, 0x8B, 0x85, 0x8C, 0x6E,
+  0x8C, 0x8C, 0x8C, 0xA3, 0xAA, 0xA4, 0xA4, 0xE9,
+  0xFB, 0xFC, 0xFC, 0xFC, 0x36, 0x6D, 0x70, 0x73,
+  0x70, 0x70, 0x70, 0x73, 0x73, 0x73, 0x73, 0x70,
+  0x70, 0x70, 0x73, 0x70, 0x37, 0x38, 0xD1, 0xCF,
+  0x61, 0x4D, 0x44, 0x2C, 0x2D, 0x2E, 0x2C, 0x2E,
+  0x3E, 0x56, 0x61, 0xCB, 0xCC, 0x62, 0x5B, 0x57,
+  0x59, 0x58, 0x55, 0x54, 0x54, 0x55, 0x58, 0x58,
+  0x58, 0x5B, 0x5E, 0x5B, 0x53, 0x55, 0x55, 0x5C,
+  0x5E, 0x61, 0x61, 0x60, 0x5D, 0x5A, 0x4E, 0xFC,
+  0xFC, 0xEA, 0xAA, 0x9C, 0x8A, 0x85, 0x82, 0x8C,
+  0x8C, 0xA8, 0xEB, 0xA8, 0xA4, 0xA4, 0xAA, 0xFC,
+  0xFC, 0xFC, 0x64, 0xFB, 0x39, 0x31, 0x72, 0x78,
+  0x73, 0x78, 0x73, 0x74, 0x74, 0x74, 0x74, 0x73,
+  0x78, 0x70, 0x73, 0x73, 0x33, 0xCC, 0xD2, 0xD1,
+  0xCE, 0x62, 0x53, 0x3F, 0x2D, 0x2D, 0x41, 0x2C,
+  0x2E, 0x3E, 0x56, 0x62, 0xCB, 0xCB, 0x61, 0x5D,
+  0x54, 0x54, 0x54, 0x54, 0x56, 0x58, 0x58, 0x58,
+  0x5C, 0x5E, 0x5A, 0x55, 0x58, 0x58, 0x5B, 0x5E,
+  0x61, 0x5E, 0x5D, 0x5A, 0x52, 0x55, 0xCD, 0xFC,
+  0xFC, 0x34, 0xC9, 0xE8, 0xA8, 0xAE, 0xC2, 0xE8,
+  0xC3, 0xA6, 0xA7, 0xA6, 0xAA, 0x78, 0x2E, 0x42,
+  0xFC, 0xFC, 0xD2, 0x64, 0xF8, 0x31, 0x72, 0x73,
+  0x73, 0x73, 0x73, 0x74, 0x75, 0x75, 0x74, 0x73,
+  0x73, 0x73, 0x73, 0x72, 0x33, 0x5C, 0x64, 0xD2,
+  0xD1, 0xCF, 0x63, 0x54, 0x3F, 0x2C, 0x41, 0x41,
+  0x2C, 0x2E, 0x47, 0x58, 0x63, 0xCB, 0xCB, 0x62,
+  0x52, 0x53, 0x53, 0x56, 0x58, 0x58, 0x5A, 0x5B,
+  0x5E, 0x5A, 0x57, 0x58, 0x58, 0x58, 0x60, 0x60,
+  0x5D, 0x5A, 0x55, 0x4E, 0x64, 0xD2, 0xD1, 0xFC,
+  0xFC, 0x41, 0x3E, 0xC1, 0xC0, 0xA3, 0xA6, 0xA7,
+  0xA7, 0xA9, 0xAA, 0xB8, 0x2E, 0x3F, 0x2C, 0x41,
+  0xFC, 0xFC, 0xF7, 0xCE, 0xCD, 0x36, 0x72, 0x73,
+  0x74, 0x75, 0x78, 0x75, 0x75, 0x75, 0x74, 0x74,
+  0x74, 0x74, 0x78, 0x72, 0x6D, 0x49, 0x59, 0xCB,
+  0xD1, 0xD1, 0xD2, 0xCB, 0x56, 0x3F, 0x2C, 0x41,
+  0x40, 0x2D, 0x2E, 0x49, 0x5B, 0x64, 0xCC, 0x64,
+  0x51, 0x53, 0x53, 0x55, 0x58, 0x59, 0x5B, 0x5E,
+  0x59, 0x58, 0x58, 0x58, 0x55, 0x60, 0x60, 0x5C,
+  0x5A, 0x53, 0x5B, 0xD0, 0xD3, 0xD3, 0xD3, 0xFB,
+  0xFC, 0x40, 0x41, 0x45, 0xC4, 0xC0, 0xBE, 0xBE,
+  0xC1, 0xC0, 0x3C, 0x47, 0x2E, 0x21, 0x22, 0x20,
+  0x65, 0xFC, 0xFC, 0xFC, 0xFC, 0x6D, 0x72, 0x75,
+  0x78, 0x76, 0x75, 0x79, 0x76, 0x76, 0x76, 0x76,
+  0x75, 0x75, 0x75, 0x72, 0x6D, 0x2E, 0x48, 0x5D,
+  0xCE, 0xD1, 0xD4, 0xD3, 0xCB, 0x56, 0x43, 0x2C,
+  0x42, 0x43, 0x2E, 0x2E, 0x4A, 0x5D, 0x64, 0x64,
+  0x50, 0x52, 0x56, 0x58, 0x5C, 0x5D, 0x5E, 0x5D,
+  0x5A, 0x58, 0x58, 0x55, 0x61, 0x60, 0x58, 0x58,
+  0x4E, 0x61, 0xD1, 0xD4, 0xD4, 0xD1, 0xEE, 0xFC,
+  0xFC, 0x2B, 0x29, 0x2E, 0x3F, 0xB0, 0xAD, 0x81,
+  0x46, 0x2D, 0x46, 0x2C, 0x24, 0x22, 0x22, 0x23,
+  0x25, 0xFC, 0xFC, 0xFC, 0xFC, 0x6E, 0x73, 0x76,
+  0x76, 0x79, 0x79, 0x79, 0x76, 0x76, 0x79, 0x76,
+  0x79, 0x79, 0x79, 0x74, 0x3F, 0x41, 0x2C, 0x48,
+  0x5F, 0xCF, 0xD5, 0xD7, 0xD6, 0xCD, 0x57, 0x40,
+  0x2E, 0x3F, 0x44, 0x2E, 0x41, 0x4C, 0x60, 0x61,
+  0x51, 0x53, 0x58, 0x5C, 0x5D, 0x5E, 0x5D, 0x5C,
+  0x58, 0x57, 0x54, 0x5F, 0x5E, 0x55, 0x55, 0x52,
+  0x64, 0xD4, 0xD5, 0xD4, 0xD1, 0x5D, 0xFA, 0xFB,
+  0xF4, 0x21, 0x24, 0x41, 0x40, 0x44, 0x2E, 0x2E,
+  0x42, 0x41, 0x2A, 0x24, 0x22, 0x22, 0x22, 0x22,
+  0x23, 0xD9, 0xFC, 0xFC, 0xFC, 0xFC, 0xE5, 0xB8,
+  0x8F, 0x8F, 0x7A, 0x8F, 0x7A, 0x8F, 0x7A, 0x8F,
+  0x8F, 0x8F, 0xB8, 0xE5, 0x3F, 0x3E, 0x43, 0x2C,
+  0x48, 0x61, 0xD1, 0xD7, 0xD9, 0xD7, 0xD0, 0x57,
+  0x41, 0x2E, 0x3E, 0x44, 0x2D, 0x40, 0x52, 0x5D,
+  0x53, 0x55, 0x59, 0x5D, 0x5E, 0x5E, 0x5D, 0x5A,
+  0x57, 0x53, 0x5E, 0x5E, 0x54, 0x53, 0x54, 0x65,
+  0xD5, 0xD6, 0xD4, 0xCE, 0x53, 0xFB, 0xF9, 0xFC,
+  0x24, 0x22, 0x23, 0x23, 0x41, 0x42, 0x2E, 0x40,
+  0x2B, 0x21, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+  0x23, 0x23, 0xFC, 0xFC, 0xFC, 0xFC, 0xE7, 0xBD,
+  0xB5, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93,
+  0x93, 0xB5, 0xC6, 0xEB, 0x2D, 0x47, 0x4A, 0x47,
+  0x2C, 0x3E, 0x61, 0xD4, 0xDC, 0xDC, 0xDA, 0xCF,
+  0x54, 0x41, 0x41, 0x3E, 0x45, 0x2C, 0x3F, 0x4A,
+  0x58, 0x5A, 0x5C, 0x5F, 0x60, 0x5E, 0x5D, 0x57,
+  0x51, 0x5D, 0x5D, 0x51, 0x53, 0x53, 0xCB, 0xD5,
+  0xD6, 0xD5, 0x63, 0x55, 0xFC, 0xFC, 0xFC, 0x2C,
+  0x23, 0x22, 0x23, 0x22, 0x20, 0x2D, 0x2C, 0x26,
+  0x21, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+  0x22, 0x21, 0xF0, 0xFC, 0xFC, 0xFC, 0xE2, 0xC6,
+  0xB5, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93,
+  0x93, 0x93, 0xC7, 0xE3, 0x3E, 0x2E, 0x49, 0x52,
+  0x4C, 0x41, 0x44, 0x62, 0xD6, 0xDE, 0xDE, 0xD9,
+  0xD0, 0x51, 0x2E, 0x40, 0x47, 0x44, 0x2C, 0x42,
+  0x5D, 0x5D, 0x5F, 0x60, 0x60, 0x5D, 0x57, 0x51,
+  0x58, 0x5D, 0x4E, 0x52, 0x55, 0x64, 0xD5, 0xD6,
+  0xD4, 0x61, 0x59, 0x6B, 0xFC, 0xFC, 0xFC, 0x21,
+  0x23, 0x22, 0x23, 0x22, 0x23, 0x21, 0x23, 0x22,
+  0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+  0x22, 0x21, 0x24, 0xFC, 0xFC, 0xFC, 0xE2, 0xC7,
+  0xB5, 0x90, 0x93, 0x93, 0x93, 0x90, 0x93, 0x93,
+  0x90, 0xB5, 0xC8, 0xE4, 0x5F, 0x45, 0x2E, 0x4D,
+  0x57, 0x57, 0x44, 0x43, 0x63, 0xDA, 0xDF, 0xDF,
+  0xD9, 0xCE, 0x4C, 0x2C, 0x3F, 0x3E, 0x40, 0x40,
+  0x60, 0x5E, 0x61, 0x61, 0x5E, 0x5B, 0x53, 0x52,
+  0x5C, 0x52, 0x52, 0x55, 0x61, 0xD4, 0xD5, 0xD1,
+  0x5E, 0x5B, 0x5C, 0xFB, 0xFC, 0xFC, 0x2A, 0x21,
+  0x23, 0x22, 0x23, 0x22, 0x22, 0x22, 0x23, 0x22,
+  0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+  0x22, 0x22, 0x22, 0xFB, 0xFC, 0xFC, 0xB3, 0xC8,
+  0xB5, 0x90, 0x92, 0xB5, 0x93, 0x93, 0xB5, 0x93,
+  0x92, 0xB5, 0xC8, 0xB9, 0xD0, 0x5E, 0x44, 0x40,
+  0x52, 0x58, 0x57, 0x48, 0x40, 0x63, 0xD9, 0xE0,
+  0xE0, 0xD9, 0xCB, 0x49, 0x2D, 0x3F, 0x45, 0x3F,
+  0x63, 0x61, 0x62, 0x60, 0x5E, 0x55, 0x4D, 0x59,
+  0x53, 0x4E, 0x54, 0x5D, 0xD2, 0xD4, 0xD2, 0x5E,
+  0x5C, 0x5D, 0xFC, 0xFC, 0xFC, 0xF8, 0x29, 0x23,
+  0x23, 0x23, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+  0x23, 0x22, 0x22, 0x23, 0x23, 0x23, 0x22, 0x22,
+  0x22, 0x22, 0x22, 0xF0, 0xFC, 0xFC, 0xB3, 0xC7,
+  0xB5, 0x93, 0xB5, 0x93, 0x93, 0x91, 0x93, 0x93,
+  0x91, 0xB5, 0xC7, 0xAD, 0xD6, 0xD2, 0x5E, 0x3F,
+  0x3F, 0x57, 0x57, 0x58, 0x4A, 0x41, 0x64, 0xDC,
+  0xF1, 0xDF, 0xDA, 0x61, 0x45, 0x2E, 0x43, 0x47,
+  0xCB, 0x63, 0x62, 0x5F, 0x58, 0x51, 0x53, 0x54,
+  0x4C, 0x52, 0x5C, 0xCD, 0xD3, 0xD2, 0x60, 0x5D,
+  0x5D, 0xFB, 0xFC, 0xFC, 0xFC, 0xDB, 0x49, 0x24,
+  0x21, 0x23, 0x23, 0x22, 0x26, 0x26, 0x2A, 0x24,
+  0x22, 0x23, 0x22, 0x21, 0x24, 0x26, 0x26, 0x2A,
+  0x29, 0x2B, 0x24, 0x25, 0xFC, 0xFC, 0xB3, 0xC5,
+  0x91, 0x91, 0x92, 0x91, 0x92, 0x92, 0x93, 0x93,
+  0x91, 0x93, 0xC6, 0xAD, 0xDC, 0xD9, 0xD4, 0x60,
+  0x43, 0x45, 0x58, 0x58, 0x57, 0x4B, 0x43, 0xCC,
+  0xDD, 0xF1, 0xD8, 0xD5, 0x5D, 0x43, 0x41, 0x47,
+  0xCD, 0x63, 0x62, 0x5D, 0x54, 0x4C, 0x55, 0x4B,
+  0x51, 0x58, 0x62, 0xD0, 0xD0, 0x62, 0x5D, 0x5D,
+  0x67, 0xFC, 0xFC, 0xFC, 0xFC, 0x58, 0x4E, 0x28,
+  0x2A, 0x20, 0x23, 0x22, 0x23, 0x2A, 0x23, 0x22,
+  0x22, 0x22, 0x23, 0x23, 0x25, 0x2A, 0x2E, 0x2D,
+  0x2E, 0x2E, 0x2E, 0x23, 0xFA, 0xFC, 0xB2, 0xBD,
+  0xB5, 0x90, 0x91, 0x93, 0x92, 0x90, 0x91, 0x93,
+  0x92, 0x91, 0xBD, 0xAD, 0xDE, 0xE0, 0xD8, 0xD7,
+  0x61, 0x40, 0x48, 0x58, 0x58, 0x58, 0x48, 0x44,
+  0xCF, 0xDE, 0xE0, 0xDD, 0xD0, 0x52, 0x41, 0x45,
+  0xCD, 0x63, 0x61, 0x58, 0x4D, 0x51, 0x4C, 0x4B,
+  0x54, 0x5D, 0xCC, 0xCE, 0x63, 0x61, 0x5D, 0x5D,
+  0xFB, 0xFC, 0xFC, 0xFC, 0xFC, 0x4B, 0x27, 0x21,
+  0x22, 0x22, 0x23, 0x22, 0x22, 0x24, 0x23, 0x22,
+  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x20,
+  0x27, 0x2B, 0x41, 0x2B, 0x23, 0xFC, 0xB2, 0xB6,
+  0x93, 0x90, 0x92, 0xB5, 0x92, 0x90, 0xB5, 0x90,
+  0x92, 0x93, 0xBC, 0xAD, 0xDC, 0xF1, 0xF3, 0xF0,
+  0xD9, 0x61, 0x41, 0x4A, 0x58, 0x57, 0x57, 0x44,
+  0x49, 0xD2, 0xDD, 0xD8, 0xDA, 0x63, 0x4A, 0x45,
+  0xCC, 0x63, 0x5E, 0x52, 0x4B, 0x4C, 0x49, 0x51,
+  0x5C, 0x61, 0xCD, 0x65, 0x63, 0x5E, 0x4E, 0xCF,
+  0xFB, 0xFB, 0xF0, 0xFC, 0xD2, 0x2A, 0x22, 0x23,
+  0x22, 0x22, 0x23, 0x22, 0x22, 0x21, 0x22, 0x22,
+  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
+  0x23, 0x22, 0x26, 0x41, 0x27, 0xF9, 0x81, 0xB7,
+  0xB5, 0x91, 0x92, 0xB5, 0x91, 0xB5, 0x93, 0xB5,
+  0x93, 0xB6, 0xB7, 0xB9, 0xCB, 0xD8, 0xF3, 0xF2,
+  0xF2, 0xDB, 0x61, 0x2D, 0x51, 0x58, 0x57, 0x58,
+  0x41, 0x51, 0xD4, 0xDB, 0xDC, 0xD1, 0x5B, 0x4C,
+  0xCB, 0x62, 0x59, 0x4C, 0x4A, 0x49, 0x4B, 0x55,
+  0x60, 0x64, 0xCC, 0x64, 0x5E, 0x55, 0x60, 0xE1,
+  0xFB, 0xF8, 0xFC, 0xFC, 0x21, 0x22, 0x22, 0x23,
+  0x22, 0x22, 0x23, 0x22, 0x22, 0x21, 0x22, 0x22,
+  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
+  0x23, 0x22, 0x21, 0x24, 0x2D, 0x21, 0xB4, 0xBB,
+  0xB6, 0xB5, 0xB6, 0xB7, 0xB7, 0xB7, 0xB7, 0xB6,
+  0xB6, 0xB6, 0xBB, 0xB9, 0x45, 0xCB, 0xDF, 0xF3,
+  0xF3, 0xF3, 0xDB, 0x5E, 0x2C, 0x51, 0x58, 0x58,
+  0x52, 0x2D, 0x5C, 0xD4, 0xD9, 0xD5, 0x63, 0x58,
+  0x64, 0x60, 0x53, 0x49, 0x4A, 0x49, 0x52, 0x5C,
+  0x63, 0xCD, 0xCD, 0x63, 0x5C, 0x4E, 0x65, 0xFC,
+  0xFC, 0xF5, 0xFC, 0xD2, 0x23, 0x22, 0x22, 0x23,
+  0x22, 0x22, 0x23, 0x22, 0x22, 0x21, 0x22, 0x22,
+  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
+  0x23, 0x22, 0x21, 0x22, 0x25, 0x29, 0xB3, 0xC7,
+  0xB5, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6,
+  0xB6, 0xB5, 0xC7, 0xAD, 0x57, 0x3F, 0xCB, 0xF0,
+  0xF3, 0xF3, 0xF2, 0xD9, 0x58, 0x41, 0x4C, 0x58,
+  0x57, 0x47, 0x42, 0x62, 0xD4, 0xD4, 0xCC, 0x60,
+  0x63, 0x5D, 0x50, 0x47, 0x48, 0x4B, 0x58, 0x60,
+  0xCC, 0xCE, 0xCD, 0x60, 0x53, 0x5C, 0x62, 0xFB,
+  0xF9, 0xFC, 0xFC, 0x21, 0x23, 0x22, 0x22, 0x23,
+  0x22, 0x22, 0x23, 0x23, 0x23, 0x21, 0x22, 0x22,
+  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
+  0x23, 0x22, 0x23, 0x23, 0x22, 0x23, 0x81, 0xC7,
+  0xB7, 0xB7, 0xBC, 0xB7, 0xBC, 0xBC, 0xBC, 0xB7,
+  0xB7, 0xB7, 0xC8, 0x80, 0x58, 0x57, 0x40, 0xCE,
+  0xF3, 0xF2, 0xF2, 0xF0, 0xD5, 0x4C, 0x3F, 0x4B,
+  0x52, 0x50, 0x2D, 0x4B, 0x64, 0xD2, 0xCC, 0x61,
+  0x60, 0x58, 0x4A, 0x47, 0x47, 0x4C, 0x59, 0x64,
+  0xD0, 0xD0, 0x64, 0x59, 0x49, 0x5D, 0xFB, 0xFC,
+  0xD9, 0xFC, 0xD6, 0x23, 0x22, 0x22, 0x22, 0x23,
+  0x22, 0x22, 0x23, 0x23, 0x21, 0x21, 0x22, 0x22,
+  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
+  0x23, 0x22, 0x23, 0x23, 0x22, 0x23, 0xB4, 0xC8,
+  0xBD, 0xB7, 0xBD, 0xBC, 0xBD, 0xC5, 0xBC, 0xC5,
+  0xBC, 0xBD, 0xC7, 0xAC, 0x58, 0x57, 0x58, 0x2C,
+  0xD1, 0xF0, 0xF3, 0xF3, 0xE0, 0xCD, 0x45, 0x3E,
+  0x48, 0x4B, 0x3F, 0x41, 0x56, 0x64, 0x65, 0x62,
+  0x5D, 0x52, 0x47, 0x48, 0x48, 0x53, 0x60, 0xCC,
+  0xD2, 0xD0, 0x63, 0x52, 0x4E, 0x53, 0xFB, 0xFB,
+  0xFC, 0xFC, 0x23, 0x23, 0x22, 0x23, 0x22, 0x23,
+  0x22, 0x22, 0x23, 0x23, 0x20, 0x21, 0x22, 0x22,
+  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
+  0x23, 0x22, 0x23, 0x22, 0x23, 0x22, 0xB4, 0xC7,
+  0xC5, 0xBC, 0xC5, 0xBD, 0xC5, 0xC5, 0xBD, 0xC5,
+  0xBC, 0xC6, 0xC7, 0xB9, 0x58, 0x57, 0x58, 0x57,
+  0x2D, 0xD4, 0xF1, 0xF2, 0xF0, 0xD9, 0x5D, 0x47,
+  0x48, 0x3F, 0x42, 0x2C, 0x48, 0x5C, 0x5F, 0x60,
+  0x58, 0x50, 0x47, 0x4A, 0x49, 0x55, 0x63, 0xD0,
+  0xD2, 0xCD, 0x5D, 0x49, 0x4E, 0xE1, 0xFC, 0xF0,
+  0xFC, 0xF8, 0x22, 0x22, 0x22, 0x23, 0x22, 0x23,
+  0x22, 0x22, 0x23, 0x20, 0x21, 0x21, 0x22, 0x22,
+  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0x22,
+  0x23, 0x22, 0x23, 0x23, 0x23, 0x22, 0xC4, 0xC8,
+  0xBD, 0xBD, 0xC6, 0xBD, 0xC6, 0xC6, 0xC5, 0xC6,
+  0xBD, 0xC6, 0xC7, 0xE4, 0x54, 0x57, 0x58, 0x57,
+  0x57, 0x43, 0xD7, 0xE0, 0xF1, 0xD8, 0xCD, 0x4B,
+  0x4A, 0x47, 0x42, 0x2C, 0x3F, 0x4D, 0x58, 0x5C,
+  0x52, 0x4B, 0x48, 0x4B, 0x4A, 0x58, 0xCB, 0xD3,
+  0xD2, 0xCD, 0x58, 0x47, 0x4A, 0xFC, 0xFC, 0xFB,
+  0xFC, 0x2B, 0x22, 0x22, 0x22, 0x23, 0x22, 0x23,
+  0x22, 0x22, 0x23, 0x26, 0x21, 0x21, 0x23, 0x22,
+  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
+  0x22, 0x23, 0x22, 0x23, 0x22, 0x23, 0xE5, 0xC8,
+  0xBA, 0xC5, 0xC6, 0xC6, 0xC6, 0xC7, 0xC6, 0xC7,
+  0xC5, 0xC6, 0xC8, 0xE5, 0x2E, 0x54, 0x58, 0x57,
+  0x57, 0x4C, 0x4D, 0xDA, 0xD8, 0xD8, 0xD4, 0x5C,
+  0x4B, 0x4B, 0x3F, 0x42, 0x44, 0x4A, 0x51, 0x58,
+  0x4B, 0x48, 0x4B, 0x51, 0x4D, 0x5F, 0xD0, 0xD1,
+  0xD0, 0x64, 0x51, 0x44, 0x6B, 0xFC, 0xFB, 0xFC,
+  0xFC, 0x21, 0x23, 0x22, 0x22, 0x23, 0x22, 0x23,
+  0x22, 0x22, 0x23, 0x26, 0x21, 0x23, 0x23, 0x22,
+  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
+  0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0xE5, 0xED,
+  0xE7, 0xBA, 0xC8, 0xC6, 0xC6, 0xC6, 0xC6, 0xC7,
+  0xC7, 0xE5, 0xED, 0xE6, 0x61, 0x41, 0x52, 0x58,
+  0x58, 0x57, 0x45, 0x5E, 0xD7, 0xDD, 0xD5, 0x60,
+  0x4B, 0x4C, 0x48, 0x4D, 0x4D, 0x50, 0x4D, 0x56,
+  0x4A, 0x3E, 0x53, 0x53, 0x52, 0x63, 0xD3, 0xD0,
+  0xCE, 0x60, 0x4A, 0x45, 0xFC, 0xFC, 0xF7, 0xFC,
+  0xFC, 0x21, 0x23, 0x23, 0x22, 0x23, 0x22, 0x23,
+  0x22, 0x23, 0x21, 0x2A, 0x20, 0x23, 0x23, 0x22,
+  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
+  0x23, 0x22, 0x23, 0x22, 0x21, 0x23, 0xEB, 0xF6,
+  0xF6, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED,
+  0xF6, 0xF6, 0xF6, 0xE6, 0xDB, 0x58, 0x45, 0x4B,
+  0x58, 0x57, 0x4D, 0x4B, 0x64, 0xD4, 0xD0, 0x5C,
+  0x48, 0x51, 0x4C, 0x5D, 0x5E, 0x5C, 0x56, 0x59,
+  0x3E, 0x4A, 0x58, 0x54, 0x52, 0x65, 0xD3, 0xD0,
+  0xCF, 0x5D, 0x48, 0xFC, 0xFC, 0xFC, 0xFA, 0xFC,
+  0xFC, 0x21, 0x22, 0x23, 0x22, 0x23, 0x22, 0x23,
+  0x22, 0x23, 0x21, 0x2A, 0x21, 0x23, 0x23, 0x22,
+  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
+  0x23, 0x22, 0x23, 0x22, 0x21, 0x4F, 0xE6, 0xC6,
+  0xC6, 0xBD, 0xC6, 0xBD, 0xBD, 0xBD, 0xBD, 0xC6,
+  0xC5, 0xBA, 0xC7, 0xE6, 0xF2, 0xD4, 0x49, 0x4B,
+  0x3E, 0x4D, 0x52, 0x3E, 0x52, 0x63, 0x64, 0x56,
+  0x48, 0x54, 0x4D, 0x61, 0xCC, 0xCC, 0x60, 0x60,
+  0x47, 0x4D, 0x5C, 0x53, 0x58, 0xCF, 0xD1, 0xCF,
+  0xD0, 0x59, 0x45, 0xFC, 0xFC, 0xFC, 0xEF, 0xF9,
+  0xFC, 0x21, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22,
+  0x23, 0x22, 0x23, 0x2A, 0x21, 0x23, 0x23, 0x22,
+  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
+  0x23, 0x22, 0x23, 0x22, 0x23, 0x4F, 0xE4, 0xB9,
+  0xAF, 0x80, 0x80, 0x8E, 0x8E, 0x8E, 0x8E, 0x8F,
+  0x80, 0xB4, 0xB9, 0xE4, 0x7F, 0xDE, 0x61, 0x52,
+  0x54, 0x48, 0x3F, 0x43, 0x4D, 0x56, 0x59, 0x4B,
+  0x3E, 0x58, 0x53, 0x61, 0xD3, 0xD4, 0xCF, 0xCD,
+  0x4C, 0x58, 0x5F, 0x53, 0x5E, 0xD3, 0xD0, 0xCE,
+  0xCE, 0x52, 0x3F, 0xFC, 0xFC, 0xFC, 0xF7, 0x65,
+  0xFA, 0x22, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22,
+  0x23, 0x22, 0x21, 0x2A, 0x23, 0x23, 0x23, 0x22,
+  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
+  0x23, 0x22, 0x23, 0x22, 0x21, 0xB1, 0xE4, 0xE6,
+  0x7C, 0xB1, 0x7C, 0xB1, 0xB2, 0xB2, 0xB3, 0x3D,
+  0xB3, 0x3C, 0xE5, 0xB3, 0xB0, 0xF1, 0xD0, 0x58,
+  0x5D, 0x4D, 0x40, 0x41, 0x48, 0x51, 0x4C, 0x3F,
+  0x3F, 0x4D, 0x5A, 0x5A, 0xD5, 0xD9, 0xD7, 0xD4,
+  0x57, 0x5E, 0x61, 0x4C, 0x63, 0xD4, 0xCF, 0xCE,
+  0xCB, 0x4D, 0x4A, 0xFC, 0xFC, 0xFC, 0xFC, 0xF0,
+  0xFB, 0x22, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22,
+  0x23, 0x22, 0x23, 0x2A, 0x21, 0x23, 0x23, 0x22,
+  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
+  0x22, 0x23, 0x22, 0x23, 0x23, 0xB1, 0x81, 0x7D,
+  0x39, 0x35, 0x35, 0x36, 0x36, 0x36, 0x36, 0x36,
+  0x36, 0x36, 0x7C, 0xB2, 0xB0, 0xDF, 0xD2, 0x57,
+  0x60, 0x59, 0x5B, 0x59, 0x52, 0x4C, 0x4A, 0x40,
+  0x42, 0x4A, 0x53, 0x4D, 0xD2, 0xDE, 0xDE, 0xD9,
+  0x5E, 0x5E, 0x60, 0x4A, 0xCD, 0xD1, 0xCF, 0xCE,
+  0x63, 0x49, 0x5C, 0xFB, 0xE8, 0x89, 0x9F, 0xFC,
+  0xD6, 0x21, 0x21, 0x23, 0x22, 0x22, 0x23, 0x22,
+  0x23, 0x22, 0x21, 0x2A, 0x22, 0x23, 0x23, 0x22,
+  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
+  0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x7F, 0xB9,
+  0x71, 0x6C, 0x38, 0x38, 0x33, 0x33, 0x33, 0x38,
+  0x38, 0x71, 0xAD, 0xE4, 0xD3, 0xDA, 0xCC, 0x52,
+  0x63, 0x60, 0xCE, 0xD4, 0xCF, 0x60, 0x4C, 0x40,
+  0x3F, 0x45, 0x4B, 0x5A, 0xCB, 0xD8, 0xDE, 0xDC,
+  0x5E, 0x5E, 0x5F, 0x4C, 0xD2, 0xD2, 0xCF, 0xCF,
+  0x61, 0x45, 0x5E, 0xA7, 0x9D, 0x95, 0x8B, 0x99,
+  0xFC, 0x41, 0x21, 0x23, 0x23, 0x22, 0x23, 0x22,
+  0x23, 0x22, 0x23, 0x2A, 0x23, 0x23, 0x23, 0x22,
+  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
+  0x22, 0x22, 0x23, 0x22, 0x23, 0x77, 0x77, 0xF6,
+  0xFC, 0x7D, 0x7D, 0x7E, 0x7E, 0x7E, 0x7E, 0x7D,
+  0x7D, 0xFC, 0x47, 0x64, 0xD0, 0xD0, 0x5D, 0x4B,
+  0x62, 0xCC, 0xD1, 0xDE, 0xDE, 0xD4, 0x5E, 0x43,
+  0x3F, 0x3E, 0x48, 0x53, 0x58, 0xDB, 0xD8, 0xDC,
+  0x5E, 0x5E, 0x5E, 0x53, 0xD4, 0xD2, 0xD0, 0xD0,
+  0x5E, 0x49, 0xA7, 0xA6, 0x89, 0x95, 0x8B, 0x9C,
+  0x9C, 0xFB, 0xD4, 0x22, 0x22, 0x22, 0x22, 0x23,
+  0x22, 0x23, 0x23, 0x2A, 0x22, 0x23, 0x23, 0x22,
+  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
+  0x23, 0x22, 0x23, 0x23, 0x98, 0x8C, 0x8C, 0x88,
+  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xF8,
+  0xE9, 0x9C, 0x48, 0x5C, 0xD0, 0xCB, 0x48, 0x49,
+  0x5B, 0xCB, 0xCD, 0xE0, 0xF1, 0xDD, 0xD0, 0x4A,
+  0x41, 0x47, 0x45, 0x4C, 0x48, 0xD7, 0xDE, 0xDC,
+  0x5E, 0x5E, 0x5A, 0x58, 0xD1, 0xD0, 0xD0, 0xD2,
+  0x5C, 0x55, 0xA7, 0xA6, 0x87, 0x86, 0x89, 0x94,
+  0x9C, 0xA9, 0xFC, 0xF4, 0x22, 0x23, 0x22, 0x23,
+  0x22, 0x23, 0x22, 0x2A, 0x21, 0x23, 0x23, 0x22,
+  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
+  0x22, 0x23, 0x22, 0x23, 0xA4, 0x89, 0x8C, 0xAA,
+  0xFB, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xF7,
+  0x85, 0x88, 0x8D, 0x59, 0x64, 0x63, 0x47, 0x3E,
+  0x4C, 0x60, 0x61, 0xE0, 0xF0, 0xDF, 0xD9, 0x5D,
+  0x2E, 0x3E, 0x3E, 0x47, 0x4D, 0xCD, 0xDE, 0xDC,
+  0x5D, 0x5C, 0x51, 0x5D, 0xD1, 0xD2, 0xD2, 0xD4,
+  0x5A, 0xBE, 0xA7, 0x98, 0x8A, 0x8A, 0xA0, 0x8B,
+  0x86, 0x86, 0xF7, 0xFC, 0xF7, 0x26, 0x23, 0x23,
+  0x22, 0x22, 0x22, 0x22, 0x21, 0x22, 0x23, 0x22,
+  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
+  0x22, 0x21, 0x21, 0x21, 0xA1, 0x98, 0x9F, 0xBF,
+  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xA7,
+  0x8C, 0x86, 0x8D, 0x59, 0x5E, 0x5D, 0x3F, 0x3E,
+  0x47, 0x53, 0x63, 0xD9, 0xF0, 0xF1, 0xDE, 0xD0,
+  0x43, 0x3E, 0x47, 0x45, 0x4A, 0x5B, 0xDC, 0xDA,
+  0x5D, 0x59, 0x49, 0x5F, 0xD1, 0xD2, 0xD3, 0xB9,
+  0xA5, 0xA7, 0x98, 0x9B, 0x96, 0x9D, 0x89, 0x89,
+  0x8B, 0x9C, 0x9D, 0xFC, 0xFC, 0xFC, 0x26, 0x22,
+  0x23, 0x23, 0x22, 0x22, 0x21, 0x22, 0x23, 0x22,
+  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
+  0x22, 0x22, 0x29, 0x2D, 0x99, 0x99, 0xA2, 0xAA,
+  0xC4, 0xFB, 0xFC, 0xFC, 0xFC, 0xF6, 0xBF, 0xA2,
+  0x9C, 0x9C, 0x8E, 0xDC, 0xCD, 0x51, 0x41, 0x3E,
+  0x45, 0x49, 0x58, 0xCD, 0xE0, 0xE0, 0xD8, 0xDA,
+  0x4C, 0x4A, 0x45, 0x45, 0x48, 0x47, 0xDA, 0xDA,
+  0x5C, 0x58, 0x44, 0x69, 0xA9, 0x98, 0xA4, 0xA6,
+  0xA1, 0xA4, 0x99, 0x9E, 0x9D, 0x8B, 0x8A, 0x97,
+  0x87, 0x9A, 0x8A, 0xC2, 0xFC, 0xFC, 0xFC, 0x4D,
+  0x21, 0x21, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22,
+  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0x22,
+  0x21, 0x22, 0x2D, 0x34, 0xA4, 0xA2, 0xA2, 0xA9,
+  0xBF, 0xC0, 0xC3, 0xC1, 0xC0, 0xBE, 0xA6, 0x9D,
+  0x99, 0x87, 0xA2, 0xF1, 0xDC, 0x64, 0x42, 0x45,
+  0x47, 0x3E, 0x49, 0x4C, 0xDD, 0xDF, 0xD8, 0xDB,
+  0x5E, 0x4C, 0x48, 0x45, 0x45, 0x41, 0xD1, 0xD6,
+  0x5A, 0x55, 0x3F, 0xA7, 0xA1, 0x98, 0x9F, 0x99,
+  0x9F, 0x9D, 0x9A, 0x95, 0x8B, 0x97, 0x89, 0x8A,
+  0x88, 0x94, 0x9C, 0x8C, 0xFC, 0xFC, 0xFC, 0xFC,
+  0xF4, 0x21, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22,
+  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
+  0x23, 0x23, 0x2C, 0x2C, 0xA8, 0xA2, 0xA4, 0xA4,
+  0xA9, 0xAA, 0xAA, 0xAA, 0xA9, 0xA6, 0x98, 0x9C,
+  0x8B, 0x88, 0x98, 0x8D, 0xD8, 0xD6, 0x4E, 0x47,
+  0x47, 0x49, 0x47, 0x3F, 0xDA, 0xDD, 0xDE, 0xDD,
+  0xCC, 0x4A, 0x4B, 0x3E, 0x45, 0x43, 0x61, 0xD4,
+  0x56, 0x51, 0x44, 0xA4, 0x9B, 0x8B, 0x9C, 0x9A,
+  0xA0, 0xA2, 0x98, 0x98, 0x8B, 0x8B, 0x98, 0x98,
+  0x84, 0x8B, 0x94, 0x8A, 0xA4, 0xFC, 0xFC, 0xFC,
+  0xFC, 0xF2, 0x21, 0x22, 0x21, 0x22, 0x23, 0x22,
+  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0x23,
+  0x23, 0x22, 0x2C, 0x2D, 0xC0, 0xA4, 0xA2, 0xA4,
+  0xA4, 0xA6, 0xA6, 0xA6, 0xA4, 0xA2, 0x9F, 0x89,
+  0x8B, 0x9C, 0x9C, 0x8B, 0x68, 0xDB, 0x5F, 0x4B,
+  0x3E, 0x49, 0x4B, 0x3E, 0xCC, 0xDA, 0xDC, 0xDD,
+  0xD3, 0x49, 0x52, 0x48, 0x45, 0x45, 0x53, 0xD0,
+  0x51, 0x4A, 0x44, 0xA4, 0x9B, 0x8B, 0x9C, 0xA0,
+  0x9B, 0x86, 0x89, 0x98, 0x89, 0x8A, 0x96, 0x8A,
+  0x9C, 0x89, 0x89, 0x9C, 0x8C, 0xF6, 0xFC, 0xFC,
+  0xFC, 0xFC, 0x21, 0x22, 0x21, 0x22, 0x23, 0x22,
+  0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x22, 0x23,
+  0x22, 0x21, 0x2B, 0x34, 0xC0, 0xA8, 0xA4, 0xA2,
+  0xA2, 0x98, 0xA1, 0xA0, 0x98, 0x9F, 0x95, 0x8A,
+  0x94, 0xA1, 0x8A, 0x84, 0x9B, 0x68, 0xCC, 0x49,
+  0x4A, 0x47, 0x4C, 0x4B, 0x51, 0xD3, 0xDA, 0xDC,
+  0xD5, 0x56, 0x56, 0x4A, 0x3E, 0x45, 0x48, 0x63,
+  0x4A, 0x47, 0x3E, 0xA7, 0x98, 0x9D, 0x9E, 0x8B,
+  0x95, 0x9B, 0x89, 0x86, 0x9B, 0x8B, 0x89, 0x84,
+  0x9A, 0xA1, 0x95, 0x9A, 0x8C, 0xA4, 0xFC, 0xFC,
+  0xFC, 0xFA, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22,
+  0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x22, 0x23,
+  0x21, 0x23, 0x2C, 0xF6, 0xBF, 0xA9, 0xA2, 0x99,
+  0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9B, 0x87, 0x8B,
+  0x9C, 0x86, 0x9C, 0x8A, 0x87, 0x87, 0x89, 0x51,
+  0x54, 0x47, 0x4B, 0x50, 0x4B, 0xCF, 0xD6, 0xDC,
+  0xD5, 0x60, 0x54, 0x52, 0x48, 0x45, 0x40, 0x5A,
+  0x45, 0x43, 0x47, 0xA7, 0x98, 0x9B, 0x95, 0x95,
+  0x9A, 0x87, 0x98, 0x98, 0x8A, 0x86, 0x87, 0x9E,
+  0x9B, 0x95, 0x9D, 0x9D, 0x99, 0x85, 0xA6, 0xFA,
+  0xF2, 0x21, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22,
+  0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x22, 0x22,
+  0x21, 0x24, 0xFB, 0xF7, 0xBF, 0xA6, 0xA2, 0x99,
+  0x97, 0x89, 0x86, 0x89, 0x9C, 0x96, 0x9E, 0x94,
+  0x89, 0x99, 0x98, 0x89, 0x9E, 0x9B, 0x89, 0x8B,
+  0x58, 0x4B, 0x4A, 0x52, 0x48, 0xCC, 0xD3, 0xDA,
+  0xD3, 0x65, 0x4C, 0x58, 0x49, 0x3E, 0x2E, 0x4D,
+  0x40, 0x41, 0x45, 0xA9, 0xA1, 0x9B, 0x9E, 0x9C,
+  0x95, 0x8A, 0x94, 0x89, 0x96, 0x87, 0x9C, 0x9A,
+  0x84, 0x9D, 0x9C, 0x9E, 0x9A, 0x9C, 0x9D, 0xBB,
+  0x23, 0x23, 0x22, 0x22, 0x21, 0x22, 0x23, 0x22,
+  0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x23, 0x23,
+  0x24, 0xFC, 0xFC, 0xF6, 0xBF, 0xA6, 0x9F, 0x99,
+  0x89, 0x95, 0x87, 0x94, 0x9D, 0x9E, 0x97, 0x9E,
+  0x95, 0x9B, 0x89, 0x95, 0x95, 0x9B, 0x89, 0x87,
+  0x5D, 0x56, 0x3E, 0x51, 0x3E, 0x60, 0xCF, 0xD3,
+  0xD2, 0xCD, 0x5C, 0x49, 0x4B, 0x3E, 0x2C, 0x48,
+  0x3E, 0x43, 0x3E, 0xA9, 0xA1, 0x9B, 0x97, 0x94,
+  0x95, 0x9A, 0x9C, 0x87, 0x87, 0x9B, 0x9C, 0x95,
+  0x9D, 0x89, 0x9A, 0x89, 0x9E, 0x9E, 0x8C, 0xA6,
+  0x20, 0x23, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22,
+  0x22, 0x22, 0x22, 0x22, 0x21, 0x21, 0x20, 0x40,
+  0xFC, 0xFC, 0xFC, 0xEC, 0xBE, 0xA4, 0x9F, 0x99,
+  0x95, 0x9F, 0xA0, 0x88, 0x9D, 0x8B, 0x97, 0x95,
+  0x87, 0x95, 0x96, 0x95, 0x97, 0x94, 0x94, 0x98,
+  0xD3, 0x4C, 0x47, 0x4D, 0x42, 0x4C, 0x60, 0xCC,
+  0xCE, 0xD0, 0x65, 0x4B, 0x47, 0x44, 0x2B, 0x45,
+  0x4B, 0x47, 0x49, 0xA7, 0xA1, 0x9A, 0x97, 0x89,
+  0x95, 0x97, 0x97, 0x9E, 0x89, 0x95, 0x89, 0x9C,
+  0x87, 0x95, 0x97, 0x99, 0x95, 0x99, 0x9F, 0xA4,
+  0xC4, 0x21, 0x21, 0x23, 0x21, 0x23, 0x23, 0x23,
+  0x23, 0x23, 0x23, 0x23, 0x21, 0x20, 0xFC, 0xFC,
+  0xFC, 0xFC, 0xFC, 0xEA, 0xAA, 0xA6, 0xA2, 0x99,
+  0x8B, 0x9A, 0x95, 0x9E, 0x9E, 0x9A, 0x94, 0x87,
+  0x94, 0x94, 0x89, 0x94, 0x9B, 0x9B, 0xA7, 0xDC,
+  0xDB, 0x65, 0x2E, 0x3E, 0x43, 0x44, 0x49, 0x58,
+  0x63, 0xD3, 0xD3, 0x5E, 0x42, 0x42, 0x2D, 0x40,
+  0x54, 0x4C, 0x4A, 0xA7, 0xA0, 0x99, 0x9B, 0x94,
+  0xA0, 0x8A, 0x9B, 0x9D, 0x87, 0x95, 0x94, 0x8B,
+  0x8A, 0x98, 0x9C, 0x8A, 0x9B, 0x99, 0xA2, 0xA6,
+  0xBF, 0xEC, 0x2A, 0x20, 0x21, 0x23, 0x21, 0x20,
+  0x20, 0x20, 0x20, 0x4C, 0xF9, 0xFC, 0xFC, 0xFC,
+  0xFC, 0xFC, 0xFC, 0xEB, 0xAA, 0xA4, 0x9F, 0x9C,
+  0x8B, 0x9B, 0x88, 0x84, 0x9E, 0x9D, 0x96, 0x94,
+  0x94, 0x9A, 0x9B, 0x9B, 0xA4, 0xD5, 0xCD, 0xDE,
+  0xF1, 0xDA, 0x4C, 0x2D, 0x41, 0x2B, 0x42, 0x4C,
+  0x5E, 0xD4, 0xD7, 0xCD, 0x49, 0x2E, 0x2E, 0x41,
+  0x5E, 0x57, 0xA7, 0xA6, 0xA7, 0xA4, 0xA2, 0x98,
+  0x9D, 0x9C, 0xA1, 0x99, 0x9D, 0x88, 0x8B, 0x9C,
+  0x8A, 0x9C, 0x9C, 0x94, 0x9C, 0x89, 0xA0, 0xA6,
+  0xAA, 0xEB, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+  0xFC, 0xFC, 0xFB, 0xE9, 0xAA, 0xA6, 0xA2, 0x8B,
+  0x8B, 0x8A, 0x86, 0x9B, 0x9C, 0x98, 0xA0, 0x9B,
+  0x9B, 0x84, 0xA7, 0xB4, 0x61, 0xD1, 0xD2, 0xE0,
+  0xF1, 0xDC, 0x61, 0x2D, 0x2E, 0x3F, 0x56, 0x62,
+  0x5D, 0xD4, 0xD9, 0xD3, 0x54, 0x41, 0x41, 0x44,
+  0xCB, 0x60, 0x52, 0xA9, 0xA9, 0xA9, 0xA7, 0xA6,
+  0xA6, 0xA4, 0xA4, 0xA2, 0xA2, 0x9D, 0x95, 0x89,
+  0x9C, 0x8A, 0x9E, 0x9C, 0x8A, 0x9E, 0xA0, 0xA8,
+  0xC0, 0xE9, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+  0xFC, 0xFC, 0xFC, 0xE9, 0xAA, 0xA6, 0xA0, 0x99,
+  0x9C, 0x8B, 0x9A, 0x84, 0x9B, 0x9B, 0x98, 0x98,
+  0xA9, 0xB9, 0x49, 0x57, 0xCB, 0xD4, 0xD3, 0xF1,
+  0xD8, 0xDA, 0xCE, 0x3F, 0x41, 0x4B, 0x5D, 0xCB,
+  0x5E, 0xD6, 0xDB, 0xD6, 0x5D, 0x43, 0x3F, 0x49,
+  0xD1, 0xCC, 0x4F, 0xDD, 0xC3, 0xBB, 0xBF, 0xAA,
+  0xAA, 0xA9, 0xAA, 0xA8, 0xA8, 0xA6, 0xA6, 0xA2,
+  0x9C, 0x9F, 0x9B, 0x9A, 0x9D, 0xA2, 0xA8, 0xAA,
+  0xC1, 0xEA, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+  0xFC, 0xFC, 0xFC, 0xEA, 0xC0, 0xAA, 0xA6, 0xA2,
+  0xA2, 0x99, 0xA0, 0xA0, 0xA4, 0xA7, 0xA9, 0xC0,
+  0x67, 0x49, 0x54, 0x60, 0xD0, 0xD4, 0xCC, 0xDF,
+  0xD9, 0xD5, 0xD2, 0x3E, 0x47, 0x56, 0x60, 0xCD,
+  0x5D, 0xD9, 0xD9, 0xD6, 0x61, 0x3F, 0x47, 0x52,
+  0xD6, 0xD3, 0x62, 0x4D, 0x40, 0x4A, 0x57, 0xCA,
+  0xC3, 0xC1, 0xC1, 0xC0, 0xBF, 0xBF, 0xAA, 0xAA,
+  0xA6, 0xA4, 0xA4, 0xA4, 0xA6, 0xA8, 0xBE, 0xC1,
+  0xC9, 0xEB, 0xFB, 0xFB, 0xFC, 0xFC, 0xFC, 0xFC,
+  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+  0xFC, 0xFC, 0xFC, 0xEB, 0xC3, 0xC0, 0xAA, 0xA8,
+  0xA6, 0xA6, 0xA6, 0xA9, 0xAA, 0xC0, 0xE8, 0xD0,
+  0xD2, 0x4C, 0x5E, 0x64, 0xD0, 0xD1, 0x5F, 0xD9,
+  0xD5, 0xD1, 0xD0, 0x48, 0x52, 0x5C, 0x64, 0xCD,
+  0x5C, 0xDC, 0xD7, 0xD5, 0x62, 0x3F, 0x4C, 0x53,
+  0xDA, 0xD7, 0xCE, 0x56, 0x40, 0x4B, 0x52, 0x56,
+  0xCE, 0xDF, 0x6A, 0xEB, 0xE9, 0xC9, 0xC3, 0xC0,
+  0xC0, 0xBF, 0xBE, 0xAA, 0xBF, 0xC0, 0xC3, 0xC9,
+  0xEA, 0xF6, 0xEE, 0x58, 0x57, 0x5E, 0xD6, 0xD0,
+  0xD2, 0x61, 0xCB, 0xD6, 0xD6, 0xD4, 0xDF, 0xF3,
+  0xF2, 0xDD, 0xD7, 0xEB, 0xC9, 0xC1, 0xC0, 0xBF,
+  0xAA, 0xAA, 0xAA, 0xBE, 0xC3, 0xF0, 0xD2, 0xD2,
+  0xD2, 0x51, 0x62, 0xCC, 0xD0, 0xCC, 0x61, 0xD3,
+  0xCF, 0xCE, 0xD2, 0x48, 0x5A, 0x61, 0xCC, 0xCE,
+  0x5F, 0xD9, 0xD5, 0xD1, 0x63, 0x44, 0x56, 0x56,
+  0xDC, 0xD9, 0xD4, 0x5E, 0x42, 0x4A, 0x4C, 0x57,
+  0x5D, 0xD8, 0xE0, 0xD8, 0xDC, 0xCB, 0x66, 0xEC,
+  0xE8, 0xC3, 0xC3, 0xC3, 0xC3, 0xC9, 0xE8, 0xEA,
+  0xF6, 0x50, 0x3E, 0x58, 0x57, 0x5A, 0xD6, 0xD4,
+  0xCC, 0x4B, 0x53, 0x5C, 0x64, 0xD1, 0xDF, 0xF3,
+  0xF1, 0xDE, 0xD9, 0xF6, 0xEB, 0xC9, 0xC1, 0xC1,
+  0xC0, 0xC0, 0xC1, 0xC9, 0xF0, 0xD6, 0xCD, 0xD6,
+  0xD3, 0x53, 0xCB, 0xCF, 0xCD, 0x5F, 0x5F, 0xCE,
+  0xCF, 0xCD, 0xD0, 0x47, 0x5F, 0xCB, 0xCE, 0xCD,
+  0x63, 0xD6, 0xD3, 0xD1, 0x63, 0x3F, 0x58, 0x58,
+  0xDB, 0xDC, 0xDA, 0x65, 0x3E, 0x49, 0x49, 0x4D,
+  0x49, 0xDC, 0xDF, 0xE0, 0xDE, 0xD5, 0x47, 0x47,
+  0x46, 0x6B, 0xEB, 0xEA, 0xE9, 0xEA, 0xEB, 0xF6,
+  0xD0, 0x57, 0x57, 0x47, 0x47, 0x5B, 0xD4, 0xD4,
+  0xCD, 0x44, 0x3E, 0x4B, 0x50, 0x4B, 0x51, 0xD5,
+  0xDB, 0xD8, 0xDE, 0x4B, 0xF6, 0xF6, 0xEA, 0xE9,
+  0xE8, 0xEA, 0xEB, 0x67, 0x5E, 0xCC, 0xD6, 0xDC,
+  0xD5, 0x58, 0xCE, 0xCE, 0x62, 0x50, 0xCC, 0xD3,
+  0xD2, 0xCD, 0xCD, 0x4B, 0x64, 0xCE, 0xCE, 0x64,
+  0xCC, 0xD3, 0xD2, 0xD2, 0x61, 0x47, 0x5D, 0x5C,
+  0xDD, 0xDD, 0xD9, 0xD1, 0x4C, 0x47, 0x49, 0x4A,
+  0x4B, 0xD1, 0xD8, 0xE0, 0xDF, 0xDD, 0x5D, 0x4A,
+  0x48, 0x52, 0x51, 0x3F, 0xF6, 0xEC, 0xE0, 0xE0,
+  0xD3, 0x5E, 0x5F, 0x50, 0x4B, 0x50, 0xCB, 0xCE,
+  0x64, 0x45, 0x4C, 0x57, 0x57, 0x58, 0x52, 0xD6,
+  0xD3, 0xDE, 0xDF, 0xD1, 0x3E, 0x4B, 0xF6, 0xF6,
+  0xEC, 0x66, 0x53, 0x43, 0x56, 0xD1, 0xD9, 0xDE,
+  0xD4, 0x5E, 0xCE, 0xCC, 0x5B, 0x2C, 0xD4, 0xD5,
+  0xD2, 0xD0, 0x63, 0x5D, 0xCD, 0xD0, 0xCD, 0x5E,
+  0xD0, 0xCF, 0xCE, 0xD2, 0x5E, 0x50, 0x60, 0x5D,
+  0xDE, 0xDD, 0xDC, 0xD7, 0x5D, 0x45, 0x47, 0x3E,
+  0x4B, 0x5E, 0xDE, 0xDF, 0xE0, 0xD8, 0xCF, 0x3E,
+  0x45, 0x51, 0x58, 0x42, 0xCB, 0xDA, 0xDE, 0xD8,
+  0xD2, 0x61, 0xCC, 0xCF, 0xD6, 0xDA, 0xDA, 0xD5,
+  0xD0, 0x50, 0x44, 0x57, 0x57, 0x58, 0x45, 0xD1,
+  0xD1, 0xD7, 0xDF, 0xDF, 0xD7, 0xCF, 0x64, 0x60,
+  0xCE, 0xCE, 0xCE, 0x63, 0xCF, 0xDA, 0xDE, 0xD9,
+  0xCF, 0x63, 0xCD, 0x63, 0x4D, 0x4B, 0xD6, 0xD5,
+  0xCE, 0xD3, 0x60, 0xCB, 0xD0, 0xD0, 0x65, 0x47,
+  0xD0, 0xCC, 0xCC, 0xD1, 0x59, 0x5D, 0x63, 0x5E,
+  0xDD, 0xDD, 0xDE, 0xDC, 0xCB, 0x40, 0x48, 0x45,
+  0x3E, 0x3E, 0xD9, 0xDF, 0xE0, 0xDF, 0xDA, 0x51,
+  0x4C, 0x48, 0x56, 0x4C, 0x5B, 0xD2, 0xDA, 0xDB,
+  0xCB, 0x5F, 0xD0, 0xCC, 0xDC, 0xF0, 0xF3, 0xE0,
+  0xDD, 0xCC, 0x41, 0x50, 0x57, 0x57, 0x4B, 0x5D,
+  0xD3, 0xD1, 0xDE, 0xDF, 0xDE, 0xD7, 0xD0, 0xD0,
+  0xD5, 0xD6, 0xD6, 0xCE, 0xD7, 0xDC, 0xDA, 0xD5,
+  0x60, 0x63, 0x64, 0x5E, 0x47, 0x61, 0xD5, 0xD2,
+  0xCF, 0xD0, 0x59, 0xCD, 0xD1, 0xCF, 0x61, 0x4D,
+  0xCC, 0xCE, 0xCD, 0xD0, 0x52, 0x61, 0x64, 0x60,
+  0xDA, 0xDE, 0xDE, 0xDD, 0xD1, 0x4B, 0x4A, 0x45,
+  0x3E, 0x41, 0xCD, 0xDE, 0xE0, 0xF1, 0xDE, 0x63,
+  0x4A, 0x4A, 0x4A, 0x4B, 0x50, 0xCB, 0xD4, 0xD7,
+  0x5E, 0x54, 0x62, 0xD3, 0xD4, 0xF0, 0xF3, 0xF3,
+  0xF2, 0xDE, 0x61, 0x40, 0x49, 0x56, 0x4D, 0x3E,
+  0x4B, 0xCE, 0xD9, 0xD8, 0xD9, 0xD5, 0xCF, 0xD2,
+  0xD6, 0xD6, 0xD1, 0xD1, 0xD7, 0xD5, 0xCF, 0xD0,
+  0x54, 0x64, 0x63, 0x56, 0x2C, 0xCB, 0xD1, 0xCC,
+  0xD3, 0xCD, 0x54, 0xCF, 0xD1, 0xCE, 0x5E, 0x5C,
+  0xCE, 0xCE, 0xCE, 0xCB, 0x4B, 0x63, 0xCC, 0x61,
+  0xD4, 0xDC, 0xDE, 0xDE, 0xDA, 0x5D, 0x45, 0x45,
+  0x48, 0x3F, 0x52, 0xD9, 0xD8, 0xDF, 0xDF, 0xD2,
+  0x52, 0x4B, 0x3E, 0x2E, 0x47, 0x60, 0xCF, 0xD3,
+  0x59, 0x48, 0x50, 0x5E, 0xCC, 0xDE, 0xF2, 0xF2,
+  0xF3, 0xF3, 0xDD, 0x5D, 0x3E, 0x48, 0x47, 0x47,
+  0x58, 0xD1, 0xDA, 0xDA, 0xD5, 0xD1, 0xCD, 0xD2,
+  0xD3, 0xCF, 0xD3, 0xD1, 0xCD, 0xD3, 0xD2, 0x5E,
+  0x52, 0x64, 0x60, 0x4B, 0x45, 0x61, 0xCD, 0xD3,
+  0xD3, 0x64, 0x61, 0xD0, 0xD0, 0x64, 0x45, 0x63,
+  0xD0, 0xCE, 0xD0, 0x60, 0x56, 0xCB, 0xCC, 0x62,
+  0xCE, 0xDA, 0xDE, 0xD8, 0xDD, 0xCC, 0x45, 0x49,
+  0x3E, 0x47, 0x42, 0xD1, 0xDC, 0xD8, 0xD8, 0xD3,
+  0x5D, 0x4C, 0x49, 0x3F, 0x47, 0x59, 0xCD, 0xCF,
+  0x59, 0x2E, 0x48, 0x47, 0x52, 0x63, 0xF0, 0xF2,
+  0xF3, 0xF3, 0xF2, 0xDA, 0x52, 0x4B, 0x52, 0x58,
+  0x5E, 0x63, 0xD0, 0xD0, 0xD0, 0xCF, 0xCE, 0xCE,
+  0xCF, 0x65, 0x61, 0xD6, 0xD6, 0xD6, 0xCB, 0x4B,
+  0x61, 0x62, 0x5D, 0x43, 0x4B, 0x61, 0xD0, 0xD4,
+  0xD1, 0x61, 0xCE, 0xD2, 0xCD, 0x5E, 0x4A, 0xCE,
+  0xD0, 0xCC, 0xD0, 0x59, 0x61, 0xCC, 0xCC, 0x62,
+  0xD1, 0xD5, 0xDE, 0xD8, 0xDD, 0xCF, 0x4B, 0x4A,
+  0x45, 0x3E, 0x2D, 0xCB, 0xDC, 0xDE, 0xD8, 0xD5,
+  0x60, 0x54, 0x51, 0x4C, 0x4D, 0x5C, 0xCC, 0xCE,
+  0x5A, 0x2C, 0x50, 0x53, 0x3E, 0x59, 0xD8, 0xF3,
+  0xF2, 0xF3, 0xF3, 0xE0, 0x5E, 0x4A, 0x4C, 0x53,
+  0x5E, 0x63, 0xCC, 0xCC, 0xCC, 0xCD, 0xCF, 0xD3,
+  0x62, 0x53, 0xD6, 0xD6, 0xD6, 0xD6, 0x5B, 0x48,
+  0x64, 0x63, 0x59, 0x44, 0x57, 0x63, 0xD2, 0xD3,
+  0xD0, 0x5E, 0xD0, 0xD1, 0xCB, 0x58, 0x4C, 0xCF,
+  0xCF, 0xCE, 0xCE, 0x57, 0x63, 0xCC, 0xCD, 0x57,
+};
+
+unsigned char linux_logo_bw[] __initdata = {
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x3F,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F,
+  0xFE, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xFE, 0x3F, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xFE, 0x7F, 0xFF, 0xC7, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xC3,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF,
+  0xFB, 0xE3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xFD, 0xFF, 0xFF, 0xE1, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xF1,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xFF,
+  0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xF9, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xF9, 0xCF, 0xC3, 0xF8, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x87, 0x81, 0xF9,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xA7,
+  0x99, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xF9, 0xF3, 0xBC, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xF9, 0xE3, 0xBC, 0xF9, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xB0, 0x3C, 0xF9,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xB0,
+  0x19, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xF9, 0xC0, 0x03, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xF9, 0x80, 0x01, 0xF8, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x80, 0x01, 0xF8,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x80,
+  0x01, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xF9, 0xC0, 0x21, 0xD8, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xF9, 0xB1, 0x80, 0xEC, 0xC0, 0x1F,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xF1, 0x90, 0x00, 0xE4,
+  0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xF1, 0x8C,
+  0xC0, 0x7C, 0x04, 0x81, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xE3, 0x80, 0x00, 0x7C, 0x40, 0x11, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xE3, 0x80, 0x00, 0x7F, 0xD2, 0x29,
+  0xFF, 0xFF, 0xFF, 0xFF, 0x87, 0x00, 0x00, 0x3F,
+  0x80, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0x0E, 0x00,
+  0x00, 0x3F, 0x80, 0x19, 0xFF, 0xFF, 0xFF, 0xFF,
+  0x1E, 0x00, 0x00, 0x1F, 0x80, 0x19, 0xFF, 0xFF,
+  0xFF, 0xFE, 0x1C, 0x00, 0x00, 0x1E, 0x80, 0x19,
+  0xFF, 0xFF, 0xFF, 0xFE, 0x3C, 0x00, 0x00, 0x1E,
+  0x80, 0x11, 0xFF, 0xFF, 0xFF, 0xFC, 0x7C, 0x00,
+  0x00, 0x0F, 0x80, 0x11, 0xFF, 0xFF, 0xFF, 0xFC,
+  0xF8, 0x00, 0x00, 0x0E, 0x80, 0x11, 0xFF, 0xFF,
+  0xFF, 0xFC, 0xF8, 0x00, 0x00, 0x06, 0x00, 0x11,
+  0xFF, 0xFF, 0xFF, 0xF8, 0xF8, 0x00, 0x00, 0x06,
+  0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xF9, 0xF0, 0x00,
+  0x00, 0x02, 0x00, 0x09, 0xFF, 0xFF, 0xFF, 0xF1,
+  0xF0, 0x00, 0x00, 0x02, 0x80, 0x10, 0xFF, 0xFF,
+  0xFF, 0xF1, 0xE0, 0x00, 0x00, 0x00, 0x97, 0x10,
+  0xFF, 0xFF, 0xFF, 0xE3, 0xE0, 0x00, 0x00, 0x00,
+  0xDF, 0xF0, 0xFF, 0xFF, 0xFF, 0xE3, 0xC0, 0x00,
+  0x00, 0x00, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xC7,
+  0xC0, 0x00, 0x00, 0x01, 0xFF, 0xF8, 0xFF, 0xFF,
+  0xFF, 0xC7, 0x80, 0x00, 0x00, 0x01, 0xFF, 0xF8,
+  0xFF, 0xFF, 0xFF, 0x8F, 0x80, 0x00, 0x00, 0x01,
+  0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0x8F, 0x80, 0x00,
+  0x00, 0x01, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0x9F,
+  0x80, 0x00, 0x00, 0x01, 0xFF, 0xF8, 0xFF, 0xFF,
+  0xFF, 0x9F, 0x80, 0x00, 0x00, 0x01, 0x80, 0x18,
+  0xFF, 0xFF, 0xFF, 0x9E, 0x80, 0x00, 0x00, 0x03,
+  0xA8, 0x11, 0xFF, 0xFF, 0xFF, 0x9F, 0x80, 0x00,
+  0x00, 0x02, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x99,
+  0x80, 0x00, 0x00, 0x00, 0x00, 0x09, 0xFF, 0xFF,
+  0xFF, 0x00, 0x80, 0x00, 0x00, 0x01, 0xC0, 0x01,
+  0xFF, 0xFF, 0xFE, 0x20, 0x60, 0x00, 0x00, 0x00,
+  0xFF, 0xC3, 0xFF, 0xFF, 0xF8, 0x00, 0x30, 0x00,
+  0x00, 0x00, 0xFF, 0x0F, 0xFF, 0xFF, 0xC0, 0x40,
+  0x38, 0x00, 0x00, 0x00, 0xFE, 0x47, 0xFF, 0xFF,
+  0x81, 0x00, 0x1C, 0x00, 0x00, 0x00, 0xFC, 0x23,
+  0xFF, 0xFF, 0x90, 0x00, 0x1E, 0x00, 0x00, 0x00,
+  0x78, 0x11, 0xFF, 0xFF, 0x80, 0x00, 0x0F, 0x80,
+  0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00,
+  0x07, 0xC0, 0x00, 0x00, 0x00, 0x08, 0xFF, 0xFF,
+  0xC0, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x04,
+  0x7F, 0xFF, 0x80, 0x00, 0x03, 0xC0, 0x00, 0x10,
+  0x00, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x01, 0x80,
+  0x00, 0x30, 0x00, 0x00, 0x0F, 0xFF, 0x80, 0x00,
+  0x00, 0x00, 0x00, 0x70, 0x00, 0x01, 0x4F, 0xFF,
+  0x80, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00,
+  0x0F, 0xFF, 0xC0, 0x00, 0x00, 0x80, 0x03, 0xF0,
+  0x00, 0x00, 0x8F, 0xFF, 0x80, 0x00, 0x00, 0x40,
+  0x0F, 0xF0, 0x00, 0x04, 0x1F, 0xFF, 0x80, 0x00,
+  0x00, 0x7F, 0xFF, 0xF0, 0x00, 0x10, 0x1F, 0xFF,
+  0xC0, 0x00, 0x00, 0x7F, 0xFF, 0xF0, 0x00, 0x40,
+  0xFF, 0xFF, 0x98, 0x00, 0x00, 0xFF, 0xFF, 0xF0,
+  0x00, 0x83, 0xFF, 0xFF, 0x81, 0xE0, 0x01, 0xFF,
+  0xFF, 0xF8, 0x02, 0x07, 0xFF, 0xFF, 0x80, 0x3F,
+  0x07, 0xE0, 0x00, 0x1C, 0x0C, 0x1F, 0xFF, 0xFF,
+  0xF8, 0x03, 0xFF, 0x80, 0x00, 0x1F, 0x78, 0x1F,
+  0xFF, 0xFF, 0xFF, 0x80, 0x7F, 0x00, 0x07, 0x0F,
+  0xF0, 0x7F, 0xFF, 0xFF, 0xFF, 0xFE, 0x0C, 0x07,
+  0xFF, 0x83, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+  0x00, 0x1F, 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x07, 0xFF,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+};
+
+/* Painted by Johnny Stenback <jst@uwasa.fi> */
+
+unsigned char *linux_serial_image __initdata = "\n"
+"         .u$e.\n"
+"       .$$$$$:S\n"
+"       $\"*$/\"*$$\n"
+"       $.`$ . ^F\n"
+"       4k+#+T.$F\n"
+"       4P+++\"$\"$\n"
+"       :R\"+  t$$B\n"
+"    ___#       $$$\n"
+"    |  |       R$$k\n"
+"   dd. | Linux  $!$\n"
+"   ddd |  Sparc $9$F\n"
+" '!!!!!$       !!#!`\n"
+"  !!!!!*     .!!!!!`\n"
+"'!!!!!!!W..e$$!!!!!!`    %s\n"
+" \"~^^~         ^~~^\n"
+"\n";
+/* $Id: linux_logo.h,v 1.1 1997/04/16 17:51:24 jj Exp $
+ * include/asm-sparc/linux_logo.h: This is a linux logo
+ *                                 to be displayed on boot.
+ *
+ * Copyright (C) 1996 Larry Ewing (lewing@isc.tamu.edu)
+ * Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ *
+ * You can put anything here, but:
+ * LINUX_LOGO_COLORS has to be less than 224
+ * image size has to be 80x80
+ * values have to start from 0x20
+ * (i.e. RGB(linux_logo_red[0],
+ *	     linux_logo_green[0],
+ *	     linux_logo_blue[0]) is color 0x20)
+ * BW image has to be 80x80 as well, with MS bit
+ * on the left
+ * Serial_console ascii image can be any size,
+ * but should contain %s to display the version
+ */
+ 
+#include <linux/init.h>
+#include <linux/version.h>
+
+#define linux_logo_banner "Linux/SPARC version " UTS_RELEASE
+
+#define LINUX_LOGO_COLORS 221
+
+unsigned char linux_logo_red[] __initdata = {
+  0xF3, 0xF6, 0xF8, 0xF7, 0xEF, 0xE7, 0xE5, 0xE3,
+  0xCA, 0xD4, 0xDD, 0xC8, 0xC7, 0xC4, 0xC2, 0xE5,
+  0xF1, 0xED, 0xEE, 0xE6, 0xC6, 0xDA, 0xDD, 0xE5,
+  0xD9, 0xC6, 0xE3, 0xD0, 0xC6, 0xBA, 0xB0, 0xB6,
+  0xBB, 0xBE, 0xB9, 0xB8, 0xB3, 0xB2, 0xB0, 0xAD,
+  0xAC, 0xA9, 0xA8, 0xA6, 0xA4, 0xA1, 0xA0, 0x9D,
+  0xA0, 0x9F, 0x9E, 0x9C, 0x9B, 0x99, 0x9A, 0x99,
+  0x98, 0x95, 0x96, 0x94, 0x93, 0x92, 0x8F, 0x8D,
+  0x8C, 0x8A, 0x87, 0x86, 0x83, 0x81, 0x0D, 0x03,
+  0x66, 0x44, 0x24, 0x08, 0xD6, 0xE6, 0xE9, 0xE6,
+  0xE7, 0xCA, 0xDC, 0xDB, 0xD5, 0xD0, 0xC9, 0xE2,
+  0xD5, 0xC6, 0xC4, 0xB3, 0xB2, 0xB9, 0xA9, 0x9A,
+  0xB2, 0x9D, 0xE8, 0xEC, 0xF5, 0xF5, 0xF4, 0xF4,
+  0xEC, 0xEE, 0xF0, 0xF5, 0xE0, 0xD6, 0xC5, 0xC2,
+  0xD9, 0xD5, 0xD8, 0xD6, 0xF6, 0xF4, 0xED, 0xEC,
+  0xEB, 0xF1, 0xF6, 0xF5, 0xF5, 0xEE, 0xEF, 0xEC,
+  0xE7, 0xE3, 0xE6, 0xD6, 0xDD, 0xC3, 0xD6, 0xD7,
+  0xCD, 0xCA, 0xC3, 0xAC, 0x95, 0x99, 0xB7, 0xA3,
+  0x8B, 0x88, 0x95, 0x8A, 0x94, 0xD2, 0xCC, 0xC4,
+  0xA8, 0x8E, 0x8F, 0xAE, 0xB8, 0xAC, 0xB6, 0xB4,
+  0xAD, 0xA5, 0xA0, 0x9B, 0x8B, 0xA3, 0x94, 0x87,
+  0x85, 0x89, 0x53, 0x80, 0x7D, 0x7C, 0x7A, 0x78,
+  0x76, 0x71, 0x73, 0x6E, 0x6B, 0x67, 0x65, 0x62,
+  0x4B, 0x5B, 0x5F, 0x53, 0x56, 0x52, 0x4F, 0x46,
+  0x42, 0x0F, 0x75, 0x78, 0x7D, 0x72, 0x5F, 0x6E,
+  0x7A, 0x75, 0x6A, 0x58, 0x48, 0x4F, 0x00, 0x2B,
+  0x37, 0x3E, 0x32, 0x33, 0x25, 0x2C, 0x3B, 0x11,
+  0x1D, 0x14, 0x06, 0x02, 0x00
+};
+
+unsigned char linux_logo_green[] __initdata = {
+  0xF3, 0xF6, 0xF8, 0xF7, 0xEF, 0xE7, 0xE5, 0xE3,
+  0xCA, 0xD4, 0xDD, 0xC8, 0xC7, 0xC4, 0xC2, 0xD3,
+  0xDA, 0xD4, 0xD7, 0xCC, 0xC1, 0xCC, 0xCB, 0xC9,
+  0xC5, 0xBC, 0xBC, 0xBB, 0xB7, 0xA5, 0xB0, 0xB6,
+  0xBB, 0xBE, 0xB9, 0xB8, 0xB3, 0xB2, 0xAD, 0xAD,
+  0xAC, 0xA9, 0xA8, 0xA6, 0xA4, 0xA1, 0xA0, 0x95,
+  0xA0, 0x9F, 0x9E, 0x9C, 0x9B, 0x99, 0x9A, 0x99,
+  0x98, 0x95, 0x96, 0x94, 0x93, 0x92, 0x8F, 0x8D,
+  0x8C, 0x8A, 0x87, 0x86, 0x83, 0x81, 0x08, 0x02,
+  0x53, 0x2E, 0x19, 0x06, 0xC6, 0xC8, 0xCF, 0xBD,
+  0xB3, 0xB6, 0xB4, 0xAB, 0xA5, 0xA3, 0x9B, 0xB6,
+  0xA7, 0x99, 0x92, 0xA4, 0x9E, 0x9D, 0x98, 0x8C,
+  0x8A, 0x86, 0xCD, 0xCC, 0xC9, 0xD7, 0xCA, 0xC4,
+  0xCA, 0xC3, 0xC7, 0xC3, 0xC8, 0xB4, 0x91, 0x8E,
+  0x8A, 0x82, 0x87, 0x85, 0xBD, 0xBF, 0xB6, 0xBC,
+  0xAE, 0xB7, 0xBC, 0xB8, 0xBF, 0xB6, 0xBC, 0xB5,
+  0xAB, 0xA6, 0xAD, 0xB2, 0xA5, 0x87, 0x9C, 0x96,
+  0x95, 0x8E, 0x87, 0x8F, 0x86, 0x86, 0x8E, 0x80,
+  0x7A, 0x70, 0x7B, 0x78, 0x78, 0x7F, 0x77, 0x6F,
+  0x70, 0x76, 0x59, 0x77, 0x68, 0x64, 0x7B, 0x7C,
+  0x75, 0x6D, 0x77, 0x69, 0x65, 0x5F, 0x5B, 0x54,
+  0x4F, 0x5B, 0x39, 0x80, 0x7D, 0x7C, 0x7A, 0x78,
+  0x76, 0x71, 0x73, 0x6E, 0x6B, 0x67, 0x65, 0x62,
+  0x4B, 0x5B, 0x5F, 0x53, 0x56, 0x52, 0x4F, 0x46,
+  0x42, 0x0B, 0x69, 0x66, 0x64, 0x57, 0x4A, 0x4E,
+  0x55, 0x4B, 0x46, 0x3B, 0x30, 0x33, 0x00, 0x2B,
+  0x37, 0x3E, 0x32, 0x33, 0x25, 0x2C, 0x29, 0x0D,
+  0x1D, 0x14, 0x06, 0x02, 0x00
+};
+
+unsigned char linux_logo_blue[] __initdata = {
+  0xF3, 0xF6, 0xF8, 0xF7, 0xEF, 0xEE, 0xE5, 0xDE,
+  0xD7, 0xD3, 0xDD, 0xC8, 0xC7, 0xC4, 0xC2, 0xB5,
+  0xB0, 0xA6, 0xAC, 0x9B, 0xB5, 0xB5, 0xAE, 0x84,
+  0x90, 0xA9, 0x81, 0x8D, 0x96, 0x86, 0xB0, 0xB6,
+  0xBB, 0xBE, 0xB9, 0xB8, 0xB3, 0xB2, 0xA7, 0xAD,
+  0xAC, 0xA9, 0xA8, 0xA6, 0xA4, 0xA1, 0xA5, 0x87,
+  0xA0, 0x9F, 0x9E, 0x9C, 0x9B, 0x9A, 0x9A, 0x99,
+  0x98, 0x95, 0x96, 0x94, 0x93, 0x92, 0x8F, 0x8D,
+  0x8C, 0x8A, 0x87, 0x86, 0x83, 0x81, 0xC8, 0xD7,
+  0x9B, 0x8E, 0x8C, 0xB2, 0x77, 0x77, 0x4E, 0x77,
+  0x69, 0x71, 0x78, 0x6B, 0x65, 0x66, 0x64, 0x59,
+  0x5C, 0x5A, 0x48, 0x72, 0x7B, 0x6B, 0x67, 0x6E,
+  0x42, 0x5B, 0x29, 0x36, 0x25, 0x10, 0x17, 0x14,
+  0x19, 0x16, 0x13, 0x0E, 0x08, 0x2E, 0x2E, 0x3D,
+  0x24, 0x24, 0x24, 0x24, 0x13, 0x12, 0x14, 0x14,
+  0x0E, 0x08, 0x0D, 0x0F, 0x08, 0x0D, 0x0E, 0x08,
+  0x08, 0x0C, 0x06, 0x06, 0x07, 0x16, 0x07, 0x0E,
+  0x08, 0x0A, 0x07, 0x0D, 0x2D, 0x3E, 0x09, 0x4E,
+  0x68, 0x52, 0x56, 0x58, 0x4B, 0x22, 0x20, 0x20,
+  0x27, 0x39, 0x28, 0x19, 0x1E, 0x1E, 0x08, 0x06,
+  0x07, 0x09, 0x08, 0x08, 0x05, 0x1D, 0x1F, 0x17,
+  0x18, 0x06, 0x79, 0x80, 0x7D, 0x7C, 0x7A, 0x78,
+  0x76, 0x71, 0x73, 0x6E, 0x6B, 0x68, 0x65, 0x62,
+  0x4B, 0x5B, 0x5F, 0x55, 0x56, 0x52, 0x4F, 0x46,
+  0x42, 0x5A, 0x14, 0x23, 0x3D, 0x2B, 0x21, 0x14,
+  0x06, 0x04, 0x03, 0x07, 0x09, 0x13, 0x2A, 0x3A,
+  0x37, 0x3E, 0x32, 0x33, 0x25, 0x2C, 0x07, 0x09,
+  0x1D, 0x14, 0x06, 0x02, 0x00
+};
+
+unsigned char linux_logo[] __initdata = {
+  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+  0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57,
+  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58, 0x57,
+  0x58, 0x58, 0x59, 0x5C, 0x5D, 0x5F, 0x60, 0x61,
+  0x62, 0x61, 0x61, 0x62, 0x62, 0x62, 0x63, 0x63,
+  0x61, 0x61, 0x61, 0x61, 0x61, 0x60, 0x5E, 0x5E,
+  0x5E, 0x5D, 0x5D, 0x5C, 0x5D, 0x5B, 0x58, 0x58,
+  0x58, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x58,
+  0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57,
+  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+  0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57,
+  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58, 0x57,
+  0x54, 0x56, 0x57, 0x67, 0xFC, 0xFC, 0xFC, 0xFC,
+  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x67, 0x4C,
+  0x4A, 0x49, 0x4A, 0x49, 0x4A, 0x49, 0x49, 0x4A,
+  0x4A, 0x4B, 0x4B, 0x4B, 0x4C, 0x50, 0x51, 0x52,
+  0x54, 0x54, 0x56, 0x57, 0x57, 0x57, 0x57, 0x58,
+  0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57,
+  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+  0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57,
+  0x57, 0x57, 0x57, 0x57, 0x58, 0x56, 0x56, 0x53,
+  0x52, 0x53, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0xFB, 0xFB,
+  0x4B, 0x4B, 0x4B, 0x4A, 0x49, 0x4A, 0x4A, 0x49,
+  0x49, 0x49, 0x48, 0x49, 0x49, 0x4A, 0x4A, 0x4B,
+  0x4C, 0x4D, 0x52, 0x54, 0x56, 0x55, 0x57, 0x58,
+  0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57,
+  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+  0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57,
+  0x57, 0x57, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50,
+  0x50, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+  0xFC, 0xFC, 0xFC, 0xFC, 0xF8, 0xF0, 0xF4, 0xFB,
+  0xFC, 0x67, 0x53, 0x50, 0x4D, 0x4C, 0x4C, 0x4C,
+  0x4B, 0x4A, 0x4A, 0x48, 0x49, 0x48, 0x48, 0x49,
+  0x49, 0x49, 0x4B, 0x4C, 0x50, 0x52, 0x53, 0x56,
+  0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57,
+  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+  0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57,
+  0x55, 0x54, 0x53, 0x51, 0x51, 0x50, 0x4C, 0x4D,
+  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+  0xFC, 0xFC, 0xFC, 0xFC, 0xF4, 0xD2, 0xD7, 0xF5,
+  0xFC, 0xFC, 0x5D, 0x5D, 0x5C, 0x5C, 0x59, 0x58,
+  0x58, 0x56, 0x52, 0x4C, 0x4B, 0x4A, 0x4A, 0x48,
+  0x48, 0x48, 0x48, 0x48, 0x49, 0x4B, 0x4D, 0x51,
+  0x54, 0x56, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57,
+  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+  0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x55, 0x54,
+  0x53, 0x52, 0x51, 0x4D, 0x4D, 0x4D, 0x50, 0x50,
+  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+  0xFC, 0xFC, 0xFC, 0xFC, 0xF4, 0x64, 0xD9, 0xF5,
+  0xF9, 0xFC, 0xFC, 0x64, 0x63, 0x62, 0x61, 0x61,
+  0x61, 0x60, 0x5E, 0x5B, 0x5A, 0x54, 0x52, 0x4C,
+  0x4B, 0x49, 0x49, 0x47, 0x47, 0x48, 0x49, 0x4B,
+  0x4C, 0x51, 0x53, 0x56, 0x57, 0x58, 0x57, 0x57,
+  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+  0x57, 0x57, 0x58, 0x57, 0x57, 0x55, 0x53, 0x53,
+  0x51, 0x50, 0x50, 0x50, 0x50, 0x50, 0x53, 0xFC,
+  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+  0xFC, 0xFC, 0xFC, 0xFC, 0xF4, 0xF5, 0xF9, 0xFC,
+  0xFC, 0xFC, 0xFC, 0x64, 0x64, 0x64, 0x64, 0x64,
+  0x64, 0x64, 0x64, 0x63, 0x61, 0x61, 0x5E, 0x59,
+  0x55, 0x52, 0x4C, 0x4A, 0x49, 0x47, 0x48, 0x48,
+  0x49, 0x4B, 0x4D, 0x51, 0x54, 0x57, 0x57, 0x57,
+  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+  0x57, 0x57, 0x58, 0x55, 0x54, 0x54, 0x52, 0x51,
+  0x51, 0x51, 0x51, 0x51, 0x53, 0x54, 0x59, 0xFC,
+  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+  0xFC, 0xFC, 0xFC, 0xFC, 0xF7, 0xFC, 0xFC, 0xFC,
+  0xFC, 0xFC, 0xFC, 0xFC, 0x60, 0x60, 0x60, 0x61,
+  0x62, 0x63, 0x64, 0x64, 0x65, 0x65, 0x64, 0x63,
+  0x61, 0x5E, 0x59, 0x56, 0x4D, 0x4B, 0x48, 0x48,
+  0x48, 0x48, 0x49, 0x4B, 0x50, 0x53, 0x56, 0x56,
+  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+  0x57, 0x57, 0x56, 0x54, 0x53, 0x52, 0x51, 0x51,
+  0x51, 0x52, 0x53, 0x55, 0x59, 0x5D, 0x5E, 0xFC,
+  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+  0xFC, 0xFC, 0xFC, 0xFB, 0xFB, 0xFB, 0xFC, 0xFC,
+  0xFC, 0xFC, 0xFC, 0xFC, 0x4C, 0x4E, 0x51, 0x52,
+  0x57, 0x5A, 0x5E, 0x60, 0x61, 0x63, 0x65, 0xCB,
+  0x64, 0x64, 0x63, 0x60, 0x5C, 0x57, 0x50, 0x4B,
+  0x48, 0x47, 0x47, 0x47, 0x4A, 0x4C, 0x52, 0x53,
+  0x54, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
+  0x55, 0x54, 0x53, 0x53, 0x51, 0x52, 0x52, 0x53,
+  0x53, 0x57, 0x5A, 0x5D, 0x5E, 0x5E, 0x60, 0xFC,
+  0xFC, 0xFC, 0xFB, 0xF9, 0xFC, 0xFC, 0xFC, 0xFC,
+  0xFC, 0xFC, 0xFC, 0xFA, 0xF9, 0xF5, 0xFB, 0xFC,
+  0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0x45, 0x3F, 0x3F,
+  0x45, 0x48, 0x4B, 0x4D, 0x54, 0x5A, 0x5E, 0x61,
+  0x63, 0xCB, 0xCB, 0x65, 0x64, 0x62, 0x5E, 0x57,
+  0x50, 0x4B, 0x48, 0x47, 0x47, 0x48, 0x4B, 0x4D,
+  0x51, 0x56, 0x56, 0x57, 0x57, 0x57, 0x57, 0x57,
+  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x55,
+  0x54, 0x54, 0x53, 0x53, 0x52, 0x53, 0x54, 0x57,
+  0x59, 0x5C, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0xFC,
+  0xFC, 0xFA, 0xFC, 0xFA, 0xE0, 0xFC, 0xFC, 0xFC,
+  0xFB, 0xFB, 0xFB, 0xDF, 0xD8, 0xF9, 0xE0, 0xFC,
+  0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0x4C, 0x4A, 0x48,
+  0x48, 0x3E, 0x44, 0x43, 0x3F, 0x47, 0x4B, 0x52,
+  0x5A, 0x5E, 0x62, 0x64, 0xCB, 0xCB, 0x64, 0x61,
+  0x5E, 0x57, 0x4D, 0x49, 0x47, 0x47, 0x48, 0x4A,
+  0x4C, 0x52, 0x54, 0x56, 0x57, 0x57, 0x57, 0x57,
+  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x55,
+  0x54, 0x53, 0x53, 0x54, 0x54, 0x55, 0x58, 0x5B,
+  0x5C, 0x5D, 0x5E, 0x5D, 0x5D, 0x5B, 0x58, 0xFC,
+  0xFC, 0xD8, 0x4C, 0x60, 0xFC, 0xF5, 0xFC, 0xFC,
+  0xFC, 0xF7, 0x5F, 0x48, 0x48, 0x2C, 0xF8, 0xF9,
+  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x4B, 0x4A, 0x49,
+  0x49, 0x49, 0x49, 0x47, 0x3E, 0x44, 0x42, 0x3F,
+  0x3E, 0x4B, 0x54, 0x5C, 0x61, 0x64, 0xCB, 0xCB,
+  0x64, 0x61, 0x5D, 0x53, 0x4B, 0x49, 0x47, 0x47,
+  0x49, 0x4B, 0x50, 0x53, 0x56, 0x57, 0x57, 0x57,
+  0x57, 0x57, 0x57, 0x57, 0x57, 0x55, 0x55, 0x54,
+  0x53, 0x53, 0x54, 0x56, 0x58, 0x5A, 0x5B, 0x5D,
+  0x5D, 0x5D, 0x5C, 0x5A, 0x54, 0x52, 0x4C, 0xFC,
+  0xF7, 0x4E, 0x2D, 0x29, 0x4E, 0xFC, 0xFC, 0xFC,
+  0xFB, 0x5F, 0x26, 0x24, 0x20, 0x2E, 0x65, 0xFC,
+  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x45, 0x3F, 0x45,
+  0x3E, 0x47, 0x47, 0x47, 0x47, 0x47, 0x3E, 0x44,
+  0x43, 0x40, 0x44, 0x49, 0x51, 0x5C, 0x62, 0x64,
+  0xCB, 0xCB, 0x63, 0x60, 0x58, 0x50, 0x49, 0x48,
+  0x48, 0x48, 0x4A, 0x4D, 0x53, 0x54, 0x57, 0x57,
+  0x57, 0x57, 0x57, 0x57, 0x55, 0x54, 0x54, 0x54,
+  0x54, 0x54, 0x55, 0x57, 0x59, 0x5B, 0x5C, 0x5D,
+  0x5C, 0x5A, 0x54, 0x51, 0x4C, 0x4C, 0x54, 0xFC,
+  0xF9, 0x23, 0xDB, 0x2D, 0x23, 0xFA, 0xFB, 0xFA,
+  0xF5, 0x27, 0x21, 0xD9, 0xF8, 0x20, 0x21, 0xFB,
+  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x5D, 0x58, 0x55,
+  0x50, 0x48, 0x45, 0x43, 0x44, 0x44, 0x45, 0x45,
+  0x3E, 0x3F, 0x43, 0x41, 0x3F, 0x48, 0x52, 0x5D,
+  0x63, 0x65, 0xCB, 0x65, 0x61, 0x5D, 0x52, 0x4B,
+  0x48, 0x47, 0x47, 0x49, 0x4C, 0x51, 0x54, 0x57,
+  0x57, 0x57, 0x57, 0x57, 0x55, 0x54, 0x54, 0x54,
+  0x54, 0x58, 0x5A, 0x59, 0x5B, 0x5B, 0x5B, 0x5A,
+  0x55, 0x52, 0x4D, 0x4D, 0x55, 0x5B, 0x5D, 0xFC,
+  0xF1, 0xF9, 0xFC, 0xD4, 0x21, 0xCC, 0xF7, 0xF8,
+  0xF2, 0x21, 0xD9, 0xFC, 0xF2, 0xFB, 0x21, 0x45,
+  0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0xD1, 0xD0, 0xCD,
+  0xCC, 0x63, 0x5E, 0x58, 0x50, 0x47, 0x43, 0x3F,
+  0x3F, 0x3F, 0x3F, 0x3F, 0x40, 0x41, 0x3F, 0x4A,
+  0x56, 0x5E, 0x64, 0xCB, 0x65, 0x63, 0x5E, 0x56,
+  0x4C, 0x48, 0x47, 0x47, 0x49, 0x4C, 0x51, 0x54,
+  0x58, 0x57, 0x57, 0x57, 0x57, 0x55, 0x54, 0x54,
+  0x57, 0x5A, 0x5A, 0x5C, 0x5B, 0x5A, 0x58, 0x54,
+  0x51, 0x4C, 0x55, 0x5D, 0x5D, 0x5B, 0x54, 0xFC,
+  0xF0, 0xF9, 0xFC, 0x65, 0x45, 0xCD, 0xFB, 0xFB,
+  0xF8, 0x26, 0xFB, 0xFC, 0xFC, 0xFC, 0x21, 0x27,
+  0xFB, 0xFC, 0xFC, 0xFC, 0xFB, 0xD7, 0x35, 0x34,
+  0x2F, 0x35, 0x36, 0x2F, 0x2F, 0x36, 0x2F, 0x2F,
+  0x36, 0x36, 0x35, 0x35, 0x43, 0x42, 0x41, 0x2E,
+  0x45, 0x4C, 0x5B, 0x62, 0x65, 0xCC, 0x64, 0x60,
+  0x58, 0x4D, 0x49, 0x47, 0x47, 0x49, 0x4C, 0x51,
+  0x58, 0x57, 0x57, 0x57, 0x57, 0x57, 0x55, 0x57,
+  0x58, 0x5A, 0x5A, 0x5B, 0x5A, 0x55, 0x54, 0x51,
+  0x53, 0x5C, 0x5D, 0x5D, 0x54, 0x4B, 0x4D, 0xFC,
+  0xFC, 0x44, 0xFC, 0xFB, 0x7B, 0xAB, 0xA8, 0xAE,
+  0xAB, 0x7F, 0xFC, 0xFC, 0xFB, 0xFB, 0x22, 0x2A,
+  0xFC, 0xFC, 0xFC, 0xFC, 0x36, 0x2F, 0x30, 0x30,
+  0x32, 0x30, 0x32, 0x30, 0x30, 0x30, 0x30, 0x30,
+  0x30, 0x30, 0x30, 0x30, 0x2F, 0x2F, 0x40, 0x41,
+  0x2E, 0x40, 0x48, 0x56, 0x5F, 0x64, 0xCC, 0x65,
+  0x61, 0x59, 0x50, 0x49, 0x47, 0x47, 0x49, 0x4C,
+  0x5A, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58,
+  0x5A, 0x5A, 0x5A, 0x58, 0x55, 0x52, 0x51, 0x5A,
+  0x5D, 0x5D, 0x57, 0x4C, 0x51, 0x54, 0x5D, 0xFC,
+  0xFC, 0x2A, 0xFC, 0xC9, 0xAA, 0x8B, 0x8A, 0x8C,
+  0xAB, 0x8C, 0x8C, 0xFB, 0xFB, 0x23, 0x20, 0xF1,
+  0xFC, 0xFC, 0xFC, 0x3B, 0x33, 0x33, 0x32, 0x32,
+  0x31, 0x32, 0x30, 0x32, 0x32, 0x32, 0x32, 0x30,
+  0x31, 0x31, 0x31, 0x32, 0x33, 0x33, 0x3C, 0x41,
+  0x41, 0x2E, 0x2D, 0x45, 0x4D, 0x5D, 0x63, 0xCC,
+  0x65, 0x62, 0x5D, 0x51, 0x49, 0x47, 0x47, 0x4A,
+  0x59, 0x57, 0x57, 0x57, 0x57, 0x58, 0x58, 0x58,
+  0x5A, 0x5A, 0x58, 0x55, 0x53, 0x53, 0x5C, 0x5E,
+  0x59, 0x51, 0x4E, 0x54, 0x59, 0x5E, 0x62, 0xFC,
+  0xFC, 0xDB, 0xAA, 0xA1, 0x95, 0x9C, 0x8C, 0x88,
+  0x82, 0x83, 0x83, 0x8C, 0x88, 0xAE, 0xB9, 0xFB,
+  0xFC, 0xFC, 0xFC, 0x3C, 0x3B, 0x72, 0x38, 0x33,
+  0x33, 0x33, 0x31, 0x33, 0x31, 0x31, 0x31, 0x31,
+  0x33, 0x33, 0x38, 0x33, 0x72, 0x3B, 0x44, 0x2E,
+  0x41, 0x2E, 0x2E, 0x2D, 0x43, 0x4B, 0x5B, 0x63,
+  0xCB, 0xCC, 0x63, 0x5D, 0x51, 0x49, 0x47, 0x49,
+  0x5C, 0x58, 0x57, 0x57, 0x57, 0x57, 0x58, 0x58,
+  0x58, 0x58, 0x57, 0x53, 0x58, 0x5D, 0x5E, 0x55,
+  0x51, 0x53, 0x58, 0x5E, 0x60, 0x63, 0x64, 0xFC,
+  0xFC, 0xC0, 0xA6, 0x9D, 0x8B, 0x9C, 0x8C, 0x8C,
+  0x6E, 0x83, 0x88, 0x8C, 0x8C, 0x8C, 0x83, 0xE8,
+  0xFB, 0xFC, 0xFC, 0xFC, 0x33, 0x70, 0x70, 0x6F,
+  0x6F, 0x6F, 0x6F, 0x3A, 0x6F, 0x6D, 0x6F, 0x6F,
+  0x70, 0x6F, 0x6F, 0x70, 0x6F, 0x32, 0x5A, 0x48,
+  0x41, 0x2D, 0x2D, 0x2D, 0x2C, 0x41, 0x49, 0x5A,
+  0x62, 0xCB, 0xCB, 0x63, 0x5D, 0x50, 0x49, 0x4A,
+  0x5C, 0x58, 0x58, 0x57, 0x55, 0x57, 0x57, 0x57,
+  0x57, 0x55, 0x56, 0x59, 0x5E, 0x5C, 0x52, 0x53,
+  0x55, 0x5B, 0x5E, 0x61, 0x63, 0x64, 0x63, 0xFC,
+  0xE8, 0xBF, 0xA4, 0x99, 0x9C, 0x8C, 0x88, 0x88,
+  0x6E, 0x88, 0x8C, 0x8C, 0x8C, 0xC2, 0xA6, 0xC4,
+  0xFC, 0xFC, 0xFC, 0xFC, 0x36, 0x3A, 0x6F, 0x70,
+  0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
+  0x70, 0x70, 0x70, 0x70, 0x37, 0x32, 0xCD, 0x5E,
+  0x4C, 0x43, 0x2C, 0x2D, 0x2D, 0x2C, 0x2E, 0x47,
+  0x57, 0x61, 0x65, 0xCC, 0x63, 0x5C, 0x50, 0x4D,
+  0x5C, 0x5A, 0x57, 0x55, 0x55, 0x55, 0x58, 0x58,
+  0x55, 0x54, 0x5B, 0x5E, 0x5D, 0x53, 0x53, 0x55,
+  0x5D, 0x5E, 0x61, 0x61, 0x61, 0x61, 0x5E, 0xFC,
+  0xEA, 0xBE, 0xA4, 0x9B, 0x8B, 0x85, 0x8C, 0x6E,
+  0x8C, 0x8C, 0x8C, 0xA3, 0xAA, 0xA4, 0xA4, 0xE9,
+  0xFB, 0xFC, 0xFC, 0xFC, 0x36, 0x6D, 0x70, 0x73,
+  0x70, 0x70, 0x70, 0x73, 0x73, 0x73, 0x73, 0x70,
+  0x70, 0x70, 0x73, 0x70, 0x37, 0x38, 0xD1, 0xCF,
+  0x61, 0x4D, 0x44, 0x2C, 0x2D, 0x2E, 0x2C, 0x2E,
+  0x3E, 0x56, 0x61, 0xCB, 0xCC, 0x62, 0x5B, 0x57,
+  0x59, 0x58, 0x55, 0x54, 0x54, 0x55, 0x58, 0x58,
+  0x58, 0x5B, 0x5E, 0x5B, 0x53, 0x55, 0x55, 0x5C,
+  0x5E, 0x61, 0x61, 0x60, 0x5D, 0x5A, 0x4E, 0xFC,
+  0xFC, 0xEA, 0xAA, 0x9C, 0x8A, 0x85, 0x82, 0x8C,
+  0x8C, 0xA8, 0xEB, 0xA8, 0xA4, 0xA4, 0xAA, 0xFC,
+  0xFC, 0xFC, 0x64, 0xFB, 0x39, 0x31, 0x72, 0x78,
+  0x73, 0x78, 0x73, 0x74, 0x74, 0x74, 0x74, 0x73,
+  0x78, 0x70, 0x73, 0x73, 0x33, 0xCC, 0xD2, 0xD1,
+  0xCE, 0x62, 0x53, 0x3F, 0x2D, 0x2D, 0x41, 0x2C,
+  0x2E, 0x3E, 0x56, 0x62, 0xCB, 0xCB, 0x61, 0x5D,
+  0x54, 0x54, 0x54, 0x54, 0x56, 0x58, 0x58, 0x58,
+  0x5C, 0x5E, 0x5A, 0x55, 0x58, 0x58, 0x5B, 0x5E,
+  0x61, 0x5E, 0x5D, 0x5A, 0x52, 0x55, 0xCD, 0xFC,
+  0xFC, 0x34, 0xC9, 0xE8, 0xA8, 0xAE, 0xC2, 0xE8,
+  0xC3, 0xA6, 0xA7, 0xA6, 0xAA, 0x78, 0x2E, 0x42,
+  0xFC, 0xFC, 0xD2, 0x64, 0xF8, 0x31, 0x72, 0x73,
+  0x73, 0x73, 0x73, 0x74, 0x75, 0x75, 0x74, 0x73,
+  0x73, 0x73, 0x73, 0x72, 0x33, 0x5C, 0x64, 0xD2,
+  0xD1, 0xCF, 0x63, 0x54, 0x3F, 0x2C, 0x41, 0x41,
+  0x2C, 0x2E, 0x47, 0x58, 0x63, 0xCB, 0xCB, 0x62,
+  0x52, 0x53, 0x53, 0x56, 0x58, 0x58, 0x5A, 0x5B,
+  0x5E, 0x5A, 0x57, 0x58, 0x58, 0x58, 0x60, 0x60,
+  0x5D, 0x5A, 0x55, 0x4E, 0x64, 0xD2, 0xD1, 0xFC,
+  0xFC, 0x41, 0x3E, 0xC1, 0xC0, 0xA3, 0xA6, 0xA7,
+  0xA7, 0xA9, 0xAA, 0xB8, 0x2E, 0x3F, 0x2C, 0x41,
+  0xFC, 0xFC, 0xF7, 0xCE, 0xCD, 0x36, 0x72, 0x73,
+  0x74, 0x75, 0x78, 0x75, 0x75, 0x75, 0x74, 0x74,
+  0x74, 0x74, 0x78, 0x72, 0x6D, 0x49, 0x59, 0xCB,
+  0xD1, 0xD1, 0xD2, 0xCB, 0x56, 0x3F, 0x2C, 0x41,
+  0x40, 0x2D, 0x2E, 0x49, 0x5B, 0x64, 0xCC, 0x64,
+  0x51, 0x53, 0x53, 0x55, 0x58, 0x59, 0x5B, 0x5E,
+  0x59, 0x58, 0x58, 0x58, 0x55, 0x60, 0x60, 0x5C,
+  0x5A, 0x53, 0x5B, 0xD0, 0xD3, 0xD3, 0xD3, 0xFB,
+  0xFC, 0x40, 0x41, 0x45, 0xC4, 0xC0, 0xBE, 0xBE,
+  0xC1, 0xC0, 0x3C, 0x47, 0x2E, 0x21, 0x22, 0x20,
+  0x65, 0xFC, 0xFC, 0xFC, 0xFC, 0x6D, 0x72, 0x75,
+  0x78, 0x76, 0x75, 0x79, 0x76, 0x76, 0x76, 0x76,
+  0x75, 0x75, 0x75, 0x72, 0x6D, 0x2E, 0x48, 0x5D,
+  0xCE, 0xD1, 0xD4, 0xD3, 0xCB, 0x56, 0x43, 0x2C,
+  0x42, 0x43, 0x2E, 0x2E, 0x4A, 0x5D, 0x64, 0x64,
+  0x50, 0x52, 0x56, 0x58, 0x5C, 0x5D, 0x5E, 0x5D,
+  0x5A, 0x58, 0x58, 0x55, 0x61, 0x60, 0x58, 0x58,
+  0x4E, 0x61, 0xD1, 0xD4, 0xD4, 0xD1, 0xEE, 0xFC,
+  0xFC, 0x2B, 0x29, 0x2E, 0x3F, 0xB0, 0xAD, 0x81,
+  0x46, 0x2D, 0x46, 0x2C, 0x24, 0x22, 0x22, 0x23,
+  0x25, 0xFC, 0xFC, 0xFC, 0xFC, 0x6E, 0x73, 0x76,
+  0x76, 0x79, 0x79, 0x79, 0x76, 0x76, 0x79, 0x76,
+  0x79, 0x79, 0x79, 0x74, 0x3F, 0x41, 0x2C, 0x48,
+  0x5F, 0xCF, 0xD5, 0xD7, 0xD6, 0xCD, 0x57, 0x40,
+  0x2E, 0x3F, 0x44, 0x2E, 0x41, 0x4C, 0x60, 0x61,
+  0x51, 0x53, 0x58, 0x5C, 0x5D, 0x5E, 0x5D, 0x5C,
+  0x58, 0x57, 0x54, 0x5F, 0x5E, 0x55, 0x55, 0x52,
+  0x64, 0xD4, 0xD5, 0xD4, 0xD1, 0x5D, 0xFA, 0xFB,
+  0xF4, 0x21, 0x24, 0x41, 0x40, 0x44, 0x2E, 0x2E,
+  0x42, 0x41, 0x2A, 0x24, 0x22, 0x22, 0x22, 0x22,
+  0x23, 0xD9, 0xFC, 0xFC, 0xFC, 0xFC, 0xE5, 0xB8,
+  0x8F, 0x8F, 0x7A, 0x8F, 0x7A, 0x8F, 0x7A, 0x8F,
+  0x8F, 0x8F, 0xB8, 0xE5, 0x3F, 0x3E, 0x43, 0x2C,
+  0x48, 0x61, 0xD1, 0xD7, 0xD9, 0xD7, 0xD0, 0x57,
+  0x41, 0x2E, 0x3E, 0x44, 0x2D, 0x40, 0x52, 0x5D,
+  0x53, 0x55, 0x59, 0x5D, 0x5E, 0x5E, 0x5D, 0x5A,
+  0x57, 0x53, 0x5E, 0x5E, 0x54, 0x53, 0x54, 0x65,
+  0xD5, 0xD6, 0xD4, 0xCE, 0x53, 0xFB, 0xF9, 0xFC,
+  0x24, 0x22, 0x23, 0x23, 0x41, 0x42, 0x2E, 0x40,
+  0x2B, 0x21, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+  0x23, 0x23, 0xFC, 0xFC, 0xFC, 0xFC, 0xE7, 0xBD,
+  0xB5, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93,
+  0x93, 0xB5, 0xC6, 0xEB, 0x2D, 0x47, 0x4A, 0x47,
+  0x2C, 0x3E, 0x61, 0xD4, 0xDC, 0xDC, 0xDA, 0xCF,
+  0x54, 0x41, 0x41, 0x3E, 0x45, 0x2C, 0x3F, 0x4A,
+  0x58, 0x5A, 0x5C, 0x5F, 0x60, 0x5E, 0x5D, 0x57,
+  0x51, 0x5D, 0x5D, 0x51, 0x53, 0x53, 0xCB, 0xD5,
+  0xD6, 0xD5, 0x63, 0x55, 0xFC, 0xFC, 0xFC, 0x2C,
+  0x23, 0x22, 0x23, 0x22, 0x20, 0x2D, 0x2C, 0x26,
+  0x21, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+  0x22, 0x21, 0xF0, 0xFC, 0xFC, 0xFC, 0xE2, 0xC6,
+  0xB5, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93,
+  0x93, 0x93, 0xC7, 0xE3, 0x3E, 0x2E, 0x49, 0x52,
+  0x4C, 0x41, 0x44, 0x62, 0xD6, 0xDE, 0xDE, 0xD9,
+  0xD0, 0x51, 0x2E, 0x40, 0x47, 0x44, 0x2C, 0x42,
+  0x5D, 0x5D, 0x5F, 0x60, 0x60, 0x5D, 0x57, 0x51,
+  0x58, 0x5D, 0x4E, 0x52, 0x55, 0x64, 0xD5, 0xD6,
+  0xD4, 0x61, 0x59, 0x6B, 0xFC, 0xFC, 0xFC, 0x21,
+  0x23, 0x22, 0x23, 0x22, 0x23, 0x21, 0x23, 0x22,
+  0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+  0x22, 0x21, 0x24, 0xFC, 0xFC, 0xFC, 0xE2, 0xC7,
+  0xB5, 0x90, 0x93, 0x93, 0x93, 0x90, 0x93, 0x93,
+  0x90, 0xB5, 0xC8, 0xE4, 0x5F, 0x45, 0x2E, 0x4D,
+  0x57, 0x57, 0x44, 0x43, 0x63, 0xDA, 0xDF, 0xDF,
+  0xD9, 0xCE, 0x4C, 0x2C, 0x3F, 0x3E, 0x40, 0x40,
+  0x60, 0x5E, 0x61, 0x61, 0x5E, 0x5B, 0x53, 0x52,
+  0x5C, 0x52, 0x52, 0x55, 0x61, 0xD4, 0xD5, 0xD1,
+  0x5E, 0x5B, 0x5C, 0xFB, 0xFC, 0xFC, 0x2A, 0x21,
+  0x23, 0x22, 0x23, 0x22, 0x22, 0x22, 0x23, 0x22,
+  0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+  0x22, 0x22, 0x22, 0xFB, 0xFC, 0xFC, 0xB3, 0xC8,
+  0xB5, 0x90, 0x92, 0xB5, 0x93, 0x93, 0xB5, 0x93,
+  0x92, 0xB5, 0xC8, 0xB9, 0xD0, 0x5E, 0x44, 0x40,
+  0x52, 0x58, 0x57, 0x48, 0x40, 0x63, 0xD9, 0xE0,
+  0xE0, 0xD9, 0xCB, 0x49, 0x2D, 0x3F, 0x45, 0x3F,
+  0x63, 0x61, 0x62, 0x60, 0x5E, 0x55, 0x4D, 0x59,
+  0x53, 0x4E, 0x54, 0x5D, 0xD2, 0xD4, 0xD2, 0x5E,
+  0x5C, 0x5D, 0xFC, 0xFC, 0xFC, 0xF8, 0x29, 0x23,
+  0x23, 0x23, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+  0x23, 0x22, 0x22, 0x23, 0x23, 0x23, 0x22, 0x22,
+  0x22, 0x22, 0x22, 0xF0, 0xFC, 0xFC, 0xB3, 0xC7,
+  0xB5, 0x93, 0xB5, 0x93, 0x93, 0x91, 0x93, 0x93,
+  0x91, 0xB5, 0xC7, 0xAD, 0xD6, 0xD2, 0x5E, 0x3F,
+  0x3F, 0x57, 0x57, 0x58, 0x4A, 0x41, 0x64, 0xDC,
+  0xF1, 0xDF, 0xDA, 0x61, 0x45, 0x2E, 0x43, 0x47,
+  0xCB, 0x63, 0x62, 0x5F, 0x58, 0x51, 0x53, 0x54,
+  0x4C, 0x52, 0x5C, 0xCD, 0xD3, 0xD2, 0x60, 0x5D,
+  0x5D, 0xFB, 0xFC, 0xFC, 0xFC, 0xDB, 0x49, 0x24,
+  0x21, 0x23, 0x23, 0x22, 0x26, 0x26, 0x2A, 0x24,
+  0x22, 0x23, 0x22, 0x21, 0x24, 0x26, 0x26, 0x2A,
+  0x29, 0x2B, 0x24, 0x25, 0xFC, 0xFC, 0xB3, 0xC5,
+  0x91, 0x91, 0x92, 0x91, 0x92, 0x92, 0x93, 0x93,
+  0x91, 0x93, 0xC6, 0xAD, 0xDC, 0xD9, 0xD4, 0x60,
+  0x43, 0x45, 0x58, 0x58, 0x57, 0x4B, 0x43, 0xCC,
+  0xDD, 0xF1, 0xD8, 0xD5, 0x5D, 0x43, 0x41, 0x47,
+  0xCD, 0x63, 0x62, 0x5D, 0x54, 0x4C, 0x55, 0x4B,
+  0x51, 0x58, 0x62, 0xD0, 0xD0, 0x62, 0x5D, 0x5D,
+  0x67, 0xFC, 0xFC, 0xFC, 0xFC, 0x58, 0x4E, 0x28,
+  0x2A, 0x20, 0x23, 0x22, 0x23, 0x2A, 0x23, 0x22,
+  0x22, 0x22, 0x23, 0x23, 0x25, 0x2A, 0x2E, 0x2D,
+  0x2E, 0x2E, 0x2E, 0x23, 0xFA, 0xFC, 0xB2, 0xBD,
+  0xB5, 0x90, 0x91, 0x93, 0x92, 0x90, 0x91, 0x93,
+  0x92, 0x91, 0xBD, 0xAD, 0xDE, 0xE0, 0xD8, 0xD7,
+  0x61, 0x40, 0x48, 0x58, 0x58, 0x58, 0x48, 0x44,
+  0xCF, 0xDE, 0xE0, 0xDD, 0xD0, 0x52, 0x41, 0x45,
+  0xCD, 0x63, 0x61, 0x58, 0x4D, 0x51, 0x4C, 0x4B,
+  0x54, 0x5D, 0xCC, 0xCE, 0x63, 0x61, 0x5D, 0x5D,
+  0xFB, 0xFC, 0xFC, 0xFC, 0xFC, 0x4B, 0x27, 0x21,
+  0x22, 0x22, 0x23, 0x22, 0x22, 0x24, 0x23, 0x22,
+  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x20,
+  0x27, 0x2B, 0x41, 0x2B, 0x23, 0xFC, 0xB2, 0xB6,
+  0x93, 0x90, 0x92, 0xB5, 0x92, 0x90, 0xB5, 0x90,
+  0x92, 0x93, 0xBC, 0xAD, 0xDC, 0xF1, 0xF3, 0xF0,
+  0xD9, 0x61, 0x41, 0x4A, 0x58, 0x57, 0x57, 0x44,
+  0x49, 0xD2, 0xDD, 0xD8, 0xDA, 0x63, 0x4A, 0x45,
+  0xCC, 0x63, 0x5E, 0x52, 0x4B, 0x4C, 0x49, 0x51,
+  0x5C, 0x61, 0xCD, 0x65, 0x63, 0x5E, 0x4E, 0xCF,
+  0xFB, 0xFB, 0xF0, 0xFC, 0xD2, 0x2A, 0x22, 0x23,
+  0x22, 0x22, 0x23, 0x22, 0x22, 0x21, 0x22, 0x22,
+  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
+  0x23, 0x22, 0x26, 0x41, 0x27, 0xF9, 0x81, 0xB7,
+  0xB5, 0x91, 0x92, 0xB5, 0x91, 0xB5, 0x93, 0xB5,
+  0x93, 0xB6, 0xB7, 0xB9, 0xCB, 0xD8, 0xF3, 0xF2,
+  0xF2, 0xDB, 0x61, 0x2D, 0x51, 0x58, 0x57, 0x58,
+  0x41, 0x51, 0xD4, 0xDB, 0xDC, 0xD1, 0x5B, 0x4C,
+  0xCB, 0x62, 0x59, 0x4C, 0x4A, 0x49, 0x4B, 0x55,
+  0x60, 0x64, 0xCC, 0x64, 0x5E, 0x55, 0x60, 0xE1,
+  0xFB, 0xF8, 0xFC, 0xFC, 0x21, 0x22, 0x22, 0x23,
+  0x22, 0x22, 0x23, 0x22, 0x22, 0x21, 0x22, 0x22,
+  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
+  0x23, 0x22, 0x21, 0x24, 0x2D, 0x21, 0xB4, 0xBB,
+  0xB6, 0xB5, 0xB6, 0xB7, 0xB7, 0xB7, 0xB7, 0xB6,
+  0xB6, 0xB6, 0xBB, 0xB9, 0x45, 0xCB, 0xDF, 0xF3,
+  0xF3, 0xF3, 0xDB, 0x5E, 0x2C, 0x51, 0x58, 0x58,
+  0x52, 0x2D, 0x5C, 0xD4, 0xD9, 0xD5, 0x63, 0x58,
+  0x64, 0x60, 0x53, 0x49, 0x4A, 0x49, 0x52, 0x5C,
+  0x63, 0xCD, 0xCD, 0x63, 0x5C, 0x4E, 0x65, 0xFC,
+  0xFC, 0xF5, 0xFC, 0xD2, 0x23, 0x22, 0x22, 0x23,
+  0x22, 0x22, 0x23, 0x22, 0x22, 0x21, 0x22, 0x22,
+  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
+  0x23, 0x22, 0x21, 0x22, 0x25, 0x29, 0xB3, 0xC7,
+  0xB5, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6,
+  0xB6, 0xB5, 0xC7, 0xAD, 0x57, 0x3F, 0xCB, 0xF0,
+  0xF3, 0xF3, 0xF2, 0xD9, 0x58, 0x41, 0x4C, 0x58,
+  0x57, 0x47, 0x42, 0x62, 0xD4, 0xD4, 0xCC, 0x60,
+  0x63, 0x5D, 0x50, 0x47, 0x48, 0x4B, 0x58, 0x60,
+  0xCC, 0xCE, 0xCD, 0x60, 0x53, 0x5C, 0x62, 0xFB,
+  0xF9, 0xFC, 0xFC, 0x21, 0x23, 0x22, 0x22, 0x23,
+  0x22, 0x22, 0x23, 0x23, 0x23, 0x21, 0x22, 0x22,
+  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
+  0x23, 0x22, 0x23, 0x23, 0x22, 0x23, 0x81, 0xC7,
+  0xB7, 0xB7, 0xBC, 0xB7, 0xBC, 0xBC, 0xBC, 0xB7,
+  0xB7, 0xB7, 0xC8, 0x80, 0x58, 0x57, 0x40, 0xCE,
+  0xF3, 0xF2, 0xF2, 0xF0, 0xD5, 0x4C, 0x3F, 0x4B,
+  0x52, 0x50, 0x2D, 0x4B, 0x64, 0xD2, 0xCC, 0x61,
+  0x60, 0x58, 0x4A, 0x47, 0x47, 0x4C, 0x59, 0x64,
+  0xD0, 0xD0, 0x64, 0x59, 0x49, 0x5D, 0xFB, 0xFC,
+  0xD9, 0xFC, 0xD6, 0x23, 0x22, 0x22, 0x22, 0x23,
+  0x22, 0x22, 0x23, 0x23, 0x21, 0x21, 0x22, 0x22,
+  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
+  0x23, 0x22, 0x23, 0x23, 0x22, 0x23, 0xB4, 0xC8,
+  0xBD, 0xB7, 0xBD, 0xBC, 0xBD, 0xC5, 0xBC, 0xC5,
+  0xBC, 0xBD, 0xC7, 0xAC, 0x58, 0x57, 0x58, 0x2C,
+  0xD1, 0xF0, 0xF3, 0xF3, 0xE0, 0xCD, 0x45, 0x3E,
+  0x48, 0x4B, 0x3F, 0x41, 0x56, 0x64, 0x65, 0x62,
+  0x5D, 0x52, 0x47, 0x48, 0x48, 0x53, 0x60, 0xCC,
+  0xD2, 0xD0, 0x63, 0x52, 0x4E, 0x53, 0xFB, 0xFB,
+  0xFC, 0xFC, 0x23, 0x23, 0x22, 0x23, 0x22, 0x23,
+  0x22, 0x22, 0x23, 0x23, 0x20, 0x21, 0x22, 0x22,
+  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
+  0x23, 0x22, 0x23, 0x22, 0x23, 0x22, 0xB4, 0xC7,
+  0xC5, 0xBC, 0xC5, 0xBD, 0xC5, 0xC5, 0xBD, 0xC5,
+  0xBC, 0xC6, 0xC7, 0xB9, 0x58, 0x57, 0x58, 0x57,
+  0x2D, 0xD4, 0xF1, 0xF2, 0xF0, 0xD9, 0x5D, 0x47,
+  0x48, 0x3F, 0x42, 0x2C, 0x48, 0x5C, 0x5F, 0x60,
+  0x58, 0x50, 0x47, 0x4A, 0x49, 0x55, 0x63, 0xD0,
+  0xD2, 0xCD, 0x5D, 0x49, 0x4E, 0xE1, 0xFC, 0xF0,
+  0xFC, 0xF8, 0x22, 0x22, 0x22, 0x23, 0x22, 0x23,
+  0x22, 0x22, 0x23, 0x20, 0x21, 0x21, 0x22, 0x22,
+  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0x22,
+  0x23, 0x22, 0x23, 0x23, 0x23, 0x22, 0xC4, 0xC8,
+  0xBD, 0xBD, 0xC6, 0xBD, 0xC6, 0xC6, 0xC5, 0xC6,
+  0xBD, 0xC6, 0xC7, 0xE4, 0x54, 0x57, 0x58, 0x57,
+  0x57, 0x43, 0xD7, 0xE0, 0xF1, 0xD8, 0xCD, 0x4B,
+  0x4A, 0x47, 0x42, 0x2C, 0x3F, 0x4D, 0x58, 0x5C,
+  0x52, 0x4B, 0x48, 0x4B, 0x4A, 0x58, 0xCB, 0xD3,
+  0xD2, 0xCD, 0x58, 0x47, 0x4A, 0xFC, 0xFC, 0xFB,
+  0xFC, 0x2B, 0x22, 0x22, 0x22, 0x23, 0x22, 0x23,
+  0x22, 0x22, 0x23, 0x26, 0x21, 0x21, 0x23, 0x22,
+  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
+  0x22, 0x23, 0x22, 0x23, 0x22, 0x23, 0xE5, 0xC8,
+  0xBA, 0xC5, 0xC6, 0xC6, 0xC6, 0xC7, 0xC6, 0xC7,
+  0xC5, 0xC6, 0xC8, 0xE5, 0x2E, 0x54, 0x58, 0x57,
+  0x57, 0x4C, 0x4D, 0xDA, 0xD8, 0xD8, 0xD4, 0x5C,
+  0x4B, 0x4B, 0x3F, 0x42, 0x44, 0x4A, 0x51, 0x58,
+  0x4B, 0x48, 0x4B, 0x51, 0x4D, 0x5F, 0xD0, 0xD1,
+  0xD0, 0x64, 0x51, 0x44, 0x6B, 0xFC, 0xFB, 0xFC,
+  0xFC, 0x21, 0x23, 0x22, 0x22, 0x23, 0x22, 0x23,
+  0x22, 0x22, 0x23, 0x26, 0x21, 0x23, 0x23, 0x22,
+  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
+  0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0xE5, 0xED,
+  0xE7, 0xBA, 0xC8, 0xC6, 0xC6, 0xC6, 0xC6, 0xC7,
+  0xC7, 0xE5, 0xED, 0xE6, 0x61, 0x41, 0x52, 0x58,
+  0x58, 0x57, 0x45, 0x5E, 0xD7, 0xDD, 0xD5, 0x60,
+  0x4B, 0x4C, 0x48, 0x4D, 0x4D, 0x50, 0x4D, 0x56,
+  0x4A, 0x3E, 0x53, 0x53, 0x52, 0x63, 0xD3, 0xD0,
+  0xCE, 0x60, 0x4A, 0x45, 0xFC, 0xFC, 0xF7, 0xFC,
+  0xFC, 0x21, 0x23, 0x23, 0x22, 0x23, 0x22, 0x23,
+  0x22, 0x23, 0x21, 0x2A, 0x20, 0x23, 0x23, 0x22,
+  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
+  0x23, 0x22, 0x23, 0x22, 0x21, 0x23, 0xEB, 0xF6,
+  0xF6, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED,
+  0xF6, 0xF6, 0xF6, 0xE6, 0xDB, 0x58, 0x45, 0x4B,
+  0x58, 0x57, 0x4D, 0x4B, 0x64, 0xD4, 0xD0, 0x5C,
+  0x48, 0x51, 0x4C, 0x5D, 0x5E, 0x5C, 0x56, 0x59,
+  0x3E, 0x4A, 0x58, 0x54, 0x52, 0x65, 0xD3, 0xD0,
+  0xCF, 0x5D, 0x48, 0xFC, 0xFC, 0xFC, 0xFA, 0xFC,
+  0xFC, 0x21, 0x22, 0x23, 0x22, 0x23, 0x22, 0x23,
+  0x22, 0x23, 0x21, 0x2A, 0x21, 0x23, 0x23, 0x22,
+  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
+  0x23, 0x22, 0x23, 0x22, 0x21, 0x4F, 0xE6, 0xC6,
+  0xC6, 0xBD, 0xC6, 0xBD, 0xBD, 0xBD, 0xBD, 0xC6,
+  0xC5, 0xBA, 0xC7, 0xE6, 0xF2, 0xD4, 0x49, 0x4B,
+  0x3E, 0x4D, 0x52, 0x3E, 0x52, 0x63, 0x64, 0x56,
+  0x48, 0x54, 0x4D, 0x61, 0xCC, 0xCC, 0x60, 0x60,
+  0x47, 0x4D, 0x5C, 0x53, 0x58, 0xCF, 0xD1, 0xCF,
+  0xD0, 0x59, 0x45, 0xFC, 0xFC, 0xFC, 0xEF, 0xF9,
+  0xFC, 0x21, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22,
+  0x23, 0x22, 0x23, 0x2A, 0x21, 0x23, 0x23, 0x22,
+  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
+  0x23, 0x22, 0x23, 0x22, 0x23, 0x4F, 0xE4, 0xB9,
+  0xAF, 0x80, 0x80, 0x8E, 0x8E, 0x8E, 0x8E, 0x8F,
+  0x80, 0xB4, 0xB9, 0xE4, 0x7F, 0xDE, 0x61, 0x52,
+  0x54, 0x48, 0x3F, 0x43, 0x4D, 0x56, 0x59, 0x4B,
+  0x3E, 0x58, 0x53, 0x61, 0xD3, 0xD4, 0xCF, 0xCD,
+  0x4C, 0x58, 0x5F, 0x53, 0x5E, 0xD3, 0xD0, 0xCE,
+  0xCE, 0x52, 0x3F, 0xFC, 0xFC, 0xFC, 0xF7, 0x65,
+  0xFA, 0x22, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22,
+  0x23, 0x22, 0x21, 0x2A, 0x23, 0x23, 0x23, 0x22,
+  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
+  0x23, 0x22, 0x23, 0x22, 0x21, 0xB1, 0xE4, 0xE6,
+  0x7C, 0xB1, 0x7C, 0xB1, 0xB2, 0xB2, 0xB3, 0x3D,
+  0xB3, 0x3C, 0xE5, 0xB3, 0xB0, 0xF1, 0xD0, 0x58,
+  0x5D, 0x4D, 0x40, 0x41, 0x48, 0x51, 0x4C, 0x3F,
+  0x3F, 0x4D, 0x5A, 0x5A, 0xD5, 0xD9, 0xD7, 0xD4,
+  0x57, 0x5E, 0x61, 0x4C, 0x63, 0xD4, 0xCF, 0xCE,
+  0xCB, 0x4D, 0x4A, 0xFC, 0xFC, 0xFC, 0xFC, 0xF0,
+  0xFB, 0x22, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22,
+  0x23, 0x22, 0x23, 0x2A, 0x21, 0x23, 0x23, 0x22,
+  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
+  0x22, 0x23, 0x22, 0x23, 0x23, 0xB1, 0x81, 0x7D,
+  0x39, 0x35, 0x35, 0x36, 0x36, 0x36, 0x36, 0x36,
+  0x36, 0x36, 0x7C, 0xB2, 0xB0, 0xDF, 0xD2, 0x57,
+  0x60, 0x59, 0x5B, 0x59, 0x52, 0x4C, 0x4A, 0x40,
+  0x42, 0x4A, 0x53, 0x4D, 0xD2, 0xDE, 0xDE, 0xD9,
+  0x5E, 0x5E, 0x60, 0x4A, 0xCD, 0xD1, 0xCF, 0xCE,
+  0x63, 0x49, 0x5C, 0xFB, 0xE8, 0x89, 0x9F, 0xFC,
+  0xD6, 0x21, 0x21, 0x23, 0x22, 0x22, 0x23, 0x22,
+  0x23, 0x22, 0x21, 0x2A, 0x22, 0x23, 0x23, 0x22,
+  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
+  0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x7F, 0xB9,
+  0x71, 0x6C, 0x38, 0x38, 0x33, 0x33, 0x33, 0x38,
+  0x38, 0x71, 0xAD, 0xE4, 0xD3, 0xDA, 0xCC, 0x52,
+  0x63, 0x60, 0xCE, 0xD4, 0xCF, 0x60, 0x4C, 0x40,
+  0x3F, 0x45, 0x4B, 0x5A, 0xCB, 0xD8, 0xDE, 0xDC,
+  0x5E, 0x5E, 0x5F, 0x4C, 0xD2, 0xD2, 0xCF, 0xCF,
+  0x61, 0x45, 0x5E, 0xA7, 0x9D, 0x95, 0x8B, 0x99,
+  0xFC, 0x41, 0x21, 0x23, 0x23, 0x22, 0x23, 0x22,
+  0x23, 0x22, 0x23, 0x2A, 0x23, 0x23, 0x23, 0x22,
+  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
+  0x22, 0x22, 0x23, 0x22, 0x23, 0x77, 0x77, 0xF6,
+  0xFC, 0x7D, 0x7D, 0x7E, 0x7E, 0x7E, 0x7E, 0x7D,
+  0x7D, 0xFC, 0x47, 0x64, 0xD0, 0xD0, 0x5D, 0x4B,
+  0x62, 0xCC, 0xD1, 0xDE, 0xDE, 0xD4, 0x5E, 0x43,
+  0x3F, 0x3E, 0x48, 0x53, 0x58, 0xDB, 0xD8, 0xDC,
+  0x5E, 0x5E, 0x5E, 0x53, 0xD4, 0xD2, 0xD0, 0xD0,
+  0x5E, 0x49, 0xA7, 0xA6, 0x89, 0x95, 0x8B, 0x9C,
+  0x9C, 0xFB, 0xD4, 0x22, 0x22, 0x22, 0x22, 0x23,
+  0x22, 0x23, 0x23, 0x2A, 0x22, 0x23, 0x23, 0x22,
+  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
+  0x23, 0x22, 0x23, 0x23, 0x98, 0x8C, 0x8C, 0x88,
+  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xF8,
+  0xE9, 0x9C, 0x48, 0x5C, 0xD0, 0xCB, 0x48, 0x49,
+  0x5B, 0xCB, 0xCD, 0xE0, 0xF1, 0xDD, 0xD0, 0x4A,
+  0x41, 0x47, 0x45, 0x4C, 0x48, 0xD7, 0xDE, 0xDC,
+  0x5E, 0x5E, 0x5A, 0x58, 0xD1, 0xD0, 0xD0, 0xD2,
+  0x5C, 0x55, 0xA7, 0xA6, 0x87, 0x86, 0x89, 0x94,
+  0x9C, 0xA9, 0xFC, 0xF4, 0x22, 0x23, 0x22, 0x23,
+  0x22, 0x23, 0x22, 0x2A, 0x21, 0x23, 0x23, 0x22,
+  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
+  0x22, 0x23, 0x22, 0x23, 0xA4, 0x89, 0x8C, 0xAA,
+  0xFB, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xF7,
+  0x85, 0x88, 0x8D, 0x59, 0x64, 0x63, 0x47, 0x3E,
+  0x4C, 0x60, 0x61, 0xE0, 0xF0, 0xDF, 0xD9, 0x5D,
+  0x2E, 0x3E, 0x3E, 0x47, 0x4D, 0xCD, 0xDE, 0xDC,
+  0x5D, 0x5C, 0x51, 0x5D, 0xD1, 0xD2, 0xD2, 0xD4,
+  0x5A, 0xBE, 0xA7, 0x98, 0x8A, 0x8A, 0xA0, 0x8B,
+  0x86, 0x86, 0xF7, 0xFC, 0xF7, 0x26, 0x23, 0x23,
+  0x22, 0x22, 0x22, 0x22, 0x21, 0x22, 0x23, 0x22,
+  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
+  0x22, 0x21, 0x21, 0x21, 0xA1, 0x98, 0x9F, 0xBF,
+  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xA7,
+  0x8C, 0x86, 0x8D, 0x59, 0x5E, 0x5D, 0x3F, 0x3E,
+  0x47, 0x53, 0x63, 0xD9, 0xF0, 0xF1, 0xDE, 0xD0,
+  0x43, 0x3E, 0x47, 0x45, 0x4A, 0x5B, 0xDC, 0xDA,
+  0x5D, 0x59, 0x49, 0x5F, 0xD1, 0xD2, 0xD3, 0xB9,
+  0xA5, 0xA7, 0x98, 0x9B, 0x96, 0x9D, 0x89, 0x89,
+  0x8B, 0x9C, 0x9D, 0xFC, 0xFC, 0xFC, 0x26, 0x22,
+  0x23, 0x23, 0x22, 0x22, 0x21, 0x22, 0x23, 0x22,
+  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
+  0x22, 0x22, 0x29, 0x2D, 0x99, 0x99, 0xA2, 0xAA,
+  0xC4, 0xFB, 0xFC, 0xFC, 0xFC, 0xF6, 0xBF, 0xA2,
+  0x9C, 0x9C, 0x8E, 0xDC, 0xCD, 0x51, 0x41, 0x3E,
+  0x45, 0x49, 0x58, 0xCD, 0xE0, 0xE0, 0xD8, 0xDA,
+  0x4C, 0x4A, 0x45, 0x45, 0x48, 0x47, 0xDA, 0xDA,
+  0x5C, 0x58, 0x44, 0x69, 0xA9, 0x98, 0xA4, 0xA6,
+  0xA1, 0xA4, 0x99, 0x9E, 0x9D, 0x8B, 0x8A, 0x97,
+  0x87, 0x9A, 0x8A, 0xC2, 0xFC, 0xFC, 0xFC, 0x4D,
+  0x21, 0x21, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22,
+  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0x22,
+  0x21, 0x22, 0x2D, 0x34, 0xA4, 0xA2, 0xA2, 0xA9,
+  0xBF, 0xC0, 0xC3, 0xC1, 0xC0, 0xBE, 0xA6, 0x9D,
+  0x99, 0x87, 0xA2, 0xF1, 0xDC, 0x64, 0x42, 0x45,
+  0x47, 0x3E, 0x49, 0x4C, 0xDD, 0xDF, 0xD8, 0xDB,
+  0x5E, 0x4C, 0x48, 0x45, 0x45, 0x41, 0xD1, 0xD6,
+  0x5A, 0x55, 0x3F, 0xA7, 0xA1, 0x98, 0x9F, 0x99,
+  0x9F, 0x9D, 0x9A, 0x95, 0x8B, 0x97, 0x89, 0x8A,
+  0x88, 0x94, 0x9C, 0x8C, 0xFC, 0xFC, 0xFC, 0xFC,
+  0xF4, 0x21, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22,
+  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
+  0x23, 0x23, 0x2C, 0x2C, 0xA8, 0xA2, 0xA4, 0xA4,
+  0xA9, 0xAA, 0xAA, 0xAA, 0xA9, 0xA6, 0x98, 0x9C,
+  0x8B, 0x88, 0x98, 0x8D, 0xD8, 0xD6, 0x4E, 0x47,
+  0x47, 0x49, 0x47, 0x3F, 0xDA, 0xDD, 0xDE, 0xDD,
+  0xCC, 0x4A, 0x4B, 0x3E, 0x45, 0x43, 0x61, 0xD4,
+  0x56, 0x51, 0x44, 0xA4, 0x9B, 0x8B, 0x9C, 0x9A,
+  0xA0, 0xA2, 0x98, 0x98, 0x8B, 0x8B, 0x98, 0x98,
+  0x84, 0x8B, 0x94, 0x8A, 0xA4, 0xFC, 0xFC, 0xFC,
+  0xFC, 0xF2, 0x21, 0x22, 0x21, 0x22, 0x23, 0x22,
+  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0x23,
+  0x23, 0x22, 0x2C, 0x2D, 0xC0, 0xA4, 0xA2, 0xA4,
+  0xA4, 0xA6, 0xA6, 0xA6, 0xA4, 0xA2, 0x9F, 0x89,
+  0x8B, 0x9C, 0x9C, 0x8B, 0x68, 0xDB, 0x5F, 0x4B,
+  0x3E, 0x49, 0x4B, 0x3E, 0xCC, 0xDA, 0xDC, 0xDD,
+  0xD3, 0x49, 0x52, 0x48, 0x45, 0x45, 0x53, 0xD0,
+  0x51, 0x4A, 0x44, 0xA4, 0x9B, 0x8B, 0x9C, 0xA0,
+  0x9B, 0x86, 0x89, 0x98, 0x89, 0x8A, 0x96, 0x8A,
+  0x9C, 0x89, 0x89, 0x9C, 0x8C, 0xF6, 0xFC, 0xFC,
+  0xFC, 0xFC, 0x21, 0x22, 0x21, 0x22, 0x23, 0x22,
+  0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x22, 0x23,
+  0x22, 0x21, 0x2B, 0x34, 0xC0, 0xA8, 0xA4, 0xA2,
+  0xA2, 0x98, 0xA1, 0xA0, 0x98, 0x9F, 0x95, 0x8A,
+  0x94, 0xA1, 0x8A, 0x84, 0x9B, 0x68, 0xCC, 0x49,
+  0x4A, 0x47, 0x4C, 0x4B, 0x51, 0xD3, 0xDA, 0xDC,
+  0xD5, 0x56, 0x56, 0x4A, 0x3E, 0x45, 0x48, 0x63,
+  0x4A, 0x47, 0x3E, 0xA7, 0x98, 0x9D, 0x9E, 0x8B,
+  0x95, 0x9B, 0x89, 0x86, 0x9B, 0x8B, 0x89, 0x84,
+  0x9A, 0xA1, 0x95, 0x9A, 0x8C, 0xA4, 0xFC, 0xFC,
+  0xFC, 0xFA, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22,
+  0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x22, 0x23,
+  0x21, 0x23, 0x2C, 0xF6, 0xBF, 0xA9, 0xA2, 0x99,
+  0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9B, 0x87, 0x8B,
+  0x9C, 0x86, 0x9C, 0x8A, 0x87, 0x87, 0x89, 0x51,
+  0x54, 0x47, 0x4B, 0x50, 0x4B, 0xCF, 0xD6, 0xDC,
+  0xD5, 0x60, 0x54, 0x52, 0x48, 0x45, 0x40, 0x5A,
+  0x45, 0x43, 0x47, 0xA7, 0x98, 0x9B, 0x95, 0x95,
+  0x9A, 0x87, 0x98, 0x98, 0x8A, 0x86, 0x87, 0x9E,
+  0x9B, 0x95, 0x9D, 0x9D, 0x99, 0x85, 0xA6, 0xFA,
+  0xF2, 0x21, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22,
+  0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x22, 0x22,
+  0x21, 0x24, 0xFB, 0xF7, 0xBF, 0xA6, 0xA2, 0x99,
+  0x97, 0x89, 0x86, 0x89, 0x9C, 0x96, 0x9E, 0x94,
+  0x89, 0x99, 0x98, 0x89, 0x9E, 0x9B, 0x89, 0x8B,
+  0x58, 0x4B, 0x4A, 0x52, 0x48, 0xCC, 0xD3, 0xDA,
+  0xD3, 0x65, 0x4C, 0x58, 0x49, 0x3E, 0x2E, 0x4D,
+  0x40, 0x41, 0x45, 0xA9, 0xA1, 0x9B, 0x9E, 0x9C,
+  0x95, 0x8A, 0x94, 0x89, 0x96, 0x87, 0x9C, 0x9A,
+  0x84, 0x9D, 0x9C, 0x9E, 0x9A, 0x9C, 0x9D, 0xBB,
+  0x23, 0x23, 0x22, 0x22, 0x21, 0x22, 0x23, 0x22,
+  0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x23, 0x23,
+  0x24, 0xFC, 0xFC, 0xF6, 0xBF, 0xA6, 0x9F, 0x99,
+  0x89, 0x95, 0x87, 0x94, 0x9D, 0x9E, 0x97, 0x9E,
+  0x95, 0x9B, 0x89, 0x95, 0x95, 0x9B, 0x89, 0x87,
+  0x5D, 0x56, 0x3E, 0x51, 0x3E, 0x60, 0xCF, 0xD3,
+  0xD2, 0xCD, 0x5C, 0x49, 0x4B, 0x3E, 0x2C, 0x48,
+  0x3E, 0x43, 0x3E, 0xA9, 0xA1, 0x9B, 0x97, 0x94,
+  0x95, 0x9A, 0x9C, 0x87, 0x87, 0x9B, 0x9C, 0x95,
+  0x9D, 0x89, 0x9A, 0x89, 0x9E, 0x9E, 0x8C, 0xA6,
+  0x20, 0x23, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22,
+  0x22, 0x22, 0x22, 0x22, 0x21, 0x21, 0x20, 0x40,
+  0xFC, 0xFC, 0xFC, 0xEC, 0xBE, 0xA4, 0x9F, 0x99,
+  0x95, 0x9F, 0xA0, 0x88, 0x9D, 0x8B, 0x97, 0x95,
+  0x87, 0x95, 0x96, 0x95, 0x97, 0x94, 0x94, 0x98,
+  0xD3, 0x4C, 0x47, 0x4D, 0x42, 0x4C, 0x60, 0xCC,
+  0xCE, 0xD0, 0x65, 0x4B, 0x47, 0x44, 0x2B, 0x45,
+  0x4B, 0x47, 0x49, 0xA7, 0xA1, 0x9A, 0x97, 0x89,
+  0x95, 0x97, 0x97, 0x9E, 0x89, 0x95, 0x89, 0x9C,
+  0x87, 0x95, 0x97, 0x99, 0x95, 0x99, 0x9F, 0xA4,
+  0xC4, 0x21, 0x21, 0x23, 0x21, 0x23, 0x23, 0x23,
+  0x23, 0x23, 0x23, 0x23, 0x21, 0x20, 0xFC, 0xFC,
+  0xFC, 0xFC, 0xFC, 0xEA, 0xAA, 0xA6, 0xA2, 0x99,
+  0x8B, 0x9A, 0x95, 0x9E, 0x9E, 0x9A, 0x94, 0x87,
+  0x94, 0x94, 0x89, 0x94, 0x9B, 0x9B, 0xA7, 0xDC,
+  0xDB, 0x65, 0x2E, 0x3E, 0x43, 0x44, 0x49, 0x58,
+  0x63, 0xD3, 0xD3, 0x5E, 0x42, 0x42, 0x2D, 0x40,
+  0x54, 0x4C, 0x4A, 0xA7, 0xA0, 0x99, 0x9B, 0x94,
+  0xA0, 0x8A, 0x9B, 0x9D, 0x87, 0x95, 0x94, 0x8B,
+  0x8A, 0x98, 0x9C, 0x8A, 0x9B, 0x99, 0xA2, 0xA6,
+  0xBF, 0xEC, 0x2A, 0x20, 0x21, 0x23, 0x21, 0x20,
+  0x20, 0x20, 0x20, 0x4C, 0xF9, 0xFC, 0xFC, 0xFC,
+  0xFC, 0xFC, 0xFC, 0xEB, 0xAA, 0xA4, 0x9F, 0x9C,
+  0x8B, 0x9B, 0x88, 0x84, 0x9E, 0x9D, 0x96, 0x94,
+  0x94, 0x9A, 0x9B, 0x9B, 0xA4, 0xD5, 0xCD, 0xDE,
+  0xF1, 0xDA, 0x4C, 0x2D, 0x41, 0x2B, 0x42, 0x4C,
+  0x5E, 0xD4, 0xD7, 0xCD, 0x49, 0x2E, 0x2E, 0x41,
+  0x5E, 0x57, 0xA7, 0xA6, 0xA7, 0xA4, 0xA2, 0x98,
+  0x9D, 0x9C, 0xA1, 0x99, 0x9D, 0x88, 0x8B, 0x9C,
+  0x8A, 0x9C, 0x9C, 0x94, 0x9C, 0x89, 0xA0, 0xA6,
+  0xAA, 0xEB, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+  0xFC, 0xFC, 0xFB, 0xE9, 0xAA, 0xA6, 0xA2, 0x8B,
+  0x8B, 0x8A, 0x86, 0x9B, 0x9C, 0x98, 0xA0, 0x9B,
+  0x9B, 0x84, 0xA7, 0xB4, 0x61, 0xD1, 0xD2, 0xE0,
+  0xF1, 0xDC, 0x61, 0x2D, 0x2E, 0x3F, 0x56, 0x62,
+  0x5D, 0xD4, 0xD9, 0xD3, 0x54, 0x41, 0x41, 0x44,
+  0xCB, 0x60, 0x52, 0xA9, 0xA9, 0xA9, 0xA7, 0xA6,
+  0xA6, 0xA4, 0xA4, 0xA2, 0xA2, 0x9D, 0x95, 0x89,
+  0x9C, 0x8A, 0x9E, 0x9C, 0x8A, 0x9E, 0xA0, 0xA8,
+  0xC0, 0xE9, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+  0xFC, 0xFC, 0xFC, 0xE9, 0xAA, 0xA6, 0xA0, 0x99,
+  0x9C, 0x8B, 0x9A, 0x84, 0x9B, 0x9B, 0x98, 0x98,
+  0xA9, 0xB9, 0x49, 0x57, 0xCB, 0xD4, 0xD3, 0xF1,
+  0xD8, 0xDA, 0xCE, 0x3F, 0x41, 0x4B, 0x5D, 0xCB,
+  0x5E, 0xD6, 0xDB, 0xD6, 0x5D, 0x43, 0x3F, 0x49,
+  0xD1, 0xCC, 0x4F, 0xDD, 0xC3, 0xBB, 0xBF, 0xAA,
+  0xAA, 0xA9, 0xAA, 0xA8, 0xA8, 0xA6, 0xA6, 0xA2,
+  0x9C, 0x9F, 0x9B, 0x9A, 0x9D, 0xA2, 0xA8, 0xAA,
+  0xC1, 0xEA, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+  0xFC, 0xFC, 0xFC, 0xEA, 0xC0, 0xAA, 0xA6, 0xA2,
+  0xA2, 0x99, 0xA0, 0xA0, 0xA4, 0xA7, 0xA9, 0xC0,
+  0x67, 0x49, 0x54, 0x60, 0xD0, 0xD4, 0xCC, 0xDF,
+  0xD9, 0xD5, 0xD2, 0x3E, 0x47, 0x56, 0x60, 0xCD,
+  0x5D, 0xD9, 0xD9, 0xD6, 0x61, 0x3F, 0x47, 0x52,
+  0xD6, 0xD3, 0x62, 0x4D, 0x40, 0x4A, 0x57, 0xCA,
+  0xC3, 0xC1, 0xC1, 0xC0, 0xBF, 0xBF, 0xAA, 0xAA,
+  0xA6, 0xA4, 0xA4, 0xA4, 0xA6, 0xA8, 0xBE, 0xC1,
+  0xC9, 0xEB, 0xFB, 0xFB, 0xFC, 0xFC, 0xFC, 0xFC,
+  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
+  0xFC, 0xFC, 0xFC, 0xEB, 0xC3, 0xC0, 0xAA, 0xA8,
+  0xA6, 0xA6, 0xA6, 0xA9, 0xAA, 0xC0, 0xE8, 0xD0,
+  0xD2, 0x4C, 0x5E, 0x64, 0xD0, 0xD1, 0x5F, 0xD9,
+  0xD5, 0xD1, 0xD0, 0x48, 0x52, 0x5C, 0x64, 0xCD,
+  0x5C, 0xDC, 0xD7, 0xD5, 0x62, 0x3F, 0x4C, 0x53,
+  0xDA, 0xD7, 0xCE, 0x56, 0x40, 0x4B, 0x52, 0x56,
+  0xCE, 0xDF, 0x6A, 0xEB, 0xE9, 0xC9, 0xC3, 0xC0,
+  0xC0, 0xBF, 0xBE, 0xAA, 0xBF, 0xC0, 0xC3, 0xC9,
+  0xEA, 0xF6, 0xEE, 0x58, 0x57, 0x5E, 0xD6, 0xD0,
+  0xD2, 0x61, 0xCB, 0xD6, 0xD6, 0xD4, 0xDF, 0xF3,
+  0xF2, 0xDD, 0xD7, 0xEB, 0xC9, 0xC1, 0xC0, 0xBF,
+  0xAA, 0xAA, 0xAA, 0xBE, 0xC3, 0xF0, 0xD2, 0xD2,
+  0xD2, 0x51, 0x62, 0xCC, 0xD0, 0xCC, 0x61, 0xD3,
+  0xCF, 0xCE, 0xD2, 0x48, 0x5A, 0x61, 0xCC, 0xCE,
+  0x5F, 0xD9, 0xD5, 0xD1, 0x63, 0x44, 0x56, 0x56,
+  0xDC, 0xD9, 0xD4, 0x5E, 0x42, 0x4A, 0x4C, 0x57,
+  0x5D, 0xD8, 0xE0, 0xD8, 0xDC, 0xCB, 0x66, 0xEC,
+  0xE8, 0xC3, 0xC3, 0xC3, 0xC3, 0xC9, 0xE8, 0xEA,
+  0xF6, 0x50, 0x3E, 0x58, 0x57, 0x5A, 0xD6, 0xD4,
+  0xCC, 0x4B, 0x53, 0x5C, 0x64, 0xD1, 0xDF, 0xF3,
+  0xF1, 0xDE, 0xD9, 0xF6, 0xEB, 0xC9, 0xC1, 0xC1,
+  0xC0, 0xC0, 0xC1, 0xC9, 0xF0, 0xD6, 0xCD, 0xD6,
+  0xD3, 0x53, 0xCB, 0xCF, 0xCD, 0x5F, 0x5F, 0xCE,
+  0xCF, 0xCD, 0xD0, 0x47, 0x5F, 0xCB, 0xCE, 0xCD,
+  0x63, 0xD6, 0xD3, 0xD1, 0x63, 0x3F, 0x58, 0x58,
+  0xDB, 0xDC, 0xDA, 0x65, 0x3E, 0x49, 0x49, 0x4D,
+  0x49, 0xDC, 0xDF, 0xE0, 0xDE, 0xD5, 0x47, 0x47,
+  0x46, 0x6B, 0xEB, 0xEA, 0xE9, 0xEA, 0xEB, 0xF6,
+  0xD0, 0x57, 0x57, 0x47, 0x47, 0x5B, 0xD4, 0xD4,
+  0xCD, 0x44, 0x3E, 0x4B, 0x50, 0x4B, 0x51, 0xD5,
+  0xDB, 0xD8, 0xDE, 0x4B, 0xF6, 0xF6, 0xEA, 0xE9,
+  0xE8, 0xEA, 0xEB, 0x67, 0x5E, 0xCC, 0xD6, 0xDC,
+  0xD5, 0x58, 0xCE, 0xCE, 0x62, 0x50, 0xCC, 0xD3,
+  0xD2, 0xCD, 0xCD, 0x4B, 0x64, 0xCE, 0xCE, 0x64,
+  0xCC, 0xD3, 0xD2, 0xD2, 0x61, 0x47, 0x5D, 0x5C,
+  0xDD, 0xDD, 0xD9, 0xD1, 0x4C, 0x47, 0x49, 0x4A,
+  0x4B, 0xD1, 0xD8, 0xE0, 0xDF, 0xDD, 0x5D, 0x4A,
+  0x48, 0x52, 0x51, 0x3F, 0xF6, 0xEC, 0xE0, 0xE0,
+  0xD3, 0x5E, 0x5F, 0x50, 0x4B, 0x50, 0xCB, 0xCE,
+  0x64, 0x45, 0x4C, 0x57, 0x57, 0x58, 0x52, 0xD6,
+  0xD3, 0xDE, 0xDF, 0xD1, 0x3E, 0x4B, 0xF6, 0xF6,
+  0xEC, 0x66, 0x53, 0x43, 0x56, 0xD1, 0xD9, 0xDE,
+  0xD4, 0x5E, 0xCE, 0xCC, 0x5B, 0x2C, 0xD4, 0xD5,
+  0xD2, 0xD0, 0x63, 0x5D, 0xCD, 0xD0, 0xCD, 0x5E,
+  0xD0, 0xCF, 0xCE, 0xD2, 0x5E, 0x50, 0x60, 0x5D,
+  0xDE, 0xDD, 0xDC, 0xD7, 0x5D, 0x45, 0x47, 0x3E,
+  0x4B, 0x5E, 0xDE, 0xDF, 0xE0, 0xD8, 0xCF, 0x3E,
+  0x45, 0x51, 0x58, 0x42, 0xCB, 0xDA, 0xDE, 0xD8,
+  0xD2, 0x61, 0xCC, 0xCF, 0xD6, 0xDA, 0xDA, 0xD5,
+  0xD0, 0x50, 0x44, 0x57, 0x57, 0x58, 0x45, 0xD1,
+  0xD1, 0xD7, 0xDF, 0xDF, 0xD7, 0xCF, 0x64, 0x60,
+  0xCE, 0xCE, 0xCE, 0x63, 0xCF, 0xDA, 0xDE, 0xD9,
+  0xCF, 0x63, 0xCD, 0x63, 0x4D, 0x4B, 0xD6, 0xD5,
+  0xCE, 0xD3, 0x60, 0xCB, 0xD0, 0xD0, 0x65, 0x47,
+  0xD0, 0xCC, 0xCC, 0xD1, 0x59, 0x5D, 0x63, 0x5E,
+  0xDD, 0xDD, 0xDE, 0xDC, 0xCB, 0x40, 0x48, 0x45,
+  0x3E, 0x3E, 0xD9, 0xDF, 0xE0, 0xDF, 0xDA, 0x51,
+  0x4C, 0x48, 0x56, 0x4C, 0x5B, 0xD2, 0xDA, 0xDB,
+  0xCB, 0x5F, 0xD0, 0xCC, 0xDC, 0xF0, 0xF3, 0xE0,
+  0xDD, 0xCC, 0x41, 0x50, 0x57, 0x57, 0x4B, 0x5D,
+  0xD3, 0xD1, 0xDE, 0xDF, 0xDE, 0xD7, 0xD0, 0xD0,
+  0xD5, 0xD6, 0xD6, 0xCE, 0xD7, 0xDC, 0xDA, 0xD5,
+  0x60, 0x63, 0x64, 0x5E, 0x47, 0x61, 0xD5, 0xD2,
+  0xCF, 0xD0, 0x59, 0xCD, 0xD1, 0xCF, 0x61, 0x4D,
+  0xCC, 0xCE, 0xCD, 0xD0, 0x52, 0x61, 0x64, 0x60,
+  0xDA, 0xDE, 0xDE, 0xDD, 0xD1, 0x4B, 0x4A, 0x45,
+  0x3E, 0x41, 0xCD, 0xDE, 0xE0, 0xF1, 0xDE, 0x63,
+  0x4A, 0x4A, 0x4A, 0x4B, 0x50, 0xCB, 0xD4, 0xD7,
+  0x5E, 0x54, 0x62, 0xD3, 0xD4, 0xF0, 0xF3, 0xF3,
+  0xF2, 0xDE, 0x61, 0x40, 0x49, 0x56, 0x4D, 0x3E,
+  0x4B, 0xCE, 0xD9, 0xD8, 0xD9, 0xD5, 0xCF, 0xD2,
+  0xD6, 0xD6, 0xD1, 0xD1, 0xD7, 0xD5, 0xCF, 0xD0,
+  0x54, 0x64, 0x63, 0x56, 0x2C, 0xCB, 0xD1, 0xCC,
+  0xD3, 0xCD, 0x54, 0xCF, 0xD1, 0xCE, 0x5E, 0x5C,
+  0xCE, 0xCE, 0xCE, 0xCB, 0x4B, 0x63, 0xCC, 0x61,
+  0xD4, 0xDC, 0xDE, 0xDE, 0xDA, 0x5D, 0x45, 0x45,
+  0x48, 0x3F, 0x52, 0xD9, 0xD8, 0xDF, 0xDF, 0xD2,
+  0x52, 0x4B, 0x3E, 0x2E, 0x47, 0x60, 0xCF, 0xD3,
+  0x59, 0x48, 0x50, 0x5E, 0xCC, 0xDE, 0xF2, 0xF2,
+  0xF3, 0xF3, 0xDD, 0x5D, 0x3E, 0x48, 0x47, 0x47,
+  0x58, 0xD1, 0xDA, 0xDA, 0xD5, 0xD1, 0xCD, 0xD2,
+  0xD3, 0xCF, 0xD3, 0xD1, 0xCD, 0xD3, 0xD2, 0x5E,
+  0x52, 0x64, 0x60, 0x4B, 0x45, 0x61, 0xCD, 0xD3,
+  0xD3, 0x64, 0x61, 0xD0, 0xD0, 0x64, 0x45, 0x63,
+  0xD0, 0xCE, 0xD0, 0x60, 0x56, 0xCB, 0xCC, 0x62,
+  0xCE, 0xDA, 0xDE, 0xD8, 0xDD, 0xCC, 0x45, 0x49,
+  0x3E, 0x47, 0x42, 0xD1, 0xDC, 0xD8, 0xD8, 0xD3,
+  0x5D, 0x4C, 0x49, 0x3F, 0x47, 0x59, 0xCD, 0xCF,
+  0x59, 0x2E, 0x48, 0x47, 0x52, 0x63, 0xF0, 0xF2,
+  0xF3, 0xF3, 0xF2, 0xDA, 0x52, 0x4B, 0x52, 0x58,
+  0x5E, 0x63, 0xD0, 0xD0, 0xD0, 0xCF, 0xCE, 0xCE,
+  0xCF, 0x65, 0x61, 0xD6, 0xD6, 0xD6, 0xCB, 0x4B,
+  0x61, 0x62, 0x5D, 0x43, 0x4B, 0x61, 0xD0, 0xD4,
+  0xD1, 0x61, 0xCE, 0xD2, 0xCD, 0x5E, 0x4A, 0xCE,
+  0xD0, 0xCC, 0xD0, 0x59, 0x61, 0xCC, 0xCC, 0x62,
+  0xD1, 0xD5, 0xDE, 0xD8, 0xDD, 0xCF, 0x4B, 0x4A,
+  0x45, 0x3E, 0x2D, 0xCB, 0xDC, 0xDE, 0xD8, 0xD5,
+  0x60, 0x54, 0x51, 0x4C, 0x4D, 0x5C, 0xCC, 0xCE,
+  0x5A, 0x2C, 0x50, 0x53, 0x3E, 0x59, 0xD8, 0xF3,
+  0xF2, 0xF3, 0xF3, 0xE0, 0x5E, 0x4A, 0x4C, 0x53,
+  0x5E, 0x63, 0xCC, 0xCC, 0xCC, 0xCD, 0xCF, 0xD3,
+  0x62, 0x53, 0xD6, 0xD6, 0xD6, 0xD6, 0x5B, 0x48,
+  0x64, 0x63, 0x59, 0x44, 0x57, 0x63, 0xD2, 0xD3,
+  0xD0, 0x5E, 0xD0, 0xD1, 0xCB, 0x58, 0x4C, 0xCF,
+  0xCF, 0xCE, 0xCE, 0x57, 0x63, 0xCC, 0xCD, 0x57,
+};
+
+unsigned char linux_logo_bw[] __initdata = {
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x3F,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F,
+  0xFE, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xFE, 0x3F, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xFE, 0x7F, 0xFF, 0xC7, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xC3,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF,
+  0xFB, 0xE3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xFD, 0xFF, 0xFF, 0xE1, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xF1,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xFF,
+  0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xF9, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xF9, 0xCF, 0xC3, 0xF8, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x87, 0x81, 0xF9,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xA7,
+  0x99, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xF9, 0xF3, 0xBC, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xF9, 0xE3, 0xBC, 0xF9, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xB0, 0x3C, 0xF9,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xB0,
+  0x19, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xF9, 0xC0, 0x03, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xF9, 0x80, 0x01, 0xF8, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x80, 0x01, 0xF8,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x80,
+  0x01, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xF9, 0xC0, 0x21, 0xD8, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xF9, 0xB1, 0x80, 0xEC, 0xC0, 0x1F,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xF1, 0x90, 0x00, 0xE4,
+  0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xF1, 0x8C,
+  0xC0, 0x7C, 0x04, 0x81, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xE3, 0x80, 0x00, 0x7C, 0x40, 0x11, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xE3, 0x80, 0x00, 0x7F, 0xD2, 0x29,
+  0xFF, 0xFF, 0xFF, 0xFF, 0x87, 0x00, 0x00, 0x3F,
+  0x80, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0x0E, 0x00,
+  0x00, 0x3F, 0x80, 0x19, 0xFF, 0xFF, 0xFF, 0xFF,
+  0x1E, 0x00, 0x00, 0x1F, 0x80, 0x19, 0xFF, 0xFF,
+  0xFF, 0xFE, 0x1C, 0x00, 0x00, 0x1E, 0x80, 0x19,
+  0xFF, 0xFF, 0xFF, 0xFE, 0x3C, 0x00, 0x00, 0x1E,
+  0x80, 0x11, 0xFF, 0xFF, 0xFF, 0xFC, 0x7C, 0x00,
+  0x00, 0x0F, 0x80, 0x11, 0xFF, 0xFF, 0xFF, 0xFC,
+  0xF8, 0x00, 0x00, 0x0E, 0x80, 0x11, 0xFF, 0xFF,
+  0xFF, 0xFC, 0xF8, 0x00, 0x00, 0x06, 0x00, 0x11,
+  0xFF, 0xFF, 0xFF, 0xF8, 0xF8, 0x00, 0x00, 0x06,
+  0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xF9, 0xF0, 0x00,
+  0x00, 0x02, 0x00, 0x09, 0xFF, 0xFF, 0xFF, 0xF1,
+  0xF0, 0x00, 0x00, 0x02, 0x80, 0x10, 0xFF, 0xFF,
+  0xFF, 0xF1, 0xE0, 0x00, 0x00, 0x00, 0x97, 0x10,
+  0xFF, 0xFF, 0xFF, 0xE3, 0xE0, 0x00, 0x00, 0x00,
+  0xDF, 0xF0, 0xFF, 0xFF, 0xFF, 0xE3, 0xC0, 0x00,
+  0x00, 0x00, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xC7,
+  0xC0, 0x00, 0x00, 0x01, 0xFF, 0xF8, 0xFF, 0xFF,
+  0xFF, 0xC7, 0x80, 0x00, 0x00, 0x01, 0xFF, 0xF8,
+  0xFF, 0xFF, 0xFF, 0x8F, 0x80, 0x00, 0x00, 0x01,
+  0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0x8F, 0x80, 0x00,
+  0x00, 0x01, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0x9F,
+  0x80, 0x00, 0x00, 0x01, 0xFF, 0xF8, 0xFF, 0xFF,
+  0xFF, 0x9F, 0x80, 0x00, 0x00, 0x01, 0x80, 0x18,
+  0xFF, 0xFF, 0xFF, 0x9E, 0x80, 0x00, 0x00, 0x03,
+  0xA8, 0x11, 0xFF, 0xFF, 0xFF, 0x9F, 0x80, 0x00,
+  0x00, 0x02, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x99,
+  0x80, 0x00, 0x00, 0x00, 0x00, 0x09, 0xFF, 0xFF,
+  0xFF, 0x00, 0x80, 0x00, 0x00, 0x01, 0xC0, 0x01,
+  0xFF, 0xFF, 0xFE, 0x20, 0x60, 0x00, 0x00, 0x00,
+  0xFF, 0xC3, 0xFF, 0xFF, 0xF8, 0x00, 0x30, 0x00,
+  0x00, 0x00, 0xFF, 0x0F, 0xFF, 0xFF, 0xC0, 0x40,
+  0x38, 0x00, 0x00, 0x00, 0xFE, 0x47, 0xFF, 0xFF,
+  0x81, 0x00, 0x1C, 0x00, 0x00, 0x00, 0xFC, 0x23,
+  0xFF, 0xFF, 0x90, 0x00, 0x1E, 0x00, 0x00, 0x00,
+  0x78, 0x11, 0xFF, 0xFF, 0x80, 0x00, 0x0F, 0x80,
+  0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00,
+  0x07, 0xC0, 0x00, 0x00, 0x00, 0x08, 0xFF, 0xFF,
+  0xC0, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x04,
+  0x7F, 0xFF, 0x80, 0x00, 0x03, 0xC0, 0x00, 0x10,
+  0x00, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x01, 0x80,
+  0x00, 0x30, 0x00, 0x00, 0x0F, 0xFF, 0x80, 0x00,
+  0x00, 0x00, 0x00, 0x70, 0x00, 0x01, 0x4F, 0xFF,
+  0x80, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00,
+  0x0F, 0xFF, 0xC0, 0x00, 0x00, 0x80, 0x03, 0xF0,
+  0x00, 0x00, 0x8F, 0xFF, 0x80, 0x00, 0x00, 0x40,
+  0x0F, 0xF0, 0x00, 0x04, 0x1F, 0xFF, 0x80, 0x00,
+  0x00, 0x7F, 0xFF, 0xF0, 0x00, 0x10, 0x1F, 0xFF,
+  0xC0, 0x00, 0x00, 0x7F, 0xFF, 0xF0, 0x00, 0x40,
+  0xFF, 0xFF, 0x98, 0x00, 0x00, 0xFF, 0xFF, 0xF0,
+  0x00, 0x83, 0xFF, 0xFF, 0x81, 0xE0, 0x01, 0xFF,
+  0xFF, 0xF8, 0x02, 0x07, 0xFF, 0xFF, 0x80, 0x3F,
+  0x07, 0xE0, 0x00, 0x1C, 0x0C, 0x1F, 0xFF, 0xFF,
+  0xF8, 0x03, 0xFF, 0x80, 0x00, 0x1F, 0x78, 0x1F,
+  0xFF, 0xFF, 0xFF, 0x80, 0x7F, 0x00, 0x07, 0x0F,
+  0xF0, 0x7F, 0xFF, 0xFF, 0xFF, 0xFE, 0x0C, 0x07,
+  0xFF, 0x83, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+  0x00, 0x1F, 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x07, 0xFF,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+};
+
+/* Painted by Johnny Stenback <jst@uwasa.fi> */
+
+unsigned char *linux_serial_image __initdata = "\n"
+"         .u$e.\n"
+"       .$$$$$:S\n"
+"       $\"*$/\"*$$\n"
+"       $.`$ . ^F\n"
+"       4k+#+T.$F\n"
+"       4P+++\"$\"$\n"
+"       :R\"+  t$$B\n"
+"    ___#       $$$\n"
+"    |  |       R$$k\n"
+"   dd. | Linux  $!$\n"
+"   ddd |  Sparc $9$F\n"
+" '!!!!!$       !!#!`\n"
+"  !!!!!*     .!!!!!`\n"
+"'!!!!!!!W..e$$!!!!!!`    %s\n"
+" \"~^^~         ^~~^\n"
+"\n";
diff -u --recursive --new-file v2.1.35/linux/include/asm-sparc/mxcc.h linux/include/asm-sparc/mxcc.h
--- v2.1.35/linux/include/asm-sparc/mxcc.h	Sat Nov  9 00:29:47 1996
+++ linux/include/asm-sparc/mxcc.h	Tue Apr 22 22:39:21 1997
@@ -1,4 +1,4 @@
-/* $Id: mxcc.h,v 1.6 1996/08/29 09:48:27 davem Exp $
+/* $Id: mxcc.h,v 1.7 1997/04/20 14:11:46 ecd Exp $
  * mxcc.h:  Definitions of the Viking MXCC registers
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -83,6 +83,8 @@
  * MID: The moduleID of the cpu your read this from.
  */
 
+#ifndef __ASSEMBLY__
+
 extern __inline__ void mxcc_set_stream_src(unsigned long *paddr)
 {
 	unsigned long data0 = paddr[0];
@@ -129,5 +131,7 @@
 			     "r" (mxcc_control), "r" (MXCC_CREG),
 			     "i" (ASI_M_MXCC));
 }
+
+#endif /* !__ASSEMBLY__ */
 
 #endif /* !(_SPARC_MXCC_H) */
diff -u --recursive --new-file v2.1.35/linux/include/asm-sparc/pgtable.h linux/include/asm-sparc/pgtable.h
--- v2.1.35/linux/include/asm-sparc/pgtable.h	Mon Apr 14 16:28:21 1997
+++ linux/include/asm-sparc/pgtable.h	Tue Apr 15 21:47:24 1997
@@ -1,4 +1,4 @@
-/* $Id: pgtable.h,v 1.59 1997/04/10 05:13:23 davem Exp $ */
+/* $Id: pgtable.h,v 1.60 1997/04/14 17:05:16 jj Exp $ */
 #ifndef _SPARC_PGTABLE_H
 #define _SPARC_PGTABLE_H
 
@@ -367,5 +367,31 @@
 }
 #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
+__get_phys (unsigned long addr)
+{
+	switch (sparc_cpu_model){
+	case sun4c:
+		return sun4c_get_pte (addr) << PAGE_SHIFT;
+	case sun4m:
+		return ((srmmu_get_pte (addr) & 0xffffff00) << 4);
+	default:
+		return 0;
+	}
+}
+
+extern __inline__ int
+__get_iospace (unsigned long addr)
+{
+	switch (sparc_cpu_model){
+	case sun4c:
+		return -1; /* Don't check iospace on sun4c */
+	case sun4m:
+		return (srmmu_get_pte (addr) >> 28);
+	default:
+		return -1;
+	}
+}
 
 #endif /* !(_SPARC_PGTABLE_H) */
diff -u --recursive --new-file v2.1.35/linux/include/asm-sparc/semaphore.h linux/include/asm-sparc/semaphore.h
--- v2.1.35/linux/include/asm-sparc/semaphore.h	Mon Apr 14 16:28:21 1997
+++ linux/include/asm-sparc/semaphore.h	Thu Apr 17 13:20:51 1997
@@ -13,8 +13,8 @@
 	struct wait_queue * wait;
 };
 
-#define MUTEX ((struct semaphore) { { (1 << 8) }, { 0 }, NULL })
-#define MUTEX_LOCKED ((struct semaphore) { { 0 }, { 0 }, NULL })
+#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);
@@ -22,6 +22,12 @@
 
 #define sema_init(sem, val)	atomic_set(&((sem)->count), val)
 
+#define wake_one_more(sem)	atomic_inc(&sem->waking);
+
+/* XXX Put this in raw assembler for SMP case so that the atomic_t
+ * XXX spinlock can allow this to be done without grabbing the IRQ
+ * XXX global lock.
+ */
 static inline int waking_non_zero(struct semaphore *sem)
 {
 	unsigned long flags;
diff -u --recursive --new-file v2.1.35/linux/include/asm-sparc/smp.h linux/include/asm-sparc/smp.h
--- v2.1.35/linux/include/asm-sparc/smp.h	Mon Apr 14 16:28:21 1997
+++ linux/include/asm-sparc/smp.h	Tue Apr 15 21:47:24 1997
@@ -96,48 +96,6 @@
 	return cpuid;
 }
 
-extern __volatile__ int smp_process_available;
-
-extern __inline__ int smp_swap(volatile int *addr, int value)
-{
-	__asm__ __volatile__("swap [%2], %0\n\t" :
-			     "=&r" (value) :
-			     "0" (value), "r" (addr));
-	return value;
-}
-
-extern __inline__ __volatile__ void inc_smp_counter(volatile int *ctr)
-{
-	int tmp;
-
-	while((tmp = smp_swap(ctr, -1)) == -1)
-		while(*ctr == -1)
-			;
-
-	*ctr = (tmp + 1);
-}
-
-extern __inline__ __volatile__ void dec_smp_counter(volatile int *ctr)
-{
-	int tmp;
-
-	while((tmp = smp_swap(ctr, -1)) == -1)
-		while(*ctr == -1)
-			;
-
-	*ctr = (tmp - 1);
-}
-
-extern __inline__ __volatile__ int read_smp_counter(volatile int *ctr)
-{
-	int value;
-
-	while((value = *ctr) == -1)
-		;
-
-	return value;
-}
-
 #endif /* !(__ASSEMBLY__) */
 
 /* Sparc specific messages. */
@@ -154,13 +112,13 @@
 #define MBOX_IDLECPU2         0xFD
 #define MBOX_STOPCPU2         0xFE
 
-#define NO_PROC_ID            0xFF
-
 #define PROC_CHANGE_PENALTY     20
 
 #define SMP_FROM_INT		1
 #define SMP_FROM_SYSCALL	2
 
 #endif /* !(__SMP__) */
+
+#define NO_PROC_ID            0xFF
 
 #endif /* !(_SPARC_SMP_H) */
diff -u --recursive --new-file v2.1.35/linux/include/asm-sparc/smp_lock.h linux/include/asm-sparc/smp_lock.h
--- v2.1.35/linux/include/asm-sparc/smp_lock.h	Mon Apr 14 16:28:21 1997
+++ linux/include/asm-sparc/smp_lock.h	Tue Apr 22 22:39:21 1997
@@ -14,7 +14,7 @@
 #define lock_kernel()				do { } while(0)
 #define unlock_kernel()				do { } while(0)
 #define release_kernel_lock(task, cpu, depth)	((depth) = 1)
-#define reaquire_kernel_lock(task, cpu, depth)	do { } while(0)
+#define reacquire_kernel_lock(task, cpu, depth)	do { } while(0)
 
 #else
 
@@ -34,7 +34,7 @@
 } while(0)
 
 /* Do not fuck with this without consulting arch/sparc/lib/locks.S first! */
-#define reaquire_kernel_lock(task, cpu, depth)					\
+#define reacquire_kernel_lock(task, cpu, depth)					\
 do {										\
 	if(depth) {								\
 		register struct klock_info *klip asm("g1");			\
@@ -42,7 +42,7 @@
 		klip = &klock_info;						\
 		proc = cpu;							\
 		__asm__ __volatile__("mov	%%o7, %%g4\n\t"			\
-				     "call	___lock_reaquire_kernel\n\t"	\
+				     "call	___lock_reacquire_kernel\n\t"	\
 				     " mov	%2, %%g2"			\
 				     : /* No outputs. */			\
 				     : "r" (klip), "r" (proc), "r" (depth)	\
@@ -63,19 +63,6 @@
 	register int proc asm("g5");
 	klip = &klock_info;
 	proc = smp_processor_id();
-
-#if 1 /* Debugging */
-	if(local_irq_count[proc]) {
-		__label__ l1;
-l1:		printk("lock from interrupt context at %p\n", &&l1);
-	}
-	if(proc == global_irq_holder) {
-		__label__ l2;
-l2:		printk("Ugh at %p\n", &&l2);
-		sti();
-	}
-#endif
-
 	__asm__ __volatile__("
 	mov	%%o7, %%g4
 	call	___lock_kernel
diff -u --recursive --new-file v2.1.35/linux/include/asm-sparc/softirq.h linux/include/asm-sparc/softirq.h
--- v2.1.35/linux/include/asm-sparc/softirq.h	Mon Apr 14 16:28:21 1997
+++ linux/include/asm-sparc/softirq.h	Tue Apr 22 22:39:21 1997
@@ -13,18 +13,17 @@
  * is entirely private to an implementation, it should not be
  * referenced at all outside of this file.
  */
+#define get_active_bhs()	(bh_mask & bh_active)
+
+#ifdef __SMP__
+
 extern atomic_t __sparc_bh_counter;
 
-/* Linus, I'd _really_ like to get rid of this synchronize_irq() -DaveM */
 #define start_bh_atomic() \
 	do { atomic_inc(&__sparc_bh_counter); synchronize_irq(); } while(0)
 
 #define end_bh_atomic()		atomic_dec(&__sparc_bh_counter)
 
-#define get_active_bhs()	(bh_mask & bh_active)
-
-#ifdef __SMP__
-
 #include <asm/spinlock.h>
 
 extern spinlock_t global_bh_lock;
@@ -39,6 +38,15 @@
 	spin_unlock_irqrestore(&global_bh_lock, flags);	\
 } while(0)
 
+#define remove_bh(nr)					\
+do {	unsigned long flags;				\
+	int ent = nr;					\
+	spin_lock_irqsave(&global_bh_lock, flags);	\
+	bh_base[ent] = NULL;				\
+	bh_mask &= ~(1 << ent);				\
+	spin_unlock_irqrestore(&global_bh_lock, flags);	\
+} while(0)
+
 #define mark_bh(nr)					\
 do {	unsigned long flags;				\
 	spin_lock_irqsave(&global_bh_lock, flags);	\
@@ -83,10 +91,13 @@
 
 #else /* !(__SMP__) */
 
-#define softirq_trylock() \
-	(atomic_read(&__sparc_bh_counter) ? 0 : ((atomic_set(&__sparc_bh_counter,1)),1))
+extern int __sparc_bh_counter;
 
-#define softirq_endlock()	(atomic_set(&__sparc_bh_counter, 0))
+#define start_bh_atomic()	do { __sparc_bh_counter++; barrier(); } while(0)
+#define end_bh_atomic()		do { barrier(); __sparc_bh_counter--; } while(0)
+
+#define softirq_trylock() (__sparc_bh_counter ? 0 : (__sparc_bh_counter=1))
+#define softirq_endlock() (__sparc_bh_counter = 0)
 #define clear_active_bhs(x)	(bh_active &= ~(x))
 
 #define init_bh(nr, routine)	\
@@ -94,6 +105,12 @@
 	bh_base[ent] = routine;	\
 	bh_mask_count[ent] = 0;	\
 	bh_mask |= 1 << ent;	\
+} while(0)
+
+#define remove_bh(nr)		\
+do {	int ent = nr;		\
+	bh_base[ent] = NULL;	\
+	bh_mask &= ~(1 << ent);	\
 } while(0)
 
 #define mark_bh(nr)		(bh_active |= (1 << (nr)))
diff -u --recursive --new-file v2.1.35/linux/include/asm-sparc/spinlock.h linux/include/asm-sparc/spinlock.h
--- v2.1.35/linux/include/asm-sparc/spinlock.h	Mon Apr 14 16:28:21 1997
+++ linux/include/asm-sparc/spinlock.h	Tue Apr 22 22:39:21 1997
@@ -16,6 +16,7 @@
 #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()
@@ -23,6 +24,33 @@
 #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 /* !(__SMP__) */
 
 #include <asm/psr.h>
@@ -30,20 +58,25 @@
 typedef unsigned char spinlock_t;
 #define SPIN_LOCK_UNLOCKED	0
 
+#define spin_lock_init(lock)	(*(lock) = 0)
+#define spin_unlock_wait(lock)	do { barrier(); } while(*(volatile spinlock_t *)lock)
+
 extern __inline__ void spin_lock(spinlock_t *lock)
 {
-	register spinlock_t *lp asm("g1");
-	lp = lock;
 	__asm__ __volatile__("
-	ldstub	[%%g1], %%g2
+1:	ldstub	[%0], %%g2
 	orcc	%%g2, 0x0, %%g0
-	be	1f
-	 mov	%%o7, %%g4
-	call	___spinlock_waitfor
-	 ldub	[%%g1], %%g2
-1:"	: /* no outputs */
-	: "r" (lp)
-	: "g2", "g4", "memory", "cc");
+	bne,a	2f
+	 ldub	[%0], %%g2
+	.text	2
+2:	orcc	%%g2, 0x0, %%g0
+	bne,a	2b
+	 ldub	[%0], %%g2
+	b,a	1b
+	.previous
+"	: /* no outputs */
+	: "r" (lock)
+	: "g2", "memory", "cc");
 }
 
 extern __inline__ int spin_trylock(spinlock_t *lock)
@@ -63,22 +96,24 @@
 
 extern __inline__ void spin_lock_irq(spinlock_t *lock)
 {
-	register spinlock_t *lp asm("g1");
-	lp = lock;
 	__asm__ __volatile__("
 	rd	%%psr, %%g2
 	or	%%g2, %0, %%g2
 	wr	%%g2, 0x0, %%psr
 	nop; nop; nop;
-	ldstub	[%%g1], %%g2
+1:	ldstub	[%1], %%g2
 	orcc	%%g2, 0x0, %%g0
-	be	1f
-	 mov	%%o7, %%g4
-	call	___spinlock_waitfor
-	 ldub	[%%g1], %%g2
-1:"	: /* No outputs */
-	: "i" (PSR_PIL), "r" (lp)
-	: "g2", "g4", "memory", "cc");
+	bne,a	2f
+	 ldub	[%1], %%g2
+	.text	2
+2:	orcc	%%g2, 0x0, %%g0
+	bne,a	2b
+	 ldub	[%1], %%g2
+	b,a	1b
+	.previous
+"	: /* No outputs */
+	: "i" (PSR_PIL), "r" (lock)
+	: "g2", "memory", "cc");
 }
 
 extern __inline__ void spin_unlock_irq(spinlock_t *lock)
@@ -102,16 +137,22 @@
 	"rd	%%psr, %0\n\t"			\
 	"or	%0, %1, %%g2\n\t"		\
 	"wr	%%g2, 0x0, %%psr\n\t"		\
-	"nop; nop; nop;\n\t"			\
-	"ldstub	[%%g1], %%g2\n\t"		\
+	"nop; nop; nop;\n"			\
+	"1:\n\t"				\
+	"ldstub	[%2], %%g2\n\t"			\
 	"orcc	%%g2, 0x0, %%g0\n\t"		\
-	"be	1f\n\t"				\
-	" mov	%%o7, %%g4\n\t"			\
-	"call	___spinlock_waitfor\n\t"	\
-	" ldub	[%%g1], %%g2\n\t"		\
-"1:"	: "=r" (flags)				\
-	: "i" (PSR_PIL), "r" (lp)		\
-	: "g2", "g4", "memory", "cc");		\
+	"bne,a	2f\n\t"				\
+	" ldub	[%2], %%g2\n\t"			\
+	".text	2\n"				\
+	"2:\n\t"				\
+	"orcc	%%g2, 0x0, %%g0\n\t"		\
+	"bne,a	2b\n\t"				\
+	" ldub	[%2], %%g2\n\t"			\
+	"b,a	1b\n\t"				\
+	".previous\n"				\
+	: "=r" (flags)				\
+	: "i" (PSR_PIL), "r" (lock)		\
+	: "g2", "memory", "cc");		\
 } while(0)
 
 extern __inline__ void spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags)
@@ -124,6 +165,92 @@
 	: "r" (lock), "r" (flags)
 	: "memory", "cc");
 }
+
+/* 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.
+ *
+ * XXX This might create some problems with my dual spinlock
+ * XXX scheme, deadlocks etc. -DaveM
+ */
+typedef struct { volatile unsigned int lock; } rwlock_t;
+
+#define RW_LOCK_UNLOCKED { 0 }
+
+/* Sort of like atomic_t's on Sparc, but even more clever.
+ *
+ *	------------------------------------
+ *	| 16-bit counter   | clock | wlock |  rwlock_t
+ *	------------------------------------
+ *	 31              16 15    8 7     0
+ *
+ * wlock signifies the one writer is in, the clock protects
+ * counter bumping, however a reader must acquire wlock
+ * before he can bump the counter on a read_lock().
+ * Similarly a writer, once he has the wlock, must await
+ * for the top 24 bits to all clear before he can finish
+ * going in (this includes the clock of course).
+ *
+ * Unfortunately this scheme limits us to ~65,000 cpus.
+ */
+extern __inline__ void read_lock(rwlock_t *rw)
+{
+	register rwlock_t *lp asm("g1");
+	lp = rw;
+	__asm__ __volatile__("
+	mov	%%o7, %%g4
+	call	___rw_read_enter
+	 ldstub	[%%g1 + 3], %%g2
+"	: /* no outputs */
+	: "r" (lp)
+	: "g2", "g4", "g7", "memory", "cc");
+}
+
+extern __inline__ void read_unlock(rwlock_t *rw)
+{
+	register rwlock_t *lp asm("g1");
+	lp = rw;
+	__asm__ __volatile__("
+	mov	%%o7, %%g4
+	call	___rw_read_exit
+	 ldstub	[%%g1 + 2], %%g2
+"	: /* no outputs */
+	: "r" (lp)
+	: "g2", "g4", "g7", "memory", "cc");
+}
+
+extern __inline__ void write_lock(rwlock_t *rw)
+{
+	register rwlock_t *lp asm("g1");
+	lp = rw;
+	__asm__ __volatile__("
+	mov	%%o7, %%g4
+	call	___rw_write_enter
+	 ldstub	[%%g1 + 3], %%g2
+"	: /* no outputs */
+	: "r" (lp)
+	: "g2", "g4", "g7", "memory", "cc");
+}
+
+#define write_unlock(rw)	do { (rw)->lock = 0; } while(0)
+#define read_lock_irq(lock)	do { __cli(); read_lock(lock); } while (0)
+#define read_unlock_irq(lock)	do { read_unlock(lock); __sti(); } while (0)
+#define write_lock_irq(lock)	do { __cli(); write_lock(lock); } while (0)
+#define write_unlock_irq(lock)	do { write_unlock(lock); __sti(); } while (0)
+
+#define read_lock_irqsave(lock, flags)	\
+	do { __save_and_cli(flags); read_lock(lock); } while (0)
+#define read_unlock_irqrestore(lock, flags) \
+	do { read_unlock(lock); __restore_flags(flags); } while (0)
+#define write_lock_irqsave(lock, flags)	\
+	do { __save_and_cli(flags); write_lock(lock); } while (0)
+#define write_unlock_irqrestore(lock, flags) \
+	do { write_unlock(lock); __restore_flags(flags); } while (0)
 
 #endif /* __SMP__ */
 
diff -u --recursive --new-file v2.1.35/linux/include/asm-sparc/system.h linux/include/asm-sparc/system.h
--- v2.1.35/linux/include/asm-sparc/system.h	Mon Apr 14 16:28:21 1997
+++ linux/include/asm-sparc/system.h	Tue Apr 22 22:39:21 1997
@@ -1,4 +1,4 @@
-/* $Id: system.h,v 1.56 1997/04/14 05:39:30 davem Exp $ */
+/* $Id: system.h,v 1.58 1997/04/18 05:44:54 davem Exp $ */
 #ifndef __SPARC_SYSTEM_H
 #define __SPARC_SYSTEM_H
 
@@ -93,9 +93,7 @@
 	"rd	%%wim, %%g5\n\t"							\
 	"wr	%%g4, 0x20, %%psr\n\t"							\
 	"nop\n\t"									\
-	"mov	%5, %%g7\n\t"								\
 	"std	%%g4, [%%g6 + %2]\n\t"							\
-	"st	%%g7, [%%g6 + %6]\n\t"							\
 	"ldd	[%1 + %2], %%g4\n\t"							\
 	"mov	%1, %%g6\n\t"								\
 	"st	%1, [%0]\n\t"								\
@@ -113,8 +111,7 @@
 	" nop\n\t" : : "r" (&(current_set[smp_processor_id()])), "r" (next),		\
 	  "i" ((const unsigned long)(&((struct task_struct *)0)->tss.kpsr)),		\
 	  "i" ((const unsigned long)(&((struct task_struct *)0)->tss.ksp)),		\
-	  "r" (task_pc), "i" (255),							\
-	  "i" ((const unsigned long)(&((struct task_struct *)0)->processor))		\
+	  "r" (task_pc)									\
 	: "g1", "g2", "g3", "g4", "g5", "g7", "l2", "l3",				\
 	"l4", "l5", "l6", "l7", "i0", "i1", "i2", "i3", "i4", "i5", "o0", "o1", "o2",	\
 	"o3");										\
@@ -127,9 +124,7 @@
 {
 	__asm__ __volatile__("
 		wr	%0, 0x0, %%psr
-		nop
-		nop
-		nop
+		nop; nop; nop
 "		: /* no outputs */
 		: "r" (__orig_psr)
 		: "memory", "cc");
@@ -141,14 +136,9 @@
 
 	__asm__ __volatile__("
 		rd	%%psr, %0
-		andcc	%0, %1, %%g0
-		bne	1f
-		 nop
-		wr	%0, %1, %%psr
-		nop
-		nop
-		nop
-1:
+		or	%0, %1, %0
+		wr	%0, 0x0, %%psr
+		nop; nop; nop
 "		: "=r" (tmp)
 		: "i" (PSR_PIL)
 		: "memory");
@@ -160,14 +150,9 @@
 
 	__asm__ __volatile__("
 		rd	%%psr, %0
-		andcc	%0, %1, %%g0
-		be	1f
-		 nop
-		wr	%0, %1, %%psr
-		nop
-		nop
-		nop
-1:
+		andn	%0, %1, %0
+		wr	%0, 0x0, %%psr
+		nop; nop; nop
 "		: "=r" (tmp)
 		: "i" (PSR_PIL)
 		: "memory");
@@ -192,7 +177,7 @@
 		xorcc	%1, %2, %%g0
 		be	1f
 		 nop
-		wr %0, %4, %%psr
+		wr	%0, %4, %%psr
 		nop
 		nop
 		nop
@@ -210,38 +195,64 @@
 
 	__asm__ __volatile__("
 		rd	%%psr, %0
-		andcc	%0, %1, %%g0
-		bne	1f
-		 nop
-		wr	%0, %1, %%psr
-		nop
-		nop
-		nop
-1:
+		or	%0, %1, %%g1
+		wr	%%g1, 0x0, %%psr
+		nop; nop; nop
 "		: "=r" (retval)
 		: "i" (PSR_PIL)
-		: "memory");
+		: "g1", "memory");
 
 	return retval;
 }
 
-extern char spdeb_buf[256];
-
 #define __save_flags(flags)	((flags) = getipl())
 #define __save_and_cli(flags)	((flags) = read_psr_and_cli())
 #define __restore_flags(flags)	setipl((flags))
 
 #ifdef __SMP__
 
-extern void __global_cli(void);
-extern void __global_sti(void);
-extern unsigned long __global_save_flags(void);
-extern void __global_restore_flags(unsigned long);
-#define cli() __global_cli()
-#define sti() __global_sti()
-#define save_flags(x)	  ((x)=__global_save_flags())
-#define restore_flags(x)  __global_restore_flags(x)
-#define save_and_cli(x)   do { (x)=__global_save_flags(); __global_cli(); } while(0)
+/* Visit arch/sparc/lib/irqlock.S for all the fun details... */
+#define cli()      __asm__ __volatile__("mov	%%o7, %%g4\n\t"			\
+					"call	___global_cli\n\t"		\
+					" rd	%%tbr, %%g7" : :		\
+					: "g1", "g2", "g3", "g4", "g5", "g7",	\
+					  "memory", "cc")
+
+#define sti()							\
+do {	register unsigned long bits asm("g7");			\
+	bits = 0;						\
+	__asm__ __volatile__("mov	%%o7, %%g4\n\t"		\
+			     "call	___global_sti\n\t"	\
+			     " rd	%%tbr, %%g2"		\
+			     : /* no outputs */			\
+			     : "r" (bits)			\
+			     : "g1", "g2", "g3", "g4", "g5",	\
+			       "memory", "cc");			\
+} while(0)
+
+extern unsigned char global_irq_holder;
+
+#define save_flags(x) \
+do {	int cpuid; \
+	__asm__ __volatile__("rd %%tbr, %0; srl %0, 12, %0; and %0, 3, %0" \
+			     : "=r" (cpuid)); \
+	((x) = ((global_irq_holder == (unsigned char) cpuid) ? 1 : \
+		((getipl() & PSR_PIL) ? 2 : 0))); \
+} while(0)
+
+#define restore_flags(flags)						\
+do {	register unsigned long bits asm("g7");				\
+	bits = flags;							\
+	__asm__ __volatile__("mov	%%o7, %%g4\n\t"			\
+			     "call	___global_restore_flags\n\t"	\
+			     " andcc	%%g7, 0x1, %%g0"		\
+			     : "=&r" (bits)				\
+			     : "0" (bits)				\
+			     : "g1", "g2", "g3", "g4", "g5",		\
+			       "memory", "cc");				\
+} while(0)
+
+#define save_and_cli(flags)   do { save_flags(flags); cli(); } while(0)
 
 #else
 
diff -u --recursive --new-file v2.1.35/linux/include/asm-sparc/viking.h linux/include/asm-sparc/viking.h
--- v2.1.35/linux/include/asm-sparc/viking.h	Mon Apr 14 16:28:21 1997
+++ linux/include/asm-sparc/viking.h	Tue Apr 22 22:39:21 1997
@@ -1,4 +1,4 @@
-/* $Id: viking.h,v 1.18 1997/04/11 00:42:23 davem Exp $
+/* $Id: viking.h,v 1.19 1997/04/20 14:11:48 ecd Exp $
  * viking.h:  Defines specific to the GNU/Viking MBUS module.
  *            This is SRMMU stuff.
  *
@@ -108,6 +108,8 @@
 #define VIKING_PTAG_DIRTY   0x00010000   /* Block has been modified */
 #define VIKING_PTAG_SHARED  0x00000100   /* Shared with some other cache */
 
+#ifndef __ASSEMBLY__
+
 extern __inline__ void viking_flush_icache(void)
 {
 	__asm__ __volatile__("sta %%g0, [%%g0] %0\n\t" : :
@@ -234,5 +236,7 @@
 			     "r" (vaddr), "i" (ASI_M_FLUSH_PROBE));
 	return val;
 }
+
+#endif /* !__ASSEMBLY__ */
 
 #endif /* !(_SPARC_VIKING_H) */
diff -u --recursive --new-file v2.1.35/linux/include/asm-sparc64/atomic.h linux/include/asm-sparc64/atomic.h
--- v2.1.35/linux/include/asm-sparc64/atomic.h	Mon Apr 14 16:28:22 1997
+++ linux/include/asm-sparc64/atomic.h	Thu Apr 17 13:20:51 1997
@@ -1,4 +1,4 @@
-/* $Id: atomic.h,v 1.13 1997/04/14 06:56:57 davem Exp $
+/* $Id: atomic.h,v 1.14 1997/04/16 05:57:06 davem Exp $
  * atomic.h: Thankfully the V9 is at least reasonable for this
  *           stuff.
  *
@@ -15,7 +15,7 @@
 #define __atomic_fool_gcc(x) ((struct { int a[100]; } *)x)
 
 typedef struct { int counter; } atomic_t;
-#define ATOMIC_INIT	{ 0 }
+#define ATOMIC_INIT(i)	{ (i) }
 
 #define atomic_read(v)		((v)->counter)
 #define atomic_set(v, i)	(((v)->counter) = i)
diff -u --recursive --new-file v2.1.35/linux/include/asm-sparc64/errno.h linux/include/asm-sparc64/errno.h
--- v2.1.35/linux/include/asm-sparc64/errno.h	Fri Dec 13 01:37:41 1996
+++ linux/include/asm-sparc64/errno.h	Tue Apr 15 21:47:24 1997
@@ -1,4 +1,4 @@
-/* $Id: errno.h,v 1.1 1996/11/20 15:27:39 davem Exp $ */
+/* $Id: errno.h,v 1.2 1997/04/15 12:46:11 jj Exp $ */
 #ifndef _SPARC64_ERRNO_H
 #define _SPARC64_ERRNO_H
 
@@ -129,5 +129,8 @@
 #define	EILSEQ		122	/* Illegal byte sequence */
 #define	ELIBMAX		123	/* Atmpt to link in too many shared libs */
 #define	ELIBSCN		124	/* .lib section in a.out corrupted */
+
+#define ENOMEDIUM       125     /* No medium found */
+#define EMEDIUMTYPE     126     /* Wrong medium type */
 
 #endif /* !(_SPARC64_ERRNO_H) */
diff -u --recursive --new-file v2.1.35/linux/include/asm-sparc64/fbio.h linux/include/asm-sparc64/fbio.h
--- v2.1.35/linux/include/asm-sparc64/fbio.h	Mon Apr 14 16:28:22 1997
+++ linux/include/asm-sparc64/fbio.h	Thu Apr 17 13:20:51 1997
@@ -33,6 +33,9 @@
 
 #define FBTYPE_LASTPLUSONE      21	/* This is not last + 1 in fact... */
 
+/* Does not seem to be listed in the Sun file either */
+#define FBTYPE_CREATOR          22
+
 /* fbio ioctls */
 /* Returned by FBIOGTYPE */
 struct  fbtype {
diff -u --recursive --new-file v2.1.35/linux/include/asm-sparc64/fcntl.h linux/include/asm-sparc64/fcntl.h
--- v2.1.35/linux/include/asm-sparc64/fcntl.h	Mon Apr 14 16:28:22 1997
+++ linux/include/asm-sparc64/fcntl.h	Tue Apr 15 21:47:24 1997
@@ -1,4 +1,4 @@
-/* $Id: fcntl.h,v 1.2 1997/04/04 00:50:15 davem Exp $ */
+/* $Id: fcntl.h,v 1.3 1997/04/14 17:05:20 jj Exp $ */
 #ifndef _SPARC64_FCNTL_H
 #define _SPARC64_FCNTL_H
 
@@ -48,7 +48,6 @@
 				   blocking */
 #define LOCK_UN		8	/* remove lock */
 
-/* XXX 32-bit binary compatability item... -DaveM */
 struct flock {
 	short l_type;
 	short l_whence;
@@ -57,5 +56,16 @@
 	pid_t l_pid;
 	short __unused;
 };
+
+#ifdef __KERNEL__
+struct flock32 {
+	short l_type;
+	short l_whence;
+	__kernel_off_t32 l_start;
+	__kernel_off_t32 l_len;
+	__kernel_pid_t32 l_pid;
+	short __unused;
+};
+#endif
 
 #endif /* !(_SPARC64_FCNTL_H) */
diff -u --recursive --new-file v2.1.35/linux/include/asm-sparc64/init.h linux/include/asm-sparc64/init.h
--- v2.1.35/linux/include/asm-sparc64/init.h	Thu Mar 27 14:40:09 1997
+++ linux/include/asm-sparc64/init.h	Thu Apr 17 13:20:51 1997
@@ -1,9 +1,6 @@
-#ifndef _SPARC64_INIT_H
-#define _SPARC64_INIT_H
+#ifndef _SPARC_INIT_H
+#define _SPARC_INIT_H
 
-#ifndef __init
-/* 'cause of buggy linker, we don't use this for now... */
-#if 0 && !defined (MODULE)
 #define __init __attribute__ ((__section__ (".text.init")))
 #define __initdata __attribute__ ((__section__ (".data.init")))
 #define __initfunc(__arginit) \
@@ -13,15 +10,5 @@
 #define __INIT		.section	".text.init",#alloc,#execinstr
 #define __FINIT	.previous
 #define __INITDATA	.section	".data.init",#alloc,#write
-#else
-#define	__init
-#define __initdata
-#define __initfunc(__arginit) __arginit
-/* For assembly routines */
-#define __INIT
-#define __FINIT
-#define __INITDATA
-#endif
-#endif
 
 #endif
diff -u --recursive --new-file v2.1.35/linux/include/asm-sparc64/ipc.h linux/include/asm-sparc64/ipc.h
--- v2.1.35/linux/include/asm-sparc64/ipc.h	Mon Apr 14 16:28:22 1997
+++ linux/include/asm-sparc64/ipc.h	Tue Apr 15 21:47:24 1997
@@ -4,12 +4,11 @@
 /* 
  * These are used to wrap system calls on the sparc.
  *
- * See arch/sparc64/kernel/sys_sparc.c for ugly details..
+ * See arch/sparc64/kernel/sys_sparc32.c for ugly details..
  */
-/* XXX 32-bit binary compatability... */
 struct ipc_kludge {
-	struct msgbuf *msgp;
-	long msgtyp;
+	u32 msgp;
+	s32 msgtyp;
 };
 
 #define SEMOP		 1
@@ -24,6 +23,7 @@
 #define SHMGET		23
 #define SHMCTL		24
 
-#define IPCCALL(version,op)	((version)<<16 | (op))
+/* We don't need to maintain backward compatibility on 64bit, we've started fresh */
+#define IPCCALL(version,op)	(op)
 
 #endif
diff -u --recursive --new-file v2.1.35/linux/include/asm-sparc64/linux_logo.h linux/include/asm-sparc64/linux_logo.h
--- v2.1.35/linux/include/asm-sparc64/linux_logo.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sparc64/linux_logo.h	Tue Apr 22 22:39:21 1997
@@ -0,0 +1,2084 @@
+/* $Id: linux_logo.h,v 1.1 1997/04/16 17:51:37 jj Exp $
+ * include/asm-sparc64/linux_logo.h: This is a linux logo
+ *                                   to be displayed on boot.
+ *
+ * Copyright (C) 1996 Larry Ewing (lewing@isc.tamu.edu)
+ * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ *
+ * You can put anything here, but:
+ * LINUX_LOGO_COLORS has to be less than 224
+ * image size has to be 80x80
+ * values have to start from 0x20
+ * (i.e. RGB(linux_logo_red[0],
+ *	     linux_logo_green[0],
+ *	     linux_logo_blue[0]) is color 0x20)
+ * BW image has to be 80x80 as well, with MS bit
+ * on the left
+ * Serial_console ascii image can be any size,
+ * but should contain %s to display the version
+ */
+ 
+#include <linux/init.h>
+#include <linux/version.h>
+
+#define linux_logo_banner "Linux/UltraSPARC version " UTS_RELEASE
+
+#define LINUX_LOGO_COLORS 215
+
+unsigned char linux_logo_red[] __initdata = {
+  0x99, 0x95, 0x92, 0x8E, 0x8A, 0x86, 0x02, 0x00,
+  0xA5, 0xA9, 0xA2, 0x9E, 0xAD, 0x1B, 0x3B, 0x25,
+  0x71, 0x65, 0x2C, 0x82, 0x5B, 0x33, 0x13, 0xB0,
+  0x0C, 0xB1, 0xD4, 0xCE, 0x04, 0x06, 0x16, 0xB6,
+  0xCD, 0xB2, 0x42, 0x46, 0x4B, 0xA8, 0xF3, 0xCA,
+  0xC5, 0x1C, 0xDC, 0xA0, 0xD4, 0xE6, 0xED, 0xF3,
+  0xC2, 0x8E, 0xCC, 0xA5, 0x7E, 0x52, 0xF7, 0xE3,
+  0x56, 0x79, 0x68, 0x8D, 0xAF, 0xFC, 0x8E, 0x3E,
+  0x6B, 0x11, 0x37, 0x79, 0x5C, 0x3C, 0x3F, 0x3C,
+  0x48, 0x47, 0x3D, 0xB9, 0x62, 0xE1, 0x4D, 0x57,
+  0x84, 0x78, 0xA6, 0x58, 0x99, 0xCD, 0xB7, 0xE3,
+  0x6D, 0x5A, 0xAF, 0x79, 0x79, 0xF2, 0x42, 0x46,
+  0xDD, 0x89, 0xC3, 0xF2, 0xF0, 0xE0, 0xD1, 0x90,
+  0x76, 0x6B, 0x4A, 0xBE, 0xBD, 0xE3, 0xF6, 0xE9,
+  0xEC, 0xE8, 0xEC, 0xC0, 0x66, 0x63, 0xCB, 0xAB,
+  0x49, 0x5C, 0xAD, 0xD6, 0xEE, 0xF5, 0xF5, 0xE9,
+  0x6E, 0x00, 0x69, 0x6A, 0xA1, 0x7A, 0xB4, 0xDE,
+  0xF1, 0xF6, 0xDD, 0x00, 0x73, 0xDB, 0x4C, 0x53,
+  0x6A, 0xF5, 0xF5, 0xD6, 0xC3, 0x6A, 0x4B, 0x4B,
+  0x60, 0xF8, 0x9B, 0xD7, 0xD7, 0x71, 0xB3, 0xA4,
+  0xCA, 0xAB, 0xB4, 0xB2, 0x76, 0xBA, 0x8B, 0xA0,
+  0xA5, 0xEE, 0xE7, 0x67, 0x5F, 0x08, 0x94, 0xDB,
+  0xE5, 0x4F, 0x00, 0x34, 0xEE, 0xEC, 0xE2, 0x48,
+  0xF3, 0xEB, 0xF4, 0xF4, 0xEF, 0xD6, 0xB6, 0xE6,
+  0xE6, 0xED, 0xE7, 0xE6, 0x3D, 0xE7, 0xCD, 0x44,
+  0xEF, 0xEC, 0xF5, 0x66, 0xF3, 0xA9, 0x77, 0x58,
+  0x75, 0x6C, 0x53, 0x24, 0xAC, 0x0D, 0x3C
+};
+
+unsigned char linux_logo_green[] __initdata = {
+  0x99, 0x95, 0x92, 0x8E, 0x8A, 0x86, 0x02, 0x00,
+  0xA5, 0xA9, 0xA2, 0x9E, 0xAD, 0x1B, 0x3B, 0x25,
+  0x71, 0x65, 0x2C, 0x82, 0x5B, 0x33, 0x13, 0xAD,
+  0x0C, 0xB1, 0x92, 0xAB, 0x03, 0x06, 0x16, 0xB6,
+  0xCD, 0x88, 0x42, 0x46, 0x4B, 0x94, 0xBB, 0xCA,
+  0xC5, 0x1C, 0xAB, 0xA0, 0xD4, 0xE6, 0xED, 0xF3,
+  0xC2, 0x73, 0xCA, 0x91, 0x7E, 0x52, 0xF7, 0xE3,
+  0x56, 0x5A, 0x49, 0x56, 0x6E, 0xFC, 0x6B, 0x3E,
+  0x6B, 0x0D, 0x37, 0x79, 0x51, 0x44, 0x3F, 0x43,
+  0x38, 0x3D, 0x48, 0xB9, 0x62, 0xA5, 0x47, 0x48,
+  0x49, 0x4A, 0x97, 0x48, 0x81, 0x95, 0x8E, 0xE3,
+  0x6D, 0x57, 0x51, 0x51, 0x47, 0xB2, 0x42, 0x46,
+  0xDD, 0x5B, 0x87, 0xBE, 0xC7, 0xC8, 0x56, 0x75,
+  0x5D, 0x4B, 0x4D, 0xBE, 0x85, 0xA6, 0xBC, 0xC7,
+  0xCA, 0xCD, 0xCC, 0xA4, 0x53, 0x4D, 0x9F, 0x55,
+  0x52, 0x5E, 0x75, 0x9C, 0xB6, 0xC3, 0xD7, 0xCC,
+  0x55, 0x00, 0x6A, 0x59, 0x7D, 0x55, 0x7C, 0xA3,
+  0xB7, 0xBF, 0xA5, 0x00, 0x67, 0xC6, 0x47, 0x54,
+  0x46, 0xB8, 0xBE, 0xB2, 0x87, 0x52, 0x4B, 0x43,
+  0x41, 0xF8, 0x69, 0x96, 0x9B, 0x66, 0xB0, 0x6C,
+  0x8E, 0x81, 0xB4, 0x76, 0x76, 0xB9, 0x65, 0x77,
+  0x6D, 0xED, 0xE7, 0x67, 0x5F, 0x06, 0x54, 0x6C,
+  0xCB, 0x4F, 0x00, 0x2F, 0xC2, 0xB5, 0xB6, 0x30,
+  0xC3, 0xAE, 0xC4, 0xCA, 0xC6, 0xB4, 0x7B, 0xAD,
+  0xAD, 0xB6, 0xB6, 0xAD, 0x29, 0xAB, 0x93, 0x2E,
+  0xBC, 0xBC, 0xC9, 0x53, 0xBF, 0x77, 0x54, 0x3B,
+  0x4B, 0x3F, 0x39, 0x19, 0x76, 0x08, 0x2C
+};
+
+unsigned char linux_logo_blue[] __initdata = {
+  0x99, 0x95, 0x92, 0x8E, 0x8A, 0x86, 0xD6, 0x00,
+  0xA5, 0xA9, 0xA2, 0x9E, 0xAD, 0x1B, 0x39, 0x25,
+  0x71, 0x65, 0x2C, 0x82, 0x5B, 0x33, 0x13, 0xA7,
+  0x0C, 0xB1, 0x58, 0x8A, 0x03, 0x07, 0x16, 0xB6,
+  0xCD, 0x5A, 0x42, 0x46, 0x4F, 0x6F, 0x77, 0xCA,
+  0xC5, 0x1C, 0x6F, 0xA5, 0xD4, 0xE6, 0xF5, 0xF3,
+  0xC2, 0x4D, 0xD1, 0x64, 0x7E, 0x52, 0xF7, 0xE3,
+  0x56, 0x49, 0x3C, 0x47, 0x45, 0xFE, 0x3B, 0x41,
+  0x6B, 0x09, 0x37, 0x79, 0x39, 0x39, 0x3F, 0x42,
+  0x3A, 0x42, 0x5F, 0xB9, 0x62, 0x4C, 0x39, 0x44,
+  0x3B, 0x3A, 0xA0, 0x3D, 0x08, 0x08, 0x09, 0xDE,
+  0x6D, 0x48, 0x3B, 0x3F, 0x42, 0xF3, 0x36, 0x3C,
+  0xDD, 0x06, 0x16, 0x08, 0x13, 0x0A, 0x4B, 0x71,
+  0x5D, 0x44, 0x47, 0xBE, 0x08, 0x0C, 0x0D, 0x0C,
+  0x19, 0x29, 0x36, 0x06, 0x43, 0x44, 0xBA, 0x45,
+  0x50, 0x58, 0x07, 0x07, 0x0D, 0x0E, 0x10, 0x50,
+  0x06, 0x42, 0x40, 0x44, 0x79, 0x06, 0x06, 0x0C,
+  0x08, 0x08, 0x07, 0x36, 0x4C, 0xE5, 0x42, 0x55,
+  0x03, 0x0F, 0x12, 0x06, 0x07, 0x3C, 0x4B, 0x3D,
+  0x01, 0xF8, 0x08, 0x0E, 0x0A, 0x69, 0xAC, 0x0C,
+  0x0A, 0x27, 0xBB, 0x36, 0x76, 0xC0, 0x04, 0x08,
+  0x08, 0xED, 0xEE, 0x68, 0x5F, 0xB2, 0x3B, 0x52,
+  0xAC, 0x4F, 0x6F, 0x2D, 0x16, 0x08, 0x59, 0x04,
+  0x13, 0x0E, 0x14, 0x17, 0x16, 0x2E, 0x08, 0x0D,
+  0x11, 0x14, 0x0D, 0x06, 0x04, 0x08, 0x25, 0x8E,
+  0x0E, 0x14, 0x25, 0x9B, 0x1C, 0x16, 0x78, 0x06,
+  0x04, 0x03, 0x79, 0x8C, 0x0B, 0xC8, 0x48
+};
+
+unsigned char linux_logo[] __initdata = {
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x21, 0x21, 0x22, 0x23, 0x24, 0x24,
+  0x25, 0x24, 0x24, 0x25, 0x25, 0x25, 0x25, 0x25,
+  0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x23, 0x23,
+  0x23, 0x22, 0x22, 0x22, 0x22, 0x21, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x26, 0x27, 0x27, 0x27, 0x27,
+  0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x26, 0x28,
+  0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+  0x29, 0x28, 0x28, 0x28, 0x2A, 0x2A, 0x2B, 0x2B,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x2B, 0x2B, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27,
+  0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27,
+  0x28, 0x28, 0x28, 0x29, 0x29, 0x29, 0x29, 0x29,
+  0x29, 0x29, 0x29, 0x2C, 0x29, 0x29, 0x29, 0x28,
+  0x28, 0x2A, 0x2B, 0x2B, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x2B, 0x2B, 0x2A, 0x2A,
+  0x2A, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27,
+  0x27, 0x27, 0x27, 0x27, 0x2D, 0x2E, 0x2F, 0x27,
+  0x27, 0x26, 0x2B, 0x2A, 0x2A, 0x2A, 0x2A, 0x28,
+  0x28, 0x29, 0x29, 0x29, 0x29, 0x2C, 0x2C, 0x29,
+  0x29, 0x29, 0x28, 0x28, 0x2A, 0x2B, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x2B, 0x2B, 0x2B, 0x2A, 0x2A, 0x2A,
+  0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27,
+  0x27, 0x27, 0x27, 0x27, 0x2F, 0x30, 0x31, 0x32,
+  0x27, 0x27, 0x22, 0x22, 0x22, 0x22, 0x21, 0x20,
+  0x20, 0x20, 0x2B, 0x2A, 0x28, 0x29, 0x29, 0x29,
+  0x2C, 0x2C, 0x2C, 0x29, 0x29, 0x28, 0x2A, 0x2B,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x2B, 0x2B, 0x2A, 0x2A, 0x2A, 0x2A, 0x2B,
+  0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27,
+  0x27, 0x27, 0x27, 0x27, 0x32, 0x33, 0x34, 0x35,
+  0x36, 0x27, 0x27, 0x33, 0x25, 0x25, 0x24, 0x24,
+  0x24, 0x24, 0x23, 0x21, 0x20, 0x20, 0x2B, 0x2A,
+  0x28, 0x29, 0x29, 0x37, 0x2C, 0x2C, 0x29, 0x28,
+  0x2A, 0x2B, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2B, 0x2B,
+  0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2A, 0x2B, 0x27,
+  0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27,
+  0x27, 0x27, 0x27, 0x27, 0x2F, 0x32, 0x36, 0x27,
+  0x27, 0x27, 0x27, 0x33, 0x33, 0x33, 0x33, 0x33,
+  0x33, 0x33, 0x33, 0x25, 0x25, 0x24, 0x23, 0x21,
+  0x20, 0x2B, 0x2A, 0x29, 0x29, 0x2C, 0x2C, 0x2C,
+  0x29, 0x28, 0x2A, 0x2B, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2B, 0x2B,
+  0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x20, 0x21, 0x27,
+  0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27,
+  0x27, 0x27, 0x27, 0x27, 0x38, 0x27, 0x27, 0x27,
+  0x27, 0x27, 0x27, 0x27, 0x23, 0x23, 0x24, 0x24,
+  0x25, 0x25, 0x33, 0x33, 0x33, 0x33, 0x33, 0x25,
+  0x24, 0x22, 0x20, 0x20, 0x2A, 0x28, 0x29, 0x2C,
+  0x2C, 0x2C, 0x29, 0x28, 0x2A, 0x2B, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x2B, 0x2B, 0x2B, 0x2B,
+  0x2B, 0x2B, 0x2B, 0x20, 0x21, 0x22, 0x23, 0x27,
+  0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27,
+  0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27,
+  0x27, 0x27, 0x27, 0x27, 0x2A, 0x2A, 0x2B, 0x2B,
+  0x20, 0x21, 0x22, 0x24, 0x20, 0x39, 0x39, 0x39,
+  0x39, 0x39, 0x3A, 0x3B, 0x22, 0x20, 0x2A, 0x28,
+  0x29, 0x2C, 0x2C, 0x2C, 0x29, 0x28, 0x2B, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B,
+  0x2B, 0x20, 0x21, 0x22, 0x22, 0x23, 0x24, 0x27,
+  0x27, 0x27, 0x3C, 0x36, 0x3C, 0x27, 0x27, 0x27,
+  0x27, 0x27, 0x27, 0x3D, 0x3E, 0x32, 0x27, 0x27,
+  0x27, 0x27, 0x27, 0x27, 0x3D, 0x39, 0x3F, 0x3F,
+  0x39, 0x2C, 0x20, 0x20, 0x39, 0x39, 0x39, 0x39,
+  0x39, 0x39, 0x39, 0x40, 0x40, 0x41, 0x22, 0x20,
+  0x2A, 0x28, 0x2C, 0x2C, 0x2C, 0x29, 0x29, 0x2A,
+  0x2B, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x2B, 0x2B, 0x2B, 0x2B, 0x20, 0x20,
+  0x21, 0x22, 0x22, 0x22, 0x23, 0x23, 0x22, 0x27,
+  0x27, 0x3C, 0x3C, 0x3D, 0x42, 0x3C, 0x27, 0x27,
+  0x3C, 0x27, 0x3C, 0x43, 0x44, 0x36, 0x42, 0x27,
+  0x27, 0x27, 0x27, 0x27, 0x3D, 0x28, 0x29, 0x2C,
+  0x2C, 0x45, 0x20, 0x39, 0x39, 0x39, 0x39, 0x39,
+  0x39, 0x46, 0x40, 0x47, 0x40, 0x47, 0x3A, 0x40,
+  0x22, 0x20, 0x2A, 0x29, 0x2C, 0x2C, 0x2C, 0x29,
+  0x28, 0x2B, 0x2B, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x2B, 0x2B, 0x2B, 0x2B, 0x20, 0x20, 0x22,
+  0x22, 0x22, 0x23, 0x22, 0x22, 0x21, 0x20, 0x27,
+  0x27, 0x44, 0x28, 0x24, 0x27, 0x2F, 0x3C, 0x27,
+  0x27, 0x38, 0x24, 0x2C, 0x2C, 0x48, 0x49, 0x36,
+  0x27, 0x27, 0x27, 0x27, 0x27, 0x28, 0x29, 0x29,
+  0x4A, 0x20, 0x3A, 0x40, 0x47, 0x40, 0x47, 0x40,
+  0x40, 0x47, 0x40, 0x40, 0x39, 0x39, 0x39, 0x4A,
+  0x25, 0x24, 0x22, 0x2B, 0x28, 0x29, 0x2C, 0x2C,
+  0x29, 0x28, 0x2A, 0x2B, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x2B, 0x2B, 0x20, 0x20, 0x20, 0x21, 0x22, 0x22,
+  0x22, 0x22, 0x22, 0x21, 0x20, 0x2B, 0x2A, 0x27,
+  0x3D, 0x4B, 0x48, 0x4C, 0x2B, 0x3C, 0x27, 0x3C,
+  0x3C, 0x23, 0x4D, 0x4E, 0x4F, 0x50, 0x33, 0x27,
+  0x27, 0x27, 0x27, 0x27, 0x27, 0x39, 0x3F, 0x39,
+  0x51, 0x20, 0x39, 0x39, 0x47, 0x40, 0x4D, 0x4D,
+  0x40, 0x52, 0x4D, 0x40, 0x47, 0x40, 0x39, 0x39,
+  0x53, 0x54, 0x25, 0x24, 0x20, 0x2A, 0x29, 0x2C,
+  0x2C, 0x2C, 0x29, 0x2A, 0x2B, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x21, 0x21, 0x22, 0x22,
+  0x22, 0x21, 0x20, 0x2B, 0x28, 0x2A, 0x20, 0x27,
+  0x36, 0x4F, 0x55, 0x48, 0x56, 0x3D, 0x3C, 0x3C,
+  0x32, 0x57, 0x56, 0x58, 0x49, 0x56, 0x56, 0x27,
+  0x27, 0x27, 0x27, 0x27, 0x27, 0x22, 0x20, 0x20,
+  0x41, 0x39, 0x39, 0x3A, 0x59, 0x5A, 0x59, 0x5B,
+  0x5C, 0x3A, 0x4D, 0x5D, 0x57, 0x39, 0x39, 0x4A,
+  0x5E, 0x33, 0x54, 0x33, 0x24, 0x22, 0x2B, 0x28,
+  0x2C, 0x2C, 0x2C, 0x29, 0x28, 0x2B, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x21, 0x21, 0x21, 0x22, 0x22, 0x21,
+  0x20, 0x2B, 0x2A, 0x2A, 0x20, 0x22, 0x22, 0x27,
+  0x5F, 0x2D, 0x3C, 0x60, 0x56, 0x54, 0x61, 0x49,
+  0x35, 0x56, 0x34, 0x27, 0x62, 0x27, 0x56, 0x39,
+  0x27, 0x27, 0x27, 0x27, 0x27, 0x30, 0x63, 0x54,
+  0x40, 0x64, 0x65, 0x66, 0x67, 0x67, 0x68, 0x5F,
+  0x2E, 0x69, 0x6A, 0x67, 0x5F, 0x3A, 0x39, 0x2C,
+  0x53, 0x23, 0x25, 0x54, 0x33, 0x25, 0x23, 0x20,
+  0x2A, 0x29, 0x2C, 0x2C, 0x29, 0x28, 0x2B, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x21, 0x21, 0x21, 0x21, 0x21, 0x20, 0x20,
+  0x2B, 0x2A, 0x20, 0x22, 0x22, 0x21, 0x2B, 0x27,
+  0x62, 0x36, 0x27, 0x33, 0x6B, 0x54, 0x3D, 0x3C,
+  0x49, 0x57, 0x27, 0x27, 0x27, 0x27, 0x56, 0x57,
+  0x27, 0x27, 0x27, 0x27, 0x27, 0x6C, 0x31, 0x6D,
+  0x64, 0x51, 0x6E, 0x2E, 0x2E, 0x6F, 0x5A, 0x70,
+  0x70, 0x71, 0x72, 0x67, 0x67, 0x69, 0x73, 0x46,
+  0x4A, 0x2A, 0x21, 0x25, 0x33, 0x54, 0x33, 0x24,
+  0x20, 0x2A, 0x29, 0x2C, 0x2C, 0x29, 0x28, 0x2B,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x21, 0x21, 0x21, 0x21, 0x20, 0x20, 0x2B,
+  0x2B, 0x22, 0x22, 0x22, 0x2B, 0x28, 0x2A, 0x27,
+  0x27, 0x39, 0x3C, 0x3D, 0x45, 0x74, 0x75, 0x76,
+  0x76, 0x45, 0x27, 0x27, 0x27, 0x27, 0x56, 0x77,
+  0x27, 0x27, 0x27, 0x27, 0x27, 0x78, 0x78, 0x5E,
+  0x79, 0x7A, 0x7B, 0x6E, 0x5A, 0x5A, 0x70, 0x7C,
+  0x70, 0x5B, 0x7D, 0x5A, 0x66, 0x7E, 0x7F, 0x79,
+  0x48, 0x6B, 0x2C, 0x20, 0x24, 0x33, 0x54, 0x33,
+  0x24, 0x21, 0x2A, 0x29, 0x2C, 0x2C, 0x29, 0x28,
+  0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x21, 0x21, 0x21, 0x20, 0x20, 0x2B, 0x2B, 0x21,
+  0x22, 0x22, 0x20, 0x28, 0x2B, 0x20, 0x22, 0x27,
+  0x27, 0x80, 0x27, 0x81, 0x82, 0x83, 0x84, 0x85,
+  0x74, 0x85, 0x84, 0x27, 0x3C, 0x4F, 0x4F, 0x66,
+  0x27, 0x27, 0x27, 0x27, 0x27, 0x22, 0x23, 0x5E,
+  0x64, 0x86, 0x79, 0x73, 0x87, 0x88, 0x7C, 0x5A,
+  0x5A, 0x71, 0x7D, 0x71, 0x89, 0x79, 0x8A, 0x8A,
+  0x51, 0x8B, 0x48, 0x39, 0x2A, 0x22, 0x33, 0x54,
+  0x33, 0x25, 0x22, 0x2B, 0x29, 0x2C, 0x2C, 0x29,
+  0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x21, 0x21, 0x20, 0x20, 0x2B, 0x2B, 0x22, 0x23,
+  0x21, 0x2A, 0x2A, 0x20, 0x21, 0x23, 0x25, 0x27,
+  0x27, 0x55, 0x8C, 0x8D, 0x8E, 0x83, 0x8F, 0x90,
+  0x91, 0x92, 0x92, 0x85, 0x85, 0x93, 0x51, 0x27,
+  0x27, 0x27, 0x27, 0x27, 0x27, 0x2A, 0x29, 0x51,
+  0x79, 0x79, 0x94, 0x89, 0x89, 0x89, 0x5A, 0x95,
+  0x64, 0x88, 0x96, 0x97, 0x7A, 0x73, 0x98, 0x98,
+  0x99, 0x50, 0x50, 0x48, 0x6B, 0x28, 0x21, 0x25,
+  0x54, 0x54, 0x25, 0x22, 0x2B, 0x29, 0x2C, 0x29,
+  0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x2B, 0x20, 0x22, 0x22, 0x20,
+  0x2B, 0x2B, 0x20, 0x22, 0x24, 0x25, 0x33, 0x27,
+  0x27, 0x9A, 0x9B, 0x9C, 0x9D, 0x83, 0x9E, 0x85,
+  0x9F, 0x92, 0x85, 0x85, 0x85, 0x85, 0x92, 0xA0,
+  0x27, 0x27, 0x27, 0x27, 0x27, 0xA1, 0x47, 0xA2,
+  0xA2, 0x94, 0xA3, 0x94, 0x95, 0x95, 0x73, 0x73,
+  0x95, 0x87, 0xA4, 0x5B, 0x97, 0x7B, 0x88, 0x98,
+  0xA2, 0x50, 0x48, 0x48, 0x48, 0x8B, 0x29, 0x20,
+  0x25, 0x54, 0x54, 0x25, 0x22, 0x2B, 0x29, 0x29,
+  0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x21, 0x22, 0x22, 0x2B, 0x2B,
+  0x20, 0x21, 0x23, 0x24, 0x25, 0x25, 0x33, 0x27,
+  0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0x8F, 0x90, 0x90,
+  0x9F, 0x90, 0x85, 0x90, 0x85, 0x74, 0xAA, 0x81,
+  0x27, 0x27, 0x27, 0x27, 0x27, 0xAB, 0x40, 0xAC,
+  0x79, 0xA3, 0x89, 0xAD, 0x95, 0x6F, 0xAE, 0xAE,
+  0xAE, 0x5B, 0x59, 0x88, 0x7B, 0x89, 0x79, 0xAF,
+  0xA2, 0x6B, 0x48, 0x48, 0x48, 0x48, 0x50, 0x2C,
+  0x20, 0x24, 0x33, 0x54, 0x25, 0x22, 0x2A, 0x2A,
+  0x21, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x21, 0x23, 0x22, 0x2B, 0x20, 0x20,
+  0x22, 0x23, 0x24, 0x25, 0x24, 0x24, 0x22, 0x27,
+  0xB0, 0x8C, 0xAA, 0xB1, 0xB2, 0x84, 0x85, 0x9F,
+  0x85, 0x85, 0x85, 0xB3, 0xB4, 0xAA, 0xAA, 0xA0,
+  0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x2A, 0xB5,
+  0xA3, 0xA3, 0xAC, 0x5D, 0xB6, 0xAE, 0xB7, 0x69,
+  0x73, 0x5B, 0x88, 0x89, 0x95, 0x73, 0x99, 0x99,
+  0x59, 0x2A, 0x39, 0x48, 0x48, 0x50, 0x48, 0x50,
+  0x2C, 0x20, 0x24, 0x33, 0x54, 0x25, 0x21, 0x20,
+  0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x21, 0x23, 0x21, 0x2B, 0x20, 0x20, 0x22,
+  0x22, 0x24, 0x24, 0x23, 0x22, 0x20, 0x2A, 0x27,
+  0x27, 0xB0, 0x8C, 0xA9, 0xB2, 0x9E, 0x91, 0x85,
+  0x85, 0x93, 0xB8, 0x75, 0xAA, 0xA7, 0x8C, 0x27,
+  0x27, 0x27, 0x33, 0x3C, 0x27, 0x27, 0x2C, 0x7B,
+  0x55, 0x79, 0xA3, 0x5D, 0xB9, 0x43, 0x7F, 0x7E,
+  0x5F, 0x5A, 0x5A, 0x95, 0x64, 0x73, 0x58, 0x64,
+  0x5C, 0x25, 0x2B, 0x3F, 0x48, 0x48, 0x8B, 0x48,
+  0x48, 0x2C, 0x20, 0x25, 0x54, 0x33, 0x24, 0x22,
+  0x2B, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x21, 0x23, 0x21, 0x20, 0x20, 0x20, 0x21, 0x22,
+  0x24, 0x23, 0x22, 0x21, 0x2B, 0x20, 0x54, 0x27,
+  0x27, 0x8B, 0x81, 0xA5, 0x93, 0x93, 0x74, 0xA5,
+  0xBA, 0x75, 0xBB, 0xBC, 0xB4, 0x6D, 0x50, 0x6B,
+  0x27, 0x27, 0x30, 0x33, 0x49, 0x27, 0x27, 0x5E,
+  0x6F, 0x73, 0x94, 0xBD, 0x4E, 0x5D, 0x7F, 0x7F,
+  0xB7, 0x68, 0x73, 0x6E, 0xB7, 0x7F, 0x95, 0x97,
+  0x47, 0x63, 0x25, 0x20, 0x3F, 0x48, 0x8B, 0x8B,
+  0x48, 0x48, 0x2C, 0x20, 0x25, 0x54, 0x33, 0x25,
+  0x2B, 0x2B, 0x2B, 0x20, 0x20, 0x20, 0x21, 0x21,
+  0x23, 0x21, 0x20, 0x20, 0x20, 0x20, 0x24, 0x24,
+  0x22, 0x21, 0x20, 0x2A, 0x33, 0x30, 0x30, 0x27,
+  0x27, 0x50, 0xBE, 0xBF, 0x9A, 0xB3, 0x9B, 0xBB,
+  0xBB, 0xC0, 0x8C, 0xC1, 0x8B, 0xC2, 0x47, 0x8B,
+  0x27, 0x27, 0x38, 0x63, 0x63, 0x27, 0x27, 0xC3,
+  0xB5, 0x95, 0x72, 0x95, 0x6F, 0x69, 0x7E, 0x66,
+  0x7E, 0x7F, 0x6E, 0x7E, 0x95, 0x95, 0x73, 0x70,
+  0x30, 0x30, 0x30, 0x33, 0x20, 0x3F, 0x48, 0x8B,
+  0x6B, 0x48, 0x50, 0x29, 0x21, 0x33, 0x54, 0x33,
+  0x2A, 0x2B, 0x2B, 0x20, 0x20, 0x21, 0x21, 0x23,
+  0x21, 0x20, 0x20, 0x20, 0x20, 0x24, 0x24, 0x22,
+  0x20, 0x2B, 0x21, 0xC4, 0x30, 0x60, 0x30, 0x27,
+  0x27, 0xC5, 0x8B, 0x39, 0xC6, 0xC7, 0xA6, 0xA6,
+  0xC8, 0x9A, 0x3B, 0x39, 0x50, 0x56, 0x56, 0x4F,
+  0x33, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x48,
+  0x59, 0x94, 0x73, 0xAE, 0xB7, 0xB7, 0x7E, 0x7E,
+  0x7E, 0x7E, 0x7E, 0x5A, 0x70, 0x7C, 0x71, 0xC3,
+  0x63, 0x30, 0x60, 0x78, 0x54, 0x20, 0x6B, 0x48,
+  0x6B, 0x6B, 0x50, 0x50, 0x29, 0x22, 0x33, 0x33,
+  0x2A, 0x2B, 0x20, 0x20, 0x21, 0x22, 0x22, 0x22,
+  0x21, 0x20, 0x20, 0x20, 0x24, 0x24, 0x20, 0x20,
+  0x2B, 0x24, 0x30, 0x60, 0x60, 0x30, 0xAB, 0x27,
+  0x27, 0x40, 0x4C, 0x50, 0x39, 0x87, 0xC3, 0x53,
+  0x37, 0x48, 0x37, 0x48, 0xC9, 0x56, 0xB9, 0x56,
+  0xCA, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x3C,
+  0x51, 0x5A, 0x6E, 0xB7, 0xB7, 0x7E, 0x7E, 0x7E,
+  0x7E, 0x7E, 0x7F, 0xB7, 0x5A, 0x7C, 0x5B, 0x37,
+  0x23, 0x63, 0x31, 0x6C, 0xCB, 0x63, 0x20, 0x6B,
+  0x50, 0x3F, 0x39, 0x50, 0x8B, 0x28, 0x24, 0x24,
+  0x2B, 0x2B, 0x20, 0x21, 0x22, 0x22, 0x22, 0x21,
+  0x20, 0x20, 0x20, 0x23, 0x23, 0x20, 0x20, 0x2B,
+  0x33, 0x78, 0xCB, 0x60, 0x30, 0x22, 0x3D, 0x27,
+  0x2F, 0x56, 0x4E, 0x8B, 0x6B, 0x39, 0x48, 0x8B,
+  0x6B, 0x8B, 0x80, 0xC9, 0xB9, 0xB9, 0x56, 0xB9,
+  0x56, 0x34, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27,
+  0x48, 0xB5, 0xB7, 0xB7, 0x7E, 0x7E, 0x2E, 0x7E,
+  0x7E, 0x7E, 0x7F, 0x7C, 0x65, 0x71, 0x3A, 0x48,
+  0x2C, 0x24, 0x30, 0x6C, 0x34, 0x6C, 0xC4, 0x20,
+  0x8B, 0x50, 0x39, 0x39, 0x48, 0x6B, 0x2B, 0x22,
+  0x2B, 0x20, 0x21, 0x22, 0x23, 0x23, 0x22, 0x21,
+  0x20, 0x2B, 0x23, 0x22, 0x20, 0x2B, 0x2B, 0x54,
+  0x60, 0x31, 0xCB, 0x54, 0x20, 0x3D, 0x36, 0x27,
+  0x4E, 0xB9, 0x56, 0x56, 0x8B, 0x6B, 0x50, 0x6B,
+  0x40, 0x56, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9,
+  0x56, 0x56, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27,
+  0x27, 0x7B, 0x6E, 0xB7, 0xB7, 0xB7, 0x7E, 0x7F,
+  0xB7, 0xB7, 0x7F, 0x7E, 0x6F, 0x5B, 0x29, 0x2C,
+  0x48, 0x39, 0x24, 0x60, 0x58, 0xAF, 0xCC, 0x63,
+  0x20, 0x8B, 0x8B, 0x39, 0x39, 0x48, 0x3F, 0x28,
+  0x20, 0x20, 0x22, 0x23, 0x23, 0x23, 0x22, 0x20,
+  0x2B, 0x22, 0x22, 0x2B, 0x2B, 0x20, 0x54, 0xCB,
+  0x31, 0xCB, 0x25, 0x20, 0x27, 0x27, 0x27, 0x48,
+  0xB9, 0x56, 0xB9, 0x56, 0x4F, 0x48, 0x47, 0x57,
+  0x56, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56,
+  0xB9, 0x56, 0x62, 0x27, 0x27, 0x27, 0x27, 0x27,
+  0x27, 0x48, 0x6F, 0x69, 0xB7, 0xB7, 0xB7, 0x7F,
+  0xB7, 0xB7, 0xB7, 0x73, 0x59, 0x50, 0x29, 0x2B,
+  0x28, 0x8B, 0x39, 0x25, 0x31, 0x55, 0xB6, 0x34,
+  0x63, 0x2B, 0x48, 0x6B, 0x2C, 0x39, 0x47, 0x6B,
+  0x22, 0x22, 0x23, 0x24, 0x23, 0x22, 0x20, 0x2B,
+  0x20, 0x22, 0x2A, 0x2B, 0x20, 0x33, 0xCB, 0x31,
+  0x78, 0x24, 0x21, 0xCD, 0x27, 0x27, 0x27, 0x56,
+  0x56, 0xB9, 0x56, 0xB9, 0x56, 0x56, 0x56, 0xB9,
+  0x56, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56,
+  0xB9, 0x56, 0xC9, 0x27, 0x27, 0x27, 0x27, 0x27,
+  0x27, 0x27, 0x41, 0x64, 0xB7, 0xB7, 0xB7, 0x7F,
+  0x68, 0xB7, 0xAE, 0xA3, 0x23, 0x39, 0x8B, 0x2A,
+  0x20, 0x20, 0x39, 0x6B, 0x25, 0xCC, 0x43, 0x43,
+  0x34, 0x63, 0x2A, 0x48, 0x3F, 0x39, 0x6B, 0x6B,
+  0x24, 0x23, 0x24, 0x24, 0x23, 0x21, 0x2B, 0x2B,
+  0x22, 0x2B, 0x2B, 0x20, 0x24, 0x78, 0x31, 0x30,
+  0x23, 0x21, 0x21, 0x27, 0x27, 0x27, 0x80, 0x56,
+  0x56, 0xB9, 0x56, 0xB9, 0x56, 0xB9, 0x56, 0xB9,
+  0x56, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9,
+  0x56, 0xB9, 0x56, 0x3C, 0x27, 0x27, 0x27, 0x27,
+  0x27, 0x27, 0x27, 0xCE, 0x8A, 0xAE, 0x6F, 0xB7,
+  0x6F, 0x89, 0x71, 0x78, 0x63, 0x23, 0x39, 0x6B,
+  0x2B, 0x20, 0x20, 0x2C, 0x6B, 0x25, 0x34, 0x42,
+  0x42, 0x34, 0x54, 0x29, 0x48, 0x3F, 0x39, 0x3F,
+  0x25, 0x24, 0x25, 0x24, 0x22, 0x20, 0x2A, 0x21,
+  0x2B, 0x2A, 0x20, 0x22, 0x30, 0x60, 0x30, 0x22,
+  0x21, 0x22, 0x27, 0x27, 0x27, 0x2D, 0x4C, 0x56,
+  0x56, 0xB9, 0xB9, 0x56, 0xB9, 0xB9, 0x56, 0x56,
+  0xB9, 0xB9, 0xB9, 0x56, 0x56, 0x56, 0xB9, 0xB9,
+  0xB9, 0xB9, 0x56, 0x2E, 0x27, 0x27, 0x27, 0x27,
+  0x27, 0x27, 0x27, 0x40, 0x97, 0x95, 0x5A, 0x71,
+  0x7C, 0xCE, 0x40, 0x60, 0x31, 0x30, 0x23, 0x3F,
+  0x3F, 0x20, 0x20, 0x20, 0x29, 0x8B, 0x33, 0x58,
+  0x66, 0x43, 0xCC, 0x25, 0x39, 0x50, 0x6B, 0x2C,
+  0x33, 0x25, 0x25, 0x23, 0x20, 0x2A, 0x2B, 0x20,
+  0x2A, 0x2B, 0x22, 0x54, 0x30, 0x30, 0x24, 0x22,
+  0x21, 0x27, 0x27, 0x27, 0x27, 0xAF, 0x29, 0x4E,
+  0x4F, 0xB9, 0x56, 0xB9, 0x4D, 0x4D, 0x77, 0xC9,
+  0xB9, 0xB9, 0xB9, 0x56, 0xC9, 0x4D, 0x4D, 0x80,
+  0x4C, 0x40, 0xC9, 0x4D, 0x27, 0x27, 0x27, 0x27,
+  0x27, 0x27, 0x27, 0x27, 0xCF, 0x97, 0x97, 0xCE,
+  0x86, 0xD0, 0x54, 0x6C, 0x58, 0x34, 0x60, 0x23,
+  0x6B, 0x39, 0x20, 0x20, 0x20, 0x28, 0x6B, 0x54,
+  0xD1, 0x66, 0xB6, 0x60, 0x22, 0x6B, 0x8B, 0x2C,
+  0x54, 0x33, 0x24, 0x22, 0x2B, 0x28, 0x20, 0x28,
+  0x2B, 0x20, 0x25, 0xC4, 0x30, 0x25, 0x22, 0x21,
+  0x26, 0x27, 0x27, 0x27, 0x27, 0x20, 0x4B, 0x52,
+  0x80, 0x4F, 0xB9, 0x56, 0xB9, 0x80, 0x56, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0x4D, 0x80, 0x50, 0x48,
+  0x50, 0x50, 0x50, 0x56, 0x3D, 0x27, 0x36, 0x27,
+  0x27, 0x27, 0x27, 0x3C, 0x46, 0xC3, 0x86, 0x86,
+  0xD0, 0x39, 0x24, 0x6C, 0xD1, 0x43, 0x43, 0x6C,
+  0x24, 0x6B, 0x2C, 0x20, 0x20, 0x20, 0x29, 0x39,
+  0x63, 0xD1, 0x42, 0x55, 0xC4, 0x2B, 0x8B, 0x39,
+  0x54, 0x25, 0x24, 0x20, 0x2A, 0x2A, 0x28, 0x28,
+  0x20, 0x22, 0x54, 0x63, 0x25, 0x24, 0x22, 0x22,
+  0x27, 0x27, 0x27, 0x27, 0x27, 0x28, 0x77, 0x56,
+  0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0xC9, 0x56, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x4F,
+  0x77, 0x47, 0x8B, 0x40, 0x56, 0x27, 0x27, 0x49,
+  0x2D, 0x27, 0x27, 0x27, 0x39, 0x40, 0x39, 0x39,
+  0x28, 0x3F, 0x39, 0x33, 0x58, 0x66, 0x35, 0x2E,
+  0x58, 0x24, 0x8B, 0x29, 0x20, 0x20, 0x20, 0x39,
+  0x29, 0x30, 0x55, 0xB6, 0xCC, 0x25, 0x29, 0x39,
+  0x54, 0x25, 0x22, 0x2B, 0x29, 0x2A, 0x29, 0x2B,
+  0x22, 0x24, 0x54, 0x33, 0x25, 0x22, 0x2B, 0x54,
+  0x27, 0x27, 0x62, 0x27, 0x30, 0x80, 0xB9, 0x56,
+  0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0x56, 0x4D, 0x8B, 0x77, 0x36, 0x27, 0x27,
+  0x3C, 0x2F, 0x27, 0x27, 0x39, 0x39, 0x39, 0x47,
+  0x20, 0x2B, 0x2C, 0x39, 0x33, 0xB6, 0x35, 0x35,
+  0x35, 0xAF, 0x24, 0x48, 0x2A, 0x20, 0x20, 0x20,
+  0x8B, 0x2B, 0x78, 0xAF, 0x58, 0x30, 0x21, 0x28,
+  0x33, 0x25, 0x21, 0x28, 0x29, 0x29, 0x28, 0x20,
+  0x24, 0x33, 0x54, 0x33, 0x23, 0x20, 0x24, 0xD2,
+  0x27, 0x49, 0x27, 0x27, 0x56, 0xB9, 0xB9, 0x56,
+  0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0xB9, 0x56, 0xC9, 0x50, 0x56, 0x27, 0x27,
+  0x3D, 0x38, 0x3D, 0x27, 0x27, 0x47, 0x39, 0x39,
+  0x28, 0x20, 0x20, 0x2A, 0x39, 0x54, 0x43, 0x35,
+  0x35, 0x35, 0xAF, 0x23, 0x48, 0x2B, 0x20, 0x20,
+  0x2B, 0x48, 0x22, 0x60, 0x34, 0xCB, 0x25, 0x21,
+  0x33, 0x24, 0x2B, 0x29, 0x29, 0x29, 0x2B, 0x22,
+  0x25, 0x54, 0x54, 0x25, 0x22, 0x2B, 0x33, 0x27,
+  0x27, 0x32, 0x27, 0x30, 0x56, 0xB9, 0xB9, 0x56,
+  0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0xB9, 0x56, 0x56, 0xC9, 0x4C, 0x36, 0x3C,
+  0x62, 0x2F, 0x2E, 0x27, 0x27, 0x54, 0x47, 0x47,
+  0x8B, 0x2B, 0x20, 0x20, 0x20, 0x3F, 0x54, 0x2E,
+  0x35, 0x35, 0x35, 0x34, 0x21, 0x8B, 0x2A, 0x20,
+  0x20, 0x2C, 0x6B, 0x25, 0x60, 0x60, 0x54, 0x23,
+  0x25, 0x22, 0x2A, 0x2C, 0x29, 0x28, 0x20, 0x24,
+  0x54, 0x63, 0x54, 0x24, 0x2B, 0x22, 0x24, 0x27,
+  0x36, 0x27, 0x27, 0x56, 0x56, 0xB9, 0xB9, 0x56,
+  0xB9, 0xB9, 0xB9, 0x56, 0x56, 0x56, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56, 0x4C, 0x36,
+  0x66, 0xD3, 0x27, 0x2F, 0x27, 0x54, 0x54, 0x27,
+  0x26, 0x6B, 0x20, 0x20, 0x20, 0x20, 0x6B, 0x63,
+  0x35, 0x35, 0x35, 0x62, 0xCB, 0x2A, 0x3F, 0x28,
+  0x2B, 0x2A, 0x50, 0x29, 0x33, 0x30, 0x54, 0x25,
+  0x24, 0x20, 0x29, 0x2C, 0x2C, 0x2A, 0x21, 0x33,
+  0xC4, 0xC4, 0x33, 0x21, 0x29, 0x22, 0x27, 0x27,
+  0x99, 0x27, 0x31, 0xB9, 0xB9, 0xB9, 0xB9, 0x56,
+  0xB9, 0xB9, 0xB9, 0x56, 0x56, 0x56, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56, 0x56, 0x3D,
+  0x3D, 0x3C, 0x3C, 0x55, 0x54, 0x54, 0x54, 0x20,
+  0x27, 0x2C, 0x39, 0x20, 0x20, 0x20, 0x20, 0x48,
+  0x30, 0x62, 0x35, 0x35, 0x42, 0x54, 0x39, 0x39,
+  0x2C, 0x28, 0x3F, 0x8B, 0x20, 0x33, 0x54, 0x24,
+  0x22, 0x2B, 0x2C, 0x2C, 0x2C, 0x2B, 0x24, 0x54,
+  0x30, 0xC4, 0x25, 0x2B, 0x28, 0x2B, 0x27, 0x3D,
+  0x27, 0x27, 0x56, 0xB9, 0xB9, 0xB9, 0xB9, 0x56,
+  0xB9, 0xB9, 0x56, 0x56, 0x4F, 0x56, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0x56, 0x56, 0x27,
+  0x20, 0x20, 0x20, 0x54, 0x54, 0x54, 0x54, 0x20,
+  0x20, 0x2D, 0x2D, 0x29, 0x20, 0x20, 0x20, 0x20,
+  0x48, 0x60, 0x66, 0x35, 0x62, 0x34, 0x22, 0x2C,
+  0x2C, 0x3F, 0x6B, 0x48, 0x2C, 0x22, 0x23, 0x23,
+  0x20, 0x2A, 0x2C, 0x29, 0x29, 0x20, 0x25, 0xC4,
+  0x30, 0x54, 0x22, 0x29, 0x28, 0xD2, 0x27, 0x35,
+  0x27, 0x49, 0x56, 0xB9, 0xB9, 0xB9, 0xB9, 0x56,
+  0xB9, 0xB9, 0x56, 0x4F, 0x56, 0x56, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0xB9, 0xB9, 0x56, 0x56, 0x56, 0x40, 0x20,
+  0x20, 0x54, 0x54, 0x54, 0x20, 0x20, 0x20, 0x20,
+  0x2D, 0x2D, 0x2D, 0x49, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x6B, 0x6C, 0x42, 0x2E, 0xB6, 0x54, 0x28,
+  0x29, 0x2C, 0x6B, 0x48, 0x3F, 0x2A, 0x20, 0x22,
+  0x2B, 0x28, 0x2C, 0x28, 0x29, 0x20, 0x33, 0x30,
+  0x30, 0x54, 0x20, 0x2C, 0x29, 0x27, 0x27, 0x3D,
+  0x27, 0x40, 0x56, 0xB9, 0x56, 0x56, 0xB9, 0x56,
+  0xB9, 0x56, 0x56, 0x4D, 0x56, 0x56, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0xB9, 0x56, 0x56, 0x63, 0x56, 0x54, 0x54,
+  0x54, 0x54, 0x20, 0xD3, 0x45, 0x51, 0x51, 0x49,
+  0x7C, 0x2D, 0x2D, 0x49, 0x49, 0x20, 0x20, 0x20,
+  0x20, 0x2A, 0x2A, 0xCC, 0xB6, 0x8A, 0x60, 0x22,
+  0x28, 0x29, 0x3F, 0x6B, 0x39, 0x29, 0x2B, 0x20,
+  0x28, 0x2C, 0x28, 0x2A, 0x2A, 0x24, 0xC4, 0x30,
+  0xC4, 0x33, 0x2B, 0x39, 0xCD, 0x27, 0x3C, 0x27,
+  0x27, 0x56, 0xB9, 0x56, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0x56, 0x56, 0x4D, 0x56, 0x56, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0xB9, 0x56, 0x63, 0x63, 0x49, 0x2D, 0x20,
+  0x20, 0x2D, 0xD3, 0x49, 0x66, 0x2D, 0x49, 0x49,
+  0x49, 0x49, 0x49, 0x49, 0x49, 0x8B, 0x2B, 0x20,
+  0x20, 0x20, 0x39, 0x23, 0x6C, 0xAF, 0xCB, 0x23,
+  0x28, 0x28, 0x29, 0x2A, 0x2A, 0x2A, 0x2A, 0x20,
+  0x29, 0x39, 0x2B, 0x2B, 0x2B, 0x25, 0x78, 0xC4,
+  0x63, 0x23, 0x29, 0x39, 0x27, 0x27, 0x3D, 0x27,
+  0x27, 0x56, 0xB9, 0x56, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0x56, 0x56, 0x80, 0x4F, 0x56, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0xB9, 0xB9, 0xB9, 0x2D, 0x49, 0x2D, 0x49,
+  0x49, 0x2D, 0x49, 0x2D, 0x49, 0x2D, 0x2D, 0x2D,
+  0x49, 0x49, 0x35, 0x49, 0x2D, 0x2D, 0x39, 0x28,
+  0x20, 0x20, 0x2A, 0x28, 0x33, 0x60, 0xC4, 0x22,
+  0x2C, 0x2A, 0x2A, 0x22, 0x23, 0x22, 0x20, 0x21,
+  0x2C, 0x29, 0x20, 0x2B, 0x2B, 0x54, 0x30, 0xC4,
+  0x63, 0x22, 0x2C, 0x27, 0x27, 0x27, 0x3D, 0x27,
+  0x27, 0x56, 0x56, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0x56, 0x56, 0x80, 0x56, 0x56, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0xB9, 0xB9, 0xB9, 0x2D, 0x49, 0x2D, 0x49,
+  0x61, 0x49, 0x2D, 0x49, 0x49, 0x2D, 0x2D, 0x49,
+  0x49, 0x49, 0x2F, 0x49, 0x2D, 0x78, 0x29, 0x28,
+  0x2C, 0x2A, 0x2B, 0x39, 0x2B, 0x25, 0x33, 0x20,
+  0x2C, 0x20, 0x2A, 0x24, 0x54, 0x54, 0x23, 0x23,
+  0x2C, 0x2A, 0x22, 0x2B, 0x20, 0x63, 0x30, 0x63,
+  0xC4, 0x21, 0x39, 0x27, 0x27, 0x27, 0x35, 0x36,
+  0x27, 0x56, 0x56, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0xB9, 0x56, 0x80, 0x56, 0x56, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0xB9, 0xB9, 0x56, 0x2D, 0x49, 0x49, 0x49,
+  0x49, 0x27, 0x27, 0x2D, 0x38, 0x27, 0x36, 0x36,
+  0x49, 0x27, 0x49, 0x2D, 0x2D, 0x44, 0x24, 0x2B,
+  0x20, 0x2C, 0x3F, 0x6B, 0x2A, 0x20, 0x21, 0x28,
+  0x2C, 0x20, 0x2B, 0x24, 0x30, 0xCB, 0x63, 0x54,
+  0x28, 0x20, 0x24, 0x2B, 0x23, 0x78, 0xC4, 0x63,
+  0x63, 0x2B, 0x3F, 0x27, 0x27, 0x27, 0x38, 0x33,
+  0x3D, 0xB9, 0x56, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0xB9, 0x56, 0x80, 0x56, 0x56, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0xB9, 0xB9, 0x56, 0x63, 0x49, 0x49, 0x49,
+  0x49, 0x49, 0x3D, 0x3D, 0x27, 0x27, 0x27, 0x2D,
+  0x49, 0x49, 0x49, 0x2D, 0x62, 0x5F, 0xC4, 0x20,
+  0x22, 0x2A, 0x6B, 0x8B, 0x2C, 0x2B, 0x2A, 0x3F,
+  0x3F, 0x2A, 0x21, 0x21, 0xCB, 0x58, 0x6C, 0x60,
+  0x20, 0x23, 0x24, 0x2A, 0x25, 0x78, 0x63, 0x63,
+  0x54, 0x2A, 0x28, 0x27, 0x27, 0x27, 0x27, 0x62,
+  0x3C, 0xB9, 0x56, 0x56, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0x56, 0x56, 0x80, 0x56, 0x56, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0x49, 0x2D, 0x2D,
+  0x2D, 0x3D, 0x2F, 0x3C, 0x2D, 0x3C, 0x27, 0x38,
+  0x2D, 0x49, 0x2D, 0x2D, 0xD1, 0x43, 0x30, 0x20,
+  0x24, 0x21, 0x21, 0x21, 0x2B, 0x2A, 0x29, 0x8B,
+  0x6B, 0x29, 0x2B, 0x2A, 0x30, 0x55, 0x55, 0x34,
+  0x22, 0x23, 0x24, 0x29, 0x54, 0x30, 0x63, 0x63,
+  0x25, 0x29, 0x22, 0x3C, 0xA5, 0xD4, 0xD5, 0x27,
+  0x31, 0x56, 0x56, 0x56, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0x56, 0x56, 0x80, 0xB9, 0x56, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0x56, 0x2D, 0x2E,
+  0x3E, 0x27, 0x27, 0x27, 0x27, 0x27, 0x36, 0x44,
+  0x3C, 0x27, 0x2D, 0xC4, 0x78, 0xCC, 0x54, 0x2B,
+  0x25, 0x24, 0x63, 0x60, 0x63, 0x24, 0x2A, 0x6B,
+  0x3F, 0x39, 0x28, 0x21, 0x33, 0xB6, 0x44, 0x58,
+  0x22, 0x23, 0x24, 0x2A, 0x30, 0x30, 0x63, 0x63,
+  0x24, 0x39, 0x22, 0xBB, 0x9C, 0xB2, 0x9D, 0xA8,
+  0x27, 0x8B, 0x56, 0x56, 0xB9, 0x56, 0xB9, 0xB9,
+  0x56, 0xB9, 0x56, 0x80, 0xB9, 0x56, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0xB9, 0xB9, 0x56, 0x56, 0xD6, 0xD6, 0xD7,
+  0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x32,
+  0x3D, 0x27, 0x39, 0x33, 0xC4, 0xC4, 0x22, 0x28,
+  0x25, 0x54, 0x30, 0xD1, 0xD1, 0x60, 0x23, 0x6B,
+  0x3F, 0x39, 0x2C, 0x2B, 0x20, 0x58, 0x8A, 0x58,
+  0x22, 0x23, 0x23, 0x2B, 0x78, 0x30, 0xC4, 0xC4,
+  0x23, 0x29, 0xBB, 0xBB, 0xD8, 0xB2, 0x9D, 0xA9,
+  0xA9, 0x3C, 0x60, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9,
+  0x56, 0xB9, 0x56, 0x80, 0xB9, 0x56, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0xB9, 0xB9, 0x56, 0xD9, 0x85, 0x85, 0x85,
+  0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x2D,
+  0xA0, 0x83, 0x2C, 0x21, 0x30, 0x33, 0x29, 0x29,
+  0x21, 0x33, 0x54, 0x42, 0x66, 0x55, 0xC4, 0x29,
+  0x8B, 0x2C, 0x39, 0x28, 0x29, 0x31, 0x44, 0x58,
+  0x23, 0x23, 0x21, 0x20, 0x30, 0xC4, 0xC4, 0x30,
+  0x21, 0x20, 0xBB, 0xBC, 0xDA, 0xDB, 0xDC, 0xB2,
+  0x83, 0xB4, 0x3C, 0x2F, 0xB9, 0x56, 0x56, 0xB9,
+  0x56, 0xB9, 0x56, 0x80, 0x56, 0x56, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0x56, 0x56, 0x56, 0xA7, 0xD4, 0x85, 0x82,
+  0x3C, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x61,
+  0x9E, 0x90, 0xDD, 0x21, 0x33, 0x25, 0x2C, 0x39,
+  0x2A, 0x24, 0x24, 0x42, 0x62, 0x43, 0x34, 0x22,
+  0x50, 0x39, 0x2C, 0x2C, 0x2A, 0x54, 0xD1, 0x58,
+  0x22, 0x22, 0x2B, 0x22, 0x30, 0xC4, 0x30, 0x60,
+  0x20, 0xDE, 0xBB, 0xD9, 0x84, 0x84, 0xDF, 0xA9,
+  0xDB, 0xDB, 0x61, 0x27, 0x38, 0x4D, 0x56, 0x56,
+  0x56, 0xB9, 0x56, 0xB9, 0x56, 0x56, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0x56, 0x56, 0x56, 0x8D, 0xD9, 0xD5, 0xA6,
+  0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0xBB,
+  0x85, 0xDB, 0xDD, 0x21, 0x22, 0x22, 0x3F, 0x39,
+  0x2C, 0x2B, 0x25, 0x34, 0x62, 0x66, 0xD1, 0xC4,
+  0x6B, 0x39, 0x2C, 0x39, 0x29, 0x21, 0x58, 0xCC,
+  0x22, 0x21, 0x29, 0x23, 0x30, 0x30, 0x30, 0x5E,
+  0x82, 0xBB, 0xE0, 0xB1, 0xE1, 0x9C, 0xD4, 0xDC,
+  0x9D, 0xA9, 0xE2, 0x27, 0x27, 0x27, 0x4D, 0x56,
+  0x56, 0xB9, 0x56, 0xB9, 0x56, 0x56, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0x56, 0x4C, 0x48, 0xA8, 0xA8, 0xE3, 0x8C,
+  0xC6, 0x3C, 0x27, 0x27, 0x27, 0xE4, 0xA6, 0xE5,
+  0x83, 0xA9, 0xE6, 0xAF, 0x54, 0x2B, 0x8B, 0x39,
+  0x39, 0x29, 0x20, 0x54, 0x42, 0x42, 0xB6, 0xCC,
+  0x2A, 0x29, 0x39, 0x39, 0x2C, 0x2C, 0xCC, 0xCC,
+  0x22, 0x20, 0x39, 0xE7, 0xC0, 0xD9, 0xA7, 0xBC,
+  0x8D, 0xAA, 0x9C, 0xE8, 0x9C, 0x9D, 0xD4, 0xD4,
+  0xD8, 0xA9, 0x84, 0xC7, 0x27, 0x27, 0x27, 0x2A,
+  0x56, 0x56, 0x56, 0xB9, 0x56, 0x56, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0x56, 0x56, 0x48, 0x50, 0xAA, 0xE3, 0xE3, 0xC0,
+  0xA6, 0x9A, 0xBA, 0xC8, 0x9A, 0xDE, 0x9B, 0xD5,
+  0xE8, 0xD8, 0xD5, 0x2E, 0x58, 0x33, 0x6B, 0x39,
+  0x2C, 0x39, 0x29, 0x28, 0xD1, 0x43, 0xB6, 0xAF,
+  0x23, 0x28, 0x2C, 0x39, 0x39, 0x8B, 0x30, 0x31,
+  0x21, 0x20, 0x3F, 0xBB, 0xDF, 0xDF, 0xD5, 0xA8,
+  0xD5, 0x9C, 0x8E, 0xB2, 0x9D, 0xE9, 0xD4, 0xD8,
+  0x90, 0xB2, 0xA9, 0x8F, 0x27, 0x27, 0x27, 0x27,
+  0x2F, 0x56, 0x56, 0xB9, 0x56, 0x56, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0x56, 0xB9, 0x48, 0x48, 0x75, 0xE3, 0xAA, 0xAA,
+  0xC0, 0xB4, 0xB4, 0xB4, 0x75, 0x9B, 0xD9, 0x83,
+  0x9D, 0x90, 0xDF, 0xDD, 0x8A, 0x31, 0x4B, 0x2C,
+  0x2C, 0x29, 0x2C, 0x3F, 0x6C, 0x55, 0xD1, 0x55,
+  0x54, 0x29, 0x28, 0x39, 0x39, 0x6B, 0x24, 0x60,
+  0x20, 0x2B, 0x3F, 0xA7, 0xB1, 0x9D, 0xA9, 0x8E,
+  0xE5, 0xE5, 0xDF, 0xE0, 0xA9, 0x9D, 0xDF, 0xDF,
+  0xEA, 0x9D, 0xB2, 0x84, 0xAA, 0x27, 0x27, 0x27,
+  0x27, 0x35, 0x56, 0x56, 0x56, 0x56, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0xB9, 0x48, 0x48, 0xA6, 0x9B, 0xE3, 0xAA,
+  0xAA, 0x9B, 0x9B, 0x9B, 0xAA, 0xE3, 0xD5, 0xD4,
+  0x9D, 0xA9, 0xA9, 0x9D, 0xEB, 0xAF, 0x23, 0x28,
+  0x2C, 0x29, 0x28, 0x39, 0x54, 0xCC, 0xAF, 0x55,
+  0x30, 0x29, 0x2B, 0x2C, 0x39, 0x39, 0x2B, 0xC4,
+  0x2B, 0x29, 0x39, 0xA7, 0x8E, 0x9D, 0x83, 0xE5,
+  0xB1, 0xDB, 0xDC, 0xE0, 0xDC, 0x84, 0xE9, 0x84,
+  0x83, 0xD4, 0xEC, 0x83, 0x8F, 0xE4, 0x27, 0x27,
+  0x27, 0x27, 0x56, 0x56, 0x56, 0x56, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0x56, 0x40, 0x50, 0x9A, 0x75, 0xE3, 0xE3,
+  0xE3, 0xD9, 0x8D, 0xAA, 0xD9, 0xA8, 0xB2, 0xDC,
+  0xB2, 0x8D, 0x84, 0xEA, 0xB1, 0xEB, 0x54, 0x29,
+  0x28, 0x2C, 0x2A, 0x28, 0x2B, 0x78, 0xCC, 0x58,
+  0xCB, 0x20, 0x20, 0x29, 0x39, 0x39, 0x2C, 0x25,
+  0x29, 0x2C, 0x39, 0xBB, 0xD9, 0xD9, 0x9D, 0x9D,
+  0xB2, 0xB1, 0xD4, 0xDB, 0xB1, 0x9D, 0xD4, 0xEA,
+  0xB1, 0x8D, 0xD8, 0x8E, 0x8F, 0xAA, 0x27, 0x27,
+  0x27, 0x3D, 0x56, 0xB9, 0x56, 0xB9, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0x56, 0x56, 0x47, 0xE4, 0xA6, 0x75, 0xAA, 0xA8,
+  0x9C, 0x9C, 0xE1, 0x9C, 0x9C, 0x8E, 0xD8, 0x9D,
+  0xA9, 0xDB, 0xA9, 0xDC, 0xD8, 0xDA, 0xD4, 0x2B,
+  0x20, 0x2C, 0x28, 0x2A, 0x28, 0x63, 0x31, 0x58,
+  0xCB, 0x24, 0x20, 0x2B, 0x2C, 0x39, 0x6B, 0x21,
+  0x39, 0x6B, 0x2C, 0xC0, 0xE0, 0xB1, 0xB2, 0x9D,
+  0x8E, 0xD8, 0xE0, 0xD9, 0x84, 0xDB, 0xD8, 0xB1,
+  0x8E, 0xB2, 0xE2, 0x9C, 0x83, 0x9E, 0xBC, 0x3D,
+  0xD3, 0x56, 0x56, 0xB9, 0x56, 0xB9, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0xB9,
+  0x56, 0x4F, 0x27, 0x61, 0xA6, 0x9B, 0xE3, 0xA9,
+  0xE9, 0xD4, 0xDA, 0xDB, 0x8E, 0xE1, 0xE9, 0x8E,
+  0xD4, 0xA8, 0xE0, 0x84, 0xE8, 0xB1, 0xDC, 0x9D,
+  0x20, 0x29, 0x29, 0x2B, 0x2C, 0x54, 0x78, 0xCC,
+  0x78, 0x33, 0x2A, 0x20, 0x29, 0x39, 0x50, 0x2A,
+  0x6B, 0x8B, 0x39, 0xC0, 0x8D, 0xB1, 0xE9, 0xA9,
+  0xB2, 0xDC, 0x8E, 0xDC, 0xE1, 0xDA, 0xA9, 0x8E,
+  0xEA, 0xE2, 0x83, 0xE8, 0x8E, 0x83, 0xE2, 0xED,
+  0xB9, 0xB9, 0x56, 0xB9, 0x56, 0xB9, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0x56, 0x56, 0xB9,
+  0xC9, 0x27, 0x27, 0xE4, 0xA6, 0x9B, 0xD5, 0xA8,
+  0xD4, 0xB2, 0xD8, 0xDA, 0xD9, 0xE8, 0xE9, 0xE8,
+  0xD8, 0xB1, 0xDA, 0xB2, 0xE9, 0x8E, 0xEC, 0xDA,
+  0x22, 0x20, 0x39, 0x2B, 0x39, 0x24, 0xC4, 0x30,
+  0x30, 0x54, 0x22, 0x29, 0x29, 0x39, 0x48, 0x2C,
+  0x39, 0x6B, 0x39, 0xC0, 0x8D, 0xB1, 0xE9, 0xB2,
+  0xB2, 0x8E, 0xA9, 0xD8, 0xDA, 0xB1, 0xA9, 0xDA,
+  0x9C, 0xDC, 0x8E, 0xD4, 0xE8, 0xE8, 0x8F, 0x9B,
+  0x4F, 0xB9, 0x56, 0xB9, 0x56, 0xB9, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0x56, 0x4F, 0x6B,
+  0x27, 0x27, 0x27, 0xD7, 0xDE, 0xAA, 0xE3, 0xA8,
+  0xB2, 0xD5, 0xE5, 0x90, 0xE2, 0xA9, 0xE9, 0xB2,
+  0xDA, 0xB2, 0xE1, 0xB2, 0xE9, 0x8E, 0xDA, 0xDF,
+  0x78, 0x2A, 0x2C, 0x2A, 0x6B, 0x28, 0x23, 0x54,
+  0x63, 0xC4, 0x33, 0x28, 0x2C, 0x39, 0x47, 0x39,
+  0x28, 0x2C, 0x29, 0xBB, 0x8D, 0x83, 0xE9, 0xD4,
+  0xB2, 0xE9, 0xE9, 0xE8, 0xD4, 0xD8, 0xD4, 0xA9,
+  0xDA, 0xB2, 0xE9, 0xA8, 0xB2, 0xA8, 0xD5, 0xAA,
+  0xC6, 0x56, 0x56, 0x56, 0x56, 0x56, 0xB9, 0x56,
+  0x56, 0x56, 0x56, 0x56, 0x56, 0xC9, 0x27, 0x27,
+  0x27, 0x27, 0x27, 0xB8, 0xB4, 0x9B, 0xE3, 0x8E,
+  0x9D, 0x8E, 0xB2, 0xE8, 0xE8, 0x8E, 0xB2, 0xDA,
+  0xB2, 0x8E, 0xEC, 0xB2, 0x8E, 0xB2, 0xBB, 0x58,
+  0xAF, 0x33, 0x50, 0x39, 0x6B, 0x39, 0x29, 0x20,
+  0x33, 0x30, 0x78, 0x23, 0x6B, 0x6B, 0x48, 0x6B,
+  0x2B, 0x2A, 0x29, 0xBB, 0xE5, 0x9C, 0xB1, 0xB2,
+  0xE5, 0x84, 0x8E, 0x9C, 0x84, 0xB2, 0xB2, 0x9D,
+  0x84, 0xDF, 0xA9, 0x84, 0x8E, 0xA8, 0xE3, 0x9B,
+  0xA6, 0xD7, 0x80, 0x4F, 0x56, 0x56, 0x56, 0x4F,
+  0x4F, 0x4F, 0x4F, 0x2A, 0x2D, 0x27, 0x27, 0x27,
+  0x27, 0x27, 0x27, 0xB8, 0xB4, 0xAA, 0xD5, 0xA9,
+  0x9D, 0xB2, 0x90, 0xEA, 0xE9, 0xE2, 0xE1, 0x8E,
+  0xB2, 0x9D, 0x8E, 0xB1, 0xA7, 0xEE, 0x63, 0xD1,
+  0x2E, 0xCC, 0x28, 0x48, 0x8B, 0x47, 0x6B, 0x28,
+  0x23, 0x78, 0x6C, 0x54, 0x29, 0x50, 0x50, 0x6B,
+  0x23, 0x20, 0xBB, 0xBC, 0xBB, 0x8D, 0xE3, 0xDF,
+  0x9C, 0xA9, 0x8D, 0xA8, 0xD9, 0x90, 0x9D, 0xA9,
+  0xDC, 0xA9, 0x83, 0xB2, 0xA9, 0xD4, 0xE3, 0x9B,
+  0x8C, 0xEF, 0x27, 0x27, 0x27, 0x3C, 0x27, 0x27,
+  0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27,
+  0x27, 0x27, 0x27, 0xF0, 0xB4, 0x9B, 0xE3, 0x84,
+  0x9D, 0x84, 0x90, 0xB1, 0xA9, 0x9C, 0xD9, 0xB1,
+  0xB2, 0xEA, 0xBB, 0x51, 0x24, 0x30, 0x30, 0x42,
+  0x66, 0x58, 0x24, 0x48, 0x50, 0x3F, 0x20, 0x25,
+  0x22, 0x60, 0x34, 0x30, 0x20, 0x8B, 0x8B, 0x39,
+  0x54, 0x24, 0x2B, 0xC0, 0xC0, 0xC0, 0xBB, 0x9B,
+  0xBC, 0xAA, 0xAA, 0xE3, 0xE3, 0x9C, 0xB2, 0xD4,
+  0x83, 0xD8, 0xE8, 0x83, 0x84, 0xE8, 0xE5, 0x75,
+  0x9A, 0xF0, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27,
+  0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27,
+  0x27, 0x27, 0x27, 0xF0, 0xB4, 0x9B, 0xE3, 0xA8,
+  0xA9, 0xD8, 0x8E, 0xEA, 0xA8, 0x9C, 0xD9, 0xE0,
+  0xC0, 0x5E, 0x2C, 0x20, 0x54, 0x60, 0x30, 0x66,
+  0xB6, 0xCC, 0x63, 0x3F, 0x8B, 0x28, 0x22, 0x33,
+  0x23, 0x31, 0xAF, 0x31, 0x22, 0x6B, 0x6B, 0x29,
+  0x30, 0x54, 0x22, 0x89, 0xBA, 0xED, 0xA6, 0x8C,
+  0xB4, 0xC0, 0xB4, 0x75, 0x75, 0x9B, 0x9B, 0xE5,
+  0xA9, 0xD5, 0x8E, 0x8E, 0x9C, 0xE3, 0x75, 0x8C,
+  0xC8, 0xF1, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27,
+  0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27,
+  0x27, 0x27, 0x27, 0xF1, 0x9A, 0xB4, 0x9B, 0xE3,
+  0xE3, 0xA8, 0xE3, 0xE5, 0xAA, 0xBC, 0xC0, 0x9A,
+  0x26, 0x29, 0x20, 0x24, 0x63, 0x60, 0x54, 0x43,
+  0x34, 0xCB, 0x30, 0x39, 0x2C, 0x20, 0x24, 0x54,
+  0x22, 0x34, 0x34, 0x31, 0x24, 0x3F, 0x2C, 0x2B,
+  0x31, 0x30, 0x25, 0x2A, 0x6B, 0x29, 0x20, 0xF2,
+  0xBA, 0xBF, 0xC8, 0x9A, 0xA6, 0xA6, 0x8C, 0xB4,
+  0x9B, 0xAA, 0xAA, 0xAA, 0x9B, 0x75, 0xDE, 0xBF,
+  0x81, 0xEF, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27,
+  0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27,
+  0x27, 0x27, 0x27, 0xEF, 0xBA, 0x9A, 0xB4, 0x75,
+  0x9B, 0x9B, 0x9B, 0xC0, 0xB4, 0x9A, 0xA5, 0xC4,
+  0x30, 0x28, 0x22, 0x33, 0x30, 0x30, 0x23, 0x34,
+  0x31, 0x30, 0xC4, 0x2C, 0x2B, 0x22, 0x33, 0x63,
+  0x21, 0x58, 0x6C, 0x60, 0x25, 0x39, 0x28, 0x2B,
+  0xCC, 0x6C, 0x63, 0x20, 0x6B, 0x28, 0x2B, 0x20,
+  0x63, 0x43, 0xF3, 0xEF, 0xF0, 0x81, 0xBA, 0xF4,
+  0xF4, 0xA6, 0xDE, 0x8C, 0xA6, 0x9A, 0xBA, 0x81,
+  0xB0, 0xE4, 0xA1, 0x20, 0x20, 0x23, 0x31, 0xC4,
+  0x30, 0x24, 0x33, 0x31, 0x31, 0x60, 0x43, 0x35,
+  0x35, 0x55, 0x6C, 0xEF, 0x81, 0xC8, 0x9A, 0xA6,
+  0xB4, 0xB4, 0x8C, 0xA6, 0xBA, 0x68, 0x30, 0x30,
+  0x30, 0x2B, 0x25, 0x54, 0xC4, 0x54, 0x24, 0x78,
+  0x63, 0x63, 0x30, 0x29, 0x21, 0x24, 0x54, 0x63,
+  0x23, 0x34, 0xCB, 0x30, 0x25, 0x39, 0x20, 0x20,
+  0x58, 0x34, 0x60, 0x23, 0x6B, 0x29, 0x28, 0x20,
+  0x22, 0xB6, 0x42, 0xB6, 0x58, 0x54, 0xF5, 0xD7,
+  0xA5, 0xBA, 0xBA, 0xBA, 0xBA, 0x81, 0xA5, 0xF1,
+  0xE4, 0x2A, 0x39, 0x20, 0x20, 0x20, 0x31, 0x60,
+  0x54, 0x28, 0x2B, 0x22, 0x33, 0x30, 0x43, 0x35,
+  0x66, 0xD1, 0x34, 0xE4, 0xEF, 0x81, 0xC8, 0x9A,
+  0x9A, 0xC8, 0xC8, 0x81, 0xF6, 0x31, 0x63, 0x31,
+  0x78, 0x2B, 0x54, 0x63, 0x54, 0x24, 0x23, 0x54,
+  0x63, 0x54, 0x63, 0x2C, 0x23, 0x33, 0x63, 0x54,
+  0x25, 0x31, 0x78, 0x30, 0x25, 0x3F, 0x20, 0x20,
+  0xAF, 0x58, 0xCC, 0x33, 0x39, 0x29, 0x29, 0x2A,
+  0x29, 0x58, 0x43, 0x42, 0xD1, 0xCB, 0x2C, 0x2C,
+  0x37, 0xCD, 0xEF, 0xB0, 0xF0, 0xB0, 0xEF, 0xE4,
+  0x63, 0x20, 0x20, 0x2C, 0x2C, 0x21, 0xCB, 0x78,
+  0x54, 0x39, 0x39, 0x28, 0x2B, 0x28, 0x2B, 0xCB,
+  0x55, 0xB6, 0xD1, 0x28, 0xE4, 0xD7, 0xB8, 0xF0,
+  0xA5, 0xB0, 0xEF, 0x26, 0x23, 0x54, 0x31, 0x58,
+  0xCB, 0x20, 0x63, 0x63, 0x25, 0x2B, 0x54, 0x78,
+  0x30, 0x63, 0x54, 0x28, 0x33, 0x63, 0x63, 0x33,
+  0x54, 0x78, 0xC4, 0x30, 0x24, 0x2C, 0x22, 0x22,
+  0x55, 0x55, 0x34, 0x30, 0x28, 0x2C, 0x29, 0x29,
+  0x28, 0x30, 0xB6, 0x42, 0x43, 0x55, 0x22, 0x29,
+  0x2C, 0x2B, 0x2B, 0x3F, 0xE4, 0xE4, 0x43, 0x66,
+  0x30, 0x23, 0x24, 0x2A, 0x28, 0x2B, 0x54, 0x63,
+  0x33, 0x39, 0x28, 0x20, 0x20, 0x20, 0x2B, 0x31,
+  0x30, 0xD1, 0x43, 0x30, 0x39, 0x28, 0xE4, 0xE4,
+  0xD7, 0xF5, 0x2B, 0x6B, 0x20, 0x30, 0x34, 0xD1,
+  0x60, 0x23, 0x63, 0x54, 0x22, 0x47, 0x60, 0xCB,
+  0xC4, 0xC4, 0x25, 0x22, 0x54, 0xC4, 0x63, 0x23,
+  0xC4, 0xC4, 0x63, 0xC4, 0x23, 0x2A, 0x24, 0x22,
+  0x55, 0x55, 0xAF, 0x6C, 0x22, 0x39, 0x2C, 0x39,
+  0x28, 0x23, 0xD1, 0x43, 0x42, 0x8A, 0x63, 0x39,
+  0x39, 0x2A, 0x20, 0x6B, 0x33, 0xCC, 0xD1, 0xB6,
+  0x30, 0x24, 0x54, 0x63, 0x31, 0xCC, 0xCC, 0xCB,
+  0xC4, 0x2A, 0x39, 0x20, 0x20, 0x20, 0x39, 0x30,
+  0x30, 0x6C, 0x43, 0x43, 0x6C, 0x63, 0x25, 0x24,
+  0x63, 0x63, 0x63, 0x25, 0x63, 0xCC, 0xD1, 0x34,
+  0x63, 0x25, 0x54, 0x25, 0x2A, 0x28, 0x31, 0xCB,
+  0x63, 0x78, 0x24, 0x33, 0xC4, 0xC4, 0x33, 0x2C,
+  0xC4, 0x54, 0x54, 0x30, 0x21, 0x22, 0x25, 0x23,
+  0x55, 0x55, 0xD1, 0x58, 0x33, 0x6B, 0x2C, 0x39,
+  0x39, 0x39, 0x34, 0x43, 0x42, 0x43, 0xCC, 0x2B,
+  0x28, 0x29, 0x20, 0x28, 0x21, 0x30, 0xCC, 0xAF,
+  0x54, 0x23, 0xC4, 0x54, 0x58, 0x2E, 0x35, 0x42,
+  0x55, 0x54, 0x8B, 0x2A, 0x20, 0x20, 0x28, 0x22,
+  0x78, 0x30, 0xD1, 0x43, 0x44, 0x6C, 0xC4, 0xC4,
+  0x60, 0x31, 0x31, 0x63, 0x6C, 0xAF, 0xCC, 0xCB,
+  0x24, 0x25, 0x33, 0x23, 0x2C, 0x24, 0x31, 0x30,
+  0x63, 0xC4, 0x21, 0x54, 0x30, 0x63, 0x24, 0x2A,
+  0x54, 0x63, 0x54, 0xC4, 0x2B, 0x24, 0x33, 0x24,
+  0x34, 0x55, 0xD1, 0x55, 0x30, 0x28, 0x29, 0x39,
+  0x39, 0x8B, 0x63, 0x55, 0x42, 0x66, 0xB6, 0x25,
+  0x29, 0x29, 0x29, 0x28, 0x2A, 0x54, 0x78, 0x6C,
+  0x23, 0x20, 0x25, 0x30, 0xCB, 0x62, 0x35, 0x35,
+  0x35, 0x44, 0x24, 0x6B, 0x29, 0x20, 0x2A, 0x39,
+  0x28, 0x63, 0x34, 0xB6, 0x34, 0xCB, 0x63, 0x30,
+  0x31, 0x31, 0x30, 0x30, 0xCC, 0x60, 0x63, 0xC4,
+  0x20, 0x33, 0x25, 0x20, 0x48, 0x33, 0x30, 0x54,
+  0x78, 0x54, 0x2B, 0x63, 0x30, 0x63, 0x23, 0x22,
+  0x63, 0x63, 0x63, 0x33, 0x28, 0x25, 0x54, 0x24,
+  0x78, 0xAF, 0xD1, 0xD1, 0xCC, 0x22, 0x39, 0x39,
+  0x2C, 0x3F, 0x2B, 0x34, 0xB6, 0x43, 0x43, 0xC4,
+  0x2B, 0x28, 0x39, 0x50, 0x2C, 0x24, 0x63, 0x78,
+  0x21, 0x2C, 0x2A, 0x23, 0x54, 0xD1, 0x35, 0x35,
+  0x35, 0x35, 0x55, 0x22, 0x39, 0x2C, 0x2C, 0x2C,
+  0x20, 0x30, 0xCC, 0x6C, 0xCB, 0x30, 0x54, 0x30,
+  0x78, 0x63, 0x78, 0x30, 0x54, 0x78, 0x30, 0x23,
+  0x2B, 0x33, 0x24, 0x28, 0x39, 0x24, 0x54, 0x30,
+  0x78, 0x33, 0x25, 0xC4, 0xC4, 0x33, 0x39, 0x25,
+  0xC4, 0x63, 0xC4, 0x24, 0x20, 0x54, 0x54, 0x25,
+  0x63, 0xCC, 0xD1, 0xB6, 0x55, 0x54, 0x39, 0x29,
+  0x39, 0x2C, 0x6B, 0x30, 0xAF, 0xB6, 0xB6, 0x60,
+  0x22, 0x2A, 0x2C, 0x39, 0x2C, 0x21, 0x54, 0x63,
+  0x21, 0x50, 0x2C, 0x2C, 0x2B, 0x25, 0x62, 0x35,
+  0x35, 0x35, 0x35, 0xCC, 0x2B, 0x29, 0x2B, 0x20,
+  0x23, 0x25, 0xC4, 0x30, 0xC4, 0x63, 0x63, 0x63,
+  0x63, 0x33, 0x24, 0x31, 0x31, 0x31, 0x54, 0x28,
+  0x24, 0x25, 0x22, 0x6B, 0x28, 0x24, 0xC4, 0x78,
+  0x30, 0x24, 0x63, 0xC4, 0x54, 0x23, 0x29, 0x63,
+  0xC4, 0x54, 0xC4, 0x21, 0x24, 0x54, 0x54, 0x25,
+  0x30, 0xCB, 0xD1, 0xB6, 0x55, 0x63, 0x28, 0x29,
+  0x39, 0x39, 0x48, 0x33, 0x58, 0x44, 0xB6, 0x60,
+  0x24, 0x20, 0x2B, 0x28, 0x2A, 0x22, 0x54, 0x63,
+  0x21, 0x48, 0x2A, 0x2B, 0x39, 0x21, 0xB6, 0x35,
+  0x35, 0x35, 0x35, 0x42, 0x23, 0x29, 0x2A, 0x2B,
+  0x23, 0x25, 0x54, 0x54, 0x54, 0x63, 0x63, 0x30,
+  0x25, 0x2B, 0x31, 0x31, 0x31, 0x31, 0x21, 0x2C,
+  0x33, 0x25, 0x21, 0x39, 0x20, 0x25, 0x30, 0x78,
+  0xC4, 0x23, 0xC4, 0x30, 0x54, 0x20, 0x28, 0x63,
+  0x63, 0x63, 0x63, 0x20, 0x25, 0x54, 0x54, 0x20,
+};
+
+unsigned char linux_logo_bw[] __initdata = {
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x3F,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F,
+  0xFE, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xFE, 0x3F, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xFE, 0x7F, 0xFF, 0xC7, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xC3,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF,
+  0xFB, 0xE3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xFD, 0xFF, 0xFF, 0xE1, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xF1,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xFF,
+  0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xF9, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xF9, 0xCF, 0xC3, 0xF8, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x87, 0x81, 0xF9,
+  0xF8, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xA7,
+  0x99, 0xF9, 0xC2, 0x40, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xF9, 0xF3, 0xBC, 0xF9, 0x90, 0x00, 0x1F, 0xFF,
+  0xFF, 0xFF, 0xF9, 0xE3, 0xBC, 0xF9, 0xA0, 0x00,
+  0x8F, 0xFF, 0xFF, 0xFF, 0xF9, 0xB0, 0x3C, 0xF9,
+  0x83, 0xE0, 0x2F, 0xFF, 0xFF, 0xFF, 0xF9, 0xB0,
+  0x19, 0xF0, 0x1F, 0xFE, 0x0F, 0xFF, 0xFF, 0xFF,
+  0xF9, 0xC0, 0x03, 0xF0, 0x3F, 0xF7, 0x8F, 0xFF,
+  0xFF, 0xFF, 0xF9, 0x80, 0x01, 0xF8, 0x7F, 0xF7,
+  0xC7, 0xFF, 0xFF, 0xFF, 0xF9, 0x80, 0x01, 0xF8,
+  0x6F, 0xF7, 0xE7, 0xFF, 0xFF, 0xFF, 0xF9, 0x80,
+  0x01, 0xF8, 0x7F, 0xF7, 0xE7, 0xFF, 0xFF, 0xFF,
+  0xF9, 0xC0, 0x21, 0xD8, 0x7F, 0xE7, 0xEF, 0xFF,
+  0xFF, 0xFF, 0xF9, 0xB1, 0x80, 0xEC, 0x7B, 0xFF,
+  0xEF, 0xFF, 0xFF, 0xFF, 0xF1, 0x90, 0x00, 0xE4,
+  0x7B, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xF1, 0x8C,
+  0xC0, 0x7C, 0x79, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF,
+  0xE3, 0x80, 0x00, 0x7C, 0x7C, 0xFF, 0xCF, 0xFF,
+  0xFF, 0xFF, 0xE3, 0x80, 0x00, 0x7F, 0x77, 0xFF,
+  0xDF, 0xFF, 0xFF, 0xFF, 0x87, 0x00, 0x00, 0x3F,
+  0x3F, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0x0E, 0x00,
+  0x00, 0x3F, 0xBF, 0xFF, 0x9F, 0xFF, 0xFF, 0xFF,
+  0x1E, 0x00, 0x00, 0x1F, 0x9F, 0xFF, 0x3F, 0xFF,
+  0xFF, 0xFE, 0x1C, 0x00, 0x00, 0x1F, 0x9F, 0xFF,
+  0x7F, 0xFF, 0xFF, 0xFE, 0x3C, 0x00, 0x00, 0x1F,
+  0x8F, 0xFE, 0x7F, 0xFF, 0xFF, 0xFC, 0x7C, 0x00,
+  0x00, 0x0F, 0xC7, 0xFC, 0xFF, 0xFF, 0xFF, 0xFC,
+  0xF8, 0x00, 0x00, 0x0F, 0xF7, 0xF9, 0xFF, 0xFF,
+  0xFF, 0xFC, 0xF8, 0x00, 0x00, 0x07, 0xFB, 0xF3,
+  0xFF, 0xFF, 0xFF, 0xF8, 0xF8, 0x00, 0x00, 0x07,
+  0xFD, 0xE7, 0xFF, 0xFF, 0xFF, 0xF9, 0xF0, 0x00,
+  0x00, 0x03, 0xFE, 0x8F, 0xFF, 0xFF, 0xFF, 0xF1,
+  0xF0, 0x00, 0x00, 0x03, 0xFE, 0x1F, 0xFF, 0xFF,
+  0xFF, 0xF1, 0xE0, 0x00, 0x00, 0x00, 0xFF, 0xBF,
+  0xFF, 0xFF, 0xFF, 0xE3, 0xE0, 0x00, 0x00, 0x00,
+  0xFE, 0xBF, 0xFF, 0xFF, 0xFF, 0xE3, 0xC0, 0x00,
+  0x00, 0x00, 0xFE, 0x3F, 0xFF, 0xFF, 0xFF, 0xC7,
+  0xC0, 0x00, 0x00, 0x01, 0xFE, 0xBF, 0xFF, 0xFF,
+  0xFF, 0xC7, 0x80, 0x00, 0x00, 0x01, 0xFE, 0x9F,
+  0xFF, 0xFF, 0xFF, 0x8F, 0x80, 0x00, 0x00, 0x01,
+  0xFE, 0x07, 0xFF, 0xFF, 0xFF, 0x8F, 0x80, 0x00,
+  0x00, 0x01, 0xFE, 0x87, 0xFF, 0xFF, 0xFF, 0x9F,
+  0x80, 0x00, 0x00, 0x01, 0xFD, 0x33, 0xFF, 0xFF,
+  0xFF, 0x9F, 0x80, 0x00, 0x00, 0x01, 0x80, 0xF3,
+  0xFF, 0xFF, 0xFF, 0x9E, 0x80, 0x00, 0x00, 0x03,
+  0x8B, 0xF9, 0xFF, 0xFF, 0xFF, 0x9F, 0x80, 0x00,
+  0x00, 0x02, 0x27, 0xF8, 0xFF, 0xFF, 0xFF, 0x99,
+  0x80, 0x00, 0x00, 0x00, 0x07, 0xF8, 0xFF, 0xFF,
+  0xFF, 0x00, 0x80, 0x00, 0x00, 0x01, 0x8F, 0xF8,
+  0xFF, 0xFF, 0xFE, 0x20, 0x60, 0x00, 0x00, 0x00,
+  0xE3, 0xF8, 0xFF, 0xFF, 0xF8, 0x00, 0x30, 0x00,
+  0x00, 0x00, 0xF8, 0x78, 0xFF, 0xFF, 0xC0, 0x40,
+  0x38, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x7F, 0xFF,
+  0x81, 0x00, 0x1C, 0x00, 0x00, 0x00, 0xFC, 0x20,
+  0x7F, 0xFF, 0x90, 0x00, 0x1E, 0x00, 0x00, 0x00,
+  0x78, 0x10, 0xFF, 0xFF, 0x80, 0x00, 0x0F, 0x80,
+  0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x80, 0x00,
+  0x07, 0xC0, 0x00, 0x00, 0x00, 0x08, 0xFF, 0xFF,
+  0xC0, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x04,
+  0x7F, 0xFF, 0x80, 0x00, 0x03, 0xC0, 0x00, 0x10,
+  0x00, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x01, 0x80,
+  0x00, 0x30, 0x00, 0x00, 0x0F, 0xFF, 0x80, 0x00,
+  0x00, 0x00, 0x00, 0x70, 0x00, 0x01, 0x4F, 0xFF,
+  0x80, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00,
+  0x0F, 0xFF, 0xC0, 0x00, 0x00, 0x80, 0x03, 0xF0,
+  0x00, 0x00, 0x8F, 0xFF, 0x80, 0x00, 0x00, 0x40,
+  0x0F, 0xF0, 0x00, 0x04, 0x1F, 0xFF, 0x80, 0x00,
+  0x00, 0x7F, 0xFF, 0xF0, 0x00, 0x10, 0x1F, 0xFF,
+  0xC0, 0x00, 0x00, 0x7F, 0xFF, 0xF0, 0x00, 0x40,
+  0xFF, 0xFF, 0x98, 0x00, 0x00, 0xFF, 0xFF, 0xF0,
+  0x00, 0x83, 0xFF, 0xFF, 0x81, 0xE0, 0x01, 0xFF,
+  0xFF, 0xF8, 0x02, 0x07, 0xFF, 0xFF, 0x80, 0x3F,
+  0x07, 0xE0, 0x00, 0x1C, 0x0C, 0x1F, 0xFF, 0xFF,
+  0xF8, 0x03, 0xFF, 0x80, 0x00, 0x1F, 0x78, 0x1F,
+  0xFF, 0xFF, 0xFF, 0x80, 0x7F, 0x00, 0x07, 0x0F,
+  0xF0, 0x7F, 0xFF, 0xFF, 0xFF, 0xFE, 0x0C, 0x07,
+  0xFF, 0x83, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+  0x00, 0x1F, 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x07, 0xFF,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+};
+
+/* Painted by Johnny Stenback <jst@uwasa.fi> */
+
+unsigned char *linux_serial_image __initdata = "\n"
+"         .u$e.\n"
+"       .$$$$$:S\n"
+"       $\"*$/\"*$$\n"
+"       $.`$ . ^F\n"
+"       4k+#+T.$F\n"
+"       4P+++\"$\"$\n"
+"       :R\"+  t$$B\n"
+"    ___#       $$$\n"
+"    |  |       R$$k\n"
+"   dd. | Linux  $!$\n"
+"   ddd |  Sparc $9$F\n"
+" '!!!!!$       !!#!`\n"
+"  !!!!!*     .!!!!!`\n"
+"'!!!!!!!W..e$$!!!!!!`    %s\n"
+" \"~^^~         ^~~^\n"
+"\n";
+/* $Id: linux_logo.h,v 1.1 1997/04/16 17:51:37 jj Exp $
+ * include/asm-sparc64/linux_logo.h: This is a linux logo
+ *                                   to be displayed on boot.
+ *
+ * Copyright (C) 1996 Larry Ewing (lewing@isc.tamu.edu)
+ * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ *
+ * You can put anything here, but:
+ * LINUX_LOGO_COLORS has to be less than 224
+ * image size has to be 80x80
+ * values have to start from 0x20
+ * (i.e. RGB(linux_logo_red[0],
+ *	     linux_logo_green[0],
+ *	     linux_logo_blue[0]) is color 0x20)
+ * BW image has to be 80x80 as well, with MS bit
+ * on the left
+ * Serial_console ascii image can be any size,
+ * but should contain %s to display the version
+ */
+ 
+#include <linux/init.h>
+#include <linux/version.h>
+
+#define linux_logo_banner "Linux/UltraSPARC version " UTS_RELEASE
+
+#define LINUX_LOGO_COLORS 215
+
+unsigned char linux_logo_red[] __initdata = {
+  0x99, 0x95, 0x92, 0x8E, 0x8A, 0x86, 0x02, 0x00,
+  0xA5, 0xA9, 0xA2, 0x9E, 0xAD, 0x1B, 0x3B, 0x25,
+  0x71, 0x65, 0x2C, 0x82, 0x5B, 0x33, 0x13, 0xB0,
+  0x0C, 0xB1, 0xD4, 0xCE, 0x04, 0x06, 0x16, 0xB6,
+  0xCD, 0xB2, 0x42, 0x46, 0x4B, 0xA8, 0xF3, 0xCA,
+  0xC5, 0x1C, 0xDC, 0xA0, 0xD4, 0xE6, 0xED, 0xF3,
+  0xC2, 0x8E, 0xCC, 0xA5, 0x7E, 0x52, 0xF7, 0xE3,
+  0x56, 0x79, 0x68, 0x8D, 0xAF, 0xFC, 0x8E, 0x3E,
+  0x6B, 0x11, 0x37, 0x79, 0x5C, 0x3C, 0x3F, 0x3C,
+  0x48, 0x47, 0x3D, 0xB9, 0x62, 0xE1, 0x4D, 0x57,
+  0x84, 0x78, 0xA6, 0x58, 0x99, 0xCD, 0xB7, 0xE3,
+  0x6D, 0x5A, 0xAF, 0x79, 0x79, 0xF2, 0x42, 0x46,
+  0xDD, 0x89, 0xC3, 0xF2, 0xF0, 0xE0, 0xD1, 0x90,
+  0x76, 0x6B, 0x4A, 0xBE, 0xBD, 0xE3, 0xF6, 0xE9,
+  0xEC, 0xE8, 0xEC, 0xC0, 0x66, 0x63, 0xCB, 0xAB,
+  0x49, 0x5C, 0xAD, 0xD6, 0xEE, 0xF5, 0xF5, 0xE9,
+  0x6E, 0x00, 0x69, 0x6A, 0xA1, 0x7A, 0xB4, 0xDE,
+  0xF1, 0xF6, 0xDD, 0x00, 0x73, 0xDB, 0x4C, 0x53,
+  0x6A, 0xF5, 0xF5, 0xD6, 0xC3, 0x6A, 0x4B, 0x4B,
+  0x60, 0xF8, 0x9B, 0xD7, 0xD7, 0x71, 0xB3, 0xA4,
+  0xCA, 0xAB, 0xB4, 0xB2, 0x76, 0xBA, 0x8B, 0xA0,
+  0xA5, 0xEE, 0xE7, 0x67, 0x5F, 0x08, 0x94, 0xDB,
+  0xE5, 0x4F, 0x00, 0x34, 0xEE, 0xEC, 0xE2, 0x48,
+  0xF3, 0xEB, 0xF4, 0xF4, 0xEF, 0xD6, 0xB6, 0xE6,
+  0xE6, 0xED, 0xE7, 0xE6, 0x3D, 0xE7, 0xCD, 0x44,
+  0xEF, 0xEC, 0xF5, 0x66, 0xF3, 0xA9, 0x77, 0x58,
+  0x75, 0x6C, 0x53, 0x24, 0xAC, 0x0D, 0x3C
+};
+
+unsigned char linux_logo_green[] __initdata = {
+  0x99, 0x95, 0x92, 0x8E, 0x8A, 0x86, 0x02, 0x00,
+  0xA5, 0xA9, 0xA2, 0x9E, 0xAD, 0x1B, 0x3B, 0x25,
+  0x71, 0x65, 0x2C, 0x82, 0x5B, 0x33, 0x13, 0xAD,
+  0x0C, 0xB1, 0x92, 0xAB, 0x03, 0x06, 0x16, 0xB6,
+  0xCD, 0x88, 0x42, 0x46, 0x4B, 0x94, 0xBB, 0xCA,
+  0xC5, 0x1C, 0xAB, 0xA0, 0xD4, 0xE6, 0xED, 0xF3,
+  0xC2, 0x73, 0xCA, 0x91, 0x7E, 0x52, 0xF7, 0xE3,
+  0x56, 0x5A, 0x49, 0x56, 0x6E, 0xFC, 0x6B, 0x3E,
+  0x6B, 0x0D, 0x37, 0x79, 0x51, 0x44, 0x3F, 0x43,
+  0x38, 0x3D, 0x48, 0xB9, 0x62, 0xA5, 0x47, 0x48,
+  0x49, 0x4A, 0x97, 0x48, 0x81, 0x95, 0x8E, 0xE3,
+  0x6D, 0x57, 0x51, 0x51, 0x47, 0xB2, 0x42, 0x46,
+  0xDD, 0x5B, 0x87, 0xBE, 0xC7, 0xC8, 0x56, 0x75,
+  0x5D, 0x4B, 0x4D, 0xBE, 0x85, 0xA6, 0xBC, 0xC7,
+  0xCA, 0xCD, 0xCC, 0xA4, 0x53, 0x4D, 0x9F, 0x55,
+  0x52, 0x5E, 0x75, 0x9C, 0xB6, 0xC3, 0xD7, 0xCC,
+  0x55, 0x00, 0x6A, 0x59, 0x7D, 0x55, 0x7C, 0xA3,
+  0xB7, 0xBF, 0xA5, 0x00, 0x67, 0xC6, 0x47, 0x54,
+  0x46, 0xB8, 0xBE, 0xB2, 0x87, 0x52, 0x4B, 0x43,
+  0x41, 0xF8, 0x69, 0x96, 0x9B, 0x66, 0xB0, 0x6C,
+  0x8E, 0x81, 0xB4, 0x76, 0x76, 0xB9, 0x65, 0x77,
+  0x6D, 0xED, 0xE7, 0x67, 0x5F, 0x06, 0x54, 0x6C,
+  0xCB, 0x4F, 0x00, 0x2F, 0xC2, 0xB5, 0xB6, 0x30,
+  0xC3, 0xAE, 0xC4, 0xCA, 0xC6, 0xB4, 0x7B, 0xAD,
+  0xAD, 0xB6, 0xB6, 0xAD, 0x29, 0xAB, 0x93, 0x2E,
+  0xBC, 0xBC, 0xC9, 0x53, 0xBF, 0x77, 0x54, 0x3B,
+  0x4B, 0x3F, 0x39, 0x19, 0x76, 0x08, 0x2C
+};
+
+unsigned char linux_logo_blue[] __initdata = {
+  0x99, 0x95, 0x92, 0x8E, 0x8A, 0x86, 0xD6, 0x00,
+  0xA5, 0xA9, 0xA2, 0x9E, 0xAD, 0x1B, 0x39, 0x25,
+  0x71, 0x65, 0x2C, 0x82, 0x5B, 0x33, 0x13, 0xA7,
+  0x0C, 0xB1, 0x58, 0x8A, 0x03, 0x07, 0x16, 0xB6,
+  0xCD, 0x5A, 0x42, 0x46, 0x4F, 0x6F, 0x77, 0xCA,
+  0xC5, 0x1C, 0x6F, 0xA5, 0xD4, 0xE6, 0xF5, 0xF3,
+  0xC2, 0x4D, 0xD1, 0x64, 0x7E, 0x52, 0xF7, 0xE3,
+  0x56, 0x49, 0x3C, 0x47, 0x45, 0xFE, 0x3B, 0x41,
+  0x6B, 0x09, 0x37, 0x79, 0x39, 0x39, 0x3F, 0x42,
+  0x3A, 0x42, 0x5F, 0xB9, 0x62, 0x4C, 0x39, 0x44,
+  0x3B, 0x3A, 0xA0, 0x3D, 0x08, 0x08, 0x09, 0xDE,
+  0x6D, 0x48, 0x3B, 0x3F, 0x42, 0xF3, 0x36, 0x3C,
+  0xDD, 0x06, 0x16, 0x08, 0x13, 0x0A, 0x4B, 0x71,
+  0x5D, 0x44, 0x47, 0xBE, 0x08, 0x0C, 0x0D, 0x0C,
+  0x19, 0x29, 0x36, 0x06, 0x43, 0x44, 0xBA, 0x45,
+  0x50, 0x58, 0x07, 0x07, 0x0D, 0x0E, 0x10, 0x50,
+  0x06, 0x42, 0x40, 0x44, 0x79, 0x06, 0x06, 0x0C,
+  0x08, 0x08, 0x07, 0x36, 0x4C, 0xE5, 0x42, 0x55,
+  0x03, 0x0F, 0x12, 0x06, 0x07, 0x3C, 0x4B, 0x3D,
+  0x01, 0xF8, 0x08, 0x0E, 0x0A, 0x69, 0xAC, 0x0C,
+  0x0A, 0x27, 0xBB, 0x36, 0x76, 0xC0, 0x04, 0x08,
+  0x08, 0xED, 0xEE, 0x68, 0x5F, 0xB2, 0x3B, 0x52,
+  0xAC, 0x4F, 0x6F, 0x2D, 0x16, 0x08, 0x59, 0x04,
+  0x13, 0x0E, 0x14, 0x17, 0x16, 0x2E, 0x08, 0x0D,
+  0x11, 0x14, 0x0D, 0x06, 0x04, 0x08, 0x25, 0x8E,
+  0x0E, 0x14, 0x25, 0x9B, 0x1C, 0x16, 0x78, 0x06,
+  0x04, 0x03, 0x79, 0x8C, 0x0B, 0xC8, 0x48
+};
+
+unsigned char linux_logo[] __initdata = {
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x21, 0x21, 0x22, 0x23, 0x24, 0x24,
+  0x25, 0x24, 0x24, 0x25, 0x25, 0x25, 0x25, 0x25,
+  0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x23, 0x23,
+  0x23, 0x22, 0x22, 0x22, 0x22, 0x21, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x26, 0x27, 0x27, 0x27, 0x27,
+  0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x26, 0x28,
+  0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
+  0x29, 0x28, 0x28, 0x28, 0x2A, 0x2A, 0x2B, 0x2B,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x2B, 0x2B, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27,
+  0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27,
+  0x28, 0x28, 0x28, 0x29, 0x29, 0x29, 0x29, 0x29,
+  0x29, 0x29, 0x29, 0x2C, 0x29, 0x29, 0x29, 0x28,
+  0x28, 0x2A, 0x2B, 0x2B, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x2B, 0x2B, 0x2A, 0x2A,
+  0x2A, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27,
+  0x27, 0x27, 0x27, 0x27, 0x2D, 0x2E, 0x2F, 0x27,
+  0x27, 0x26, 0x2B, 0x2A, 0x2A, 0x2A, 0x2A, 0x28,
+  0x28, 0x29, 0x29, 0x29, 0x29, 0x2C, 0x2C, 0x29,
+  0x29, 0x29, 0x28, 0x28, 0x2A, 0x2B, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x2B, 0x2B, 0x2B, 0x2A, 0x2A, 0x2A,
+  0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27,
+  0x27, 0x27, 0x27, 0x27, 0x2F, 0x30, 0x31, 0x32,
+  0x27, 0x27, 0x22, 0x22, 0x22, 0x22, 0x21, 0x20,
+  0x20, 0x20, 0x2B, 0x2A, 0x28, 0x29, 0x29, 0x29,
+  0x2C, 0x2C, 0x2C, 0x29, 0x29, 0x28, 0x2A, 0x2B,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x2B, 0x2B, 0x2A, 0x2A, 0x2A, 0x2A, 0x2B,
+  0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27,
+  0x27, 0x27, 0x27, 0x27, 0x32, 0x33, 0x34, 0x35,
+  0x36, 0x27, 0x27, 0x33, 0x25, 0x25, 0x24, 0x24,
+  0x24, 0x24, 0x23, 0x21, 0x20, 0x20, 0x2B, 0x2A,
+  0x28, 0x29, 0x29, 0x37, 0x2C, 0x2C, 0x29, 0x28,
+  0x2A, 0x2B, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2B, 0x2B,
+  0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2A, 0x2B, 0x27,
+  0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27,
+  0x27, 0x27, 0x27, 0x27, 0x2F, 0x32, 0x36, 0x27,
+  0x27, 0x27, 0x27, 0x33, 0x33, 0x33, 0x33, 0x33,
+  0x33, 0x33, 0x33, 0x25, 0x25, 0x24, 0x23, 0x21,
+  0x20, 0x2B, 0x2A, 0x29, 0x29, 0x2C, 0x2C, 0x2C,
+  0x29, 0x28, 0x2A, 0x2B, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2B, 0x2B,
+  0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x20, 0x21, 0x27,
+  0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27,
+  0x27, 0x27, 0x27, 0x27, 0x38, 0x27, 0x27, 0x27,
+  0x27, 0x27, 0x27, 0x27, 0x23, 0x23, 0x24, 0x24,
+  0x25, 0x25, 0x33, 0x33, 0x33, 0x33, 0x33, 0x25,
+  0x24, 0x22, 0x20, 0x20, 0x2A, 0x28, 0x29, 0x2C,
+  0x2C, 0x2C, 0x29, 0x28, 0x2A, 0x2B, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x2B, 0x2B, 0x2B, 0x2B,
+  0x2B, 0x2B, 0x2B, 0x20, 0x21, 0x22, 0x23, 0x27,
+  0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27,
+  0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27,
+  0x27, 0x27, 0x27, 0x27, 0x2A, 0x2A, 0x2B, 0x2B,
+  0x20, 0x21, 0x22, 0x24, 0x20, 0x39, 0x39, 0x39,
+  0x39, 0x39, 0x3A, 0x3B, 0x22, 0x20, 0x2A, 0x28,
+  0x29, 0x2C, 0x2C, 0x2C, 0x29, 0x28, 0x2B, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B, 0x2B,
+  0x2B, 0x20, 0x21, 0x22, 0x22, 0x23, 0x24, 0x27,
+  0x27, 0x27, 0x3C, 0x36, 0x3C, 0x27, 0x27, 0x27,
+  0x27, 0x27, 0x27, 0x3D, 0x3E, 0x32, 0x27, 0x27,
+  0x27, 0x27, 0x27, 0x27, 0x3D, 0x39, 0x3F, 0x3F,
+  0x39, 0x2C, 0x20, 0x20, 0x39, 0x39, 0x39, 0x39,
+  0x39, 0x39, 0x39, 0x40, 0x40, 0x41, 0x22, 0x20,
+  0x2A, 0x28, 0x2C, 0x2C, 0x2C, 0x29, 0x29, 0x2A,
+  0x2B, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x2B, 0x2B, 0x2B, 0x2B, 0x20, 0x20,
+  0x21, 0x22, 0x22, 0x22, 0x23, 0x23, 0x22, 0x27,
+  0x27, 0x3C, 0x3C, 0x3D, 0x42, 0x3C, 0x27, 0x27,
+  0x3C, 0x27, 0x3C, 0x43, 0x44, 0x36, 0x42, 0x27,
+  0x27, 0x27, 0x27, 0x27, 0x3D, 0x28, 0x29, 0x2C,
+  0x2C, 0x45, 0x20, 0x39, 0x39, 0x39, 0x39, 0x39,
+  0x39, 0x46, 0x40, 0x47, 0x40, 0x47, 0x3A, 0x40,
+  0x22, 0x20, 0x2A, 0x29, 0x2C, 0x2C, 0x2C, 0x29,
+  0x28, 0x2B, 0x2B, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x2B, 0x2B, 0x2B, 0x2B, 0x20, 0x20, 0x22,
+  0x22, 0x22, 0x23, 0x22, 0x22, 0x21, 0x20, 0x27,
+  0x27, 0x44, 0x28, 0x24, 0x27, 0x2F, 0x3C, 0x27,
+  0x27, 0x38, 0x24, 0x2C, 0x2C, 0x48, 0x49, 0x36,
+  0x27, 0x27, 0x27, 0x27, 0x27, 0x28, 0x29, 0x29,
+  0x4A, 0x20, 0x3A, 0x40, 0x47, 0x40, 0x47, 0x40,
+  0x40, 0x47, 0x40, 0x40, 0x39, 0x39, 0x39, 0x4A,
+  0x25, 0x24, 0x22, 0x2B, 0x28, 0x29, 0x2C, 0x2C,
+  0x29, 0x28, 0x2A, 0x2B, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x2B, 0x2B, 0x20, 0x20, 0x20, 0x21, 0x22, 0x22,
+  0x22, 0x22, 0x22, 0x21, 0x20, 0x2B, 0x2A, 0x27,
+  0x3D, 0x4B, 0x48, 0x4C, 0x2B, 0x3C, 0x27, 0x3C,
+  0x3C, 0x23, 0x4D, 0x4E, 0x4F, 0x50, 0x33, 0x27,
+  0x27, 0x27, 0x27, 0x27, 0x27, 0x39, 0x3F, 0x39,
+  0x51, 0x20, 0x39, 0x39, 0x47, 0x40, 0x4D, 0x4D,
+  0x40, 0x52, 0x4D, 0x40, 0x47, 0x40, 0x39, 0x39,
+  0x53, 0x54, 0x25, 0x24, 0x20, 0x2A, 0x29, 0x2C,
+  0x2C, 0x2C, 0x29, 0x2A, 0x2B, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x21, 0x21, 0x22, 0x22,
+  0x22, 0x21, 0x20, 0x2B, 0x28, 0x2A, 0x20, 0x27,
+  0x36, 0x4F, 0x55, 0x48, 0x56, 0x3D, 0x3C, 0x3C,
+  0x32, 0x57, 0x56, 0x58, 0x49, 0x56, 0x56, 0x27,
+  0x27, 0x27, 0x27, 0x27, 0x27, 0x22, 0x20, 0x20,
+  0x41, 0x39, 0x39, 0x3A, 0x59, 0x5A, 0x59, 0x5B,
+  0x5C, 0x3A, 0x4D, 0x5D, 0x57, 0x39, 0x39, 0x4A,
+  0x5E, 0x33, 0x54, 0x33, 0x24, 0x22, 0x2B, 0x28,
+  0x2C, 0x2C, 0x2C, 0x29, 0x28, 0x2B, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x21, 0x21, 0x21, 0x22, 0x22, 0x21,
+  0x20, 0x2B, 0x2A, 0x2A, 0x20, 0x22, 0x22, 0x27,
+  0x5F, 0x2D, 0x3C, 0x60, 0x56, 0x54, 0x61, 0x49,
+  0x35, 0x56, 0x34, 0x27, 0x62, 0x27, 0x56, 0x39,
+  0x27, 0x27, 0x27, 0x27, 0x27, 0x30, 0x63, 0x54,
+  0x40, 0x64, 0x65, 0x66, 0x67, 0x67, 0x68, 0x5F,
+  0x2E, 0x69, 0x6A, 0x67, 0x5F, 0x3A, 0x39, 0x2C,
+  0x53, 0x23, 0x25, 0x54, 0x33, 0x25, 0x23, 0x20,
+  0x2A, 0x29, 0x2C, 0x2C, 0x29, 0x28, 0x2B, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x21, 0x21, 0x21, 0x21, 0x21, 0x20, 0x20,
+  0x2B, 0x2A, 0x20, 0x22, 0x22, 0x21, 0x2B, 0x27,
+  0x62, 0x36, 0x27, 0x33, 0x6B, 0x54, 0x3D, 0x3C,
+  0x49, 0x57, 0x27, 0x27, 0x27, 0x27, 0x56, 0x57,
+  0x27, 0x27, 0x27, 0x27, 0x27, 0x6C, 0x31, 0x6D,
+  0x64, 0x51, 0x6E, 0x2E, 0x2E, 0x6F, 0x5A, 0x70,
+  0x70, 0x71, 0x72, 0x67, 0x67, 0x69, 0x73, 0x46,
+  0x4A, 0x2A, 0x21, 0x25, 0x33, 0x54, 0x33, 0x24,
+  0x20, 0x2A, 0x29, 0x2C, 0x2C, 0x29, 0x28, 0x2B,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x21, 0x21, 0x21, 0x21, 0x20, 0x20, 0x2B,
+  0x2B, 0x22, 0x22, 0x22, 0x2B, 0x28, 0x2A, 0x27,
+  0x27, 0x39, 0x3C, 0x3D, 0x45, 0x74, 0x75, 0x76,
+  0x76, 0x45, 0x27, 0x27, 0x27, 0x27, 0x56, 0x77,
+  0x27, 0x27, 0x27, 0x27, 0x27, 0x78, 0x78, 0x5E,
+  0x79, 0x7A, 0x7B, 0x6E, 0x5A, 0x5A, 0x70, 0x7C,
+  0x70, 0x5B, 0x7D, 0x5A, 0x66, 0x7E, 0x7F, 0x79,
+  0x48, 0x6B, 0x2C, 0x20, 0x24, 0x33, 0x54, 0x33,
+  0x24, 0x21, 0x2A, 0x29, 0x2C, 0x2C, 0x29, 0x28,
+  0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x21, 0x21, 0x21, 0x20, 0x20, 0x2B, 0x2B, 0x21,
+  0x22, 0x22, 0x20, 0x28, 0x2B, 0x20, 0x22, 0x27,
+  0x27, 0x80, 0x27, 0x81, 0x82, 0x83, 0x84, 0x85,
+  0x74, 0x85, 0x84, 0x27, 0x3C, 0x4F, 0x4F, 0x66,
+  0x27, 0x27, 0x27, 0x27, 0x27, 0x22, 0x23, 0x5E,
+  0x64, 0x86, 0x79, 0x73, 0x87, 0x88, 0x7C, 0x5A,
+  0x5A, 0x71, 0x7D, 0x71, 0x89, 0x79, 0x8A, 0x8A,
+  0x51, 0x8B, 0x48, 0x39, 0x2A, 0x22, 0x33, 0x54,
+  0x33, 0x25, 0x22, 0x2B, 0x29, 0x2C, 0x2C, 0x29,
+  0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x21, 0x21, 0x20, 0x20, 0x2B, 0x2B, 0x22, 0x23,
+  0x21, 0x2A, 0x2A, 0x20, 0x21, 0x23, 0x25, 0x27,
+  0x27, 0x55, 0x8C, 0x8D, 0x8E, 0x83, 0x8F, 0x90,
+  0x91, 0x92, 0x92, 0x85, 0x85, 0x93, 0x51, 0x27,
+  0x27, 0x27, 0x27, 0x27, 0x27, 0x2A, 0x29, 0x51,
+  0x79, 0x79, 0x94, 0x89, 0x89, 0x89, 0x5A, 0x95,
+  0x64, 0x88, 0x96, 0x97, 0x7A, 0x73, 0x98, 0x98,
+  0x99, 0x50, 0x50, 0x48, 0x6B, 0x28, 0x21, 0x25,
+  0x54, 0x54, 0x25, 0x22, 0x2B, 0x29, 0x2C, 0x29,
+  0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x2B, 0x20, 0x22, 0x22, 0x20,
+  0x2B, 0x2B, 0x20, 0x22, 0x24, 0x25, 0x33, 0x27,
+  0x27, 0x9A, 0x9B, 0x9C, 0x9D, 0x83, 0x9E, 0x85,
+  0x9F, 0x92, 0x85, 0x85, 0x85, 0x85, 0x92, 0xA0,
+  0x27, 0x27, 0x27, 0x27, 0x27, 0xA1, 0x47, 0xA2,
+  0xA2, 0x94, 0xA3, 0x94, 0x95, 0x95, 0x73, 0x73,
+  0x95, 0x87, 0xA4, 0x5B, 0x97, 0x7B, 0x88, 0x98,
+  0xA2, 0x50, 0x48, 0x48, 0x48, 0x8B, 0x29, 0x20,
+  0x25, 0x54, 0x54, 0x25, 0x22, 0x2B, 0x29, 0x29,
+  0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x21, 0x22, 0x22, 0x2B, 0x2B,
+  0x20, 0x21, 0x23, 0x24, 0x25, 0x25, 0x33, 0x27,
+  0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0x8F, 0x90, 0x90,
+  0x9F, 0x90, 0x85, 0x90, 0x85, 0x74, 0xAA, 0x81,
+  0x27, 0x27, 0x27, 0x27, 0x27, 0xAB, 0x40, 0xAC,
+  0x79, 0xA3, 0x89, 0xAD, 0x95, 0x6F, 0xAE, 0xAE,
+  0xAE, 0x5B, 0x59, 0x88, 0x7B, 0x89, 0x79, 0xAF,
+  0xA2, 0x6B, 0x48, 0x48, 0x48, 0x48, 0x50, 0x2C,
+  0x20, 0x24, 0x33, 0x54, 0x25, 0x22, 0x2A, 0x2A,
+  0x21, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x21, 0x23, 0x22, 0x2B, 0x20, 0x20,
+  0x22, 0x23, 0x24, 0x25, 0x24, 0x24, 0x22, 0x27,
+  0xB0, 0x8C, 0xAA, 0xB1, 0xB2, 0x84, 0x85, 0x9F,
+  0x85, 0x85, 0x85, 0xB3, 0xB4, 0xAA, 0xAA, 0xA0,
+  0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x2A, 0xB5,
+  0xA3, 0xA3, 0xAC, 0x5D, 0xB6, 0xAE, 0xB7, 0x69,
+  0x73, 0x5B, 0x88, 0x89, 0x95, 0x73, 0x99, 0x99,
+  0x59, 0x2A, 0x39, 0x48, 0x48, 0x50, 0x48, 0x50,
+  0x2C, 0x20, 0x24, 0x33, 0x54, 0x25, 0x21, 0x20,
+  0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x21, 0x23, 0x21, 0x2B, 0x20, 0x20, 0x22,
+  0x22, 0x24, 0x24, 0x23, 0x22, 0x20, 0x2A, 0x27,
+  0x27, 0xB0, 0x8C, 0xA9, 0xB2, 0x9E, 0x91, 0x85,
+  0x85, 0x93, 0xB8, 0x75, 0xAA, 0xA7, 0x8C, 0x27,
+  0x27, 0x27, 0x33, 0x3C, 0x27, 0x27, 0x2C, 0x7B,
+  0x55, 0x79, 0xA3, 0x5D, 0xB9, 0x43, 0x7F, 0x7E,
+  0x5F, 0x5A, 0x5A, 0x95, 0x64, 0x73, 0x58, 0x64,
+  0x5C, 0x25, 0x2B, 0x3F, 0x48, 0x48, 0x8B, 0x48,
+  0x48, 0x2C, 0x20, 0x25, 0x54, 0x33, 0x24, 0x22,
+  0x2B, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x21, 0x23, 0x21, 0x20, 0x20, 0x20, 0x21, 0x22,
+  0x24, 0x23, 0x22, 0x21, 0x2B, 0x20, 0x54, 0x27,
+  0x27, 0x8B, 0x81, 0xA5, 0x93, 0x93, 0x74, 0xA5,
+  0xBA, 0x75, 0xBB, 0xBC, 0xB4, 0x6D, 0x50, 0x6B,
+  0x27, 0x27, 0x30, 0x33, 0x49, 0x27, 0x27, 0x5E,
+  0x6F, 0x73, 0x94, 0xBD, 0x4E, 0x5D, 0x7F, 0x7F,
+  0xB7, 0x68, 0x73, 0x6E, 0xB7, 0x7F, 0x95, 0x97,
+  0x47, 0x63, 0x25, 0x20, 0x3F, 0x48, 0x8B, 0x8B,
+  0x48, 0x48, 0x2C, 0x20, 0x25, 0x54, 0x33, 0x25,
+  0x2B, 0x2B, 0x2B, 0x20, 0x20, 0x20, 0x21, 0x21,
+  0x23, 0x21, 0x20, 0x20, 0x20, 0x20, 0x24, 0x24,
+  0x22, 0x21, 0x20, 0x2A, 0x33, 0x30, 0x30, 0x27,
+  0x27, 0x50, 0xBE, 0xBF, 0x9A, 0xB3, 0x9B, 0xBB,
+  0xBB, 0xC0, 0x8C, 0xC1, 0x8B, 0xC2, 0x47, 0x8B,
+  0x27, 0x27, 0x38, 0x63, 0x63, 0x27, 0x27, 0xC3,
+  0xB5, 0x95, 0x72, 0x95, 0x6F, 0x69, 0x7E, 0x66,
+  0x7E, 0x7F, 0x6E, 0x7E, 0x95, 0x95, 0x73, 0x70,
+  0x30, 0x30, 0x30, 0x33, 0x20, 0x3F, 0x48, 0x8B,
+  0x6B, 0x48, 0x50, 0x29, 0x21, 0x33, 0x54, 0x33,
+  0x2A, 0x2B, 0x2B, 0x20, 0x20, 0x21, 0x21, 0x23,
+  0x21, 0x20, 0x20, 0x20, 0x20, 0x24, 0x24, 0x22,
+  0x20, 0x2B, 0x21, 0xC4, 0x30, 0x60, 0x30, 0x27,
+  0x27, 0xC5, 0x8B, 0x39, 0xC6, 0xC7, 0xA6, 0xA6,
+  0xC8, 0x9A, 0x3B, 0x39, 0x50, 0x56, 0x56, 0x4F,
+  0x33, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x48,
+  0x59, 0x94, 0x73, 0xAE, 0xB7, 0xB7, 0x7E, 0x7E,
+  0x7E, 0x7E, 0x7E, 0x5A, 0x70, 0x7C, 0x71, 0xC3,
+  0x63, 0x30, 0x60, 0x78, 0x54, 0x20, 0x6B, 0x48,
+  0x6B, 0x6B, 0x50, 0x50, 0x29, 0x22, 0x33, 0x33,
+  0x2A, 0x2B, 0x20, 0x20, 0x21, 0x22, 0x22, 0x22,
+  0x21, 0x20, 0x20, 0x20, 0x24, 0x24, 0x20, 0x20,
+  0x2B, 0x24, 0x30, 0x60, 0x60, 0x30, 0xAB, 0x27,
+  0x27, 0x40, 0x4C, 0x50, 0x39, 0x87, 0xC3, 0x53,
+  0x37, 0x48, 0x37, 0x48, 0xC9, 0x56, 0xB9, 0x56,
+  0xCA, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x3C,
+  0x51, 0x5A, 0x6E, 0xB7, 0xB7, 0x7E, 0x7E, 0x7E,
+  0x7E, 0x7E, 0x7F, 0xB7, 0x5A, 0x7C, 0x5B, 0x37,
+  0x23, 0x63, 0x31, 0x6C, 0xCB, 0x63, 0x20, 0x6B,
+  0x50, 0x3F, 0x39, 0x50, 0x8B, 0x28, 0x24, 0x24,
+  0x2B, 0x2B, 0x20, 0x21, 0x22, 0x22, 0x22, 0x21,
+  0x20, 0x20, 0x20, 0x23, 0x23, 0x20, 0x20, 0x2B,
+  0x33, 0x78, 0xCB, 0x60, 0x30, 0x22, 0x3D, 0x27,
+  0x2F, 0x56, 0x4E, 0x8B, 0x6B, 0x39, 0x48, 0x8B,
+  0x6B, 0x8B, 0x80, 0xC9, 0xB9, 0xB9, 0x56, 0xB9,
+  0x56, 0x34, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27,
+  0x48, 0xB5, 0xB7, 0xB7, 0x7E, 0x7E, 0x2E, 0x7E,
+  0x7E, 0x7E, 0x7F, 0x7C, 0x65, 0x71, 0x3A, 0x48,
+  0x2C, 0x24, 0x30, 0x6C, 0x34, 0x6C, 0xC4, 0x20,
+  0x8B, 0x50, 0x39, 0x39, 0x48, 0x6B, 0x2B, 0x22,
+  0x2B, 0x20, 0x21, 0x22, 0x23, 0x23, 0x22, 0x21,
+  0x20, 0x2B, 0x23, 0x22, 0x20, 0x2B, 0x2B, 0x54,
+  0x60, 0x31, 0xCB, 0x54, 0x20, 0x3D, 0x36, 0x27,
+  0x4E, 0xB9, 0x56, 0x56, 0x8B, 0x6B, 0x50, 0x6B,
+  0x40, 0x56, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9,
+  0x56, 0x56, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27,
+  0x27, 0x7B, 0x6E, 0xB7, 0xB7, 0xB7, 0x7E, 0x7F,
+  0xB7, 0xB7, 0x7F, 0x7E, 0x6F, 0x5B, 0x29, 0x2C,
+  0x48, 0x39, 0x24, 0x60, 0x58, 0xAF, 0xCC, 0x63,
+  0x20, 0x8B, 0x8B, 0x39, 0x39, 0x48, 0x3F, 0x28,
+  0x20, 0x20, 0x22, 0x23, 0x23, 0x23, 0x22, 0x20,
+  0x2B, 0x22, 0x22, 0x2B, 0x2B, 0x20, 0x54, 0xCB,
+  0x31, 0xCB, 0x25, 0x20, 0x27, 0x27, 0x27, 0x48,
+  0xB9, 0x56, 0xB9, 0x56, 0x4F, 0x48, 0x47, 0x57,
+  0x56, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56,
+  0xB9, 0x56, 0x62, 0x27, 0x27, 0x27, 0x27, 0x27,
+  0x27, 0x48, 0x6F, 0x69, 0xB7, 0xB7, 0xB7, 0x7F,
+  0xB7, 0xB7, 0xB7, 0x73, 0x59, 0x50, 0x29, 0x2B,
+  0x28, 0x8B, 0x39, 0x25, 0x31, 0x55, 0xB6, 0x34,
+  0x63, 0x2B, 0x48, 0x6B, 0x2C, 0x39, 0x47, 0x6B,
+  0x22, 0x22, 0x23, 0x24, 0x23, 0x22, 0x20, 0x2B,
+  0x20, 0x22, 0x2A, 0x2B, 0x20, 0x33, 0xCB, 0x31,
+  0x78, 0x24, 0x21, 0xCD, 0x27, 0x27, 0x27, 0x56,
+  0x56, 0xB9, 0x56, 0xB9, 0x56, 0x56, 0x56, 0xB9,
+  0x56, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56,
+  0xB9, 0x56, 0xC9, 0x27, 0x27, 0x27, 0x27, 0x27,
+  0x27, 0x27, 0x41, 0x64, 0xB7, 0xB7, 0xB7, 0x7F,
+  0x68, 0xB7, 0xAE, 0xA3, 0x23, 0x39, 0x8B, 0x2A,
+  0x20, 0x20, 0x39, 0x6B, 0x25, 0xCC, 0x43, 0x43,
+  0x34, 0x63, 0x2A, 0x48, 0x3F, 0x39, 0x6B, 0x6B,
+  0x24, 0x23, 0x24, 0x24, 0x23, 0x21, 0x2B, 0x2B,
+  0x22, 0x2B, 0x2B, 0x20, 0x24, 0x78, 0x31, 0x30,
+  0x23, 0x21, 0x21, 0x27, 0x27, 0x27, 0x80, 0x56,
+  0x56, 0xB9, 0x56, 0xB9, 0x56, 0xB9, 0x56, 0xB9,
+  0x56, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9,
+  0x56, 0xB9, 0x56, 0x3C, 0x27, 0x27, 0x27, 0x27,
+  0x27, 0x27, 0x27, 0xCE, 0x8A, 0xAE, 0x6F, 0xB7,
+  0x6F, 0x89, 0x71, 0x78, 0x63, 0x23, 0x39, 0x6B,
+  0x2B, 0x20, 0x20, 0x2C, 0x6B, 0x25, 0x34, 0x42,
+  0x42, 0x34, 0x54, 0x29, 0x48, 0x3F, 0x39, 0x3F,
+  0x25, 0x24, 0x25, 0x24, 0x22, 0x20, 0x2A, 0x21,
+  0x2B, 0x2A, 0x20, 0x22, 0x30, 0x60, 0x30, 0x22,
+  0x21, 0x22, 0x27, 0x27, 0x27, 0x2D, 0x4C, 0x56,
+  0x56, 0xB9, 0xB9, 0x56, 0xB9, 0xB9, 0x56, 0x56,
+  0xB9, 0xB9, 0xB9, 0x56, 0x56, 0x56, 0xB9, 0xB9,
+  0xB9, 0xB9, 0x56, 0x2E, 0x27, 0x27, 0x27, 0x27,
+  0x27, 0x27, 0x27, 0x40, 0x97, 0x95, 0x5A, 0x71,
+  0x7C, 0xCE, 0x40, 0x60, 0x31, 0x30, 0x23, 0x3F,
+  0x3F, 0x20, 0x20, 0x20, 0x29, 0x8B, 0x33, 0x58,
+  0x66, 0x43, 0xCC, 0x25, 0x39, 0x50, 0x6B, 0x2C,
+  0x33, 0x25, 0x25, 0x23, 0x20, 0x2A, 0x2B, 0x20,
+  0x2A, 0x2B, 0x22, 0x54, 0x30, 0x30, 0x24, 0x22,
+  0x21, 0x27, 0x27, 0x27, 0x27, 0xAF, 0x29, 0x4E,
+  0x4F, 0xB9, 0x56, 0xB9, 0x4D, 0x4D, 0x77, 0xC9,
+  0xB9, 0xB9, 0xB9, 0x56, 0xC9, 0x4D, 0x4D, 0x80,
+  0x4C, 0x40, 0xC9, 0x4D, 0x27, 0x27, 0x27, 0x27,
+  0x27, 0x27, 0x27, 0x27, 0xCF, 0x97, 0x97, 0xCE,
+  0x86, 0xD0, 0x54, 0x6C, 0x58, 0x34, 0x60, 0x23,
+  0x6B, 0x39, 0x20, 0x20, 0x20, 0x28, 0x6B, 0x54,
+  0xD1, 0x66, 0xB6, 0x60, 0x22, 0x6B, 0x8B, 0x2C,
+  0x54, 0x33, 0x24, 0x22, 0x2B, 0x28, 0x20, 0x28,
+  0x2B, 0x20, 0x25, 0xC4, 0x30, 0x25, 0x22, 0x21,
+  0x26, 0x27, 0x27, 0x27, 0x27, 0x20, 0x4B, 0x52,
+  0x80, 0x4F, 0xB9, 0x56, 0xB9, 0x80, 0x56, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0x4D, 0x80, 0x50, 0x48,
+  0x50, 0x50, 0x50, 0x56, 0x3D, 0x27, 0x36, 0x27,
+  0x27, 0x27, 0x27, 0x3C, 0x46, 0xC3, 0x86, 0x86,
+  0xD0, 0x39, 0x24, 0x6C, 0xD1, 0x43, 0x43, 0x6C,
+  0x24, 0x6B, 0x2C, 0x20, 0x20, 0x20, 0x29, 0x39,
+  0x63, 0xD1, 0x42, 0x55, 0xC4, 0x2B, 0x8B, 0x39,
+  0x54, 0x25, 0x24, 0x20, 0x2A, 0x2A, 0x28, 0x28,
+  0x20, 0x22, 0x54, 0x63, 0x25, 0x24, 0x22, 0x22,
+  0x27, 0x27, 0x27, 0x27, 0x27, 0x28, 0x77, 0x56,
+  0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0xC9, 0x56, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x4F,
+  0x77, 0x47, 0x8B, 0x40, 0x56, 0x27, 0x27, 0x49,
+  0x2D, 0x27, 0x27, 0x27, 0x39, 0x40, 0x39, 0x39,
+  0x28, 0x3F, 0x39, 0x33, 0x58, 0x66, 0x35, 0x2E,
+  0x58, 0x24, 0x8B, 0x29, 0x20, 0x20, 0x20, 0x39,
+  0x29, 0x30, 0x55, 0xB6, 0xCC, 0x25, 0x29, 0x39,
+  0x54, 0x25, 0x22, 0x2B, 0x29, 0x2A, 0x29, 0x2B,
+  0x22, 0x24, 0x54, 0x33, 0x25, 0x22, 0x2B, 0x54,
+  0x27, 0x27, 0x62, 0x27, 0x30, 0x80, 0xB9, 0x56,
+  0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0x56, 0x4D, 0x8B, 0x77, 0x36, 0x27, 0x27,
+  0x3C, 0x2F, 0x27, 0x27, 0x39, 0x39, 0x39, 0x47,
+  0x20, 0x2B, 0x2C, 0x39, 0x33, 0xB6, 0x35, 0x35,
+  0x35, 0xAF, 0x24, 0x48, 0x2A, 0x20, 0x20, 0x20,
+  0x8B, 0x2B, 0x78, 0xAF, 0x58, 0x30, 0x21, 0x28,
+  0x33, 0x25, 0x21, 0x28, 0x29, 0x29, 0x28, 0x20,
+  0x24, 0x33, 0x54, 0x33, 0x23, 0x20, 0x24, 0xD2,
+  0x27, 0x49, 0x27, 0x27, 0x56, 0xB9, 0xB9, 0x56,
+  0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0xB9, 0x56, 0xC9, 0x50, 0x56, 0x27, 0x27,
+  0x3D, 0x38, 0x3D, 0x27, 0x27, 0x47, 0x39, 0x39,
+  0x28, 0x20, 0x20, 0x2A, 0x39, 0x54, 0x43, 0x35,
+  0x35, 0x35, 0xAF, 0x23, 0x48, 0x2B, 0x20, 0x20,
+  0x2B, 0x48, 0x22, 0x60, 0x34, 0xCB, 0x25, 0x21,
+  0x33, 0x24, 0x2B, 0x29, 0x29, 0x29, 0x2B, 0x22,
+  0x25, 0x54, 0x54, 0x25, 0x22, 0x2B, 0x33, 0x27,
+  0x27, 0x32, 0x27, 0x30, 0x56, 0xB9, 0xB9, 0x56,
+  0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0xB9, 0x56, 0x56, 0xC9, 0x4C, 0x36, 0x3C,
+  0x62, 0x2F, 0x2E, 0x27, 0x27, 0x54, 0x47, 0x47,
+  0x8B, 0x2B, 0x20, 0x20, 0x20, 0x3F, 0x54, 0x2E,
+  0x35, 0x35, 0x35, 0x34, 0x21, 0x8B, 0x2A, 0x20,
+  0x20, 0x2C, 0x6B, 0x25, 0x60, 0x60, 0x54, 0x23,
+  0x25, 0x22, 0x2A, 0x2C, 0x29, 0x28, 0x20, 0x24,
+  0x54, 0x63, 0x54, 0x24, 0x2B, 0x22, 0x24, 0x27,
+  0x36, 0x27, 0x27, 0x56, 0x56, 0xB9, 0xB9, 0x56,
+  0xB9, 0xB9, 0xB9, 0x56, 0x56, 0x56, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56, 0x4C, 0x36,
+  0x66, 0xD3, 0x27, 0x2F, 0x27, 0x54, 0x54, 0x27,
+  0x26, 0x6B, 0x20, 0x20, 0x20, 0x20, 0x6B, 0x63,
+  0x35, 0x35, 0x35, 0x62, 0xCB, 0x2A, 0x3F, 0x28,
+  0x2B, 0x2A, 0x50, 0x29, 0x33, 0x30, 0x54, 0x25,
+  0x24, 0x20, 0x29, 0x2C, 0x2C, 0x2A, 0x21, 0x33,
+  0xC4, 0xC4, 0x33, 0x21, 0x29, 0x22, 0x27, 0x27,
+  0x99, 0x27, 0x31, 0xB9, 0xB9, 0xB9, 0xB9, 0x56,
+  0xB9, 0xB9, 0xB9, 0x56, 0x56, 0x56, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56, 0x56, 0x3D,
+  0x3D, 0x3C, 0x3C, 0x55, 0x54, 0x54, 0x54, 0x20,
+  0x27, 0x2C, 0x39, 0x20, 0x20, 0x20, 0x20, 0x48,
+  0x30, 0x62, 0x35, 0x35, 0x42, 0x54, 0x39, 0x39,
+  0x2C, 0x28, 0x3F, 0x8B, 0x20, 0x33, 0x54, 0x24,
+  0x22, 0x2B, 0x2C, 0x2C, 0x2C, 0x2B, 0x24, 0x54,
+  0x30, 0xC4, 0x25, 0x2B, 0x28, 0x2B, 0x27, 0x3D,
+  0x27, 0x27, 0x56, 0xB9, 0xB9, 0xB9, 0xB9, 0x56,
+  0xB9, 0xB9, 0x56, 0x56, 0x4F, 0x56, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0x56, 0x56, 0x27,
+  0x20, 0x20, 0x20, 0x54, 0x54, 0x54, 0x54, 0x20,
+  0x20, 0x2D, 0x2D, 0x29, 0x20, 0x20, 0x20, 0x20,
+  0x48, 0x60, 0x66, 0x35, 0x62, 0x34, 0x22, 0x2C,
+  0x2C, 0x3F, 0x6B, 0x48, 0x2C, 0x22, 0x23, 0x23,
+  0x20, 0x2A, 0x2C, 0x29, 0x29, 0x20, 0x25, 0xC4,
+  0x30, 0x54, 0x22, 0x29, 0x28, 0xD2, 0x27, 0x35,
+  0x27, 0x49, 0x56, 0xB9, 0xB9, 0xB9, 0xB9, 0x56,
+  0xB9, 0xB9, 0x56, 0x4F, 0x56, 0x56, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0xB9, 0xB9, 0x56, 0x56, 0x56, 0x40, 0x20,
+  0x20, 0x54, 0x54, 0x54, 0x20, 0x20, 0x20, 0x20,
+  0x2D, 0x2D, 0x2D, 0x49, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x6B, 0x6C, 0x42, 0x2E, 0xB6, 0x54, 0x28,
+  0x29, 0x2C, 0x6B, 0x48, 0x3F, 0x2A, 0x20, 0x22,
+  0x2B, 0x28, 0x2C, 0x28, 0x29, 0x20, 0x33, 0x30,
+  0x30, 0x54, 0x20, 0x2C, 0x29, 0x27, 0x27, 0x3D,
+  0x27, 0x40, 0x56, 0xB9, 0x56, 0x56, 0xB9, 0x56,
+  0xB9, 0x56, 0x56, 0x4D, 0x56, 0x56, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0xB9, 0x56, 0x56, 0x63, 0x56, 0x54, 0x54,
+  0x54, 0x54, 0x20, 0xD3, 0x45, 0x51, 0x51, 0x49,
+  0x7C, 0x2D, 0x2D, 0x49, 0x49, 0x20, 0x20, 0x20,
+  0x20, 0x2A, 0x2A, 0xCC, 0xB6, 0x8A, 0x60, 0x22,
+  0x28, 0x29, 0x3F, 0x6B, 0x39, 0x29, 0x2B, 0x20,
+  0x28, 0x2C, 0x28, 0x2A, 0x2A, 0x24, 0xC4, 0x30,
+  0xC4, 0x33, 0x2B, 0x39, 0xCD, 0x27, 0x3C, 0x27,
+  0x27, 0x56, 0xB9, 0x56, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0x56, 0x56, 0x4D, 0x56, 0x56, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0xB9, 0x56, 0x63, 0x63, 0x49, 0x2D, 0x20,
+  0x20, 0x2D, 0xD3, 0x49, 0x66, 0x2D, 0x49, 0x49,
+  0x49, 0x49, 0x49, 0x49, 0x49, 0x8B, 0x2B, 0x20,
+  0x20, 0x20, 0x39, 0x23, 0x6C, 0xAF, 0xCB, 0x23,
+  0x28, 0x28, 0x29, 0x2A, 0x2A, 0x2A, 0x2A, 0x20,
+  0x29, 0x39, 0x2B, 0x2B, 0x2B, 0x25, 0x78, 0xC4,
+  0x63, 0x23, 0x29, 0x39, 0x27, 0x27, 0x3D, 0x27,
+  0x27, 0x56, 0xB9, 0x56, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0x56, 0x56, 0x80, 0x4F, 0x56, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0xB9, 0xB9, 0xB9, 0x2D, 0x49, 0x2D, 0x49,
+  0x49, 0x2D, 0x49, 0x2D, 0x49, 0x2D, 0x2D, 0x2D,
+  0x49, 0x49, 0x35, 0x49, 0x2D, 0x2D, 0x39, 0x28,
+  0x20, 0x20, 0x2A, 0x28, 0x33, 0x60, 0xC4, 0x22,
+  0x2C, 0x2A, 0x2A, 0x22, 0x23, 0x22, 0x20, 0x21,
+  0x2C, 0x29, 0x20, 0x2B, 0x2B, 0x54, 0x30, 0xC4,
+  0x63, 0x22, 0x2C, 0x27, 0x27, 0x27, 0x3D, 0x27,
+  0x27, 0x56, 0x56, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0x56, 0x56, 0x80, 0x56, 0x56, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0xB9, 0xB9, 0xB9, 0x2D, 0x49, 0x2D, 0x49,
+  0x61, 0x49, 0x2D, 0x49, 0x49, 0x2D, 0x2D, 0x49,
+  0x49, 0x49, 0x2F, 0x49, 0x2D, 0x78, 0x29, 0x28,
+  0x2C, 0x2A, 0x2B, 0x39, 0x2B, 0x25, 0x33, 0x20,
+  0x2C, 0x20, 0x2A, 0x24, 0x54, 0x54, 0x23, 0x23,
+  0x2C, 0x2A, 0x22, 0x2B, 0x20, 0x63, 0x30, 0x63,
+  0xC4, 0x21, 0x39, 0x27, 0x27, 0x27, 0x35, 0x36,
+  0x27, 0x56, 0x56, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0xB9, 0x56, 0x80, 0x56, 0x56, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0xB9, 0xB9, 0x56, 0x2D, 0x49, 0x49, 0x49,
+  0x49, 0x27, 0x27, 0x2D, 0x38, 0x27, 0x36, 0x36,
+  0x49, 0x27, 0x49, 0x2D, 0x2D, 0x44, 0x24, 0x2B,
+  0x20, 0x2C, 0x3F, 0x6B, 0x2A, 0x20, 0x21, 0x28,
+  0x2C, 0x20, 0x2B, 0x24, 0x30, 0xCB, 0x63, 0x54,
+  0x28, 0x20, 0x24, 0x2B, 0x23, 0x78, 0xC4, 0x63,
+  0x63, 0x2B, 0x3F, 0x27, 0x27, 0x27, 0x38, 0x33,
+  0x3D, 0xB9, 0x56, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0xB9, 0x56, 0x80, 0x56, 0x56, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0xB9, 0xB9, 0x56, 0x63, 0x49, 0x49, 0x49,
+  0x49, 0x49, 0x3D, 0x3D, 0x27, 0x27, 0x27, 0x2D,
+  0x49, 0x49, 0x49, 0x2D, 0x62, 0x5F, 0xC4, 0x20,
+  0x22, 0x2A, 0x6B, 0x8B, 0x2C, 0x2B, 0x2A, 0x3F,
+  0x3F, 0x2A, 0x21, 0x21, 0xCB, 0x58, 0x6C, 0x60,
+  0x20, 0x23, 0x24, 0x2A, 0x25, 0x78, 0x63, 0x63,
+  0x54, 0x2A, 0x28, 0x27, 0x27, 0x27, 0x27, 0x62,
+  0x3C, 0xB9, 0x56, 0x56, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0x56, 0x56, 0x80, 0x56, 0x56, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0x49, 0x2D, 0x2D,
+  0x2D, 0x3D, 0x2F, 0x3C, 0x2D, 0x3C, 0x27, 0x38,
+  0x2D, 0x49, 0x2D, 0x2D, 0xD1, 0x43, 0x30, 0x20,
+  0x24, 0x21, 0x21, 0x21, 0x2B, 0x2A, 0x29, 0x8B,
+  0x6B, 0x29, 0x2B, 0x2A, 0x30, 0x55, 0x55, 0x34,
+  0x22, 0x23, 0x24, 0x29, 0x54, 0x30, 0x63, 0x63,
+  0x25, 0x29, 0x22, 0x3C, 0xA5, 0xD4, 0xD5, 0x27,
+  0x31, 0x56, 0x56, 0x56, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0x56, 0x56, 0x80, 0xB9, 0x56, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0x56, 0x2D, 0x2E,
+  0x3E, 0x27, 0x27, 0x27, 0x27, 0x27, 0x36, 0x44,
+  0x3C, 0x27, 0x2D, 0xC4, 0x78, 0xCC, 0x54, 0x2B,
+  0x25, 0x24, 0x63, 0x60, 0x63, 0x24, 0x2A, 0x6B,
+  0x3F, 0x39, 0x28, 0x21, 0x33, 0xB6, 0x44, 0x58,
+  0x22, 0x23, 0x24, 0x2A, 0x30, 0x30, 0x63, 0x63,
+  0x24, 0x39, 0x22, 0xBB, 0x9C, 0xB2, 0x9D, 0xA8,
+  0x27, 0x8B, 0x56, 0x56, 0xB9, 0x56, 0xB9, 0xB9,
+  0x56, 0xB9, 0x56, 0x80, 0xB9, 0x56, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0xB9, 0xB9, 0x56, 0x56, 0xD6, 0xD6, 0xD7,
+  0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x32,
+  0x3D, 0x27, 0x39, 0x33, 0xC4, 0xC4, 0x22, 0x28,
+  0x25, 0x54, 0x30, 0xD1, 0xD1, 0x60, 0x23, 0x6B,
+  0x3F, 0x39, 0x2C, 0x2B, 0x20, 0x58, 0x8A, 0x58,
+  0x22, 0x23, 0x23, 0x2B, 0x78, 0x30, 0xC4, 0xC4,
+  0x23, 0x29, 0xBB, 0xBB, 0xD8, 0xB2, 0x9D, 0xA9,
+  0xA9, 0x3C, 0x60, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9,
+  0x56, 0xB9, 0x56, 0x80, 0xB9, 0x56, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0xB9, 0xB9, 0x56, 0xD9, 0x85, 0x85, 0x85,
+  0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x2D,
+  0xA0, 0x83, 0x2C, 0x21, 0x30, 0x33, 0x29, 0x29,
+  0x21, 0x33, 0x54, 0x42, 0x66, 0x55, 0xC4, 0x29,
+  0x8B, 0x2C, 0x39, 0x28, 0x29, 0x31, 0x44, 0x58,
+  0x23, 0x23, 0x21, 0x20, 0x30, 0xC4, 0xC4, 0x30,
+  0x21, 0x20, 0xBB, 0xBC, 0xDA, 0xDB, 0xDC, 0xB2,
+  0x83, 0xB4, 0x3C, 0x2F, 0xB9, 0x56, 0x56, 0xB9,
+  0x56, 0xB9, 0x56, 0x80, 0x56, 0x56, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0x56, 0x56, 0x56, 0xA7, 0xD4, 0x85, 0x82,
+  0x3C, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x61,
+  0x9E, 0x90, 0xDD, 0x21, 0x33, 0x25, 0x2C, 0x39,
+  0x2A, 0x24, 0x24, 0x42, 0x62, 0x43, 0x34, 0x22,
+  0x50, 0x39, 0x2C, 0x2C, 0x2A, 0x54, 0xD1, 0x58,
+  0x22, 0x22, 0x2B, 0x22, 0x30, 0xC4, 0x30, 0x60,
+  0x20, 0xDE, 0xBB, 0xD9, 0x84, 0x84, 0xDF, 0xA9,
+  0xDB, 0xDB, 0x61, 0x27, 0x38, 0x4D, 0x56, 0x56,
+  0x56, 0xB9, 0x56, 0xB9, 0x56, 0x56, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0x56, 0x56, 0x56, 0x8D, 0xD9, 0xD5, 0xA6,
+  0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0xBB,
+  0x85, 0xDB, 0xDD, 0x21, 0x22, 0x22, 0x3F, 0x39,
+  0x2C, 0x2B, 0x25, 0x34, 0x62, 0x66, 0xD1, 0xC4,
+  0x6B, 0x39, 0x2C, 0x39, 0x29, 0x21, 0x58, 0xCC,
+  0x22, 0x21, 0x29, 0x23, 0x30, 0x30, 0x30, 0x5E,
+  0x82, 0xBB, 0xE0, 0xB1, 0xE1, 0x9C, 0xD4, 0xDC,
+  0x9D, 0xA9, 0xE2, 0x27, 0x27, 0x27, 0x4D, 0x56,
+  0x56, 0xB9, 0x56, 0xB9, 0x56, 0x56, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0x56, 0x4C, 0x48, 0xA8, 0xA8, 0xE3, 0x8C,
+  0xC6, 0x3C, 0x27, 0x27, 0x27, 0xE4, 0xA6, 0xE5,
+  0x83, 0xA9, 0xE6, 0xAF, 0x54, 0x2B, 0x8B, 0x39,
+  0x39, 0x29, 0x20, 0x54, 0x42, 0x42, 0xB6, 0xCC,
+  0x2A, 0x29, 0x39, 0x39, 0x2C, 0x2C, 0xCC, 0xCC,
+  0x22, 0x20, 0x39, 0xE7, 0xC0, 0xD9, 0xA7, 0xBC,
+  0x8D, 0xAA, 0x9C, 0xE8, 0x9C, 0x9D, 0xD4, 0xD4,
+  0xD8, 0xA9, 0x84, 0xC7, 0x27, 0x27, 0x27, 0x2A,
+  0x56, 0x56, 0x56, 0xB9, 0x56, 0x56, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0x56, 0x56, 0x48, 0x50, 0xAA, 0xE3, 0xE3, 0xC0,
+  0xA6, 0x9A, 0xBA, 0xC8, 0x9A, 0xDE, 0x9B, 0xD5,
+  0xE8, 0xD8, 0xD5, 0x2E, 0x58, 0x33, 0x6B, 0x39,
+  0x2C, 0x39, 0x29, 0x28, 0xD1, 0x43, 0xB6, 0xAF,
+  0x23, 0x28, 0x2C, 0x39, 0x39, 0x8B, 0x30, 0x31,
+  0x21, 0x20, 0x3F, 0xBB, 0xDF, 0xDF, 0xD5, 0xA8,
+  0xD5, 0x9C, 0x8E, 0xB2, 0x9D, 0xE9, 0xD4, 0xD8,
+  0x90, 0xB2, 0xA9, 0x8F, 0x27, 0x27, 0x27, 0x27,
+  0x2F, 0x56, 0x56, 0xB9, 0x56, 0x56, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0x56, 0xB9, 0x48, 0x48, 0x75, 0xE3, 0xAA, 0xAA,
+  0xC0, 0xB4, 0xB4, 0xB4, 0x75, 0x9B, 0xD9, 0x83,
+  0x9D, 0x90, 0xDF, 0xDD, 0x8A, 0x31, 0x4B, 0x2C,
+  0x2C, 0x29, 0x2C, 0x3F, 0x6C, 0x55, 0xD1, 0x55,
+  0x54, 0x29, 0x28, 0x39, 0x39, 0x6B, 0x24, 0x60,
+  0x20, 0x2B, 0x3F, 0xA7, 0xB1, 0x9D, 0xA9, 0x8E,
+  0xE5, 0xE5, 0xDF, 0xE0, 0xA9, 0x9D, 0xDF, 0xDF,
+  0xEA, 0x9D, 0xB2, 0x84, 0xAA, 0x27, 0x27, 0x27,
+  0x27, 0x35, 0x56, 0x56, 0x56, 0x56, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0xB9, 0x48, 0x48, 0xA6, 0x9B, 0xE3, 0xAA,
+  0xAA, 0x9B, 0x9B, 0x9B, 0xAA, 0xE3, 0xD5, 0xD4,
+  0x9D, 0xA9, 0xA9, 0x9D, 0xEB, 0xAF, 0x23, 0x28,
+  0x2C, 0x29, 0x28, 0x39, 0x54, 0xCC, 0xAF, 0x55,
+  0x30, 0x29, 0x2B, 0x2C, 0x39, 0x39, 0x2B, 0xC4,
+  0x2B, 0x29, 0x39, 0xA7, 0x8E, 0x9D, 0x83, 0xE5,
+  0xB1, 0xDB, 0xDC, 0xE0, 0xDC, 0x84, 0xE9, 0x84,
+  0x83, 0xD4, 0xEC, 0x83, 0x8F, 0xE4, 0x27, 0x27,
+  0x27, 0x27, 0x56, 0x56, 0x56, 0x56, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0xB9, 0x56, 0x40, 0x50, 0x9A, 0x75, 0xE3, 0xE3,
+  0xE3, 0xD9, 0x8D, 0xAA, 0xD9, 0xA8, 0xB2, 0xDC,
+  0xB2, 0x8D, 0x84, 0xEA, 0xB1, 0xEB, 0x54, 0x29,
+  0x28, 0x2C, 0x2A, 0x28, 0x2B, 0x78, 0xCC, 0x58,
+  0xCB, 0x20, 0x20, 0x29, 0x39, 0x39, 0x2C, 0x25,
+  0x29, 0x2C, 0x39, 0xBB, 0xD9, 0xD9, 0x9D, 0x9D,
+  0xB2, 0xB1, 0xD4, 0xDB, 0xB1, 0x9D, 0xD4, 0xEA,
+  0xB1, 0x8D, 0xD8, 0x8E, 0x8F, 0xAA, 0x27, 0x27,
+  0x27, 0x3D, 0x56, 0xB9, 0x56, 0xB9, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0x56,
+  0x56, 0x56, 0x47, 0xE4, 0xA6, 0x75, 0xAA, 0xA8,
+  0x9C, 0x9C, 0xE1, 0x9C, 0x9C, 0x8E, 0xD8, 0x9D,
+  0xA9, 0xDB, 0xA9, 0xDC, 0xD8, 0xDA, 0xD4, 0x2B,
+  0x20, 0x2C, 0x28, 0x2A, 0x28, 0x63, 0x31, 0x58,
+  0xCB, 0x24, 0x20, 0x2B, 0x2C, 0x39, 0x6B, 0x21,
+  0x39, 0x6B, 0x2C, 0xC0, 0xE0, 0xB1, 0xB2, 0x9D,
+  0x8E, 0xD8, 0xE0, 0xD9, 0x84, 0xDB, 0xD8, 0xB1,
+  0x8E, 0xB2, 0xE2, 0x9C, 0x83, 0x9E, 0xBC, 0x3D,
+  0xD3, 0x56, 0x56, 0xB9, 0x56, 0xB9, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0xB9, 0xB9,
+  0x56, 0x4F, 0x27, 0x61, 0xA6, 0x9B, 0xE3, 0xA9,
+  0xE9, 0xD4, 0xDA, 0xDB, 0x8E, 0xE1, 0xE9, 0x8E,
+  0xD4, 0xA8, 0xE0, 0x84, 0xE8, 0xB1, 0xDC, 0x9D,
+  0x20, 0x29, 0x29, 0x2B, 0x2C, 0x54, 0x78, 0xCC,
+  0x78, 0x33, 0x2A, 0x20, 0x29, 0x39, 0x50, 0x2A,
+  0x6B, 0x8B, 0x39, 0xC0, 0x8D, 0xB1, 0xE9, 0xA9,
+  0xB2, 0xDC, 0x8E, 0xDC, 0xE1, 0xDA, 0xA9, 0x8E,
+  0xEA, 0xE2, 0x83, 0xE8, 0x8E, 0x83, 0xE2, 0xED,
+  0xB9, 0xB9, 0x56, 0xB9, 0x56, 0xB9, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0x56, 0x56, 0xB9,
+  0xC9, 0x27, 0x27, 0xE4, 0xA6, 0x9B, 0xD5, 0xA8,
+  0xD4, 0xB2, 0xD8, 0xDA, 0xD9, 0xE8, 0xE9, 0xE8,
+  0xD8, 0xB1, 0xDA, 0xB2, 0xE9, 0x8E, 0xEC, 0xDA,
+  0x22, 0x20, 0x39, 0x2B, 0x39, 0x24, 0xC4, 0x30,
+  0x30, 0x54, 0x22, 0x29, 0x29, 0x39, 0x48, 0x2C,
+  0x39, 0x6B, 0x39, 0xC0, 0x8D, 0xB1, 0xE9, 0xB2,
+  0xB2, 0x8E, 0xA9, 0xD8, 0xDA, 0xB1, 0xA9, 0xDA,
+  0x9C, 0xDC, 0x8E, 0xD4, 0xE8, 0xE8, 0x8F, 0x9B,
+  0x4F, 0xB9, 0x56, 0xB9, 0x56, 0xB9, 0xB9, 0xB9,
+  0xB9, 0xB9, 0xB9, 0xB9, 0x56, 0x56, 0x4F, 0x6B,
+  0x27, 0x27, 0x27, 0xD7, 0xDE, 0xAA, 0xE3, 0xA8,
+  0xB2, 0xD5, 0xE5, 0x90, 0xE2, 0xA9, 0xE9, 0xB2,
+  0xDA, 0xB2, 0xE1, 0xB2, 0xE9, 0x8E, 0xDA, 0xDF,
+  0x78, 0x2A, 0x2C, 0x2A, 0x6B, 0x28, 0x23, 0x54,
+  0x63, 0xC4, 0x33, 0x28, 0x2C, 0x39, 0x47, 0x39,
+  0x28, 0x2C, 0x29, 0xBB, 0x8D, 0x83, 0xE9, 0xD4,
+  0xB2, 0xE9, 0xE9, 0xE8, 0xD4, 0xD8, 0xD4, 0xA9,
+  0xDA, 0xB2, 0xE9, 0xA8, 0xB2, 0xA8, 0xD5, 0xAA,
+  0xC6, 0x56, 0x56, 0x56, 0x56, 0x56, 0xB9, 0x56,
+  0x56, 0x56, 0x56, 0x56, 0x56, 0xC9, 0x27, 0x27,
+  0x27, 0x27, 0x27, 0xB8, 0xB4, 0x9B, 0xE3, 0x8E,
+  0x9D, 0x8E, 0xB2, 0xE8, 0xE8, 0x8E, 0xB2, 0xDA,
+  0xB2, 0x8E, 0xEC, 0xB2, 0x8E, 0xB2, 0xBB, 0x58,
+  0xAF, 0x33, 0x50, 0x39, 0x6B, 0x39, 0x29, 0x20,
+  0x33, 0x30, 0x78, 0x23, 0x6B, 0x6B, 0x48, 0x6B,
+  0x2B, 0x2A, 0x29, 0xBB, 0xE5, 0x9C, 0xB1, 0xB2,
+  0xE5, 0x84, 0x8E, 0x9C, 0x84, 0xB2, 0xB2, 0x9D,
+  0x84, 0xDF, 0xA9, 0x84, 0x8E, 0xA8, 0xE3, 0x9B,
+  0xA6, 0xD7, 0x80, 0x4F, 0x56, 0x56, 0x56, 0x4F,
+  0x4F, 0x4F, 0x4F, 0x2A, 0x2D, 0x27, 0x27, 0x27,
+  0x27, 0x27, 0x27, 0xB8, 0xB4, 0xAA, 0xD5, 0xA9,
+  0x9D, 0xB2, 0x90, 0xEA, 0xE9, 0xE2, 0xE1, 0x8E,
+  0xB2, 0x9D, 0x8E, 0xB1, 0xA7, 0xEE, 0x63, 0xD1,
+  0x2E, 0xCC, 0x28, 0x48, 0x8B, 0x47, 0x6B, 0x28,
+  0x23, 0x78, 0x6C, 0x54, 0x29, 0x50, 0x50, 0x6B,
+  0x23, 0x20, 0xBB, 0xBC, 0xBB, 0x8D, 0xE3, 0xDF,
+  0x9C, 0xA9, 0x8D, 0xA8, 0xD9, 0x90, 0x9D, 0xA9,
+  0xDC, 0xA9, 0x83, 0xB2, 0xA9, 0xD4, 0xE3, 0x9B,
+  0x8C, 0xEF, 0x27, 0x27, 0x27, 0x3C, 0x27, 0x27,
+  0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27,
+  0x27, 0x27, 0x27, 0xF0, 0xB4, 0x9B, 0xE3, 0x84,
+  0x9D, 0x84, 0x90, 0xB1, 0xA9, 0x9C, 0xD9, 0xB1,
+  0xB2, 0xEA, 0xBB, 0x51, 0x24, 0x30, 0x30, 0x42,
+  0x66, 0x58, 0x24, 0x48, 0x50, 0x3F, 0x20, 0x25,
+  0x22, 0x60, 0x34, 0x30, 0x20, 0x8B, 0x8B, 0x39,
+  0x54, 0x24, 0x2B, 0xC0, 0xC0, 0xC0, 0xBB, 0x9B,
+  0xBC, 0xAA, 0xAA, 0xE3, 0xE3, 0x9C, 0xB2, 0xD4,
+  0x83, 0xD8, 0xE8, 0x83, 0x84, 0xE8, 0xE5, 0x75,
+  0x9A, 0xF0, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27,
+  0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27,
+  0x27, 0x27, 0x27, 0xF0, 0xB4, 0x9B, 0xE3, 0xA8,
+  0xA9, 0xD8, 0x8E, 0xEA, 0xA8, 0x9C, 0xD9, 0xE0,
+  0xC0, 0x5E, 0x2C, 0x20, 0x54, 0x60, 0x30, 0x66,
+  0xB6, 0xCC, 0x63, 0x3F, 0x8B, 0x28, 0x22, 0x33,
+  0x23, 0x31, 0xAF, 0x31, 0x22, 0x6B, 0x6B, 0x29,
+  0x30, 0x54, 0x22, 0x89, 0xBA, 0xED, 0xA6, 0x8C,
+  0xB4, 0xC0, 0xB4, 0x75, 0x75, 0x9B, 0x9B, 0xE5,
+  0xA9, 0xD5, 0x8E, 0x8E, 0x9C, 0xE3, 0x75, 0x8C,
+  0xC8, 0xF1, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27,
+  0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27,
+  0x27, 0x27, 0x27, 0xF1, 0x9A, 0xB4, 0x9B, 0xE3,
+  0xE3, 0xA8, 0xE3, 0xE5, 0xAA, 0xBC, 0xC0, 0x9A,
+  0x26, 0x29, 0x20, 0x24, 0x63, 0x60, 0x54, 0x43,
+  0x34, 0xCB, 0x30, 0x39, 0x2C, 0x20, 0x24, 0x54,
+  0x22, 0x34, 0x34, 0x31, 0x24, 0x3F, 0x2C, 0x2B,
+  0x31, 0x30, 0x25, 0x2A, 0x6B, 0x29, 0x20, 0xF2,
+  0xBA, 0xBF, 0xC8, 0x9A, 0xA6, 0xA6, 0x8C, 0xB4,
+  0x9B, 0xAA, 0xAA, 0xAA, 0x9B, 0x75, 0xDE, 0xBF,
+  0x81, 0xEF, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27,
+  0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27,
+  0x27, 0x27, 0x27, 0xEF, 0xBA, 0x9A, 0xB4, 0x75,
+  0x9B, 0x9B, 0x9B, 0xC0, 0xB4, 0x9A, 0xA5, 0xC4,
+  0x30, 0x28, 0x22, 0x33, 0x30, 0x30, 0x23, 0x34,
+  0x31, 0x30, 0xC4, 0x2C, 0x2B, 0x22, 0x33, 0x63,
+  0x21, 0x58, 0x6C, 0x60, 0x25, 0x39, 0x28, 0x2B,
+  0xCC, 0x6C, 0x63, 0x20, 0x6B, 0x28, 0x2B, 0x20,
+  0x63, 0x43, 0xF3, 0xEF, 0xF0, 0x81, 0xBA, 0xF4,
+  0xF4, 0xA6, 0xDE, 0x8C, 0xA6, 0x9A, 0xBA, 0x81,
+  0xB0, 0xE4, 0xA1, 0x20, 0x20, 0x23, 0x31, 0xC4,
+  0x30, 0x24, 0x33, 0x31, 0x31, 0x60, 0x43, 0x35,
+  0x35, 0x55, 0x6C, 0xEF, 0x81, 0xC8, 0x9A, 0xA6,
+  0xB4, 0xB4, 0x8C, 0xA6, 0xBA, 0x68, 0x30, 0x30,
+  0x30, 0x2B, 0x25, 0x54, 0xC4, 0x54, 0x24, 0x78,
+  0x63, 0x63, 0x30, 0x29, 0x21, 0x24, 0x54, 0x63,
+  0x23, 0x34, 0xCB, 0x30, 0x25, 0x39, 0x20, 0x20,
+  0x58, 0x34, 0x60, 0x23, 0x6B, 0x29, 0x28, 0x20,
+  0x22, 0xB6, 0x42, 0xB6, 0x58, 0x54, 0xF5, 0xD7,
+  0xA5, 0xBA, 0xBA, 0xBA, 0xBA, 0x81, 0xA5, 0xF1,
+  0xE4, 0x2A, 0x39, 0x20, 0x20, 0x20, 0x31, 0x60,
+  0x54, 0x28, 0x2B, 0x22, 0x33, 0x30, 0x43, 0x35,
+  0x66, 0xD1, 0x34, 0xE4, 0xEF, 0x81, 0xC8, 0x9A,
+  0x9A, 0xC8, 0xC8, 0x81, 0xF6, 0x31, 0x63, 0x31,
+  0x78, 0x2B, 0x54, 0x63, 0x54, 0x24, 0x23, 0x54,
+  0x63, 0x54, 0x63, 0x2C, 0x23, 0x33, 0x63, 0x54,
+  0x25, 0x31, 0x78, 0x30, 0x25, 0x3F, 0x20, 0x20,
+  0xAF, 0x58, 0xCC, 0x33, 0x39, 0x29, 0x29, 0x2A,
+  0x29, 0x58, 0x43, 0x42, 0xD1, 0xCB, 0x2C, 0x2C,
+  0x37, 0xCD, 0xEF, 0xB0, 0xF0, 0xB0, 0xEF, 0xE4,
+  0x63, 0x20, 0x20, 0x2C, 0x2C, 0x21, 0xCB, 0x78,
+  0x54, 0x39, 0x39, 0x28, 0x2B, 0x28, 0x2B, 0xCB,
+  0x55, 0xB6, 0xD1, 0x28, 0xE4, 0xD7, 0xB8, 0xF0,
+  0xA5, 0xB0, 0xEF, 0x26, 0x23, 0x54, 0x31, 0x58,
+  0xCB, 0x20, 0x63, 0x63, 0x25, 0x2B, 0x54, 0x78,
+  0x30, 0x63, 0x54, 0x28, 0x33, 0x63, 0x63, 0x33,
+  0x54, 0x78, 0xC4, 0x30, 0x24, 0x2C, 0x22, 0x22,
+  0x55, 0x55, 0x34, 0x30, 0x28, 0x2C, 0x29, 0x29,
+  0x28, 0x30, 0xB6, 0x42, 0x43, 0x55, 0x22, 0x29,
+  0x2C, 0x2B, 0x2B, 0x3F, 0xE4, 0xE4, 0x43, 0x66,
+  0x30, 0x23, 0x24, 0x2A, 0x28, 0x2B, 0x54, 0x63,
+  0x33, 0x39, 0x28, 0x20, 0x20, 0x20, 0x2B, 0x31,
+  0x30, 0xD1, 0x43, 0x30, 0x39, 0x28, 0xE4, 0xE4,
+  0xD7, 0xF5, 0x2B, 0x6B, 0x20, 0x30, 0x34, 0xD1,
+  0x60, 0x23, 0x63, 0x54, 0x22, 0x47, 0x60, 0xCB,
+  0xC4, 0xC4, 0x25, 0x22, 0x54, 0xC4, 0x63, 0x23,
+  0xC4, 0xC4, 0x63, 0xC4, 0x23, 0x2A, 0x24, 0x22,
+  0x55, 0x55, 0xAF, 0x6C, 0x22, 0x39, 0x2C, 0x39,
+  0x28, 0x23, 0xD1, 0x43, 0x42, 0x8A, 0x63, 0x39,
+  0x39, 0x2A, 0x20, 0x6B, 0x33, 0xCC, 0xD1, 0xB6,
+  0x30, 0x24, 0x54, 0x63, 0x31, 0xCC, 0xCC, 0xCB,
+  0xC4, 0x2A, 0x39, 0x20, 0x20, 0x20, 0x39, 0x30,
+  0x30, 0x6C, 0x43, 0x43, 0x6C, 0x63, 0x25, 0x24,
+  0x63, 0x63, 0x63, 0x25, 0x63, 0xCC, 0xD1, 0x34,
+  0x63, 0x25, 0x54, 0x25, 0x2A, 0x28, 0x31, 0xCB,
+  0x63, 0x78, 0x24, 0x33, 0xC4, 0xC4, 0x33, 0x2C,
+  0xC4, 0x54, 0x54, 0x30, 0x21, 0x22, 0x25, 0x23,
+  0x55, 0x55, 0xD1, 0x58, 0x33, 0x6B, 0x2C, 0x39,
+  0x39, 0x39, 0x34, 0x43, 0x42, 0x43, 0xCC, 0x2B,
+  0x28, 0x29, 0x20, 0x28, 0x21, 0x30, 0xCC, 0xAF,
+  0x54, 0x23, 0xC4, 0x54, 0x58, 0x2E, 0x35, 0x42,
+  0x55, 0x54, 0x8B, 0x2A, 0x20, 0x20, 0x28, 0x22,
+  0x78, 0x30, 0xD1, 0x43, 0x44, 0x6C, 0xC4, 0xC4,
+  0x60, 0x31, 0x31, 0x63, 0x6C, 0xAF, 0xCC, 0xCB,
+  0x24, 0x25, 0x33, 0x23, 0x2C, 0x24, 0x31, 0x30,
+  0x63, 0xC4, 0x21, 0x54, 0x30, 0x63, 0x24, 0x2A,
+  0x54, 0x63, 0x54, 0xC4, 0x2B, 0x24, 0x33, 0x24,
+  0x34, 0x55, 0xD1, 0x55, 0x30, 0x28, 0x29, 0x39,
+  0x39, 0x8B, 0x63, 0x55, 0x42, 0x66, 0xB6, 0x25,
+  0x29, 0x29, 0x29, 0x28, 0x2A, 0x54, 0x78, 0x6C,
+  0x23, 0x20, 0x25, 0x30, 0xCB, 0x62, 0x35, 0x35,
+  0x35, 0x44, 0x24, 0x6B, 0x29, 0x20, 0x2A, 0x39,
+  0x28, 0x63, 0x34, 0xB6, 0x34, 0xCB, 0x63, 0x30,
+  0x31, 0x31, 0x30, 0x30, 0xCC, 0x60, 0x63, 0xC4,
+  0x20, 0x33, 0x25, 0x20, 0x48, 0x33, 0x30, 0x54,
+  0x78, 0x54, 0x2B, 0x63, 0x30, 0x63, 0x23, 0x22,
+  0x63, 0x63, 0x63, 0x33, 0x28, 0x25, 0x54, 0x24,
+  0x78, 0xAF, 0xD1, 0xD1, 0xCC, 0x22, 0x39, 0x39,
+  0x2C, 0x3F, 0x2B, 0x34, 0xB6, 0x43, 0x43, 0xC4,
+  0x2B, 0x28, 0x39, 0x50, 0x2C, 0x24, 0x63, 0x78,
+  0x21, 0x2C, 0x2A, 0x23, 0x54, 0xD1, 0x35, 0x35,
+  0x35, 0x35, 0x55, 0x22, 0x39, 0x2C, 0x2C, 0x2C,
+  0x20, 0x30, 0xCC, 0x6C, 0xCB, 0x30, 0x54, 0x30,
+  0x78, 0x63, 0x78, 0x30, 0x54, 0x78, 0x30, 0x23,
+  0x2B, 0x33, 0x24, 0x28, 0x39, 0x24, 0x54, 0x30,
+  0x78, 0x33, 0x25, 0xC4, 0xC4, 0x33, 0x39, 0x25,
+  0xC4, 0x63, 0xC4, 0x24, 0x20, 0x54, 0x54, 0x25,
+  0x63, 0xCC, 0xD1, 0xB6, 0x55, 0x54, 0x39, 0x29,
+  0x39, 0x2C, 0x6B, 0x30, 0xAF, 0xB6, 0xB6, 0x60,
+  0x22, 0x2A, 0x2C, 0x39, 0x2C, 0x21, 0x54, 0x63,
+  0x21, 0x50, 0x2C, 0x2C, 0x2B, 0x25, 0x62, 0x35,
+  0x35, 0x35, 0x35, 0xCC, 0x2B, 0x29, 0x2B, 0x20,
+  0x23, 0x25, 0xC4, 0x30, 0xC4, 0x63, 0x63, 0x63,
+  0x63, 0x33, 0x24, 0x31, 0x31, 0x31, 0x54, 0x28,
+  0x24, 0x25, 0x22, 0x6B, 0x28, 0x24, 0xC4, 0x78,
+  0x30, 0x24, 0x63, 0xC4, 0x54, 0x23, 0x29, 0x63,
+  0xC4, 0x54, 0xC4, 0x21, 0x24, 0x54, 0x54, 0x25,
+  0x30, 0xCB, 0xD1, 0xB6, 0x55, 0x63, 0x28, 0x29,
+  0x39, 0x39, 0x48, 0x33, 0x58, 0x44, 0xB6, 0x60,
+  0x24, 0x20, 0x2B, 0x28, 0x2A, 0x22, 0x54, 0x63,
+  0x21, 0x48, 0x2A, 0x2B, 0x39, 0x21, 0xB6, 0x35,
+  0x35, 0x35, 0x35, 0x42, 0x23, 0x29, 0x2A, 0x2B,
+  0x23, 0x25, 0x54, 0x54, 0x54, 0x63, 0x63, 0x30,
+  0x25, 0x2B, 0x31, 0x31, 0x31, 0x31, 0x21, 0x2C,
+  0x33, 0x25, 0x21, 0x39, 0x20, 0x25, 0x30, 0x78,
+  0xC4, 0x23, 0xC4, 0x30, 0x54, 0x20, 0x28, 0x63,
+  0x63, 0x63, 0x63, 0x20, 0x25, 0x54, 0x54, 0x20,
+};
+
+unsigned char linux_logo_bw[] __initdata = {
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x3F,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F,
+  0xFE, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xFE, 0x3F, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xFE, 0x7F, 0xFF, 0xC7, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xC3,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF,
+  0xFB, 0xE3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xFD, 0xFF, 0xFF, 0xE1, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xF1,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xFF,
+  0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xF9, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xF9, 0xCF, 0xC3, 0xF8, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x87, 0x81, 0xF9,
+  0xF8, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xA7,
+  0x99, 0xF9, 0xC2, 0x40, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xF9, 0xF3, 0xBC, 0xF9, 0x90, 0x00, 0x1F, 0xFF,
+  0xFF, 0xFF, 0xF9, 0xE3, 0xBC, 0xF9, 0xA0, 0x00,
+  0x8F, 0xFF, 0xFF, 0xFF, 0xF9, 0xB0, 0x3C, 0xF9,
+  0x83, 0xE0, 0x2F, 0xFF, 0xFF, 0xFF, 0xF9, 0xB0,
+  0x19, 0xF0, 0x1F, 0xFE, 0x0F, 0xFF, 0xFF, 0xFF,
+  0xF9, 0xC0, 0x03, 0xF0, 0x3F, 0xF7, 0x8F, 0xFF,
+  0xFF, 0xFF, 0xF9, 0x80, 0x01, 0xF8, 0x7F, 0xF7,
+  0xC7, 0xFF, 0xFF, 0xFF, 0xF9, 0x80, 0x01, 0xF8,
+  0x6F, 0xF7, 0xE7, 0xFF, 0xFF, 0xFF, 0xF9, 0x80,
+  0x01, 0xF8, 0x7F, 0xF7, 0xE7, 0xFF, 0xFF, 0xFF,
+  0xF9, 0xC0, 0x21, 0xD8, 0x7F, 0xE7, 0xEF, 0xFF,
+  0xFF, 0xFF, 0xF9, 0xB1, 0x80, 0xEC, 0x7B, 0xFF,
+  0xEF, 0xFF, 0xFF, 0xFF, 0xF1, 0x90, 0x00, 0xE4,
+  0x7B, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xF1, 0x8C,
+  0xC0, 0x7C, 0x79, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF,
+  0xE3, 0x80, 0x00, 0x7C, 0x7C, 0xFF, 0xCF, 0xFF,
+  0xFF, 0xFF, 0xE3, 0x80, 0x00, 0x7F, 0x77, 0xFF,
+  0xDF, 0xFF, 0xFF, 0xFF, 0x87, 0x00, 0x00, 0x3F,
+  0x3F, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0x0E, 0x00,
+  0x00, 0x3F, 0xBF, 0xFF, 0x9F, 0xFF, 0xFF, 0xFF,
+  0x1E, 0x00, 0x00, 0x1F, 0x9F, 0xFF, 0x3F, 0xFF,
+  0xFF, 0xFE, 0x1C, 0x00, 0x00, 0x1F, 0x9F, 0xFF,
+  0x7F, 0xFF, 0xFF, 0xFE, 0x3C, 0x00, 0x00, 0x1F,
+  0x8F, 0xFE, 0x7F, 0xFF, 0xFF, 0xFC, 0x7C, 0x00,
+  0x00, 0x0F, 0xC7, 0xFC, 0xFF, 0xFF, 0xFF, 0xFC,
+  0xF8, 0x00, 0x00, 0x0F, 0xF7, 0xF9, 0xFF, 0xFF,
+  0xFF, 0xFC, 0xF8, 0x00, 0x00, 0x07, 0xFB, 0xF3,
+  0xFF, 0xFF, 0xFF, 0xF8, 0xF8, 0x00, 0x00, 0x07,
+  0xFD, 0xE7, 0xFF, 0xFF, 0xFF, 0xF9, 0xF0, 0x00,
+  0x00, 0x03, 0xFE, 0x8F, 0xFF, 0xFF, 0xFF, 0xF1,
+  0xF0, 0x00, 0x00, 0x03, 0xFE, 0x1F, 0xFF, 0xFF,
+  0xFF, 0xF1, 0xE0, 0x00, 0x00, 0x00, 0xFF, 0xBF,
+  0xFF, 0xFF, 0xFF, 0xE3, 0xE0, 0x00, 0x00, 0x00,
+  0xFE, 0xBF, 0xFF, 0xFF, 0xFF, 0xE3, 0xC0, 0x00,
+  0x00, 0x00, 0xFE, 0x3F, 0xFF, 0xFF, 0xFF, 0xC7,
+  0xC0, 0x00, 0x00, 0x01, 0xFE, 0xBF, 0xFF, 0xFF,
+  0xFF, 0xC7, 0x80, 0x00, 0x00, 0x01, 0xFE, 0x9F,
+  0xFF, 0xFF, 0xFF, 0x8F, 0x80, 0x00, 0x00, 0x01,
+  0xFE, 0x07, 0xFF, 0xFF, 0xFF, 0x8F, 0x80, 0x00,
+  0x00, 0x01, 0xFE, 0x87, 0xFF, 0xFF, 0xFF, 0x9F,
+  0x80, 0x00, 0x00, 0x01, 0xFD, 0x33, 0xFF, 0xFF,
+  0xFF, 0x9F, 0x80, 0x00, 0x00, 0x01, 0x80, 0xF3,
+  0xFF, 0xFF, 0xFF, 0x9E, 0x80, 0x00, 0x00, 0x03,
+  0x8B, 0xF9, 0xFF, 0xFF, 0xFF, 0x9F, 0x80, 0x00,
+  0x00, 0x02, 0x27, 0xF8, 0xFF, 0xFF, 0xFF, 0x99,
+  0x80, 0x00, 0x00, 0x00, 0x07, 0xF8, 0xFF, 0xFF,
+  0xFF, 0x00, 0x80, 0x00, 0x00, 0x01, 0x8F, 0xF8,
+  0xFF, 0xFF, 0xFE, 0x20, 0x60, 0x00, 0x00, 0x00,
+  0xE3, 0xF8, 0xFF, 0xFF, 0xF8, 0x00, 0x30, 0x00,
+  0x00, 0x00, 0xF8, 0x78, 0xFF, 0xFF, 0xC0, 0x40,
+  0x38, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x7F, 0xFF,
+  0x81, 0x00, 0x1C, 0x00, 0x00, 0x00, 0xFC, 0x20,
+  0x7F, 0xFF, 0x90, 0x00, 0x1E, 0x00, 0x00, 0x00,
+  0x78, 0x10, 0xFF, 0xFF, 0x80, 0x00, 0x0F, 0x80,
+  0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x80, 0x00,
+  0x07, 0xC0, 0x00, 0x00, 0x00, 0x08, 0xFF, 0xFF,
+  0xC0, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x04,
+  0x7F, 0xFF, 0x80, 0x00, 0x03, 0xC0, 0x00, 0x10,
+  0x00, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x01, 0x80,
+  0x00, 0x30, 0x00, 0x00, 0x0F, 0xFF, 0x80, 0x00,
+  0x00, 0x00, 0x00, 0x70, 0x00, 0x01, 0x4F, 0xFF,
+  0x80, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00,
+  0x0F, 0xFF, 0xC0, 0x00, 0x00, 0x80, 0x03, 0xF0,
+  0x00, 0x00, 0x8F, 0xFF, 0x80, 0x00, 0x00, 0x40,
+  0x0F, 0xF0, 0x00, 0x04, 0x1F, 0xFF, 0x80, 0x00,
+  0x00, 0x7F, 0xFF, 0xF0, 0x00, 0x10, 0x1F, 0xFF,
+  0xC0, 0x00, 0x00, 0x7F, 0xFF, 0xF0, 0x00, 0x40,
+  0xFF, 0xFF, 0x98, 0x00, 0x00, 0xFF, 0xFF, 0xF0,
+  0x00, 0x83, 0xFF, 0xFF, 0x81, 0xE0, 0x01, 0xFF,
+  0xFF, 0xF8, 0x02, 0x07, 0xFF, 0xFF, 0x80, 0x3F,
+  0x07, 0xE0, 0x00, 0x1C, 0x0C, 0x1F, 0xFF, 0xFF,
+  0xF8, 0x03, 0xFF, 0x80, 0x00, 0x1F, 0x78, 0x1F,
+  0xFF, 0xFF, 0xFF, 0x80, 0x7F, 0x00, 0x07, 0x0F,
+  0xF0, 0x7F, 0xFF, 0xFF, 0xFF, 0xFE, 0x0C, 0x07,
+  0xFF, 0x83, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+  0x00, 0x1F, 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x07, 0xFF,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+};
+
+/* Painted by Johnny Stenback <jst@uwasa.fi> */
+
+unsigned char *linux_serial_image __initdata = "\n"
+"         .u$e.\n"
+"       .$$$$$:S\n"
+"       $\"*$/\"*$$\n"
+"       $.`$ . ^F\n"
+"       4k+#+T.$F\n"
+"       4P+++\"$\"$\n"
+"       :R\"+  t$$B\n"
+"    ___#       $$$\n"
+"    |  |       R$$k\n"
+"   dd. | Linux  $!$\n"
+"   ddd |  Sparc $9$F\n"
+" '!!!!!$       !!#!`\n"
+"  !!!!!*     .!!!!!`\n"
+"'!!!!!!!W..e$$!!!!!!`    %s\n"
+" \"~^^~         ^~~^\n"
+"\n";
diff -u --recursive --new-file v2.1.35/linux/include/asm-sparc64/pgtable.h linux/include/asm-sparc64/pgtable.h
--- v2.1.35/linux/include/asm-sparc64/pgtable.h	Mon Apr 14 16:28:23 1997
+++ linux/include/asm-sparc64/pgtable.h	Tue Apr 15 21:47:24 1997
@@ -1,4 +1,4 @@
-/* $Id: pgtable.h,v 1.27 1997/04/10 23:32:46 davem Exp $
+/* $Id: pgtable.h,v 1.28 1997/04/14 17:05:19 jj Exp $
  * pgtable.h: SpitFire page table operations.
  *
  * Copyright 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -672,6 +672,31 @@
 #define SWP_TYPE(entry)		(((entry>>PAGE_SHIFT) & 0xff))
 #define SWP_OFFSET(entry)	((entry) >> (PAGE_SHIFT+8))
 #define SWP_ENTRY(type,offset)	pte_val(mk_swap_pte((type),(offset)))
+
+extern __inline__ unsigned long
+sun4u_get_pte (unsigned long addr)
+{
+	pgd_t *pgdp;
+	pmd_t *pmdp;
+	pte_t *ptep;
+	
+	pgdp = pgd_offset (current->mm, addr);
+	pmdp = pmd_offset (pgdp, addr);
+	ptep = pte_offset (pmdp, addr);
+	return pte_val (*ptep) & _PAGE_PADDR;
+}
+
+extern __inline__ unsigned int
+__get_phys (unsigned long addr)
+{
+	return (sun4u_get_pte (addr) & 0x0fffffff);
+}
+
+extern __inline__ int
+__get_iospace (unsigned long addr)
+{
+	return ((sun4u_get_pte (addr) & 0xf0000000) >> 28);
+}
 
 #endif /* !(__ASSEMBLY__) */
 
diff -u --recursive --new-file v2.1.35/linux/include/asm-sparc64/posix_types.h linux/include/asm-sparc64/posix_types.h
--- v2.1.35/linux/include/asm-sparc64/posix_types.h	Mon Apr 14 16:28:23 1997
+++ linux/include/asm-sparc64/posix_types.h	Tue Apr 15 21:47:24 1997
@@ -34,6 +34,27 @@
 	int	val[2];
 } __kernel_fsid_t;
 
+/* Now 32bit compatibility types */
+typedef unsigned int           __kernel_size_t32;
+typedef int                    __kernel_ssize_t32;
+typedef int                    __kernel_ptrdiff_t32;
+typedef int                    __kernel_time_t32;
+typedef int                    __kernel_clock_t32;
+typedef int                    __kernel_pid_t32;
+typedef unsigned short         __kernel_ipc_pid_t32;
+typedef unsigned short         __kernel_uid_t32;
+typedef unsigned short         __kernel_gid_t32;
+typedef unsigned short         __kernel_dev_t32;
+typedef unsigned int           __kernel_ino_t32;
+typedef unsigned short         __kernel_mode_t32;
+typedef unsigned short         __kernel_umode_t32;
+typedef short                  __kernel_nlink_t32;
+typedef int                    __kernel_daddr_t32;
+typedef int                    __kernel_off_t32;
+typedef unsigned int           __kernel_caddr_t32;
+typedef long		       __kernel_loff_t32;
+typedef __kernel_fsid_t        __kernel_fsid_t32;
+
 #undef __FD_SET
 static __inline__ void __FD_SET(unsigned long fd, __kernel_fd_set *fdsetp)
 {
diff -u --recursive --new-file v2.1.35/linux/include/asm-sparc64/processor.h linux/include/asm-sparc64/processor.h
--- v2.1.35/linux/include/asm-sparc64/processor.h	Mon Apr 14 16:28:23 1997
+++ linux/include/asm-sparc64/processor.h	Tue Apr 15 21:47:24 1997
@@ -1,4 +1,4 @@
-/* $Id: processor.h,v 1.20 1997/04/11 22:34:54 davem Exp $
+/* $Id: processor.h,v 1.21 1997/04/14 17:05:18 jj Exp $
  * include/asm-sparc64/processor.h
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -132,6 +132,7 @@
 	"stx		%%g0, [%0 + %2 + 0x68]\n\t" \
 	"stx		%1,   [%0 + %2 + 0x70]\n\t" \
 	"stx		%%g0, [%0 + %2 + 0x78]\n\t" \
+	"wrpr		%%g0, 1, %%wstate\n\t" \
 	: \
 	: "r" (regs), "r" (sp - REGWIN_SZ), \
 	  "i" ((const unsigned long)(&((struct pt_regs *)0)->u_regs[0]))); \
@@ -167,6 +168,7 @@
 	"stx		%%g0, [%0 + %2 + 0x68]\n\t" \
 	"stx		%1,   [%0 + %2 + 0x70]\n\t" \
 	"stx		%%g0, [%0 + %2 + 0x78]\n\t" \
+	"wrpr		%%g0, 2, %%wstate\n\t" \
 	: \
 	: "r" (regs), "r" (sp - REGWIN32_SZ), \
 	  "i" ((const unsigned long)(&((struct pt_regs *)0)->u_regs[0])), \
diff -u --recursive --new-file v2.1.35/linux/include/asm-sparc64/semaphore.h linux/include/asm-sparc64/semaphore.h
--- v2.1.35/linux/include/asm-sparc64/semaphore.h	Mon Apr 14 16:28:24 1997
+++ linux/include/asm-sparc64/semaphore.h	Thu Apr 17 13:20:51 1997
@@ -2,8 +2,10 @@
 #define _SPARC64_SEMAPHORE_H
 
 /* These are actually reasonable on the V9. */
+#ifdef __KERNEL__
 
 #include <asm/atomic.h>
+#include <asm/system.h>
 
 struct semaphore {
 	atomic_t count;
@@ -11,8 +13,8 @@
 	struct wait_queue * wait;
 };
 
-#define MUTEX ((struct semaphore) { { 1 }, { 0 }, NULL })
-#define MUTEX_LOCKED ((struct semaphore) { { 0 }, { 0 }, NULL })
+#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);
@@ -20,6 +22,23 @@
 
 #define sema_init(sem, val)	atomic_set(&((sem)->count), val)
 
+#define wake_one_more(sem)      atomic_inc(&sem->waking);
+
+extern __inline__ int waking_non_zero(struct semaphore *sem)
+{
+        unsigned long flags;
+        int ret = 0;
+
+        save_flags(flags);
+        cli();
+        if (atomic_read(&sem->waking) > 0) {
+                atomic_dec(&sem->waking);
+                ret = 1;
+        }
+        restore_flags(flags);
+        return ret;
+}
+
 extern __inline__ void down(struct semaphore * sem)
 {
 	if (atomic_dec_return(&sem->count) < 0)
@@ -39,5 +58,7 @@
 	if (atomic_inc_return(&sem->count) <= 0)
 		__up(sem);
 }	
+
+#endif /* __KERNEL__ */
 
 #endif /* !(_SPARC64_SEMAPHORE_H) */
diff -u --recursive --new-file v2.1.35/linux/include/asm-sparc64/signal.h linux/include/asm-sparc64/signal.h
--- v2.1.35/linux/include/asm-sparc64/signal.h	Mon Mar 17 14:54:34 1997
+++ linux/include/asm-sparc64/signal.h	Tue Apr 22 22:39:21 1997
@@ -1,4 +1,4 @@
-/* $Id: signal.h,v 1.2 1997/03/03 16:51:57 jj Exp $ */
+/* $Id: signal.h,v 1.3 1997/04/18 14:34:47 jj Exp $ */
 #ifndef _ASMSPARC64_SIGNAL_H
 #define _ASMSPARC64_SIGNAL_H
 
@@ -83,7 +83,7 @@
 #ifndef __ASSEMBLY__
 
 typedef unsigned long sigset_t;
-typedef unsigned int sigset32_t;
+typedef unsigned int sigset_t32;
 
 #ifdef __KERNEL__
 #include <asm/sigcontext.h>
@@ -165,10 +165,8 @@
 
 struct sigaction32 {
 	unsigned	sa_handler;
-	sigset32_t      sa_mask;
+	sigset_t32      sa_mask;
 	unsigned int    sa_flags;
-
-	/* XXX 32-bit func ptr... */
 	unsigned	sa_restorer;     /* not used by Linux/SPARC yet */
 };
 
diff -u --recursive --new-file v2.1.35/linux/include/asm-sparc64/smp.h linux/include/asm-sparc64/smp.h
--- v2.1.35/linux/include/asm-sparc64/smp.h	Mon Apr 14 16:28:24 1997
+++ linux/include/asm-sparc64/smp.h	Tue Apr 15 21:47:24 1997
@@ -106,51 +106,6 @@
 
 
 extern __volatile__ unsigned long smp_proc_in_lock[NR_CPUS]; /* for computing process time */
-extern __volatile__ int smp_process_available;
-
-extern __inline__ __volatile__ void inc_smp_counter(volatile int *ctr)
-{
-	unsigned long temp0, temp1;
-
-	__asm__ __volatile__("
-	lduw		[%2], %0
-1:
-	add		%0, 1, %1
-	cas		[%2], %0, %1
-	cmp		%0, %1
-	bne,a,pn	%%icc, 1b
-	 lduw		[%2], %0
-2:
-	membar		#StoreStore | #StoreLoad
-" 	: "=&r" (temp0), "=&r" (temp1), "=r" (ctr)
-	: "ir" (i), "r" (ctr)
-	: "cc");
-}
-
-extern __inline__ __volatile__ void dec_smp_counter(volatile int *ctr)
-{
-	unsigned long temp0, temp1;
-
-	__asm__ __volatile__("
-	lduw		[%2], %0
-1:
-	sub		%0, 1, %1
-	cas		[%2], %0, %1
-	cmp		%0, %1
-	bne,a,pn	%%icc, 1b
-	 lduw		[%2], %0
-2:
-	membar		#StoreStore | #StoreLoad
-" 	: "=&r" (temp0), "=&r" (temp1), "=r" (ctr)
-	: "ir" (i), "r" (ctr)
-	: "cc");
-}
-
-extern __inline__ __volatile__ int read_smp_counter(volatile int *ctr)
-{
-	return *ctr;
-}
-
 #endif /* !(__ASSEMBLY__) */
 
 /* Sparc specific messages. */
diff -u --recursive --new-file v2.1.35/linux/include/asm-sparc64/smp_lock.h linux/include/asm-sparc64/smp_lock.h
--- v2.1.35/linux/include/asm-sparc64/smp_lock.h	Mon Apr 14 16:28:24 1997
+++ linux/include/asm-sparc64/smp_lock.h	Thu Apr 17 09:24:45 1997
@@ -15,7 +15,7 @@
 #define lock_kernel()				do { } while(0)
 #define unlock_kernel()				do { } while(0)
 #define release_kernel_lock(task, cpu, depth)	((depth) = 1)
-#define reaquire_kernel_lock(task, cpu, depth)	do { } while(0)
+#define reacquire_kernel_lock(task, cpu, depth)	do { } while(0)
 
 #else
 #error SMP on sparc64 not supported yet
diff -u --recursive --new-file v2.1.35/linux/include/asm-sparc64/softirq.h linux/include/asm-sparc64/softirq.h
--- v2.1.35/linux/include/asm-sparc64/softirq.h	Mon Apr 14 16:28:24 1997
+++ linux/include/asm-sparc64/softirq.h	Tue Apr 22 22:39:21 1997
@@ -34,6 +34,12 @@
 	bh_mask |= 1 << ent;	\
 } while(0)
 
+#define remove_bh(nr)		\
+do {	int ent = nr;		\
+	bh_base[ent] = NULL;	\
+	bh_mask &= ~(1 << ent);	\
+} while(0)
+
 #define mark_bh(nr)		(bh_active |= (1 << (nr)))
 
 #define disable_bh(nr)		\
diff -u --recursive --new-file v2.1.35/linux/include/asm-sparc64/spinlock.h linux/include/asm-sparc64/spinlock.h
--- v2.1.35/linux/include/asm-sparc64/spinlock.h	Mon Apr 14 16:28:24 1997
+++ linux/include/asm-sparc64/spinlock.h	Tue Apr 22 22:39:21 1997
@@ -16,12 +16,40 @@
 #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 /* !(__SMP__) */
 #error SMP not supported on sparc64
diff -u --recursive --new-file v2.1.35/linux/include/asm-sparc64/stat.h linux/include/asm-sparc64/stat.h
--- v2.1.35/linux/include/asm-sparc64/stat.h	Mon Dec 30 02:00:03 1996
+++ linux/include/asm-sparc64/stat.h	Tue Apr 22 22:39:21 1997
@@ -1,41 +1,26 @@
-/* $Id: stat.h,v 1.1 1996/12/26 14:22:31 davem Exp $ */
+/* $Id: stat.h,v 1.3 1997/04/18 14:34:43 jj Exp $ */
 #ifndef _SPARC64_STAT_H
 #define _SPARC64_STAT_H
 
 #include <linux/types.h>
 
-struct __old_kernel_stat {
-	unsigned short st_dev;
-	unsigned short st_ino;
-	unsigned short st_mode;
-	unsigned short st_nlink;
-	unsigned short st_uid;
-	unsigned short st_gid;
-	unsigned short st_rdev;
-	unsigned long  st_size;
-	unsigned long  st_atime;
-	unsigned long  st_mtime;
-	unsigned long  st_ctime;
-};
-
-/* XXX Fix this for full backwards 32-bit compat. */
 struct stat32 {
-	dev_t   st_dev;
-	ino_t   st_ino;
-	mode_t  st_mode;
-	short   st_nlink;
-	uid_t   st_uid;
-	gid_t   st_gid;
-	dev_t   st_rdev;
-	off_t   st_size;
-	time_t  st_atime;
-	unsigned int  __unused1;
-	time_t  st_mtime;
-	unsigned int  __unused2;
-	time_t  st_ctime;
-	unsigned int  __unused3;
-	off_t   st_blksize;
-	off_t   st_blocks;
+	__kernel_dev_t32   st_dev;
+	__kernel_ino_t32   st_ino;
+	__kernel_mode_t32  st_mode;
+	short   	   st_nlink;
+	__kernel_uid_t32   st_uid;
+	__kernel_gid_t32   st_gid;
+	__kernel_dev_t32   st_rdev;
+	__kernel_off_t32   st_size;
+	__kernel_time_t32  st_atime;
+	unsigned int       __unused1;
+	__kernel_time_t32  st_mtime;
+	unsigned int       __unused2;
+	__kernel_time_t32  st_ctime;
+	unsigned int       __unused3;
+	__kernel_off_t32   st_blksize;
+	__kernel_off_t32   st_blocks;
 	unsigned int  __unused4[2];
 };
 
@@ -49,11 +34,8 @@
 	dev_t   st_rdev;
 	off_t   st_size;
 	time_t  st_atime;
-	unsigned long  __unused1;
 	time_t  st_mtime;
-	unsigned long  __unused2;
 	time_t  st_ctime;
-	unsigned long  __unused3;
 	off_t   st_blksize;
 	off_t   st_blocks;
 	unsigned long  __unused4[2];
diff -u --recursive --new-file v2.1.35/linux/include/asm-sparc64/statfs.h linux/include/asm-sparc64/statfs.h
--- v2.1.35/linux/include/asm-sparc64/statfs.h	Mon Dec 30 02:00:03 1996
+++ linux/include/asm-sparc64/statfs.h	Tue Apr 15 21:47:24 1997
@@ -1,4 +1,4 @@
-/* $Id: statfs.h,v 1.1 1996/12/26 14:22:40 davem Exp $ */
+/* $Id: statfs.h,v 1.2 1997/04/14 17:05:22 jj Exp $ */
 #ifndef _SPARC64_STATFS_H
 #define _SPARC64_STATFS_H
 
@@ -10,7 +10,6 @@
 
 #endif
 
-/* XXX Fix this for full backwards 32-bit compat. */
 struct statfs32 {
 	int f_type;
 	int f_bsize;
@@ -19,7 +18,7 @@
 	int f_bavail;
 	int f_files;
 	int f_ffree;
-	__kernel_fsid_t f_fsid;
+	__kernel_fsid_t32 f_fsid;
 	int f_namelen;  /* SunOS ignores this field. */
 	int f_spare[6];
 };
diff -u --recursive --new-file v2.1.35/linux/include/asm-sparc64/unistd.h linux/include/asm-sparc64/unistd.h
--- v2.1.35/linux/include/asm-sparc64/unistd.h	Mon Apr 14 16:28:24 1997
+++ linux/include/asm-sparc64/unistd.h	Tue Apr 22 22:49:38 1997
@@ -1,4 +1,4 @@
-/* $Id: unistd.h,v 1.3 1997/04/10 23:32:51 davem Exp $ */
+/* $Id: unistd.h,v 1.4 1997/04/19 08:52:25 jj Exp $ */
 #ifndef _SPARC64_UNISTD_H
 #define _SPARC64_UNISTD_H
 
@@ -270,7 +270,7 @@
 #define __NR__sysctl            251
 #define __NR_getsid             252
 #define __NR_fdatasync          253
-#define __NR_nfsctl             254
+#define __NR_nfsservctl         254
 #define __NR_aplib              255
 
 #define _syscall0(type,name) \
diff -u --recursive --new-file v2.1.35/linux/include/linux/fs.h linux/include/linux/fs.h
--- v2.1.35/linux/include/linux/fs.h	Mon Apr  7 11:35:31 1997
+++ linux/include/linux/fs.h	Wed Apr 23 11:00:45 1997
@@ -36,7 +36,7 @@
 /* And dynamically-tunable limits and defaults: */
 extern int max_inodes, nr_inodes;
 extern int max_files, nr_files;
-#define NR_INODE 3072	/* this should be bigger than NR_FILE */
+#define NR_INODE 4096	/* this should be bigger than NR_FILE */
 #define NR_FILE 1024	/* this can well be larger on a larger system */
 
 #define MAY_EXEC 1
@@ -128,7 +128,7 @@
 #include <asm/bitops.h>
 
 extern void buffer_init(void);
-extern unsigned long inode_init(unsigned long start, unsigned long end);
+extern void inode_init(void);
 extern unsigned long file_table_init(unsigned long start, unsigned long end);
 extern unsigned long name_cache_init(unsigned long start, unsigned long end);
 
@@ -179,7 +179,7 @@
 	unsigned long b_lru_time;       /* Time when this buffer was 
 					 * last used. */
 	struct wait_queue * b_wait;
-	struct buffer_head * b_prev;		/* doubly linked list of hash-queue */
+	struct buffer_head ** b_pprev;		/* doubly linked list of hash-queue */
 	struct buffer_head * b_prev_free;	/* doubly linked list of buffers */
 	struct buffer_head * b_reqnext;		/* request queue */
 };
@@ -270,8 +270,13 @@
 #include <linux/quota.h>
 
 struct inode {
-	kdev_t		i_dev;
+	struct inode 	*i_hash_next;
+	struct inode	**i_hash_pprev;
+	struct inode	*i_next;
+	struct inode	**i_pprev;
 	unsigned long	i_ino;
+	kdev_t		i_dev;
+	unsigned short	i_count;
 	umode_t		i_mode;
 	nlink_t		i_nlink;
 	uid_t		i_uid;
@@ -293,11 +298,8 @@
 	struct vm_area_struct *i_mmap;
 	struct page *i_pages;
 	struct dquot *i_dquot[MAXQUOTAS];
-	struct inode *i_next, *i_prev;
-	struct inode *i_hash_next, *i_hash_prev;
 	struct inode *i_bound_to, *i_bound_by;
 	struct inode *i_mount;
-	unsigned short i_count;
 	unsigned short i_flags;
 	unsigned char i_lock;
 	unsigned char i_dirt;
diff -u --recursive --new-file v2.1.35/linux/include/linux/init.h linux/include/linux/init.h
--- v2.1.35/linux/include/linux/init.h	Thu Mar 27 14:40:10 1997
+++ linux/include/linux/init.h	Thu Apr 17 13:20:51 1997
@@ -30,6 +30,22 @@
  * static char linux_logo[] __initdata = { 0x32, 0x36, ... };
  */
 
+/*
+ * Disable the __initfunc macros if a file that is a part of a
+ * module attempts to use them. We do not want to interfere
+ * with module linking.
+ */
+
+#ifndef MODULE
 #include <asm/init.h>
+#else
+#define __init
+#define __initdata
+#define __initfunc(__arginit) __arginit
+/* For assembly routines */
+#define __INIT
+#define __FINIT
+#define __INITDATA
+#endif
 
 #endif
diff -u --recursive --new-file v2.1.35/linux/include/linux/mm.h linux/include/linux/mm.h
--- v2.1.35/linux/include/linux/mm.h	Thu Feb  6 02:53:33 1997
+++ linux/include/linux/mm.h	Wed Apr 23 11:00:46 1997
@@ -125,7 +125,7 @@
 	unsigned dirty:16,
 		 age:8;
 	struct wait_queue *wait;
-	struct page *prev_hash;
+	struct page **pprev_hash;
 	struct buffer_head * buffers;
 	unsigned long swap_unlock_entry;
 	unsigned long map_nr;	/* page->map_nr == page - mem_map */
diff -u --recursive --new-file v2.1.35/linux/include/linux/pagemap.h linux/include/linux/pagemap.h
--- v2.1.35/linux/include/linux/pagemap.h	Thu Feb  6 02:53:33 1997
+++ linux/include/linux/pagemap.h	Wed Apr 23 11:00:46 1997
@@ -71,20 +71,12 @@
 
 static inline void remove_page_from_hash_queue(struct page * page)
 {
-	struct page **p;
-	struct page *next_hash, *prev_hash;
-
-	next_hash = page->next_hash;
-	prev_hash = page->prev_hash;
-	page->next_hash = NULL;
-	page->prev_hash = NULL;
-	if (next_hash)
-		next_hash->prev_hash = prev_hash;
-	if (prev_hash)
-		prev_hash->next_hash = next_hash;
-	p = page_hash(page->inode,page->offset);
-	if (*p == page)
-		*p = next_hash;
+	if(page->pprev_hash) {
+		if(page->next_hash)
+			page->next_hash->pprev_hash = page->pprev_hash;
+		*page->pprev_hash = page->next_hash;
+		page->pprev_hash = NULL;
+	}
 	page_cache_size--;
 }
 
@@ -93,17 +85,16 @@
 	page_cache_size++;
 	set_bit(PG_referenced, &page->flags);
 	page->age = PAGE_AGE_VALUE;
-	page->prev_hash = NULL;
-	if ((page->next_hash = *p) != NULL)
-		page->next_hash->prev_hash = page;
+	if((page->next_hash = *p) != NULL)
+		(*p)->pprev_hash = &page->next_hash;
 	*p = page;
+	page->pprev_hash = p;
 }
 
 static inline void add_page_to_hash_queue(struct page * page, struct inode * inode, unsigned long offset)
 {
 	__add_page_to_hash_queue(page, page_hash(inode,offset));
 }
-
 
 static inline void remove_page_from_inode_queue(struct page * page)
 {
diff -u --recursive --new-file v2.1.35/linux/include/linux/parport.h linux/include/linux/parport.h
--- v2.1.35/linux/include/linux/parport.h	Sun Apr 13 10:18:22 1997
+++ linux/include/linux/parport.h	Wed Apr 23 11:01:37 1997
@@ -1,14 +1,20 @@
-/* $Id: parport.h,v 1.1.2.5 1997/03/29 21:08:31 phil Exp $ */
+/* $Id: parport.h,v 1.2.6.3 1997/04/16 21:21:03 phil Exp $ */
 
 #ifndef _PARPORT_H_
 #define _PARPORT_H_
 
 #include <asm/system.h>
 #include <asm/ptrace.h>
+#include <linux/proc_fs.h>
 
 /* Maximum of 8 ports per machine */
 #define PARPORT_MAX  8 
 
+/* Magic numbers */
+#define PARPORT_IRQ_NONE  -1
+#define PARPORT_DMA_NONE  -1
+#define PARPORT_DISABLE   -2
+
 /* Type classes for Plug-and-Play probe */
 
 typedef enum {
@@ -78,6 +84,14 @@
 	struct ppd *prev;
 };
 
+struct parport_dir{
+	struct proc_dir_entry *entry;    /* Directory /proc/parport/X     */
+	struct proc_dir_entry *irq;      /* IRQ entry /proc/parport/X/irq */
+	struct proc_dir_entry *devices;  /* /proc/parport/X/devices       */
+	struct proc_dir_entry *hardware; /* /proc/parport/X/hardware      */
+    char name[4]; /* /proc/parport/"XXXX" */
+};
+
 /* A parallel port */
 struct parport {
 	unsigned int base;	/* base address */
@@ -93,8 +107,9 @@
 	unsigned int ecr;	/* ECP ECR register */
 	struct parport *next;
         unsigned int flags; 
-	struct proc_dir_entry *proc_dir;
+	struct parport_dir pdir;
 	struct parport_device_info probe_info; 
+	int speed;  /* Max Write in Bytes/s */
 };
 
 /* parport_register_port registers a new parallel port at the given address (if
@@ -174,8 +189,10 @@
 				   char);
 
 /* Prototypes from parport_procfs */
+extern int parport_proc_init(void);
+extern int parport_proc_cleanup(void);
 extern int parport_proc_register(struct parport *pp);
-extern void parport_proc_unregister(struct parport *pp);
+extern int parport_proc_unregister(struct parport *pp);
 
 /* Prototypes from parport_ksyms.c */
 extern void dec_parport_count(void);
diff -u --recursive --new-file v2.1.35/linux/include/linux/pci.h linux/include/linux/pci.h
--- v2.1.35/linux/include/linux/pci.h	Fri Apr  4 08:52:25 1997
+++ linux/include/linux/pci.h	Wed Apr 23 08:18:20 1997
@@ -593,6 +593,7 @@
 #define PCI_DEVICE_ID_INTEL_82371SB_1	0x7010
 #define PCI_DEVICE_ID_INTEL_82371SB_2	0x7020
 #define PCI_DEVICE_ID_INTEL_82437VX	0x7030
+#define PCI_DEVICE_ID_INTEL_82371AB	0x7111
 #define PCI_DEVICE_ID_INTEL_P6		0x84c4
 
 #define PCI_VENDOR_ID_KTI		0x8e2e
diff -u --recursive --new-file v2.1.35/linux/include/linux/sched.h linux/include/linux/sched.h
--- v2.1.35/linux/include/linux/sched.h	Wed Apr 16 14:15:00 1997
+++ linux/include/linux/sched.h	Wed Apr 23 11:00:46 1997
@@ -112,8 +112,8 @@
  * _adding_ to the beginning of the run-queue has
  * a separate lock).
  */
+extern rwlock_t tasklist_lock;
 extern spinlock_t scheduler_lock;
-extern spinlock_t tasklist_lock;
 
 extern void sched_init(void);
 extern void show_state(void);
@@ -174,14 +174,16 @@
 		&init_mmap, &init_mmap, MUTEX }
 
 struct signal_struct {
-	int count;
-	struct sigaction action[32];
+	atomic_t		count;
+	struct sigaction	action[32];
+	spinlock_t		siglock;
 };
 
 
 #define INIT_SIGNALS { \
-		1, \
-		{ {0,}, } }
+		ATOMIC_INIT(1), \
+		{ {0,}, }, \
+		SPIN_LOCK_UNLOCKED }
 
 struct task_struct {
 /* these are hardcoded - don't touch */
@@ -261,6 +263,8 @@
 	int processor;
 	int last_processor;
 	int lock_depth;		/* Lock depth. We can context switch in and out of holding a syscall kernel lock... */	
+	/* Spinlocks for various pieces or per-task state. */
+	spinlock_t sigmask_lock;	/* Protects signal and blocked */
 };
 
 /*
@@ -471,11 +475,11 @@
 	p->nr++;
 }
 
-#define REMOVE_LINKS(p) do { \
-	spin_lock(&tasklist_lock); \
+#define REMOVE_LINKS(p) do { unsigned long flags; \
+	write_lock_irqsave(&tasklist_lock, flags); \
 	(p)->next_task->prev_task = (p)->prev_task; \
 	(p)->prev_task->next_task = (p)->next_task; \
-	spin_unlock(&tasklist_lock); \
+	write_unlock_irqrestore(&tasklist_lock, flags); \
 	if ((p)->p_osptr) \
 		(p)->p_osptr->p_ysptr = (p)->p_ysptr; \
 	if ((p)->p_ysptr) \
@@ -484,13 +488,13 @@
 		(p)->p_pptr->p_cptr = (p)->p_osptr; \
 	} while (0)
 
-#define SET_LINKS(p) do { \
-	spin_lock(&tasklist_lock); \
+#define SET_LINKS(p) do { unsigned long flags; \
+	write_lock_irqsave(&tasklist_lock, flags); \
 	(p)->next_task = &init_task; \
 	(p)->prev_task = init_task.prev_task; \
 	init_task.prev_task->next_task = (p); \
 	init_task.prev_task = (p); \
-	spin_unlock(&tasklist_lock); \
+	write_unlock_irqrestore(&tasklist_lock, flags); \
 	(p)->p_ysptr = NULL; \
 	if (((p)->p_osptr = (p)->p_pptr->p_cptr) != NULL) \
 		(p)->p_osptr->p_ysptr = p; \
diff -u --recursive --new-file v2.1.35/linux/include/linux/skbuff.h linux/include/linux/skbuff.h
--- v2.1.35/linux/include/linux/skbuff.h	Mon Apr 14 16:28:26 1997
+++ linux/include/linux/skbuff.h	Wed Apr 23 11:00:46 1997
@@ -20,12 +20,9 @@
 #include <asm/atomic.h>
 #include <asm/types.h>
 
-#define CONFIG_SKB_CHECK 0
-
 #define HAVE_ALLOC_SKB		/* For the drivers to know */
 #define HAVE_ALIGNABLE_SKB	/* Ditto 8)		   */
 
-
 #define FREE_READ	1
 #define FREE_WRITE	0
 
@@ -39,9 +36,6 @@
 	struct sk_buff	* prev;
 	__u32		qlen;		/* Must be same length as a pointer
 					   for using debugging */
-#if CONFIG_SKB_CHECK
-	int		magic_debug_cookie;
-#endif
 };
 
 struct sk_buff 
@@ -49,9 +43,6 @@
 	struct sk_buff	* next;			/* Next buffer in list 				*/
 	struct sk_buff	* prev;			/* Previous buffer in list 			*/
 	struct sk_buff_head * list;		/* List we are on				*/
-#if CONFIG_SKB_CHECK
-	int		magic_debug_cookie;
-#endif
 	struct sock	*sk;			/* Socket we are owned by 			*/
 	unsigned long	when;			/* used to compute rtt's			*/
 	struct timeval	stamp;			/* Time we arrived				*/
@@ -95,8 +86,7 @@
   
 	unsigned int 	len;			/* Length of actual data			*/
 	unsigned int	csum;			/* Checksum 					*/
-	volatile char 	acked,			/* Are we acked ?				*/
-			used,			/* Are we in use ?				*/
+	volatile char 	used,			/* Are we in use ?				*/
 			arp;			/* Has IP/ARP resolution finished		*/
 	unsigned char	tries,			/* Times tried					*/
   			inclone,		/* Inline clone					*/
@@ -141,12 +131,6 @@
 #define SK_RMEM_MAX	32767
 #endif
 
-#if CONFIG_SKB_CHECK
-#define SK_FREED_SKB	0x0DE2C0DE
-#define SK_GOOD_SKB	0xDEC0DED1
-#define SK_HEAD_SKB	0x12231298
-#endif
-
 #ifdef __KERNEL__
 /*
  *	Handling routines are only of interest to the kernel
@@ -245,14 +229,6 @@
 	return(list_->qlen);
 }
 
-#if CONFIG_SKB_CHECK
-extern int 			skb_check(struct sk_buff *skb,int,int, char *);
-#define IS_SKB(skb)		skb_check((skb), 0, __LINE__,__FILE__)
-#define IS_SKB_HEAD(skb)	skb_check((skb), 1, __LINE__,__FILE__)
-#else
-#define IS_SKB(skb)		
-#define IS_SKB_HEAD(skb)	
-
 extern __inline__ void skb_queue_head_init(struct sk_buff_head *list)
 {
 	list->prev = (struct sk_buff *)list;
@@ -534,9 +510,6 @@
 	skb->destructor = NULL;
 	skb->sk = NULL;
 }
-
-
-#endif
 
 extern struct sk_buff *		skb_recv_datagram(struct sock *sk,unsigned flags,int noblock, int *err);
 extern unsigned int		datagram_poll(struct socket *sock, poll_table *wait);
diff -u --recursive --new-file v2.1.35/linux/include/linux/sysctl.h linux/include/linux/sysctl.h
--- v2.1.35/linux/include/linux/sysctl.h	Mon Apr  7 11:35:32 1997
+++ linux/include/linux/sysctl.h	Tue Apr 22 22:46:27 1997
@@ -121,6 +121,11 @@
 	NET_IPV4_ARP_CHECK_INTERVAL,
 	NET_IPV4_ARP_CONFIRM_INTERVAL,
 	NET_IPV4_ARP_CONFIRM_TIMEOUT,
+	NET_IPV4_TCP_HOE_RETRANSMITS,
+	NET_IPV4_TCP_SACK,
+	NET_IPV4_TCP_TSACK,
+	NET_IPV4_TCP_TIMESTAMPS,
+	NET_IPV4_TCP_WINDOW_SCALING,
 	NET_IPV4_TCP_VEGAS_CONG_AVOID,
 	NET_IPV4_FORWARDING,
 	NET_IPV4_DEFAULT_TTL,
diff -u --recursive --new-file v2.1.35/linux/include/linux/vmalloc.h linux/include/linux/vmalloc.h
--- v2.1.35/linux/include/linux/vmalloc.h	Thu Feb  6 02:53:43 1997
+++ linux/include/linux/vmalloc.h	Wed Apr 23 11:00:46 1997
@@ -20,14 +20,16 @@
 
 extern inline void set_pgdir(unsigned long address, pgd_t entry)
 {
-#ifndef __mc68000__
+#if !defined(__mc68000__) && !defined(__sparc_v9__)
 	struct task_struct * p;
 
+	read_lock(&tasklist_lock);
 	for_each_task(p) {
 		if (!p->mm)
 			continue;
 		*pgd_offset(p->mm,address) = entry;
 	}
+	read_unlock(&tasklist_lock);
 #endif
 }
 
diff -u --recursive --new-file v2.1.35/linux/include/linux/wireless.h linux/include/linux/wireless.h
--- v2.1.35/linux/include/linux/wireless.h	Mon Mar 17 14:54:35 1997
+++ linux/include/linux/wireless.h	Thu Apr 17 14:40:36 1997
@@ -63,20 +63,25 @@
  * (there is some stuff that will be added in the future...)
  * I just plan to increment with each new version.
  */
-#define WIRELESS_EXT	4
+#define WIRELESS_EXT	5
 
 /*
  * Changes :
  *
  * V2 to V3
  * --------
- *	Alan Cox start some imcompatibles changes. I've integrated a bit more.
+ *	Alan Cox start some incompatibles changes. I've integrated a bit more.
  *	- Encryption renamed to Encode to avoid US regulation problems
  *	- Frequency changed from float to struct to avoid problems on old 386
  *
  * V3 to V4
  * --------
  *	- Add sensitivity
+ *
+ * V4 to V5
+ * --------
+ *	- Missing encoding definitions in range
+ *	- Access points stuff
  */
 
 /* -------------------------- IOCTL LIST -------------------------- */
@@ -103,11 +108,16 @@
 #define SIOCSIWSPY	0x8B10		/* set spy addresses */
 #define SIOCGIWSPY	0x8B11		/* get spy info (quality of link) */
 
+/* Access Point manipulation */
+#define SIOCSIWAP	0x8B14		/* set access point hardware addresses */
+#define SIOCGIWAP	0x8B15		/* get access point hardware addresses */
+#define SIOCGIWAPLIST	0x8B17		/* get list of access point in range */
+
 /* ------------------------- IOCTL STUFF ------------------------- */
 
 /* The first and the last (range) */
 #define SIOCIWFIRST	0x8B00
-#define SIOCIWLAST	0x8B13
+#define SIOCIWLAST	0x8B17
 
 /* Even : get (world access), odd : set (root access) */
 #define IW_IS_SET(cmd)	(!((cmd) & 0x1))
@@ -185,6 +195,17 @@
 	__u32		misc;		/* Others cases */
 };
 
+/*
+ *	Encoding information (setting and so on)
+ *	Encoding might be hardware encryption, scrambing or others
+ */
+struct	iw_encoding
+{
+  __u8	method;			/* Algorithm number / key used */
+  __u64	code;			/* Data/key used for algorithm */
+};
+
+
 /* ------------------------ WIRELESS STATS ------------------------ */
 /*
  * Wireless statistics (used for /proc/net/wireless)
@@ -234,13 +255,11 @@
 					 * 0-1000 = channel
 					 * > 1000 = frequency in Hz */
 
-		struct		/* Encoding stuff */
-		{
-			__u8	method;		/* Algorithm number / off */
-			__u64	code;		/* Data used for algorithm */
-		}	encoding;
+		struct iw_encoding	encoding;	/* Encoding stuff */
 
-		__u32	sensitivity;	/* signal level threshold */
+		__u32	sensitivity;		/* signal level threshold */
+
+		struct sockaddr	ap_addr;	/* Access point address */
 
 		struct		/* For all data bigger than 16 octets */
 		{
@@ -275,16 +294,16 @@
 	__u16		num_channels;	/* Number of channels [0; num - 1] */
 	__u8		num_frequency;	/* Number of entry in the list */
 	struct iw_freq	freq[IW_MAX_FREQUENCIES];	/* list */
-
 	/* Note : this frequency list doesn't need to fit channel numbers */
 
-	/* Encoder stuff */
-
 	/* signal level threshold range */
 	__u32	sensitivity;
 
 	/* Quality of link & SNR stuff */
 	struct iw_quality	max_qual;	/* Quality of the link */
+
+	/* Encoder stuff */
+	struct iw_encoding	max_encoding;	/* Encoding max range */
 };
 
 /*
diff -u --recursive --new-file v2.1.35/linux/include/linux/zorro.h linux/include/linux/zorro.h
--- v2.1.35/linux/include/linux/zorro.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/zorro.h	Tue Apr 22 22:45:22 1997
@@ -0,0 +1,1278 @@
+/*
+ * linux/zorro.h -- Amiga AutoConfig (Zorro) Expansion Device Definitions
+ *
+ * Copyright (C) 1995 Geert Uytterhoeven
+ *
+ * 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.
+ */
+
+#ifndef __ZORRO_H
+#define __ZORRO_H
+
+#ifndef __ASSEMBLY__
+
+/*
+ * Defined Board Manufacturers
+ *
+ * Please update arch/m68k/amiga/zorro.c if you make changes here
+ * Many IDs were obtained from ExpName/Identify ((C) Richard Körber)
+ * and by looking at the NetBSD-Amiga kernel sources
+ */
+
+#define MANUF_PACIFIC          (0x00D3)	/* Pacific Peripherals */
+#define PROD_SE_2000_A500      (0x00)	/* SE 2000 A500 */
+#define PROD_PACIFIC_HD        (0x0A)	/* HD Controller */
+
+#define MANUF_KUPKE            (0x00DD)	/* Kupke */
+#define PROD_GOLEM_BOX_2       (0x00)	/* Golem RAM Box 2MB */
+
+#define MANUF_MEMPHIS          (0x0100)	/* Memphis */
+#define PROD_STORMBRINGER      (0x00)	/* Stormbringer */
+
+#define MANUF_3_STATE          (0x0200)	/* 3-State */
+#define PROD_MEGAMIX_2000      (0x02)	/* Megamix 2000 RAM */
+
+#define MANUF_COMMODORE2       (0x0201)	/* Commodore Braunschweig */
+#define PROD_A2088             (0x01)	/* CBM A2088 XT Bridgeboard */
+#define PROD_A2286             (0x02)	/* CBM A2286 AT Bridgeboard */
+#define PROD_A4091_2           (0x54)	/* CBM A4091 SCSI Controller */
+#define PROD_A2386SX           (0x67)	/* CBM A2386-SX Bridgeboard */
+
+#define MANUF_COMMODORE        (0x0202)	/* Commodore West Chester */
+#define PROD_A2090A            (0x01)	/* CBM A2090/A2090A HD Controller */
+#define PROD_A590              (0x02)	/* CBM A590 SCSI Controller */
+#define PROD_A2091             (0x03)	/* CBM A2091 SCSI Controller */
+#define PROD_A2090B            (0x04)	/* CBM A2090B 2090 Autoboot Card */
+#define PROD_ARCNET            (0x09)	/* CBM A2060 Arcnet Card */
+#define PROD_CBMRAM            (0x0A)	/* CBM A2052/58.RAM | 590/2091.RAM */
+#define PROD_A560RAM           (0x20)	/* CBM A560 Memory Module */
+#define PROD_A2232PROTO        (0x45)	/* CBM A2232 Serial Prototype */
+#define PROD_A2232             (0x46)	/* CBM A2232 Serial Production */
+#define PROD_A2620             (0x50)	/* CBM A2620 68020/RAM Card */
+#define PROD_A2630             (0x51)	/* CBM A2630 68030/RAM Card */
+#define PROD_A4091             (0x54)	/* CBM A4091 SCSI Controller */
+#define PROD_A2065_2           (0x5A)	/* A2065 Ethernet Card */
+#define PROD_ROMULATOR         (0x60)	/* CBM Romulator Card */
+#define PROD_A3000TESTFIX      (0x61)	/* CBM A3000 Test Fixture */
+#define PROD_A2386SX_2         (0x67)	/* A2386-SX Bridgeboard */
+#define PROD_A2065             (0x70)	/* CBM A2065 Ethernet Card */
+
+#define MANUF_COMMODORE3       (0x0203)	/* Commodore West Chester */
+#define PROD_A2090A_CM         (0x03)	/* A2090A Combitec/MacroSystem */
+
+#define MANUF_KCS              (0x02FF)	/* Kolff Computer Supplies */
+#define PROD_POWER_BOARD       (0x00)	/* KCS Power PC Board */
+
+#define MANUF_CARDCO           (0x03EC)	/* Cardco */
+#define PROD_KRONOS_2000_SCSI  (0x04)	/* Kronos 2000 SCSI Controller */
+#define PROD_A1000_SCSI        (0x0C)	/* A1000 SCSI Controller */
+#define PROD_ESCORT_SCSI       (0x0E)	/* Escort SCSI Controller */
+#define PROD_CC_A2410          (0xF5)	/* Cardco A2410 Hires Graphics Card */
+
+#define MANUF_A_SQUARED        (0x03ED)	/* A-Squared */
+#define PROD_LIVE_2000         (0x01)	/* Live! 2000 */
+
+#define MANUF_COMSPEC          (0x03EE)	/* ComSpec Communications */
+#define PROD_AX2000            (0x01)	/* AX2000 */
+
+#define MANUF_ANAKIN           (0x03F1)	/* Anakin */
+#define PROD_EASYL             (0x01)	/* Easyl Tablet */
+
+#define MANUF_MICROBOTICS      (0x03F2)	/* MicroBotics */
+#define PROD_STARBOARD_II      (0x00)	/* StarBoard II */
+#define PROD_STARDRIVE         (0x02)	/* StarDrive */
+#define PROD_8_UP_A            (0x03)	/* 8-Up (Rev A) */
+#define PROD_8_UP_Z            (0x04)	/* 8-Up (Rev Z) */
+#define PROD_DELTA_RAM         (0x20)	/* Delta Card RAM */
+#define PROD_8_STAR_RAM        (0x40)	/* 8-Star RAM */
+#define PROD_8_STAR            (0x41)	/* 8-Star */
+#define PROD_VXL_RAM           (0x44)	/* VXL RAM */
+#define PROD_VXL_30            (0x45)	/* VXL-30 Turbo Board */
+#define PROD_DELTA             (0x60)	/* Delta Card */
+#define PROD_MBX_1200          (0x81)	/* MBX 1200 */
+#define PROD_HARDFRAME_2000    (0x9E)	/* Hardframe 2000 */
+#define PROD_MBX_1200_2        (0xC1)	/* MBX 1200 */
+
+#define MANUF_ACCESS           (0x03F4)	/* Access Associates */
+
+#define MANUF_EXPANSION_TECH   (0x03F6)	/* Expansion Technologies */
+
+#define MANUF_ASDG             (0x03FF)	/* ASDG */
+#define PROD_ASDG_MEMORY       (0x01)	/* Memory Expansion */
+#define PROD_ASDG_MEMORY_2     (0x02)	/* Memory Expansion */
+#define PROD_LAN_ROVER         (0xFE)	/* Lan Rover Ethernet */
+#define PROD_TWIN_X            (0xFF)	/* Twin-X Serial Card */
+
+#define MANUF_IMTRONICS        (0x0404)	/* Imtronics */
+#define PROD_HURRICANE_2800    (0x39)	/* Hurricane 2800 68030 */
+#define PROD_HURRICANE_2800_2  (0x57)	/* Hurricane 2800 68030 */
+
+#define MANUF_UNIV_OF_LOWELL   (0x0406)	/* University of Lowell */
+#define PROD_A2410             (0x00)	/* CBM A2410 Hires Graphics Card */
+
+#define MANUF_AMERISTAR        (0x041D)	/* Ameristar */
+#define PROD_AMERISTAR2065     (0x01)	/* A2065 Ethernet Card */
+#define PROD_A560              (0x09)	/* Arcnet Card */
+#define PROD_A4066             (0x0A)	/* A4066 Ethernet Card */
+
+#define MANUF_SUPRA            (0x0420)	/* Supra */
+#define PROD_SUPRADRIVE_4x4    (0x01)	/* SupraDrive 4x4 SCSI Controller */
+#define PROD_SUPRA_2000        (0x03)	/* 2000 DMA HD */
+#define PROD_SUPRA_500         (0x05)	/* 500 HD/RAM */
+#define PROD_SUPRA_500XP       (0x09)	/* 500XP/2000 RAM */
+#define PROD_SUPRA_500RX       (0x0A)	/* 500RX/2000 RAM */
+#define PROD_SUPRA_2400ZI      (0x0B)	/* 2400zi Modem */
+#define PROD_WORDSYNC          (0x0C)	/* Supra Wordsync SCSI Controller */
+#define PROD_WORDSYNC_II       (0x0D)	/* Supra Wordsync II SCSI Controller */
+#define PROD_SUPRA_2400ZIPLUS  (0x10)	/* 2400zi+ Modem */
+
+#define MANUF_CSA              (0x0422)	/* Computer Systems Ass. */
+#define PROD_MAGNUM            (0x11)	/* Magnum 40 SCSI Controller */
+#define PROD_12GAUGE           (0x15)	/* 12 Gauge SCSI Controller */
+
+#define MANUF_MTEC2            (0x0502)	/* M-Tech */
+#define PROD_AT500_2           (0x03)	/* AT500 RAM */
+
+#define MANUF_GVP3             (0x06E1)	/* Great Valley Products */
+#define PROD_IMPACT            (0x08)	/* Impact SCSI/Memory */
+
+#define MANUF_BYTEBOX          (0x07DA)	/* ByteBox */
+#define PROD_BYTEBOX_A500      (0x00)	/* A500 */
+
+#define MANUF_HACKER           (0x07DB)	/* Test only: no product definitions */
+
+#define MANUF_POWER_COMPUTING  (0x07DC)	/* Power Computing (DKB) */
+#define PROD_DKB_3128          (0x0E)	/* DKB 3128 RAM */
+#define PROD_RAPID_FIRE        (0x0F)	/* Rapid Fire SCSI Controller */
+#define PROD_DKB_1202          (0x10)	/* DKB 1202 RAM */
+#define PROD_VIPER_II_COBRA    (0x12)	/* Viper II Turbo Board (DKB Cobra) */
+#define PROD_WILDFIRE_060      (0x17)	/* WildFire 060 Turbo Board */
+#define PROD_WILDFIRE_060_2    (0xFF)	/* WildFire 060 Turbo Board */
+
+#define MANUF_GVP              (0x07E1)	/* Great Valley Products */
+#define PROD_IMPACT_I_4K       (0x01)	/* Impact Series-I SCSI 4K */
+#define PROD_IMPACT_I_16K_2    (0x02)	/* Impact Series-I SCSI 16K/2 */
+#define PROD_IMPACT_I_16K_3    (0x03)	/* Impact Series-I SCSI 16K/3 */
+#define PROD_IMPACT_3001_IDE   (0x08)	/* Impact 3001 IDE */
+#define PROD_IMPACT_3001_RAM   (0x09)	/* Impact 3001 RAM */
+#define PROD_GVPIISCSI         (0x0B)	/* GVP Series II SCSI Controller */
+#define PROD_GVPIISCSI_2       (0x09)	/* evidence that the driver works
+					   for this product code also */
+#define PROD_GVPIIRAM          (0x0A)	/* GVP Series II RAM */
+#define PROD_GVP               (0x0B)	/* This code is used by a wide range of
+					   GVP products - use the epc to
+					   identify it correctly */
+#define PROD_GVP_A2000_030     (0x0D)	/* GVP A2000 68030 Turbo Board */
+#define PROD_IMPACT_3001_IDE_2 (0x0D)	/* Impact 3001 IDE */
+#define PROD_GFORCE_040_SCSI   (0x16)	/* GForce 040 with SCSI (new) */
+#define PROD_GVPIV_24          (0x20)	/* GVP IV-24 Graphics Board */
+#define PROD_GFORCE_040        (0xFF)	/* GForce 040 Turbo Board */
+/* #define PROD_GVPIO_EXT      (0xFF)*/	/* GVP I/O Extender */
+
+#define MANUF_SYNERGY          (0x07E5)	/* Synergy */
+
+#define MANUF_XETEC            (0x07E6)	/* Xetec */
+#define PROD_FASTCARD_SCSI     (0x01)	/* FastCard SCSI Controller */
+#define PROD_FASTCARD_RAM      (0x02)	/* FastCard RAM */
+
+#define MANUF_PPI              (0x07EA)	/* Progressive Peripherals Inc. */
+#define PROD_MERCURY           (0x00)	/* Mercury Turbo Board */
+#define PROD_PPS_A3000_040     (0x01)	/* PP&S A3000 68040 Turbo Board */
+#define PROD_PPS_A2000_040     (0x69)	/* PP&S A2000 68040 Turbo Board */
+#define PROD_ZEUS              (0x96)	/* Zeus SCSI Controller */
+#define PROD_PPS_A500_040      (0xBB)	/* PP&S A500 68040 Turbo Board */
+
+#define MANUF_XEBEC            (0x07EC)	/* Xebec */
+
+#define MANUF_SPIRIT           (0x07F2)	/* Spirit */
+#define PROD_HDA_506           (0x04)	/* HDA 506 Harddisk */
+#define PROD_OCTABYTE_RAM      (0x06)	/* OctaByte RAM */
+
+#define MANUF_BSC              (0x07FE)	/* BSC */
+#define PROD_ALF_3_SCSI        (0x03)	/* BSC ALF 3 SCSI Controller */
+
+#define MANUF_BSC3             (0x0801)	/* BSC */
+#define PROD_ALF_2_SCSI        (0x01)	/* ALF 2 SCSI Controller */
+#define PROD_ALF_2_SCSI_2      (0x02)	/* ALF 2 SCSI Controller */
+#define PROD_ALF_3_SCSI_2      (0x03)	/* ALF 3 SCSI Controller */
+
+#define MANUF_C_LTD            (0x0802)	/* C Ltd. */
+#define PROD_KRONOS_SCSI       (0x04)	/* Kronos SCSI Controller */
+#define PROD_A1000_SCSI_2      (0x0C)	/* A1000 SCSI Controller */
+
+#define MANUF_JOCHHEIM         (0x0804)	/* Jochheim */
+#define PROD_JOCHHEIM_RAM      (0x01)	/* Jochheim RAM */
+
+#define MANUF_CHECKPOINT       (0x0807)	/* Checkpoint Technologies */
+#define PROD_SERIAL_SOLUTION   (0x00)	/* Serial Solution */
+
+#define MANUF_ICD              (0x0817)	/* ICD */
+#define PROD_ADVANTAGE_2000    (0x01)	/* Advantage 2000 SCSI Controller */
+
+#define MANUF_KUPKE2           (0x0819)	/* Kupke */
+#define PROD_KUPKE_SCSI_II     (0x02)	/* Golem SCSI-II Controller */
+#define PROD_GOLEM_BOX         (0x03)	/* Golem Box */
+#define PROD_KUPKE_TURBO       (0x04)	/* 030/882 Turbo Board */
+#define PROD_KUPKE_SCSI_AT     (0x05)	/* SCSI/AT Controller */
+
+#define MANUF_GVP4             (0x081D)	/* Great Valley Products */
+#define PROD_A2000_RAM8        (0x09)	/* A2000-RAM8/2 */
+
+#define MANUF_INTERWORKS_NET   (0x081E)	/* Interworks Network */
+
+#define MANUF_HARDITAL         (0x0820)	/* Hardital Synthesis */
+#define PROD_TQM               (0x14)	/* TQM 68030+68882 Turbo Board */
+
+#define MANUF_BSC2             (0x082C)	/* BSC */
+#define PROD_OKTAGON_SCSI      (0x05)	/* BSC Oktagon 2008 SCSI Controller */
+#define PROD_TANDEM            (0x06)	/* BSC Tandem AT-2008/508 IDE */
+#define PROD_ALPHA_RAM_1200    (0x07)	/* Alpha RAM 1200 */
+#define PROD_OKTAGON_RAM       (0x08)	/* BSC Oktagon 2008 RAM */
+#define PROD_MULTIFACE_I       (0x10)	/* Alfa Data MultiFace I */
+#define PROD_MULTIFACE_II      (0x11)	/* Alfa Data MultiFace II */
+#define PROD_MULTIFACE_III     (0x12)	/* Alfa Data MultiFace III */
+#define PROD_BSC_FRAEMBUFFER   (0x20)	/* Framebuffer */
+#define PROD_GRAFFITI_RAM      (0x21)	/* Graffiti Graphics Board */
+#define PROD_GRAFFITI_REG      (0x22)
+#define PROD_ISDN_MASTERCARD   (0x40)	/* BSC ISDN MasterCard */
+#define PROD_ISDN_MASTERCARD_2 (0x41)	/* BSC ISDN MasterCard II */
+
+#define MANUF_ADV_SYS_SOFT     (0x0836)	/* Advanced Systems & Software */
+#define PROD_NEXUS_SCSI        (0x01)	/* Nexus SCSI Controller */
+#define PROD_NEXUS_RAM         (0x08)	/* Nexus RAM */
+
+#define MANUF_IMPULSE          (0x0838)	/* Impulse */
+#define PROD_FIRECRACKER_24    (0x00)	/* FireCracker 24 */
+
+#define MANUF_IVS              (0x0840)	/* IVS */
+#define PROD_GRANDSLAM_PIC_2   (0x02)	/* GrandSlam PIC 2 RAM */
+#define PROD_GRANDSLAM_PIC_1   (0x04)	/* GrandSlam PIC 1 RAM */
+#define PROD_IVS_OVERDRIVE     (0x10)	/* OverDrive HD */
+#define PROD_TRUMPCARD_CLASSIC (0x30)	/* Trumpcard Classic SCSI Controller */
+#define PROD_TRUMPCARD_PRO     (0x34)	/* Trumpcard Pro SCSI Controller */
+#define PROD_META_4            (0x40)	/* Meta-4 RAM */
+#define PROD_WAVETOOLS         (0xBF)	/* Wavetools Sound Board */
+#define PROD_VECTOR            (0xF3)	/* Vector SCSI Controller */
+#define PROD_VECTOR_2          (0xF4)	/* Vector SCSI Controller */
+
+#define MANUF_VECTOR           (0x0841)	/* Vector */
+#define PROD_CONNECTION        (0xE3)	/* Connection Serial IO */
+
+#define MANUF_XPERT_PRODEV     (0x0845)	/* XPert/ProDev */
+#define PROD_VISIONA_RAM       (0x01)	/* Visiona Graphics Board */
+#define PROD_VISIONA_REG       (0x02)
+#define PROD_MERLIN_RAM        (0x03)	/* Merlin Graphics Board */
+#define PROD_MERLIN_REG        (0x04)
+#define PROD_MERLIN_REG_2      (0xC9)
+
+#define MANUF_HYDRA_SYSTEMS    (0x0849)	/* Hydra Systems */
+#define PROD_AMIGANET          (0x01)	/* Amiganet Board */
+
+#define MANUF_SUNRIZE          (0x084F)	/* Sunrize Industries */
+#define PROD_AD1012            (0x01)	/* AD1012 Sound Board */
+#define PROD_AD516             (0x02)	/* AD516 Sound Board */
+#define PROD_DD512             (0x03)	/* DD512 Sound Board */
+
+#define MANUF_TRICERATOPS      (0x0850)	/* Triceratops */
+#define PROD_TRICERATOPS       (0x01)	/* Triceratops Multi I/O Board */
+
+#define MANUF_APPLIED_MAGIC    (0x0851)	/* Applied Magic Inc */
+#define PROD_DMI_RESOLVER      (0x01)	/* DMI Resolver Graphics Board */
+#define PROD_DIGITAL_BCASTER   (0x06)	/* Digital Broadcaster */
+
+#define MANUF_GFX_BASE         (0x085E)	/* GFX-Base */
+#define PROD_GDA_1_RAM         (0x00)	/* GDA-1 Graphics Board */
+#define PROD_GDA_1_REG         (0x01)
+
+#define MANUF_ROCTEC           (0x0860)	/* RocTec */
+#define PROD_RH_800C           (0x01)	/* RH 800C Hard Disk Controller */
+#define PROD_RH_800C_RAM       (0x01)	/* RH 800C RAM */
+
+#define MANUF_HELFRICH1        (0x0861)	/* Helfrich */
+#define PROD_RAINBOW3          (0x21)	/* Rainbow3 Graphics Board */
+
+#define MANUF_SW_RESULT_ENTS   (0x0866)	/* Software Result Enterprises */
+#define PROD_GG2PLUS           (0x01)	/* GG2+ Bus Converter */
+
+#define MANUF_MASOBOSHI        (0x086D)	/* Masoboshi */
+#define PROD_MASTER_CARD_RAM   (0x03)	/* Master Card RAM */
+#define PROD_MASTER_CARD_SCSI  (0x04)	/* Master Card SCSI Controller */
+#define PROD_MVD_819           (0x07)	/* MVD 819 */
+
+#define MANUF_DELACOMP         (0x0873)	/* DelaComp */
+#define PROD_DELACOMP_RAM_2000 (0x01)	/* RAM Expansion 2000 */
+
+#define MANUF_VILLAGE_TRONIC   (0x0877)	/* Village Tronic */
+#define PROD_DOMINO_RAM        (0x01)	/* Domino Graphics Board */
+#define PROD_DOMINO_REG        (0x02)
+#define PROD_PICASSO_II_RAM    (0x0B)	/* Picasso II/II+ Graphics Board */
+#define PROD_PICASSO_II_REG    (0x0C)
+#define PROD_PICASSO_II_SEGM   (0x0D)	/* Picasso II/II+ (Segmented Mode) */
+#define PROD_PICASSO_IV        (0x15)	/* Picassio IV Graphics Board */
+#define PROD_PICASSO_IV_2      (0x16)
+#define PROD_PICASSO_IV_3      (0x17)
+#define PROD_PICASSO_IV_4      (0x18)
+#define PROD_ARIADNE           (0xC9)	/* Ariadne Ethernet */
+
+#define MANUF_UTILITIES_ULTD   (0x087B)	/* Utilities Unlimited */
+#define PROD_EMPLANT_DELUXE    (0x15)	/* Emplant Deluxe SCSI Controller */
+#define PROD_EMPLANT_DELUXE2   (0x20)	/* Emplant Deluxe SCSI Controller */
+
+#define MANUF_AMITRIX          (0x0880)	/* Amitrix */
+#define PROD_AMITRIX_MULTI_IO  (0x01)	/* Multi-IO */
+#define PROD_AMITRIX_CD_RAM    (0x02)	/* CD-RAM Memory */
+
+#define MANUF_ARMAX            (0x0885)	/* ArMax */
+#define PROD_OMNIBUS           (0x00)	/* OmniBus Graphics Board */
+
+#define MANUF_NEWTEK           (0x088F)	/* NewTek */
+#define PROD_VIDEOTOASTER      (0x00)	/* VideoToaster */
+
+#define MANUF_MTEC             (0x0890)	/* M-Tech Germany */
+#define PROD_AT500             (0x01)	/* AT500 IDE Controller */
+#define PROD_MTEC_68030        (0x03)	/* 68030 Turbo Board */
+#define PROD_MTEC_68020I       (0x06)	/* 68020i Turbo Board */
+#define PROD_MTEC_T1230        (0x20)	/* A1200 T68030/42 RTC Turbo Board */
+#define PROD_MTEC_RAM          (0x22)	/* MTEC 8MB RAM */
+
+#define MANUF_GVP2             (0x0891)	/* Great Valley Products */
+#define PROD_SPECTRUM_RAM      (0x01)	/* EGS 28/24 Spectrum Graphics Board */
+#define PROD_SPECTRUM_REG      (0x02)
+
+#define MANUF_HELFRICH2        (0x0893)	/* Helfrich */
+#define PROD_PICCOLO_RAM       (0x05)	/* Piccolo Graphics Board */
+#define PROD_PICCOLO_REG       (0x06)
+#define PROD_PEGGY_PLUS        (0x07)	/* PeggyPlus MPEG Decoder Board */
+#define PROD_VIDEOCRUNCHER     (0x08)	/* VideoCruncher */
+#define PROD_SD64_RAM          (0x0A)	/* SD64 Graphics Board */
+#define PROD_SD64_REG          (0x0B)
+
+#define MANUF_MACROSYSTEMS     (0x089B)	/* MacroSystems USA */
+#define PROD_WARP_ENGINE       (0x13)	/* Warp Engine 40xx SCSI Controller */
+
+#define MANUF_ELBOX            (0x089E)	/* ElBox Computer */
+#define PROD_ELBOX_1200        (0x06)	/* Elbox 1200/4 RAM */
+
+#define MANUF_HARMS_PROF       (0x0A00)	/* Harms Professional */
+#define PROD_HARMS_030_PLUS    (0x10)	/* 030 plus */
+#define PROD_3500_TURBO        (0xD0)	/* 3500 Turbo board */
+
+#define MANUF_MICRONIK         (0x0A50)	/* Micronik */
+#define PROD_RCA_120           (0x0A)	/* RCA 120 RAM */
+
+#define MANUF_MEGA_MICRO       (0x1000)	/* MegaMicro */
+#define PROD_SCRAM_500_SCSI    (0x03)	/* SCRAM 500 SCSI Controller */
+#define PROD_SCRAM_500_RAM     (0x04)	/* SCRAM 500 RAM */
+
+#define MANUF_IMTRONICS2       (0x1028)	/* Imtronics */
+#define PROD_HURRICANE_2800_3  (0x39)	/* Hurricane 2800 68030 */
+#define PROD_HURRICANE_2800_4  (0x57)	/* Hurricane 2800 68030 */
+
+#define MANUF_KUPKE3           (0x1248)	/* Kupke */
+#define PROD_GOLEM_3000        (0x01)	/* Golem HD 3000 */
+
+#define MANUF_ITH              (0x1388)	/* ITH */
+#define PROD_ISDN_MASTER_II    (0x01)	/* ISDN-Master II */
+
+#define MANUF_VMC              (0x1389)	/* VMC */
+#define PROD_ISDN_BLASTER_Z2   (0x01)	/* ISDN Blaster Z2 */
+#define PROD_HYPERCOM_4        (0x02)	/* HyperCom 4 */
+
+#define MANUF_INFORMATION      (0x157C)	/* Information */
+#define PROD_ISDN_ENGINE_I     (0x64)	/* ISDN Engine I */
+
+#define MANUF_VORTEX           (0x2017)	/* Vortex */
+#define PROD_GOLDEN_GATE_386SX (0x07)	/* Golden Gate 80386SX Board */
+#define PROD_GOLDEN_GATE_RAM   (0x08)	/* Golden Gate RAM */
+#define PROD_GOLDEN_GATE_486   (0x09)	/* Golden Gate 80486 Board */
+
+#define MANUF_DATAFLYER        (0x2062)	/* DataFlyer */
+#define PROD_DATAFLYER_4000SXS (0x01)	/* DataFlyer 4000SX SCSI Controller */
+#define PROD_DATAFLYER_4000SXR (0x02)	/* DataFlyer 4000SX RAM */
+
+#define MANUF_READYSOFT        (0x2100)	/* ReadySoft */
+#define PROD_AMAX              (0x01)	/* AMax II/IV */
+
+#define MANUF_PHASE5           (0x2140)	/* Phase5 */
+#define PROD_BLIZZARD_RAM      (0x01)	/* Blizzard RAM */
+#define PROD_BLIZZARD          (0x02)	/* Blizzard */
+#define PROD_BLIZZARD_1220_IV  (0x06)	/* Blizzard 1220-IV Turbo Board */
+#define PROD_FASTLANE_RAM      (0x0A)	/* FastLane RAM */
+#define PROD_FASTLANE_SCSI     (0x0B)	/* FastLane/Blizzard 1230-II SCSI/CyberSCSI */
+#define PROD_CYBERSTORM_SCSI   (0x0C)	/* Blizzard 1220/CyberStorm */
+#define PROD_BLIZZARD_1230_III (0x0D)	/* Blizzard 1230-III Turbo Board */
+#define PROD_BLIZZARD_1230_IV  (0x11)	/* Blizzard 1230-IV/1260 Turbo Board */
+#define PROD_BLIZZARD_2060SCSI (0x18)	/* Blizzard 2060 SCSI Controller */
+#define PROD_CYBERSTORM_II     (0x19)	/* CyberStorm Mk II */
+#define PROD_CYBERVISION       (0x22)	/* CyberVision64 Graphics Board */
+#define PROD_CYBERVISION3D_PRT (0x32)	/* CyberVision64-3D Prototype */
+#define PROD_CYBERVISION3D     (0x43)	/* CyberVision64-3D Graphics Board */
+
+#define MANUF_DPS              (0x2169)	/* DPS */
+#define PROD_DPS_PAR           (0x01)	/* Personal Animation Recorder */
+
+#define MANUF_APOLLO2          (0x2200)	/* Apollo */
+#define PROD_A620              (0x00)	/* A620 68020 Accelerator */
+#define PROD_A620_2            (0x01)	/* A620 68020 Accelerator */
+
+#define MANUF_APOLLO           (0x2222)	/* Apollo */
+#define PROD_AT_APOLLO         (0x22)	/* AT-Apollo */
+#define PROD_APOLLO_TURBO      (0x23)	/* Apollo Turbo Board */
+
+#define MANUF_PETSOFF          (0x38A5)	/* Petsoff LP */
+#define PROD_DELFINA           (0x00)	/* Delfina DSP */
+
+#define MANUF_UWE_GERLACH      (0x3FF7)	/* Uwe Gerlach */
+#define PROD_UG_RAM_ROM        (0xd4)	/* RAM/ROM */
+
+#define MANUF_MACROSYSTEMS2    (0x4754)	/* MacroSystems Germany */
+#define PROD_MAESTRO           (0x03)	/* Maestro */
+#define PROD_VLAB              (0x04)	/* VLab */
+#define PROD_MAESTRO_PRO       (0x05)	/* Maestro Pro */
+#define PROD_RETINA_Z2         (0x06)	/* Retina Z2 Graphics Board */
+#define PROD_MULTI_EVOLUTION   (0x08)	/* MultiEvolution */
+#define PROD_TOCCATA           (0x0C)	/* Toccata Sound Board */
+#define PROD_RETINA_Z3         (0x10)	/* Retina Z3 Graphics Board */
+#define PROD_VLAB_MOTION       (0x12)	/* VLab Motion */
+#define PROD_ALTAIS            (0x13)	/* Altais Graphics Board */
+#define PROD_FALCON_040        (0xFD)	/* Falcon '040 Turbo Board */
+
+#define MANUF_COMBITEC         (0x6766)	/* Combitec */
+
+#define MANUF_SKI              (0x8000)	/* SKI Peripherals */
+#define PROD_MAST_FIREBALL     (0x08)	/* M.A.S.T. Fireball SCSI Controller */
+#define PROD_SKI_SCSI_SERIAL   (0x80)	/* SCSI / Dual Serial */
+
+#define MANUF_CAMERON          (0xAA01)	/* Cameron */
+#define PROD_PERSONAL_A4       (0x10)	/* Personal A4 */
+
+#define MANUF_REIS_WARE        (0xAA11)	/* Reis-Ware */
+#define PROD_RW_HANDYSCANNER   (0x11)	/* Handyscanner */
+
+
+/* Illegal Manufacturer IDs. These do NOT appear in arch/m68k/amiga/zorro.c! */
+
+#define MANUF_HACKER_INC       (0x07DB)	/* Hacker Inc. */
+#define PROD_HACKER_SCSI       (0x01)	/* Hacker Inc. SCSI Controller */
+
+#define MANUF_RES_MNGT_FORCE   (0x07DB)	/* Resource Management Force */
+#define PROD_QUICKNET          (0x02)	/* QuickNet Ethernet */
+
+#define MANUF_VECTOR2          (0x07DB)	/* Vector */
+#define PROD_CONNECTION_2      (0xE0)	/* Vector Connection */
+#define PROD_CONNECTION_3      (0xE1)	/* Vector Connection */
+#define PROD_CONNECTION_4      (0xE2)	/* Vector Connection */
+#define PROD_CONNECTION_5      (0xE3)	/* Vector Connection */
+
+
+/*
+ * GVP's identifies most of their product through the 'extended
+ * product code' (epc). The epc has to be and'ed with the GVP_PRODMASK
+ * before the identification.
+ */
+
+#define GVP_PRODMASK    (0xf8)
+#define GVP_SCSICLKMASK (0x01)
+
+enum GVP_ident {
+  GVP_GFORCE_040      = 0x20,
+  GVP_GFORCE_040_SCSI = 0x30,
+  GVP_A1291_SCSI      = 0x40,
+  GVP_COMBO_R4        = 0x60,
+  GVP_COMBO_R4_SCSI   = 0x70,
+  GVP_PHONEPAK        = 0x78,
+  GVP_IOEXT           = 0x98,
+  GVP_GFORCE_030      = 0xa0,
+  GVP_GFORCE_030_SCSI = 0xb0,
+  GVP_A530            = 0xc0,
+  GVP_A530_SCSI       = 0xd0,
+  GVP_COMBO_R3        = 0xe0,
+  GVP_COMBO_R3_SCSI   = 0xf0,
+  GVP_SERIESII        = 0xf8,
+};
+
+enum GVP_flags {
+  GVP_IO       = 0x01,
+  GVP_ACCEL    = 0x02,
+  GVP_SCSI     = 0x04,
+  GVP_24BITDMA = 0x08,
+  GVP_25BITDMA = 0x10,
+  GVP_NOBANK   = 0x20,
+  GVP_14MHZ    = 0x40,
+};
+
+
+struct Node {
+    struct  Node *ln_Succ;	/* Pointer to next (successor) */
+    struct  Node *ln_Pred;	/* Pointer to previous (predecessor) */
+    u_char  ln_Type;
+    char    ln_Pri;		/* Priority, for sorting */
+    char    *ln_Name;		/* ID string, null terminated */
+};
+
+struct ExpansionRom {
+    /* -First 16 bytes of the expansion ROM */
+    u_char	er_Type;	/* Board type, size and flags */
+    u_char	er_Product;	/* Product number, assigned by manufacturer */
+    u_char	er_Flags;	/* Flags */
+    u_char	er_Reserved03;	/* Must be zero ($ff inverted) */
+    u_short	er_Manufacturer; /* Unique ID,ASSIGNED BY COMMODORE-AMIGA! */
+    u_long	er_SerialNumber; /* Available for use by manufacturer */
+    u_short	er_InitDiagVec;	/* Offset to optional "DiagArea" structure */
+    u_char	er_Reserved0c;
+    u_char	er_Reserved0d;
+    u_char	er_Reserved0e;
+    u_char	er_Reserved0f;
+};
+
+/* er_Type board type bits */
+#define ERT_TYPEMASK	0xc0
+#define ERT_ZORROII	0xc0
+#define ERT_ZORROIII	0x80
+
+/* other bits defined in er_Type */
+#define ERTB_MEMLIST	5		/* Link RAM into free memory list */
+#define ERTF_MEMLIST	(1<<5)
+
+struct ConfigDev {
+    struct Node 	cd_Node;
+    u_char		cd_Flags;	/* (read/write) */
+    u_char		cd_Pad; 	/* reserved */
+    struct ExpansionRom cd_Rom; 	/* copy of board's expansion ROM */
+    void		*cd_BoardAddr;	/* where in memory the board was placed */
+    u_long		cd_BoardSize;	/* size of board in bytes */
+    u_short		cd_SlotAddr;	/* which slot number (PRIVATE) */
+    u_short		cd_SlotSize;	/* number of slots (PRIVATE) */
+    void		*cd_Driver;	/* pointer to node of driver */
+    struct ConfigDev	*cd_NextCD;	/* linked list of drivers to config */
+    u_long		cd_Unused[4];	/* for whatever the driver wants */
+};
+
+#else	/* __ASSEMBLY__ */
+
+LN_Succ		= 0
+LN_Pred		= LN_Succ+4
+LN_Type		= LN_Pred+4
+LN_Pri		= LN_Type+1
+LN_Name		= LN_Pri+1
+LN_sizeof	= LN_Name+4
+
+ER_Type		= 0
+ER_Product	= ER_Type+1
+ER_Flags	= ER_Product+1
+ER_Reserved03	= ER_Flags+1
+ER_Manufacturer	= ER_Reserved03+1
+ER_SerialNumber	= ER_Manufacturer+2
+ER_InitDiagVec	= ER_SerialNumber+4
+ER_Reserved0c	= ER_InitDiagVec+2
+ER_Reserved0d	= ER_Reserved0c+1
+ER_Reserved0e	= ER_Reserved0d+1
+ER_Reserved0f	= ER_Reserved0e+1
+ER_sizeof	= ER_Reserved0f+1
+
+CD_Node		= 0
+CD_Flags	= CD_Node+LN_sizeof
+CD_Pad		= CD_Flags+1
+CD_Rom		= CD_Pad+1
+CD_BoardAddr	= CD_Rom+ER_sizeof
+CD_BoardSize	= CD_BoardAddr+4
+CD_SlotAddr	= CD_BoardSize+4
+CD_SlotSize	= CD_SlotAddr+2
+CD_Driver	= CD_SlotSize+2
+CD_NextCD	= CD_Driver+4
+CD_Unused	= CD_NextCD+4
+CD_sizeof	= CD_Unused+(4*4)
+
+#endif	/* __ASSEMBLY__ */
+
+#ifndef __ASSEMBLY__
+
+#define ZORRO_NUM_AUTO		16
+
+#ifdef __KERNEL__
+
+extern int zorro_num_autocon;		/* # of autoconfig devices found */
+extern struct ConfigDev zorro_autocon[ZORRO_NUM_AUTO];
+
+
+/*
+ * Zorro Functions
+ */
+
+extern int zorro_find(int manuf, int prod, int part, int index);
+extern struct ConfigDev *zorro_get_board(int key);
+extern void zorro_config_board(int key, int part);
+extern void zorro_unconfig_board(int key, int part);
+
+
+/*
+ * Bitmask indicating portions of available Zorro II RAM that are unused
+ * by the system. Every bit represents a 64K chunk, for a maximum of 8MB
+ * (128 chunks, physical 0x00200000-0x009fffff).
+ *
+ * If you want to use (= allocate) portions of this RAM, you should clear
+ * the corresponding bits.
+ */
+
+extern u_long zorro_unused_z2ram[4];
+
+#define Z2RAM_START		(0x00200000)
+#define Z2RAM_END		(0x00a00000)
+#define Z2RAM_SIZE		(0x00800000)
+#define Z2RAM_CHUNKSIZE		(0x00010000)
+#define Z2RAM_CHUNKMASK		(0x0000ffff)
+#define Z2RAM_CHUNKSHIFT	(16)
+
+
+/*
+ * Verbose Board Identification
+ */
+
+extern void zorro_identify(void);
+extern int zorro_get_list(char *buffer);
+
+#endif	/* !__ASSEMBLY__ */
+#endif	/* __KERNEL__ */
+
+#endif /* __ZORRO_H */
+/*
+ * linux/zorro.h -- Amiga AutoConfig (Zorro) Expansion Device Definitions
+ *
+ * Copyright (C) 1995 Geert Uytterhoeven
+ *
+ * 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.
+ */
+
+#ifndef __ZORRO_H
+#define __ZORRO_H
+
+#ifndef __ASSEMBLY__
+
+/*
+ * Defined Board Manufacturers
+ *
+ * Please update arch/m68k/amiga/zorro.c if you make changes here
+ * Many IDs were obtained from ExpName/Identify ((C) Richard Körber)
+ * and by looking at the NetBSD-Amiga kernel sources
+ */
+
+#define MANUF_PACIFIC          (0x00D3)	/* Pacific Peripherals */
+#define PROD_SE_2000_A500      (0x00)	/* SE 2000 A500 */
+#define PROD_PACIFIC_HD        (0x0A)	/* HD Controller */
+
+#define MANUF_KUPKE            (0x00DD)	/* Kupke */
+#define PROD_GOLEM_BOX_2       (0x00)	/* Golem RAM Box 2MB */
+
+#define MANUF_MEMPHIS          (0x0100)	/* Memphis */
+#define PROD_STORMBRINGER      (0x00)	/* Stormbringer */
+
+#define MANUF_3_STATE          (0x0200)	/* 3-State */
+#define PROD_MEGAMIX_2000      (0x02)	/* Megamix 2000 RAM */
+
+#define MANUF_COMMODORE2       (0x0201)	/* Commodore Braunschweig */
+#define PROD_A2088             (0x01)	/* CBM A2088 XT Bridgeboard */
+#define PROD_A2286             (0x02)	/* CBM A2286 AT Bridgeboard */
+#define PROD_A4091_2           (0x54)	/* CBM A4091 SCSI Controller */
+#define PROD_A2386SX           (0x67)	/* CBM A2386-SX Bridgeboard */
+
+#define MANUF_COMMODORE        (0x0202)	/* Commodore West Chester */
+#define PROD_A2090A            (0x01)	/* CBM A2090/A2090A HD Controller */
+#define PROD_A590              (0x02)	/* CBM A590 SCSI Controller */
+#define PROD_A2091             (0x03)	/* CBM A2091 SCSI Controller */
+#define PROD_A2090B            (0x04)	/* CBM A2090B 2090 Autoboot Card */
+#define PROD_ARCNET            (0x09)	/* CBM A2060 Arcnet Card */
+#define PROD_CBMRAM            (0x0A)	/* CBM A2052/58.RAM | 590/2091.RAM */
+#define PROD_A560RAM           (0x20)	/* CBM A560 Memory Module */
+#define PROD_A2232PROTO        (0x45)	/* CBM A2232 Serial Prototype */
+#define PROD_A2232             (0x46)	/* CBM A2232 Serial Production */
+#define PROD_A2620             (0x50)	/* CBM A2620 68020/RAM Card */
+#define PROD_A2630             (0x51)	/* CBM A2630 68030/RAM Card */
+#define PROD_A4091             (0x54)	/* CBM A4091 SCSI Controller */
+#define PROD_A2065_2           (0x5A)	/* A2065 Ethernet Card */
+#define PROD_ROMULATOR         (0x60)	/* CBM Romulator Card */
+#define PROD_A3000TESTFIX      (0x61)	/* CBM A3000 Test Fixture */
+#define PROD_A2386SX_2         (0x67)	/* A2386-SX Bridgeboard */
+#define PROD_A2065             (0x70)	/* CBM A2065 Ethernet Card */
+
+#define MANUF_COMMODORE3       (0x0203)	/* Commodore West Chester */
+#define PROD_A2090A_CM         (0x03)	/* A2090A Combitec/MacroSystem */
+
+#define MANUF_KCS              (0x02FF)	/* Kolff Computer Supplies */
+#define PROD_POWER_BOARD       (0x00)	/* KCS Power PC Board */
+
+#define MANUF_CARDCO           (0x03EC)	/* Cardco */
+#define PROD_KRONOS_2000_SCSI  (0x04)	/* Kronos 2000 SCSI Controller */
+#define PROD_A1000_SCSI        (0x0C)	/* A1000 SCSI Controller */
+#define PROD_ESCORT_SCSI       (0x0E)	/* Escort SCSI Controller */
+#define PROD_CC_A2410          (0xF5)	/* Cardco A2410 Hires Graphics Card */
+
+#define MANUF_A_SQUARED        (0x03ED)	/* A-Squared */
+#define PROD_LIVE_2000         (0x01)	/* Live! 2000 */
+
+#define MANUF_COMSPEC          (0x03EE)	/* ComSpec Communications */
+#define PROD_AX2000            (0x01)	/* AX2000 */
+
+#define MANUF_ANAKIN           (0x03F1)	/* Anakin */
+#define PROD_EASYL             (0x01)	/* Easyl Tablet */
+
+#define MANUF_MICROBOTICS      (0x03F2)	/* MicroBotics */
+#define PROD_STARBOARD_II      (0x00)	/* StarBoard II */
+#define PROD_STARDRIVE         (0x02)	/* StarDrive */
+#define PROD_8_UP_A            (0x03)	/* 8-Up (Rev A) */
+#define PROD_8_UP_Z            (0x04)	/* 8-Up (Rev Z) */
+#define PROD_DELTA_RAM         (0x20)	/* Delta Card RAM */
+#define PROD_8_STAR_RAM        (0x40)	/* 8-Star RAM */
+#define PROD_8_STAR            (0x41)	/* 8-Star */
+#define PROD_VXL_RAM           (0x44)	/* VXL RAM */
+#define PROD_VXL_30            (0x45)	/* VXL-30 Turbo Board */
+#define PROD_DELTA             (0x60)	/* Delta Card */
+#define PROD_MBX_1200          (0x81)	/* MBX 1200 */
+#define PROD_HARDFRAME_2000    (0x9E)	/* Hardframe 2000 */
+#define PROD_MBX_1200_2        (0xC1)	/* MBX 1200 */
+
+#define MANUF_ACCESS           (0x03F4)	/* Access Associates */
+
+#define MANUF_EXPANSION_TECH   (0x03F6)	/* Expansion Technologies */
+
+#define MANUF_ASDG             (0x03FF)	/* ASDG */
+#define PROD_ASDG_MEMORY       (0x01)	/* Memory Expansion */
+#define PROD_ASDG_MEMORY_2     (0x02)	/* Memory Expansion */
+#define PROD_LAN_ROVER         (0xFE)	/* Lan Rover Ethernet */
+#define PROD_TWIN_X            (0xFF)	/* Twin-X Serial Card */
+
+#define MANUF_IMTRONICS        (0x0404)	/* Imtronics */
+#define PROD_HURRICANE_2800    (0x39)	/* Hurricane 2800 68030 */
+#define PROD_HURRICANE_2800_2  (0x57)	/* Hurricane 2800 68030 */
+
+#define MANUF_UNIV_OF_LOWELL   (0x0406)	/* University of Lowell */
+#define PROD_A2410             (0x00)	/* CBM A2410 Hires Graphics Card */
+
+#define MANUF_AMERISTAR        (0x041D)	/* Ameristar */
+#define PROD_AMERISTAR2065     (0x01)	/* A2065 Ethernet Card */
+#define PROD_A560              (0x09)	/* Arcnet Card */
+#define PROD_A4066             (0x0A)	/* A4066 Ethernet Card */
+
+#define MANUF_SUPRA            (0x0420)	/* Supra */
+#define PROD_SUPRADRIVE_4x4    (0x01)	/* SupraDrive 4x4 SCSI Controller */
+#define PROD_SUPRA_2000        (0x03)	/* 2000 DMA HD */
+#define PROD_SUPRA_500         (0x05)	/* 500 HD/RAM */
+#define PROD_SUPRA_500XP       (0x09)	/* 500XP/2000 RAM */
+#define PROD_SUPRA_500RX       (0x0A)	/* 500RX/2000 RAM */
+#define PROD_SUPRA_2400ZI      (0x0B)	/* 2400zi Modem */
+#define PROD_WORDSYNC          (0x0C)	/* Supra Wordsync SCSI Controller */
+#define PROD_WORDSYNC_II       (0x0D)	/* Supra Wordsync II SCSI Controller */
+#define PROD_SUPRA_2400ZIPLUS  (0x10)	/* 2400zi+ Modem */
+
+#define MANUF_CSA              (0x0422)	/* Computer Systems Ass. */
+#define PROD_MAGNUM            (0x11)	/* Magnum 40 SCSI Controller */
+#define PROD_12GAUGE           (0x15)	/* 12 Gauge SCSI Controller */
+
+#define MANUF_MTEC2            (0x0502)	/* M-Tech */
+#define PROD_AT500_2           (0x03)	/* AT500 RAM */
+
+#define MANUF_GVP3             (0x06E1)	/* Great Valley Products */
+#define PROD_IMPACT            (0x08)	/* Impact SCSI/Memory */
+
+#define MANUF_BYTEBOX          (0x07DA)	/* ByteBox */
+#define PROD_BYTEBOX_A500      (0x00)	/* A500 */
+
+#define MANUF_HACKER           (0x07DB)	/* Test only: no product definitions */
+
+#define MANUF_POWER_COMPUTING  (0x07DC)	/* Power Computing (DKB) */
+#define PROD_DKB_3128          (0x0E)	/* DKB 3128 RAM */
+#define PROD_RAPID_FIRE        (0x0F)	/* Rapid Fire SCSI Controller */
+#define PROD_DKB_1202          (0x10)	/* DKB 1202 RAM */
+#define PROD_VIPER_II_COBRA    (0x12)	/* Viper II Turbo Board (DKB Cobra) */
+#define PROD_WILDFIRE_060      (0x17)	/* WildFire 060 Turbo Board */
+#define PROD_WILDFIRE_060_2    (0xFF)	/* WildFire 060 Turbo Board */
+
+#define MANUF_GVP              (0x07E1)	/* Great Valley Products */
+#define PROD_IMPACT_I_4K       (0x01)	/* Impact Series-I SCSI 4K */
+#define PROD_IMPACT_I_16K_2    (0x02)	/* Impact Series-I SCSI 16K/2 */
+#define PROD_IMPACT_I_16K_3    (0x03)	/* Impact Series-I SCSI 16K/3 */
+#define PROD_IMPACT_3001_IDE   (0x08)	/* Impact 3001 IDE */
+#define PROD_IMPACT_3001_RAM   (0x09)	/* Impact 3001 RAM */
+#define PROD_GVPIISCSI         (0x0B)	/* GVP Series II SCSI Controller */
+#define PROD_GVPIISCSI_2       (0x09)	/* evidence that the driver works
+					   for this product code also */
+#define PROD_GVPIIRAM          (0x0A)	/* GVP Series II RAM */
+#define PROD_GVP               (0x0B)	/* This code is used by a wide range of
+					   GVP products - use the epc to
+					   identify it correctly */
+#define PROD_GVP_A2000_030     (0x0D)	/* GVP A2000 68030 Turbo Board */
+#define PROD_IMPACT_3001_IDE_2 (0x0D)	/* Impact 3001 IDE */
+#define PROD_GFORCE_040_SCSI   (0x16)	/* GForce 040 with SCSI (new) */
+#define PROD_GVPIV_24          (0x20)	/* GVP IV-24 Graphics Board */
+#define PROD_GFORCE_040        (0xFF)	/* GForce 040 Turbo Board */
+/* #define PROD_GVPIO_EXT      (0xFF)*/	/* GVP I/O Extender */
+
+#define MANUF_SYNERGY          (0x07E5)	/* Synergy */
+
+#define MANUF_XETEC            (0x07E6)	/* Xetec */
+#define PROD_FASTCARD_SCSI     (0x01)	/* FastCard SCSI Controller */
+#define PROD_FASTCARD_RAM      (0x02)	/* FastCard RAM */
+
+#define MANUF_PPI              (0x07EA)	/* Progressive Peripherals Inc. */
+#define PROD_MERCURY           (0x00)	/* Mercury Turbo Board */
+#define PROD_PPS_A3000_040     (0x01)	/* PP&S A3000 68040 Turbo Board */
+#define PROD_PPS_A2000_040     (0x69)	/* PP&S A2000 68040 Turbo Board */
+#define PROD_ZEUS              (0x96)	/* Zeus SCSI Controller */
+#define PROD_PPS_A500_040      (0xBB)	/* PP&S A500 68040 Turbo Board */
+
+#define MANUF_XEBEC            (0x07EC)	/* Xebec */
+
+#define MANUF_SPIRIT           (0x07F2)	/* Spirit */
+#define PROD_HDA_506           (0x04)	/* HDA 506 Harddisk */
+#define PROD_OCTABYTE_RAM      (0x06)	/* OctaByte RAM */
+
+#define MANUF_BSC              (0x07FE)	/* BSC */
+#define PROD_ALF_3_SCSI        (0x03)	/* BSC ALF 3 SCSI Controller */
+
+#define MANUF_BSC3             (0x0801)	/* BSC */
+#define PROD_ALF_2_SCSI        (0x01)	/* ALF 2 SCSI Controller */
+#define PROD_ALF_2_SCSI_2      (0x02)	/* ALF 2 SCSI Controller */
+#define PROD_ALF_3_SCSI_2      (0x03)	/* ALF 3 SCSI Controller */
+
+#define MANUF_C_LTD            (0x0802)	/* C Ltd. */
+#define PROD_KRONOS_SCSI       (0x04)	/* Kronos SCSI Controller */
+#define PROD_A1000_SCSI_2      (0x0C)	/* A1000 SCSI Controller */
+
+#define MANUF_JOCHHEIM         (0x0804)	/* Jochheim */
+#define PROD_JOCHHEIM_RAM      (0x01)	/* Jochheim RAM */
+
+#define MANUF_CHECKPOINT       (0x0807)	/* Checkpoint Technologies */
+#define PROD_SERIAL_SOLUTION   (0x00)	/* Serial Solution */
+
+#define MANUF_ICD              (0x0817)	/* ICD */
+#define PROD_ADVANTAGE_2000    (0x01)	/* Advantage 2000 SCSI Controller */
+
+#define MANUF_KUPKE2           (0x0819)	/* Kupke */
+#define PROD_KUPKE_SCSI_II     (0x02)	/* Golem SCSI-II Controller */
+#define PROD_GOLEM_BOX         (0x03)	/* Golem Box */
+#define PROD_KUPKE_TURBO       (0x04)	/* 030/882 Turbo Board */
+#define PROD_KUPKE_SCSI_AT     (0x05)	/* SCSI/AT Controller */
+
+#define MANUF_GVP4             (0x081D)	/* Great Valley Products */
+#define PROD_A2000_RAM8        (0x09)	/* A2000-RAM8/2 */
+
+#define MANUF_INTERWORKS_NET   (0x081E)	/* Interworks Network */
+
+#define MANUF_HARDITAL         (0x0820)	/* Hardital Synthesis */
+#define PROD_TQM               (0x14)	/* TQM 68030+68882 Turbo Board */
+
+#define MANUF_BSC2             (0x082C)	/* BSC */
+#define PROD_OKTAGON_SCSI      (0x05)	/* BSC Oktagon 2008 SCSI Controller */
+#define PROD_TANDEM            (0x06)	/* BSC Tandem AT-2008/508 IDE */
+#define PROD_ALPHA_RAM_1200    (0x07)	/* Alpha RAM 1200 */
+#define PROD_OKTAGON_RAM       (0x08)	/* BSC Oktagon 2008 RAM */
+#define PROD_MULTIFACE_I       (0x10)	/* Alfa Data MultiFace I */
+#define PROD_MULTIFACE_II      (0x11)	/* Alfa Data MultiFace II */
+#define PROD_MULTIFACE_III     (0x12)	/* Alfa Data MultiFace III */
+#define PROD_BSC_FRAEMBUFFER   (0x20)	/* Framebuffer */
+#define PROD_GRAFFITI_RAM      (0x21)	/* Graffiti Graphics Board */
+#define PROD_GRAFFITI_REG      (0x22)
+#define PROD_ISDN_MASTERCARD   (0x40)	/* BSC ISDN MasterCard */
+#define PROD_ISDN_MASTERCARD_2 (0x41)	/* BSC ISDN MasterCard II */
+
+#define MANUF_ADV_SYS_SOFT     (0x0836)	/* Advanced Systems & Software */
+#define PROD_NEXUS_SCSI        (0x01)	/* Nexus SCSI Controller */
+#define PROD_NEXUS_RAM         (0x08)	/* Nexus RAM */
+
+#define MANUF_IMPULSE          (0x0838)	/* Impulse */
+#define PROD_FIRECRACKER_24    (0x00)	/* FireCracker 24 */
+
+#define MANUF_IVS              (0x0840)	/* IVS */
+#define PROD_GRANDSLAM_PIC_2   (0x02)	/* GrandSlam PIC 2 RAM */
+#define PROD_GRANDSLAM_PIC_1   (0x04)	/* GrandSlam PIC 1 RAM */
+#define PROD_IVS_OVERDRIVE     (0x10)	/* OverDrive HD */
+#define PROD_TRUMPCARD_CLASSIC (0x30)	/* Trumpcard Classic SCSI Controller */
+#define PROD_TRUMPCARD_PRO     (0x34)	/* Trumpcard Pro SCSI Controller */
+#define PROD_META_4            (0x40)	/* Meta-4 RAM */
+#define PROD_WAVETOOLS         (0xBF)	/* Wavetools Sound Board */
+#define PROD_VECTOR            (0xF3)	/* Vector SCSI Controller */
+#define PROD_VECTOR_2          (0xF4)	/* Vector SCSI Controller */
+
+#define MANUF_VECTOR           (0x0841)	/* Vector */
+#define PROD_CONNECTION        (0xE3)	/* Connection Serial IO */
+
+#define MANUF_XPERT_PRODEV     (0x0845)	/* XPert/ProDev */
+#define PROD_VISIONA_RAM       (0x01)	/* Visiona Graphics Board */
+#define PROD_VISIONA_REG       (0x02)
+#define PROD_MERLIN_RAM        (0x03)	/* Merlin Graphics Board */
+#define PROD_MERLIN_REG        (0x04)
+#define PROD_MERLIN_REG_2      (0xC9)
+
+#define MANUF_HYDRA_SYSTEMS    (0x0849)	/* Hydra Systems */
+#define PROD_AMIGANET          (0x01)	/* Amiganet Board */
+
+#define MANUF_SUNRIZE          (0x084F)	/* Sunrize Industries */
+#define PROD_AD1012            (0x01)	/* AD1012 Sound Board */
+#define PROD_AD516             (0x02)	/* AD516 Sound Board */
+#define PROD_DD512             (0x03)	/* DD512 Sound Board */
+
+#define MANUF_TRICERATOPS      (0x0850)	/* Triceratops */
+#define PROD_TRICERATOPS       (0x01)	/* Triceratops Multi I/O Board */
+
+#define MANUF_APPLIED_MAGIC    (0x0851)	/* Applied Magic Inc */
+#define PROD_DMI_RESOLVER      (0x01)	/* DMI Resolver Graphics Board */
+#define PROD_DIGITAL_BCASTER   (0x06)	/* Digital Broadcaster */
+
+#define MANUF_GFX_BASE         (0x085E)	/* GFX-Base */
+#define PROD_GDA_1_RAM         (0x00)	/* GDA-1 Graphics Board */
+#define PROD_GDA_1_REG         (0x01)
+
+#define MANUF_ROCTEC           (0x0860)	/* RocTec */
+#define PROD_RH_800C           (0x01)	/* RH 800C Hard Disk Controller */
+#define PROD_RH_800C_RAM       (0x01)	/* RH 800C RAM */
+
+#define MANUF_HELFRICH1        (0x0861)	/* Helfrich */
+#define PROD_RAINBOW3          (0x21)	/* Rainbow3 Graphics Board */
+
+#define MANUF_SW_RESULT_ENTS   (0x0866)	/* Software Result Enterprises */
+#define PROD_GG2PLUS           (0x01)	/* GG2+ Bus Converter */
+
+#define MANUF_MASOBOSHI        (0x086D)	/* Masoboshi */
+#define PROD_MASTER_CARD_RAM   (0x03)	/* Master Card RAM */
+#define PROD_MASTER_CARD_SCSI  (0x04)	/* Master Card SCSI Controller */
+#define PROD_MVD_819           (0x07)	/* MVD 819 */
+
+#define MANUF_DELACOMP         (0x0873)	/* DelaComp */
+#define PROD_DELACOMP_RAM_2000 (0x01)	/* RAM Expansion 2000 */
+
+#define MANUF_VILLAGE_TRONIC   (0x0877)	/* Village Tronic */
+#define PROD_DOMINO_RAM        (0x01)	/* Domino Graphics Board */
+#define PROD_DOMINO_REG        (0x02)
+#define PROD_PICASSO_II_RAM    (0x0B)	/* Picasso II/II+ Graphics Board */
+#define PROD_PICASSO_II_REG    (0x0C)
+#define PROD_PICASSO_II_SEGM   (0x0D)	/* Picasso II/II+ (Segmented Mode) */
+#define PROD_PICASSO_IV        (0x15)	/* Picassio IV Graphics Board */
+#define PROD_PICASSO_IV_2      (0x16)
+#define PROD_PICASSO_IV_3      (0x17)
+#define PROD_PICASSO_IV_4      (0x18)
+#define PROD_ARIADNE           (0xC9)	/* Ariadne Ethernet */
+
+#define MANUF_UTILITIES_ULTD   (0x087B)	/* Utilities Unlimited */
+#define PROD_EMPLANT_DELUXE    (0x15)	/* Emplant Deluxe SCSI Controller */
+#define PROD_EMPLANT_DELUXE2   (0x20)	/* Emplant Deluxe SCSI Controller */
+
+#define MANUF_AMITRIX          (0x0880)	/* Amitrix */
+#define PROD_AMITRIX_MULTI_IO  (0x01)	/* Multi-IO */
+#define PROD_AMITRIX_CD_RAM    (0x02)	/* CD-RAM Memory */
+
+#define MANUF_ARMAX            (0x0885)	/* ArMax */
+#define PROD_OMNIBUS           (0x00)	/* OmniBus Graphics Board */
+
+#define MANUF_NEWTEK           (0x088F)	/* NewTek */
+#define PROD_VIDEOTOASTER      (0x00)	/* VideoToaster */
+
+#define MANUF_MTEC             (0x0890)	/* M-Tech Germany */
+#define PROD_AT500             (0x01)	/* AT500 IDE Controller */
+#define PROD_MTEC_68030        (0x03)	/* 68030 Turbo Board */
+#define PROD_MTEC_68020I       (0x06)	/* 68020i Turbo Board */
+#define PROD_MTEC_T1230        (0x20)	/* A1200 T68030/42 RTC Turbo Board */
+#define PROD_MTEC_RAM          (0x22)	/* MTEC 8MB RAM */
+
+#define MANUF_GVP2             (0x0891)	/* Great Valley Products */
+#define PROD_SPECTRUM_RAM      (0x01)	/* EGS 28/24 Spectrum Graphics Board */
+#define PROD_SPECTRUM_REG      (0x02)
+
+#define MANUF_HELFRICH2        (0x0893)	/* Helfrich */
+#define PROD_PICCOLO_RAM       (0x05)	/* Piccolo Graphics Board */
+#define PROD_PICCOLO_REG       (0x06)
+#define PROD_PEGGY_PLUS        (0x07)	/* PeggyPlus MPEG Decoder Board */
+#define PROD_VIDEOCRUNCHER     (0x08)	/* VideoCruncher */
+#define PROD_SD64_RAM          (0x0A)	/* SD64 Graphics Board */
+#define PROD_SD64_REG          (0x0B)
+
+#define MANUF_MACROSYSTEMS     (0x089B)	/* MacroSystems USA */
+#define PROD_WARP_ENGINE       (0x13)	/* Warp Engine 40xx SCSI Controller */
+
+#define MANUF_ELBOX            (0x089E)	/* ElBox Computer */
+#define PROD_ELBOX_1200        (0x06)	/* Elbox 1200/4 RAM */
+
+#define MANUF_HARMS_PROF       (0x0A00)	/* Harms Professional */
+#define PROD_HARMS_030_PLUS    (0x10)	/* 030 plus */
+#define PROD_3500_TURBO        (0xD0)	/* 3500 Turbo board */
+
+#define MANUF_MICRONIK         (0x0A50)	/* Micronik */
+#define PROD_RCA_120           (0x0A)	/* RCA 120 RAM */
+
+#define MANUF_MEGA_MICRO       (0x1000)	/* MegaMicro */
+#define PROD_SCRAM_500_SCSI    (0x03)	/* SCRAM 500 SCSI Controller */
+#define PROD_SCRAM_500_RAM     (0x04)	/* SCRAM 500 RAM */
+
+#define MANUF_IMTRONICS2       (0x1028)	/* Imtronics */
+#define PROD_HURRICANE_2800_3  (0x39)	/* Hurricane 2800 68030 */
+#define PROD_HURRICANE_2800_4  (0x57)	/* Hurricane 2800 68030 */
+
+#define MANUF_KUPKE3           (0x1248)	/* Kupke */
+#define PROD_GOLEM_3000        (0x01)	/* Golem HD 3000 */
+
+#define MANUF_ITH              (0x1388)	/* ITH */
+#define PROD_ISDN_MASTER_II    (0x01)	/* ISDN-Master II */
+
+#define MANUF_VMC              (0x1389)	/* VMC */
+#define PROD_ISDN_BLASTER_Z2   (0x01)	/* ISDN Blaster Z2 */
+#define PROD_HYPERCOM_4        (0x02)	/* HyperCom 4 */
+
+#define MANUF_INFORMATION      (0x157C)	/* Information */
+#define PROD_ISDN_ENGINE_I     (0x64)	/* ISDN Engine I */
+
+#define MANUF_VORTEX           (0x2017)	/* Vortex */
+#define PROD_GOLDEN_GATE_386SX (0x07)	/* Golden Gate 80386SX Board */
+#define PROD_GOLDEN_GATE_RAM   (0x08)	/* Golden Gate RAM */
+#define PROD_GOLDEN_GATE_486   (0x09)	/* Golden Gate 80486 Board */
+
+#define MANUF_DATAFLYER        (0x2062)	/* DataFlyer */
+#define PROD_DATAFLYER_4000SXS (0x01)	/* DataFlyer 4000SX SCSI Controller */
+#define PROD_DATAFLYER_4000SXR (0x02)	/* DataFlyer 4000SX RAM */
+
+#define MANUF_READYSOFT        (0x2100)	/* ReadySoft */
+#define PROD_AMAX              (0x01)	/* AMax II/IV */
+
+#define MANUF_PHASE5           (0x2140)	/* Phase5 */
+#define PROD_BLIZZARD_RAM      (0x01)	/* Blizzard RAM */
+#define PROD_BLIZZARD          (0x02)	/* Blizzard */
+#define PROD_BLIZZARD_1220_IV  (0x06)	/* Blizzard 1220-IV Turbo Board */
+#define PROD_FASTLANE_RAM      (0x0A)	/* FastLane RAM */
+#define PROD_FASTLANE_SCSI     (0x0B)	/* FastLane/Blizzard 1230-II SCSI/CyberSCSI */
+#define PROD_CYBERSTORM_SCSI   (0x0C)	/* Blizzard 1220/CyberStorm */
+#define PROD_BLIZZARD_1230_III (0x0D)	/* Blizzard 1230-III Turbo Board */
+#define PROD_BLIZZARD_1230_IV  (0x11)	/* Blizzard 1230-IV/1260 Turbo Board */
+#define PROD_BLIZZARD_2060SCSI (0x18)	/* Blizzard 2060 SCSI Controller */
+#define PROD_CYBERSTORM_II     (0x19)	/* CyberStorm Mk II */
+#define PROD_CYBERVISION       (0x22)	/* CyberVision64 Graphics Board */
+#define PROD_CYBERVISION3D_PRT (0x32)	/* CyberVision64-3D Prototype */
+#define PROD_CYBERVISION3D     (0x43)	/* CyberVision64-3D Graphics Board */
+
+#define MANUF_DPS              (0x2169)	/* DPS */
+#define PROD_DPS_PAR           (0x01)	/* Personal Animation Recorder */
+
+#define MANUF_APOLLO2          (0x2200)	/* Apollo */
+#define PROD_A620              (0x00)	/* A620 68020 Accelerator */
+#define PROD_A620_2            (0x01)	/* A620 68020 Accelerator */
+
+#define MANUF_APOLLO           (0x2222)	/* Apollo */
+#define PROD_AT_APOLLO         (0x22)	/* AT-Apollo */
+#define PROD_APOLLO_TURBO      (0x23)	/* Apollo Turbo Board */
+
+#define MANUF_PETSOFF          (0x38A5)	/* Petsoff LP */
+#define PROD_DELFINA           (0x00)	/* Delfina DSP */
+
+#define MANUF_UWE_GERLACH      (0x3FF7)	/* Uwe Gerlach */
+#define PROD_UG_RAM_ROM        (0xd4)	/* RAM/ROM */
+
+#define MANUF_MACROSYSTEMS2    (0x4754)	/* MacroSystems Germany */
+#define PROD_MAESTRO           (0x03)	/* Maestro */
+#define PROD_VLAB              (0x04)	/* VLab */
+#define PROD_MAESTRO_PRO       (0x05)	/* Maestro Pro */
+#define PROD_RETINA_Z2         (0x06)	/* Retina Z2 Graphics Board */
+#define PROD_MULTI_EVOLUTION   (0x08)	/* MultiEvolution */
+#define PROD_TOCCATA           (0x0C)	/* Toccata Sound Board */
+#define PROD_RETINA_Z3         (0x10)	/* Retina Z3 Graphics Board */
+#define PROD_VLAB_MOTION       (0x12)	/* VLab Motion */
+#define PROD_ALTAIS            (0x13)	/* Altais Graphics Board */
+#define PROD_FALCON_040        (0xFD)	/* Falcon '040 Turbo Board */
+
+#define MANUF_COMBITEC         (0x6766)	/* Combitec */
+
+#define MANUF_SKI              (0x8000)	/* SKI Peripherals */
+#define PROD_MAST_FIREBALL     (0x08)	/* M.A.S.T. Fireball SCSI Controller */
+#define PROD_SKI_SCSI_SERIAL   (0x80)	/* SCSI / Dual Serial */
+
+#define MANUF_CAMERON          (0xAA01)	/* Cameron */
+#define PROD_PERSONAL_A4       (0x10)	/* Personal A4 */
+
+#define MANUF_REIS_WARE        (0xAA11)	/* Reis-Ware */
+#define PROD_RW_HANDYSCANNER   (0x11)	/* Handyscanner */
+
+
+/* Illegal Manufacturer IDs. These do NOT appear in arch/m68k/amiga/zorro.c! */
+
+#define MANUF_HACKER_INC       (0x07DB)	/* Hacker Inc. */
+#define PROD_HACKER_SCSI       (0x01)	/* Hacker Inc. SCSI Controller */
+
+#define MANUF_RES_MNGT_FORCE   (0x07DB)	/* Resource Management Force */
+#define PROD_QUICKNET          (0x02)	/* QuickNet Ethernet */
+
+#define MANUF_VECTOR2          (0x07DB)	/* Vector */
+#define PROD_CONNECTION_2      (0xE0)	/* Vector Connection */
+#define PROD_CONNECTION_3      (0xE1)	/* Vector Connection */
+#define PROD_CONNECTION_4      (0xE2)	/* Vector Connection */
+#define PROD_CONNECTION_5      (0xE3)	/* Vector Connection */
+
+
+/*
+ * GVP's identifies most of their product through the 'extended
+ * product code' (epc). The epc has to be and'ed with the GVP_PRODMASK
+ * before the identification.
+ */
+
+#define GVP_PRODMASK    (0xf8)
+#define GVP_SCSICLKMASK (0x01)
+
+enum GVP_ident {
+  GVP_GFORCE_040      = 0x20,
+  GVP_GFORCE_040_SCSI = 0x30,
+  GVP_A1291_SCSI      = 0x40,
+  GVP_COMBO_R4        = 0x60,
+  GVP_COMBO_R4_SCSI   = 0x70,
+  GVP_PHONEPAK        = 0x78,
+  GVP_IOEXT           = 0x98,
+  GVP_GFORCE_030      = 0xa0,
+  GVP_GFORCE_030_SCSI = 0xb0,
+  GVP_A530            = 0xc0,
+  GVP_A530_SCSI       = 0xd0,
+  GVP_COMBO_R3        = 0xe0,
+  GVP_COMBO_R3_SCSI   = 0xf0,
+  GVP_SERIESII        = 0xf8,
+};
+
+enum GVP_flags {
+  GVP_IO       = 0x01,
+  GVP_ACCEL    = 0x02,
+  GVP_SCSI     = 0x04,
+  GVP_24BITDMA = 0x08,
+  GVP_25BITDMA = 0x10,
+  GVP_NOBANK   = 0x20,
+  GVP_14MHZ    = 0x40,
+};
+
+
+struct Node {
+    struct  Node *ln_Succ;	/* Pointer to next (successor) */
+    struct  Node *ln_Pred;	/* Pointer to previous (predecessor) */
+    u_char  ln_Type;
+    char    ln_Pri;		/* Priority, for sorting */
+    char    *ln_Name;		/* ID string, null terminated */
+};
+
+struct ExpansionRom {
+    /* -First 16 bytes of the expansion ROM */
+    u_char	er_Type;	/* Board type, size and flags */
+    u_char	er_Product;	/* Product number, assigned by manufacturer */
+    u_char	er_Flags;	/* Flags */
+    u_char	er_Reserved03;	/* Must be zero ($ff inverted) */
+    u_short	er_Manufacturer; /* Unique ID,ASSIGNED BY COMMODORE-AMIGA! */
+    u_long	er_SerialNumber; /* Available for use by manufacturer */
+    u_short	er_InitDiagVec;	/* Offset to optional "DiagArea" structure */
+    u_char	er_Reserved0c;
+    u_char	er_Reserved0d;
+    u_char	er_Reserved0e;
+    u_char	er_Reserved0f;
+};
+
+/* er_Type board type bits */
+#define ERT_TYPEMASK	0xc0
+#define ERT_ZORROII	0xc0
+#define ERT_ZORROIII	0x80
+
+/* other bits defined in er_Type */
+#define ERTB_MEMLIST	5		/* Link RAM into free memory list */
+#define ERTF_MEMLIST	(1<<5)
+
+struct ConfigDev {
+    struct Node 	cd_Node;
+    u_char		cd_Flags;	/* (read/write) */
+    u_char		cd_Pad; 	/* reserved */
+    struct ExpansionRom cd_Rom; 	/* copy of board's expansion ROM */
+    void		*cd_BoardAddr;	/* where in memory the board was placed */
+    u_long		cd_BoardSize;	/* size of board in bytes */
+    u_short		cd_SlotAddr;	/* which slot number (PRIVATE) */
+    u_short		cd_SlotSize;	/* number of slots (PRIVATE) */
+    void		*cd_Driver;	/* pointer to node of driver */
+    struct ConfigDev	*cd_NextCD;	/* linked list of drivers to config */
+    u_long		cd_Unused[4];	/* for whatever the driver wants */
+};
+
+#else	/* __ASSEMBLY__ */
+
+LN_Succ		= 0
+LN_Pred		= LN_Succ+4
+LN_Type		= LN_Pred+4
+LN_Pri		= LN_Type+1
+LN_Name		= LN_Pri+1
+LN_sizeof	= LN_Name+4
+
+ER_Type		= 0
+ER_Product	= ER_Type+1
+ER_Flags	= ER_Product+1
+ER_Reserved03	= ER_Flags+1
+ER_Manufacturer	= ER_Reserved03+1
+ER_SerialNumber	= ER_Manufacturer+2
+ER_InitDiagVec	= ER_SerialNumber+4
+ER_Reserved0c	= ER_InitDiagVec+2
+ER_Reserved0d	= ER_Reserved0c+1
+ER_Reserved0e	= ER_Reserved0d+1
+ER_Reserved0f	= ER_Reserved0e+1
+ER_sizeof	= ER_Reserved0f+1
+
+CD_Node		= 0
+CD_Flags	= CD_Node+LN_sizeof
+CD_Pad		= CD_Flags+1
+CD_Rom		= CD_Pad+1
+CD_BoardAddr	= CD_Rom+ER_sizeof
+CD_BoardSize	= CD_BoardAddr+4
+CD_SlotAddr	= CD_BoardSize+4
+CD_SlotSize	= CD_SlotAddr+2
+CD_Driver	= CD_SlotSize+2
+CD_NextCD	= CD_Driver+4
+CD_Unused	= CD_NextCD+4
+CD_sizeof	= CD_Unused+(4*4)
+
+#endif	/* __ASSEMBLY__ */
+
+#ifndef __ASSEMBLY__
+
+#define ZORRO_NUM_AUTO		16
+
+#ifdef __KERNEL__
+
+extern int zorro_num_autocon;		/* # of autoconfig devices found */
+extern struct ConfigDev zorro_autocon[ZORRO_NUM_AUTO];
+
+
+/*
+ * Zorro Functions
+ */
+
+extern int zorro_find(int manuf, int prod, int part, int index);
+extern struct ConfigDev *zorro_get_board(int key);
+extern void zorro_config_board(int key, int part);
+extern void zorro_unconfig_board(int key, int part);
+
+
+/*
+ * Bitmask indicating portions of available Zorro II RAM that are unused
+ * by the system. Every bit represents a 64K chunk, for a maximum of 8MB
+ * (128 chunks, physical 0x00200000-0x009fffff).
+ *
+ * If you want to use (= allocate) portions of this RAM, you should clear
+ * the corresponding bits.
+ */
+
+extern u_long zorro_unused_z2ram[4];
+
+#define Z2RAM_START		(0x00200000)
+#define Z2RAM_END		(0x00a00000)
+#define Z2RAM_SIZE		(0x00800000)
+#define Z2RAM_CHUNKSIZE		(0x00010000)
+#define Z2RAM_CHUNKMASK		(0x0000ffff)
+#define Z2RAM_CHUNKSHIFT	(16)
+
+
+/*
+ * Verbose Board Identification
+ */
+
+extern void zorro_identify(void);
+extern int zorro_get_list(char *buffer);
+
+#endif	/* !__ASSEMBLY__ */
+#endif	/* __KERNEL__ */
+
+#endif /* __ZORRO_H */
diff -u --recursive --new-file v2.1.35/linux/include/net/sock.h linux/include/net/sock.h
--- v2.1.35/linux/include/net/sock.h	Mon Apr 14 16:28:26 1997
+++ linux/include/net/sock.h	Wed Apr 23 11:01:33 1997
@@ -179,6 +179,7 @@
 
 #endif /* IPV6 */
 
+
 struct tcp_opt
 {
 /*
@@ -197,6 +198,7 @@
 
 	__u32	rcv_wup;	/* rcv_nxt on last window update sent	*/
 
+	__u32	fin_seq;	/* XXX This one should go, we don't need it. -DaveM */
 
 	__u32	srtt;		/* smothed round trip time << 3		*/
 	__u32	mdev;		/* medium deviation			*/
@@ -207,6 +209,28 @@
  */
  	__u32	snd_cwnd;	/* Sending congestion window		*/
  	__u32	snd_ssthresh;	/* Slow start size threshold		*/
+	__u16	snd_cwnd_cnt;
+	__u16	max_window;
+
+/*
+ *      Options received (usually on last packet, some only on SYN packets).
+ */
+	char	tstamp_ok,	/* TIMESTAMP seen on SYN packet		*/
+		sack_ok;	/* SACK_PERM seen on SYN packet		*/
+	char	saw_tstamp;	/* Saw TIMESTAMP on last packet		*/
+        __u16	in_mss;		/* MSS option received from sender	*/
+        __u8	snd_wscale;	/* Window scaling received from sender	*/
+        __u8	rcv_wscale;	/* Window scaling to send to receiver	*/
+        __u32	rcv_tsval;	/* Time stamp value             	*/
+        __u32	rcv_tsecr;	/* Time stamp echo reply        	*/
+        __u32	ts_recent;	/* Time stamp to echo next		*/
+        __u32	ts_recent_stamp;/* Time we stored ts_recent (for aging) */
+	__u32	last_ack_sent;	/* last ack we sent			*/
+        int	sacks;		/* Number of SACK blocks if any		*/
+        __u32	left_sack[4];	/* Left edges of blocks         	*/
+        __u32	right_sack[4];	/* Right edges of blocks        	*/
+	int	tcp_header_len;      /* Bytes of tcp header to send 	*/
+
 /*
  *	Timers used by the TCP protocol layer
  */
@@ -217,17 +241,21 @@
  	struct timer_list	retransmit_timer;	/* Resend (no ack) */
 
 	__u32	basertt;	/* Vegas baseRTT */
+	__u32	packets_out;	/* Packets which are "in flight" */
+	__u32	window_clamp;	/* XXX Document this... -DaveM */
 
+	__u8	pending;	/* pending events */
 	__u8	delayed_acks;
-	__u8	dup_acks;
+	__u8	dup_acks;	/* Consequetive duplicate acks seen from other end */
+	__u8	retransmits;
 
 	__u32	lrcvtime;	/* timestamp of last received data packet  */
 	__u32	rcv_tstamp;	/* timestamp of last received packet  */
 	__u32	iat_mdev;	/* interarrival time medium deviation */
 	__u32	iat;		/* interarrival time */
 	__u32	ato;		/* delayed ack timeout */
+	__u32	high_seq;	/* highest sequence number sent by onset of congestion */
 
-	__u32	high_seq;
 /*
  *	new send pointers
  */
@@ -238,11 +266,6 @@
 						 * fast retransmit
 						 */
 /*
- * pending events
- */
-	__u8	pending;
-
-/*
  *	Header prediction flags
  *	0x5?10 << 16 + snd_wnd in net byte order
  */
@@ -252,6 +275,7 @@
 	__u32	probes_out;		/* unanswered 0 window probes	   */
 
 	struct open_request	*syn_wait_queue;
+	struct open_request	**syn_wait_last;
 	struct tcp_func		*af_specific;
 };
 
@@ -311,29 +335,29 @@
 	atomic_t		wmem_alloc;
 	atomic_t		rmem_alloc;
 	unsigned long		allocation;		/* Allocation mode */
+
+	/* The following stuff should probably move to the tcp private area */
 	__u32			write_seq;
 	__u32			copied_seq;
-	__u32			fin_seq;
 	__u32			syn_seq;
 	__u32			urg_seq;
 	__u32			urg_data;
+	unsigned char		delayed_acks;
+	/* End of block to move */
+
 	int			sock_readers;		/* user count */
 
-	unsigned char		delayed_acks,
-				dup_acks;
   /*
    *	Not all are volatile, but some are, so we
    * 	might as well say they all are.
    */
 	volatile char		dead,
 				urginline,
-				intr,
 				done,
 				reuse,
 				keepopen,
 				linger,
 				destroy,
-				ack_timed,
 				no_check,
 				zapped,	/* In ax25 & ipx means not linked */
 				broadcast,
@@ -350,12 +374,7 @@
 	int			hashent;
 	struct sock		*pair;
 
-	struct sk_buff		* send_head;
-
 	struct sk_buff_head	back_log;
-	struct sk_buff		*partial;
-	struct timer_list	partial_timer;
-	atomic_t		retransmits;
 
 	struct sk_buff_head	write_queue,
 				receive_queue,
@@ -374,22 +393,14 @@
 
 	unsigned short		max_unacked;
 
-
-	unsigned short		bytes_rcv;
 /*
  *	mss is min(mtu, max_window) 
  */
 	unsigned short		mtu;       /* mss negotiated in the syn's */
 	unsigned short		mss;       /* current eff. mss - can change */
 	unsigned short		user_mss;  /* mss requested by user in ioctl */
-	unsigned short		max_window;
-	unsigned long 		window_clamp;
-	unsigned int		ssthresh;
 	unsigned short		num;
 
-	unsigned short		cong_window;
-	unsigned short		cong_count;
-	atomic_t		packets_out;
 	unsigned short		shutdown;
 
 #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
@@ -404,13 +415,7 @@
 		struct raw6_opt		tp_raw;
 #endif
 	} tp_pinfo;
-/*
- *	currently backoff isn't used, but I'm maintaining it in case
- *	we want to go back to a backoff formula that needs it
- */
-/* 
-	unsigned short		backoff;
- */
+
 	int			err, err_soft;	/* Soft holds errors that don't
 						   cause failure but are the cause
 						   of a persistent failure not just
@@ -426,6 +431,7 @@
 	unsigned short		type;
 	unsigned char		localroute;	/* Route locally only */
 	struct ucred		peercred;
+
 	/* What the user has tried to set with the security API */
 	short			authentication;
 	short			encryption;  
@@ -471,10 +477,6 @@
 	int			ip_tos;			/* TOS */
 	unsigned	   	ip_cmsg_flags;
 	struct tcphdr		dummy_th;
-	struct timer_list	keepalive_timer;	/* TCP keepalive hack */
-	struct timer_list	retransmit_timer;	/* TCP retransmit timer */
-	struct timer_list	delack_timer;		/* TCP delayed ack timer */
-	int			ip_xmit_timeout;	/* Why the timeout is running */
 	struct ip_options	*opt;
 	unsigned char		ip_hdrincl;		/* Include headers ? */
 	__u8			ip_mc_ttl;		/* Multicasting TTL */
@@ -491,8 +493,8 @@
  
 	int			timeout;	/* What are we waiting for? */
 	struct timer_list	timer;		/* This is the TIME_WAIT/receive timer
-					 * when we are doing IP
-					 */
+						 * when we are doing IP
+						 */
 	struct timeval		stamp;
 
  /*
diff -u --recursive --new-file v2.1.35/linux/include/net/tcp.h linux/include/net/tcp.h
--- v2.1.35/linux/include/net/tcp.h	Mon Apr 14 16:28:26 1997
+++ linux/include/net/tcp.h	Wed Apr 23 11:03:11 1997
@@ -23,8 +23,11 @@
 #include <linux/slab.h>
 #include <net/checksum.h>
 
-/* This is for all connections with a full identity, no wildcards. */
-#define TCP_HTABLE_SIZE		256
+/* This is for all connections with a full identity, no wildcards.
+ * New scheme, half the table is for TIME_WAIT, the other half is
+ * for the rest.  I'll experiment with dynamic table growth later.
+ */
+#define TCP_HTABLE_SIZE		1024
 
 /* This is for listening sockets, thus all sockets which possess wildcards. */
 #define TCP_LHTABLE_SIZE	32	/* Yes, really, this is all you need. */
@@ -52,9 +55,7 @@
 	return tcp_bhashfn(lport);
 }
 
-/* These can have wildcards, don't try too hard.
- * XXX deal with thousands of IP aliases for listening ports later
- */
+/* These can have wildcards, don't try too hard. */
 static __inline__ int tcp_lhashfn(unsigned short num)
 {
 	return num & (TCP_LHTABLE_SIZE - 1);
@@ -95,11 +96,13 @@
 
 /*
  * 40 is maximal IP options size
- * 4  is TCP option size (MSS)
+ * 20 is the maximum TCP options size we can currently construct on a SYN.
+ * 40 is the maximum possible TCP options size.
  */
 
-#define MAX_SYN_SIZE	(NETHDR_SIZE + sizeof(struct tcphdr) + 4 + MAX_HEADER + 15)
+#define MAX_SYN_SIZE	(NETHDR_SIZE + sizeof(struct tcphdr) + 20 + MAX_HEADER + 15)
 #define MAX_FIN_SIZE	(NETHDR_SIZE + sizeof(struct tcphdr) + MAX_HEADER + 15)
+#define BASE_ACK_SIZE	(NETHDR_SIZE + MAX_HEADER + 15)
 #define MAX_ACK_SIZE	(NETHDR_SIZE + sizeof(struct tcphdr) + MAX_HEADER + 15)
 #define MAX_RESET_SIZE	(NETHDR_SIZE + sizeof(struct tcphdr) + MAX_HEADER + 15)
 
@@ -163,6 +166,8 @@
  *	We don't use these yet, but they are for PAWS and big windows
  */
 #define TCPOPT_WINDOW		3	/* Window scaling */
+#define TCPOPT_SACK_PERM        4       /* SACK Permitted */
+#define TCPOPT_SACK             5       /* SACK Block */
 #define TCPOPT_TIMESTAMP	8	/* Better RTT estimations/PAWS */
 
 /*
@@ -171,8 +176,15 @@
 
 #define TCPOLEN_MSS            4
 #define TCPOLEN_WINDOW         3
+#define TCPOLEN_SACK_PERM      2
 #define TCPOLEN_TIMESTAMP      10
 
+/*
+ *      TCP option flags for parsed options.
+ */
+
+#define TCPOPTF_SACK_PERM       1
+#define TCPOPTF_TIMESTAMP       2
 
 /*
  *	TCP Vegas constants
@@ -206,11 +218,15 @@
 
 struct open_request {
 	struct open_request	*dl_next;
-	struct open_request	*dl_prev;
+	struct open_request	**dl_pprev;
 	__u32			rcv_isn;
 	__u32			snt_isn;
 	__u16			rmt_port;
 	__u16			mss;
+	__u8			snd_wscale;
+	char			sack_ok;
+	char			tstamp_ok;
+	__u32			ts_recent;
 	unsigned long		expires;
 	int			retrans;
 	struct or_calltable	*class;
@@ -354,7 +370,7 @@
 					    int len, int nonblock, 
 					    int flags, int *addr_len);
 
-extern int			tcp_parse_options(struct tcphdr *th);
+extern void			tcp_parse_options(struct tcphdr *th, struct tcp_opt *tp);
 
 /*
  *	TCP v4 functions exported for the inet6 API
@@ -511,9 +527,8 @@
 
 	switch (state) {
 	case TCP_ESTABLISHED:
-		if (oldstate != TCP_ESTABLISHED) {
+		if (oldstate != TCP_ESTABLISHED)
 			tcp_statistics.TcpCurrEstab++;
-		}
 		break;
 
 	case TCP_CLOSE:
@@ -523,47 +538,68 @@
 	default:
 		if (oldstate==TCP_ESTABLISHED)
 			tcp_statistics.TcpCurrEstab--;
+		if (state == TCP_TIME_WAIT)
+			sk->prot->rehash(sk);
 	}
 }
 
-extern __inline__ void tcp_synq_unlink(struct tcp_opt *tp, struct open_request *req)
-{
-	if (req->dl_next == req)
-	{
-		tp->syn_wait_queue = NULL;
-	}
-	else
-	{
-		req->dl_prev->dl_next = req->dl_next;
-		req->dl_next->dl_prev = req->dl_prev;
-		
-		if (tp->syn_wait_queue == req)
-		{
-			tp->syn_wait_queue = req->dl_next;
+/*
+ * Construct a tcp options header for a SYN or SYN_ACK packet.
+ * If this is every changed make sure to change the definition of
+ * MAX_SYN_SIZE to match the new maximum number of options that you
+ * can generate.
+ * FIXME: This is completely disgusting.
+ * This is probably a good candidate for a bit of assembly magic.
+ * It would be especially magical to compute the checksum for this
+ * stuff on the fly here.
+ */
+extern __inline__ int tcp_syn_build_options(struct sk_buff *skb, int mss, int sack, int ts, int wscale)
+{
+	int count = 4 + (wscale ? 4 : 0) +  ((ts || sack) ? 4 : 0) +  (ts ? 8 : 0);
+	unsigned char *optr = skb_put(skb,count);
+	__u32 *ptr = (__u32 *)optr;
+
+	/*
+	 * We always get an MSS option.
+	 */
+	*ptr++ = htonl((TCPOPT_MSS << 24) | (TCPOLEN_MSS << 16) | mss);
+	if (ts) {
+		if (sack) {
+			*ptr++ = htonl((TCPOPT_SACK_PERM << 24) | (TCPOLEN_SACK_PERM << 16)
+					| (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP);
+			*ptr++ = htonl(jiffies);	/* TSVAL */
+			*ptr++ = htonl(0);		/* TSECR */
+		} else {
+			*ptr++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16)
+					| (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP);
+			*ptr++ = htonl(jiffies);	/* TSVAL */
+			*ptr++ = htonl(0);		/* TSECR */
 		}
+	} else if (sack) {
+		*ptr++ = htonl((TCPOPT_SACK_PERM << 24) | (TCPOLEN_SACK_PERM << 16)
+				| (TCPOPT_NOP << 8) | TCPOPT_NOP);
 	}
-
-	req->dl_prev = req->dl_next = NULL;
+	if (wscale)
+		*ptr++ = htonl((TCPOPT_WINDOW << 24) | (TCPOLEN_WINDOW << 16) | wscale);
+	skb->csum = csum_partial(optr, count, 0);
+	return count;
 }
 
-extern __inline__ void tcp_synq_queue(struct tcp_opt *tp, struct open_request *req)
+extern __inline__ void tcp_synq_unlink(struct tcp_opt *tp, struct open_request *req)
 {
-	if (!tp->syn_wait_queue)
-	{
-		req->dl_next = req;
-		req->dl_prev = req;
-		tp->syn_wait_queue = req;
-	}
+	if(req->dl_next)
+		req->dl_next->dl_pprev = req->dl_pprev;
 	else
-	{
-		struct open_request *list = tp->syn_wait_queue;
-		
-		req->dl_next = list;
-		req->dl_prev = list->dl_prev;
-		list->dl_prev->dl_next = req;
-		list->dl_prev = req;
-	}
+		tp->syn_wait_last = req->dl_pprev;
+	*req->dl_pprev = req->dl_next;
+}
 
+extern __inline__ void tcp_synq_queue(struct tcp_opt *tp, struct open_request *req)
+{
+	req->dl_next = NULL;
+	req->dl_pprev = tp->syn_wait_last;
+	*tp->syn_wait_last = req;
+	tp->syn_wait_last = &req->dl_next;
 }
 
 extern void __tcp_inc_slow_timer(struct tcp_sl_timer *slt);
@@ -587,4 +623,3 @@
 }
 
 #endif	/* _TCP_H */
-
diff -u --recursive --new-file v2.1.35/linux/init/main.c linux/init/main.c
--- v2.1.35/linux/init/main.c	Wed Apr 16 14:15:00 1997
+++ linux/init/main.c	Tue Apr 22 23:02:26 1997
@@ -896,7 +896,6 @@
 	memory_start = kmem_cache_init(memory_start, memory_end);
 	sti();
 	calibrate_delay();
-	memory_start = inode_init(memory_start,memory_end);
 	memory_start = file_table_init(memory_start,memory_end);
 	memory_start = name_cache_init(memory_start,memory_end);
 #ifdef CONFIG_BLK_DEV_INITRD
@@ -913,6 +912,7 @@
 	kmem_cache_sizes_init();
 	vma_init();
 	buffer_init();
+	inode_init();
 	sock_init();
 #if defined(CONFIG_SYSVIPC) || defined(CONFIG_KERNELD)
 	ipc_init();
@@ -948,7 +948,7 @@
 }
 
 #ifdef CONFIG_BLK_DEV_INITRD
-__initfunc(static int do_linuxrc(void * shell))
+static int do_linuxrc(void * shell)
 {
 	static char *argv[] = { "linuxrc", NULL, };
 
diff -u --recursive --new-file v2.1.35/linux/kernel/exit.c linux/kernel/exit.c
--- v2.1.35/linux/kernel/exit.c	Sun Apr 13 10:18:22 1997
+++ linux/kernel/exit.c	Tue Apr 22 22:53:52 1997
@@ -41,18 +41,23 @@
 	 * be handled immediately (ie non-blocked and untraced)
 	 * and that is ignored (either explicitly or by default)
 	 */
+	spin_lock_irq(&p->sig->siglock);
 	if (!(mask & p->blocked) && !(p->flags & PF_PTRACED)) {
 		/* don't bother with ignored signals (but SIGCHLD is special) */
 		if (sa->sa_handler == SIG_IGN && sig != SIGCHLD)
-			return;
+			goto out;
 		/* some signals are ignored by default.. (but SIGCONT already did its deed) */
 		if ((sa->sa_handler == SIG_DFL) &&
 		    (sig == SIGCONT || sig == SIGCHLD || sig == SIGWINCH || sig == SIGURG))
-			return;
+			goto out;
 	}
+	spin_lock(&p->sigmask_lock);
 	p->signal |= mask;
+	spin_unlock(&p->sigmask_lock);
 	if (p->state == TASK_INTERRUPTIBLE && (p->signal & ~p->blocked))
 		wake_up_process(p);
+out:
+	spin_unlock_irq(&p->sig->siglock);
 }
 
 /*
@@ -65,16 +70,23 @@
 	if (p->sig) {
 		unsigned long mask = 1UL << sig;
 		struct sigaction *sa = p->sig->action + sig;
+
+		spin_lock_irq(&p->sig->siglock);
+
+		spin_lock(&p->sigmask_lock);
 		p->signal |= mask;
 		p->blocked &= ~mask;
+		spin_unlock(&p->sigmask_lock);
+
 		if (sa->sa_handler == SIG_IGN)
 			sa->sa_handler = SIG_DFL;
 		if (p->state == TASK_INTERRUPTIBLE)
 			wake_up_process(p);
+
+		spin_unlock_irq(&p->sig->siglock);
 	}
 }
 
-
 int send_sig(unsigned long sig,struct task_struct * p,int priv)
 {
 	if (!p || sig > 32)
@@ -84,24 +96,23 @@
 	    (current->uid ^ p->suid) && (current->uid ^ p->uid) &&
 	    !suser())
 		return -EPERM;
-	if (!sig)
-		return 0;
-	/*
-	 * Forget it if the process is already zombie'd.
-	 */
-	if (!p->sig)
-		return 0;
-	if ((sig == SIGKILL) || (sig == SIGCONT)) {
-		if (p->state == TASK_STOPPED)
-			wake_up_process(p);
-		p->exit_code = 0;
-		p->signal &= ~( (1<<(SIGSTOP-1)) | (1<<(SIGTSTP-1)) |
-				(1<<(SIGTTIN-1)) | (1<<(SIGTTOU-1)) );
-	}
-	if (sig == SIGSTOP || sig == SIGTSTP || sig == SIGTTIN || sig == SIGTTOU)
-		p->signal &= ~(1<<(SIGCONT-1));
-	/* Actually generate the signal */
-	generate(sig,p);
+
+	if (sig && p->sig) {
+		spin_lock_irq(&p->sigmask_lock);
+		if ((sig == SIGKILL) || (sig == SIGCONT)) {
+			if (p->state == TASK_STOPPED)
+				wake_up_process(p);
+			p->exit_code = 0;
+			p->signal &= ~( (1<<(SIGSTOP-1)) | (1<<(SIGTSTP-1)) |
+					(1<<(SIGTTIN-1)) | (1<<(SIGTTOU-1)) );
+		}
+		if (sig == SIGSTOP || sig == SIGTSTP || sig == SIGTTIN || sig == SIGTTOU)
+			p->signal &= ~(1<<(SIGCONT-1));
+		spin_unlock_irq(&p->sigmask_lock);
+
+		/* Actually generate the signal */
+		generate(sig,p);
+	}
 	return 0;
 }
 
@@ -125,6 +136,12 @@
 	}
 	for (i=1 ; i<NR_TASKS ; i++)
 		if (task[i] == p) {
+#ifdef __SMP__
+			/* FIXME! Cheesy, but kills the window... -DaveM */
+			while(p->processor != NO_PROC_ID)
+				barrier();
+			spin_unlock_wait(&scheduler_lock);
+#endif
 			nr_tasks--;
 			task[i] = NULL;
 			REMOVE_LINKS(p);
@@ -245,14 +262,18 @@
 	int fallback;
 
 	fallback = -1;
+	read_lock(&tasklist_lock);
 	for_each_task(p) {
  		if (p->session <= 0)
  			continue;
-		if (p->pgrp == pgrp)
-			return p->session;
+		if (p->pgrp == pgrp) {
+			fallback = p->session;
+			break;
+		}
 		if (p->pid == pgrp)
 			fallback = p->session;
 	}
+	read_unlock(&tasklist_lock);
 	return fallback;
 }
 
@@ -262,21 +283,29 @@
  */
 int kill_pg(int pgrp, int sig, int priv)
 {
-	struct task_struct *p;
-	int err,retval = -ESRCH;
-	int found = 0;
+	int retval;
 
-	if (sig<0 || sig>32 || pgrp<=0)
-		return -EINVAL;
-	for_each_task(p) {
-		if (p->pgrp == pgrp) {
-			if ((err = send_sig(sig,p,priv)) != 0)
-				retval = err;
-			else
-				found++;
+	retval = -EINVAL;
+	if (sig >= 0 && sig <= 32 && pgrp > 0) {
+		struct task_struct *p;
+		int found = 0;
+
+		retval = -ESRCH;
+		read_lock(&tasklist_lock);
+		for_each_task(p) {
+			if (p->pgrp == pgrp) {
+				int err = send_sig(sig,p,priv);
+				if (err != 0)
+					retval = err;
+				else
+					found++;
+			}
 		}
+		read_unlock(&tasklist_lock);
+		if (found)
+			retval = 0;
 	}
-	return(found ? 0 : retval);
+	return retval;
 }
 
 /*
@@ -286,34 +315,51 @@
  */
 int kill_sl(int sess, int sig, int priv)
 {
-	struct task_struct *p;
-	int err,retval = -ESRCH;
-	int found = 0;
+	int retval;
 
-	if (sig<0 || sig>32 || sess<=0)
-		return -EINVAL;
-	for_each_task(p) {
-		if (p->session == sess && p->leader) {
-			if ((err = send_sig(sig,p,priv)) != 0)
-				retval = err;
-			else
-				found++;
+	retval = -EINVAL;
+	if (sig >= 0 && sig <= 32 && sess > 0) {
+		struct task_struct *p;
+		int found = 0;
+
+		retval = -ESRCH;
+		read_lock(&tasklist_lock);
+		for_each_task(p) {
+			if (p->leader && p->session == sess) {
+				int err = send_sig(sig,p,priv);
+
+				if (err)
+					retval = err;
+				else
+					found++;
+			}
 		}
+		read_unlock(&tasklist_lock);
+		if (found)
+			retval = 0;
 	}
-	return(found ? 0 : retval);
+	return retval;
 }
 
 int kill_proc(int pid, int sig, int priv)
 {
- 	struct task_struct *p;
+	int retval;
 
-	if (sig<0 || sig>32)
-		return -EINVAL;
-	for_each_task(p) {
-		if (p && p->pid == pid)
-			return send_sig(sig,p,priv);
+	retval = -EINVAL;
+	if (sig >= 0 && sig <= 32) {
+		struct task_struct *p;
+		
+		retval = -ESRCH;
+		read_lock(&tasklist_lock);
+		for_each_task(p) {
+			if (p->pid != pid)
+				continue;
+			retval = send_sig(sig,p,priv);
+			break;
+		}
+		read_unlock(&tasklist_lock);
 	}
-	return(-ESRCH);
+	return retval;
 }
 
 /*
@@ -322,34 +368,30 @@
  */
 asmlinkage int sys_kill(int pid,int sig)
 {
-	int err, retval = 0, count = 0;
+	if (!pid)
+		return kill_pg(current->pgrp,sig,0);
 
-	lock_kernel();
-	if (!pid) {
-		err = kill_pg(current->pgrp,sig,0);
-		goto out;
-	}
 	if (pid == -1) {
+		int retval = 0, count = 0;
 		struct task_struct * p;
+
+		read_lock(&tasklist_lock);
 		for_each_task(p) {
 			if (p->pid > 1 && p != current) {
+				int err;
 				++count;
 				if ((err = send_sig(sig,p,0)) != -EPERM)
 					retval = err;
 			}
 		}
-		err = count ? retval : -ESRCH;
-		goto out;
-	}
-	if (pid < 0) {
-		err = kill_pg(-pid,sig,0);
-		goto out;
+		read_unlock(&tasklist_lock);
+		return count ? retval : -ESRCH;
 	}
+	if (pid < 0)
+		return kill_pg(-pid,sig,0);
+
 	/* Normal kill */
-	err = kill_proc(pid,sig,0);
-out:
-	unlock_kernel();
-	return err;
+	return kill_proc(pid,sig,0);
 }
 
 /*
@@ -364,16 +406,20 @@
 {
 	struct task_struct *p;
 
+	read_lock(&tasklist_lock);
 	for_each_task(p) {
 		if ((p == ignored_task) || (p->pgrp != pgrp) ||
 		    (p->state == TASK_ZOMBIE) ||
 		    (p->p_pptr->pid == 1))
 			continue;
 		if ((p->p_pptr->pgrp != pgrp) &&
-		    (p->p_pptr->session == p->session))
-			return 0;
+		    (p->p_pptr->session == p->session)) {
+			read_unlock(&tasklist_lock);
+ 			return 0;
+		}
 	}
-	return(1);	/* (sighing) "Often!" */
+	read_unlock(&tasklist_lock);
+	return 1;	/* (sighing) "Often!" */
 }
 
 int is_orphaned_pgrp(int pgrp)
@@ -383,21 +429,27 @@
 
 static inline int has_stopped_jobs(int pgrp)
 {
+	int retval = 0;
 	struct task_struct * p;
 
+	read_lock(&tasklist_lock);
 	for_each_task(p) {
 		if (p->pgrp != pgrp)
 			continue;
-		if (p->state == TASK_STOPPED)
-			return(1);
+		if (p->state != TASK_STOPPED)
+			continue;
+		retval = 1;
+		break;
 	}
-	return(0);
+	read_unlock(&tasklist_lock);
+	return retval;
 }
 
 static inline void forget_original_parent(struct task_struct * father)
 {
 	struct task_struct * p;
 
+	read_lock(&tasklist_lock);
 	for_each_task(p) {
 		if (p->p_opptr == father)
 			if (task[smp_num_cpus])	/* init */
@@ -405,6 +457,7 @@
 			else
 				p->p_opptr = task[0];
 	}
+	read_unlock(&tasklist_lock);
 }
 
 static inline void close_files(struct files_struct * files)
@@ -470,9 +523,8 @@
 
 	if (sig) {
 		tsk->sig = NULL;
-		if (!--sig->count) {
+		if (atomic_dec_and_test(&sig->count))
 			kfree(sig);
-		}
 	}
 }
 
@@ -635,24 +687,22 @@
 	struct wait_queue wait = { current, NULL };
 	struct task_struct *p;
 
-	lock_kernel();
 	if (stat_addr) {
-		retval = verify_area(VERIFY_WRITE, stat_addr, sizeof(*stat_addr));
-		if (retval)
-			goto out;
+		if(verify_area(VERIFY_WRITE, stat_addr, sizeof(*stat_addr)))
+			return -EFAULT;
 	}
 	if (ru) {
-		retval = verify_area(VERIFY_WRITE, ru, sizeof(*ru));
-		if (retval)
-			goto out;
+		if(verify_area(VERIFY_WRITE, ru, sizeof(*ru)))
+			return -EFAULT;
 	}
-	retval = -EINVAL;
+
 	if (options & ~(WNOHANG|WUNTRACED|__WCLONE))
-	    goto out;
+		return -EINVAL;
 
 	add_wait_queue(&current->wait_chldexit,&wait);
 repeat:
-	flag=0;
+	flag = 0;
+	read_lock(&tasklist_lock);
  	for (p = current->p_cptr ; p ; p = p->p_osptr) {
 		if (pid>0) {
 			if (p->pid != pid)
@@ -674,23 +724,28 @@
 					continue;
 				if (!(options & WUNTRACED) && !(p->flags & PF_PTRACED))
 					continue;
+				read_unlock(&tasklist_lock);
 				if (ru != NULL)
 					getrusage(p, RUSAGE_BOTH, ru);
 				if (stat_addr)
-					put_user((p->exit_code << 8) | 0x7f,
-						stat_addr);
+					__put_user((p->exit_code << 8) | 0x7f,
+						   stat_addr);
 				p->exit_code = 0;
 				retval = p->pid;
 				goto end_wait4;
 			case TASK_ZOMBIE:
 				current->cutime += p->utime + p->cutime;
 				current->cstime += p->stime + p->cstime;
+				read_unlock(&tasklist_lock);
 				if (ru != NULL)
 					getrusage(p, RUSAGE_BOTH, ru);
 				if (stat_addr)
-					put_user(p->exit_code, stat_addr);
+					__put_user(p->exit_code, stat_addr);
 				retval = p->pid;
 				if (p->p_opptr != p->p_pptr) {
+					/* Note this grabs tasklist_lock
+					 * as a writer... (twice!)
+					 */
 					REMOVE_LINKS(p);
 					p->p_pptr = p->p_opptr;
 					SET_LINKS(p);
@@ -705,6 +760,7 @@
 				continue;
 		}
 	}
+	read_unlock(&tasklist_lock);
 	if (flag) {
 		retval = 0;
 		if (options & WNOHANG)
@@ -719,8 +775,6 @@
 	retval = -ECHILD;
 end_wait4:
 	remove_wait_queue(&current->wait_chldexit,&wait);
-out:
-	unlock_kernel();
 	return retval;
 }
 
@@ -732,12 +786,7 @@
  */
 asmlinkage int sys_waitpid(pid_t pid,unsigned int * stat_addr, int options)
 {
-	int ret;
-
-	lock_kernel();
-	ret = sys_wait4(pid, stat_addr, options, NULL);
-	unlock_kernel();
-	return ret;
+	return sys_wait4(pid, stat_addr, options, NULL);
 }
 
 #endif
diff -u --recursive --new-file v2.1.35/linux/kernel/fork.c linux/kernel/fork.c
--- v2.1.35/linux/kernel/fork.c	Sun Apr 13 10:18:22 1997
+++ linux/kernel/fork.c	Tue Apr 22 22:53:52 1997
@@ -47,11 +47,15 @@
 		max_tasks--;	/* count the new process.. */
 		if (max_tasks < nr_tasks) {
 			struct task_struct *p;
+			read_lock(&tasklist_lock);
 			for_each_task (p) {
 				if (p->uid == current->uid)
-					if (--max_tasks < 0)
+					if (--max_tasks < 0) {
+						read_unlock(&tasklist_lock);
 						return -EAGAIN;
+					}
 			}
+			read_unlock(&tasklist_lock);
 		}
 	}
 	for (i = 0 ; i < NR_TASKS ; i++) {
@@ -67,6 +71,8 @@
 
 	if (flags & CLONE_PID)
 		return current->pid;
+
+	read_lock(&tasklist_lock);
 repeat:
 	if ((++last_pid) & 0xffff8000)
 		last_pid=1;
@@ -76,6 +82,8 @@
 		    p->session == last_pid)
 			goto repeat;
 	}
+	read_unlock(&tasklist_lock);
+
 	return last_pid;
 }
 
@@ -203,13 +211,14 @@
 static inline int copy_sighand(unsigned long clone_flags, struct task_struct * tsk)
 {
 	if (clone_flags & CLONE_SIGHAND) {
-		current->sig->count++;
+		atomic_inc(&current->sig->count);
 		return 0;
 	}
 	tsk->sig = kmalloc(sizeof(*tsk->sig), GFP_KERNEL);
 	if (!tsk->sig)
 		return -1;
-	tsk->sig->count = 1;
+	spin_lock_init(&tsk->sig->siglock);
+	atomic_set(&tsk->sig->count, 1);
 	memcpy(tsk->sig->action, current->sig->action, sizeof(tsk->sig->action));
 	return 0;
 }
diff -u --recursive --new-file v2.1.35/linux/kernel/info.c linux/kernel/info.c
--- v2.1.35/linux/kernel/info.c	Fri Apr  4 08:52:26 1997
+++ linux/kernel/info.c	Tue Apr 22 22:53:52 1997
@@ -23,7 +23,7 @@
 
 	memset((char *)&val, 0, sizeof(struct sysinfo));
 
-	lock_kernel();
+	cli();
 	val.uptime = jiffies / HZ;
 
 	val.loads[0] = avenrun[0] << (SI_LOAD_SHIFT - FSHIFT);
@@ -31,10 +31,10 @@
 	val.loads[2] = avenrun[2] << (SI_LOAD_SHIFT - FSHIFT);
 
 	val.procs = nr_tasks-1;
+	sti();
 
 	si_meminfo(&val);
 	si_swapinfo(&val);
-	unlock_kernel();
 
 	if (copy_to_user(info, &val, sizeof(struct sysinfo)))
 		return -EFAULT;
diff -u --recursive --new-file v2.1.35/linux/kernel/itimer.c linux/kernel/itimer.c
--- v2.1.35/linux/kernel/itimer.c	Sun Jan 26 02:07:49 1997
+++ linux/kernel/itimer.c	Tue Apr 22 22:53:52 1997
@@ -43,7 +43,6 @@
 {
 	value->tv_usec = (jiffies % HZ) * (1000000 / HZ);
 	value->tv_sec = jiffies / HZ;
-	return;
 }
 
 static int _getitimer(int which, struct itimerval *value)
@@ -80,20 +79,18 @@
 	return 0;
 }
 
+/* SMP: Only we modify our itimer values. */
 asmlinkage int sys_getitimer(int which, struct itimerval *value)
 {
 	int error = -EFAULT;
 	struct itimerval get_buffer;
 
-	lock_kernel();
-	if (!value)
-		goto out;
-	error = _getitimer(which, &get_buffer);
-	if (error)
-		goto out;
-	error = copy_to_user(value, &get_buffer, sizeof(get_buffer)) ? -EFAULT : 0;
-out:
-	unlock_kernel();
+	if (value) {
+		error = _getitimer(which, &get_buffer);
+		if (!error)
+			error =	copy_to_user(value, &get_buffer, sizeof(get_buffer))
+				? -EFAULT : 0;
+	}
 	return error;
 }
 
@@ -155,31 +152,27 @@
 	return 0;
 }
 
+/* SMP: Again, only we play with our itimers, and signals are SMP safe
+ *      now so that is not an issue at all anymore.
+ */
 asmlinkage int sys_setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
 {
-	int error;
 	struct itimerval set_buffer, get_buffer;
+	int error;
 
-	lock_kernel();
 	if (value) {
-		error = verify_area(VERIFY_READ, value, sizeof(*value));
-		if (error)
-			goto out;
-		error = copy_from_user(&set_buffer, value, sizeof(set_buffer));
-		if (error) {
-			error = -EFAULT;
-			goto out;
-		}
+		if(verify_area(VERIFY_READ, value, sizeof(*value)))
+			return -EFAULT;
+		if(copy_from_user(&set_buffer, value, sizeof(set_buffer)))
+			return -EFAULT;
 	} else
 		memset((char *) &set_buffer, 0, sizeof(set_buffer));
 
 	error = _setitimer(which, &set_buffer, ovalue ? &get_buffer : 0);
 	if (error || !ovalue)
-		goto out;
+		return error;
 
 	if (copy_to_user(ovalue, &get_buffer, sizeof(get_buffer)))
-		error = -EFAULT; 
-out:
-	unlock_kernel();
-	return error;
+		return -EFAULT; 
+	return 0;
 }
diff -u --recursive --new-file v2.1.35/linux/kernel/ksyms.c linux/kernel/ksyms.c
--- v2.1.35/linux/kernel/ksyms.c	Mon Apr 14 16:28:26 1997
+++ linux/kernel/ksyms.c	Tue Apr 22 22:49:38 1997
@@ -20,6 +20,7 @@
 #include <linux/kernel_stat.h>
 #include <linux/mm.h>
 #include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/ptrace.h>
 #include <linux/sys.h>
@@ -76,6 +77,9 @@
 extern void set_device_ro(int dev,int flag);
 extern struct file_operations * get_blkfops(unsigned int);
 extern int blkdev_release(struct inode * inode);
+#if !defined(CONFIG_NFSD) && defined(CONFIG_NFSD_MODULE)
+extern int (*do_nfsservctl)(int, void *, void *);
+#endif
 
 extern void *sys_call_table;
 
@@ -130,6 +134,10 @@
 EXPORT_SYMBOL(num_physpages);
 EXPORT_SYMBOL(high_memory);
 EXPORT_SYMBOL(update_vm_cache);
+EXPORT_SYMBOL(kmem_cache_create);
+EXPORT_SYMBOL(kmem_cache_destroy);
+EXPORT_SYMBOL(kmem_cache_alloc);
+EXPORT_SYMBOL(kmem_cache_free);
 
 /* filesystem internal functions */
 EXPORT_SYMBOL(getname);
@@ -174,6 +182,10 @@
 EXPORT_SYMBOL(posix_block_lock);
 EXPORT_SYMBOL(posix_unblock_lock);
 
+#if !defined(CONFIG_NFSD) && defined(CONFIG_NFSD_MODULE)
+EXPORT_SYMBOL(do_nfsservctl);
+#endif
+
 /* device registration */
 EXPORT_SYMBOL(register_chrdev);
 EXPORT_SYMBOL(unregister_chrdev);
@@ -258,7 +270,10 @@
 EXPORT_SYMBOL(tq_scheduler);
 EXPORT_SYMBOL(timer_active);
 EXPORT_SYMBOL(timer_table);
+
 #ifdef __SMP__
+/* Various random spinlocks we want to export */
+EXPORT_SYMBOL(tqueue_lock);
 EXPORT_SYMBOL(waitqueue_lock);
 #endif
 
diff -u --recursive --new-file v2.1.35/linux/kernel/sched.c linux/kernel/sched.c
--- v2.1.35/linux/kernel/sched.c	Wed Apr 16 14:15:00 1997
+++ linux/kernel/sched.c	Tue Apr 22 22:55:30 1997
@@ -126,22 +126,6 @@
 	(p->prev_run = init_task.prev_run)->next_run = p;
 	p->next_run = &init_task;
 	init_task.prev_run = p;
-#if 0 /* def __SMP__ */
-	/* this is safe only if called with cli()*/
-	inc_smp_counter(&smp_process_available);
-	if ((0!=p->pid) && smp_threads_ready)
-	{
-		int i;
-		for (i=0;i<smp_num_cpus;i++)
-		{
-			if (0==current_set[cpu_logical_map[i]]->pid) 
-			{
-				smp_message_pass(cpu_logical_map[i], MSG_RESCHEDULE, 0L, 0);
-				break;
-			}
-		}
-	}
-#endif
 }
 
 static inline void del_from_runqueue(struct task_struct * p)
@@ -187,9 +171,7 @@
 }
 
 /*
- * The tasklist_lock protects the linked list of processes
- * and doesn't need to be interrupt-safe as interrupts never
- * use the task-list.
+ * The tasklist_lock protects the linked list of processes.
  *
  * The scheduler lock is protecting against multiple entry
  * into the scheduling code, and doesn't need to worry
@@ -199,7 +181,7 @@
  * The run-queue lock locks the parts that actually access
  * and change the run-queues, and have to be interrupt-safe.
  */
-spinlock_t tasklist_lock = SPIN_LOCK_UNLOCKED;
+rwlock_t tasklist_lock = RW_LOCK_UNLOCKED;
 spinlock_t scheduler_lock = SPIN_LOCK_UNLOCKED;
 static spinlock_t runqueue_lock = SPIN_LOCK_UNLOCKED;
 
@@ -391,10 +373,10 @@
 			/* Do we need to re-calculate counters? */
 			if (!c) {
 				struct task_struct *p;
-				spin_lock(&tasklist_lock);
+				read_lock(&tasklist_lock);
 				for_each_task(p)
 					p->counter = (p->counter >> 1) + p->priority;
-				spin_unlock(&tasklist_lock);
+				read_unlock(&tasklist_lock);
 			}
 		}
 	}
@@ -421,7 +403,7 @@
 	}
 	spin_unlock(&scheduler_lock);
 
-	reaquire_kernel_lock(prev, smp_processor_id(), lock_depth);
+	reacquire_kernel_lock(prev, smp_processor_id(), lock_depth);
 }
 
 #ifndef __alpha__
@@ -432,10 +414,8 @@
  */
 asmlinkage int sys_pause(void)
 {
-	lock_kernel();
 	current->state = TASK_INTERRUPTIBLE;
 	schedule();
-	unlock_kernel();
 	return -ERESTARTNOHAND;
 }
 
@@ -1208,7 +1188,6 @@
 	struct itimerval it_new, it_old;
 	unsigned int oldalarm;
 
-	lock_kernel();
 	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;
@@ -1218,7 +1197,6 @@
 	/* And we'd better return too much than too little anyway */
 	if (it_old.it_value.tv_usec)
 		oldalarm++;
-	unlock_kernel();
 	return oldalarm;
 }
 
@@ -1366,13 +1344,15 @@
 
 	p = current;
 	if (pid) {
+		read_lock(&tasklist_lock);
 		for_each_task(p) {
 			if (p->pid == pid)
 				goto found;
 		}
 		p = NULL;
-	}
 found:
+		read_unlock(&tasklist_lock);
+	}
 	return p;
 }
 
@@ -1428,64 +1408,42 @@
 asmlinkage int sys_sched_setscheduler(pid_t pid, int policy, 
 				      struct sched_param *param)
 {
-	int ret;
-
-	lock_kernel();
-	ret = setscheduler(pid, policy, param);
-	unlock_kernel();
-	return ret;
+	return setscheduler(pid, policy, param);
 }
 
 asmlinkage int sys_sched_setparam(pid_t pid, struct sched_param *param)
 {
-	int ret;
-
-	lock_kernel();
-	ret = setscheduler(pid, -1, param);
-	unlock_kernel();
-	return ret;
+	return setscheduler(pid, -1, param);
 }
 
 asmlinkage int sys_sched_getscheduler(pid_t pid)
 {
 	struct task_struct *p;
-	int ret = -EINVAL;
 
-	lock_kernel();
 	if (pid < 0)
-		goto out;
+		return -EINVAL;
 
 	p = find_process_by_pid(pid);
-	ret = -ESRCH;
 	if (!p)
-		goto out;
+		return -ESRCH;
 			
-	ret = p->policy;
-out:
-	unlock_kernel();
-	return ret;
+	return p->policy;
 }
 
 asmlinkage int sys_sched_getparam(pid_t pid, struct sched_param *param)
 {
 	struct task_struct *p;
 	struct sched_param lp;
-	int ret = -EINVAL;
 
-	lock_kernel();
 	if (!param || pid < 0)
-		goto out;
+		return -EINVAL;
 
 	p = find_process_by_pid(pid);
-	ret = -ESRCH;
 	if (!p)
-		goto out;
+		return -ESRCH;
 
 	lp.sched_priority = p->rt_priority;
-	ret = copy_to_user(param, &lp, sizeof(struct sched_param)) ? -EFAULT : 0;
-out:
-	unlock_kernel();
-	return ret;
+	return copy_to_user(param, &lp, sizeof(struct sched_param)) ? -EFAULT : 0;
 }
 
 asmlinkage int sys_sched_yield(void)
@@ -1561,7 +1519,6 @@
 {
 	value->tv_nsec = (jiffies % HZ) * (1000000000L / HZ);
 	value->tv_sec = jiffies / HZ;
-	return;
 }
 
 asmlinkage int sys_nanosleep(struct timespec *rqtp, struct timespec *rmtp)
@@ -1590,11 +1547,10 @@
 	}
 
 	expire = timespectojiffies(&t) + (t.tv_sec || t.tv_nsec) + jiffies;
-	lock_kernel();
+
 	current->timeout = expire;
 	current->state = TASK_INTERRUPTIBLE;
 	schedule();
-	unlock_kernel();
 
 	if (expire > jiffies) {
 		if (rmtp) {
diff -u --recursive --new-file v2.1.35/linux/kernel/signal.c linux/kernel/signal.c
--- v2.1.35/linux/kernel/signal.c	Thu Mar 27 14:40:12 1997
+++ linux/kernel/signal.c	Tue Apr 22 22:53:52 1997
@@ -31,6 +31,9 @@
  * We don't need to get the kernel lock - this is all local to this
  * particular thread.. (and that's good, because this is _heavily_
  * used by various programs)
+ *
+ * No SMP locking would prevent the inherent races present in this
+ * routine, thus we do not perform any locking at all.
  */
 asmlinkage int sys_sigprocmask(int how, sigset_t *set, sigset_t *oset)
 {
@@ -38,9 +41,10 @@
 
 	if (set) {
 		sigset_t new_set;
-		int error = get_user(new_set, set);
-		if (error)
-			return error;
+
+		if(get_user(new_set, set))
+			return -EFAULT;
+
 		new_set &= _BLOCKABLE;
 		switch (how) {
 		default:
@@ -57,9 +61,8 @@
 		current->blocked = new_set;
 	}
 	if (oset) {
-		int error = put_user(old_set, oset);
-		if (error)
-			return error;
+		if(put_user(old_set, oset))
+			return -EFAULT;
 	}
 	return 0;
 }
@@ -69,21 +72,19 @@
  */
 asmlinkage int sys_sgetmask(void)
 {
-	int ret;
-
 	/* SMP safe */
-	ret = current->blocked;
-	return ret;
+	return current->blocked;
 }
 
 asmlinkage int sys_ssetmask(int newmask)
 {
 	int old;
 
-	lock_kernel();
+	spin_lock_irq(&current->sigmask_lock);
 	old = current->blocked;
 	current->blocked = newmask & _BLOCKABLE;
-	unlock_kernel();
+	spin_unlock_irq(&current->sigmask_lock);
+
 	return old;
 }
 
@@ -94,9 +95,9 @@
 	int ret;
 
 	/* fill in "set" with signals pending but blocked. */
-	lock_kernel();
+	spin_lock_irq(&current->sigmask_lock);
 	ret = put_user(current->blocked & current->signal, set);
-	unlock_kernel();
+	spin_unlock_irq(&current->sigmask_lock);
 	return ret;
 }
 
@@ -114,22 +115,24 @@
  * Note the silly behaviour of SIGCHLD: SIG_IGN means that the signal
  * isn't actually ignored, but does automatic child reaping, while
  * SIG_DFL is explicitly said by POSIX to force the signal to be ignored..
+ *
+ * All callers of check_pending must be holding current->sig->siglock.
  */
 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);
-		return;
-	}
-	if (p->sa_handler == SIG_DFL) {
-		if (signum != SIGCONT && signum != SIGCHLD && signum != SIGWINCH)
-			return;
-		current->signal &= ~_S(signum);
-		return;
+	} else if (p->sa_handler == SIG_DFL) {
+		if (signum == SIGCONT ||
+		    signum == SIGCHLD ||
+		    signum != SIGWINCH)
+			current->signal &= ~_S(signum);
 	}	
+	spin_unlock(&current->sigmask_lock);
 }
 
 #ifndef __alpha__
@@ -138,30 +141,28 @@
  */
 asmlinkage unsigned long sys_signal(int signum, __sighandler_t handler)
 {
-	unsigned long err;
 	struct sigaction tmp;
 
-	lock_kernel();
-	err = -EINVAL;
 	if (signum<1 || signum>32)
-		goto out;
+		return -EINVAL;
 	if (signum==SIGKILL || signum==SIGSTOP)
-		goto out;
+		return -EINVAL;
 	if (handler != SIG_DFL && handler != SIG_IGN) {
-		err = verify_area(VERIFY_READ, handler, 1);
-		if (err)
-			goto out;
+		if(verify_area(VERIFY_READ, handler, 1))
+			return -EFAULT;
 	}
+
 	memset(&tmp, 0, sizeof(tmp));
 	tmp.sa_handler = handler;
 	tmp.sa_flags = SA_ONESHOT | SA_NOMASK;
+
+	spin_lock_irq(&current->sig->siglock);
 	handler = current->sig->action[signum-1].sa_handler;
 	current->sig->action[signum-1] = tmp;
 	check_pending(signum);
-	err = (unsigned long) handler;
-out:
-	unlock_kernel();
-	return err;
+	spin_unlock_irq(&current->sig->siglock);
+
+	return (unsigned long) handler;
 }
 #endif
 
@@ -171,22 +172,33 @@
 {
 	struct sigaction new_sa, *p;
 
-	if (signum<1 || signum>32)
+	if (signum < 1 || signum > 32)
 		return -EINVAL;
+
 	p = signum - 1 + current->sig->action;
+
 	if (action) {
 		if (copy_from_user(&new_sa, action, sizeof(struct sigaction)))
 			return -EFAULT;
 		if (signum==SIGKILL || signum==SIGSTOP)
 			return -EINVAL;
 	}
+
 	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.
+		 */
 		if (copy_to_user(oldaction, p, sizeof(struct sigaction)))
 			return -EFAULT;
 	}
+
 	if (action) {
+		spin_lock_irq(&current->sig->siglock);
 		*p = new_sa;
 		check_pending(signum);
+		spin_unlock_irq(&current->sig->siglock);
 	}
 	return 0;
 }
diff -u --recursive --new-file v2.1.35/linux/kernel/sys.c linux/kernel/sys.c
--- v2.1.35/linux/kernel/sys.c	Sun Apr 13 10:18:22 1997
+++ linux/kernel/sys.c	Tue Apr 22 22:53:52 1997
@@ -87,12 +87,11 @@
 asmlinkage int sys_setpriority(int which, int who, int niceval)
 {
 	struct task_struct *p;
-	int error = EINVAL;
 	unsigned int priority;
+	int error;
 
-	lock_kernel();
 	if (which > 2 || which < 0)
-		goto out;
+		return -EINVAL;
 
 	/* normalize: avoid signed division (rounding problems) */
 	error = ESRCH;
@@ -109,6 +108,7 @@
 			priority = 1;
 	}
 
+	read_lock(&tasklist_lock);
 	for_each_task(p) {
 		if (!proc_sel(p, which, who))
 			continue;
@@ -124,8 +124,8 @@
 		else
 			p->priority = priority;
 	}
-out:
-	unlock_kernel();
+	read_unlock(&tasklist_lock);
+
 	return -error;
 }
 
@@ -138,26 +138,23 @@
 {
 	struct task_struct *p;
 	long max_prio = -ESRCH;
-	int ret = -EINVAL;
 
-	lock_kernel();
 	if (which > 2 || which < 0)
-		goto out;
+		return -EINVAL;
 
+	read_lock(&tasklist_lock);
 	for_each_task (p) {
 		if (!proc_sel(p, which, who))
 			continue;
 		if (p->priority > max_prio)
 			max_prio = p->priority;
 	}
+	read_unlock(&tasklist_lock);
 
 	/* scale the priority from timeslice to 0..40 */
 	if (max_prio > 0)
 		max_prio = (max_prio * 20 + DEF_PRIORITY/2) / DEF_PRIORITY;
-	ret = max_prio;
-out:
-	unlock_kernel();
-	return ret;
+	return max_prio;
 }
 
 #ifndef __alpha__
@@ -304,21 +301,22 @@
  * The general idea is that a program which uses just setregid() will be
  * 100% compatible with BSD.  A program which uses just setgid() will be
  * 100% compatible with POSIX w/ Saved ID's. 
+ *
+ * SMP: There are not races, the gid's are checked only by filesystem
+ *      operations (as far as semantic preservation is concerned).
  */
 asmlinkage int sys_setregid(gid_t rgid, gid_t egid)
 {
 	int old_rgid = current->gid;
 	int old_egid = current->egid;
-	int err = -EPERM;
 
-	lock_kernel();
 	if (rgid != (gid_t) -1) {
 		if ((old_rgid == rgid) ||
 		    (current->egid==rgid) ||
 		    suser())
 			current->gid = rgid;
 		else
-			goto out;
+			return -EPERM;
 	}
 	if (egid != (gid_t) -1) {
 		if ((old_rgid == egid) ||
@@ -328,7 +326,7 @@
 			current->fsgid = current->egid = egid;
 		else {
 			current->gid = old_rgid;
-			goto out;
+			return -EPERM;
 		}
 	}
 	if (rgid != (gid_t) -1 ||
@@ -337,33 +335,28 @@
 	current->fsgid = current->egid;
 	if (current->egid != old_egid)
 		current->dumpable = 0;
-	err = 0;
-out:
-	unlock_kernel();
-	return err;
+	return 0;
 }
 
 /*
  * setgid() is implemented like SysV w/ SAVED_IDS 
+ *
+ * SMP: Same implicit races as above.
  */
 asmlinkage int sys_setgid(gid_t gid)
 {
 	int old_egid = current->egid;
-	int err = -EPERM;
 
-	lock_kernel();
 	if (suser())
 		current->gid = current->egid = current->sgid = current->fsgid = gid;
 	else if ((gid == current->gid) || (gid == current->sgid))
 		current->egid = current->fsgid = gid;
 	else
-		goto out;
-	err = 0;
+		return -EPERM;
+
 	if (current->egid != old_egid)
 		current->dumpable = 0;
-out:
-	unlock_kernel();
-	return err;
+	return 0;
 }
   
 static char acct_active = 0;
@@ -532,9 +525,7 @@
 {
 	int old_ruid;
 	int old_euid;
-	int err = -EPERM;
 
-	lock_kernel();
 	old_ruid = current->uid;
 	old_euid = current->euid;
 	if (ruid != (uid_t) -1) {
@@ -543,7 +534,7 @@
 		    suser())
 			current->uid = ruid;
 		else
-			goto out;
+			return -EPERM;
 	}
 	if (euid != (uid_t) -1) {
 		if ((old_ruid == euid) ||
@@ -553,7 +544,7 @@
 			current->fsuid = current->euid = euid;
 		else {
 			current->uid = old_ruid;
-			goto out;
+			return -EPERM;
 		}
 	}
 	if (ruid != (uid_t) -1 ||
@@ -562,10 +553,7 @@
 	current->fsuid = current->euid;
 	if (current->euid != old_euid)
 		current->dumpable = 0;
-	err = 0;
-out:
-	unlock_kernel();
-	return err;
+	return 0;
 }
 
 /*
@@ -582,22 +570,17 @@
 asmlinkage int sys_setuid(uid_t uid)
 {
 	int old_euid = current->euid;
-	int retval = 0;
 
-	lock_kernel();
 	if (suser())
 		current->uid = current->euid = current->suid = current->fsuid = uid;
 	else if ((uid == current->uid) || (uid == current->suid))
 		current->fsuid = current->euid = uid;
-	else {
-		retval = -EPERM;
-		goto out;
-	}
+	else
+		return -EPERM;
+
 	if (current->euid != old_euid)
 		current->dumpable = 0;
-out:
-	unlock_kernel();
-	return retval;
+	return 0;
 }
 
 
@@ -608,43 +591,37 @@
 asmlinkage int sys_setresuid(uid_t ruid, uid_t euid, uid_t suid)
 {
 	uid_t old_ruid, old_euid, old_suid;
-	int err = -EPERM;
 
-	lock_kernel();
 	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))
-		goto out;
+		return -EPERM;
 	if ((euid != (uid_t) -1) && (euid != current->uid) &&
 	    (euid != current->euid) && (euid != current->suid))
-		goto out;
+		return -EPERM;
 	if ((suid != (uid_t) -1) && (suid != current->uid) &&
 	    (suid != current->euid) && (suid != current->suid))
-		goto out;
+		return -EPERM;
 	if (ruid != (uid_t) -1)
 		current->uid = ruid;
 	if (euid != (uid_t) -1)
 		current->euid = euid;
 	if (suid != (uid_t) -1)
 		current->suid = suid;
-	err = 0;
-out:
-	unlock_kernel();
-	return err;
+	return 0;
 }
 
 asmlinkage int sys_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid)
 {
 	int retval;
 
-	lock_kernel();
 	if (!(retval = put_user(current->uid, ruid)) &&
 	    !(retval = put_user(current->euid, euid)))
 		retval = put_user(current->suid, suid);
-	unlock_kernel();
+
 	return retval;
 }
 
@@ -659,14 +636,13 @@
 {
 	int old_fsuid;
 
-	lock_kernel();
 	old_fsuid = current->fsuid;
 	if (uid == current->uid || uid == current->euid ||
 	    uid == current->suid || uid == current->fsuid || suser())
 		current->fsuid = uid;
 	if (current->fsuid != old_fsuid)
 		current->dumpable = 0;
-	unlock_kernel();
+
 	return old_fsuid;
 }
 
@@ -677,14 +653,13 @@
 {
 	int old_fsgid;
 
-	lock_kernel();
 	old_fsgid = current->fsgid;
 	if (gid == current->gid || gid == current->egid ||
 	    gid == current->sgid || gid == current->fsgid || suser())
 		current->fsgid = gid;
 	if (current->fsgid != old_fsgid)
 		current->dumpable = 0;
-	unlock_kernel();
+
 	return old_fsgid;
 }
 
@@ -727,21 +702,29 @@
 	struct task_struct * p;
 	int err = -EINVAL;
 
-	lock_kernel();
 	if (!pid)
 		pid = current->pid;
 	if (!pgid)
 		pgid = pid;
 	if (pgid < 0)
-		goto out;
+		return -EINVAL;
+
+	read_lock(&tasklist_lock);
 	for_each_task(p) {
-		if (p->pid == pid)
+		if (p->pid == pid) {
+			/* NOTE: I haven't dropped tasklist_lock, this is
+			 *       on purpose. -DaveM
+			 */
 			goto found_task;
+		}
 	}
-	err = -ESRCH;
-	goto out;
+	read_unlock(&tasklist_lock);
+	return -ESRCH;
 
 found_task:
+	/* From this point forward we keep holding onto the tasklist lock
+	 * so that our parent does not change from under us. -DaveM
+	 */
 	err = -ESRCH;
 	if (p->p_pptr == current || p->p_opptr == current) {
 		err = -EPERM;
@@ -769,30 +752,29 @@
 	p->pgrp = pgid;
 	err = 0;
 out:
-	unlock_kernel();
+	/* All paths lead to here, thus we are safe. -DaveM */
+	read_unlock(&tasklist_lock);
 	return err;
 }
 
 asmlinkage int sys_getpgid(pid_t pid)
 {
-	struct task_struct * p;
-	int ret;
-
-	lock_kernel();
 	if (!pid) {
-		ret = current->pgrp;
+		return current->pgrp;
 	} else {
+		struct task_struct *p;
+		int ret = -ESRCH;
+
+		read_lock(&tasklist_lock);
 		for_each_task(p) {
 			if (p->pid == pid) {
 				ret = p->pgrp;
-				goto out;
+				break;
 			}
 		}
-		ret = -ESRCH;
+		read_unlock(&tasklist_lock);
+		return ret;
 	}
-out:
-	unlock_kernel();
-	return ret;
 }
 
 asmlinkage int sys_getpgrp(void)
@@ -810,17 +792,16 @@
 	if (!pid) {
 		ret = current->session;
 	} else {
-		/* Walking the process table needs locks */
-		lock_kernel();
+		ret = -ESRCH;
+
+		read_lock(&tasklist_lock);
 		for_each_task(p) {
 			if (p->pid == pid) {
 				ret = p->session;
-				goto out;
+				break;
 			}
 		}
-		ret = -ESRCH;
-out:
-		unlock_kernel();
+		read_unlock(&tasklist_lock);
 	}
 	return ret;
 }
@@ -830,7 +811,7 @@
 	struct task_struct * p;
 	int err = -EPERM;
 
-	lock_kernel();
+	read_lock(&tasklist_lock);
 	for_each_task(p) {
 		if (p->pgrp == current->pid)
 		        goto out;
@@ -842,7 +823,7 @@
 	current->tty_old_pgrp = 0;
 	err = current->pgrp;
 out:
-	unlock_kernel();
+	read_unlock(&tasklist_lock);
 	return err;
 }
 
@@ -908,17 +889,11 @@
 
 asmlinkage int sys_newuname(struct new_utsname * name)
 {
-	int err = -EFAULT;
-
-	lock_kernel();
 	if (!name)
-		goto out;
+		return -EFAULT;
 	if (copy_to_user(name,&system_utsname,sizeof *name))
-		goto out;
-	err = 0;
-out:
-	unlock_kernel();
-	return err;
+		return -EFAULT;
+	return 0;
 }
 
 #ifndef __alpha__
@@ -927,26 +902,24 @@
  * Move these to arch dependent dir since they are for
  * backward compatibility only?
  */
+
+#ifndef __sparc__
 asmlinkage int sys_uname(struct old_utsname * name)
 {
-	int error = -EFAULT;
-
-	lock_kernel();
 	if (name && !copy_to_user(name, &system_utsname, sizeof (*name)))
-		error = 0;
-	unlock_kernel();
-	return error;
+		return 0;
+	return -EFAULT;
 }
+#endif
 
 asmlinkage int sys_olduname(struct oldold_utsname * name)
 {
-	int error = -EFAULT;
+	int error;
 
-	lock_kernel();
 	if (!name)
-		goto out;
+		return -EFAULT;
 	if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname)))
-		goto out;
+		return -EFAULT;
   
 	error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN);
 	error -= __put_user(0,name->sysname+__OLD_UTS_LEN);
@@ -959,8 +932,7 @@
 	error -= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN);
 	error = __put_user(0,name->machine+__OLD_UTS_LEN);
 	error = error ? -EFAULT : 0;
-out:
-	unlock_kernel();
+
 	return error;
 }
 
@@ -968,39 +940,26 @@
 
 asmlinkage int sys_sethostname(char *name, int len)
 {
-	int error = -EPERM;
-
-	lock_kernel();
 	if (!suser())
-		goto out;
-	error = -EINVAL;
+		return -EPERM;
 	if (len < 0 || len > __NEW_UTS_LEN)
-		goto out;
-	error = copy_from_user(system_utsname.nodename, name, len);
-	if (error) {
-		error = -EFAULT;
-		goto out;
-	}
+		return -EINVAL;
+	if(copy_from_user(system_utsname.nodename, name, len))
+		return -EFAULT;
 	system_utsname.nodename[len] = 0;
-out:
-	unlock_kernel();
-	return error;
+	return 0;
 }
 
 asmlinkage int sys_gethostname(char *name, int len)
 {
-	int i, err = -EINVAL;
+	int i;
 
-	lock_kernel();
 	if (len < 0)
-		goto out;
-	i = 1+strlen(system_utsname.nodename);
+		return -EINVAL;
+	i = 1 + strlen(system_utsname.nodename);
 	if (i > len)
 		i = len;
-	err = copy_to_user(name, system_utsname.nodename, i) ? -EFAULT : 0;
-out:
-	unlock_kernel();
-	return err;
+	return copy_to_user(name, system_utsname.nodename, i) ? -EFAULT : 0;
 }
 
 /*
@@ -1009,66 +968,44 @@
  */
 asmlinkage int sys_setdomainname(char *name, int len)
 {
-	int error = -EPERM;
-	
-	lock_kernel();
 	if (!suser())
-		goto out;
-	error = -EINVAL;
+		return -EPERM;
 	if (len < 0 || len > __NEW_UTS_LEN)
-		goto out;
-	error = copy_from_user(system_utsname.domainname, name, len);
-	if (error)
-		error = -EFAULT;
-	else
-		system_utsname.domainname[len] = 0;
-out:
-	unlock_kernel();
-	return error;
+		return -EINVAL;
+	if(copy_from_user(system_utsname.domainname, name, len))
+		return -EFAULT;
+	system_utsname.domainname[len] = 0;
+	return 0;
 }
 
 asmlinkage int sys_getrlimit(unsigned int resource, struct rlimit *rlim)
 {
-	int error;
-
-	lock_kernel();
 	if (resource >= RLIM_NLIMITS)
-		error = -EINVAL;
+		return -EINVAL;
 	else
-		error = copy_to_user(rlim, current->rlim + resource, sizeof(*rlim))
+		return copy_to_user(rlim, current->rlim + resource, sizeof(*rlim))
 			? -EFAULT : 0;
-	unlock_kernel();
-	return error;
 }
 
 asmlinkage int sys_setrlimit(unsigned int resource, struct rlimit *rlim)
 {
 	struct rlimit new_rlim, *old_rlim;
-	int err = -EINVAL;
 
-	lock_kernel();
 	if (resource >= RLIM_NLIMITS)
-		goto out;
-	err = copy_from_user(&new_rlim, rlim, sizeof(*rlim));
-	if (err) {
-		err = -EFAULT;
-		goto out;
-	}
+		return -EINVAL;
+	if(copy_from_user(&new_rlim, rlim, sizeof(*rlim)))
+		return -EFAULT;
 	old_rlim = current->rlim + resource;
-	err = -EPERM;
 	if (((new_rlim.rlim_cur > old_rlim->rlim_max) ||
 	     (new_rlim.rlim_max > old_rlim->rlim_max)) &&
 	    !suser())
-		goto out;
+		return -EPERM;
 	if (resource == RLIMIT_NOFILE) {
 		if (new_rlim.rlim_cur > NR_OPEN || new_rlim.rlim_max > NR_OPEN)
-			goto out;
+			return -EPERM;
 	}
 	*old_rlim = new_rlim;
-	err = 0;
-out:
-	unlock_kernel();
-	return err;
+	return 0;
 }
 
 /*
@@ -1078,13 +1015,18 @@
  * make sense to do this.  It will make moving the rest of the information
  * a lot simpler!  (Which we're not doing right now because we're not
  * measuring them yet).
+ *
+ * This is SMP safe.  Either we are called from sys_getrusage on ourselves
+ * below (we know we aren't going to exit/disappear and only we change our
+ * rusage counters), or we are called from wait4() on a process which is
+ * either stopped or zombied.  In the zombied case the task won't get
+ * reaped till shortly after the call to getrusage(), in both cases the
+ * task being examined is in a frozen state so the counters won't change.
  */
 int getrusage(struct task_struct *p, int who, struct rusage *ru)
 {
 	struct rusage r;
-	int err;
 
-	lock_kernel();
 	memset((char *) &r, 0, sizeof(r));
 	switch (who) {
 		case RUSAGE_SELF:
@@ -1115,22 +1057,14 @@
 			r.ru_nswap = p->nswap + p->cnswap;
 			break;
 	}
-	err = copy_to_user(ru, &r, sizeof(r)) ? -EFAULT : 0;
-	unlock_kernel();
-	return err;
+	return copy_to_user(ru, &r, sizeof(r)) ? -EFAULT : 0;
 }
 
 asmlinkage int sys_getrusage(int who, struct rusage *ru)
 {
-	int err = -EINVAL;
-
-	lock_kernel();
 	if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN)
-		goto out;
-	err = getrusage(current, who, ru);
-out:
-	unlock_kernel();
-	return err;
+		return -EINVAL;
+	return getrusage(current, who, ru);
 }
 
 asmlinkage int sys_umask(int mask)
diff -u --recursive --new-file v2.1.35/linux/kernel/time.c linux/kernel/time.c
--- v2.1.35/linux/kernel/time.c	Fri Apr  4 08:52:26 1997
+++ linux/kernel/time.c	Tue Apr 22 22:53:52 1997
@@ -167,20 +167,21 @@
 	if (tz) {
 		if (copy_from_user(&new_tz, tz, sizeof(*tz)))
 			return -EFAULT;
-		lock_kernel();
+
+		/* SMP safe, global irq locking makes it work. */
 		sys_tz = new_tz;
 		if (firsttime) {
 			firsttime = 0;
 			if (!tv)
 				warp_clock();
 		}
-		unlock_kernel();
 	}
 	if (tv)
 	{
-		lock_kernel();
+		/* SMP safe, again the code in arch/foo/time.c should
+		 * globally block out interrupts when it runs.
+		 */
 		do_settimeofday(&new_tv);
-		unlock_kernel();
 	}
 	return 0;
 }
@@ -234,9 +235,7 @@
 		if (txc.tick < 900000/HZ || txc.tick > 1100000/HZ)
 			return -EINVAL;
 
-	lock_kernel();
-
-	cli();
+	cli(); /* SMP: global cli() is enough protection. */
 
 	/* Save for later - semantics of adjtime is to return old value */
 	save_adjust = time_adjust;
@@ -351,6 +350,6 @@
 	txc.stbcnt	   = pps_stbcnt;
 
 	sti();
-	unlock_kernel();
+
 	return copy_to_user(txc_p, &txc, sizeof(struct timex)) ? -EFAULT : time_state;
 }
diff -u --recursive --new-file v2.1.35/linux/mm/page_alloc.c linux/mm/page_alloc.c
--- v2.1.35/linux/mm/page_alloc.c	Mon Apr 14 16:28:27 1997
+++ linux/mm/page_alloc.c	Tue Apr 22 08:14:21 1997
@@ -276,8 +276,8 @@
 	 * with a minimum of 16 pages. This is totally arbitrary
 	 */
 	i = (end_mem - PAGE_OFFSET) >> (PAGE_SHIFT+7);
-	if (i < 16)
-		i = 16;
+	if (i < 48)
+		i = 48;
 	min_free_pages = i;
 	free_pages_low = i + (i>>1);
 	free_pages_high = i + i;
diff -u --recursive --new-file v2.1.35/linux/mm/swap.c linux/mm/swap.c
--- v2.1.35/linux/mm/swap.c	Mon Apr 14 16:28:27 1997
+++ linux/mm/swap.c	Tue Apr 22 08:14:21 1997
@@ -38,13 +38,13 @@
  *
  * Keep these three variables contiguous for sysctl(2).  
  */
-int min_free_pages = 20;
-int free_pages_low = 30;
-int free_pages_high = 40;
+int min_free_pages = 48;
+int free_pages_low = 72;
+int free_pages_high = 96;
 
 /* We track the number of pages currently being asynchronously swapped
    out, so that we don't try to swap TOO many pages out at once */
-atomic_t nr_async_pages = ATOMIC_INIT;
+atomic_t nr_async_pages = ATOMIC_INIT(0);
 
 /*
  * Constants for the page aging mechanism: the maximum age (actually,
diff -u --recursive --new-file v2.1.35/linux/net/bridge/br.c linux/net/bridge/br.c
--- v2.1.35/linux/net/bridge/br.c	Thu Mar 27 14:40:14 1997
+++ linux/net/bridge/br.c	Tue Apr 22 22:46:27 1997
@@ -42,6 +42,7 @@
 #include <linux/string.h>
 #include <linux/skbuff.h>
 #include <linux/if_arp.h>
+#include <linux/init.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
 #include <net/br.h>
@@ -699,7 +700,7 @@
 	}					  /* (4.6.1.2.3)	 */
 }
 
-void br_init(void)
+__initfunc(void br_init(void))
 {						  /* (4.8.1)	 */
 	int             port_no;
 
diff -u --recursive --new-file v2.1.35/linux/net/core/dev.c linux/net/core/dev.c
--- v2.1.35/linux/net/core/dev.c	Mon Apr 14 16:28:27 1997
+++ linux/net/core/dev.c	Tue Apr 22 22:46:27 1997
@@ -79,6 +79,7 @@
 #include <linux/stat.h>
 #include <net/br.h>
 #include <linux/net_alias.h>
+#include <linux/init.h>
 #ifdef CONFIG_KERNELD
 #include <linux/kerneld.h>
 #endif
@@ -122,7 +123,7 @@
  *	Device list lock
  */
  
-atomic_t dev_lockct = ATOMIC_INIT;
+atomic_t dev_lockct = ATOMIC_INIT(0);
  
 /*
  *	Our notifier list
@@ -479,10 +480,6 @@
 				/* at the front or the back of the	*/
 				/* queue - front is a retransmit try	*/
 
-#if CONFIG_SKB_CHECK 
-	IS_SKB(skb);
-#endif    
-
 	/*
 	 *	Negative priority is used to flag a frame that is being pulled from the
 	 *	queue front as a retransmit attempt. It therefore goes back on the queue
@@ -576,10 +573,6 @@
 
 	start_bh_atomic();
 
-#if CONFIG_SKB_CHECK 
-	IS_SKB(skb);
-#endif    
-
 	/*
 	 *	If the address has not been resolved. Call the device header rebuilder.
 	 *	This can cover all protocols and technically not just ARP either.
@@ -676,9 +669,7 @@
 	/*
 	 *	Add it to the "backlog" queue. 
 	 */
-#if CONFIG_SKB_CHECK
-	IS_SKB(skb);
-#endif	
+
 	skb_queue_tail(&backlog,skb);
 	backlog_size++;
   
@@ -1578,7 +1569,7 @@
 #endif	/* CONFIG_PROC_FS */
 #endif	/* CONFIG_NET_RADIO */
 
-int net_dev_init(void)
+__initfunc(int net_dev_init(void))
 {
 	struct device *dev, **dp;
 
diff -u --recursive --new-file v2.1.35/linux/net/core/dst.c linux/net/core/dst.c
--- v2.1.35/linux/net/core/dst.c	Mon Apr 14 16:28:27 1997
+++ linux/net/core/dst.c	Thu Apr 17 13:20:52 1997
@@ -20,7 +20,7 @@
 #include <net/dst.h>
 
 struct dst_entry * dst_garbage_list;
-atomic_t	dst_total = ATOMIC_INIT;
+atomic_t	dst_total = ATOMIC_INIT(0);
 
 static unsigned long dst_gc_timer_expires;
 static unsigned long dst_gc_timer_inc = DST_GC_MAX;
diff -u --recursive --new-file v2.1.35/linux/net/core/net_alias.c linux/net/core/net_alias.c
--- v2.1.35/linux/net/core/net_alias.c	Sun Jan 19 05:47:27 1997
+++ linux/net/core/net_alias.c	Tue Apr 22 22:46:27 1997
@@ -43,6 +43,7 @@
 #include <linux/in.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
+#include <linux/init.h>
 
 #include <linux/net_alias.h>
 
@@ -1359,7 +1360,7 @@
  *	Net_alias initialisation called from net_dev_init().
  */
 
-void net_alias_init(void)
+__initfunc(void net_alias_init(void))
 {
 
 	/*
diff -u --recursive --new-file v2.1.35/linux/net/core/skbuff.c linux/net/core/skbuff.c
--- v2.1.35/linux/net/core/skbuff.c	Mon Apr 14 16:28:27 1997
+++ linux/net/core/skbuff.c	Tue Apr 22 22:46:27 1997
@@ -60,9 +60,9 @@
  *	Resource tracking variables
  */
 
-static atomic_t net_skbcount = ATOMIC_INIT;
-static atomic_t net_allocs = ATOMIC_INIT;
-static atomic_t net_fails  = ATOMIC_INIT;
+static atomic_t net_skbcount = ATOMIC_INIT(0);
+static atomic_t net_allocs = ATOMIC_INIT(0);
+static atomic_t net_fails  = ATOMIC_INIT(0);
 
 extern atomic_t ip_frag_mem;
 
@@ -87,509 +87,17 @@
 #endif	
 }
 
-#if CONFIG_SKB_CHECK
-
-/*
- *	Debugging paranoia. Used for debugging network stacks.
- */
-
-int skb_check(struct sk_buff *skb, int head, int line, char *file)
-{
-	if (head) {
-		if (skb->magic_debug_cookie != SK_HEAD_SKB) {
-			printk("File: %s Line %d, found a bad skb-head\n",
-				file,line);
-			return -1;
-		}
-		if (!skb->next || !skb->prev) {
-			printk("skb_check: head without next or prev\n");
-			return -1;
-		}
-		if (skb->next->magic_debug_cookie != SK_HEAD_SKB
-			&& skb->next->magic_debug_cookie != SK_GOOD_SKB) {
-			printk("File: %s Line %d, bad next head-skb member\n",
-				file,line);
-			return -1;
-		}
-		if (skb->prev->magic_debug_cookie != SK_HEAD_SKB
-			&& skb->prev->magic_debug_cookie != SK_GOOD_SKB) {
-			printk("File: %s Line %d, bad prev head-skb member\n",
-				file,line);
-			return -1;
-		}
-		return 0;
-	}
-	if (skb->next != NULL && skb->next->magic_debug_cookie != SK_HEAD_SKB
-		&& skb->next->magic_debug_cookie != SK_GOOD_SKB) {
-		printk("File: %s Line %d, bad next skb member\n",
-			file,line);
-		return -1;
-	}
-	if (skb->prev != NULL && skb->prev->magic_debug_cookie != SK_HEAD_SKB
-		&& skb->prev->magic_debug_cookie != SK_GOOD_SKB) {
-		printk("File: %s Line %d, bad prev skb member\n",
-			file,line);
-		return -1;
-	}
-
-
-	if(skb->magic_debug_cookie==SK_FREED_SKB)
-	{
-		printk("File: %s Line %d, found a freed skb lurking in the undergrowth!\n",
-			file,line);
-		printk("skb=%p, real size=%d, free=%d\n",
-			skb,skb->truesize,skb->free);
-		return -1;
-	}
-	if(skb->magic_debug_cookie!=SK_GOOD_SKB)
-	{
-		printk("File: %s Line %d, passed a non skb!\n", file,line);
-		printk("skb=%p, real size=%d, free=%d\n",
-			skb,skb->truesize,skb->free);
-		return -1;
-	}
-	if(skb->head>skb->data)
-	{
-		printk("File: %s Line %d, head > data !\n", file,line);
-		printk("skb=%p, head=%p, data=%p\n",
-			skb,skb->head,skb->data);
-		return -1;
-	}
-	if(skb->tail>skb->end)
-	{
-		printk("File: %s Line %d, tail > end!\n", file,line);
-		printk("skb=%p, tail=%p, end=%p\n",
-			skb,skb->tail,skb->end);
-		return -1;
-	}
-	if(skb->data>skb->tail)
-	{
-		printk("File: %s Line %d, data > tail!\n", file,line);
-		printk("skb=%p, data=%p, tail=%p\n",
-			skb,skb->data,skb->tail);
-		return -1;
-	}
-	if(skb->tail-skb->data!=skb->len)
-	{
-		printk("File: %s Line %d, wrong length\n", file,line);
-		printk("skb=%p, data=%p, end=%p len=%ld\n",
-			skb,skb->data,skb->end,skb->len);
-		return -1;
-	}
-	if((unsigned long) skb->end > (unsigned long) skb)
-	{
-		printk("File: %s Line %d, control overrun\n", file,line);
-		printk("skb=%p, end=%p\n",
-			skb,skb->end);
-		return -1;
-	}
-
-	/* Guess it might be acceptable then */
-	return 0;
-}
-#endif
-
-
-#if CONFIG_SKB_CHECK
-void skb_queue_head_init(struct sk_buff_head *list)
-{
-	list->prev = (struct sk_buff *)list;
-	list->next = (struct sk_buff *)list;
-	list->qlen = 0;
-	list->magic_debug_cookie = SK_HEAD_SKB;
-}
-
-
-/*
- *	Insert an sk_buff at the start of a list.
- */
-void skb_queue_head(struct sk_buff_head *list_,struct sk_buff *newsk)
-{
-	unsigned long flags;
-	struct sk_buff *list = (struct sk_buff *)list_;
-
-	save_flags(flags);
-	cli();
-
-	IS_SKB(newsk);
-	IS_SKB_HEAD(list);
-	if (newsk->next || newsk->prev)
-		printk("Suspicious queue head: sk_buff on list!\n");
-
-	newsk->next = list->next;
-	newsk->prev = list;
-
-	newsk->next->prev = newsk;
-	newsk->prev->next = newsk;
-	newsk->list = list_;
-	list_->qlen++;
-
-	restore_flags(flags);
-}
-
-void __skb_queue_head(struct sk_buff_head *list_,struct sk_buff *newsk)
-{
-	struct sk_buff *list = (struct sk_buff *)list_;
-
-
-	IS_SKB(newsk);
-	IS_SKB_HEAD(list);
-	if (newsk->next || newsk->prev)
-		printk("Suspicious queue head: sk_buff on list!\n");
-
-	newsk->next = list->next;
-	newsk->prev = list;
-
-	newsk->next->prev = newsk;
-	newsk->prev->next = newsk;
-	newsk->list = list_;
-	list_->qlen++;
-
-}
-
-/*
- *	Insert an sk_buff at the end of a list.
- */
-void skb_queue_tail(struct sk_buff_head *list_, struct sk_buff *newsk)
-{
-	unsigned long flags;
-	struct sk_buff *list = (struct sk_buff *)list_;
-
-	save_flags(flags);
-	cli();
-
-	if (newsk->next || newsk->prev)
-		printk("Suspicious queue tail: sk_buff on list!\n");
-	IS_SKB(newsk);
-	IS_SKB_HEAD(list);
-
-	newsk->next = list;
-	newsk->prev = list->prev;
-
-	newsk->next->prev = newsk;
-	newsk->prev->next = newsk;
-	
-	newsk->list = list_;
-	list_->qlen++;
-
-	restore_flags(flags);
-}
-
-void __skb_queue_tail(struct sk_buff_head *list_, struct sk_buff *newsk)
-{
-	struct sk_buff *list = (struct sk_buff *)list_;
-
-	if (newsk->next || newsk->prev)
-		printk("Suspicious queue tail: sk_buff on list!\n");
-	IS_SKB(newsk);
-	IS_SKB_HEAD(list);
-
-	newsk->next = list;
-	newsk->prev = list->prev;
-
-	newsk->next->prev = newsk;
-	newsk->prev->next = newsk;
-	
-	newsk->list = list_;
-	list_->qlen++;
-}
-
-/*
- *	Remove an sk_buff from a list. This routine is also interrupt safe
- *	so you can grab read and free buffers as another process adds them.
- */
-
-struct sk_buff *skb_dequeue(struct sk_buff_head *list_)
-{
-	unsigned long flags;
-	struct sk_buff *result;
-	struct sk_buff *list = (struct sk_buff *)list_;
-
-	save_flags(flags);
-	cli();
-
-	IS_SKB_HEAD(list);
-
-	result = list->next;
-	if (result == list) {
-		restore_flags(flags);
-		return NULL;
-	}
-
-	result->next->prev = list;
-	list->next = result->next;
-
-	result->next = NULL;
-	result->prev = NULL;
-	list_->qlen--;
-	result->list = NULL;
-	
-	restore_flags(flags);
-
-	IS_SKB(result);
-	return result;
-}
-
-struct sk_buff *__skb_dequeue(struct sk_buff_head *list_)
-{
-	struct sk_buff *result;
-	struct sk_buff *list = (struct sk_buff *)list_;
-
-	IS_SKB_HEAD(list);
-
-	result = list->next;
-	if (result == list) {
-		return NULL;
-	}
-
-	result->next->prev = list;
-	list->next = result->next;
-
-	result->next = NULL;
-	result->prev = NULL;
-	list_->qlen--;
-	result->list = NULL;
-	
-	IS_SKB(result);
-	return result;
-}
-
-/*
- *	Insert a packet before another one in a list.
- */
-void skb_insert(struct sk_buff *old, struct sk_buff *newsk)
-{
-	unsigned long flags;
-
-	IS_SKB(old);
-	IS_SKB(newsk);
-
-	if(!old->next || !old->prev)
-		printk("insert before unlisted item!\n");
-	if(newsk->next || newsk->prev)
-		printk("inserted item is already on a list.\n");
-
-	save_flags(flags);
-	cli();
-	newsk->next = old;
-	newsk->prev = old->prev;
-	old->prev = newsk;
-	newsk->prev->next = newsk;
-	newsk->list = old->list;
-	newsk->list->qlen++;
-
-	restore_flags(flags);
-}
-
-/*
- *	Insert a packet before another one in a list.
- */
-
-void __skb_insert(struct sk_buff *newsk,
-	struct sk_buff * prev, struct sk_buff *next,
-	struct sk_buff_head * list)
-{
-	IS_SKB(prev);
-	IS_SKB(newsk);
-	IS_SKB(next);
-
-	if(!prev->next || !prev->prev)
-		printk("insert after unlisted item!\n");
-	if(!next->next || !next->prev)
-		printk("insert before unlisted item!\n");
-	if(newsk->next || newsk->prev)
-		printk("inserted item is already on a list.\n");
-
-	newsk->next = next;
-	newsk->prev = prev;
-	next->prev = newsk;
-	prev->next = newsk;
-	newsk->list = list;
-	list->qlen++;
-
-}
-
-/*
- *	Place a packet after a given packet in a list.
- */
-void skb_append(struct sk_buff *old, struct sk_buff *newsk)
-{
-	unsigned long flags;
-
-	IS_SKB(old);
-	IS_SKB(newsk);
-
-	if(!old->next || !old->prev)
-		printk("append before unlisted item!\n");
-	if(newsk->next || newsk->prev)
-		printk("append item is already on a list.\n");
-
-	save_flags(flags);
-	cli();
-
-	newsk->prev = old;
-	newsk->next = old->next;
-	newsk->next->prev = newsk;
-	old->next = newsk;
-	newsk->list = old->list;
-	newsk->list->qlen++;
-
-	restore_flags(flags);
-}
-
-/*
- *	Remove an sk_buff from its list. Works even without knowing the list it
- *	is sitting on, which can be handy at times. It also means that THE LIST
- *	MUST EXIST when you unlink. Thus a list must have its contents unlinked
- *	_FIRST_.
- */
-void skb_unlink(struct sk_buff *skb)
-{
-	unsigned long flags;
-
-	save_flags(flags);
-	cli();
-
-	IS_SKB(skb);
-
-	if(skb->list)
-	{
-		skb->list->qlen--;
-		skb->next->prev = skb->prev;
-		skb->prev->next = skb->next;
-		skb->next = NULL;
-		skb->prev = NULL;
-		skb->list = NULL;
-	}
-#ifdef PARANOID_BUGHUNT_MODE	/* This is legal but we sometimes want to watch it */
-	else
-		printk("skb_unlink: not a linked element\n");
-#endif
-	restore_flags(flags);
-}
-
-void __skb_unlink(struct sk_buff *skb)
-{
-	IS_SKB(skb);
-
-	if(skb->list)
-	{
-		skb->list->qlen--;
-		skb->next->prev = skb->prev;
-		skb->prev->next = skb->next;
-		skb->next = NULL;
-		skb->prev = NULL;
-		skb->list = NULL;
-	}
-#ifdef PARANOID_BUGHUNT_MODE	/* This is legal but we sometimes want to watch it */
-	else
-		printk("skb_unlink: not a linked element\n");
-#endif
-}
-
-/*
- *	Add data to an sk_buff
- */
- 
-unsigned char *skb_put(struct sk_buff *skb, unsigned int len)
-{
-	unsigned char *tmp=skb->tail;
-	IS_SKB(skb);
-	skb->tail+=len;
-	skb->len+=len;
-	IS_SKB(skb);
-	if(skb->tail>skb->end)
-		panic("skput:over: %p:%d", __builtin_return_address(0),len);
-	return tmp;
-}
-
-unsigned char *skb_push(struct sk_buff *skb, unsigned int len)
-{
-	IS_SKB(skb);
-	skb->data-=len;
-	skb->len+=len;
-	IS_SKB(skb);
-	if(skb->data<skb->head)
-		panic("skpush:under: %p:%d", __builtin_return_address(0),len);
-	return skb->data;
-}
-
-unsigned char * skb_pull(struct sk_buff *skb, unsigned int len)
-{
-	IS_SKB(skb);
-	if(len>skb->len)
-		return 0;
-	skb->data+=len;
-	skb->len-=len;
-	return skb->data;
-}
-
-int skb_headroom(struct sk_buff *skb)
-{
-	IS_SKB(skb);
-	return skb->data-skb->head;
-}
-
-int skb_tailroom(struct sk_buff *skb)
-{
-	IS_SKB(skb);
-	return skb->end-skb->tail;
-}
-
-void skb_reserve(struct sk_buff *skb, unsigned int len)
-{
-	IS_SKB(skb);
-	skb->data+=len;
-	skb->tail+=len;
-	if(skb->tail>skb->end)
-		panic("sk_res: over");
-	if(skb->data<skb->head)
-		panic("sk_res: under");
-	IS_SKB(skb);
-}
-
-void skb_trim(struct sk_buff *skb, unsigned int len)
-{
-	IS_SKB(skb);
-	if(skb->len>len)
-	{
-		skb->len=len;
-		skb->tail=skb->data+len;
-	}
-}
-
-
-
-#endif
-
-/**************************************************************************
-
-      Stuff below this point isn't debugging duplicates of the inlines
-      used for buffer handling
-      
-***************************************************************************/
-
 /*
  *	Free an sk_buff. Release anything attached to the buffer.
  */
 
 void __kfree_skb(struct sk_buff *skb)
 {
-#if CONFIG_SKB_CHECK
-	if (skb == NULL)
-	{
-		printk(KERN_CRIT "kfree_skb: skb = NULL (from %p)\n",
- 			__builtin_return_address(0));
-		return;
-  	}
-	IS_SKB(skb);
-#endif
 	if (skb->list)
-	 	printk(KERN_WARNING "Warning: kfree_skb passed an skb still on a list (from %p).\n",
-			__builtin_return_address(0));
+	 	printk(KERN_WARNING "Warning: kfree_skb passed an skb still "
+		       "on a list (from %p).\n", __builtin_return_address(0));
 
 	dst_release(skb->dst);
-
 	if(skb->destructor)
 		skb->destructor(skb);
 	kfree_skbmem(skb);
@@ -607,15 +115,14 @@
 struct sk_buff *alloc_skb(unsigned int size,int priority)
 {
 	struct sk_buff *skb;
-	int len;
 	unsigned char *bptr;
+	int len;
 
-	if (in_interrupt() && priority!=GFP_ATOMIC) 
-	{
+	if (in_interrupt() && priority!=GFP_ATOMIC) {
 		static int count = 0;
 		if (++count < 5) {
-			printk(KERN_ERR "alloc_skb called nonatomically from interrupt %p\n",
-				__builtin_return_address(0));
+			printk(KERN_ERR "alloc_skb called nonatomically "
+			       "from interrupt %p\n", __builtin_return_address(0));
 			priority = GFP_ATOMIC;
 		}
 	}
@@ -625,25 +132,23 @@
 	 *	'alignment mask'.
 	 */
 	 
-	size=(size+15)&~15;		/* Allow for alignments. Make a multiple of 16 bytes */
+	/* Allow for alignments. Make a multiple of 16 bytes */
+	size = (size + 15) & ~15;
 	len = size;
 	
-	size+=sizeof(struct sk_buff);	/* And stick the control itself on the end */
+	/* And stick the control itself on the end */
+	size += sizeof(struct sk_buff);
 	
 	/*
 	 *	Allocate some space
 	 */
 	 
-	bptr=(unsigned char *)kmalloc(size,priority);
-	if (bptr == NULL)
-	{
+	bptr = kmalloc(size,priority);
+	if (bptr == NULL) {
 		atomic_inc(&net_fails);
 		return NULL;
 	}
-#ifdef PARANOID_BUGHUNT_MODE
-	if(skb->magic_debug_cookie == SK_GOOD_SKB)
-		printk("Kernel kmalloc handed us an existing skb (%p)\n",skb);
-#endif
+
 	/*
 	 *	Now we play a little game with the caches. Linux kmalloc is
 	 *	a bit cache dumb, in fact its just about maximally non 
@@ -653,7 +158,7 @@
 	 */
 	atomic_inc(&net_allocs);
 	
-	skb=(struct sk_buff *)(bptr+size)-1;
+	skb = (struct sk_buff *)(bptr + size) - 1;
 
 	atomic_set(&skb->count, 1);		/* only one reference to this */
 	skb->data_skb = skb;			/* and we're our own data skb */
@@ -672,16 +177,14 @@
 	memset(skb->cb, 0, sizeof(skb->cb));
 	skb->priority = SOPRI_NORMAL;
 	atomic_inc(&net_skbcount);
-#if CONFIG_SKB_CHECK
-	skb->magic_debug_cookie = SK_GOOD_SKB;
-#endif
 	atomic_set(&skb->users, 1);
-	/* Load the data pointers */
-	skb->head=bptr;
-	skb->data=bptr;
-	skb->tail=bptr;
-	skb->end=bptr+len;
-	skb->len=0;
+
+	/* Load the data pointers. */
+	skb->head = bptr;
+	skb->data = bptr;
+	skb->tail = bptr;
+	skb->end = bptr + len;
+	skb->len = 0;
 	skb->inclone = 0;
 	return skb;
 }
@@ -705,10 +208,7 @@
 
 	/* don't do anything if somebody still uses us */
 	if (atomic_dec_and_test(&skb->count)) {
-
-		int free_head;
-
-		free_head = (skb->inclone != SKB_CLONE_INLINE);
+		int free_head = (skb->inclone != SKB_CLONE_INLINE);
 
 		/* free the skb that contains the actual data if we've clone()'d */
 		if (skb->data_skb != skb) {
@@ -730,16 +230,12 @@
 	struct sk_buff *n;
 	int inbuff = 0;
 	
-	IS_SKB(skb);
-	if (!skb->inclone && skb_tailroom(skb) >= sizeof(struct sk_buff))
-	{
+	if (!skb->inclone && skb_tailroom(skb) >= sizeof(struct sk_buff)) {
 		n = ((struct sk_buff *) skb->end) - 1;
 		skb->end -= sizeof(struct sk_buff);
 		skb->inclone = SKB_CLONE_ORIG;
 		inbuff = SKB_CLONE_INLINE;
-	}
-	else
-	{
+	} else {
 		n = kmalloc(sizeof(*n), priority);
 		if (!n)
 			return NULL;
@@ -775,8 +271,6 @@
 	 *	Allocate the copy buffer
 	 */
 	 
-	IS_SKB(skb);
-	
 	n=alloc_skb(skb->end - skb->head, priority);
 	if(n==NULL)
 		return NULL;
@@ -806,7 +300,6 @@
 	n->seq=skb->seq;
 	n->end_seq=skb->end_seq;
 	n->ack_seq=skb->ack_seq;
-	n->acked=skb->acked;
 	memcpy(n->cb, skb->cb, sizeof(skb->cb));
 	n->used=skb->used;
 	n->arp=skb->arp;
@@ -816,7 +309,6 @@
 	n->stamp=skb->stamp;
 	n->destructor = NULL;
 	n->security=skb->security;
-	IS_SKB(n);
 	return n;
 }
 
@@ -830,8 +322,6 @@
 	 *	Allocate the copy buffer
 	 */
  	 
-	IS_SKB(skb);
-	
 	n=alloc_skb(skb->truesize+newheadroom-headroom-sizeof(struct sk_buff), GFP_ATOMIC);
 	if(n==NULL)
 		return NULL;
@@ -862,7 +352,6 @@
 	n->seq=skb->seq;
  	n->end_seq=skb->end_seq;
 	n->ack_seq=skb->ack_seq;
-	n->acked=skb->acked;
 	n->used=skb->used;
 	n->arp=skb->arp;
 	n->tries=0;
@@ -872,7 +361,6 @@
 	n->destructor = NULL;
 	n->security=skb->security;
 
-	IS_SKB(n);
 	return n;
 }
   
diff -u --recursive --new-file v2.1.35/linux/net/core/sock.c linux/net/core/sock.c
--- v2.1.35/linux/net/core/sock.c	Mon Apr 14 16:28:27 1997
+++ linux/net/core/sock.c	Tue Apr 22 22:46:27 1997
@@ -189,7 +189,7 @@
 			 *	is best
 			 */
 			 
-			if(val > SK_WMEM_MAX*2 || val < 2048)
+			if(val > SK_WMEM_MAX*2)
 				return -EINVAL;
 			/*
 			 *	Once this is all 32bit values we can
@@ -197,7 +197,7 @@
 			 */
 			if(val > 65535)
 				return -EINVAL;
-			sk->sndbuf = val;
+			sk->sndbuf = max(val,2048);
 			/*
 			 *	Wake up sending tasks if we
 			 *	upped the value.
@@ -206,12 +206,12 @@
 			break;
 
 		case SO_RCVBUF:
-			if(val > SK_RMEM_MAX*2 || val < 256)
+			if(val > SK_RMEM_MAX*2)
 				return -EINVAL;
 			/* Can go soon: FIXME */
 			if(val > 65535)
 				return -EINVAL;
-			sk->rcvbuf = val;
+			sk->rcvbuf = max(val,256);
 			break;
 
 		case SO_KEEPALIVE:
@@ -479,9 +479,6 @@
 void sock_wfree(struct sk_buff *skb)
 {
 	struct sock *sk = skb->sk;
-#if CONFIG_SKB_CHECK
-	IS_SKB(skb);
-#endif
 #if 1
 	if (!sk) {
 		printk(KERN_DEBUG "sock_wfree: sk==NULL\n");
@@ -497,9 +494,6 @@
 void sock_rfree(struct sk_buff *skb)
 {
 	struct sock *sk = skb->sk;
-#if CONFIG_SKB_CHECK
-	IS_SKB(skb);
-#endif	
 #if 1
 	if (!sk) {
 		printk(KERN_DEBUG "sock_rfree: sk==NULL\n");
diff -u --recursive --new-file v2.1.35/linux/net/ethernet/eth.c linux/net/ethernet/eth.c
--- v2.1.35/linux/net/ethernet/eth.c	Thu Mar 27 14:40:15 1997
+++ linux/net/ethernet/eth.c	Tue Apr 22 22:46:27 1997
@@ -295,7 +295,6 @@
 	struct iphdr *iph;
 	int ip_length;
 
-	IS_SKB(dest);
 	eth=(struct ethhdr *)src;
 	if(eth->h_proto!=htons(ETH_P_IP))
 	{
diff -u --recursive --new-file v2.1.35/linux/net/ipv4/arp.c linux/net/ipv4/arp.c
--- v2.1.35/linux/net/ipv4/arp.c	Mon Apr 14 16:28:27 1997
+++ linux/net/ipv4/arp.c	Thu Apr 17 13:20:52 1997
@@ -230,13 +230,6 @@
 
 int sysctl_arp_dead_res_time = ARP_DEAD_RES_TIME;
 
-/* This should be completely nuked... -DaveM */
-#if RT_CACHE_DEBUG >= 1
-#define ASSERT_BH() if (!in_interrupt()) printk(KERN_CRIT __FUNCTION__ " called from SPL=0\n");
-#else
-#define ASSERT_BH()
-#endif
-
 static void arp_neigh_destroy(struct neighbour *neigh);
 
 /*
@@ -251,8 +244,8 @@
 };
 
 
-static atomic_t arp_size = ATOMIC_INIT;
-static atomic_t arp_unres_size = ATOMIC_INIT;
+static atomic_t arp_size = ATOMIC_INIT(0);
+static atomic_t arp_unres_size = ATOMIC_INIT(0);
 
 #ifdef CONFIG_ARPD
 static int arpd_not_running;
@@ -340,12 +333,9 @@
 {
 	struct sk_buff *skb;
 
-	ASSERT_BH();
-
 	/* Release the list of `skb' pointers. */
 	while ((skb = skb_dequeue(&entry->u.neigh.arp_queue)) != NULL)
 		kfree_skb(skb, FREE_WRITE);
-	return;
 }
 
 static void arp_free(struct arp_table **entryp)
@@ -353,8 +343,6 @@
 	struct arp_table *entry = *entryp;
 	*entryp = entry->u.next;
 
-	ASSERT_BH();
-
 	if (!(entry->flags&ATF_PUBL)) {
 		atomic_dec(&arp_size);
 		if (!(entry->flags&ATF_COM))
@@ -373,8 +361,6 @@
 	struct arp_table *entry = (struct arp_table*)neigh;
 	struct hh_cache *hh, *next;
 
-	ASSERT_BH();
-
 	del_timer(&entry->timer);
 	arp_purge_send_q(entry);
 
@@ -877,11 +863,8 @@
 {
 	struct sk_buff *skb;
 
-	ASSERT_BH();
-
-	while((skb = skb_dequeue(&entry->u.neigh.arp_queue)) != NULL) {
+	while((skb = skb_dequeue(&entry->u.neigh.arp_queue)) != NULL)
 		dev_queue_xmit(skb);
-	}
 }
 
 
diff -u --recursive --new-file v2.1.35/linux/net/ipv4/fib.c linux/net/ipv4/fib.c
--- v2.1.35/linux/net/ipv4/fib.c	Mon Apr 14 16:28:27 1997
+++ linux/net/ipv4/fib.c	Thu Apr 17 13:20:52 1997
@@ -117,7 +117,7 @@
  */
 
 static struct wait_queue *fib_wait;
-static atomic_t fib_users = ATOMIC_INIT;
+static atomic_t fib_users = ATOMIC_INIT(0);
 
 static void fib_lock(void)
 {
diff -u --recursive --new-file v2.1.35/linux/net/ipv4/icmp.c linux/net/ipv4/icmp.c
--- v2.1.35/linux/net/ipv4/icmp.c	Thu Mar 27 14:40:15 1997
+++ linux/net/ipv4/icmp.c	Tue Apr 22 22:46:27 1997
@@ -754,7 +754,7 @@
 	if(__ip_chk_addr(iph->daddr)==IS_BROADCAST)
 	{
 		printk("%s sent an invalid ICMP error to a broadcast.\n",
-			in_ntoa(iph->daddr));
+			in_ntoa(skb->nh.iph->saddr));
 		kfree_skb(skb, FREE_READ);
 	}
 
diff -u --recursive --new-file v2.1.35/linux/net/ipv4/ip_fragment.c linux/net/ipv4/ip_fragment.c
--- v2.1.35/linux/net/ipv4/ip_fragment.c	Mon Apr 14 16:28:27 1997
+++ linux/net/ipv4/ip_fragment.c	Tue Apr 22 22:46:27 1997
@@ -46,7 +46,7 @@
 
 static struct ipq *ipqueue = NULL;		/* IP fragment queue	*/
 
-atomic_t ip_frag_mem = ATOMIC_INIT;		/* Memory used for fragments */
+atomic_t ip_frag_mem = ATOMIC_INIT(0);		/* Memory used for fragments */
 
 char *in_ntoa(unsigned long in);
 
@@ -177,7 +177,6 @@
 	while (fp != NULL)
 	{
 		xp = fp->next;
-		IS_SKB(fp->skb);
 		frag_kfree_skb(fp->skb,FREE_READ);
 		frag_kfree_s(fp, sizeof(struct ipfrag));
 		fp = xp;
diff -u --recursive --new-file v2.1.35/linux/net/ipv4/ip_sockglue.c linux/net/ipv4/ip_sockglue.c
--- v2.1.35/linux/net/ipv4/ip_sockglue.c	Tue Mar  4 10:25:27 1997
+++ linux/net/ipv4/ip_sockglue.c	Tue Apr 22 22:46:27 1997
@@ -296,10 +296,8 @@
 			if (sk->ip_recverr && !val) {
 				struct sk_buff *skb;
 				/* Drain queued errors */
-				while((skb=skb_dequeue(&sk->error_queue))!=NULL) {
-					IS_SKB(skb);
+				while((skb=skb_dequeue(&sk->error_queue))!=NULL)
 					kfree_skb(skb, FREE_READ);
-				}
 			}
 			sk->ip_recverr = val?1:0;
 			release_sock(sk);
diff -u --recursive --new-file v2.1.35/linux/net/ipv4/proc.c linux/net/ipv4/proc.c
--- v2.1.35/linux/net/ipv4/proc.c	Mon Apr 14 16:28:27 1997
+++ linux/net/ipv4/proc.c	Tue Apr 22 22:46:27 1997
@@ -124,7 +124,7 @@
 			format==0?sp->write_seq-tp->snd_una:atomic_read(&sp->wmem_alloc), 
 			format==0?tp->rcv_nxt-sp->copied_seq:atomic_read(&sp->rmem_alloc),
 			timer_active, timer_expires-jiffies,
-			(unsigned) atomic_read(&sp->retransmits),
+			tp->retransmits,
 			sp->socket ? sp->socket->inode->i_uid:0,
 			timer_active?sp->timeout:0,
 			sp->socket ? sp->socket->inode->i_ino:0);
diff -u --recursive --new-file v2.1.35/linux/net/ipv4/route.c linux/net/ipv4/route.c
--- v2.1.35/linux/net/ipv4/route.c	Mon Apr 14 16:28:27 1997
+++ linux/net/ipv4/route.c	Thu Apr 17 13:20:52 1997
@@ -111,7 +111,7 @@
  * Route cache.
  */
 
-static atomic_t		 rt_cache_size = ATOMIC_INIT;
+static atomic_t		 rt_cache_size = ATOMIC_INIT(0);
 static struct rtable 	*rt_hash_table[RT_HASH_DIVISOR];
 
 static struct rtable * rt_intern_hash(unsigned hash, struct rtable * rth, u16 protocol);
diff -u --recursive --new-file v2.1.35/linux/net/ipv4/sysctl_net_ipv4.c linux/net/ipv4/sysctl_net_ipv4.c
--- v2.1.35/linux/net/ipv4/sysctl_net_ipv4.c	Mon Apr 14 16:28:28 1997
+++ linux/net/ipv4/sysctl_net_ipv4.c	Tue Apr 22 22:46:27 1997
@@ -36,6 +36,12 @@
 extern int sysctl_arp_confirm_timeout;
 
 extern int sysctl_tcp_cong_avoidance;
+extern int sysctl_tcp_hoe_retransmits;
+extern int sysctl_tcp_sack;
+extern int sysctl_tcp_tsack;
+extern int sysctl_tcp_timestamps;
+extern int sysctl_tcp_window_scaling;
+
 extern int tcp_sysctl_congavoid(ctl_table *ctl, int write, struct file * filp,
 				void *buffer, size_t *lenp);
 
@@ -80,6 +86,21 @@
          &proc_dointvec},
         {NET_IPV4_ARP_CONFIRM_TIMEOUT, "arp_confirm_timeout",
          &sysctl_arp_confirm_timeout, sizeof(int), 0644, NULL,
+         &proc_dointvec},
+        {NET_IPV4_TCP_HOE_RETRANSMITS, "tcp_hoe_retransmits",
+         &sysctl_tcp_hoe_retransmits, sizeof(int), 0644, NULL,
+         &proc_dointvec},
+        {NET_IPV4_TCP_SACK, "tcp_sack",
+         &sysctl_tcp_sack, sizeof(int), 0644, NULL,
+         &proc_dointvec},
+        {NET_IPV4_TCP_TSACK, "tcp_tsack",
+         &sysctl_tcp_tsack, sizeof(int), 0644, NULL,
+         &proc_dointvec},
+        {NET_IPV4_TCP_TIMESTAMPS, "tcp_timestamps",
+         &sysctl_tcp_timestamps, sizeof(int), 0644, NULL,
+         &proc_dointvec},
+        {NET_IPV4_TCP_WINDOW_SCALING, "tcp_window_scaling",
+         &sysctl_tcp_window_scaling, sizeof(int), 0644, NULL,
          &proc_dointvec},
 	{NET_IPV4_TCP_VEGAS_CONG_AVOID, "tcp_vegas_cong_avoid",
 	 &sysctl_tcp_cong_avoidance, sizeof(int), 0644,
diff -u --recursive --new-file v2.1.35/linux/net/ipv4/tcp.c linux/net/ipv4/tcp.c
--- v2.1.35/linux/net/ipv4/tcp.c	Mon Apr 14 16:28:28 1997
+++ linux/net/ipv4/tcp.c	Tue Apr 22 22:46:27 1997
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp.c,v 1.55 1997/04/13 10:31:45 davem Exp $
+ * Version:	$Id: tcp.c,v 1.61 1997/04/22 02:53:10 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -444,15 +444,14 @@
 {
 	struct open_request *req = tp->syn_wait_queue;
 
-	if (!req)
-		return NULL;
-	do {
+	while(req) {
 		if (req->sk && 
 		    (req->sk->state == TCP_ESTABLISHED ||
 		     req->sk->state >= TCP_FIN_WAIT1))
-			return req;
-	} while ((req = req->dl_next) != tp->syn_wait_queue);
-	return NULL;
+			break;
+		req = req->dl_next;
+	}
+	return req;
 }
 
 /*
@@ -466,9 +465,7 @@
 	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
 	struct open_request *req = tp->syn_wait_queue;
 
-	if (!req)
-		return;
-	do {
+	while(req) {
 		struct open_request *iter;
 		
 		if (req->sk)
@@ -481,9 +478,10 @@
 		tcp_dec_slow_timer(TCP_SLT_SYNACK);
 		sk->ack_backlog--;
 		tcp_openreq_free(iter);
-	} while (req != tp->syn_wait_queue);
+	}
 
 	tp->syn_wait_queue = NULL;
+	tp->syn_wait_last = &tp->syn_wait_queue;
 }
 
 /*
@@ -518,8 +516,7 @@
 
 	save_flags(flags);
 	cli();
-	if (sk == NULL || (skb = skb_peek(&sk->receive_queue)) == NULL)
-	{
+	if (sk == NULL || (skb = skb_peek(&sk->receive_queue)) == NULL) {
 		restore_flags(flags);
 		SOCK_DEBUG(sk, "empty\n");
 	  	return(0);
@@ -528,32 +525,27 @@
 	counted = sk->copied_seq;	/* Where we are at the moment */
 	amount = 0;
 
-	/*
-	 *	Do until a push or until we are out of data.
-	 */
-
-	do
-	{
-		/* Found a hole so stops here */
+	/* Do until a push or until we are out of data. */
+	do {
+		/* Found a hole so stops here. */
 		if (before(counted, skb->seq))	 	
 			break;
-		/* 
-		 * Length - header but start from where we are up to 
-		 * avoid overlaps 
+
+		/* Length - header but start from where we are up to
+		 * avoid overlaps.
 		 */
-		sum = skb->len - (counted - skb->seq);	
+		sum = skb->len - (counted - skb->seq);
 		if (skb->h.th->syn)
 			sum++;
-		if (sum > 0)
-		{	
-			/* Add it up, move on */
+		if (sum > 0) {
+			/* Add it up, move on. */
 			amount += sum;
 			if (skb->h.th->syn)
 				amount--;
 			counted += sum;
 		}
-		/*
-		 * Don't count urg data ... but do it in the right place!
+
+		/* Don't count urg data ... but do it in the right place!
 		 * Consider: "old_data (ptr is here) URG PUSH data"
 		 * The old code would stop at the first push because
 		 * it counted the urg (amount==1) and then does amount--
@@ -569,15 +561,14 @@
 		 * was correct.  Mike <pall@rz.uni-karlsruhe.de>
 		 */
 
-		/* don't count urg data */
+		/* Don't count urg data. */
 		if (skb->h.th->urg)
 			amount--;
 #if 0
 		if (amount && skb->h.th->psh) break;
 #endif
 		skb = skb->next;
-	}
-	while(skb != (struct sk_buff *)&sk->receive_queue);
+	} while(skb != (struct sk_buff *)&sk->receive_queue);
 
 	restore_flags(flags);
 	SOCK_DEBUG(sk, "got %lu bytes.\n",amount);
@@ -619,18 +610,20 @@
 	mask = 0;
 	if (sk->err)
 		mask = POLLERR;
-	/* connected ? */
+	/* Connected? */
 	if (sk->state != TCP_SYN_SENT && sk->state != TCP_SYN_RECV) {
-
 		if (sk->shutdown & RCV_SHUTDOWN)
 			mask |= POLLHUP;
-			
+
 		if ((tp->rcv_nxt != sk->copied_seq) &&
 		    (sk->urg_seq != sk->copied_seq ||
 		     tp->rcv_nxt != sk->copied_seq+1 ||
 		     sk->urginline || !sk->urg_data))
 			mask |= POLLIN | POLLRDNORM;
 
+		/* FIXME: this assumed sk->mtu is correctly maintained.
+		 * I see no evidence this is the case. -- erics
+		 */
 		if (!(sk->shutdown & SEND_SHUTDOWN) &&
 		     (sock_wspace(sk) >= sk->mtu+128+sk->prot->max_header))
 			mask |= POLLOUT | POLLWRNORM;
@@ -643,9 +636,7 @@
 
 int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg)
 {
-	switch(cmd)
-	{
-
+	switch(cmd) {
 		case TIOCINQ:
 #ifdef FIXME	/* FIXME: */
 		case FIONREAD:
@@ -676,28 +667,39 @@
 		}
 		default:
 			return(-EINVAL);
-	}
+	};
 }
 
 
 /* 
  *	This routine builds a generic TCP header. 
+ *	It also builds in the RFC1323 Timestamp.
+ *	It can't (unfortunately) do SACK as well.
  */
  
-extern __inline int tcp_build_header(struct tcphdr *th, struct sock *sk, int push)
+extern __inline void tcp_build_header(struct tcphdr *th, struct sock *sk, int push)
 {
-	struct tcp_opt *tp=&(sk->tp_pinfo.af_tcp);
+	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
 	memcpy(th,(void *) &(sk->dummy_th), sizeof(*th));
 	th->seq = htonl(sk->write_seq);
-
 	th->psh =(push == 0) ? 1 : 0;
-
-	sk->bytes_rcv = 0;
-	sk->ack_timed = 0;
 	th->ack_seq = htonl(tp->rcv_nxt);
 	th->window = htons(tcp_select_window(sk));
 
-	return(sizeof(*th));
+	/* FIXME: could use the inline found in tcp_output.c as well.
+	 * Probably that means we should move these up to an include file. --erics
+	 */
+	if (tp->tstamp_ok) {
+		__u32 *ptr = (__u32 *)(th+1);
+		*ptr++ = ntohl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16)
+			| (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP);
+		/* FIXME: Not sure it's worth setting these here already, but I'm
+	 	 * also not sure we replace them on all paths later. --erics
+		 */
+		*ptr++ = jiffies;
+		*ptr++ = tp->ts_recent;
+	}
 }
 
 /*
@@ -708,9 +710,7 @@
 	release_sock(sk);
 	cli();
 	if (sk->state != TCP_ESTABLISHED && sk->state != TCP_CLOSE_WAIT && sk->err == 0)
-    	{
 		interruptible_sleep_on(sk->sleep);
-	}
 	sti();
 	lock_sock(sk);
 }
@@ -756,22 +756,15 @@
 	int fault;
 	int copy;
 
-	/* 
-	 * Add more stuff to the end 
-	 * of the skb
-	 */
-
+	/* Add more stuff to the end of the skb. */
 	copy = min(sk->mss - tcp_size, skb_tailroom(skb));
 	copy = min(copy, seglen);
 
 	tcp_size += copy;
 
 	fault = copy_from_user(skb->tail, from, copy);
-
 	if (fault)
-	{
 		return -1;
-	}
 
 	skb_put(skb, copy);
 	skb->csum = csum_partial(skb->tail - tcp_size, tcp_size, 0);
@@ -793,19 +786,12 @@
 	int copied  = 0;
 	struct tcp_opt *tp=&(sk->tp_pinfo.af_tcp);
 
-	/* 
-	 *	Wait for a connection to finish.
-	 */
-	while (sk->state != TCP_ESTABLISHED && sk->state != TCP_CLOSE_WAIT)
-	{
-		if (copied)
-			return copied;
-
+	/* Wait for a connection to finish. */
+	while (sk->state != TCP_ESTABLISHED && sk->state != TCP_CLOSE_WAIT) {
 		if (sk->err)
 			return sock_error(sk);
 
-		if (sk->state != TCP_SYN_SENT && sk->state != TCP_SYN_RECV)
-		{
+		if (sk->state != TCP_SYN_SENT && sk->state != TCP_SYN_RECV) {
 			if (sk->keepopen)
 				send_sig(SIGPIPE, current, 0);
 			return -EPIPE;
@@ -820,19 +806,14 @@
 		wait_for_tcp_connect(sk);
 	}
 
-	/*
-	 *	Ok commence sending
-	 */
-
-	while(--iovlen >= 0)
-	{
+	/* Ok commence sending. */
+	while(--iovlen >= 0) {
 		int seglen=iov->iov_len;
 		unsigned char * from=iov->iov_base;
 
 		iov++;
 
-		while(seglen > 0)
-		{
+		while(seglen > 0) {
 			unsigned int actual_win;
 			int copy;
 			int tmp;
@@ -840,142 +821,110 @@
 
 			if (err)
 				return (err);
-			/*
-			 * Stop on errors
-			 */
-			if (sk->err) 
-			{
+
+			/* Stop on errors. */
+			if (sk->err) {
 				if (copied) 
 					return copied;
 				return sock_error(sk);
 			}
 
-			/*
-			 *	Make sure that we are established. 
-			 */
-			if (sk->shutdown & SEND_SHUTDOWN) 
-			{
+			/* Make sure that we are established. */
+			if (sk->shutdown & SEND_SHUTDOWN) {
 				if (copied)
 					return copied;
 				send_sig(SIGPIPE,current,0);
 				return -EPIPE;
 			}
 	
-			/* 
-			 *	Now we need to check if we have a half built packet. 
-			 */
+			/* Now we need to check if we have a half built packet. */
 
-			/* if we have queued packets */
-			if (tp->send_head && !(flags & MSG_OOB) ) 
-			{
+			/* If we have queued packets.. */
+			if (tp->send_head && !(flags & MSG_OOB)) {
 				int tcp_size;
 
 				/* Tail */
 
 				skb = sk->write_queue.prev;
 				tcp_size = skb->tail -
-					(unsigned char *)(skb->h.th + 1);
+					((unsigned char *)(skb->h.th) + tp->tcp_header_len);
 
-				/*
-				 * This window_seq test is somewhat dangerous
+				/* printk("extending buffer\n"); */
+				/* This window_seq test is somewhat dangerous
 				 * If the remote does SWS avoidance we should
 				 * queue the best we can if not we should in 
 				 * fact send multiple packets...
 				 * a method for detecting this would be most
 				 * welcome
 				 */
-
 				if (skb->end > skb->tail &&
 				    sk->mss - tcp_size > 0 &&
-				    tp->snd_nxt < skb->end_seq) 
-				{
+				    tp->snd_nxt < skb->end_seq) {
 					int tcopy;
-					
+
 					tcopy = tcp_append_tail(sk, skb, from,
 							       tcp_size,
 							       seglen);
 					if (tcopy == -1)
-					{
 						return -EFAULT;
-					}
 
 					from += tcopy;
 					copied += tcopy;
 					seglen -= tcopy;
 
-					/*
-					 *	FIXME: if we're nagling we
+					/*	FIXME: if we're nagling we
 					 *	should send here.
 					 */
 					continue;
 				}
 			}
 
-
-		/*
-		 *   We also need to worry about the window.
-	 	 *   If window < 1/2 the maximum window we've seen from this
-	 	 *   host, don't use it.  This is sender side
-	 	 *   silly window prevention, as specified in RFC1122.
-	 	 *   (Note that this is different than earlier versions of
-		 *   SWS prevention, e.g. RFC813.).  What we actually do is
-		 *   use the whole MSS.  Since the results in the right
-		 *   edge of the packet being outside the window, it will
-		 *   be queued for later rather than sent.
-		 */
-
+			/*   We also need to worry about the window.
+			 *   If window < 1/2 the maximum window we've seen from this
+			 *   host, don't use it.  This is sender side
+			 *   silly window prevention, as specified in RFC1122.
+			 *   (Note that this is different than earlier versions of
+			 *   SWS prevention, e.g. RFC813.).  What we actually do is
+			 *   use the whole MSS.  Since the results in the right
+			 *   edge of the packet being outside the window, it will
+			 *   be queued for later rather than sent.
+			 */
 			copy = min(seglen, sk->mss);
-
 			actual_win = tp->snd_wnd - (tp->snd_nxt - tp->snd_una);
 
 			if (copy > actual_win &&
-			    (((int) actual_win) >= (sk->max_window >> 1))
-			    && actual_win)
-			{
+			    (((int) actual_win) >= (tp->max_window >> 1)) &&
+			    actual_win)
 				copy = actual_win;
-			}
 
-			if (copy <= 0)
-			{
+			if (copy <= 0) {
 				printk(KERN_DEBUG "sendmsg: copy < 0\n");
 				return -EIO;
 			}
 
-			/*
-			 *  If sk->packets_out > 0 segment will be nagled
-			 *  else we kick it right away
+			/* If tp->packets_out > 0 segment will be nagled
+			 *  else we kick it right away.
 			 */
-
 			tmp = MAX_HEADER + sk->prot->max_header + 
 				sizeof(struct sk_buff) + 15;
-			if (copy < min(sk->mss, sk->max_window >> 1) && 
-			    !(flags & MSG_OOB) && atomic_read(&sk->packets_out))
-			{
-				tmp += min(sk->mss, sk->max_window);
-			}
+			if (copy < min(sk->mss, tp->max_window >> 1) && 
+			    !(flags & MSG_OOB) && tp->packets_out)
+				tmp += min(sk->mss, tp->max_window);
 			else
-			{
 				tmp += copy;
-			}
 
 			skb = sock_wmalloc(sk, tmp, 0, GFP_KERNEL);
 
-			/*
-			 *	If we didn't get any memory, we need to sleep.
-			 */
-
-			if (skb == NULL)
-			{
+			/* If we didn't get any memory, we need to sleep. */
+			if (skb == NULL) {
 				sk->socket->flags |= SO_NOSPACE;
-				if (flags&MSG_DONTWAIT)
-				{
+				if (flags&MSG_DONTWAIT) {
 					if (copied) 
 						return copied;
 					return -EAGAIN;
 				}
 
-				if (current->signal & ~current->blocked)
-				{
+				if (current->signal & ~current->blocked) {
 					if (copied)
 						return copied;
 					return -ERESTARTSYS;
@@ -985,37 +934,25 @@
 				continue;
 			}
 
-			/*
-			 * FIXME: we need to optimize this.
+			/* FIXME: we need to optimize this.
 			 * Perhaps some hints here would be good.
 			 */
-
 			tmp = tp->af_specific->build_net_header(sk, skb);
-
-			if (tmp < 0)
-			{
+			if (tmp < 0) {
 				kfree_skb(skb, FREE_WRITE);
 				if (copied)
 					return(copied);
 				return(tmp);
 			}
 
-			skb->h.th =(struct tcphdr *) 
-			  skb_put(skb,sizeof(struct tcphdr));
+			skb->h.th =(struct tcphdr *)
+			  skb_put(skb,tp->tcp_header_len);
 
 			seglen -= copy;
-			tmp = tcp_build_header(skb->h.th, sk, seglen || iovlen);
+			tcp_build_header(skb->h.th, sk, seglen || iovlen);
+			/* FIXME: still need to think about SACK options here. */
 
-                        if (tmp < 0) 
-                        {
-                                kfree_skb(skb, FREE_WRITE);
-                                if (copied) 
-                                        return(copied);
-                                return(tmp);
-                        }
-
-			if (flags & MSG_OOB)
-			{
+			if (flags & MSG_OOB) {
 				skb->h.th->urg = 1;
 				skb->h.th->urg_ptr = ntohs(copy);
 			}
@@ -1027,7 +964,7 @@
 			copied += copy;
 
 			sk->write_seq += copy;
-		
+
 			tcp_send_skb(sk, skb);
 
 			release_sock(sk);
@@ -1043,9 +980,6 @@
 	return copied;
 }
 
-
-	
-
 /*
  *	Send an ack if one is backlogged at this point. Ought to merge
  *	this with tcp_send_ack().
@@ -1054,18 +988,15 @@
  
 void tcp_read_wakeup(struct sock *sk)
 {
-	/*
-	 * If we're closed, don't send an ack, or we'll get a RST
+	/* If we're closed, don't send an ack, or we'll get a RST
 	 * from the closed destination.
 	 */
-
 	if ((sk->state == TCP_CLOSE) || (sk->state == TCP_TIME_WAIT))
 		return;
 
 	tcp_send_ack(sk);
 }
 
-
 /*
  *	Handle reading urgent data. BSD has very simple semantics for
  *	this, no blocking and very strange errors 8)
@@ -1078,33 +1009,28 @@
 	int err=0; 
 	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
 
-	/*
-	 *	No URG data to read
-	 */
+	/* No URG data to read. */
 	if (sk->urginline || !sk->urg_data || sk->urg_data == URG_READ)
 		return -EINVAL;	/* Yes this is right ! */
 
 	if (sk->err)
 		return sock_error(sk);
 
-	if (sk->state == TCP_CLOSE || sk->done)
-	{
-		if (!sk->done)
-		{
+	if (sk->state == TCP_CLOSE || sk->done) {
+		if (!sk->done) {
 			sk->done = 1;
 			return 0;
 		}
 		return -ENOTCONN;
 	}
 
-	if (sk->shutdown & RCV_SHUTDOWN)
-	{
+	if (sk->shutdown & RCV_SHUTDOWN) {
 		sk->done = 1;
 		return 0;
 	}
+
 	lock_sock(sk);
-	if (sk->urg_data & URG_VALID)
-	{
+	if (sk->urg_data & URG_VALID) {
 		char c = sk->urg_data;
 		if (!(flags & MSG_PEEK))
 			sk->urg_data = URG_READ;
@@ -1115,23 +1041,20 @@
 			msg->msg_flags|=MSG_TRUNC;
 			
 		if(msg->msg_name)
-		{
 			tp->af_specific->addr2sockaddr(sk, (struct sockaddr *)
 						       msg->msg_name);       
-		}
+
 		if(addr_len)
 			*addr_len = tp->af_specific->sockaddr_len;
-		/* 
-		 *	Read urgent data
-		 */
+
+		/* Read urgent data. */
 		msg->msg_flags|=MSG_OOB;
 		release_sock(sk);
 		return err ? -EFAULT : 1;
 	}
 	release_sock(sk);
 
-	/*
-	 * Fixed the recv(..., MSG_OOB) behaviour.  BSD docs and
+	/* Fixed the recv(..., MSG_OOB) behaviour.  BSD docs and
 	 * the available implementations agree in this case:
 	 * this call should never block, independent of the
 	 * blocking state of the socket.
@@ -1148,7 +1071,7 @@
 
 static inline void tcp_eat_skb(struct sock *sk, struct sk_buff * skb)
 {
-	sk->delayed_acks++;
+	sk->tp_pinfo.af_tcp.delayed_acks++;
 
 	__skb_unlink(skb, &sk->receive_queue);
 	kfree_skb(skb, FREE_READ);
@@ -1159,11 +1082,9 @@
 {
 	struct sk_buff *skb;
 
-	/*
-	 * NOTE! The socket must be locked, so that we don't get
+	/* NOTE! The socket must be locked, so that we don't get
 	 * a messed-up receive queue.
 	 */
-
 	while ((skb=skb_peek(&sk->receive_queue)) != NULL) {
 		if (!skb->used || atomic_read(&skb->users)>1)
 			break;
@@ -1172,13 +1093,10 @@
 
 	SOCK_DEBUG(sk, "sk->rspace = %lu\n", sock_rspace(sk));
 
-  	/*
-  	 *	We send a ACK if the sender is blocked
-  	 *	else let tcp_data deal with the acking policy.
+  	/* We send a ACK if the sender is blocked
+  	 * else let tcp_data deal with the acking policy.
   	 */
-
-	if (sk->delayed_acks)
-	{
+	if (sk->tp_pinfo.af_tcp.delayed_acks) {
 		struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
 		__u32 rcv_wnd;
 
@@ -1209,47 +1127,34 @@
 	if (sk->state == TCP_LISTEN)
 		return -ENOTCONN;
 
-	/*
-	 *	Urgent data needs to be handled specially.
-	 */
-
+	/* Urgent data needs to be handled specially. */
 	if (flags & MSG_OOB)
 		return tcp_recv_urg(sk, nonblock, msg, len, flags, addr_len);
 
-	/*
-	 *	Copying sequence to update. This is volatile to handle
+	/*	Copying sequence to update. This is volatile to handle
 	 *	the multi-reader case neatly (memcpy_to/fromfs might be
 	 *	inline and thus not flush cached variables otherwise).
 	 */
-
 	peek_seq = sk->copied_seq;
 	seq = &sk->copied_seq;
 	if (flags & MSG_PEEK)
 		seq = &peek_seq;
 		
-	/*
-	 *	Handle the POSIX bogosity MSG_WAITALL
-	 */
-	 
+	/* Handle the POSIX bogosity MSG_WAITALL. */
 	if (flags & MSG_WAITALL)
 		target=len;
 
 	add_wait_queue(sk->sleep, &wait);
 	lock_sock(sk);
-	while (len > 0)
-	{
+	while (len > 0) {
 		struct sk_buff * skb;
 		u32 offset;
 
-		/*
-		 * Are we at urgent data? Stop if we have read anything.
-		 */
-
+		/* Are we at urgent data? Stop if we have read anything. */
 		if (copied && sk->urg_data && sk->urg_seq == *seq)
 			break;
 
-		/*
-		 * We need to check signals first, to get correct SIGURG
+		/* We need to check signals first, to get correct SIGURG
 		 * handling. FIXME: Need to check this doesnt impact 1003.1g
 		 * and move it down to the bottom of the loop
 		 */
@@ -1262,20 +1167,16 @@
 			break;
 		}
 
-		/*
-		 *	Next get a buffer.
-		 */
-
+		/* Next get a buffer. */
 		current->state = TASK_INTERRUPTIBLE;
 
 		skb = skb_peek(&sk->receive_queue);
-		do
-		{
+		do {
 			if (!skb)
 				break;
-			/* 
-			 * now that we have two receive queues this 
-			 * shouldn't happen
+
+			/* Now that we have two receive queues this 
+			 * shouldn't happen.
 			 */
 			if (before(*seq, skb->seq)) {
 				printk(KERN_INFO "recvmsg bug: copied %X seq %X\n",
@@ -1292,22 +1193,18 @@
 			if (!(flags & MSG_PEEK))
 				skb->used = 1;
 			skb = skb->next;
-		}
-		while (skb != (struct sk_buff *)&sk->receive_queue);
+		} while (skb != (struct sk_buff *)&sk->receive_queue);
 
 		if (copied >= target)
 			break;
 
-		if (sk->err && !(flags&MSG_PEEK))
-		{
+		if (sk->err && !(flags&MSG_PEEK)) {
 			copied = sock_error(sk);
 			break;
 		}
 
-		if (sk->state == TCP_CLOSE)
-		{
-			if (!sk->done)
-			{
+		if (sk->state == TCP_CLOSE) {
+			if (!sk->done) {
 				sk->done = 1;
 				break;
 			}
@@ -1315,14 +1212,12 @@
 			break;
 		}
 
-		if (sk->shutdown & RCV_SHUTDOWN)
-		{
+		if (sk->shutdown & RCV_SHUTDOWN) {
 			sk->done = 1;
 			break;
 		}
 
-		if (nonblock)
-		{
+		if (nonblock) {
 			copied = -EAGAIN;
 			break;
 		}
@@ -1336,65 +1231,46 @@
 		continue;
 
 	found_ok_skb:
-		/*
-		 *	Lock the buffer. We can be fairly relaxed as
+		/*	Lock the buffer. We can be fairly relaxed as
 		 *	an interrupt will never steal a buffer we are
 		 *	using unless I've missed something serious in
 		 *	tcp_data.
 		 */
-
 		atomic_inc(&skb->users);
 
-		/*
-		 *	Ok so how much can we use ?
-		 */
-
+		/* Ok so how much can we use? */
 		used = skb->len - offset;
 		if (len < used)
 			used = len;
-		/*
-		 *	Do we have urgent data here?
-		 */
 
-		if (sk->urg_data)
-		{
+		/* Do we have urgent data here? */
+		if (sk->urg_data) {
 			u32 urg_offset = sk->urg_seq - *seq;
-			if (urg_offset < used)
-			{
-				if (!urg_offset)
-				{
-					if (!sk->urginline)
-					{
+			if (urg_offset < used) {
+				if (!urg_offset) {
+					if (!sk->urginline) {
 						++*seq;
 						offset++;
 						used--;
 					}
-				}
-				else
+				} else
 					used = urg_offset;
 			}
 		}
 
-		/*
-		 *	Copy it - We _MUST_ update *seq first so that we
+		/*	Copy it - We _MUST_ update *seq first so that we
 		 *	don't ever double read when we have dual readers
 		 */
-
 		*seq += used;
 
-		/*
-		 *	This memcpy_toiovec can sleep. If it sleeps and we
+		/*	This memcpy_toiovec can sleep. If it sleeps and we
 		 *	do a second read it relies on the skb->users to avoid
 		 *	a crash when cleanup_rbuf() gets called.
 		 */
-
 		err = memcpy_toiovec(msg->msg_iov, ((unsigned char *)skb->h.th) + skb->h.th->doff*4 + offset, used);
 		
-		if (err)
-		{
-			/*
-			 *	exception. bailout!
-			 */
+		if (err) {
+			/* Exception. Bailout! */
 			*seq -= err;
 			atomic_dec(&skb->users);
 			copied = -EFAULT;
@@ -1404,12 +1280,10 @@
 		copied += used;
 		len -= used;
 
-		/*
-		 *	We now will not sleep again until we are finished
+		/*	We now will not sleep again until we are finished
 		 *	with skb. Sorry if you are doing the SMP port
 		 *	but you'll just have to fix it neatly ;)
 		 */
-
 		atomic_dec(&skb->users);
 
 		if (after(sk->copied_seq,sk->urg_seq))
@@ -1417,11 +1291,9 @@
 		if (used + offset < skb->len)
 			continue;
 
-		/*
-		 *	Process the FIN. We may also need to handle PSH
-		 *	here and make it break out of MSG_WAITALL
+		/*	Process the FIN. We may also need to handle PSH
+		 *	here and make it break out of MSG_WAITALL.
 		 */
-
 		if (skb->h.th->fin)
 			goto found_fin_ok;
 		if (flags & MSG_PEEK)
@@ -1436,35 +1308,28 @@
 		if (flags & MSG_PEEK)
 			break;
 
-		/*
-		 *	All is done
-		 */
-
+		/* All is done. */
 		skb->used = 1;
 		sk->shutdown |= RCV_SHUTDOWN;
 		break;
-
 	}
 
 	if(copied > 0 && msg->msg_name)
-	{
 		tp->af_specific->addr2sockaddr(sk, (struct sockaddr *)
 					       msg->msg_name);       
-	}
+
 	if(addr_len)
 		*addr_len = tp->af_specific->sockaddr_len;
 
 	remove_wait_queue(sk->sleep, &wait);
 	current->state = TASK_RUNNING;
 
-	/* Clean up data we have read: This will do ACK frames */
+	/* Clean up data we have read: This will do ACK frames. */
 	cleanup_rbuf(sk);
 	release_sock(sk);
 	return copied;
 }
 
-
-
 /*
  *	State processing on a close. This implements the state shift for
  *	sending our FIN frame. Note that we only send a FIN for some
@@ -1476,8 +1341,7 @@
 {
 	int ns=TCP_CLOSE;
 	int send_fin=0;
-	switch(sk->state)
-	{
+	switch(sk->state) {
 		case TCP_SYN_SENT:	/* No SYN back, no FIN needed */
 			break;
 		case TCP_SYN_RECV:
@@ -1498,12 +1362,11 @@
 					   wait only for the ACK */
 			ns=TCP_LAST_ACK;
 			send_fin=1;
-	}
+	};
 
 	tcp_set_state(sk,ns);
 
-	/*
-	 *	This is a (useful) BSD violating of the RFC. There is a
+	/*	This is a (useful) BSD violating of the RFC. There is a
 	 *	problem with TCP as specified in that the other end could
 	 *	keep a socket open forever with no application left this end.
 	 *	We use a 3 minute timeout (about the same as BSD) then kill
@@ -1511,8 +1374,7 @@
 	 *	that we won't make the old 4*rto = almost no time - whoops
 	 *	reset mistake.
 	 */
-	if(dead && ns==TCP_FIN_WAIT2)
-	{
+	if(dead && ns==TCP_FIN_WAIT2) {
 		int timer_active=del_timer(&sk->timer);
 		if(timer_active)
 			add_timer(&sk->timer);
@@ -1530,50 +1392,29 @@
 
 void tcp_shutdown(struct sock *sk, int how)
 {
-	/*
-	 *	We need to grab some memory, and put together a FIN,
+	/*	We need to grab some memory, and put together a FIN,
 	 *	and then put it into the queue to be sent.
 	 *		Tim MacKenzie(tym@dibbler.cs.monash.edu.au) 4 Dec '92.
 	 */
-
 	if (!(how & SEND_SHUTDOWN))
 		return;
 
-	/*
-	 *	If we've already sent a FIN, or it's a closed state
-	 */
-
-	if (sk->state == TCP_FIN_WAIT1 ||
-	    sk->state == TCP_FIN_WAIT2 ||
-	    sk->state == TCP_CLOSING ||
-	    sk->state == TCP_LAST_ACK ||
-	    sk->state == TCP_TIME_WAIT ||
-	    sk->state == TCP_CLOSE ||
-	    sk->state == TCP_LISTEN
-	  )
-	{
-		return;
-	}
-	lock_sock(sk);
-
-	/*
-	 * flag that the sender has shutdown
-	 */
-
-	sk->shutdown |= SEND_SHUTDOWN;
-
-	/*
-	 *  Clear out any half completed packets. 
-	 */
+	/* If we've already sent a FIN, or it's a closed state, skip this. */
+	if (sk->state == TCP_ESTABLISHED	||
+	    sk->state == TCP_SYN_SENT		||
+	    sk->state == TCP_SYN_RECV		||
+	    sk->state == TCP_CLOSE_WAIT) {
+		lock_sock(sk);
 
-	/*
-	 *	FIN if needed
-	 */
+		/* Flag that the sender has shutdown. */
+		sk->shutdown |= SEND_SHUTDOWN;
 
-	if (tcp_close_state(sk,0))
-		tcp_send_fin(sk);
+		/* Clear out any half completed packets.  FIN if needed. */
+		if (tcp_close_state(sk,0))
+			tcp_send_fin(sk);
 
-	release_sock(sk);
+		release_sock(sk);
+	}
 }
 
 
@@ -1588,7 +1429,7 @@
 		case TCP_CLOSING:
 		case TCP_LAST_ACK:
 			return 1;
-	}
+	};
 	return 0;
 }
 
@@ -1597,16 +1438,12 @@
 {
 	struct sk_buff *skb;
 
-	/*
-	 * We need to grab some memory, and put together a FIN,
+	/* We need to grab some memory, and put together a FIN,
 	 * and then put it into the queue to be sent.
 	 */
-
 	lock_sock(sk);
-
-	if(sk->state == TCP_LISTEN)
-	{
-		/* Special case */
+	if(sk->state == TCP_LISTEN) {
+		/* Special case. */
 		tcp_set_state(sk, TCP_CLOSE);
 		tcp_close_pending(sk);
 		release_sock(sk);
@@ -1621,37 +1458,27 @@
 	if (!sk->dead)
 	  	sk->state_change(sk);
 
-	/*
-	 *  We need to flush the recv. buffs.  We do this only on the
+	/*  We need to flush the recv. buffs.  We do this only on the
 	 *  descriptor close, not protocol-sourced closes, because the
 	 *  reader process may not have drained the data yet!
 	 */
-		 
 	while((skb=skb_dequeue(&sk->receive_queue))!=NULL)
 		kfree_skb(skb, FREE_READ);
 
-		
-	/*
-	 *	Timeout is not the same thing - however the code likes
-	 *	to send both the same way (sigh).
+	/*  Timeout is not the same thing - however the code likes
+	 *  to send both the same way (sigh).
 	 */
-	 
 	if (tcp_close_state(sk,1)==1)
-	{
 		tcp_send_fin(sk);
-	}
 
 	if (timeout) {
 		cli();
 		release_sock(sk);
 		current->timeout = timeout;
-		while(closing(sk) && current->timeout)
-		{
+		while(closing(sk) && current->timeout) {
 			interruptible_sleep_on(sk->sleep);
 			if (current->signal & ~current->blocked)
-			{
 				break;
-			}
 		}
 		current->timeout=0;
 		lock_sock(sk);
@@ -1661,8 +1488,7 @@
 	/* Now that the socket is dead, if we are in the FIN_WAIT2 state
 	 * we may need to set up a timer.
          */
-	if (sk->state==TCP_FIN_WAIT2)
-	{
+	if (sk->state==TCP_FIN_WAIT2) {
 		int timer_active=del_timer(&sk->timer);
 		if(timer_active)
 			add_timer(&sk->timer);
@@ -1677,7 +1503,6 @@
 		sk->prot->unhash(sk);
 }
 
-
 /*
  *	Wait for an incoming connection, avoid race
  *	conditions. This must be called with the socket locked.
@@ -1703,7 +1528,6 @@
 	return req;
 }
 
-
 /*
  *	This will accept the next outstanding connection.
  *
@@ -1751,7 +1575,6 @@
 	goto out;
 }
 
-
 /*
  *	Socket option code for TCP. 
  */
@@ -1772,11 +1595,9 @@
   	if (get_user(val, (int *)optval))
 		return -EFAULT;
 
-	switch(optname)
-	{
+	switch(optname) {
 		case TCP_MAXSEG:
-/*
- * values greater than interface MTU won't take effect.  however at
+/* values greater than interface MTU won't take effect.  however at
  * the point when this call is done we typically don't yet know
  * which interface is going to be used
  */
@@ -1789,7 +1610,7 @@
 			return 0;
 		default:
 			return(-ENOPROTOOPT);
-	}
+	};
 }
 
 int tcp_getsockopt(struct sock *sk, int level, int optname, char *optval, 
@@ -1800,18 +1621,15 @@
 	int len;
 
 	if(level != SOL_TCP)
-	{
 		return tp->af_specific->getsockopt(sk, level, optname,
 						   optval, optlen);
-	}
 	
 	if(get_user(len,optlen))
 		return -EFAULT;
 		
-	len=min(len,sizeof(int));
+	len = min(len,sizeof(int));
 
-	switch(optname)
-	{
+	switch(optname) {
 		case TCP_MAXSEG:
 			val=sk->user_mss;
 			break;
@@ -1820,7 +1638,7 @@
 			break;
 		default:
 			return(-ENOPROTOOPT);
-	}
+	};
 
   	if(put_user(len, optlen))
   		return -EFAULT;
@@ -1832,13 +1650,9 @@
 void tcp_set_keepalive(struct sock *sk, int val)
 {
 	if (!sk->keepopen && val)
-	{
 		tcp_inc_slow_timer(TCP_SLT_KEEPALIVE);
-	}
 	else if (sk->keepopen && !val)
-	{
 		tcp_dec_slow_timer(TCP_SLT_KEEPALIVE);
-	}
 }
 
 void tcp_init(void)
diff -u --recursive --new-file v2.1.35/linux/net/ipv4/tcp_input.c linux/net/ipv4/tcp_input.c
--- v2.1.35/linux/net/ipv4/tcp_input.c	Mon Apr 14 16:28:28 1997
+++ linux/net/ipv4/tcp_input.c	Tue Apr 22 22:46:28 1997
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp_input.c,v 1.42 1997/04/12 04:32:24 davem Exp $
+ * Version:	$Id: tcp_input.c,v 1.50 1997/04/22 02:53:12 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -57,6 +57,12 @@
 				 u32 seq_rtt);
 
 int sysctl_tcp_cong_avoidance = 0;
+int sysctl_tcp_hoe_retransmits = 0;
+int sysctl_tcp_sack = 0;
+int sysctl_tcp_tsack = 0;
+int sysctl_tcp_timestamps = 0;
+int sysctl_tcp_window_scaling = 0;
+ 
 
 static tcp_sys_cong_ctl_t tcp_sys_cong_ctl_f = &tcp_cong_avoid_vanj;
 
@@ -72,9 +78,7 @@
 {
 	int m;
 
-	/*
-	 *	Delayed ACK time estimator.
-	 */
+	/* Delayed ACK time estimator. */
 	
 	m = jiffies - tp->lrcvtime;
 
@@ -83,12 +87,10 @@
 	if (m < 0)
 		return;
 
-	/*
-	 * if the mesured value is bigger than
+	/* if the mesured value is bigger than
 	 * twice the round trip time ignore it.
 	 */
-	if ((m << 2) <= tp->srtt) 
-	{
+	if ((m << 2) <= tp->srtt) {
 		m -= (tp->iat >> 3);
 		tp->iat += m;
 
@@ -102,18 +104,21 @@
 
 		if (tp->ato < HZ/50)
 			tp->ato = HZ/50;
-	}
-	else
+	} else
 		tp->ato = 0;
 }
 
-/*
- *	Called on frames that were known _not_ to have been
- *	retransmitted [see Karn/Partridge Proceedings SIGCOMM 87]. 
- *	The algorithm is from the SIGCOMM 88 piece by Van Jacobson.
+/* Called to compute a smoothed rtt estimate. The data fed to this
+ * routine either comes from timestamps, or from segments that were
+ * known _not_ to have been retransmitted [see Karn/Partridge
+ * Proceedings SIGCOMM 87]. The algorithm is from the SIGCOMM 88
+ * piece by Van Jacobson.
+ * NOTE: the next three routines used to be one big routine.
+ * To save cycles in the RFC 1323 implementation it was better to break
+ * it up into three procedures. -- erics
  */
 
-extern __inline__ void tcp_rtt_estimator(struct tcp_opt *tp, __u32 mrtt)
+static __inline__ void tcp_rtt_estimator(struct tcp_opt *tp, __u32 mrtt)
 {
 	long m;
 	/*
@@ -122,8 +127,7 @@
 	 *	are scaled versions of rtt and mean deviation.
 	 *	This is designed to be as fast as possible 
 	 *	m stands for "measurement".
-	 */
-	/*
+	 *
 	 *	On a 1990 paper the rto value is changed to:
 	 *	RTO = rtt + 4 * mdev
 	 */
@@ -140,44 +144,73 @@
 		m -= (tp->mdev >> 2);   /* similar update on mdev */
 		tp->mdev += m;	    	/* mdev = 3/4 mdev + 1/4 new */
 	} else {
-					/* no previous measure. */
+		/* no previous measure. */
 		tp->srtt = m<<3;	/* take the measured time to be rtt */
 		tp->mdev = m<<2;	/* make sure rto = 3*rtt */
 	}
+}
 
+/* Calculate rto without backoff. This is the second half of Van Jacobsons
+ * routine refered to above.
+ */
 
-	/*
-	 *	Now update timeout.  Note that this removes any backoff.
-	 */
-			 
+static __inline__ void tcp_set_rto(struct tcp_opt *tp)
+{
 	tp->rto = (tp->srtt >> 3) + tp->mdev;
 	tp->rto += (tp->rto >> 2) + (tp->rto >> (tp->snd_cwnd-1));
+}
+ 
 
+/* Keep the rto between HZ/5 and 120*HZ. 120*HZ is the upper bound
+ * on packet lifetime in the internet. We need the HZ/5 lower
+ * bound to behave correctly against BSD stacks with a fixed
+ * delayed ack.
+ * FIXME: It's not entirely clear this lower bound is the best
+ * way to avoid the problem. Is it possible to drop the lower
+ * bound and still avoid trouble with BSD stacks? Perhaps
+ * some modification to the RTO calculation that takes delayed
+ * ack bais into account? This needs serious thought. -- erics
+ */
 
+static __inline__ void tcp_bound_rto(struct tcp_opt *tp)
+{
 	if (tp->rto > 120*HZ)
 		tp->rto = 120*HZ;
-
-	/* Was 1*HZ - keep .2 as minimum cos of the BSD delayed acks 
-	 * FIXME: It's not entirely clear this lower bound is the best
-	 * way to avoid the problem. Is it possible to drop the lower
-	 * bound and still avoid trouble with BSD stacks? Perhaps
-	 * some modification to the RTO calculation that takes delayed
-	 * ack bais into account? This needs serious thought. -- erics
-	 */
 	if (tp->rto < HZ/5)
 		tp->rto = HZ/5;
+}
+
+/* WARNING: this must not be called if tp->saw_timestamp was false. */
+
+extern __inline__ void tcp_replace_ts_recent(struct tcp_opt *tp, __u32 end_seq)
+{
+	/* From draft-ietf-tcplw-high-performance: the correct
+	 * test is last_ack_sent <= end_seq.
+	 * (RFC1323 stated last_ack_sent < end_seq.)
+	 */
+	if (!before(end_seq,tp->last_ack_sent)) {
+		tp->ts_recent = tp->rcv_tsval;
+		/* FIXME: need a corse timestamp. Days uptime
+		 * would be good.
+		 */
+		tp->ts_recent_stamp = jiffies;
+	}
+}
 
-	tp->backoff = 0;
+extern __inline__ int tcp_paws_discard(struct tcp_opt *tp)
+{
+	/* FIXME: must check that ts_recent is not
+ 	 * more than 24 days old here. Yuck.
+ 	 */
+	return (tp->rcv_tsval-tp->ts_recent < 0);
 }
 
+
 static int __tcp_sequence(struct tcp_opt *tp, u32 seq, u32 end_seq)
 {
-	u32 end_window;
+	u32 end_window = tp->rcv_wup + tp->rcv_wnd;
 
-	end_window = tp->rcv_wup + tp->rcv_wnd;
-
-	if (tp->rcv_wnd)
-	{
+	if (tp->rcv_wnd) {
 		if (!before(seq, tp->rcv_nxt) && before(seq, end_window))
 			return 1;
 
@@ -196,9 +229,8 @@
 extern __inline__ int tcp_sequence(struct tcp_opt *tp, u32 seq, u32 end_seq)
 {
 	if (seq == tp->rcv_nxt)
-	{
 		return (tp->rcv_wnd || (end_seq == seq));
-	}
+
 	return __tcp_sequence(tp, seq, end_seq);
 }
 
@@ -210,9 +242,8 @@
 static int tcp_reset(struct sock *sk, struct sk_buff *skb)
 {
 	sk->zapped = 1;
-	/*
-	 *	We want the right error as BSD sees it (and indeed as we do).
-	 */
+
+	/* We want the right error as BSD sees it (and indeed as we do). */
 	switch (sk->state) {
 		case TCP_TIME_WAIT:
 			break;
@@ -224,7 +255,7 @@
 			break;
 		default:
 			sk->err = ECONNRESET;
-	}
+	};
 #ifdef CONFIG_TCP_RFC1337
 	/*
 	 *	Time wait assassination protection [RFC1337]
@@ -234,8 +265,7 @@
 	 *	Ian Heavens has since shown this is an inadequate fix for the protocol
 	 *	bug in question.
 	 */
-	if(sk->state!=TCP_TIME_WAIT)
-	{	
+	if(sk->state!=TCP_TIME_WAIT) {
 		tcp_set_state(sk,TCP_CLOSE);
 		sk->shutdown = SHUTDOWN_MASK;
 	}
@@ -249,34 +279,30 @@
 	return(0);
 }
 
-
 /*
- *	Look for tcp options. Parses everything but only knows about MSS.
- *	This routine is always called with the packet containing the SYN.
- *	However it may also be called with the ack to the SYN.  So you
- *	can't assume this is always the SYN.  It's always called after
- *	we have set up sk->mtu to our own MTU.
- *
- *	We need at minimum to add PAWS support here. Possibly large windows
- *	as Linux gets deployed on 100Mb/sec networks.
+ *	Look for tcp options. Normally only called on SYN and SYNACK packets.
+ *	But, this can also be called on packets in the established flow when
+ *	the fast version below fails.
+ *	FIXME: surely this can be more efficient. -- erics
  */
  
-int tcp_parse_options(struct tcphdr *th)
+void tcp_parse_options(struct tcphdr *th, struct tcp_opt *tp)
 {
 	unsigned char *ptr;
 	int length=(th->doff*4)-sizeof(struct tcphdr);
-	int mss = 0;
 
 	ptr = (unsigned char *)(th + 1);
+	tp->sacks = 0;
+	tp->saw_tstamp = 0;
 
-	while(length>0)
-	{
+	while(length>0) {
 	  	int opcode=*ptr++;
 	  	int opsize=*ptr++;
-	  	switch(opcode)
-	  	{
+		if (length - opsize < 0)	/* Don't parse partial options */
+			break;
+	  	switch(opcode) {
 	  		case TCPOPT_EOL:
-	  			return 0;
+	  			return;
 	  		case TCPOPT_NOP:	/* Ref: RFC 793 section 3.1 */
 	  			length--;
 	  			ptr--;		/* the opsize=*ptr++ above was a mistake */
@@ -284,25 +310,86 @@
 	  		
 	  		default:
 	  			if(opsize<=2)	/* Avoid silly options looping forever */
-	  				return 0;
-	  			switch(opcode)
-	  			{
+	  				return;
+	  			switch(opcode) {
 	  				case TCPOPT_MSS:
-	  					if(opsize==TCPOLEN_MSS && th->syn)
-	  					{
-							mss = ntohs(*(unsigned short *)ptr);
-	  					}
+	  					if(opsize==TCPOLEN_MSS && th->syn) {
+							tp->in_mss = ntohs(*(__u16 *)ptr);
+							if (tp->in_mss == 0)
+								tp->in_mss = 536;
+						}
 	  					break;
-		  				/* Add other options here as people feel the urge to implement stuff like large windows */
+					case TCPOPT_WINDOW:
+	  					if(opsize==TCPOLEN_WINDOW && th->syn)
+							if (sysctl_tcp_window_scaling)
+								tp->snd_wscale = *(__u8 *)ptr;
+						break;
+					case TCPOPT_SACK_PERM:
+	  					if(opsize==TCPOLEN_SACK_PERM && th->syn)
+							if (sysctl_tcp_sack)
+								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)
+								tp->tstamp_ok = 1;
+							tp->saw_tstamp = 1;
+							tp->rcv_tsval = ntohl(*(__u32 *)ptr);
+							tp->rcv_tsecr = ntohl(*(__u32 *)(ptr+4));
+						}
+						break;
+					case TCPOPT_SACK:
+						tp->sacks = (opsize-2)>>3;
+						if (tp->sacks<<3 == opsize-2) {
+							int i;
+							for (i = 0; i < tp->sacks; i++) {
+								tp->left_sack[i] = ntohl(((__u32 *)ptr)[2*i]);
+								tp->right_sack[i] = ntohl(((__u32 *)ptr)[2*i+1]);
+							}
+						} else
+							tp->sacks = 0;
 	  			}
 	  			ptr+=opsize-2;
 	  			length-=opsize;
-	  	}
+	  	};
 	}
+}
 
-	return mss;
+/* Fast parse options. This hopes to only see timestamps.
+ * If it is wrong it falls back on tcp_parse_option().
+ * This should probably get extended for timestamps + SACK as well.
+ * Assembly code anyone? -- erics
+ */
+static __inline__ int tcp_fast_parse_options(struct tcphdr *th, struct tcp_opt *tp)
+{
+	if (tp->tcp_header_len == sizeof(struct tcphdr))
+		return 0;
+	if (th->doff == sizeof(struct tcphdr)>>2) {
+		tp->saw_tstamp = 0;
+		tp->sacks = 0;
+		return 0;
+	} else if (th->doff == (sizeof(struct tcphdr)>>2)+3) {
+		__u32 *ptr = (__u32 *)(th + 1);
+		if (*ptr == htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16)
+				  | (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP)) {
+			tp->saw_tstamp = 1;
+			tp->sacks = 0;
+			tp->rcv_tsval = ntohl(*++ptr);
+			tp->rcv_tsecr = ntohl(*++ptr);
+			return 1;
+		}
+	}
+	tcp_parse_options(th,tp);
+	return 1;
 }
 
+#if 0
+
+/*
+ * This is the old fast retransmit code. It will go away eventually. -- erics
+ */
 
 /* 
  *  See draft-stevens-tcpca-spec-01 for documentation.
@@ -332,62 +419,170 @@
 	 *     The packet acked data after high_seq;
 	 */
 
-	if (ack == tp->snd_una && atomic_read(&sk->packets_out) && (not_dup == 0))
-	{
-		/*
-		 * 1. When the third duplicate ack is received, set ssthresh 
-		 * to one half the current congestion window, but no less 
-		 * than two segments. Retransmit the missing segment.
+	if (ack == tp->snd_una && tp->packets_out && (not_dup == 0)) {
+		/* 1. When the third duplicate ack is received, set ssthresh 
+		 *    to one half the current congestion window, but no less 
+		 *    than two segments. Retransmit the missing segment.
 		 */
+		if (tp->high_seq == 0 || after(ack, tp->high_seq)) {
+			tp->dup_acks++;
 
-		if (tp->high_seq == 0 || after(ack, tp->high_seq))
-		{
-			sk->dup_acks++;
-
-			if (sk->dup_acks == 3)
-			{
-				sk->ssthresh = max(tp->snd_cwnd >> 1, 2);
-				tp->snd_cwnd = sk->ssthresh + 3;
+			if (tp->dup_acks == 3) {
+				tp->snd_ssthresh = max(tp->snd_cwnd >> 1, 2);
+				tp->snd_cwnd = tp->snd_ssthresh + 3;
 				tcp_do_retransmit(sk, 0);
-				/* careful not to timeout just after fast
+
+				/* Careful not to timeout just after fast
 				 * retransmit!
 				 */
-				tcp_reset_xmit_timer(sk, TIME_RETRANS,
-						     tp->rto);
+				tcp_reset_xmit_timer(sk, TIME_RETRANS, tp->rto);
 			}
 		}
 
-		/*
-		 * 2. Each time another duplicate ACK arrives, increment 
-		 * cwnd by the segment size. [...] Transmit a packet...
+		/* 2. Each time another duplicate ACK arrives, increment 
+		 *    cwnd by the segment size. [...] Transmit a packet...
 		 *
-		 * Packet transmission will be done on normal flow processing
-		 * since we're not in "retransmit mode"
+		 *    Packet transmission will be done on normal flow processing
+		 *    since we're not in "retransmit mode".
 		 */
-
-		if (sk->dup_acks >= 3)
-		{
-			sk->dup_acks++;
+		if (tp->dup_acks >= 3) {
+			tp->dup_acks++;
 			tp->snd_cwnd++;
 		}
-	}
-	else
-	{
-		/*
-		 * 3. When the next ACK arrives that acknowledges new data,
-		 *    set cwnd to ssthresh
+	} else {
+		/* 3. When the next ACK arrives that acknowledges new data,
+		 *    set cwnd to ssthresh.
 		 */
-
-		if (sk->dup_acks >= 3)
-		{
+		if (tp->dup_acks >= 3) {
 			tp->retrans_head = NULL;
-			tp->snd_cwnd = max(sk->ssthresh, 1);
-			atomic_set(&sk->retransmits, 0);
+			tp->snd_cwnd = max(tp->snd_ssthresh, 1);
+			tp->retransmits = 0;
 		}
-		sk->dup_acks = 0;
+		tp->dup_acks = 0;
+
+		/* FIXME: This is wrong if the new ack that arrives
+		 * is below the value for high_seq.
+		 */
 		tp->high_seq = 0;
 	}
 }
+#endif
+
+#define FLAG_DATA		0x01
+#define FLAG_WIN_UPDATE		0x02
+#define FLAG_DATA_ACKED		0x04
+
+static __inline__ void clear_fast_retransmit(struct sock *sk) {
+	struct tcp_opt *tp=&(sk->tp_pinfo.af_tcp);
+	if (tp->dup_acks > 3) {
+		tp->retrans_head = NULL;
+		tp->snd_cwnd = max(tp->snd_ssthresh, 1);
+	}
+	tp->dup_acks = 0;
+}
+
+/*
+ * NOTE: This code assumes that tp->dup_acks gets cleared when a
+ * retransmit timer fires.
+ */
+
+static void tcp_fast_retrans(struct sock *sk, u32 ack, int not_dup)
+{
+	struct tcp_opt *tp=&(sk->tp_pinfo.af_tcp);
+
+	/*
+	 * Note: If not_dup is set this implies we got a
+	 * data carrying packet or a window update.
+	 * This carries no new information about possible
+	 * lost packets, so we have to ignore it for the purposes
+	 * of counting duplicate acks. Ideally this does not imply we
+	 * should stop our fast retransmit phase, more acks may come
+	 * later without data to help us. Unfortunately this would make
+	 * the code below much more complex. For now if I see such
+	 * a packet I clear the fast retransmit phase.
+	 */
+
+	if (ack == tp->snd_una && tp->packets_out && (not_dup == 0)) {
+		/* This is the standard reno style fast retransmit branch. */
+
+                /* 1. When the third duplicate ack is received, set ssthresh 
+                 * to one half the current congestion window, but no less 
+                 * than two segments. Retransmit the missing segment.
+                 */
+		if (tp->high_seq == 0 || after(ack, tp->high_seq)) {
+			tp->dup_acks++;
+			if (tp->dup_acks == 3) {
+				tp->dup_acks++;
+                                tp->snd_ssthresh = max(tp->snd_cwnd >> 1, 2);
+                                tp->snd_cwnd = tp->snd_ssthresh + 3;
+				tp->high_seq = tp->snd_nxt;
+                                tcp_do_retransmit(sk, 0);
+                                tcp_reset_xmit_timer(sk, TIME_RETRANS, tp->rto);
+			}
+		}
+
+                /* 2. Each time another duplicate ACK arrives, increment 
+                 * cwnd by the segment size. [...] Transmit a packet...
+                 *
+                 * Packet transmission will be done on normal flow processing
+                 * since we're not in "retransmit mode"
+                 */
+                if (tp->dup_acks > 3)
+                        tp->snd_cwnd++;
+	} else if (tp->high_seq != 0) {
+		/* In this branch we deal with clearing the Floyd style
+		 * block on duplicate fast retransmits, and if requested
+		 * we do Hoe style secondary fast retransmits.
+		 */
+		if (!before(ack,tp->high_seq) || (not_dup&FLAG_DATA) != 0) {
+			/* Once we have acked all the packets up to high_seq
+			 * we are done this fast retransmit phase.
+			 * Alternatively data arrived. In this case we
+			 * Have to abort the fast retransmit attempt.
+			 * Note that we do want to accept a window
+			 * update since this is expected with Hoe's algorithm.
+			 */
+			clear_fast_retransmit(sk);
+
+			/* After we have cleared up to high_seq we can
+			 * clear the Floyd style block.
+			 */
+			if (after(ack,tp->high_seq))
+				tp->high_seq = 0;
+		} else if (tp->dup_acks >= 3) {
+			if (sysctl_tcp_hoe_retransmits) {
+				/* Hoe Style. We didn't ack the whole
+				 * window. Take this as a cue that
+				 * another packet was lost and retransmit it.
+				 * Don't muck with the congestion window here.
+				 * Note that we have to be careful not to
+				 * act if this was a window update and it
+				 * didn't ack new data, since this does
+				 * not indicate a packet left the system.
+				 * We can test this by just checking
+				 * if ack changed from snd_una, since
+				 * the only way to get here without changing
+				 * advancing from snd_una is if this was a
+				 * window update.
+				 */
+				if (ack != tp->snd_una && before(ack,tp->high_seq)) {
+                                	tcp_do_retransmit(sk, 0);
+                                	tcp_reset_xmit_timer(sk, TIME_RETRANS,
+						tp->rto);
+				}
+			} else {
+				/* Reno style. We didn't ack the whole
+				 * window, now we have to drop out of
+				 * fast retransmit and wait for a timeout.
+				 */
+				clear_fast_retransmit(sk);
+			}
+		}
+	} else {
+		/* Clear any aborted fast retransmit starts. */
+		tp->dup_acks = 0;
+	}
+}
 
 /*
  *      TCP slow start and congestion avoidance in two flavors:
@@ -401,24 +596,20 @@
 static void tcp_cong_avoid_vegas(struct sock *sk, u32 seq, u32 ack,
 				 u32 seq_rtt)
 {
-	struct tcp_opt * tp;
+	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
 	unsigned int actual, expected;
 	unsigned int inv_rtt, inv_basertt, inv_basebd;
 	u32 snt_bytes;
 
-	/*
-	 *	From:
+	/*	From:
 	 *      TCP Vegas: New Techniques for Congestion 
 	 *	Detection and Avoidance.
 	 *
-	 *
 	 *	Warning: This code is a scratch implementation taken
 	 *	from the paper only. The code they distribute seams
 	 *	to have improved several things over the initial spec.
 	 */
 
-	tp = &(sk->tp_pinfo.af_tcp);
-
 	if (!seq_rtt)
 		seq_rtt = 1;
 
@@ -427,11 +618,8 @@
 	else
 		tp->basertt = seq_rtt;
 
-	/*
-	 * 
-	 *	actual	 = throughput for this segment.
+	/*	actual	 = throughput for this segment.
 	 *	expected = number_of_bytes in transit / BaseRTT
-	 * 
 	 */
 
 	snt_bytes = ack - seq;
@@ -443,55 +631,36 @@
 
 	expected = (tp->snd_nxt - tp->snd_una) * inv_basertt;
 
+	/* XXX sk->mss should move into tcp_opt as well -DaveM */
 	inv_basebd = sk->mss * inv_basertt;
 
-	/*
-	 *      Slow Start
-	 */
-	
-	if (tp->snd_cwnd < sk->ssthresh &&
+	/* Slow Start */
+	if (tp->snd_cwnd < tp->snd_ssthresh &&
 	    (seq == tp->snd_nxt ||
-	     (expected - actual <= TCP_VEGAS_GAMMA * inv_basebd)))
-	{
-		/*
-		 * "Vegas allows exponential growth only every other
-		 *  RTT"
-		 */
-			
-		if (sk->cong_count++)
-		{
+	     (expected - actual <= TCP_VEGAS_GAMMA * inv_basebd))) {
+		/* "Vegas allows exponential growth only every other RTT" */
+		if (tp->snd_cwnd_cnt++) {
 			tp->snd_cwnd++;
-			sk->cong_count = 0;
+			tp->snd_cwnd_cnt = 0;
 		}
-	}
-	else 
-	{
-		/*
-		 *      Congestion Avoidance
-		 */
-
-		if (expected - actual <= TCP_VEGAS_ALPHA * inv_basebd)
-		{
+	} else {
+		/* Congestion Avoidance */
+		if (expected - actual <= TCP_VEGAS_ALPHA * inv_basebd) {
 			/* Increase Linearly */
-				
-			if (sk->cong_count++ >= tp->snd_cwnd)
-			{
+			if (tp->snd_cwnd_cnt++ >= tp->snd_cwnd) {
 				tp->snd_cwnd++;
-				sk->cong_count = 0;
+				tp->snd_cwnd_cnt = 0;
 			}
 		}
 
-		if (expected - actual >= TCP_VEGAS_BETA * inv_basebd)
-		{
+		if (expected - actual >= TCP_VEGAS_BETA * inv_basebd) {
 			/* Decrease Linearly */
-
-			if (sk->cong_count++ >= tp->snd_cwnd)
-			{
+			if (tp->snd_cwnd_cnt++ >= tp->snd_cwnd) {
 				tp->snd_cwnd--;
-				sk->cong_count = 0;
+				tp->snd_cwnd_cnt = 0;
 			}
 
-			/* Never less than 2 segments */
+			/* Never less than 2 segments. */
 			if (tp->snd_cwnd < 2)
 				tp->snd_cwnd = 2;
 		}
@@ -500,17 +669,16 @@
 
 static void tcp_cong_avoid_vanj(struct sock *sk, u32 seq, u32 ack, u32 seq_rtt)
 {
-	struct tcp_opt *tp=&(sk->tp_pinfo.af_tcp);
+	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
 	
-        /* 
-         * This is Jacobson's slow start and congestion avoidance. 
+        /* This is Jacobson's slow start and congestion avoidance. 
          * SIGCOMM '88, p. 328.  Because we keep cong_window in 
          * integral mss's, we can't do cwnd += 1 / cwnd.  
          * Instead, maintain a counter and increment it once every 
          * cwnd times.  
 	 * FIXME: Check to be sure the mathematics works out right
 	 * on this trick when we have to reduce the congestion window.
-	 * The cong_count has to be reset properly when reduction events
+	 * The snd_cwnd_cnt has to be reset properly when reduction events
 	 * happen.
 	 * FIXME: What happens when the congestion window gets larger
 	 * than the maximum receiver window by some large factor
@@ -520,38 +688,22 @@
 	 * be reduced to is not clear, since 1/2 the old window may
 	 * still be larger than the maximum sending rate we ever achieved.
          */
-
-        if (tp->snd_cwnd <= sk->ssthresh)  
-	{
-                /* 
-                 *	In "safe" area, increase
-                 */
-
+        if (tp->snd_cwnd <= tp->snd_ssthresh) {
+                /* In "safe" area, increase. */
                 tp->snd_cwnd++;
-	}
-        else 
-	{
-                /*
-                 *	In dangerous area, increase slowly.  
-                 *      In theory this is
-                 *  	tp->snd_cwnd += 1 / tp->snd_cwnd
+	} else {
+                /* In dangerous area, increase slowly.  In theory this is
+                 * tp->snd_cwnd += 1 / tp->snd_cwnd
                  */
-
-                if (sk->cong_count >= tp->snd_cwnd) {
-			
+                if (tp->snd_cwnd_cnt >= tp->snd_cwnd) {
                         tp->snd_cwnd++;
-                        sk->cong_count = 0;
-                }
-                else 
-                        sk->cong_count++;
+                        tp->snd_cwnd_cnt = 0;
+                } else 
+                        tp->snd_cwnd_cnt++;
         }       
 }
 
 
-#define FLAG_DATA		0x01
-#define FLAG_WIN_UPDATE		0x02
-#define FLAG_DATA_ACKED		0x04
-
 static int tcp_clean_rtx_queue(struct sock *sk, __u32 ack, __u32 *seq,
 			       __u32 *seq_rtt)
 {
@@ -560,25 +712,18 @@
 	unsigned long now = jiffies;
 	int acked = 0;
 
-	while((skb=skb_peek(&sk->write_queue)) && (skb != tp->send_head))
-	{
-
+	while((skb=skb_peek(&sk->write_queue)) && (skb != tp->send_head)) {
 #ifdef TCP_DEBUG
 		/* Check for a bug. */
-
 		if (skb->next != (struct sk_buff*) &sk->write_queue &&
 		    after(skb->end_seq, skb->next->seq))
-		{
 			printk(KERN_DEBUG "INET: tcp_input.c: *** "
 			       "bug send_list out of order.\n");
-		}
 #endif								
-		/*
-		 *	If our packet is before the ack sequence we can
-		 *	discard it as it's confirmed to have arrived the 
-		 *	other end.
+		/* If our packet is before the ack sequence we can
+		 * discard it as it's confirmed to have arrived the 
+		 * other end.
 		 */
-		 
 		if (after(skb->end_seq, ack))
 			break;
 
@@ -591,7 +736,7 @@
 		 * do packet "repackaging" for stacks that don't
 		 * like overlapping packets.
 		 */
-		atomic_dec(&sk->packets_out);
+		tp->packets_out--;
 
 		*seq = skb->seq;
 		*seq_rtt = now - skb->when;
@@ -601,13 +746,11 @@
 		kfree_skb(skb, FREE_WRITE);
 	}
 
-	if (acked)
-	{
+	if (acked) {
 		tp->retrans_head = NULL;
 		if (!sk->dead)
 			sk->write_space(sk);
 	}
-
 	return acked;
 }
 
@@ -615,27 +758,18 @@
 {
 	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
 	
-	/*
-	 *	Our probe was answered
-	 */
+	/* Our probe was answered. */
 	tp->probes_out = 0;
 	
-	/*
-	 *	Was it a usable window open ?
-	 */
+	/* Was it a usable window open? */
 	
 	/* should always be non-null */
 	if (tp->send_head != NULL &&
-	    !before (ack + tp->snd_wnd, tp->send_head->end_seq))
-	{
+	    !before (ack + tp->snd_wnd, tp->send_head->end_seq)) {
 		tp->backoff = 0;
 		tp->pending = 0;
-		
 		tcp_clear_xmit_timer(sk, TIME_PROBE0);
-		
-	}
-	else
-	{
+	} else {
 		tcp_reset_xmit_timer(sk, TIME_PROBE0,
 				     min(tp->rto << tp->backoff, 120*HZ));
 	}
@@ -648,138 +782,126 @@
 static int tcp_ack(struct sock *sk, struct tcphdr *th, 
 		   u32 ack_seq, u32 ack, int len)
 {
+	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
 	int flag = 0;
 	u32 seq = 0;
 	u32 seq_rtt = 0;
 	struct sk_buff *skb;
-	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
-
 
 	if(sk->zapped)
 		return(1);	/* Dead, can't ack any more so why bother */
 
 	if (tp->pending == TIME_KEEPOPEN)
-	{
 	  	tp->probes_out = 0;
-	}
 
 	tp->rcv_tstamp = jiffies;
 
-	/*
-	 *	If the ack is newer than sent or older than previous acks
-	 *	then we can probably ignore it.
+	/* If the ack is newer than sent or older than previous acks
+	 * then we can probably ignore it.
 	 */
-
 	if (after(ack, tp->snd_nxt) || before(ack, tp->snd_una))
 		goto uninteresting_ack;
 
-	/*
-	 *	If there is data set flag 1
-	 */
-	 
-	if (len != th->doff*4) 
-	{
+	/* If there is data set flag 1 */
+	if (len != th->doff*4) {
 		flag |= FLAG_DATA;
 		tcp_delack_estimator(tp);
 	}
 
-	/*
-	 *	Update our send window
-	 */
+	/* Update our send window. */
 
-	/*
-	 *	This is the window update code as per RFC 793
-	 *	snd_wl{1,2} are used to prevent unordered
-	 *	segments from shrinking the window 
+	/* This is the window update code as per RFC 793
+	 * snd_wl{1,2} are used to prevent unordered
+	 * segments from shrinking the window 
 	 */
-
 	if (before(tp->snd_wl1, ack_seq) ||
-	    (tp->snd_wl1 == ack_seq && !after(tp->snd_wl2, ack)))
-	{
-		unsigned long nwin;
-
-		nwin = ntohs(th->window);
-		if ((tp->snd_wl2 != ack) || (nwin > tp->snd_wnd))
-		{
+	    (tp->snd_wl1 == ack_seq && !after(tp->snd_wl2, ack))) {
+		unsigned long nwin = ntohs(th->window);
+
+		if ((tp->snd_wl2 != ack) || (nwin > tp->snd_wnd)) {
 			flag |= FLAG_WIN_UPDATE;
 			tp->snd_wnd = nwin;
 
 			tp->snd_wl1 = ack_seq;
 			tp->snd_wl2 = ack;
 
-			if (nwin > sk->max_window)
-				sk->max_window = nwin;
+			if (nwin > tp->max_window)
+				tp->max_window = nwin;
 		}
 	}
 
-	/*
-	 *	We passed data and got it acked, remove any soft error
-	 *	log. Something worked...
+	/* We passed data and got it acked, remove any soft error
+	 * log. Something worked...
 	 */
-
 	sk->err_soft = 0;
 
-	/*
-	 *	If this ack opens up a zero window, clear backoff.  It was
-	 *	being used to time the probes, and is probably far higher than
-	 *	it needs to be for normal retransmission.
+	/* If this ack opens up a zero window, clear backoff.  It was
+	 * being used to time the probes, and is probably far higher than
+	 * it needs to be for normal retransmission.
 	 */
-
 	if (tp->pending == TIME_PROBE0)
-	{
 		tcp_ack_probe(sk, ack);
-	}
-
-	/* 
-	 *	See if we can take anything off of the retransmit queue.
-	 */
 
+	/* See if we can take anything off of the retransmit queue. */
 	if (tcp_clean_rtx_queue(sk, ack, &seq, &seq_rtt))
 		flag |= FLAG_DATA_ACKED;
 
-
-	/*
-	 *	if we where retransmiting don't count rtt estimate
-	 */
-
-	if (atomic_read(&sk->retransmits))
-	{
-		if (atomic_read(&sk->packets_out) == 0)
-			atomic_set(&sk->retransmits, 0);
-	}
-	else
-	{
-		/*
-		 * Note that we only reset backoff and rto in the
-		 * rtt recomputation code.  And that doesn't happen
-		 * if there were retransmissions in effect.  So the
-		 * first new packet after the retransmissions is
-		 * sent with the backoff still in effect.  Not until
-		 * we get an ack from a non-retransmitted packet do
-		 * we reset the backoff and rto.  This allows us to deal
-		 * with a situation where the network delay has increased
-		 * suddenly.  I.e. Karn's algorithm. (SIGCOMM '87, p5.)
+	/* If we have a timestamp, we always do rtt estimates. */
+	if (tp->saw_tstamp) {
+		/* Read draft-ietf-tcplw-high-performance before mucking
+		 * with this code. (Superceeds RFC1323)
 		 */
-
-		if (flag & FLAG_DATA_ACKED)
-		{
-			tcp_rtt_estimator(tp, seq_rtt);
-
-			(*tcp_sys_cong_ctl_f)(sk, seq, ack, seq_rtt);
+		seq_rtt = (jiffies-tp->rcv_tsecr);
+		tcp_rtt_estimator(tp, seq_rtt);
+		if (tp->retransmits) {
+			if (tp->packets_out == 0) {
+				tp->retransmits = 0;
+				tp->backoff = 0;
+				tcp_set_rto(tp);
+			} else {
+				/* Still retransmitting, use backoff */
+				tcp_set_rto(tp);
+				tp->rto = tp->rto << tp->backoff;
+			}
+		} else {
+			tcp_set_rto(tp);
+			if (flag && FLAG_DATA_ACKED)
+				(*tcp_sys_cong_ctl_f)(sk, seq, ack, seq_rtt);
+		}
+		/* NOTE: safe here so long as cong_ctl doesn't use rto */
+		tcp_bound_rto(tp);
+	} else {
+		/* If we were retransmiting don't count rtt estimate. */
+		if (tp->retransmits) {
+			if (tp->packets_out == 0)
+				tp->retransmits = 0;
+		} else {
+			/* We don't have a timestamp. Can only use
+			 * packets that are not retransmitted to determine
+			 * rtt estimates. Also, we must not reset the
+			 * backoff for rto until we get a non-retransmitted
+			 * packet. This allows us to deal with a situation
+			 * where the network delay has increased suddenly.
+			 * I.e. Karn's algorithm. (SIGCOMM '87, p5.)
+			 */
+			if (flag & FLAG_DATA_ACKED) {
+				tp->backoff = 0;
+				tcp_rtt_estimator(tp, seq_rtt);
+				tcp_set_rto(tp);
+				tcp_bound_rto(tp);
+				(*tcp_sys_cong_ctl_f)(sk, seq, ack, seq_rtt);
+			}
 		}
 	}
 
-	if (atomic_read(&sk->packets_out))
-	{
-		if (flag & FLAG_DATA_ACKED)
-		{
+	if (tp->packets_out) {
+		if (flag & FLAG_DATA_ACKED) {
 			long when;
 
 			skb = skb_peek(&sk->write_queue);
 			when = tp->rto - (jiffies - skb->when);
 
-			/*
-			 * FIXME: This assumes that when we are retransmitting
+			/* FIXME: This assumes that when we are retransmitting
 			 * we should only ever respond with one packet.
 			 * This means congestion windows should not grow
 			 * during recovery. In 2.0.X we allow the congestion
@@ -791,36 +913,23 @@
 			 * we have to fix the call to congestion window
 			 * updates so that it works during retransmission.
 			 */
-
-			if (atomic_read(&sk->retransmits))
-			{
+			if (tp->retransmits) {
 				tp->retrans_head = NULL;
-				/* 
-				 * This is tricky. We are retransmiting a 
+
+				/* This is tricky. We are retransmiting a 
 				 * segment of a window when congestion occured.
 				 */
 				tcp_do_retransmit(sk, 0);
-				tcp_reset_xmit_timer(sk, TIME_RETRANS,
-						     tp->rto);
-			}
-			else
+				tcp_reset_xmit_timer(sk, TIME_RETRANS, tp->rto);
+			} else
 				tcp_reset_xmit_timer(sk, TIME_RETRANS, when);
 		}
-	}
-	else
+	} else
 		tcp_clear_xmit_timer(sk, TIME_RETRANS);
 
-
-	/* FIXME: danger, if we just did a timeout and got the third
-	 * ack on this packet, then this is going to send it again!
-	 * [No. Floyd retransmit war check keeps this from happening. -- erics]
-	 */
 	tcp_fast_retrans(sk, ack, (flag & (FLAG_DATA|FLAG_WIN_UPDATE)));
 
-	/*
-	 *	Remember the highest ack received.
-	 */
-
+	/* Remember the highest ack received. */
 	tp->snd_una = ack;
 
 	return 1;
@@ -828,11 +937,9 @@
 uninteresting_ack:
 
 	SOCK_DEBUG(sk, "Ack ignored %u %u\n", ack, tp->snd_nxt);
-
 	return 0;
 }
 
-
 /*
  * 	Process the FIN bit. This now behaves as it is supposed to work
  *	and the FIN takes effect when it is validly part of sequence
@@ -846,53 +953,46 @@
  *	close and we go into CLOSING (and later onto TIME-WAIT)
  *
  *	If we are in FINWAIT-2, a received FIN moves us to TIME-WAIT.
- *
  */
  
 static int tcp_fin(struct sk_buff *skb, struct sock *sk, struct tcphdr *th)
 {
-	sk->fin_seq = skb->end_seq;
+	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+	/* XXX This fin_seq thing should disappear... -DaveM */
+	tp->fin_seq = skb->end_seq;
 
 	tcp_send_ack(sk);
 
-	if (!sk->dead) 
-	{
+	if (!sk->dead) {
 		sk->state_change(sk);
 		sock_wake_async(sk->socket, 1);
 	}
 
-	switch(sk->state) 
-	{
+	switch(sk->state) {
 		case TCP_SYN_RECV:
 		case TCP_SYN_SENT:
 		case TCP_ESTABLISHED:
-			/*
-			 * move to CLOSE_WAIT
-			 */
-
+			/* Move to CLOSE_WAIT */
 			tcp_set_state(sk, TCP_CLOSE_WAIT);
-			
 			if (th->rst)
 				sk->shutdown = SHUTDOWN_MASK;
 			break;
 
 		case TCP_CLOSE_WAIT:
 		case TCP_CLOSING:
-			/*
-			 * received a retransmission of the FIN, do
+			/* Received a retransmission of the FIN, do
 			 * nothing.
 			 */
 			break;
 		case TCP_TIME_WAIT:
-			/*
-			 * received a retransmission of the FIN,
+			/* Received a retransmission of the FIN,
 			 * restart the TIME_WAIT timer.
 			 */
 			tcp_reset_msl_timer(sk, TIME_CLOSE, TCP_TIMEWAIT_LEN);
 			return(0);
 		case TCP_FIN_WAIT1:
-			/*
-			 * This case occurs when a simultaneous close
+			/* This case occurs when a simultaneous close
 			 * happens, we must ack the received FIN and
 			 * enter the CLOSING state.
 			 *
@@ -902,47 +1002,39 @@
 			 * FIN lost hang). The TIME_WRITE code is already 
 			 * correct for handling this timeout.
 			 */
-
 			tcp_set_state(sk, TCP_CLOSING);
 			break;
 		case TCP_FIN_WAIT2:
-			/*
-			 * received a FIN -- send ACK and enter TIME_WAIT
-			 */
+			/* Received a FIN -- send ACK and enter TIME_WAIT. */
 			tcp_reset_msl_timer(sk, TIME_CLOSE, TCP_TIMEWAIT_LEN);
-			sk->shutdown|=SHUTDOWN_MASK;
+			sk->shutdown |= SHUTDOWN_MASK;
 			tcp_set_state(sk,TCP_TIME_WAIT);
 			break;
 		case TCP_CLOSE:
-			/*
-			 * already in CLOSE
-			 */
+			/* Already in CLOSE. */
 			break;
 		default:
+			/* FIXME: Document whats happening in this case. -DaveM */
 			tcp_set_state(sk,TCP_LAST_ACK);
 	
 			/* Start the timers. */
 			tcp_reset_msl_timer(sk, TIME_CLOSE, TCP_TIMEWAIT_LEN);
 			return(0);
-	}
+	};
 
 	return(0);
 }
 
-
-
-	/*
-	 * This one checks to see if we can put data from the
-	 * out_of_order queue into the receive_queue
-	 */
-
-static void  tcp_ofo_queue(struct sock *sk)
+/* This one checks to see if we can put data from the
+ * out_of_order queue into the receive_queue.
+ */
+static void tcp_ofo_queue(struct sock *sk)
 {
-	struct sk_buff * skb;
-	struct tcp_opt *tp=&(sk->tp_pinfo.af_tcp);
+	struct sk_buff *skb;
+	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
 
+	/* FIXME: out_of_order_queue is a strong tcp_opt candidate... -DaveM */
 	while ((skb = skb_peek(&sk->out_of_order_queue))) {
-		
 		if (after(skb->seq, tp->rcv_nxt))
 			break;
 
@@ -950,106 +1042,59 @@
 			SOCK_DEBUG(sk, "ofo packet was allready received \n");
 			skb_unlink(skb);
 			kfree_skb(skb, FREE_READ);
-
 			continue;
 		}
 		SOCK_DEBUG(sk, "ofo requeuing : rcv_next %X seq %X - %X\n",
 			   tp->rcv_nxt, skb->seq, skb->end_seq);
 
 		skb_unlink(skb);
-		 
 		skb_queue_tail(&sk->receive_queue, skb);
-
 		tp->rcv_nxt = skb->end_seq;
 	}
 }
 
 static void tcp_data_queue(struct sock *sk, struct sk_buff *skb)
 {
-	struct sk_buff * skb1;
-	struct tcp_opt *tp=&(sk->tp_pinfo.af_tcp);
+	struct sk_buff *skb1;
+	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
 
-	/*
-	 *  Queue data for delivery to the user
-	 *  Packets in sequence go to the receive queue
-	 *  Out of sequence packets to out_of_order_queue
+	/*  Queue data for delivery to the user.
+	 *  Packets in sequence go to the receive queue.
+	 *  Out of sequence packets to out_of_order_queue.
 	 */
-
-
 	if (skb->seq == tp->rcv_nxt) {
-
-		/*
-		 * Ok. In sequence.
-		 */
-		
- 
+		/* Ok. In sequence. */
+queue_and_out:
 		skb_queue_tail(&sk->receive_queue, skb);
-
-
 		tp->rcv_nxt = skb->end_seq;
-
 		tcp_ofo_queue(sk);
-		
 		if (skb_queue_len(&sk->out_of_order_queue) == 0)
 			tp->pred_flags = htonl((0x5010 << 16) | tp->snd_wnd);
-
 		return;
 	}
 	
-	/*
-	 *  Not in sequence
-	 *  either a retransmit or some packet got lost
-	 */
-
+	/* Not in sequence, either a retransmit or some packet got lost. */
 	if (!after(skb->end_seq, tp->rcv_nxt)) {
-		
-		/* 
-		 * A retransmit.
-		 * 2nd most common case.
-		 * force an imediate ack
-		 */
+		/* A retransmit, 2nd most common case.  Force an imediate ack. */
 		SOCK_DEBUG(sk, "retransmit received: seq %X\n", skb->seq);
 
-		sk->delayed_acks = MAX_DELAY_ACK;
+		tp->delayed_acks = MAX_DELAY_ACK;
 		kfree_skb(skb, FREE_READ);
-
 		return;
 	}
 
-
 	if (before(skb->seq, tp->rcv_nxt)) {
-
-		/*
-		 * Partial packet
-		 * seq < rcv_next < end_seq
-		 */
+		/* Partial packet, seq < rcv_next < end_seq */
 		SOCK_DEBUG(sk, "partial packet: rcv_next %X seq %X - %X\n",
 			   tp->rcv_nxt, skb->seq, skb->end_seq);
 
-		skb_queue_tail(&sk->receive_queue, skb);
-
-		tp->rcv_nxt = skb->end_seq;
-
-		tcp_ofo_queue(sk);
-
-		if (skb_queue_len(&sk->out_of_order_queue) == 0)
-			tp->pred_flags = htonl((0x5010 << 16) | tp->snd_wnd);
-
-		return;
+		goto queue_and_out;
 	}
 
-	/*
-	 *	Ok. This is an out_of_order segment
-	 */
-
-	/* Force an ack */
-
-	sk->delayed_acks = MAX_DELAY_ACK;
-
-	/*
-	 *	disable header predition
-	 */
+	/* Ok. This is an out_of_order segment, force an ack. */
+	tp->delayed_acks = MAX_DELAY_ACK;
 
+	/* Disable header predition. */
 	tp->pred_flags = 0;
 
 	SOCK_DEBUG(sk, "out of order segment: rcv_next %X seq %X - %X\n",
@@ -1057,33 +1102,28 @@
 
 	if (skb_peek(&sk->out_of_order_queue) == NULL) {
 		skb_queue_head(&sk->out_of_order_queue,skb);
-	}
-	else 
+	} else {
 		for(skb1=sk->out_of_order_queue.prev; ; skb1 = skb1->prev) {
-
-			/* allready there */
-			if (skb->seq==skb1->seq && skb->len>=skb1->len)
-			{
- 				skb_append(skb1,skb);
+			/* Already there. */
+			if (skb->seq == skb1->seq && skb->len >= skb1->len) {
+ 				skb_append(skb1, skb);
  				skb_unlink(skb1);
- 				kfree_skb(skb1,FREE_READ);
+ 				kfree_skb(skb1, FREE_READ);
 				break;
 			}
 			
-			if (after(skb->seq, skb1->seq))
-			{
+			if (after(skb->seq, skb1->seq)) {
 				skb_append(skb1,skb);
 				break;
 			}
 
-                        /*
-			 *	See if we've hit the start. If so insert.
-			 */
+                        /* See if we've hit the start. If so insert. */
 			if (skb1 == skb_peek(&sk->out_of_order_queue)) {
 				skb_queue_head(&sk->out_of_order_queue,skb);
 				break;
 			}
 		}
+	}
 }
 
 
@@ -1096,48 +1136,33 @@
 static int tcp_data(struct sk_buff *skb, struct sock *sk, unsigned int len)
 {
 	struct tcphdr *th;
-	struct tcp_opt *tp=&(sk->tp_pinfo.af_tcp);
+	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
 
 	th = skb->h.th;
-	skb_pull(skb,th->doff*4);
-	skb_trim(skb,len-(th->doff*4));
+	skb_pull(skb, th->doff*4);
+	skb_trim(skb, len - (th->doff*4));
 
         if (skb->len == 0 && !th->fin)
-        {
 		return(0);
-        }
 
-	/*
-	 *	FIXME: don't accept data after the receved fin
-	 */
-
-	/*
-	 *	The bytes in the receive read/assembly queue has increased. 
-	 *	Needed for the low memory discard algorithm 
-	 */
-
-	sk->bytes_rcv += skb->len;
-
-	/*
-	 *	We no longer have anyone receiving data on this connection.
+	/* FIXME: don't accept data after the received fin.
+	 *
+	 * Would checking snd_seq against fin_seq be enough?
+	 * If so, how do we handle that case exactly? -DaveM
 	 */
 
+	/* We no longer have anyone receiving data on this connection. */
 	tcp_data_queue(sk, skb);
 
-	if (before(tp->rcv_nxt, sk->copied_seq)) 
-	{
+	if (before(tp->rcv_nxt, sk->copied_seq)) {
 		printk(KERN_DEBUG "*** tcp.c:tcp_data bug acked < copied\n");
 		tp->rcv_nxt = sk->copied_seq;
 	}
 
-	sk->delayed_acks++;
-
-	/*
-	 *	Now tell the user we may have some data. 
-	 */
+	tp->delayed_acks++;
 
-	if (!sk->dead)
-	{
+	/* Now tell the user we may have some data. */
+	if (!sk->dead) {
 		SOCK_DEBUG(sk, "Data wakeup.\n");
 		sk->data_ready(sk,0);
 	}
@@ -1149,29 +1174,25 @@
 	struct sk_buff *skb;
 	struct tcp_opt *tp=&(sk->tp_pinfo.af_tcp);
 
-	if ((skb = tp->send_head))
-	{
+	if ((skb = tp->send_head)) {
 		if (!after(skb->end_seq, tp->snd_una + tp->snd_wnd) &&
-		    atomic_read(&sk->packets_out) < tp->snd_cwnd )
-		{
-			/*
-			 *	Add more data to the send queue.
-			 */
+		    tp->packets_out < tp->snd_cwnd ) {
+			/* Add more data to the send queue. */
+
 			/* FIXME: the congestion window is checked
-			 * again in tcp_write_xmit anyway?!
+			 * again in tcp_write_xmit anyway?! -- erics
+			 *
+			 * I think it must, it bumps tp->packets_out for
+			 * each packet it fires onto the wire. -DaveM
 			 */
-
 			tcp_write_xmit(sk);
 			if(!sk->dead)
 				sk->write_space(sk);
-		}
-		else if (atomic_read(&sk->packets_out) == 0 && !tp->pending)
- 		{
- 			/*
- 			 *	Data to queue but no room.
- 			 */
+		} else if (tp->packets_out == 0 && !tp->pending) {
+ 			/* Data to queue but no room. */
+
 			/* FIXME: Is it right to do a zero window probe into
-			 * a congestion window limited window???
+			 * a congestion window limited window??? -- erics
 			 */
  			tcp_reset_xmit_timer(sk, TIME_PROBE0, tp->rto);
  		}
@@ -1180,32 +1201,25 @@
 
 static __inline__ void tcp_ack_snd_check(struct sock *sk)
 {
-	/*
-	 *	This also takes care of updating the window.
-	 *	This if statement needs to be simplified.
+	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+	/* This also takes care of updating the window.
+	 * This if statement needs to be simplified.
 	 *
-	 *      rules for delaying an ack:
+	 * Rules for delaying an ack:
 	 *      - delay time <= 0.5 HZ
 	 *      - we don't have a window update to send
 	 *      - must send at least every 2 full sized packets
 	 */
-
-	if (sk->delayed_acks == 0)
-	{
-		/*
-		 *	We sent a data segment already
-		 */
+	if (tp->delayed_acks == 0) {
+		/* We sent a data segment already. */
 		return;
 	}
 
-	if (sk->delayed_acks >= MAX_DELAY_ACK || tcp_raise_window(sk))
-	{
+	if (tp->delayed_acks >= MAX_DELAY_ACK || tcp_raise_window(sk))
 		tcp_send_ack(sk);
-	}
 	else
-	{
 		tcp_send_delayed_ack(sk, HZ/2);
-	}
 }
 
 /*
@@ -1227,62 +1241,49 @@
 		ptr--;
 	ptr += ntohl(th->seq);
 
-	/* ignore urgent data that we've already seen and read */
+	/* Ignore urgent data that we've already seen and read. */
 	if (after(sk->copied_seq, ptr))
 		return;
 
-	/* do we already have a newer (or duplicate) urgent pointer? */
+	/* Do we already have a newer (or duplicate) urgent pointer? */
 	if (sk->urg_data && !after(ptr, sk->urg_seq))
 		return;
 
-	/* tell the world about our new urgent pointer */
+	/* Tell the world about our new urgent pointer. */
 	if (sk->proc != 0) {
-		if (sk->proc > 0) {
+		if (sk->proc > 0)
 			kill_proc(sk->proc, SIGURG, 1);
-		} else {
+		else
 			kill_pg(-sk->proc, SIGURG, 1);
-		}
 	}
-	/*
-	 *	We may be adding urgent data when the last byte read was
-	 *	urgent. To do this requires some care. We cannot just ignore
-	 *	sk->copied_seq since we would read the last urgent byte again
-	 *	as data, nor can we alter copied_seq until this data arrives
-	 *	or we break the sematics of SIOCATMARK (and thus sockatmark())
+
+	/* We may be adding urgent data when the last byte read was
+	 * urgent. To do this requires some care. We cannot just ignore
+	 * sk->copied_seq since we would read the last urgent byte again
+	 * as data, nor can we alter copied_seq until this data arrives
+	 * or we break the sematics of SIOCATMARK (and thus sockatmark())
 	 */
 	if (sk->urg_seq == sk->copied_seq)
 		sk->copied_seq++;	/* Move the copied sequence on correctly */
 	sk->urg_data = URG_NOTYET;
 	sk->urg_seq = ptr;
 
-	/* disable header prediction */
+	/* Disable header prediction. */
 	tp->pred_flags = 0;
 }
 
-/*
- *	This is the 'fast' part of urgent handling.
- */
- 
+/* This is the 'fast' part of urgent handling. */
 static inline void tcp_urg(struct sock *sk, struct tcphdr *th, unsigned long len)
 {
-	/*
-	 *	Check if we get a new urgent pointer - normally not 
-	 */
-	 
+	/* Check if we get a new urgent pointer - normally not. */
 	if (th->urg)
 		tcp_check_urg(sk,th);
 
-	/*
-	 *	Do we wait for any urgent data? - normally not
-	 */
-	 
+	/* Do we wait for any urgent data? - normally not... */
 	if (sk->urg_data == URG_NOTYET) {
-		u32 ptr;
+		u32 ptr = sk->urg_seq - ntohl(th->seq) + (th->doff*4);
 
-		/*
-		 *	Is the urgent pointer pointing into this packet? 
-		 */	 
-		ptr = sk->urg_seq - ntohl(th->seq) + th->doff*4;
+		/* Is the urgent pointer pointing into this packet? */	 
 		if (ptr < len) {
 			sk->urg_data = URG_VALID | *(ptr + (unsigned char *) th);
 			if (!sk->dead)
@@ -1291,26 +1292,19 @@
 	}
 }
 
-
 static void prune_queue(struct sock *sk)
 {
 	struct sk_buff * skb;
 
-	/*
-	 *	clean the out_of_order queue
-	 */
-
+	/* Clean the out_of_order queue. */
 	while ((skb = skb_dequeue(&sk->out_of_order_queue))) 
-	{
 		kfree_skb(skb, FREE_READ);
-	}
 }
 
-
 int tcp_rcv_established(struct sock *sk, struct sk_buff *skb,
 			struct tcphdr *th, __u16 len)
 {
-	struct tcp_opt *tp;
+	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
 	int queued = 0;
 	u32 flg;
 	
@@ -1330,6 +1324,23 @@
 	 */
 
 	tp = &(sk->tp_pinfo.af_tcp); 
+
+	/*
+	 * RFC1323: H1. Apply PAWS check first.
+	 */
+	if (tcp_fast_parse_options(th,tp)) {
+		if (tp->saw_tstamp) {
+			if (tcp_paws_discard(tp)) {
+				if (!th->rst) {
+					tcp_send_ack(sk);
+					kfree_skb(skb, FREE_READ);
+					return 0;
+				}
+			}
+			tcp_replace_ts_recent(tp,skb->end_seq);
+		}
+	}
+
 	flg = *(((u32 *)th) + 3);
 		
 	/*
@@ -1340,53 +1351,39 @@
 	 *	 space for instance)
 	 */
 
-	if (flg == tp->pred_flags && skb->seq == tp->rcv_nxt)
-	{
-		if (len <= sizeof(struct tcphdr))
-		{
-			if (len == sizeof(struct tcphdr))
-			{
+	if (flg == tp->pred_flags && skb->seq == tp->rcv_nxt) {
+		if (len <= th->doff*4) {
+			/* Bulk data transfer: sender */
+			if (len == th->doff*4) {
 				tcp_ack(sk, th, skb->seq, skb->ack_seq, len);
 				tcp_data_snd_check(sk);
 			}
 
 			kfree_skb(skb, FREE_READ);
 			return 0;
-		}
-		else if (skb->ack_seq == tp->snd_una)
-		{
-			/* 
-			 * Bulk data transfer: receiver 
-			 */
+		} else if (skb->ack_seq == tp->snd_una) {
+			/* Bulk data transfer: receiver */
 			
-			skb_pull(skb,sizeof(struct tcphdr));
+			skb_pull(skb,th->doff*4);
 			
 			skb_queue_tail(&sk->receive_queue, skb);
 			tp->rcv_nxt = skb->end_seq;
-			sk->bytes_rcv += len - sizeof(struct tcphdr);
-			
+
 			sk->data_ready(sk, 0);
 			tcp_delack_estimator(tp);
 
-			if (sk->delayed_acks++ == 0)
-			{
+			if (tp->delayed_acks++ == 0)
 				tcp_send_delayed_ack(sk, HZ/2);
-			}
 			else
-			{
 				tcp_send_ack(sk);
-			}
 
 			return 0;
 		}
 	}
 
-	if (!tcp_sequence(tp, skb->seq, skb->end_seq))
-	{
-		if (!th->rst)
-		{
-			if (after(skb->seq, tp->rcv_nxt))
-			{
+	if (!tcp_sequence(tp, skb->seq, skb->end_seq)) {
+		if (!th->rst) {
+			if (after(skb->seq, tp->rcv_nxt)) {
 				SOCK_DEBUG(sk, "seq:%d end:%d wup:%d wnd:%d\n",
 					   skb->seq, skb->end_seq,
 					   tp->rcv_wup, tp->rcv_wnd);
@@ -1397,68 +1394,45 @@
 		}
 	}
 
-	if(th->syn && skb->seq != sk->syn_seq)
-	{
+	if(th->syn && skb->seq != sk->syn_seq) {
 		printk(KERN_DEBUG "syn in established state\n");
 		tcp_reset(sk, skb);
 		kfree_skb(skb, FREE_READ);
 		return 1;
 	}
 	
-	if(th->rst)
-	{
+	if(th->rst) {
 		tcp_reset(sk,skb);
 		kfree_skb(skb, FREE_READ);
 		return 0;
 	}
 	
 	if(th->ack)
-	{
 		tcp_ack(sk, th, skb->seq, skb->ack_seq, len);
-	}
-
 	
-	/*
-	 *	Process urgent data
-	 */
-
+	/* Process urgent data. */
 	tcp_urg(sk, th, len);
 
-	/*
-	 *	step 7: process the segment text
-	 */
-
-
+	/* step 7: process the segment text */
 	queued = tcp_data(skb, sk, len);
 
-	/*
-	 *	step 8: check the FIN bit
-	 */
-
+	/* step 8: check the FIN bit */
 	if (th->fin)
-	{
 		tcp_fin(skb, sk, th);
-	}
 
 	tcp_data_snd_check(sk);
 	tcp_ack_snd_check(sk);
 
-	/*
-	 *	If our receive queue has grown past its limits,
-	 *	try to prune away duplicates etc..
+	/* If our receive queue has grown past its limits,
+	 * try to prune away duplicates etc..
 	 */
 	if (atomic_read(&sk->rmem_alloc) > sk->rcvbuf)
 		prune_queue(sk);
 
-	/*
-	 *	And done
-	 */	
-	
 	if (!queued)
 		kfree_skb(skb, FREE_READ);
 	return 0;
 }
-		
 
 /*
  *	This function implements the receiving procedure of RFC 793.
@@ -1471,49 +1445,26 @@
 {
 	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
 	int queued = 0;
-	int rcv_mss;
-
-	/*
-	 *	state == CLOSED
-	 *	Hash lookup always fails, so no worries. -DaveM 
-	 */
 
+	/* state == CLOSED, hash lookup always fails, so no worries. -DaveM */
 	switch (sk->state) {
-
-
 	case TCP_LISTEN:
-		
 		if (th->rst)			
 			goto discard;
 
-		/* 
-		 * These use the socket TOS.. 
+		/* These use the socket TOS.. 
 		 * might want to be the received TOS 
 		 */
-
 		if(th->ack)
-		{	
-			/*
-			 *  send reset
-			 */
-
-			return 1;
-		}
+			return 1; /* send reset */
 		
-		
-		if(th->syn)
-		{
-			int err;
-			__u32 isn;
-
-			isn = tp->af_specific->init_sequence(sk, skb);
-			err = tp->af_specific->conn_request(sk, skb, opt, isn);
+		if(th->syn) {
+			__u32 isn = tp->af_specific->init_sequence(sk, skb);
 
-			if (err < 0)
+			if(tp->af_specific->conn_request(sk, skb, opt, isn) < 0)
 				return 1;
 
-			/*
-			 *  Now we have several options: In theory there is 
+			/*  Now we have several options: In theory there is 
 			 *  nothing else in the frame. KA9Q has an option to 
 			 *  send data with the syn, BSD accepts data with the
 			 *  syn up to the [to be] advertised window and 
@@ -1525,7 +1476,6 @@
 			 *  Now that TTCP is starting to be used we ought to 
 			 *  queue this data.
 			 */
-
 			return 0;
 		}
 		
@@ -1533,47 +1483,36 @@
 		break;
 
 	case TCP_SYN_SENT:
-		
-		/*
-		 *	SYN sent means we have to look for a suitable ack and 
-		 *	either reset for bad matches or go to connected. 
-		 *	The SYN_SENT case is unusual and should
-		 *	not be in line code. [AC]
+		/* SYN sent means we have to look for a suitable ack and 
+		 * either reset for bad matches or go to connected. 
+		 * The SYN_SENT case is unusual and should
+		 * not be in line code. [AC]
 		 */
-	   
-		if(th->ack)
-		{
+		if(th->ack) {
 			tp->snd_wl1 = skb->seq;
 
-			/* We got an ack, but it's not a good ack */
-			if(!tcp_ack(sk,th, skb->seq, skb->ack_seq, len))
-			{
+			/* We got an ack, but it's not a good ack. */
+			if(!tcp_ack(sk,th, skb->seq, skb->ack_seq, len)) {
 				tcp_statistics.TcpAttemptFails++;
 				return 1;
 			}
 
-			if(th->rst)
-			{
+			if(th->rst) {
 				tcp_reset(sk,skb);
 				goto discard;
 			}
 
-			if(!th->syn)
-			{
-				/* 
-				 *  A valid ack from a different connection
-				 *  start. Shouldn't happen but cover it 
+			if(!th->syn) {
+				/* A valid ack from a different connection
+				 * start.  Shouldn't happen but cover it.
 				 */
 				tcp_statistics.TcpAttemptFails++;
 				return 1;
 			}
 
-			/*
-			 *	Ok.. it's good. Set up sequence 
-			 *	numbers and
-			 *	move to established.
+			/* Ok.. it's good. Set up sequence numbers and
+			 * move to established.
 			 */
-
 			tp->rcv_nxt = skb->seq+1;
 			tp->rcv_wnd = 0;
 			tp->rcv_wup = skb->seq+1;
@@ -1582,39 +1521,53 @@
 			tp->snd_wl1 = skb->seq;
 			tp->snd_wl2 = skb->ack_seq;
 
-			sk->fin_seq = skb->seq;
-			tcp_send_ack(sk);
+			tp->fin_seq = skb->seq;
 
 			tcp_set_state(sk, TCP_ESTABLISHED);
-			rcv_mss = tcp_parse_options(th);
-			
-			if (rcv_mss)
-				sk->mss = min(sk->mss, rcv_mss);
+			tcp_parse_options(th,tp);
+			/* FIXME: need to make room for SACK still */
+			if (tp->tstamp_ok) {
+				tp->tcp_header_len = sizeof(struct tcphdr) + 12;	/* FIXME: Define constant! */
+				sk->dummy_th.doff += 3;		/* reserve space of options */
+			} else
+				tp->tcp_header_len = sizeof(struct tcphdr);
+			if (tp->saw_tstamp) {
+				tp->ts_recent = tp->rcv_tsval;
+				tp->ts_recent_stamp = jiffies;
+			}
+
+			/* Can't be earlier, doff would be wrong. */
+			tcp_send_ack(sk);
+
+			if (tp->in_mss)
+				sk->mss = min(sk->mss, tp->in_mss);
+
+			/* Take out space for tcp options. */
+			sk->mss -= tp->tcp_header_len - sizeof(struct tcphdr);
 			
 			sk->dummy_th.dest = th->source;
 			sk->copied_seq = tp->rcv_nxt;
 
-			if(!sk->dead)
-			{
+			if(!sk->dead) {
 				sk->state_change(sk);
 				sock_wake_async(sk->socket, 0);
 			}
 
 			/* Drop through step 6 */
 			goto step6;
-		}
-		else
-		{
-			if(th->syn && !th->rst)
-			{
-				/* 
-				 * the previous version of the code
+		} else {
+			if(th->syn && !th->rst) {
+				/* The previous version of the code
 				 * checked for "connecting to self"
 				 * here. that check is done now in
-				 * tcp_connect
+				 * tcp_connect.
 				 */
-
 				tcp_set_state(sk, TCP_SYN_RECV);
+				tcp_parse_options(th,tp);
+				if (tp->saw_tstamp) {
+					tp->ts_recent = tp->rcv_tsval;
+					tp->ts_recent_stamp = jiffies;
+				}
 				
 				tp->rcv_nxt = skb->seq + 1;
 				tp->rcv_wup = skb->seq + 1;
@@ -1630,8 +1583,7 @@
 		break;
 
 	case TCP_TIME_WAIT:
-	        /*
-		 *	RFC 1122:
+	        /*	RFC 1122:
 		 *	"When a connection is [...] on TIME-WAIT state [...]
 		 *	[a TCP] MAY accept a new SYN from the remote TCP to
 		 *	reopen the connection directly, if it:
@@ -1644,11 +1596,8 @@
 		 *	(2)  returns to TIME-WAIT state if the SYN turns out 
 		 *	to be an old duplicate".
 		 */
-
-		if (th->syn && !th->rst && after(skb->seq, tp->rcv_nxt))
-		{
+		if (th->syn && !th->rst && after(skb->seq, tp->rcv_nxt)) {
 			__u32 isn;
-			int err;
 
 			skb_orphan(skb);
                         sk->err = ECONNRESET;
@@ -1664,50 +1613,53 @@
 
 			skb_set_owner_r(skb, sk);
 			tp = &sk->tp_pinfo.af_tcp;
-			
-			err = tp->af_specific->conn_request(sk, skb, opt, isn);
 
-			if (err < 0)
+			if(tp->af_specific->conn_request(sk, skb, opt, isn) < 0)
 				return 1;
-
 			return 0;
 		}
 
 		break;
-
 	}
 
-	/*
-	 *	step 1: check sequence number
-	 */
+	/*   Parse the tcp_options present on this header.
+	 *   By this point we really only expect timestamps and SACKs.
+	 *   Note that this really has to be here and not later for PAWS
+	 *   (RFC1323) to work.
+	 */
+	if (tcp_fast_parse_options(th,tp)) {
+		/* NOTE: assumes saw_tstamp is never set if we didn't
+		 * negotiate the option. tcp_fast_parse_options() must
+		 * guarantee this.
+		 */
+		if (tp->saw_tstamp) {
+			if (tcp_paws_discard(tp)) {
+				if (!th->rst) {
+					tcp_send_ack(sk);
+					goto discard;
+				}
+			}
+			tcp_replace_ts_recent(tp,skb->end_seq);
+		}
+	}
 
-	if (!tcp_sequence(tp, skb->seq, skb->end_seq))
-	{
-		if (!th->rst)
-		{
+	/* step 1: check sequence number */
+	if (!tcp_sequence(tp, skb->seq, skb->end_seq)) {
+		if (!th->rst) {
 			tcp_send_ack(sk);
 			goto discard;
 		}
 	}
 
-
-	/*
-	 *	step 2: check RST bit
-	 */
-
-	if(th->rst)
-	{
+	/* step 2: check RST bit */
+	if(th->rst) {
 		tcp_reset(sk,skb);
 		goto discard;
 	}
 
-	/*
-	 *	step 3: check security and precedence 
-	 *	[ignored]
-	 */
+	/* step 3: check security and precedence [ignored] */
 
-	/*
-	 *	step 4:
+	/*	step 4:
 	 *
 	 *	Check for a SYN, and ensure it matches the SYN we were
 	 *	first sent. We have to handle the rather unusual (but valid)
@@ -1723,24 +1675,18 @@
 	 *	original syn. 
 	 */
 
-	if (th->syn && skb->seq!=sk->syn_seq)
-	{
+	if (th->syn && skb->seq!=sk->syn_seq) {
 		tcp_reset(sk, skb);
 		return 1;
 	}
 
-	/*
-	 *	step 5: check the ACK field
-	 */
-
-	if (th->ack) 
-	{
+	/* step 5: check the ACK field */
+	if (th->ack) {
 		int acceptable = tcp_ack(sk,th,skb->seq, skb->ack_seq,len);
 		
 		switch(sk->state) {
 		case TCP_SYN_RECV:
-			if (acceptable)
-			{
+			if (acceptable) {
 				tcp_set_state(sk, TCP_ESTABLISHED);
 				sk->dummy_th.dest=th->source;
 				sk->copied_seq = tp->rcv_nxt;
@@ -1753,15 +1699,12 @@
 				tp->snd_wl1 = skb->seq;
 				tp->snd_wl2 = skb->ack_seq;
 
-			}
-			else
+			} else
 				return 1;
 			break;
 
 		case TCP_FIN_WAIT1:
-
-			if (tp->snd_una == sk->write_seq) 
-			{
+			if (tp->snd_una == sk->write_seq) {
 				sk->shutdown |= SEND_SHUTDOWN;
 				tcp_set_state(sk, TCP_FIN_WAIT2);
 				if (!sk->dead)
@@ -1770,17 +1713,12 @@
 			break;
 
 		case TCP_CLOSING:	
-
 			if (tp->snd_una == sk->write_seq)
-			{
 				tcp_time_wait(sk);
-			}
 			break;
 
 		case TCP_LAST_ACK:
-
-			if (tp->snd_una == sk->write_seq)
-			{
+			if (tp->snd_una == sk->write_seq) {
 				sk->shutdown = SHUTDOWN_MASK;
 				tcp_set_state(sk,TCP_CLOSE);
 				if (!sk->dead)
@@ -1790,49 +1728,34 @@
 			break;
 
 		case TCP_TIME_WAIT:
-			/*
-			 * keep us in TIME_WAIT until we stop getting 
+			/* Keep us in TIME_WAIT until we stop getting 
 			 * packets, reset the timeout.
 			 */
 			tcp_reset_msl_timer(sk, TIME_CLOSE, TCP_TIMEWAIT_LEN);
 			break;
-
 		}
-	}
-	else
+	} else
 		goto discard;
 
-  step6:
-
-	/*
-	 *	step 6: check the URG bit
-	 */
-
+step6:
+	/* step 6: check the URG bit */
 	tcp_urg(sk, th, len);
 
-	/*
-	 *	step 7: process the segment text
-	 */
-
+	/* step 7: process the segment text */
 	switch (sk->state) {
 	case TCP_CLOSE_WAIT:
 	case TCP_CLOSING:
-		if (!before(skb->seq, sk->fin_seq))
+		if (!before(skb->seq, tp->fin_seq))
 			break;
 	
 	case TCP_FIN_WAIT1:
 	case TCP_FIN_WAIT2:
-
-		/*
-		 *	RFC 793 says to queue data in this states,
-		 *	RFC 1122 says we MUST send a reset. 
-		 *	BSD 4.4 also does reset.
+		/* RFC 793 says to queue data in these states,
+		 * RFC 1122 says we MUST send a reset. 
+		 * BSD 4.4 also does reset.
 		 */
-
-		if ((sk->shutdown & RCV_SHUTDOWN) && sk->dead)
-		{
-			if (after(skb->end_seq - th->fin, tp->rcv_nxt))
-			{
+		if ((sk->shutdown & RCV_SHUTDOWN) && sk->dead) {
+			if (after(skb->end_seq - th->fin, tp->rcv_nxt)) {
 				tcp_reset(sk, skb);
 				return 1;
 			}
@@ -1843,22 +1766,16 @@
 		break;
 	}
 
-	/*
-	 *	step 8: check the FIN bit
-	 */
-
+	/* step 8: check the FIN bit */
 	if (th->fin)
-	{
 		tcp_fin(skb, sk, th);
-	}
 
 	tcp_data_snd_check(sk);
 	tcp_ack_snd_check(sk);
 
 	if (queued)
 		return 0;
-  discard:
-
+discard:
 	kfree_skb(skb, FREE_READ);
 	return 0;
 }
@@ -1871,19 +1788,18 @@
 
 	retv = proc_dointvec(ctl, write, filp, buffer, lenp);
 
-	if (write)
-	{
+	if (write) {
 		switch (sysctl_tcp_cong_avoidance) {
-			case 0:
-				tcp_sys_cong_ctl_f = &tcp_cong_avoid_vanj;
-				break;
-			case 1:
-				tcp_sys_cong_ctl_f = &tcp_cong_avoid_vegas;
-				break;
-			default:
-				retv = -EINVAL;
-				sysctl_tcp_cong_avoidance = val;
-		}
+		case 0:
+			tcp_sys_cong_ctl_f = &tcp_cong_avoid_vanj;
+			break;
+		case 1:
+			tcp_sys_cong_ctl_f = &tcp_cong_avoid_vegas;
+			break;
+		default:
+			retv = -EINVAL;
+			sysctl_tcp_cong_avoidance = val;
+		};
 	}
 
 	return retv;
diff -u --recursive --new-file v2.1.35/linux/net/ipv4/tcp_ipv4.c linux/net/ipv4/tcp_ipv4.c
--- v2.1.35/linux/net/ipv4/tcp_ipv4.c	Mon Apr 14 16:28:28 1997
+++ linux/net/ipv4/tcp_ipv4.c	Tue Apr 22 22:46:28 1997
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp_ipv4.c,v 1.30 1997/04/13 10:31:44 davem Exp $
+ * Version:	$Id: tcp_ipv4.c,v 1.39 1997/04/22 02:53:14 davem Exp $
  *
  *		IPv4 specific functions
  *
@@ -27,6 +27,9 @@
  * Changes:
  *		David S. Miller	:	New socket lookup architecture.
  *					This code is dedicated to John Dyson.
+ *		David S. Miller :	Change semantics of established hash,
+ *					half is devoted to TIME_WAIT sockets
+ *					and the rest go in the other half.
  */
 
 #include <linux/config.h>
@@ -41,6 +44,11 @@
 
 #include <asm/segment.h>
 
+extern int sysctl_tcp_sack;
+extern int sysctl_tcp_tsack;
+extern int sysctl_tcp_timestamps;
+extern int sysctl_tcp_window_scaling;
+
 static void tcp_v4_send_reset(struct sk_buff *skb);
 
 void tcp_v4_send_check(struct sock *sk, struct tcphdr *th, int len, 
@@ -49,12 +57,15 @@
 /* This is for sockets with full identity only.  Sockets here will always
  * be without wildcards and will have the following invariant:
  *          TCP_ESTABLISHED <= sk->state < TCP_CLOSE
+ *
+ * First half of the table is for sockets not in TIME_WAIT, second half
+ * is for TIME_WAIT sockets only.
  */
 struct sock *tcp_established_hash[TCP_HTABLE_SIZE];
 
 /* All sockets in TCP_LISTEN state will be in here.  This is the only table
  * where wildcard'd TCP sockets can exist.  Hash function here is just local
- * port number.  XXX Fix or we'll lose with thousands of IP aliases...
+ * port number.
  */
 struct sock *tcp_listening_hash[TCP_LHTABLE_SIZE];
 
@@ -66,7 +77,7 @@
 static __inline__ int tcp_hashfn(__u32 laddr, __u16 lport,
 				 __u32 faddr, __u16 fport)
 {
-	return ((laddr ^ lport) ^ (faddr ^ fport)) & (TCP_HTABLE_SIZE - 1);
+	return ((laddr ^ lport) ^ (faddr ^ fport)) & ((TCP_HTABLE_SIZE/2) - 1);
 }
 
 static __inline__ int tcp_sk_hashfn(struct sock *sk)
@@ -243,10 +254,14 @@
 	if(state != TCP_CLOSE || !sk->dead) {
 		struct sock **skp;
 
-		if(state == TCP_LISTEN)
+		if(state == TCP_LISTEN) {
 			skp = &tcp_listening_hash[tcp_sk_listen_hashfn(sk)];
-		else
-			skp = &tcp_established_hash[tcp_sk_hashfn(sk)];
+		} else {
+			int hash= tcp_sk_hashfn(sk);
+			if(state == TCP_TIME_WAIT)
+				hash += (TCP_HTABLE_SIZE/2);
+			skp = &tcp_established_hash[hash];
+		}
 
 		if((sk->next = *skp) != NULL)
 			(*skp)->pprev = &sk->next;
@@ -262,19 +277,13 @@
  * to specify the remote port nor the remote address for the
  * connection.  So always assume those are both wildcarded
  * during the search since they can never be otherwise.
- *
- * XXX Later on, hash on both local port _and_ local address,
- * XXX to handle a huge IP alias'd box.  Keep in mind that
- * XXX such a scheme will require us to run through the listener
- * XXX hash twice, once for local addresses bound, and once for
- * XXX the local address wildcarded (because the hash is different).
  */
-static struct sock *tcp_v4_lookup_longway(u32 daddr, unsigned short hnum)
+static struct sock *tcp_v4_lookup_listener(u32 daddr, unsigned short hnum)
 {
-	struct sock *sk = tcp_listening_hash[tcp_lhashfn(hnum)];
+	struct sock *sk;
 	struct sock *result = NULL;
 
-	for(; sk; sk = sk->next) {
+	for(sk = tcp_listening_hash[tcp_lhashfn(hnum)]; sk; sk = sk->next) {
 		if(sk->num == hnum) {
 			__u32 rcv_saddr = sk->rcv_saddr;
 
@@ -296,19 +305,28 @@
 {
 	unsigned short hnum = ntohs(dport);
 	struct sock *sk;
+	int hash = tcp_hashfn(daddr, hnum, saddr, sport);
 
 	/* Optimize here for direct hit, only listening connections can
 	 * have wildcards anyways.  It is assumed that this code only
 	 * gets called from within NET_BH.
 	 */
-	sk = tcp_established_hash[tcp_hashfn(daddr, hnum, saddr, sport)];
-	for(; sk; sk = sk->next)
+	for(sk = tcp_established_hash[hash]; sk; sk = sk->next)
 		if(sk->daddr		== saddr		&& /* remote address */
 		   sk->dummy_th.dest	== sport		&& /* remote port    */
 		   sk->num		== hnum			&& /* local port     */
 		   sk->rcv_saddr	== daddr)		   /* local address  */
 			goto hit; /* You sunk my battleship! */
-	sk = tcp_v4_lookup_longway(daddr, hnum);
+
+	/* Must check for a TIME_WAIT'er before going to listener hash. */
+	for(sk = tcp_established_hash[hash+(TCP_HTABLE_SIZE/2)]; sk; sk = sk->next)
+		if(sk->daddr		== saddr		&& /* remote address */
+		   sk->dummy_th.dest	== sport		&& /* remote port    */
+		   sk->num		== hnum			&& /* local port     */
+		   sk->rcv_saddr	== daddr)		   /* local address  */
+			goto hit;
+
+	sk = tcp_v4_lookup_listener(daddr, hnum);
 hit:
 	return sk;
 }
@@ -417,13 +435,27 @@
 		   sk->num		== snum			&& /* local port */
 		   sk->saddr		== saddr) {		   /* local address */
 			retval = 0;
-			break;
+			goto out;
+		}
+	}
+
+	/* Must check TIME_WAIT'ers too. */
+	sk = tcp_established_hash[hashent + (TCP_HTABLE_SIZE/2)];
+	for (; sk != NULL; sk = sk->next) {
+		if(sk->daddr		== daddr		&& /* remote address */
+		   sk->dummy_th.dest	== dnum			&& /* remote port */
+		   sk->num		== snum			&& /* local port */
+		   sk->saddr		== saddr) {		   /* local address */
+			retval = 0;
+			goto out;
 		}
 	}
+out:
 	SOCKHASH_UNLOCK();
 	return retval;
 }
 
+
 /*
  *	This will initiate an outgoing connection. 
  */
@@ -432,7 +464,6 @@
 {
 	struct sk_buff *buff;
 	struct sk_buff *skb1;
-	unsigned char *ptr;
 	int tmp;
 	struct tcphdr *t1;
 	struct rtable *rt;
@@ -442,10 +473,7 @@
 	if (sk->state != TCP_CLOSE) 
 		return(-EISCONN);
 
-	/*
-	 *	Don't allow a double connect.
-	 */
-
+	/* Don't allow a double connect. */
 	if (sk->daddr)
 		return -EINVAL;
 
@@ -505,20 +533,14 @@
 	sk->err = 0;
 	
 	buff = sock_wmalloc(sk, MAX_SYN_SIZE, 0, GFP_KERNEL);
-	if (buff == NULL)
-	{
+	if (buff == NULL) {
 		release_sock(sk);
 		return(-ENOBUFS);
 	}
 
-	/*
-	 *	Put in the IP header and routing stuff.
-	 */
-
+	/* Put in the IP header and routing stuff. */
 	tmp = ip_build_header(buff, sk);
-
-	if (tmp < 0)
-	{
+	if (tmp < 0) {
 		kfree_skb(buff, FREE_WRITE);
 		release_sock(sk);
 		return(-ENETUNREACH);
@@ -535,11 +557,9 @@
 	t1->ack = 0;
 	t1->window = htons(512);
 	t1->syn = 1;
-	t1->doff = 6;
 
-	/* use 512 or whatever user asked for */
-
-	sk->window_clamp=rt->u.dst.window;
+	/* Use 512 or whatever user asked for. */
+	tp->window_clamp = rt->u.dst.window;
 
 	sk->mtu = rt->u.dst.pmtu;
 	if ((sk->ip_pmtudisc == IP_PMTUDISC_DONT ||
@@ -557,17 +577,13 @@
 		sk->mss = (sk->mtu - sizeof(struct iphdr) -
 			   sizeof(struct tcphdr));
 
-	/*
-	 *	Put in the TCP options to say MSS.
-	 */
+	tmp = tcp_syn_build_options(buff, sk->mss, sysctl_tcp_sack,
+		sysctl_tcp_timestamps,
+		sysctl_tcp_window_scaling?tp->rcv_wscale:0);
+	buff->csum = 0;
+	t1->doff = (sizeof(*t1)+ tmp)>>2;
 
-	ptr = skb_put(buff,4);
-	ptr[0] = TCPOPT_MSS;
-	ptr[1] = TCPOLEN_MSS;
-	ptr[2] = (sk->mss) >> 8;
-	ptr[3] = (sk->mss) & 0xff;
-	buff->csum = csum_partial(ptr, 4, 0);
-	tcp_v4_send_check(sk, t1, sizeof(struct tcphdr) + 4, buff);
+	tcp_v4_send_check(sk, t1, sizeof(struct tcphdr) + tmp, buff);
 
 	tcp_set_state(sk,TCP_SYN_SENT);
 
@@ -580,18 +596,18 @@
 
 	tcp_init_xmit_timers(sk);
 
-	/* Now works the right way instead of a hacked initial setting */
-	atomic_set(&sk->retransmits, 0);
+	/* Now works the right way instead of a hacked initial setting. */
+	tp->retransmits = 0;
 
 	skb_queue_tail(&sk->write_queue, buff);
 
-	atomic_inc(&sk->packets_out);
+	tp->packets_out++;
 	buff->when = jiffies;
 
 	skb1 = skb_clone(buff, GFP_KERNEL);
 	ip_queue_xmit(skb1);
 
-	/* Timer for repeating the SYN until an answer  */
+	/* Timer for repeating the SYN until an answer. */
 	tcp_reset_xmit_timer(sk, TIME_RETRANS, tp->rto);
 	tcp_statistics.TcpActiveOpens++;
 	tcp_statistics.TcpOutSegs++;
@@ -604,10 +620,7 @@
 {
 	int retval = -EINVAL;
 
-	/*
-	 *	Do sanity checking for sendmsg/sendto/send
-	 */
-
+	/* Do sanity checking for sendmsg/sendto/send. */
 	if (msg->msg_flags & ~(MSG_OOB|MSG_DONTROUTE|MSG_DONTWAIT))
 		goto out;
 	if (msg->msg_name) {
@@ -650,6 +663,7 @@
 {
 	struct iphdr *iph = (struct iphdr*)dp;
 	struct tcphdr *th = (struct tcphdr*)(dp+(iph->ihl<<2));
+	struct tcp_opt *tp;
 	int type = skb->h.icmph->type;
 	int code = skb->h.icmph->code;
 	struct sock *sk;
@@ -659,26 +673,23 @@
 	if (sk == NULL)
 		return;
 
-	if (type == ICMP_SOURCE_QUENCH)
-	{
-		struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
-
-		sk->ssthresh = max(tp->snd_cwnd >> 1, 2);
-		tp->snd_cwnd = sk->ssthresh + 3;
+	tp = &sk->tp_pinfo.af_tcp;
+	if (type == ICMP_SOURCE_QUENCH) {
+		tp->snd_ssthresh = max(tp->snd_cwnd >> 1, 2);
+		tp->snd_cwnd = tp->snd_ssthresh;
 		tp->high_seq = tp->snd_nxt;
-
 		return;
 	}
 
-	if (type == ICMP_PARAMETERPROB)
-	{
+	if (type == ICMP_PARAMETERPROB) {
 		sk->err=EPROTO;
 		sk->error_report(sk);
 	}
 
+	/* FIXME: What about the IP layer options size here? */
 	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) - sizeof(struct tcphdr);
+			int new_mtu = sk->dst_cache->pmtu - sizeof(struct iphdr) - tp->tcp_header_len;
 			if (new_mtu < sk->mss && new_mtu > 0) {
 				sk->mss = new_mtu;
 			}
@@ -686,24 +697,18 @@
 		return;
 	}
 
-	/*
-	 * If we've already connected we will keep trying
+	/* If we've already connected we will keep trying
 	 * until we time out, or the user gives up.
 	 */
-
-	if (code <= NR_ICMP_UNREACH)
-	{
-		if(icmp_err_convert[code].fatal || sk->state == TCP_SYN_SENT || sk->state == TCP_SYN_RECV)
-		{
+	if (code <= NR_ICMP_UNREACH) {
+		if(icmp_err_convert[code].fatal || sk->state == TCP_SYN_SENT || sk->state == TCP_SYN_RECV) {
 			sk->err = icmp_err_convert[code].errno;
-			if (sk->state == TCP_SYN_SENT || sk->state == TCP_SYN_RECV)
-			{
+			if (sk->state == TCP_SYN_SENT || sk->state == TCP_SYN_RECV) {
 				tcp_statistics.TcpAttemptFails++;
 				tcp_set_state(sk,TCP_CLOSE);
 				sk->error_report(sk);		/* Wake people up to see the error (see connect in sock.c) */
 			}
-		}
-		else	/* Only an error on timeout */
+		} else	/* Only an error on timeout */
 			sk->err_soft = icmp_err_convert[code].errno;
 	}
 }
@@ -714,7 +719,7 @@
 {
 	th->check = 0;
 	th->check = tcp_v4_check(th, len, sk->saddr, sk->daddr,
-				 csum_partial((char *)th, sizeof(*th), skb->csum));
+				 csum_partial((char *)th, th->doff<<2, skb->csum));
 }
 
 /*
@@ -746,10 +751,7 @@
 	skb1->h.th = th1 = (struct tcphdr *)skb_put(skb1, sizeof(struct tcphdr));
 	memset(th1, 0, sizeof(*th1));
 
-	/*
-	 *	Swap the send and the receive.
-	 */
-
+	/* Swap the send and the receive. */
 	th1->dest = th->source;
 	th1->source = th->dest;
 	th1->doff = sizeof(*th1)/4;
@@ -768,6 +770,7 @@
 	skb1->csum = csum_partial((u8 *) th1, sizeof(*th1), 0);
 	th1->check = tcp_v4_check(th1, sizeof(*th1), skb1->nh.iph->saddr,
 				  skb1->nh.iph->daddr, skb1->csum);
+	/* FIXME: should this carry an options packet? */
 	ip_queue_xmit(skb1);
 	tcp_statistics.TcpOutSegs++;
 }
@@ -803,7 +806,7 @@
 	struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
 	struct sk_buff * skb;
 	struct tcphdr *th;
-	unsigned char *ptr;
+	int tmp;
 	int mss;
 
 	skb = sock_wmalloc(sk, MAX_SYN_SIZE, 1, GFP_ATOMIC);
@@ -816,11 +819,16 @@
 		return;
 	}
 
-	mss = (skb->dst->pmtu - sizeof(struct iphdr) + sizeof(struct tcphdr));
+	mss = (skb->dst->pmtu - sizeof(struct iphdr) - sizeof(struct tcphdr));
 	if (sk->user_mss)
 		mss = min(mss, sk->user_mss);
 	skb->h.th = th = (struct tcphdr *) skb_put(skb, sizeof(struct tcphdr));
 
+	/* Don't offer more than they did.
+	 * This way we don't have to memorize who said what.
+	 */
+	req->mss = min(mss, req->mss);
+
 	/* Yuck, make this header setup more efficient... -DaveM */
 	memset(th, 0, sizeof(struct tcphdr));
 	th->syn = 1;
@@ -831,20 +839,23 @@
 	skb->end_seq = skb->seq + 1;
 	th->seq = ntohl(skb->seq);
 	th->ack_seq = htonl(req->rcv_isn + 1);
-	th->doff = sizeof(*th)/4 + 1;
 	th->window = ntohs(tp->rcv_wnd);
 
-	/* FIXME: csum_partial() of a four byte quantity is itself! -DaveM */
-	ptr = skb_put(skb, TCPOLEN_MSS);
-	ptr[0] = TCPOPT_MSS;
-	ptr[1] = TCPOLEN_MSS;
-	ptr[2] = (mss >> 8) & 0xff;
-	ptr[3] = mss & 0xff;
-	skb->csum = csum_partial(ptr, TCPOLEN_MSS, 0);
+	/* XXX Partial csum of 4 byte quantity is itself! -DaveM
+	 * Yes, but it's a bit harder to special case now. It's
+	 * now computed inside the tcp_v4_send_check() to clean up
+	 * updating the options fields in the mainline send code.
+	 * If someone thinks this is really bad let me know and
+	 * I'll try to do it a different way. -- erics
+	 */
 
-	th->check = tcp_v4_check(th, sizeof(*th) + TCPOLEN_MSS,
+	tmp = tcp_syn_build_options(skb, req->mss, req->sack_ok, req->tstamp_ok,
+		(req->snd_wscale)?tp->rcv_wscale:0);
+	skb->csum = 0;
+	th->doff = (sizeof(*th) + tmp)>>2;
+	th->check = tcp_v4_check(th, sizeof(*th) + tmp,
 				 req->af.v4_req.loc_addr, req->af.v4_req.rmt_addr,
-				 csum_partial((char *)th, sizeof(*th), skb->csum));
+				 csum_partial((char *)th, sizeof(*th)+tmp, skb->csum));
 
 	ip_queue_xmit(skb);
 	tcp_statistics.TcpOutSegs++;
@@ -870,23 +881,21 @@
 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 = &(sk->tp_pinfo.af_tcp);
 	struct open_request *req;
 	struct tcphdr *th = skb->h.th;
 	__u32 saddr = skb->nh.iph->saddr;
 	__u32 daddr = skb->nh.iph->daddr;
-	__u16 req_mss;
 
 	/* If the socket is dead, don't accept the connection.	*/
-	if (sk->dead)
-	{
+	if (sk->dead) {
 		SOCK_DEBUG(sk, "Reset on %p: Connect on dead socket.\n",sk);
 		tcp_statistics.TcpAttemptFails++;
 		return -ENOTCONN;
 	}
 
 	if (sk->ack_backlog >= sk->max_ack_backlog ||
-	    tcp_v4_syn_filter(sk, skb, saddr))
-	{
+	    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
@@ -906,10 +915,17 @@
 
 	req->rcv_isn = skb->seq;
 	req->snt_isn = isn;
-	req_mss = tcp_parse_options(th);
-	if (!req_mss)
-		req_mss = 536;
-	req->mss = req_mss;
+	tp->tstamp_ok = tp->sack_ok = tp->snd_wscale = 0;
+	tcp_parse_options(th,tp);
+	if (tp->saw_tstamp) {
+		tp->ts_recent = tp->rcv_tsval;
+		tp->ts_recent_stamp = jiffies;
+	}
+	req->mss = tp->in_mss;
+	req->tstamp_ok = tp->tstamp_ok;
+	req->sack_ok = tp->sack_ok;
+	req->snd_wscale = tp->snd_wscale;
+	req->ts_recent = tp->ts_recent;
 	req->rmt_port = th->source;
 	req->af.v4_req.loc_addr = daddr;
 	req->af.v4_req.rmt_addr = saddr;
@@ -968,12 +984,7 @@
 	skb_queue_head_init(&newsk->out_of_order_queue);
 	skb_queue_head_init(&newsk->error_queue);
 
-	/*
-	 *	Unused
-	 */
-
-	newsk->send_head = NULL;
-
+	/* Unused */
 	newtp = &(newsk->tp_pinfo.af_tcp);
 	newtp->send_head = NULL;
 	newtp->retrans_head = NULL;
@@ -984,15 +995,10 @@
 
 	newsk->prot->init(newsk);
 
-	newsk->cong_count = 0;
-#if 0 /* Don't mess up the initialization we did in the init routine! */
-	newsk->ssthresh = 0;
-#endif
+	newtp->snd_cwnd_cnt = 0;
 	newtp->backoff = 0;
-	newsk->intr = 0;
 	newsk->proc = 0;
 	newsk->done = 0;
-	newsk->partial = NULL;
 	newsk->pair = NULL;
 	atomic_set(&newsk->wmem_alloc, 0);
 	atomic_set(&newsk->rmem_alloc, 0);
@@ -1004,24 +1010,23 @@
 	newsk->shutdown = 0;
 	newsk->ack_backlog = 0;
 
-	newsk->fin_seq = req->rcv_isn;
+	newtp->fin_seq = req->rcv_isn;
 	newsk->syn_seq = req->rcv_isn;
 	newsk->state = TCP_SYN_RECV;
 	newsk->timeout = 0;
-	newsk->ip_xmit_timeout = 0;
 
 	newsk->write_seq = req->snt_isn;
 
 	newtp->snd_wnd = ntohs(skb->h.th->window);
-	newsk->max_window = newtp->snd_wnd;
+	newtp->max_window = newtp->snd_wnd;
 	newtp->snd_wl1 = req->rcv_isn;
 	newtp->snd_wl2 = newsk->write_seq;
 	newtp->snd_una = newsk->write_seq++;
 	newtp->snd_nxt = newsk->write_seq;
 
 	newsk->urg_data = 0;
-	atomic_set(&newsk->packets_out, 0);
-	atomic_set(&newsk->retransmits, 0);
+	newtp->packets_out = 0;
+	newtp->retransmits = 0;
 	newsk->linger=0;
 	newsk->destroy = 0;
 	init_timer(&newsk->timer);
@@ -1034,7 +1039,7 @@
 	newsk->dummy_th.dest = req->rmt_port;
 	newsk->sock_readers=0;
 
-	newtp->rcv_nxt = req->rcv_isn + 1;
+	newtp->last_ack_sent = newtp->rcv_nxt = req->rcv_isn + 1;
 	newtp->rcv_wup = req->rcv_isn + 1;
 	newsk->copied_seq = req->rcv_isn + 1;
 
@@ -1044,9 +1049,7 @@
 	newsk->saddr = req->af.v4_req.loc_addr;
 	newsk->rcv_saddr = req->af.v4_req.loc_addr;
 
-	/*
-	 *	options / mss / route_cache
-	 */
+	/* 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,
@@ -1057,19 +1060,34 @@
 
 	newsk->dst_cache = &rt->u.dst;
 
-	newsk->window_clamp = rt->u.dst.window;
+	newtp->window_clamp = rt->u.dst.window;
 	snd_mss = rt->u.dst.pmtu;
 
+	/* FIXME: is mtu really the same as snd_mss? */
 	newsk->mtu = snd_mss;
+	/* FIXME: where does mtu get used after this? */
 	/* sanity check */
 	if (newsk->mtu < 64)
 		newsk->mtu = 64;
 
+	newtp->sack_ok = req->sack_ok;
+	newtp->tstamp_ok = req->tstamp_ok;
+	newtp->snd_wscale = req->snd_wscale;
+	newtp->ts_recent = req->ts_recent;
+	newtp->ts_recent_stamp = jiffies;
+	if (newtp->tstamp_ok) {
+		newtp->tcp_header_len = sizeof(struct tcphdr) + 12;	/* FIXME: define constant! */
+		newsk->dummy_th.doff += 3;
+	} else {
+		newtp->tcp_header_len = sizeof(struct tcphdr);
+	}
+
 	snd_mss -= sizeof(struct iphdr) + sizeof(struct tcphdr);
 	if (sk->user_mss)
 		snd_mss = min(snd_mss, sk->user_mss);
 
-	newsk->mss = min(req->mss, snd_mss);
+	/* Make sure our mtu is adjusted for headers. */
+	newsk->mss = min(req->mss, snd_mss) + sizeof(struct tcphdr) - newtp->tcp_header_len;
 
 	tcp_v4_hash(newsk);
 	add_to_prot_sklist(newsk);
@@ -1085,10 +1103,10 @@
 	 *	as we checked the user count on tcp_rcv and we're
 	 *	running from a soft interrupt.
 	 */
-	if (!req)
+	if(!req)
 		return sk;
 
-	do {
+	while(req) {
 		if (req->af.v4_req.rmt_addr == skb->nh.iph->saddr &&
 		    req->af.v4_req.loc_addr == skb->nh.iph->daddr &&
 		    req->rmt_port == skb->h.th->source) {
@@ -1122,7 +1140,8 @@
 			req->sk = sk;
 			break;
 		}
-	} while ((req = req->dl_next) != tp->syn_wait_queue);
+		req = req->dl_next;
+	}
 
 	skb_orphan(skb);
 	skb_set_owner_r(skb, sk);
@@ -1146,20 +1165,13 @@
 		goto ok;
 	}
 
-	if (sk->state == TCP_LISTEN)
-	{
+	if (sk->state == TCP_LISTEN) {
 		struct sock *nsk;
 
-		/*
-		 *	find possible connection requests
-		 */
-
+		/* Find possible connection requests. */
 		nsk = tcp_v4_check_req(sk, skb);
-
 		if (nsk == NULL)
-		{
 			goto discard_it;
-		}
 
 		release_sock(sk);
 		lock_sock(nsk);
@@ -1173,9 +1185,7 @@
 	tcp_v4_send_reset(skb);
 
 discard_it:
-	/*
-	 *	Discard frame
-	 */
+	/* Discard frame. */
 	kfree_skb(skb, FREE_READ);
 
 ok:
@@ -1199,25 +1209,19 @@
 	if (skb->pkt_type!=PACKET_HOST)
 		goto discard_it;
 
-	/*
-	 *	Pull up the IP header.
-	 */
-
+	/* Pull up the IP header. */
 	skb_pull(skb, skb->h.raw-skb->data);
 
-	/*
-	 *	Try to use the device checksum if provided.
-	 */
-
-	switch (skb->ip_summed)
-	{
+	/* Try to use the device checksum if provided. */
+	switch (skb->ip_summed) {
 	case CHECKSUM_NONE:
 		skb->csum = csum_partial((char *)th, len, 0);
 	case CHECKSUM_HW:
 		if (tcp_v4_check(th,len,saddr,daddr,skb->csum)) {
 			struct iphdr * iph = skb->nh.iph;
-			printk(KERN_DEBUG "TCPv4 bad checksum from %08x:%04x to %08x:%04x, len=%d/%d/%d\n",
+			printk(KERN_DEBUG "TCPv4 bad checksum from %08x:%04x to %08x:%04x, ack = %u, seq = %u, len=%d/%d/%d\n",
 			       saddr, ntohs(th->source), daddr,
+			       ntohl(th->ack_seq), ntohl(th->seq),
 			       ntohs(th->dest), len, skb->len, ntohs(iph->tot_len));
 					goto discard_it;
 		}
@@ -1243,7 +1247,6 @@
 	skb->end_seq = skb->seq + th->syn + th->fin + len - th->doff*4;
 	skb->ack_seq = ntohl(th->ack_seq);
 
-	skb->acked = 0;
 	skb->used = 0;
 
 	if (!sk->sock_readers)
@@ -1256,9 +1259,7 @@
 	tcp_v4_send_reset(skb);
 
 discard_it:
-	/*
- 	 *	Discard frame
-	 */
+	/* Discard frame. */
 	kfree_skb(skb, FREE_READ);
   	return 0;
 }
@@ -1290,10 +1291,7 @@
 		skb->dst = &rt->u.dst;
 	}
 
-	/*
-	 *	Discard the surplus MAC header
-	 */
-
+	/* Discard the surplus MAC header. */
 	skb_pull(skb, skb->nh.raw-skb->data);
 
 	iph = skb->nh.iph;
@@ -1349,32 +1347,38 @@
 	tp->iat = (HZ/5) << 3;
 
 	tp->rcv_wnd = 8192;
+	tp->tstamp_ok = 0;
+	tp->sack_ok = 0;
+	tp->in_mss = 0;
+	tp->snd_wscale = 0;
+	tp->sacks = 0;
+	tp->saw_tstamp = 0;
 
 	/*
 	 * See draft-stevens-tcpca-spec-01 for discussion of the
 	 * initialization of these values.
 	 */
 	tp->snd_cwnd = 1;
-	sk->ssthresh = 0x7fffffff;	/* Infinity */
+	tp->snd_ssthresh = 0x7fffffff;	/* Infinity */
 
 	sk->priority = 1;
 	sk->state = TCP_CLOSE;
 
-	/* this is how many unacked bytes we will accept for this socket.  */
+	/* This is how many unacked bytes we will accept for this socket. */
 	sk->max_unacked = 2048; /* needs to be at most 2 full packets. */
 	sk->max_ack_backlog = SOMAXCONN;
 
 	sk->mtu = 576;
 	sk->mss = 536;
 
-	/*
-	 *	Speed up by setting some standard state for the dummy_th.
-	 */
-
-	sk->dummy_th.doff = sizeof(sk->dummy_th)/4;
+	/* Speed up by setting some standard state for the dummy_th. */
   	sk->dummy_th.ack=1;
   	sk->dummy_th.doff=sizeof(struct tcphdr)>>2;
 
+	/* Init SYN queue. */
+	tp->syn_wait_queue = NULL;
+	tp->syn_wait_last = &tp->syn_wait_queue;
+
 	sk->tp_pinfo.af_tcp.af_specific = &ipv4_specific;
 
 	return 0;
@@ -1387,27 +1391,15 @@
 	tcp_clear_xmit_timers(sk);
 
 	if (sk->keepopen)
-	{
 		tcp_dec_slow_timer(TCP_SLT_KEEPALIVE);
-	}
 
-	/*
-	 *	Cleanup up the write buffer.
-	 */
-
-  	while((skb = skb_dequeue(&sk->write_queue)) != NULL) {
-		IS_SKB(skb);
+	/* Cleanup up the write buffer. */
+  	while((skb = skb_dequeue(&sk->write_queue)) != NULL)
 		kfree_skb(skb, FREE_WRITE);
-  	}
-
-	/*
-	 *  Cleans up our, hopefuly empty, out_of_order_queue
-	 */
 
-  	while((skb = skb_dequeue(&sk->out_of_order_queue)) != NULL) {
-		IS_SKB(skb);
+	/* Cleans up our, hopefuly empty, out_of_order_queue. */
+  	while((skb = skb_dequeue(&sk->out_of_order_queue)) != NULL)
 		kfree_skb(skb, FREE_READ);
-  	}
 
 	return 0;
 }
diff -u --recursive --new-file v2.1.35/linux/net/ipv4/tcp_output.c linux/net/ipv4/tcp_output.c
--- v2.1.35/linux/net/ipv4/tcp_output.c	Mon Apr 14 16:28:28 1997
+++ linux/net/ipv4/tcp_output.c	Tue Apr 22 22:46:28 1997
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp_output.c,v 1.34 1997/04/12 04:32:33 davem Exp $
+ * Version:	$Id: tcp_output.c,v 1.42 1997/04/22 01:06:33 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -34,14 +34,18 @@
 
 #include <net/tcp.h>
 
-/*
- *	Get rid of any delayed acks, we sent one already..
- */
+extern int sysctl_tcp_sack;
+extern int sysctl_tcp_tsack;
+extern int sysctl_tcp_timestamps;
+extern int sysctl_tcp_window_scaling;
+
+/* Get rid of any delayed acks, we sent one already.. */
 static __inline__ void clear_delayed_acks(struct sock * sk)
 {
-	sk->delayed_acks = 0;
+	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
+	tp->delayed_acks = 0;
 	sk->ack_backlog = 0;
-	sk->bytes_rcv = 0;
 	tcp_clear_xmit_timer(sk, TIME_DACK);
 }
 
@@ -50,12 +54,8 @@
 	struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
 	
 	tp->send_head = tp->send_head->next;
-
 	if (tp->send_head == (struct sk_buff *) &sk->write_queue)
-	{
 		tp->send_head = NULL;
-	}
-
 }
 
 static __inline__ int tcp_snd_test(struct sock *sk, struct sk_buff *skb)
@@ -64,8 +64,7 @@
 	int nagle_check = 1;
 	int len;
 
-	/*
-	 *	RFC 1122 - section 4.2.3.4
+	/*	RFC 1122 - section 4.2.3.4
 	 *
 	 *	We must queue if
 	 *
@@ -76,17 +75,41 @@
 	 *	c) We are retransmiting [Nagle]
 	 *	d) We have too many packets 'in flight'
 	 */
-		
 	len = skb->end_seq - skb->seq;
-
-	if (!sk->nonagle && len < (sk->mss >> 1) && atomic_read(&sk->packets_out))
-	{
+	if (!sk->nonagle && len < (sk->mss >> 1) && tp->packets_out)
 		nagle_check = 0;
-	}
 
-	return (nagle_check && atomic_read(&sk->packets_out) < tp->snd_cwnd &&
+	return (nagle_check && tp->packets_out < tp->snd_cwnd &&
 		!after(skb->end_seq, tp->snd_una + tp->snd_wnd) &&
-		atomic_read(&sk->retransmits) == 0);
+		tp->retransmits == 0);
+}
+
+static __inline__ void tcp_build_options(__u32 *ptr, struct tcp_opt *tp)
+{
+	/* FIXME: We will still need to do SACK here. */
+	if (tp->tstamp_ok) {
+		*ptr++ = ntohl((TCPOPT_NOP << 24)
+			| (TCPOPT_NOP << 16)
+                        | (TCPOPT_TIMESTAMP << 8)
+			| TCPOLEN_TIMESTAMP);
+		/* WARNING: If HZ is ever larger than 1000 on some system,
+	 	 * then we will be violating RFC1323 here because our timestamps
+	 	 * will be moving too fast.
+		 * FIXME: code TCP so it uses at most ~ 1000 ticks a second?
+		 * (I notice alpha is 1024 ticks now). -- erics
+	 	 */
+		*ptr++ = htonl(jiffies);
+		*ptr = htonl(tp->ts_recent);
+	}
+}
+
+static __inline__ void tcp_update_options(__u32 *ptr, struct tcp_opt *tp)
+{
+	/* FIXME: We will still need to do SACK here. */
+	if (tp->tstamp_ok) {
+		*++ptr = htonl(jiffies);
+		*++ptr = htonl(tp->ts_recent);
+	}
 }
 
 /*
@@ -100,75 +123,56 @@
 	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
 	int size;
 
-	/*
-	 *	length of packet (not counting length of pre-tcp headers) 
-	 */
-
+	/* Length of packet (not counting length of pre-tcp headers). */
 	size = skb->len - ((unsigned char *) th - skb->data);
 
-	/*
-	 *	Sanity check it..
-	 */
-
-	if (size < sizeof(struct tcphdr) || size > skb->len) 
-	{
-		printk(KERN_DEBUG "tcp_send_skb: bad skb (skb = %p, data = %p, th = %p, len = %u)\n",
-			skb, skb->data, th, skb->len);
+	/* Sanity check it.. */
+	if (size < sizeof(struct tcphdr) || size > skb->len) {
+		printk(KERN_DEBUG "tcp_send_skb: bad skb "
+		       "(skb = %p, data = %p, th = %p, len = %u)\n",
+		       skb, skb->data, th, skb->len);
 		kfree_skb(skb, FREE_WRITE);
 		return 0;
 	}
 
-	/*
-	 *	If we have queued a header size packet.. (these crash a few
-	 *	tcp stacks if ack is not set)
-	 */
-
-	if (size == sizeof(struct tcphdr))
-	{
-		/* 
-                 * If it's got a syn or fin discard
-                 */
-		if(!th->syn && !th->fin) 
-		{
+	/* If we have queued a header size packet.. (these crash a few
+	 * tcp stacks if ack is not set)
+	 * FIXME: What is the equivalent below when we have options?
+	 */
+	if (size == sizeof(struct tcphdr)) {
+		/* If it's got a syn or fin discard. */
+		if(!th->syn && !th->fin) {
 			printk(KERN_DEBUG "tcp_send_skb: attempt to queue a bogon.\n");
 			kfree_skb(skb,FREE_WRITE);
 			return 0;
 		}
 	}
 
-	/*
-	 *	Actual processing.
-	 */
+	/* Actual processing. */
 	skb->seq = ntohl(th->seq);
 	skb->end_seq = skb->seq + size - 4*th->doff;
 
 	skb_queue_tail(&sk->write_queue, skb);
 
-	if (tp->send_head == NULL && tcp_snd_test(sk, skb))
-	{
+	if (tp->send_head == NULL && tcp_snd_test(sk, skb)) {
 		struct sk_buff * buff;
 
-		/*
-		 *	This is going straight out
-		 */
-
-		th->ack_seq = htonl(tp->rcv_nxt);
+		/* This is going straight out. */
+		tp->last_ack_sent = th->ack_seq = htonl(tp->rcv_nxt);
 		th->window = htons(tcp_select_window(sk));
+		tcp_update_options((__u32 *)(th+1),tp);
 
 		tp->af_specific->send_check(sk, th, size, skb);
 
 		buff = skb_clone(skb, GFP_KERNEL);
-
 		if (buff == NULL)
-		{
 			goto queue;
-		}
 		
 		clear_delayed_acks(sk);
 		skb_set_owner_w(buff, sk);
 
 		tp->snd_nxt = skb->end_seq;
-		atomic_inc(&sk->packets_out);
+		tp->packets_out++;
 
 		skb->when = jiffies;
 
@@ -182,19 +186,13 @@
 	}
 
 queue:
-	/* 
-	 *	Remember where we must start sending
-	 */
-
+	/* Remember where we must start sending. */
 	if (tp->send_head == NULL)
 		tp->send_head = skb;
-
-	if (atomic_read(&sk->packets_out) == 0 && !tp->pending)
-	{
+	if (tp->packets_out == 0 && !tp->pending) {
 		tp->pending = TIME_PROBE0;
 		tcp_reset_xmit_timer(sk, TIME_PROBE0, tp->rto);
 	}
-
 	return 0;
 }
 
@@ -215,86 +213,61 @@
 
 	th = skb->h.th;
 
-	/* size of new segment */
-	nsize = skb->tail - ((unsigned char *) (th + 1)) - len;
-
-	if (nsize <= 0)
-	{
+	/* Size of new segment. */
+	nsize = skb->tail - ((unsigned char *)(th)+tp->tcp_header_len) - len;
+	if (nsize <= 0) {
 		printk(KERN_DEBUG "tcp_fragment: bug size <= 0\n");
 		return -1;
 	}
 
-	/*
-	 *	Get a new skb... force flag on
-	 */
+	/* Get a new skb... force flag on. */
 	buff = sock_wmalloc(sk, nsize + 128 + sk->prot->max_header + 15, 1, 
 			    GFP_ATOMIC);
-
 	if (buff == NULL)
 		return -1;
 
-	/*
-	 *	Put headers on the new packet
-	 */
-
+	/* Put headers on the new packet. */
 	tmp = tp->af_specific->build_net_header(sk, buff);
-
-	if (tmp < 0)
-	{
+	if (tmp < 0) {
 		kfree_skb(buff, FREE_WRITE);
 		return -1;
 	}
 		
-	/*
-	 *	Move the TCP header over
-	 */
-	
-	nth = (struct tcphdr *) skb_put(buff, sizeof(*th));
-
+	/* Move the TCP header over. */
+	nth = (struct tcphdr *) skb_put(buff, tp->tcp_header_len);
 	buff->h.th = nth;
+	memcpy(nth, th, tp->tcp_header_len);
+
+	/* FIXME: Make sure this gets tcp options right. */
 	
-	memcpy(nth, th, sizeof(*th));
-	
-	/*
-	 *	Correct the new header
-	 */
-	
+	/* Correct the new header. */
 	buff->seq = skb->seq + len;
 	buff->end_seq = skb->end_seq;
 	nth->seq = htonl(buff->seq);
 	nth->check = 0;
-	nth->doff  = 5; 
+	nth->doff  = th->doff;
 	
 	/* urg data is always an headache */
-	if (th->urg)
-	{
-		if (th->urg_ptr > len)
-		{
+	if (th->urg) {
+		if (th->urg_ptr > len) {
 			th->urg = 0;
 			nth->urg_ptr -= len;
-		}
-		else
-		{
+		} else {
 			nth->urg = 0;
 		}
 	}
 
-	/*
-	 *	Copy TCP options and data start to our new buffer
-	 */
-	
-	buff->csum = csum_partial_copy(((u8 *)(th + 1)) + len,
+	/* Copy data tail to our new buffer. */
+	buff->csum = csum_partial_copy(((u8 *)(th)+tp->tcp_header_len) + len,
 				       skb_put(buff, nsize),
 				       nsize, 0);
-       
 
 	skb->end_seq -= nsize;
-
 	skb_trim(skb, skb->len - nsize);
 
-	/* remember to checksum this packet afterwards */
+	/* Remember to checksum this packet afterwards. */
 	th->check = 0;
-	skb->csum = csum_partial((u8*) (th + 1), skb->tail - ((u8 *) (th + 1)),
+	skb->csum = csum_partial((u8*)(th) + tp->tcp_header_len, skb->tail - ((u8 *) (th)+tp->tcp_header_len),
 				 0);
 
 	skb_append(skb, buff);
@@ -304,12 +277,10 @@
 
 static void tcp_wrxmit_prob(struct sock *sk, struct sk_buff *skb)
 {
-	/*
-	 *	This is acked data. We can discard it. This 
-	 *	cannot currently occur.
-	 */
+	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
 
-	atomic_set(&sk->retransmits, 0);
+	/* This is acked data. We can discard it. This cannot currently occur. */
+	tp->retransmits = 0;
 
 	printk(KERN_DEBUG "tcp_write_xmit: bug skb in write queue\n");
 
@@ -329,17 +300,13 @@
 	SOCK_DEBUG(sk, "tcp_write_xmit: frag needed size=%d mss=%d\n",
 		   size, sk->mss);
 
-	if (tcp_fragment(sk, skb, sk->mss))
-	{
+	if (tcp_fragment(sk, skb, sk->mss)) {
 		/* !tcp_frament Failed! */
 		tp->send_head = skb;
-		atomic_dec(&sk->packets_out);
+		tp->packets_out--;
 		return -1;
-	}
-	else
-	{
-		/* 
-		 * If tcp_fragment succeded then
+	} else {
+		/* If tcp_fragment succeded then
 		 * the send head is the resulting
 		 * fragment
 		 */
@@ -357,69 +324,52 @@
 void tcp_write_xmit(struct sock *sk)
 {
 	struct sk_buff *skb;
-	struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
 	u16 rcv_wnd;
 	int sent_pkts = 0;
 
-	/*
-	 *	The bytes will have to remain here. In time closedown will
-	 *	empty the write queue and all will be happy
+	/* The bytes will have to remain here. In time closedown will
+	 * empty the write queue and all will be happy.
 	 */
-
 	if(sk->zapped)
 		return;
 
-	/*
-	 *	Anything on the transmit queue that fits the window can
+	/*	Anything on the transmit queue that fits the window can
 	 *	be added providing we are:
 	 *
 	 *	a) following SWS avoidance [and Nagle algorithm]
 	 *	b) not exceeding our congestion window.
 	 *	c) not retransmiting [Nagle]
 	 */
-
 	rcv_wnd = htons(tcp_select_window(sk));
-
-	while((skb = tp->send_head) && tcp_snd_test(sk, skb))
-	{
+	while((skb = tp->send_head) && tcp_snd_test(sk, skb)) {
 		struct tcphdr *th;
 		struct sk_buff *buff;
 		int size;
 
-		IS_SKB(skb);
-
-		/*
-		 *	See if we really need to send the packet.
-		 *	(debugging code)
-		 */
-
-		if (!after(skb->end_seq, tp->snd_una))
-		{
+		/* See if we really need to send the packet. (debugging code) */
+		if (!after(skb->end_seq, tp->snd_una)) {
 			tcp_wrxmit_prob(sk, skb);
 			continue;
-		} 
-
+		}
 
-		/*
-		 *	Put in the ack seq and window at this point rather
+		/*	Put in the ack seq and window at this point rather
 		 *	than earlier, in order to keep them monotonic.
 		 *	We really want to avoid taking back window allocations.
 		 *	That's legal, but RFC1122 says it's frowned on.
 		 *	Ack and window will in general have changed since
 		 *	this packet was put on the write queue.
 		 */
-
 		th = skb->h.th;
 		size = skb->len - (((unsigned char *) th) - skb->data);
-
-		if (size - (th->doff << 2) > sk->mss)
-		{
+		if (size - (th->doff << 2) > sk->mss) {
 			if (tcp_wrxmit_frag(sk, skb, size))
 				break;
 		}
 
-		th->ack_seq = htonl(tp->rcv_nxt);
+		tp->last_ack_sent = th->ack_seq = htonl(tp->rcv_nxt);
 		th->window = rcv_wnd;
+		tcp_update_options((__u32 *)(th+1),tp);
 
 		tp->af_specific->send_check(sk, th, size, skb);
 
@@ -430,18 +380,14 @@
 #endif
 
 		buff = skb_clone(skb, GFP_ATOMIC);
-
 		if (buff == NULL)
 			break;
 
-		/*
-		 *	Advance the send_head. This one is going out.
-		 */
-
+		/* Advance the send_head.  This one is going out. */
 		update_send_head(sk);
 		clear_delayed_acks(sk);
 
-		atomic_inc(&sk->packets_out);
+		tp->packets_out++;
 		skb_set_owner_w(buff, sk);
 
 		tp->snd_nxt = skb->end_seq;
@@ -450,13 +396,10 @@
 
 		sent_pkts = 1;
 		tp->af_specific->queue_xmit(buff);
-
 	}
 
 	if (sent_pkts && !tcp_timer_is_set(sk, TIME_RETRANS))
-	{
 		tcp_reset_xmit_timer(sk, TIME_RETRANS, tp->rto);
-	}
 }
 
 
@@ -469,33 +412,25 @@
  *	2. We limit memory per socket
  */
 
-
 unsigned short tcp_select_window(struct sock *sk)
 {
 	struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
 	int mss = sk->mss;
 	long free_space = sock_rspace(sk);
-	long window;
-	long cur_win;
-	long usable;
+	long window, cur_win, usable;
 
-	
-	if (sk->window_clamp)
-	{
-		free_space = min(sk->window_clamp, free_space);
-		mss = min(sk->window_clamp, mss);
+	if (tp->window_clamp) {
+		free_space = min(tp->window_clamp, free_space);
+		mss = min(tp->window_clamp, mss);
 	}
 	
-	/*
-	 * compute the actual window i.e.
+	/* compute the actual window i.e.
 	 * old_window - received_bytes_on_that_win
 	 */
-
 	cur_win = tp->rcv_wup - (tp->rcv_nxt - tp->rcv_wnd);
 	window  = tp->rcv_wnd;
 	
-	if ( cur_win < 0 )
-	{
+	if (cur_win < 0) {
 		cur_win = 0;
 		printk(KERN_DEBUG "TSW: win < 0 w=%d 1=%u 2=%u\n",
 		       tp->rcv_wnd, tp->rcv_nxt, tp->rcv_wup);
@@ -511,49 +446,33 @@
 	 * it MSS bytes
 	 */
 
-	/*
-	 * It would be a good idea if it didn't break header prediction.
+	/* It would be a good idea if it didn't break header prediction.
 	 * and BSD made the header predition standard...
 	 * It expects the same value in the header i.e. th->window to be
 	 * constant
 	 */
-
 	usable = free_space - cur_win;
 	if (usable < 0)
-	{
 		usable = 0;
-	}
 
-	if ( window <  usable )
-	{
-		/*
-		 *	Window is not blocking the sender
+	if (window < usable) {
+		/*	Window is not blocking the sender
 		 *	and we have enought free space for it
 		 */
-
 		if (cur_win > (sk->mss << 1))
 			goto out;
 	}
-
        	
-	if (window >= usable)
-	{
-		/*
-		 *	We are offering too much, cut it down... 
+	if (window >= usable) {
+		/*	We are offering too much, cut it down... 
 		 *	but don't shrink the window
 		 */
-		
 		window = max(usable, cur_win);
-	}
-	else
-	{	
+	} else {
 		if ((usable - window) >= mss)
-		{
 			window += mss;
-		}
 	}
-
-  out:
+out:
 	tp->rcv_wnd = window;
 	tp->rcv_wup = tp->rcv_nxt;
 	return window;
@@ -561,6 +480,7 @@
 
 static int tcp_retrans_try_collapse(struct sock *sk, struct sk_buff *skb)
 {
+	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
 	struct tcphdr *th1, *th2;
 	int size1, size2, avail;
 	struct sk_buff *buff = skb->next;
@@ -572,54 +492,35 @@
 
 	avail = skb_tailroom(skb);
 
-	/*
-	 *  size of tcp payload
-	 */
-
-	size1 = skb->tail - (u8 *) (th1 + 1);
+	/* Size of TCP payload. */
+	size1 = skb->tail - ((u8 *) (th1)+(th1->doff<<2));
 	
 	th2 = buff->h.th;
-
-	size2 = buff->tail - (u8 *) (th2 + 1); 
+	size2 = buff->tail - ((u8 *) (th2)+(th2->doff<<2)); 
 
 	if (size2 > avail || size1 + size2 > sk->mss )
 		return -1;
 
-	/*
-	 *  ok. we will be able to collapse the packet
-	 */
-
+	/* Ok.  We will be able to collapse the packet. */
 	skb_unlink(buff);
-
 	memcpy(skb_put(skb, size2), ((char *) th2) + (th2->doff << 2), size2);
 	
-	/*
-	 * update sizes on original skb. both TCP and IP
-	 */
- 
+	/* Update sizes on original skb, both TCP and IP. */
 	skb->end_seq += size2;
-
-	if (th2->urg)
-	{
+	if (th2->urg) {
 		th1->urg = 1;
 		th1->urg_ptr = th2->urg_ptr + size1;
 	}
 
-	/*
-	 * ... and off you go.
-	 */
-
+	/* ... and off you go. */
 	kfree_skb(buff, FREE_WRITE);
-	atomic_dec(&sk->packets_out);
+	tp->packets_out--;
 
-	/* 
-	 *	Header checksum will be set by the retransmit procedure
-	 *	after calling rebuild header
+	/* Header checksum will be set by the retransmit procedure
+	 * after calling rebuild header.
 	 */
-
 	th1->check = 0;
-	skb->csum = csum_partial((u8*) (th1+1), size1 + size2, 0);
-
+	skb->csum = csum_partial((u8*)(th1)+(th1->doff<<2), size1 + size2, 0);
 	return 0;
 }
 
@@ -643,17 +544,13 @@
 	if (tp->retrans_head == tp->send_head)
 		tp->retrans_head = NULL;
 	
-	while ((skb = tp->retrans_head) != NULL)
-	{
+	while ((skb = tp->retrans_head) != NULL) {
 		struct sk_buff *buff;
 		struct tcphdr *th;
 		int tcp_size;
 		int size;
 
-		IS_SKB(skb);
-		
-		/*
-		 * In general it's OK just to use the old packet.  However we
+		/* In general it's OK just to use the old packet.  However we
 		 * need to use the current ack and window fields.  Urg and
 		 * urg_ptr could possibly stand to be updated as well, but we
 		 * don't keep the necessary data.  That shouldn't be a problem,
@@ -663,28 +560,23 @@
 
 		th = skb->h.th;
 
-		tcp_size = skb->tail - ((unsigned char *) (th + 1));
+		tcp_size = skb->tail - ((unsigned char *)(th)+tp->tcp_header_len);
 
-		if (tcp_size > sk->mss)
-		{
-			if (tcp_fragment(sk, skb, sk->mss))
-			{
+		if (tcp_size > sk->mss) {
+			if (tcp_fragment(sk, skb, sk->mss)) {
 				printk(KERN_DEBUG "tcp_fragment failed\n");
 				return;
 			}
-			atomic_inc(&sk->packets_out);
+			tp->packets_out++;
 		}
 
 		if (!th->syn &&
 		    tcp_size < (sk->mss >> 1) &&
 		    skb->next != tp->send_head &&
 		    skb->next != (struct sk_buff *)&sk->write_queue)
-		{
 			tcp_retrans_try_collapse(sk, skb);
-		}	       		
 
-		if (tp->af_specific->rebuild_header(sk, skb)) 
-		{
+		if (tp->af_specific->rebuild_header(sk, skb)) {
 #ifdef TCP_DEBUG
 			printk(KERN_DEBUG "tcp_do_rebuild_header failed\n");
 #endif
@@ -693,12 +585,10 @@
 
 		SOCK_DEBUG(sk, "retransmit sending\n");
 
-		/*
-		 *	update ack and window
-		 */
-
-		th->ack_seq = htonl(tp->rcv_nxt);
+		/* Update ack and window. */
+		tp->last_ack_sent = th->ack_seq = htonl(tp->rcv_nxt);
 		th->window = ntohs(tcp_select_window(sk));
+		tcp_update_options((__u32 *)(th+1),tp);
 
 		size = skb->tail - (unsigned char *) th;
 		tp->af_specific->send_check(sk, th, size, skb);
@@ -706,49 +596,32 @@
 		skb->when = jiffies;
 
 		buff = skb_clone(skb, GFP_ATOMIC);
-
 		if (buff == NULL)
 			break;
+
 		skb_set_owner_w(buff, sk);
 
 		clear_delayed_acks(sk);
-
 		tp->af_specific->queue_xmit(buff);
 		
-		/*
-		 *	Count retransmissions
-		 */
-		 
+		/* Count retransmissions. */
 		ct++;
-		sk->prot->retransmits++; /* ???: atomic_t necessary here? -DaveM */
+		sk->prot->retransmits++;
 		tcp_statistics.TcpRetransSegs++;
 
-		tp->high_seq = tp->snd_nxt;
-
-		/*
-		 *	Only one retransmit requested.
-		 */
-	
+		/* Only one retransmit requested. */
 		if (!all)
 			break;
 
-		/*
-		 *	This should cut it off before we send too many packets.
-		 */
-
+		/* This should cut it off before we send too many packets. */
 		if (ct >= tp->snd_cwnd)
 			break;
 
-		/*
-		 *	Advance the pointer
-		 */
-		
+		/* Advance the pointer. */
 		tp->retrans_head = skb->next;
 		if ((tp->retrans_head == tp->send_head) ||
 		    (tp->retrans_head == (struct sk_buff *) &sk->write_queue))
-		{
 			tp->retrans_head = NULL;
-		}
 	}
 }
 
@@ -764,53 +637,40 @@
 	struct sk_buff *buff;
 	int tmp;
 	
-		
-	buff = sock_wmalloc(sk, MAX_RESET_SIZE, 1, GFP_KERNEL);
-
-	if (buff == NULL)
-	{
-		/* This is a disaster if it occurs */
+	buff = sock_wmalloc(sk, BASE_ACK_SIZE + tp->tcp_header_len, 1, GFP_KERNEL);
+	if (buff == NULL) {
+		/* FIXME: This is a disaster if it occurs. */
 		printk(KERN_INFO "tcp_send_fin: Impossible malloc failure");
 		return;
 	}
 
-	/*
-	 *	Administrivia
-	 */
-	 
+	/* Administrivia. */
 	buff->csum = 0;
 
-	/*
-	 *	Put in the IP header and routing stuff. 
-	 */
-
+	/* Put in the IP header and routing stuff. */
 	tmp = tp->af_specific->build_net_header(sk, buff);
-
-	if (tmp < 0) 
-	{
+	if (tmp < 0) {
 		int t;
-  		/*
-  		 *	Finish anyway, treat this as a send that got lost. 
-  		 *	(Not good).
+
+  		/* FIXME: We must not throw this out. Eventually we must
+                 * put a FIN into the queue, otherwise it never gets queued.
   		 */
-  		 
 		kfree_skb(buff, FREE_WRITE);
 		sk->write_seq++;
-		t=del_timer(&sk->timer);
-		if(t)
+		t = del_timer(&sk->timer);
+		if (t)
 			add_timer(&sk->timer);
 		else
 			tcp_reset_msl_timer(sk, TIME_CLOSE, TCP_TIMEWAIT_LEN);
 		return;
 	}
 	
-	/*
-	 *	We ought to check if the end of the queue is a buffer and
-	 *	if so simply add the fin to that buffer, not send it ahead.
+	/* We ought to check if the end of the queue is a buffer and
+	 * if so simply add the fin to that buffer, not send it ahead.
 	 */
-
-	t1 =(struct tcphdr *)skb_put(buff,sizeof(struct tcphdr));
+	t1 =(struct tcphdr *)skb_put(buff,tp->tcp_header_len);
 	buff->h.th =  t1;
+	tcp_build_options((__u32 *)(t1+1),tp);
 
 	memcpy(t1, th, sizeof(*t1));
 	buff->seq = sk->write_seq;
@@ -821,26 +681,19 @@
 	t1->window = htons(tcp_select_window(sk));
 	t1->fin = 1;
 
-	tp->af_specific->send_check(sk, t1, sizeof(*t1), buff);
+	tp->af_specific->send_check(sk, t1, tp->tcp_header_len, buff);
 
-	/*
-	 *	The fin can only be transmited after the data.
- 	 */
- 	
+	/* The fin can only be transmited after the data. */
 	skb_queue_tail(&sk->write_queue, buff);
-
- 	if (tp->send_head == NULL)
-	{
+ 	if (tp->send_head == NULL) {
 		struct sk_buff *skb1;
 
-		atomic_inc(&sk->packets_out);
+		tp->packets_out++;
 		tp->snd_nxt = sk->write_seq;
 		buff->when = jiffies;
 
 		skb1 = skb_clone(buff, GFP_KERNEL);
-
-		if (skb1)
-		{
+		if (skb1) {
 			skb_set_owner_w(skb1, sk);
 			tp->af_specific->queue_xmit(skb1);
 		}
@@ -856,20 +709,14 @@
 	struct sk_buff * skb;	
 	struct sk_buff * buff;
 	struct tcphdr *th;
-	unsigned char *ptr;
 	int tmp;
 	
 	skb = sock_wmalloc(sk, MAX_SYN_SIZE, 1, GFP_ATOMIC);
-
 	if (skb == NULL) 
-	{
 		return -ENOMEM;
-	}
 
 	tmp = tp->af_specific->build_net_header(sk, skb);
-	
-	if (tmp < 0)
-	{
+	if (tmp < 0) {
 		kfree_skb(skb, FREE_WRITE);
 		return tmp;
 	}
@@ -890,27 +737,23 @@
 
 	th->window = ntohs(tp->rcv_wnd);
 
-	th->ack_seq = htonl(tp->rcv_nxt);
-	th->doff = sizeof(*th)/4 + 1;
+	tp->last_ack_sent = th->ack_seq = htonl(tp->rcv_nxt);
 
-	ptr = skb_put(skb, TCPOLEN_MSS);
-	ptr[0] = TCPOPT_MSS;
-	ptr[1] = TCPOLEN_MSS;
-	ptr[2] = ((sk->mss) >> 8) & 0xff;
-	ptr[3] = (sk->mss) & 0xff;
-	skb->csum = csum_partial(ptr, TCPOLEN_MSS, 0);
+	tmp = tcp_syn_build_options(skb, sk->mss,
+		tp->sack_ok, tp->tstamp_ok,
+		tp->snd_wscale?tp->rcv_wscale:0);
+	skb->csum = 0;
+	th->doff = (sizeof(*th) + tmp)>>2;
 
-	tp->af_specific->send_check(sk, th, sizeof(*th)+4, skb);
+	tp->af_specific->send_check(sk, th, sizeof(*th)+tmp, skb);
 
 	skb_queue_tail(&sk->write_queue, skb);
 	
 	buff = skb_clone(skb, GFP_ATOMIC);
-
-	if (buff)
-	{
+	if (buff) {
 		skb_set_owner_w(buff, sk);
 
-		atomic_inc(&sk->packets_out);
+		tp->packets_out++;
 		skb->when = jiffies;
 
 		tp->af_specific->queue_xmit(buff);
@@ -935,22 +778,19 @@
 	struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
 	unsigned long timeout, now;
 
-	/* Calculate new timeout */
+	/* Calculate new timeout. */
 	now = jiffies;
 	timeout = tp->ato;
 
-	if (timeout > max_timeout || sk->bytes_rcv > (sk->mss << 2))
-	{
+	if (timeout > max_timeout ||
+	    ((tp->rcv_nxt - tp->rcv_wup) > (sk->mss << 2)))
 		timeout = now;
-	}
 	else
 		timeout += now;
 
-	/* Use new timeout only if there wasn't a older one earlier  */
+	/* Use new timeout only if there wasn't a older one earlier. */
 	if (!del_timer(&tp->delack_timer) || timeout < tp->delack_timer.expires)
-	{
 		tp->delack_timer.expires = timeout;
-	}
 
 	add_timer(&tp->delack_timer);
 }
@@ -968,75 +808,53 @@
 	struct tcphdr *th;
 	int tmp;
 
-	
 	if(sk->zapped)
-	{
-		/* We have been reset, we may not send again */
-		return;		
-	}
+		return;	/* We have been reset, we may not send again. */
 
-	/*
-	 * We need to grab some memory, and put together an ack,
+	/* We need to grab some memory, and put together an ack,
 	 * and then put it into the queue to be sent.
+	 * FIXME: is it better to waste memory here and use a
+	 * constant sized ACK?
 	 */
-
-	buff = sock_wmalloc(sk, MAX_ACK_SIZE, 1, GFP_ATOMIC);
-	if (buff == NULL) 
-	{
-		/* 
-		 *	Force it to send an ack. We don't have to do this
-		 *	(ACK is unreliable) but it's much better use of 
+	buff = sock_wmalloc(sk, BASE_ACK_SIZE + tp->tcp_header_len, 1, GFP_ATOMIC);
+	if (buff == NULL) {
+		/*	Force it to send an ack. We don't have to do this
+		 *	(ACK is unreliable) but it's much better use of
 		 *	bandwidth on slow links to send a spare ack than
-		 *	resend packets. 
+		 *	resend packets.
 		 */
-		 
 		tcp_send_delayed_ack(sk, HZ/2);
 		return;
 	}
 
 	clear_delayed_acks(sk);
 
-	/*
-	 *	Assemble a suitable TCP frame
-	 */
-	 
+	/* Assemble a suitable TCP frame. */
 	buff->csum = 0;
 
-	/* 
-	 *	Put in the IP header and routing stuff. 
-	 */
-	 
+	/* Put in the IP header and routing stuff. */
 	tmp = tp->af_specific->build_net_header(sk, buff);
-
-	if (tmp < 0) 
-	{
+	if (tmp < 0) {
 		kfree_skb(buff, FREE_WRITE);
 		return;
 	}
 
-	th =(struct tcphdr *)skb_put(buff,sizeof(struct tcphdr));
-
+	th = (struct tcphdr *)skb_put(buff,tp->tcp_header_len);
 	memcpy(th, &sk->dummy_th, sizeof(struct tcphdr));
+	tcp_build_options((__u32 *)(th+1),tp);
 
-	/*
-	 *	Swap the send and the receive. 
-	 */
-	 
+	/* Swap the send and the receive. */
 	th->window	= ntohs(tcp_select_window(sk));
 	th->seq		= ntohl(tp->snd_nxt);
-	th->ack_seq	= ntohl(tp->rcv_nxt);
-
-  	/*
-  	 *	Fill in the packet and send it
-  	 */
+	tp->last_ack_sent = th->ack_seq	= ntohl(tp->rcv_nxt);
 
-	tp->af_specific->send_check(sk, th, sizeof(struct tcphdr), buff);
+  	/* Fill in the packet and send it. */
+	tp->af_specific->send_check(sk, th, tp->tcp_header_len, buff);
 
 	SOCK_DEBUG(sk, "\rtcp_send_ack: seq %x ack %x\n",
 		   tp->snd_nxt, tp->rcv_nxt);
 
 	tp->af_specific->queue_xmit(buff);
-
   	tcp_statistics.TcpOutSegs++;
 }
 
@@ -1053,61 +871,44 @@
 	int tmp;
 
 	if (sk->zapped)
-		return;	/* After a valid reset we can send no more */
+		return;	/* After a valid reset we can send no more. */
 
-	/*
-	 *	Write data can still be transmitted/retransmitted in the
+	/*	Write data can still be transmitted/retransmitted in the
 	 *	following states.  If any other state is encountered, return.
 	 *	[listen/close will never occur here anyway]
 	 */
-
 	if (sk->state != TCP_ESTABLISHED && 
 	    sk->state != TCP_CLOSE_WAIT &&
 	    sk->state != TCP_FIN_WAIT1 && 
 	    sk->state != TCP_LAST_ACK &&
-	    sk->state != TCP_CLOSING
-	) 
-	{
+	    sk->state != TCP_CLOSING)
 		return;
-	}
-
-	if (before(tp->snd_nxt, tp->snd_una + tp->snd_wnd) && 
-	    (skb=tp->send_head))
-	{
-		/*
-	    	 * We are probing the opening of a window
-	    	 * but the window size is != 0
-	    	 * must have been a result SWS avoidance ( sender )
-	    	 */
 
+	if (before(tp->snd_nxt, tp->snd_una + tp->snd_wnd) && (skb=tp->send_head)) {
 		struct tcphdr *th;
 		unsigned long win_size;
 
+		/* We are probing the opening of a window
+	    	 * but the window size is != 0
+	    	 * must have been a result SWS avoidance ( sender )
+	    	 */
 		win_size = tp->snd_wnd - (tp->snd_nxt - tp->snd_una);
-
-		if (win_size < skb->end_seq - skb->seq)
-		{
-			if (tcp_fragment(sk, skb, win_size))
-			{
+		if (win_size < skb->end_seq - skb->seq) {
+			if (tcp_fragment(sk, skb, win_size)) {
 				printk(KERN_DEBUG "tcp_write_wakeup: "
 				       "fragment failed\n");
 				return;
 			}
 		}
 
-			    	
 		th = skb->h.th;
-		
-		tp->af_specific->send_check(sk, th, th->doff * 4 + win_size, 
-					    skb);
-
+		tp->af_specific->send_check(sk, th, th->doff * 4 + win_size, skb);
 		buff = skb_clone(skb, GFP_ATOMIC);
 		if (buff == NULL)
-		{
 			return;
-		}
+
 		skb_set_owner_w(buff, sk);
-		atomic_inc(&sk->packets_out);
+		tp->packets_out++;
 
 		clear_delayed_acks(sk);
 
@@ -1115,36 +916,29 @@
 			tcp_reset_xmit_timer(sk, TIME_RETRANS, tp->rto);
 
 		skb->when = jiffies;
-
 		update_send_head(sk);
-
 		tp->snd_nxt = skb->end_seq;
-	}
-	else
-	{	
-		buff = sock_wmalloc(sk,MAX_ACK_SIZE, 1, GFP_ATOMIC);
+	} else {
+		buff = sock_wmalloc(sk, MAX_ACK_SIZE, 1, GFP_ATOMIC);
 		if (buff == NULL) 
 			return;
 
 		buff->csum = 0;
 
-		/*
-		 *	Put in the IP header and routing stuff. 
-		 */
-
+		/* Put in the IP header and routing stuff. */
 		tmp = tp->af_specific->build_net_header(sk, buff);
-
-		if (tmp < 0)
-		{
+		if (tmp < 0) {
 			kfree_skb(buff, FREE_WRITE);
 			return;
 		}
 
 		t1 = (struct tcphdr *) skb_put(buff, sizeof(struct tcphdr));
 		memcpy(t1,(void *) &sk->dummy_th, sizeof(*t1));
+		/* FIXME: should zero window probes have SACK and/or TIMESTAMP data?
+		 * If so we have to tack them on here.
+		 */
 
-		/*
-		 *	Use a previous sequence.
+		/*	Use a previous sequence.
 		 *	This should cause the other end to send an ack.
 		 */
 	 
@@ -1153,13 +947,13 @@
 		t1->ack_seq = htonl(tp->rcv_nxt);
 		t1->window = htons(tcp_select_window(sk));
 
+		/* Value from dummy_th may be larger. */
+		t1->doff = sizeof(struct tcphdr)/4;
+
 		tp->af_specific->send_check(sk, t1, sizeof(*t1), buff);
 	}
 
-	/*
-	 *	Send it.
-	 */
-
+	/* Send it. */
 	tp->af_specific->queue_xmit(buff);
 	tcp_statistics.TcpOutSegs++;
 }
@@ -1175,16 +969,12 @@
 	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
 
 	if (sk->zapped)
-		return;		/* After a valid reset we can send no more */
-
+		return; /* After a valid reset we can send no more. */
 
 	tcp_write_wakeup(sk);
-
 	tp->pending = TIME_PROBE0;
-
 	tp->backoff++;
 	tp->probes_out++;
-
 	tcp_reset_xmit_timer (sk, TIME_PROBE0, 
 			      min(tp->rto << tp->backoff, 120*HZ));
 }
diff -u --recursive --new-file v2.1.35/linux/net/ipv4/tcp_timer.c linux/net/ipv4/tcp_timer.c
--- v2.1.35/linux/net/ipv4/tcp_timer.c	Mon Apr 14 16:28:28 1997
+++ linux/net/ipv4/tcp_timer.c	Tue Apr 22 22:46:28 1997
@@ -34,8 +34,8 @@
 
 
 struct tcp_sl_timer tcp_slt_array[TCP_SLT_MAX] = {
-	{ATOMIC_INIT, TCP_SYNACK_PERIOD, 0, tcp_syn_recv_timer},/* SYNACK	*/
-	{ATOMIC_INIT, TCP_KEEPALIVE_PERIOD, 0, tcp_keepalive}	/* KEEPALIVE	*/
+	{ATOMIC_INIT(0), TCP_SYNACK_PERIOD, 0, tcp_syn_recv_timer},/* SYNACK	*/
+	{ATOMIC_INIT(0), TCP_KEEPALIVE_PERIOD, 0, tcp_keepalive}   /* KEEPALIVE	*/
 };
 
 /*
@@ -67,16 +67,14 @@
 {
 	struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
 
-	if((long)when <= 0)
-	{		
+	if((long)when <= 0) {
 		printk(KERN_DEBUG "xmit_timer <= 0 - timer:%d when:%lx\n", what, when);
 		when=HZ/50;
 	}
 
 	switch (what) {
 	case TIME_RETRANS:
-		/*
-		 * When seting the transmit timer the probe timer 
+		/* When seting the transmit timer the probe timer 
 		 * should not be set.
 		 * The delayed ack timer can be set if we are changing the
 		 * retransmit timer when removing acked frames.
@@ -105,7 +103,7 @@
 
 	default:
 		printk(KERN_DEBUG "bug: unknown timer value\n");
-	}
+	};
 }
 
 void tcp_clear_xmit_timer(struct sock *sk, int what)
@@ -124,7 +122,7 @@
 		break;	
 	default:
 		printk(KERN_DEBUG "bug: unknown timer value\n");
-	}
+	};
 }
 
 int tcp_timer_is_set(struct sock *sk, int what)
@@ -143,7 +141,7 @@
 		break;	
 	default:
 		printk(KERN_DEBUG "bug: unknown timer value\n");
-	}
+	};
 	return 0;
 }
 
@@ -162,28 +160,25 @@
 
 static int tcp_write_timeout(struct sock *sk)
 {
+	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+
 	/*
 	 *	Look for a 'soft' timeout.
 	 */
 	if ((sk->state == TCP_ESTABLISHED &&
-	     atomic_read(&sk->retransmits) &&
-	     !(atomic_read(&sk->retransmits) & 7)) ||
-	    (sk->state != TCP_ESTABLISHED &&
-	     atomic_read(&sk->retransmits) > TCP_RETR1)) 
-	{
-		/*
-		 *	Attempt to recover if arp has changed (unlikely!) or
+
+	     /* Eric, what the heck is this doing?!?! */
+	     tp->retransmits && !(tp->retransmits & 7)) ||
+
+	    (sk->state != TCP_ESTABLISHED && tp->retransmits > TCP_RETR1)) {
+		/*	Attempt to recover if arp has changed (unlikely!) or
 		 *	a route has shifted (not supported prior to 1.3).
 		 */
 		ip_rt_advice((struct rtable**)&sk->dst_cache, 0);
 	}
 	
-	/*
-	 *	Have we tried to SYN too many times (repent repent 8))
-	 */
-	 
-	if(atomic_read(&sk->retransmits) > TCP_SYN_RETRIES && sk->state==TCP_SYN_SENT)
-	{
+	/* Have we tried to SYN too many times (repent repent 8)) */
+	if(tp->retransmits > TCP_SYN_RETRIES && sk->state==TCP_SYN_SENT) {
 		if(sk->err_soft)
 			sk->err=sk->err_soft;
 		else
@@ -199,11 +194,9 @@
 		/* Don't FIN, we got nothing back */
 		return 0;
 	}
-	/*
-	 *	Has it gone just too far ?
-	 */
-	if (atomic_read(&sk->retransmits) > TCP_RETR2) 
-	{
+
+	/* Has it gone just too far? */
+	if (tp->retransmits > TCP_RETR2) {
 		if(sk->err_soft)
 			sk->err = sk->err_soft;
 		else
@@ -212,19 +205,12 @@
 
 		tcp_clear_xmit_timers(sk);
 
-		/*
-		 *	Time wait the socket 
-		 */
-		if (sk->state == TCP_FIN_WAIT1 || sk->state == TCP_FIN_WAIT2 || sk->state == TCP_CLOSING ) 
-		{
+		/* Time wait the socket. */
+		if (sk->state == TCP_FIN_WAIT1 || sk->state == TCP_FIN_WAIT2 || sk->state == TCP_CLOSING) {
 			tcp_set_state(sk,TCP_TIME_WAIT);
 			tcp_reset_msl_timer (sk, TIME_CLOSE, TCP_TIMEWAIT_LEN);
-		}
-		else
-		{
-			/*
-			 *	Clean up time.
-			 */
+		} else {
+			/* Clean up time. */
 			tcp_set_state(sk, TCP_CLOSE);
 			return 0;
 		}
@@ -238,14 +224,10 @@
 	struct sock *sk = (struct sock*)data;
 
 	if(sk->zapped)
-	{
 		return;
-	}
 	
-	if (sk->delayed_acks)
-	{
+	if (sk->tp_pinfo.af_tcp.delayed_acks)
 		tcp_read_wakeup(sk); 		
-	}
 }
 
 void tcp_probe_timer(unsigned long data) {
@@ -254,16 +236,10 @@
 	struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
 
 	if(sk->zapped) 
-	{		
 		return;
-	}
 	
-	if (sk->sock_readers) 
-	{
-		/* 
-		 * Try again in second 
-		 */
-
+	if (sk->sock_readers) {
+		/* Try again in second. */
 		tcp_reset_xmit_timer(sk, TIME_PROBE0, HZ);
 		return;
 	}
@@ -273,28 +249,20 @@
 	 *	FIXME: We ought not to do it, Solaris 2.5 actually has fixing
 	 *	this behaviour in Solaris down as a bug fix. [AC]
 	 */
-	if (tp->probes_out > TCP_RETR2) 
-	{
+	if (tp->probes_out > TCP_RETR2) {
 		if(sk->err_soft)
 			sk->err = sk->err_soft;
 		else
 			sk->err = ETIMEDOUT;
 		sk->error_report(sk);
 
-		/*
-		 *	Time wait the socket 
-		 */
+		/* Time wait the socket. */
 		if (sk->state == TCP_FIN_WAIT1 || sk->state == TCP_FIN_WAIT2 
-		    || sk->state == TCP_CLOSING ) 
-		{
+		    || sk->state == TCP_CLOSING) {
 			tcp_set_state(sk, TCP_TIME_WAIT);
 			tcp_reset_msl_timer (sk, TIME_CLOSE, TCP_TIMEWAIT_LEN);
-		}
-		else
-		{
-			/*
-			 *	Clean up time.
-			 */
+		} else {
+			/* Clean up time. */
 			tcp_set_state(sk, TCP_CLOSE);
 		}
 	}
@@ -307,24 +275,19 @@
 	int res = 0;
 
 	if (sk->state == TCP_ESTABLISHED || sk->state == TCP_CLOSE_WAIT ||
-	    sk->state == TCP_FIN_WAIT2)
-	{
+	    sk->state == TCP_FIN_WAIT2) {
 		struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
 		__u32 elapsed = jiffies - tp->rcv_tstamp;
 
-		if (elapsed >= TCP_KEEPALIVE_TIME)
-		{
-			if (tp->probes_out > TCP_KEEPALIVE_PROBES)
-			{
+		if (elapsed >= TCP_KEEPALIVE_TIME) {
+			if (tp->probes_out > TCP_KEEPALIVE_PROBES) {
 				if(sk->err_soft)
 					sk->err = sk->err_soft;
 				else
 					sk->err = ETIMEDOUT;
 
 				tcp_set_state(sk, TCP_CLOSE);
-			}
-			else
-			{
+			} else {
 				tp->probes_out++;
 				tp->pending = TIME_KEEPOPEN;
 				tcp_write_wakeup(sk);
@@ -354,6 +317,16 @@
 /* Keepopen's are only valid for "established" TCP's, nicely our listener
  * hash gets rid of most of the useless testing, so we run through a couple
  * of the established hash chains each clock tick.  -DaveM
+ *
+ * And now, even more magic... TIME_WAIT TCP's cannot have keepalive probes
+ * going off for them, so we only need check the first half of the established
+ * hash table, even less testing under heavy load.
+ *
+ * I _really_ would rather do this by adding a new timer_struct to struct sock,
+ * and this way only those who set the keepalive option will get the overhead.
+ * The idea is you set it for 2 hours when the sock is first connected, when it
+ * does fire off (if at all, most sockets die earlier) you check for the keepalive
+ * option and also if the sock has been idle long enough to start probing.
  */
 static void tcp_keepalive(unsigned long data)
 {
@@ -361,7 +334,7 @@
 	int count = 0;
 	int i;
 	
-	for(i = chain_start; i < (chain_start + (TCP_HTABLE_SIZE >> 2)); i++) {
+	for(i = chain_start; i < (chain_start + ((TCP_HTABLE_SIZE/2) >> 2)); i++) {
 		struct sock *sk = tcp_established_hash[i];
 		while(sk) {
 			if(sk->keepopen) {
@@ -373,7 +346,8 @@
 		}
 	}
 out:
-	chain_start = ((chain_start + (TCP_HTABLE_SIZE>>2)) & (TCP_HTABLE_SIZE - 1));
+	chain_start = ((chain_start + ((TCP_HTABLE_SIZE/2)>>2)) &
+		       ((TCP_HTABLE_SIZE/2) - 1));
 }
 
 /*
@@ -394,48 +368,35 @@
 	struct sock *sk = (struct sock*)data;
 	struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
 
-	/*
-	 *	We are reset. We will send no more retransmits.
-	 */
-
-	if(sk->zapped)
-	{
+	/* We are reset. We will send no more retransmits. */
+	if(sk->zapped) {
 		tcp_clear_xmit_timer(sk, TIME_RETRANS);
 		return;
 	}
 
 	lock_sock(sk);
 
-	/*
-	 * Clear delay ack timer
-	 */
-
+	/* Clear delay ack timer. */
 	tcp_clear_xmit_timer(sk, TIME_DACK);
 
-	/*
-	 *	Retransmission
-	 */
-
+	/* Retransmission. */
 	tp->retrans_head = NULL;
-
-	if (atomic_read(&sk->retransmits) == 0)
-	{
-		/*
-		 * remember window where we lost
+	if (tp->retransmits == 0) {
+		/* remember window where we lost
 		 * "one half of the current window but at least 2 segments"
 		 */
-
-		sk->ssthresh = max(tp->snd_cwnd >> 1, 2);
-		sk->cong_count = 0;
+		tp->snd_ssthresh = max(tp->snd_cwnd >> 1, 2);
+		tp->snd_cwnd_cnt = 0;
 		tp->snd_cwnd = 1;
 	}
 
-	atomic_inc(&sk->retransmits);
+	tp->retransmits++;
 
+	tp->dup_acks = 0;
+	tp->high_seq = tp->snd_nxt;
 	tcp_do_retransmit(sk, 0);
 
-	/*
-	 * Increase the timeout each time we retransmit.  Note that
+	/* Increase the timeout each time we retransmit.  Note that
 	 * we do not increase the rtt estimate.  rto is initialized
 	 * from rtt, but increases here.  Jacobson (SIGCOMM 88) suggests
 	 * that doubling rto each time is the least we can get away with.
@@ -450,8 +411,7 @@
 	 * implemented ftp to mars will work nicely. We will have to fix
 	 * the 120 second clamps though!
 	 */
-
-	tp->backoff++;
+	tp->backoff++;	/* FIXME: always same as retransmits? -- erics */
 	tp->rto = min(tp->rto << 1, 120*HZ);
 	tcp_reset_xmit_timer(sk, TIME_RETRANS, tp->rto);
 
@@ -521,7 +481,7 @@
 						conn->expires = now + timeo;
 						tcp_synq_queue(tp, conn);
 					}
-				} while (req != tp->syn_wait_queue);
+				} while (req);
 			}
 			sk = sk->next;
 		}
@@ -535,16 +495,13 @@
 	unsigned long now = jiffies;
 	int i;
 
-	for (i=0; i < TCP_SLT_MAX; i++, slt++)
-	{
-		if (atomic_read(&slt->count))
-		{
+	for (i=0; i < TCP_SLT_MAX; i++, slt++) {
+		if (atomic_read(&slt->count)) {
 			long trigger;
 
 			trigger = slt->period - ((long)(now - slt->last));
 
-			if (trigger <= 0)
-			{
+			if (trigger <= 0) {
 				(*slt->handler)((unsigned long) slt);
 				slt->last = now;
 				trigger = slt->period;
@@ -553,8 +510,7 @@
 		}
 	}
 
-	if (next != ~0UL)
-	{
+	if (next != ~0UL) {
 		tcp_slow_timer.expires = now + next;
 		add_timer(&tcp_slow_timer);
 	}
@@ -570,13 +526,10 @@
 		
 	when = now + slt->period;
 	if (del_timer(&tcp_slow_timer))
-	{
 		next = tcp_slow_timer.expires;
-	}
+
 	if (next && ((long)(next - when) < 0))
-	{
 		when = next;
-	}
 		
 	tcp_slow_timer.expires = when;
 	add_timer(&tcp_slow_timer);
diff -u --recursive --new-file v2.1.35/linux/net/ipv4/udp.c linux/net/ipv4/udp.c
--- v2.1.35/linux/net/ipv4/udp.c	Mon Apr 14 16:28:28 1997
+++ linux/net/ipv4/udp.c	Tue Apr 22 22:46:28 1997
@@ -446,10 +446,16 @@
 			kfree_skb(skb2, FREE_READ);
 	}
   	
-	if (type == ICMP_SOURCE_QUENCH) 
-	{	/* Slow down! */
+	if (type == ICMP_SOURCE_QUENCH) {
+#if 0 /* FIXME:	If you check the rest of the code, this is a NOP!
+       * 	Someone figure out what we were trying to be doing
+       * 	here.  Besides, cong_window is a TCP thing and thus
+       * 	I moved it out of normal sock and into tcp_opt.
+       */
+		/* Slow down! */
 		if (sk->cong_window > 1) 
 			sk->cong_window = sk->cong_window/2;
+#endif
 		return;
 	}
 
diff -u --recursive --new-file v2.1.35/linux/net/ipv6/addrconf.c linux/net/ipv6/addrconf.c
--- v2.1.35/linux/net/ipv6/addrconf.c	Mon Apr 14 16:28:28 1997
+++ linux/net/ipv6/addrconf.c	Thu Apr 17 13:20:52 1997
@@ -5,7 +5,7 @@
  *	Authors:
  *	Pedro Roque		<roque@di.fc.ul.pt>	
  *
- *	$Id: addrconf.c,v 1.16 1997/04/12 04:32:44 davem Exp $
+ *	$Id: addrconf.c,v 1.18 1997/04/16 05:58:03 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -69,7 +69,7 @@
  */
 struct inet6_dev		*inet6_dev_lst[IN6_ADDR_HSIZE];
 
-static atomic_t			addr_list_lock = ATOMIC_INIT;
+static atomic_t			addr_list_lock = ATOMIC_INIT(0);
 
 void addrconf_verify(unsigned long);
 
diff -u --recursive --new-file v2.1.35/linux/net/ipv6/ipv6_sockglue.c linux/net/ipv6/ipv6_sockglue.c
--- v2.1.35/linux/net/ipv6/ipv6_sockglue.c	Mon Apr 14 16:28:28 1997
+++ linux/net/ipv6/ipv6_sockglue.c	Tue Apr 22 22:46:28 1997
@@ -7,7 +7,7 @@
  *
  *	Based on linux/net/ipv4/ip_sockglue.c
  *
- *	$Id: ipv6_sockglue.c,v 1.9 1997/04/07 06:55:51 davem Exp $
+ *	$Id: ipv6_sockglue.c,v 1.11 1997/04/20 09:44:33 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -53,7 +53,7 @@
 struct ipv6_mib ipv6_statistics={0, };
 struct packet_type ipv6_packet_type =
 {
-	0, 
+	__constant_htons(ETH_P_IPV6), 
 	NULL,					/* All devices */
 	ipv6_rcv,
 	NULL,
@@ -241,8 +241,6 @@
 
 void ipv6_init(void)
 {
-	ipv6_packet_type.type = ntohs(ETH_P_IPV6);
-
 	dev_add_pack(&ipv6_packet_type);
 
 #if defined(MODULE) && defined(CONFIG_SYSCTL)
diff -u --recursive --new-file v2.1.35/linux/net/ipv6/proc.c linux/net/ipv6/proc.c
--- v2.1.35/linux/net/ipv6/proc.c	Mon Apr 14 16:28:28 1997
+++ linux/net/ipv6/proc.c	Tue Apr 22 22:46:28 1997
@@ -7,7 +7,7 @@
  *		PROC file system.  This is very similar to the IPv4 version,
  *		except it reports the sockets in the INET6 address family.
  *
- * Version:	$Id: proc.c,v 1.2 1997/04/12 04:32:55 davem Exp $
+ * Version:	$Id: proc.c,v 1.4 1997/04/20 22:50:44 schenk Exp $
  *
  * Authors:	David S. Miller (davem@caip.rutgers.edu)
  *
@@ -61,15 +61,15 @@
 		destp = ntohs(sp->dummy_th.dest);
 		srcp  = ntohs(sp->dummy_th.source);
 
-		timer_active1 = del_timer(&sp->retransmit_timer);
+		timer_active1 = del_timer(&tp->retransmit_timer);
 		timer_active2 = del_timer(&sp->timer);
-		if(!timer_active1) sp->retransmit_timer.expires = 0;
+		if(!timer_active1) tp->retransmit_timer.expires = 0;
 		if(!timer_active2) sp->timer.expires = 0;
 		timer_active = 0;
 		timer_expires = (unsigned) -1;
-		if(timer_active1 && sp->retransmit_timer.expires < timer_expires) {
+		if(timer_active1 && tp->retransmit_timer.expires < timer_expires) {
 			timer_active = timer_active1;
-			timer_expires = sp->retransmit_timer.expires;
+			timer_expires = tp->retransmit_timer.expires;
 		}
 		if(timer_active2 && sp->timer.expires < timer_expires) {
 			timer_active = timer_active2;
@@ -86,12 +86,12 @@
 			format==0?sp->write_seq-tp->snd_una:atomic_read(&sp->wmem_alloc),
 			format==0?tp->rcv_nxt-sp->copied_seq:atomic_read(&sp->rmem_alloc),
 			timer_active, timer_expires-jiffies,
-			(unsigned) atomic_read(&sp->retransmits),
+			tp->retransmits,
 			sp->socket ? sp->socket->inode->i_uid:0,
 			timer_active?sp->timeout:0,
 			sp->socket ? sp->socket->inode->i_ino:0);
 
-		if(timer_active1) add_timer(&sp->retransmit_timer);
+		if(timer_active1) add_timer(&tp->retransmit_timer);
 		if(timer_active2) add_timer(&sp->timer);
 		len += sprintf(buffer+len, "%-148s\n", tmpbuf);
 		if(len >= length)
diff -u --recursive --new-file v2.1.35/linux/net/ipv6/route.c linux/net/ipv6/route.c
--- v2.1.35/linux/net/ipv6/route.c	Mon Apr 14 16:28:28 1997
+++ linux/net/ipv6/route.c	Thu Apr 17 13:20:52 1997
@@ -5,7 +5,7 @@
  *	Authors:
  *	Pedro Roque		<roque@di.fc.ul.pt>	
  *
- *	$Id: route.c,v 1.10 1997/04/12 04:32:57 davem Exp $
+ *	$Id: route.c,v 1.11 1997/04/16 05:58:05 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -62,7 +62,7 @@
 };
 
 struct rt6_info ip6_null_entry = {
-	{{NULL, ATOMIC_INIT, ATOMIC_INIT, NULL,
+	{{NULL, ATOMIC_INIT(0), ATOMIC_INIT(0), NULL,
 	  0, 0, 0, 0, 0, 0, 0, 0, -ENETUNREACH, NULL, NULL,
 	  ip6_pkt_discard, ip6_pkt_discard, &ip6_dst_ops}},
 	NULL, {{{0}}}, 256, RTF_REJECT|RTF_NONEXTHOP, ~0UL,
@@ -93,7 +93,7 @@
 #define ip6_rt_policy (0)
 #endif
 
-static atomic_t	rt6_tbl_lock	= ATOMIC_INIT;
+static atomic_t	rt6_tbl_lock	= ATOMIC_INIT(0);
 static int	rt6_bh_mask	= 0;
 
 #define RT_BH_REQUEST		1
diff -u --recursive --new-file v2.1.35/linux/net/ipv6/tcp_ipv6.c linux/net/ipv6/tcp_ipv6.c
--- v2.1.35/linux/net/ipv6/tcp_ipv6.c	Mon Apr 14 16:28:28 1997
+++ linux/net/ipv6/tcp_ipv6.c	Tue Apr 22 22:46:28 1997
@@ -5,7 +5,7 @@
  *	Authors:
  *	Pedro Roque		<roque@di.fc.ul.pt>	
  *
- *	$Id: tcp_ipv6.c,v 1.20 1997/04/13 10:31:48 davem Exp $
+ *	$Id: tcp_ipv6.c,v 1.27 1997/04/22 02:53:20 davem Exp $
  *
  *	Based on: 
  *	linux/net/ipv4/tcp.c
@@ -41,6 +41,10 @@
 
 #include <asm/uaccess.h>
 
+extern int sysctl_tcp_sack;
+extern int sysctl_tcp_timestamps;
+extern int sysctl_tcp_window_scaling;
+
 static void	tcp_v6_send_reset(struct in6_addr *saddr,
 				  struct in6_addr *daddr,
 				  struct tcphdr *th, struct proto *prot,
@@ -65,7 +69,8 @@
 
 	hashent ^= (laddr->s6_addr32[0] ^ laddr->s6_addr32[1]);
 	hashent ^= (faddr->s6_addr32[0] ^ faddr->s6_addr32[1]);
-	return (hashent & (TCP_HTABLE_SIZE - 1));
+	hashent ^= (faddr->s6_addr32[2] ^ faddr->s6_addr32[3]);
+	return (hashent & ((TCP_HTABLE_SIZE/2) - 1));
 }
 
 static __inline__ int tcp_v6_sk_hashfn(struct sock *sk)
@@ -166,11 +171,14 @@
 	if(state != TCP_CLOSE) {
 		struct sock **skp;
 
-		if(state == TCP_LISTEN)
+		if(state == TCP_LISTEN) {
 			skp = &tcp_listening_hash[tcp_sk_listen_hashfn(sk)];
-		else
-			skp = &tcp_established_hash[tcp_v6_sk_hashfn(sk)];
-
+		} else {
+			int hash = tcp_v6_sk_hashfn(sk);
+			if(state == TCP_TIME_WAIT)
+				hash += (TCP_HTABLE_SIZE/2);
+			skp = &tcp_established_hash[hash];
+		}
 		if((sk->next = *skp) != NULL)
 			(*skp)->pprev = &sk->next;
 		*skp = sk;
@@ -180,11 +188,12 @@
 	SOCKHASH_UNLOCK();
 }
 
-static struct sock *tcp_v6_lookup_longway(struct in6_addr *daddr, unsigned short hnum)
+static struct sock *tcp_v6_lookup_listener(struct in6_addr *daddr, unsigned short hnum)
 {
-	struct sock *sk = tcp_listening_hash[tcp_lhashfn(hnum)];
+	struct sock *sk;
 	struct sock *result = NULL;
 
+	sk = tcp_listening_hash[tcp_lhashfn(hnum)];
 	for(; sk; sk = sk->next) {
 		if((sk->num == hnum) && (sk->family == AF_INET6)) {
 			struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6;
@@ -207,13 +216,13 @@
 {
 	unsigned short hnum = ntohs(dport);
 	struct sock *sk;
+	int hash = tcp_v6_hashfn(daddr, hnum, saddr, sport);
 
 	/* Optimize here for direct hit, only listening connections can
 	 * have wildcards anyways.  It is assumed that this code only
 	 * gets called from within NET_BH.
 	 */
-	sk = tcp_established_hash[tcp_v6_hashfn(daddr, hnum, saddr, sport)];
-	for(; sk; sk = sk->next)
+	for(sk = tcp_established_hash[hash]; sk; sk = sk->next)
 		/* For IPV6 do the cheaper port and family tests first. */
 		if(sk->num		== hnum			&& /* local port     */
 		   sk->family		== AF_INET6		&& /* address family */
@@ -221,7 +230,17 @@
 		   !ipv6_addr_cmp(&sk->net_pinfo.af_inet6.daddr, saddr)	&&
 		   !ipv6_addr_cmp(&sk->net_pinfo.af_inet6.rcv_saddr, daddr))
 			goto hit; /* You sunk my battleship! */
-	sk = tcp_v6_lookup_longway(daddr, hnum);
+
+	/* Must check for a TIME_WAIT'er before going to listener hash. */
+	for(sk = tcp_established_hash[hash+(TCP_HTABLE_SIZE/2)]; sk; sk = sk->next)
+		if(sk->num		== hnum			&& /* local port     */
+		   sk->family		== AF_INET6		&& /* address family */
+		   sk->dummy_th.dest	== sport		&& /* remote port    */
+		   !ipv6_addr_cmp(&sk->net_pinfo.af_inet6.daddr, saddr)	&&
+		   !ipv6_addr_cmp(&sk->net_pinfo.af_inet6.rcv_saddr, daddr))
+			goto hit;
+
+	sk = tcp_v6_lookup_listener(daddr, hnum);
 hit:
 	return sk;
 }
@@ -267,7 +286,7 @@
 	struct tcphdr *th;
 	struct sk_buff *buff;
 	struct sk_buff *skb1;
-	__u8 *ptr;
+	int tmp;
 	int addr_type;
 
 	if (sk->state != TCP_CLOSE) 
@@ -369,6 +388,8 @@
 		ipv6_addr_copy(&np->saddr, saddr);
 	}
 
+	/* FIXME: Need to do tcp_v6_unique_address() here! -DaveM */
+
 	/*
 	 *	Init variables
 	 */
@@ -413,9 +434,8 @@
 	th->ack = 0;
 	th->window = 2;
 	th->syn = 1;
-	th->doff = 6;
 
-	sk->window_clamp = 0;
+	tp->window_clamp = 0;
 
 	sk->mtu = dst->pmtu;
 	sk->mss = sk->mtu - sizeof(struct ipv6hdr) - sizeof(struct tcphdr);
@@ -424,14 +444,12 @@
 	 *	Put in the TCP options to say MTU.
 	 */
 
-	ptr = skb_put(buff,4);
-	ptr[0] = 2;
-	ptr[1] = 4;
-	ptr[2] = (sk->mss) >> 8;
-	ptr[3] = (sk->mss) & 0xff;
-	buff->csum = csum_partial(ptr, 4, 0);
-
-	tcp_v6_send_check(sk, th, sizeof(struct tcphdr) + 4, buff);
+        tmp = tcp_syn_build_options(buff, sk->mss, sysctl_tcp_sack,
+                sysctl_tcp_timestamps,
+                sysctl_tcp_window_scaling?tp->rcv_wscale:0);
+        th->doff = sizeof(*th)/4 + (tmp>>2);
+	buff->csum = 0;
+	tcp_v6_send_check(sk, th, sizeof(struct tcphdr) + tmp, buff);
 
 	tcp_set_state(sk, TCP_SYN_SENT);
 
@@ -445,10 +463,10 @@
 
 	tcp_init_xmit_timers(sk);
 
-	atomic_set(&sk->retransmits, 0);
+	tp->retransmits = 0;
 
 	skb_queue_tail(&sk->write_queue, buff);
-	atomic_inc(&sk->packets_out);
+	tp->packets_out++;
 	buff->when = jiffies;
 	skb1 = skb_clone(buff, GFP_KERNEL);
 	skb_set_owner_w(skb1, sk);
@@ -573,9 +591,9 @@
 	struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
 	struct sk_buff * skb;
 	struct tcphdr *th;
-	unsigned char *ptr;
 	struct dst_entry *dst;
 	struct flowi fl;
+	int tmp;
 
 	skb = sock_wmalloc(sk, MAX_SYN_SIZE, 1, GFP_ATOMIC);
 	if (skb == NULL)
@@ -615,17 +633,12 @@
 	
 	th->window = ntohs(tp->rcv_wnd);
 
-	/* FIXME: csum_partial() of a four byte quantity is itself! -DaveM */
-	ptr = skb_put(skb, TCPOLEN_MSS);
-	ptr[0] = TCPOPT_MSS;
-	ptr[1] = TCPOLEN_MSS;
-	ptr[2] = (dst->pmtu >> 8) & 0xff;
-	ptr[3] = dst->pmtu & 0xff;
-	skb->csum = csum_partial(ptr, TCPOLEN_MSS, 0);
-
-	th->check = tcp_v6_check(th, sizeof(*th) + TCPOLEN_MSS,
+	tmp = tcp_syn_build_options(skb, sk->mss, req->sack_ok, req->tstamp_ok,
+		(req->snd_wscale)?tp->rcv_wscale:0);
+	th->doff = sizeof(*th)/4 + (tmp>>2);
+	th->check = tcp_v6_check(th, sizeof(*th) + tmp,
 				 &req->af.v6_req.loc_addr, &req->af.v6_req.rmt_addr,
-				 csum_partial((char *)th, sizeof(*th), skb->csum));
+				 csum_partial((char *)th, sizeof(*th)+tmp, skb->csum));
 
 	ip6_dst_store(sk, dst);
 	ip6_xmit(sk, skb, &fl, req->af.v6_req.opt);
@@ -646,6 +659,7 @@
 static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb, void *ptr,
 			       __u32 isn)
 {
+	struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
 	struct open_request *req;
 	__u16 req_mss;
 	
@@ -680,7 +694,8 @@
 	req->rcv_isn = skb->seq;
 	req->snt_isn = isn;
 
-	req_mss = tcp_parse_options(skb->h.th);
+	tcp_parse_options(skb->h.th,tp);
+	req_mss = tp->in_mss;
 	if (!req_mss)
 		req_mss = 536;
 	req->mss = req_mss;
@@ -714,7 +729,7 @@
 	th->check = 0;
 	
 	th->check = csum_ipv6_magic(&np->saddr, &np->daddr, len, IPPROTO_TCP, 
-				    csum_partial((char *)th, sizeof(*th), 
+				    csum_partial((char *)th, th->doff<<2, 
 						 skb->csum));
 }
 
@@ -773,8 +788,6 @@
 	 *	Unused
 	 */
 
-	newsk->send_head = NULL;
-
 	newtp = &(newsk->tp_pinfo.af_tcp);
 	np = &newsk->net_pinfo.af_inet6;
 
@@ -787,13 +800,13 @@
 
 	newsk->prot->init(newsk);
 
-	newsk->cong_count = 0;
-	newsk->ssthresh = 0;
+	newtp->snd_cwnd_cnt = 0;
+#if 0 /* Don't mess up the initialization we did in the init routine! */
+	newtp->snd_ssthresh = 0;
+#endif
 	newtp->backoff = 0;
-	newsk->intr = 0;
 	newsk->proc = 0;
 	newsk->done = 0;
-	newsk->partial = NULL;
 	newsk->pair = NULL;
 	atomic_set(&newsk->wmem_alloc, 0);
 	atomic_set(&newsk->rmem_alloc, 0);
@@ -805,24 +818,23 @@
 	newsk->shutdown = 0;
 	newsk->ack_backlog = 0;
 
-	newsk->fin_seq = req->rcv_isn;
+	newtp->fin_seq = req->rcv_isn;
 	newsk->syn_seq = req->rcv_isn;
 	newsk->state = TCP_SYN_RECV;
 	newsk->timeout = 0;
-	newsk->ip_xmit_timeout = 0;
 
 	newsk->write_seq = req->snt_isn;
 
 	newtp->snd_wnd = ntohs(skb->h.th->window);
-	newsk->max_window = newtp->snd_wnd;
+	newtp->max_window = newtp->snd_wnd;
 	newtp->snd_wl1 = req->rcv_isn;
 	newtp->snd_wl2 = newsk->write_seq;
 	newtp->snd_una = newsk->write_seq++;
 	newtp->snd_nxt = newsk->write_seq;
 
 	newsk->urg_data = 0;
-	atomic_set(&newsk->packets_out, 0);
-	atomic_set(&newsk->retransmits, 0);
+	newtp->packets_out = 0;
+	newtp->retransmits = 0;
 	newsk->linger=0;
 	newsk->destroy = 0;
 	init_timer(&newsk->timer);
@@ -861,13 +873,25 @@
 
 	ip6_dst_store(newsk, dst);
 
+        newtp->sack_ok = req->sack_ok;
+        newtp->tstamp_ok = req->tstamp_ok;
+        newtp->snd_wscale = req->snd_wscale;
+        newtp->ts_recent = req->ts_recent;
+        if (newtp->tstamp_ok) {
+                newtp->tcp_header_len = sizeof(struct tcphdr) + 12; /* FIXME: define the contant. */
+                newsk->dummy_th.doff += 3;
+        } else {
+                newtp->tcp_header_len = sizeof(struct tcphdr);
+        }
+  
 	if (dst->error)
 		newsk->mtu = req->af.v6_req.dev->mtu;
 	else
 		newsk->mtu = dst->pmtu;
 
-	newsk->mss = min(req->mss, (newsk->mtu - sizeof(struct ipv6hdr) -
-				    sizeof(struct tcphdr)));
+	newsk->mss = min(req->mss+sizeof(struct tcphdr)-newtp->tcp_header_len,
+		(newsk->mtu - sizeof(struct ipv6hdr) - newtp->tcp_header_len));
+	/* XXX tp->window_clamp??? -DaveM */
 
 	newsk->daddr	= LOOPBACK4_IPV6;
 	newsk->saddr	= LOOPBACK4_IPV6;
@@ -957,7 +981,7 @@
 	if (!req)
 		return sk;
 
-	do {
+	while(req) {
 		if (!ipv6_addr_cmp(&req->af.v6_req.rmt_addr, &skb->nh.ipv6h->saddr) &&
 		    !ipv6_addr_cmp(&req->af.v6_req.loc_addr, &skb->nh.ipv6h->daddr) &&
 		    req->rmt_port == skb->h.th->source) {
@@ -994,7 +1018,8 @@
 			req->sk = sk;
 			break;
 		}
-	} while ((req = req->dl_next) != tp->syn_wait_queue);
+		req = req->dl_next;
+	}
 	return sk;
 }
 
@@ -1057,7 +1082,6 @@
 		skb->end_seq = skb->seq + th->syn + th->fin + len - th->doff*4;
 		skb->ack_seq = ntohl(th->ack_seq);
 
-		skb->acked = 0;
 		skb->used = 0;
 	}
 
@@ -1286,7 +1310,7 @@
 
 	/* start with only sending one packet at a time. */
 	tp->snd_cwnd = 1;
-	sk->ssthresh = 0x7fffffff;
+	tp->snd_ssthresh = 0x7fffffff;
 
 	sk->priority = 1;
 	sk->state = TCP_CLOSE;
@@ -1306,6 +1330,10 @@
   	sk->dummy_th.ack=1;
   	sk->dummy_th.doff=sizeof(struct tcphdr)>>2;
 
+	/* Init SYN queue. */
+	tp->syn_wait_queue = NULL;
+	tp->syn_wait_last = &tp->syn_wait_queue;
+
 	sk->tp_pinfo.af_tcp.af_specific = &ipv6_specific;
 
 	return 0;
@@ -1325,19 +1353,15 @@
 	 *	Cleanup up the write buffer.
 	 */
 
-  	while((skb = skb_dequeue(&sk->write_queue)) != NULL) {
-		IS_SKB(skb);
+  	while((skb = skb_dequeue(&sk->write_queue)) != NULL)
 		kfree_skb(skb, FREE_WRITE);
-  	}
 
 	/*
 	 *  Cleans up our, hopefuly empty, out_of_order_queue
 	 */
 
-  	while((skb = skb_dequeue(&sk->out_of_order_queue)) != NULL) {
-		IS_SKB(skb);
+  	while((skb = skb_dequeue(&sk->out_of_order_queue)) != NULL)
 		kfree_skb(skb, FREE_READ);
-  	}
 
 	/*
 	 *	Release destination entry
diff -u --recursive --new-file v2.1.35/linux/net/unix/af_unix.c linux/net/unix/af_unix.c
--- v2.1.35/linux/net/unix/af_unix.c	Mon Apr 14 16:28:29 1997
+++ linux/net/unix/af_unix.c	Fri Apr 18 10:53:54 1997
@@ -936,6 +936,7 @@
 	if (scm->fp)
 		unix_attach_fds(scm, skb);
 
+	skb->h.raw = skb->data;
 	memcpy_fromiovec(skb_put(skb,len), msg->msg_iov, len);
 
 	other = unix_peer(sk);
