diff -u --recursive --new-file v1.3.43/linux/Documentation/cdrom/aztcd linux/Documentation/cdrom/aztcd
--- v1.3.43/linux/Documentation/cdrom/aztcd	Sun Oct 29 11:38:47 1995
+++ linux/Documentation/cdrom/aztcd	Sat Nov 25 17:28:41 1995
@@ -1,9 +1,9 @@
-$Id: README.aztcd,v 1.90 1995/10/21 17:52:16 root Exp root $
-                       Readme-File README.aztcd
+$Id: README.aztcd,v 2.0 1995/11/10 19:37:18 root Exp root $
+          Readme-File /usr/src/Documentation/cdrom/aztcd
            for Aztech CD-ROM CDA268-01A, ORCHID CD-3110,
                   OKANO/WEARNES CDD110, Conrad TXC
                            CD-ROM Driver 
-                       Version 1.9 and newer
+                       Version 2.0 and newer
                    (for other drives see 6.-8.)
 
 NOTE: THIS DRIVER WILL WORK WITH THE CD-ROM DRIVES LISTED, WHICH HAVE
@@ -53,7 +53,7 @@
 2. INSTALLATION
 The driver consists of a header file 'aztcd.h', which normally should reside 
 in /usr/include/linux and the source code 'aztcd.c', which normally resides in
-/usr/src/linux/drivers/block. It uses /dev/aztcd (/dev/aztcd0 in some distri-
+/usr/src/linux/drivers/cdrom. It uses /dev/aztcd (/dev/aztcd0 in some distri-
 butions), which must be a valid block device with major number 29 and reside 
 in directory /dev. To mount a CD-ROM, your kernel needs to have the ISO9660-
 filesystem support included.
@@ -163,7 +163,7 @@
                     insmod /lib/modules/X.X.X/fs/isofs.o
 The mount procedure works as described in 4. above.
 (In all commands 'X.X.X' is the current linux kernel version number. For details
-see file README.modules in /usr/src/linux.)
+see file modules.txt in /usr/src/linux/Documentation)
 
 4.2 CDROM CONNECTED TO A SOUNDCARD
 Most soundcards do have a bus interface to the CDROM-drive. In many cases
@@ -460,7 +460,7 @@
 Reinhard Max delivered the information for the CDROM-interface of the
 SoundWave32 soundcards.
 
-Jochen Koch and Olaf ? delivered the information for supporting Conrad's TXC
+Jochen Koch and Olaf Koluza delivered the information for supporting Conrad's TXC
 drive.
 
 Anybody, who is interested in these items should have a look at 'ftp.gwdg.de',
diff -u --recursive --new-file v1.3.43/linux/MAGIC linux/MAGIC
--- v1.3.43/linux/MAGIC	Mon Oct 23 18:02:00 1995
+++ linux/MAGIC	Sat Nov 25 17:29:47 1995
@@ -85,6 +85,7 @@
 'T'	asm/termios.h		conflict!
 'V'	linux/vt.h
 'Y'	linux/cyclades.h	codes in 0x004359NN
+'a'	various, see http://lrcwww.epfl.ch/linux-atm/magic.html
 'f'	linux/ext2_fs.h
 'm'	linux/mtio.h		conflict!
 'm'	linux/soundcard.h	conflict!
diff -u --recursive --new-file v1.3.43/linux/Makefile linux/Makefile
--- v1.3.43/linux/Makefile	Tue Nov 21 13:22:04 1995
+++ linux/Makefile	Fri Nov 24 07:17:26 1995
@@ -1,6 +1,6 @@
 VERSION = 1
 PATCHLEVEL = 3
-SUBLEVEL = 43
+SUBLEVEL = 44
 
 ARCH = i386
 
@@ -282,7 +282,7 @@
 
 mrproper: clean
 	rm -f include/linux/autoconf.h include/linux/version.h
-	rm -f drivers/sound/local.h
+	rm -f drivers/sound/local.h drivers/sound/.defines
 	rm -f drivers/scsi/aic7xxx_asm drivers/scsi/aic7xxx_seq.h
 	rm -f drivers/char/uni_hash.tbl drivers/char/conmakehash
 	rm -f .version .config* config.in config.old
diff -u --recursive --new-file v1.3.43/linux/arch/alpha/defconfig linux/arch/alpha/defconfig
--- v1.3.43/linux/arch/alpha/defconfig	Mon Nov 13 12:36:42 1995
+++ linux/arch/alpha/defconfig	Thu Nov 23 11:26:03 1995
@@ -58,7 +58,7 @@
 #
 # CONFIG_INET_PCTCP is not set
 # CONFIG_INET_RARP is not set
-CONFIG_INET_SNARL=y
+# CONFIG_NO_PATH_MTU_DISCOVERY is not set
 # CONFIG_TCP_NAGLE_OFF is not set
 CONFIG_IP_NOSR=y
 CONFIG_SKB_LARGE=y
@@ -128,7 +128,6 @@
 CONFIG_NET_EISA=y
 # CONFIG_APRICOT is not set
 CONFIG_DE4X5=y
-# CONFIG_ETH16 is not set
 # CONFIG_ZNET is not set
 # CONFIG_NET_POCKET is not set
 # CONFIG_TR is not set
diff -u --recursive --new-file v1.3.43/linux/arch/i386/kernel/entry.S linux/arch/i386/kernel/entry.S
--- v1.3.43/linux/arch/i386/kernel/entry.S	Tue Nov 21 13:22:05 1995
+++ linux/arch/i386/kernel/entry.S	Fri Nov 24 16:13:59 1995
@@ -656,7 +656,7 @@
 	.long SYMBOL_NAME(sys_msync)
 	.long SYMBOL_NAME(sys_readv)		/* 145 */
 	.long SYMBOL_NAME(sys_writev)
-	.long 0
+	.long SYMBOL_NAME(sys_getsid)
 	.long 0
 	.long 0
 	.long SYMBOL_NAME(sys_mlock)		/* 150 */
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/Makefile linux/arch/sparc/Makefile
--- v1.3.43/linux/arch/sparc/Makefile	Tue Jun 27 14:11:30 1995
+++ linux/arch/sparc/Makefile	Sat Nov 25 02:57:32 1995
@@ -1,4 +1,4 @@
-#
+# $Id: Makefile,v 1.6 1995/11/25 00:57:30 davem Exp $
 # sparc/Makefile
 #
 # Makefile for the architecture dependent flags and dependencies on the
@@ -7,21 +7,19 @@
 # Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
 #
 
-
 # If the solaris /bin/sh wasn't so broken, I wouldn't need the following
 # line...
 SHELL  =/bin/bash
 
 #
-# How to link, we send the linker the address at which the text section
-# is to start. The prom loads us at 0x0-kernel_size. There is also an
-# alias of this address space at 0xf8000000-(0xf8000000+kernel_size) but
-# I ignore it and eliminate those mappings during vm initialization and
-# just leave the low mapping.
-#
-LINKFLAGS = -N -Ttext 0xf0004000
+# Uncomment the first CFLAGS if you are doing kgdb source level
+# debugging of the kernel to get the proper debugging information.
+
+#CFLAGS := $(CFLAGS) -g -pipe
 CFLAGS := $(CFLAGS) -pipe
 
+LINKFLAGS = -N -Ttext 0xf0004000
+
 HEAD := arch/sparc/kernel/head.o
 
 SUBDIRS := $(SUBDIRS) arch/sparc/kernel arch/sparc/lib arch/sparc/mm \
@@ -29,13 +27,11 @@
 
 ARCHIVES := arch/sparc/kernel/kernel.o arch/sparc/mm/mm.o $(ARCHIVES)
 
+LIBS := $(TOPDIR)/lib/lib.a $(LIBS) $(TOPDIR)/arch/sparc/prom/promlib.a \
+	$(TOPDIR)/arch/sparc/lib/lib.a
+
 aoutimage: vmlinux
 	elftoaout -o aoutimage vmlinux
-
-
-LIBS := $(TOPDIR)/lib/lib.a $(LIBS) $(TOPDIR)/arch/sparc/lib/lib.a \
-	$(TOPDIR)/arch/sparc/prom/promlib.a
-
 
 archclean:
 	rm -f $(TOPDIR)/arch/sparc/boot/boot
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/boot/Makefile linux/arch/sparc/boot/Makefile
--- v1.3.43/linux/arch/sparc/boot/Makefile	Tue Aug 15 20:39:00 1995
+++ linux/arch/sparc/boot/Makefile	Sat Nov 25 02:57:38 1995
@@ -1,3 +1,4 @@
+# $Id: Makefile,v 1.2 1995/11/25 00:57:37 davem Exp $
 # Makefile for the Sparc low level /boot module.
 #
 # Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -18,5 +19,3 @@
 dep:
 	$(CPP) -M *.c > .depend
 	$(CPP) -M -D__ASSEMBLY__ -ansi *.S >>.depend
-
-include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/boot/bare.S linux/arch/sparc/boot/bare.S
--- v1.3.43/linux/arch/sparc/boot/bare.S	Tue Jun 27 14:11:30 1995
+++ linux/arch/sparc/boot/bare.S	Sat Nov 25 02:57:40 1995
@@ -1,4 +1,5 @@
-/* base.S:      Ugly low-level boot program entry code.  The job of this
+/* $Id: bare.S,v 1.2 1995/11/25 00:57:39 davem Exp $
+ * base.S:      Ugly low-level boot program entry code.  The job of this
  *              module is to parse the boot flags, try to mount the remote
  *              root filesystem and load the kernel into virtual memory.
  *
@@ -6,6 +7,7 @@
  */
 
 #include "bare.h"
+#include <asm/ptrace.h>
 
 	.data
 	.globl C_LABEL(romvec)
@@ -49,7 +51,7 @@
 start_of_execution:
 	sethi	%hi(C_LABEL(first_adr_in_text)), %o1		! This is our top
 	or	%o1, %lo(C_LABEL(first_adr_in_text)), %o1	! of stack too.
-	sub	%o1, C_STACK, %o1
+	sub	%o1, STACKFRAME_SZ, %o1
 	add	%o1, 0x7, %o1
 	andn	%o1, 0x7, %o1
 	save	%o1, 0x0, %sp					! save is an add
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/boot/bare.h linux/arch/sparc/boot/bare.h
--- v1.3.43/linux/arch/sparc/boot/bare.h	Tue Jun 27 14:11:30 1995
+++ linux/arch/sparc/boot/bare.h	Sat Nov 25 02:57:42 1995
@@ -1,4 +1,5 @@
-/* bare.h:  Defines for the low level entry code of the BOOT program.
+/* $Id: bare.h,v 1.2 1995/11/25 00:57:41 davem Exp $
+ * bare.h:  Defines for the low level entry code of the BOOT program.
  *          We include in the head.h stuff that the real kernel uses
  *          and this saves a lot of repetition here.
  *
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/boot/imperical.h linux/arch/sparc/boot/imperical.h
--- v1.3.43/linux/arch/sparc/boot/imperical.h	Tue Jun 27 14:11:30 1995
+++ linux/arch/sparc/boot/imperical.h	Sat Nov 25 02:57:44 1995
@@ -1,4 +1,5 @@
-/* imperical.h:  Nasty hacks....
+/* $Id: imperical.h,v 1.2 1995/11/25 00:57:42 davem Exp $
+ * imperical.h:  Nasty hacks....
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  */
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/boot/init_me.c linux/arch/sparc/boot/init_me.c
--- v1.3.43/linux/arch/sparc/boot/init_me.c	Tue Jun 27 14:11:31 1995
+++ linux/arch/sparc/boot/init_me.c	Sat Nov 25 02:57:45 1995
@@ -1,4 +1,5 @@
-/* init_me.c:  Initialize imperical constants and gather some info from
+/* $Id: init_me.c,v 1.2 1995/11/25 00:57:44 davem Exp $
+ * init_me.c:  Initialize imperical constants and gather some info from
  *             the boot prom.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/config.in linux/arch/sparc/config.in
--- v1.3.43/linux/arch/sparc/config.in	Mon Oct 16 18:38:21 1995
+++ linux/arch/sparc/config.in	Sat Nov 25 02:57:34 1995
@@ -1,134 +1,54 @@
-#
-# arch/sparc/config.in
-#
-# Bare minimum configuration file for the Sparc.
-#
-# Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
-#
+# $Id: config.in,v 1.5 1995/11/25 00:57:32 davem Exp $
 # For a description of the syntax of this configuration file,
 # see the Configure script.
 #
-mainmenu_name 'Sparc Linux Kernel Configuration'
-
-echo "#define CONFIG_SPARCDEVS 1" >> $CONFIG_H
-echo "CONFIG_SPARCDEVS=y" >> $CONFIG
+mainmenu_name "Kernel configuration of Linux for SparcStations"
 
 mainmenu_option next_comment
-comment 'Sparc Kernel setup'
+comment 'General setup'
 
-bool 'Sun floppy controller support' CONFIG_BLK_DEV_SUNFD n
-bool 'Networking support' CONFIG_NET n
-bool 'Limit memory to low 16MB' CONFIG_MAX_16M n
-bool 'System V IPC' CONFIG_SYSVIPC y
-bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF y
+# Global things across all Sparc machines.
+define_bool CONFIG_SBUS y
+define_bool CONFIG_SUN_MOUSE y
+define_bool CONFIG_SUN_SERIAL y
+define_bool CONFIG_SUN_KEYBOARD y
+define_bool CONFIG_SUN_CONSOLE y
+
+bool 'Networking support' CONFIG_NET
+bool 'System V IPC' CONFIG_SYSVIPC
+tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
+
+source drivers/block/Config.in
 
 if [ "$CONFIG_NET" = "y" ]; then
-mainmenu_option next_comment
-comment 'Networking options'
-bool 'TCP/IP networking' CONFIG_INET y
-if [ "$CONFIG_INET" "=" "y" ]; then
-bool 'IP forwarding/gatewaying' CONFIG_IP_FORWARD n
-bool 'IP multicasting (ALPHA)' CONFIG_IP_MULTICAST n
-bool 'IP firewalling' CONFIG_IP_FIREWALL n
-bool 'IP accounting' CONFIG_IP_ACCT n
-comment '(it is safe to leave these untouched)'
-bool 'PC/TCP compatibility mode' CONFIG_INET_PCTCP n
-bool 'Reverse ARP' CONFIG_INET_RARP n
-bool 'Assume subnets are local' CONFIG_INET_SNARL y
-bool 'Disable NAGLE algorithm (normally enabled)' CONFIG_TCP_NAGLE_OFF n
-fi
-bool 'The IPX protocol' CONFIG_IPX n
-#bool 'Amateur Radio AX.25 Level 2' CONFIG_AX25 n
+	source net/Config.in
 fi
 
 mainmenu_option next_comment
 comment 'SCSI support'
 
-bool 'SCSI support?' CONFIG_SCSI n
-
-if [ "$CONFIG_SCSI" = "n" ]; then
-
-comment 'Skipping SCSI configuration options...'
-
-else
-
-comment 'SCSI support type (disk, tape, CDrom)'
-
-bool 'SCSI disk support' CONFIG_BLK_DEV_SD y
-bool 'SCSI tape support' CONFIG_CHR_DEV_ST n
-bool 'SCSI CDROM support' CONFIG_BLK_DEV_SR n
-bool 'SCSI generic support' CONFIG_CHR_DEV_SG n
-
-comment 'SCSI low-level drivers'
-
-bool 'Sun ESP Scsi support' CONFIG_SCSI_SUN_ESP n
+tristate 'SCSI support' CONFIG_SCSI
 
+if [ "$CONFIG_SCSI" != "n" ]; then
+	source drivers/scsi/Config.in
 fi
 
-
 if [ "$CONFIG_NET" = "y" ]; then
+	mainmenu_option next_comment
+	comment 'Network device support'
 
-mainmenu_option next_comment
-comment 'Network device support'
-
-bool 'Network device support?' CONFIG_NETDEVICES y
-if [ "$CONFIG_NETDEVICES" = "n" ]; then
-
-comment 'Skipping network driver configuration options...'
-
-else
-bool 'Dummy net driver support' CONFIG_DUMMY n
-bool 'SLIP (serial line) support' CONFIG_SLIP n
-if [ "$CONFIG_SLIP" = "y" ]; then
-  bool ' CSLIP compressed headers' SL_COMPRESSED y
-#  bool ' SLIP debugging on' SL_DUMP y
-fi
-bool 'PPP (point-to-point) support' CONFIG_PPP n
-bool 'PLIP (parallel port) support' CONFIG_PLIP n
-bool 'Load balancing support (experimental)' CONFIG_SLAVE_BALANCING n
-bool 'Sun LANCE Ethernet support' CONFIG_SUN_LANCE n
-bool 'Sun Intel Ethernet support' CONFIG_SUN_INTEL n
-fi
+	bool 'Network device support' CONFIG_NETDEVICES
+	if [ "$CONFIG_NETDEVICES" = "y" ]; then
+		source drivers/net/Config.in
+	fi
 fi
 
-mainmenu_option next_comment
-comment 'Filesystems'
-
-bool 'Standard (minix) fs support' CONFIG_MINIX_FS n
-bool 'Extended fs support' CONFIG_EXT_FS n
-bool 'Second extended fs support' CONFIG_EXT2_FS y
-bool 'xiafs filesystem support' CONFIG_XIA_FS n
-bool 'msdos fs support' CONFIG_MSDOS_FS n
-bool '/proc filesystem support' CONFIG_PROC_FS n
-if [ "$CONFIG_INET" = "y" ]; then
-bool 'NFS filesystem support' CONFIG_NFS_FS n
-fi
-if [ "$CONFIG_BLK_DEV_SR" = "y" -o "$CONFIG_CDU31A" = "y" -o "$CONFIG_MCD" = "y" -o "$CONFIG_SBPCD" = "y" -o "$CONFIG_BLK_DEV_IDECD" = "y" ]; then
-	bool 'ISO9660 cdrom filesystem support' CONFIG_ISO9660_FS n
-else
-	bool 'ISO9660 cdrom filesystem support' CONFIG_ISO9660_FS n
-fi
-bool 'OS/2 HPFS filesystem support (read only)' CONFIG_HPFS_FS n
-bool 'System V and Coherent filesystem support' CONFIG_SYSV_FS n
-
-
-mainmenu_option next_comment
-comment 'character devices'
-
-bool 'Zilog serial support' CONFIG_SUN_ZS n
-
-comment 'Sound'
-
-bool 'Sun Audio support' CONFIG_SUN_AUDIO n
+source fs/Config.in
 
 mainmenu_option next_comment
 comment 'Kernel hacking'
 
-bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC n
-bool 'Kernel profiling support' CONFIG_PROFILE n
+bool 'Kernel profiling support' CONFIG_PROFILE
 if [ "$CONFIG_PROFILE" = "y" ]; then
-  int ' Profile shift count' CONFIG_PROFILE_SHIFT 2
-fi
-if [ "$CONFIG_SCSI" = "y" ]; then
-bool 'Verbose SCSI error reporting (kernel size +=12K)' CONFIG_SCSI_CONSTANTS y
+	int ' Profile shift count' CONFIG_PROFILE_SHIFT 2
 fi
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/defconfig linux/arch/sparc/defconfig
--- v1.3.43/linux/arch/sparc/defconfig	Thu Jan  1 02:00:00 1970
+++ linux/arch/sparc/defconfig	Tue Nov 21 12:23:18 1995
@@ -0,0 +1,98 @@
+#
+# Automatically generated make config: don't edit
+#
+
+#
+# General setup
+#
+CONFIG_SBUS=y
+CONFIG_SUN_MOUSE=y
+CONFIG_SUN_SERIAL=y
+CONFIG_SUN_KEYBOARD=y
+CONFIG_SUN_CONSOLE=y
+CONFIG_NET=y
+CONFIG_SYSVIPC=y
+# CONFIG_BINFMT_ELF is not set
+
+#
+# block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+
+#
+# Networking options
+#
+# CONFIG_FIREWALL is not set
+CONFIG_INET=y
+# CONFIG_IP_FORWARD is not set
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ACCT is not set
+
+#
+# (it is safe to leave these untouched)
+#
+# CONFIG_INET_PCTCP is not set
+# CONFIG_INET_RARP is not set
+# CONFIG_NO_PATH_MTU_DISCOVERY is not set
+# CONFIG_TCP_NAGLE_OFF is not set
+CONFIG_IP_NOSR=y
+# CONFIG_SKB_LARGE is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_AX25 is not set
+# CONFIG_NETLINK is not set
+
+#
+# SCSI support
+#
+CONFIG_SCSI=y
+
+#
+# SCSI support type (disk, tape, CDrom)
+#
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=y
+CONFIG_BLK_DEV_SR=y
+# CONFIG_CHR_DEV_SG is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_CONSTANTS=y
+
+#
+# SCSI low-level drivers
+#
+CONFIG_SCSI_SUNESP=y
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=y
+# CONFIG_SLIP is not set
+# CONFIG_PPP is not set
+CONFIG_SUNLANCE=y
+
+#
+# Filesystems
+#
+# CONFIG_MINIX_FS is not set
+# CONFIG_EXT_FS is not set
+CONFIG_EXT2_FS=y
+# CONFIG_XIA_FS is not set
+CONFIG_MSDOS_FS=y
+# CONFIG_UMSDOS_FS is not set
+CONFIG_PROC_FS=y
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
+CONFIG_ISO9660_FS=y
+# CONFIG_HPFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_SMB_FS is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PROFILE is not set
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/kernel/Makefile linux/arch/sparc/kernel/Makefile
--- v1.3.43/linux/arch/sparc/kernel/Makefile	Tue Aug 15 20:39:00 1995
+++ linux/arch/sparc/kernel/Makefile	Sat Nov 25 02:57:50 1995
@@ -1,4 +1,4 @@
-#
+# $Id: Makefile,v 1.18 1995/11/25 00:57:48 davem Exp $
 # Makefile for the linux kernel.
 #
 # Note! Dependencies are done automagically by 'make dep', which also
@@ -12,15 +12,15 @@
 .S.o:
 	$(CC) -D__ASSEMBLY__ -ansi -c $< -o $*.o
 
-OBJS  = entry.o traps.o irq.o process.o signal.o ioport.o setup.o \
-	idprom.o probe.o mp.o c_mp.o
+OBJS  = entry.o wof.o wuf.o etrap.o rtrap.o switch.o traps.o irq.o \
+	process.o signal.o ioport.o setup.o idprom.o probe.o mp.o  \
+	c_mp.o sys_sparc.o sunos_asm.o sparc-stub.o systbls.o      \
+	sys_sunos.o sunos_ioctl.o time.o
 
 all: kernel.o head.o
 
-head.o: head.s
-
-head.s: head.S
-	$(CPP) -D__KERNEL__ -D__ASSEMBLY__ -ansi -o $*.s $<
+head.o: head.S
+	$(CC) -D__ASSEMBLY__ -ansi -c $*.S -o $*.o
 
 kernel.o: $(OBJS)
 	$(LD) -r -o kernel.o $(OBJS)
@@ -28,6 +28,5 @@
 
 dep:
 	$(CPP) -M *.c > .depend
-	$(CPP) -M -D__ASSEMBLY__ -ansi *.S >>.depend
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/kernel/V9head.S linux/arch/sparc/kernel/V9head.S
--- v1.3.43/linux/arch/sparc/kernel/V9head.S	Tue Jun 27 14:11:31 1995
+++ linux/arch/sparc/kernel/V9head.S	Thu Jan  1 02:00:00 1970
@@ -1,16 +0,0 @@
-/* V9head.S: Initial boot code for the V9 Sparc under Linux.
- *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- *
- */
-
-#include <asm/cprefix.h>
-
-	.text
-
-	.globl	start
-	.globl	_start
-	.globl	C_LABEL(trapbase)
-_start:
-start:
-C_LABEL(trapbase):
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/kernel/c_mp.c linux/arch/sparc/kernel/c_mp.c
--- v1.3.43/linux/arch/sparc/kernel/c_mp.c	Tue Jun 27 14:11:31 1995
+++ linux/arch/sparc/kernel/c_mp.c	Sat Nov 25 02:57:52 1995
@@ -1,7 +1,10 @@
-/* mp.c:  SMP cpu idling and dispatch on the Sparc.
+/* $Id: c_mp.c,v 1.3 1995/11/25 00:57:50 davem Exp $
+ * mp.c:  SMP cpu idling and dispatch on the Sparc.
  *
  * Copyright (C) 1995 David S. Miller
  */
+
+#include <linux/kernel.h>
 
 #include <asm/mp.h>
 #include <asm/mbus.h>
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/kernel/entry.S linux/arch/sparc/kernel/entry.S
--- v1.3.43/linux/arch/sparc/kernel/entry.S	Tue Jun 27 14:11:31 1995
+++ linux/arch/sparc/kernel/entry.S	Sat Nov 25 02:57:55 1995
@@ -1,1950 +1,887 @@
-/* arch/sparc/kernel/entry.S:  Sparc trap low-level entry points.
- *
- * Sparc traps are so ugly, this code is going to go through a lot
- * of changes as I find out more interesting things. See head.S for
- * the trap table and how it works, this will show you how we get
- * to these routines.
+/* $Id: entry.S,v 1.64 1995/11/25 00:57:53 davem Exp $
+ * arch/sparc/kernel/entry.S:  Sparc trap low-level entry points.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  */
 
+#include <linux/config.h>
 
 #include <asm/head.h>
 #include <asm/asi.h>
+#include <asm/kgdb.h>
 #include <asm/contregs.h>
+#include <asm/ptrace.h>
 #include <asm/psr.h>
 #include <asm/cprefix.h>
 #include <asm/vaddrs.h>
 #include <asm/memreg.h>
 #include <asm/page.h>
+#include <asm/winmacro.h>
+#include <asm/signal.h>
+#include <asm/errno.h>
 
 #define NR_SYSCALLS 255      /* Each OS is different... */
 
-/* A debugging macro, it just prints a dot on the screen.  For now
- * it is only used in the context switch code since it is so delicate
- * I need to use the prom putchar() routines and reload the pointers
- * every time.  This clobbers %l7 and %o0.
- */
-#define DO_SPARC_DOT \
-	sethi	%hi(C_LABEL(romvec)), %l7; \
-	ld	[%l7 + %lo(C_LABEL(romvec))], %l7; \
-	ld	[%l7 + 0x54], %l7; \
-	or	%g0, '.', %o0; \
-	call	%l7; \
-	nop; \
-	nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; \
-
-/* Another macro, the name speaks for itself. */
-#define DROP_THE_BOMB \
-	sethi	%hi(C_LABEL(romvec)), %l7;  \
-	ld	[%l7 + %lo(C_LABEL(romvec))], %l7;  \
-	ld	[%l7 + 0x74], %l7;  \
-	call	%l7;  \
-	nop;  \
-
-/* Turn off interrupts while we change contexts. Clobbers %l7 */
-#define TRAPS_OFF \
-	rd	%psr, %l7; \
-	andn	%l7, (PSR_ET), %l7; \
-	wr	%l7, 0x0, %psr; \
-
-/* Here are macros for routines we do often, this allows me to inline this
- * without making the code look real ugly.  Well, the macro looks ugly too
- * but makes the trap entry code easier to understand.
+/* All trap entry points _must_ begin with this macro or else you
+ * lose.  It makes sure the kernel has a proper window so that
+ * c-code can be called.  Some day for SMP we'll grab klock here.
+ */
+#define SAVE_ALL \
+	sethi	%hi(trap_setup), %l4; \
+	jmpl	%l4 + %lo(trap_setup), %l6; \
+	 nop;
+
+/* All traps low-level code here must end with this macro.
+ * For SMP configurations the ret_trap_entry routine will
+ * have to appropriate code to actually release the kernel
+ * entry lock.
+ */
+#define RESTORE_ALL \
+	b	ret_trap_entry; \
+	 nop;
+
+/* First, KGDB low level things.  This is a rewrite
+ * of the routines found in the sparc-stub.c asm() statement
+ * from the gdb distribution.  This is also dual-purpose
+ * as a software trap for userlevel programs.
  */
+	.data
+	.align	4
 
-/* I really don't like synthetic instructions. So I avoid them like the
- * plague.
- */
+in_trap_handler:
+	.word	0
 
-/* Note that when I have to write a window out, and it is a user's window, I
- * have to check that the pages of memory that I am going to throw the window(s)
- * onto are valid and are writable by the user (this is %sp to %sp + 64) before
- * I start dumping stuff there. We always assume that kernels stack is ok.
- * XXX Will change on MP's XXX
- *
- * If we have to save a kernel window, only one branch is taken. This should
- * make trap handlers quicker in this scenario.
- *
- * Once 'current' is loaded into %g6, it stays there until we leave
- * this macro.
- */
+	.text
+	.align	4
 
-/* I will document how this works real soon. TODO */
+! This function is called when any SPARC trap (except window overflow or
+! underflow) occurs.  It makes sure that the invalid register window is still
+! available before jumping into C code.  It will also restore the world if you
+! return from handle_exception.
 
-#define TRAP_WIN_CLEAN \
-	or	%g0, %g5, %l5;    /* we need the globals to do our work */ \
-	or	%g0, %g6, %l6;    /* and %l0 to %l4 are loaded with important */ \
-	or	%g0, %g7, %l7;	  /* information like the psr and pc's to return to */ \
-	sethi	%hi( C_LABEL(current) ), %g6; \
-	ld	[%g6 + %lo( C_LABEL(current) )], %g6; \
-	ld	[%g6 + THREAD_UWINDOWS], %g7; /* how many user wins are active? */ \
-	subcc	%g7, 0x0, %g0; \
-	bne	2f;                            /* If there are any, branch. */ \
-	save	%g0, %g0, %g0;                 /* Save into that window either way. */ \
-	std	%l0, [%sp];                    /* If above shows only kernel windows */ \
-1:	std	%l2, [%sp + 0x8];              /* then we get here. */ \
-	std	%l4, [%sp + 0x10]; \
-	std	%l6, [%sp + 0x18]; \
-	std	%i0, [%sp + 0x20]; \
-	std	%i2, [%sp + 0x28]; \
-	std	%i4, [%sp + 0x30]; \
-	std	%i6, [%sp + 0x38]; \
-	or	%g0, 0x1, %g5; \
-	rd	%psr, %g7; \
-	sll	%g5, %g7, %g5; \
-	wr	%g5, 0x0, %wim;                 /* update %wim to 'now' invalid */ \
-	and	%g7, 0x1f, %g7; \
-	sethi	%hi( C_LABEL(current) ), %g6; \
-	ld	[%g6 + %lo( C_LABEL(current) )], %g6; \
-	st	%g7, [%g6 + THREAD_WIM];        /* save 'this' threads mask */ \
-	restore	%g0, %g0, %g0; \
-	or	%g0, %l5, %g5;                  /* restore the globals we used */ \
-	or	%g0, %l6, %g6; \
-	b	8f;                             /* we are done */ \
-	or	%g0, %l7, %g7; \
-2:	sub	%g7, 0x1, %g7; \
-	sethi	%hi( C_LABEL(current) ), %g6; \
-	ld	[%g6 + %lo( C_LABEL(current) )], %g6; \
-	st	%g7, [%g6 + THREAD_UWINDOWS];   /* There are user windows if we */ \
-	andcc	%sp, 0x7, %g0;                  /* get here. Check for stack alignment. */ \
-	bne	5f;                             /* Stack is unaligned, yuck. */ \
-	sra	%sp, 0x1e, %g7;                 /* This stuff checks to see if top 3-bits */ \
-	subcc	%g7, 0x0, %g0;                  /* of stack pointer address are ok. */ \
-	be,a    3f; \
-	andn	%sp, 0xfff, %g7; \
-	subcc	%g7, -1, %g0; \
-	bne	5f; 				/* bad stack pointer, ugh */ \
-	andn	%sp, 0xfff, %g7; \
-3:	lda	[%g7] ASI_PTE, %g7;             /* Ok, user stack is a valid address */ \
-	srl	%g7, 0x1d, %g7; \
-	subcc	%g7, 0x6, %g0;                  /* Can the user write to it? */ \
-	bne	5f; \
-	and	%sp, 0xfff, %g7; \
-	subcc	%g7, 0xfc1, %g0;                /* Is our save area on one page? */ \
-	bl,a	1b; \
-	std	%l0, [%sp]; \
-	add	%sp, 0x38, %g5;                 /* Nope, have to check both pages */ \
-	sra	%g5, 0x1e, %g7; \
-	subcc	%g7, 0x0, %g0; \
-	be,a	4f; \
-	andn	%g5, 0xfff, %g7; \
-	subcc	%g7, -1, %g0; \
-	bne	5f; \
-	andn	%g5, 0xfff, %g7; \
-4:	lda	[%g7] ASI_PTE, %g7;             /* Stack space in 2nd page is valid */ \
-	srl	%g7, 0x1d, %g7; \
-	subcc	%g7, 0x6, %g0;                  /* Can user write here too? */ \
-	be,a	1b; \
-	std	%l0, [%sp]; \
-5:	ld	[%g6 + THREAD_UWINDOWS], %g7;   /* This is due to either bad page perms */ \
-	add	%g6, THREAD_REG_WINDOW, %g5;    /* for the users stack area, or the stack */ \
-6:	std	%l0, [%g5];                     /* pointer is misaligned. See above. */ \
-	std	%l2, [%g5 + 0x8]; \
-	std	%l4, [%g5 + 0x10]; \
-	std	%l6, [%g5 + 0x18]; \
-	std	%i0, [%g5 + 0x20]; \
-	std	%i2, [%g5 + 0x28]; \
-	std	%i4, [%g5 + 0x30]; \
-	std	%i6, [%g5 + 0x38]; \
-	subcc	%g7, 0x1, %g7; \
-	bge,a	6b;                             /* while(uwindows>=0) { write_win(); */ \
-	save	%g5, 0x40, %g5;                 /*     uwindows--; } */ \
-	st	%sp, [%g6 + THREAD_USP]; \
-	or	%g0, 0x1, %g5; \
-	rd	%psr, %g7; \
-	sll	%g5, %g7, %g5; \
-	wr	%g5, 0x0, %wim; \
-	and	%g7, 0x1f, %g7; \
-	st	%g7, [%g6 + THREAD_WIM];        /* Update thread_struct fields */ \
-	ld	[%g6 + THREAD_UWINDOWS], %g7; \
-	add	%g7, 0x1, %g5; \
-	st	%g5, [%g6 + THREAD_W_SAVED]; \
-	st	%g0, [%g6 + THREAD_UWINDOWS]; \
-7:	subcc	%g7, 0x1, %g7;                  /* Restore back to where we started. */ \
-	bge	7b; \
-	restore	%g0, %g0, %g0; \
-	or	%g0, %l5, %g5;                  /* Restore the globals. */ \
-	or	%g0, %l6, %g6; \
-	or	%g0, %l7, %g7; \
-8:      nop;                                     /* We are done when we get here. */ \
-
-/* As if the last macro wasn't enough, we have to go through a very similar routine
- * upon entry to most traps and interrupts. This is save away the current window
- * if it is the trap window, clean it, and adjust the stack for the handler c-code
- * to work.
- *
- * See asm-sparc/cprefix.h to see how the CONCAT macros work.
- */
-/* NOTE: The system call entry code ASSUMES that the ENTER_TRAP macro
- *       does NOT touch register %l7 and leaves the same contents after
- *       the macro is done. Keep in mind if you change this code.
- */
-
-#define ENTER_TRAP(label) \
-	rd	%wim, %l4; \
-	or	%g0, 0x1, %l5; \
-	sll	%l5, %l0, %l5; \
-	andcc	%l0, PSR_PS, %g0; \
-	bz	CONCAT1(label, 1); \
-	andcc	%l4, %l5, %g0; \
-	bz,a	CONCAT1(label, 3); \
-	sub	%fp, 0xb0, %sp; \
-	TRAP_WIN_CLEAN \
-	b	CONCAT1(label, 3); \
-	sub	%fp, 0xb0, %sp; \
-CONCAT1(label, 1): \
-	sethi	%hi( C_LABEL(current) ), %l6; \
-	ld	[%l6 + %lo( C_LABEL(current) )], %l6; \
-	ld	[%l6 + THREAD_WIM], %l5; \
-	and	%l0, 0x1f, %l4; \
-	cmp	%l5, %l3; \
-	ble,a	CONCAT1(label, 4); \
-	sethi	%hi( C_LABEL(nwindowsm1) ), %l4; \
-	sub	%l5, %l3, %l3; \
-	b	CONCAT1(label, 5); \
-	sub	%l3, 0x1, %l5; \
-CONCAT1(label, 4): \
-	ld	[%l4 + %lo( C_LABEL(nwindowsm1) )], %l4; \
-	sub	%l4, %l3, %l4; \
-	add	%l5, %l4, %l5; \
-CONCAT1(label, 5): \
-	st	%l5, [%l6 + THREAD_UWINDOWS]; \
-	bz,a	CONCAT1(label, 2); \
-	sethi	%hi(C_LABEL(current)), %l6; \
-	TRAP_WIN_CLEAN \
-	sethi	%hi(C_LABEL(current)), %l6; \
-CONCAT1(label, 2): \
-	ld	[%l6 + %lo(C_LABEL(current))], %l6; \
-	ld	[%l6 + TASK_KSTACK_PG], %l6; \
-	add	%l6, (PAGE_SIZE - 96 - 80), %l6; \
-	andn	%l6, 0x7, %l6; \
-	or	%g0, %l6, %sp; \
-CONCAT1(label, 3):
+	.globl	C_LABEL(trap_low)
+C_LABEL(trap_low):
+	rd	%wim, %l3
+	SAVE_ALL
 
-/* What needs to be executed upon entry to an interrupt.
- *
- * See asm-sparc/cprefix.h to see how the CONCAT macros work.
- */
+	sethi	%hi(in_trap_handler), %l4
+	ld	[%lo(in_trap_handler) + %l4], %l5
+	inc	%l5
+	st	%l5, [%lo(in_trap_handler) + %l4]
+
+	/* Make sure kgdb sees the same state we just saved. */
+	LOAD_PT_GLOBALS(sp)
+	LOAD_PT_INS(sp)
+	ld	[%sp + STACKFRAME_SZ + PT_Y], %l4
+	ld	[%sp + STACKFRAME_SZ + PT_WIM], %l3
+	ld	[%sp + STACKFRAME_SZ + PT_PSR], %l0
+	ld	[%sp + STACKFRAME_SZ + PT_PC], %l1
+	ld	[%sp + STACKFRAME_SZ + PT_NPC], %l2
+	rd	%tbr, %l5	/* Never changes... */
+
+	/* Make kgdb exception frame. */	
+	sub	%sp,(16+1+6+1+72)*4,%sp	! Make room for input & locals
+ 					! + hidden arg + arg spill
+					! + doubleword alignment
+					! + registers[72] local var
+	SAVE_KGDB_GLOBALS(sp)
+	SAVE_KGDB_INS(sp)
+	SAVE_KGDB_SREGS(sp, l4, l0, l3, l5, l1, l2)
+
+	/* We are increasing PIL, so two writes. */
+	or	%l0, PSR_PIL, %l0
+	wr	%l0, 0, %psr
+	wr	%l0, PSR_ET, %psr
+	WRITE_PAUSE
 
-#define ENTER_IRQ(label) \
-	rd	%wim, %l4; \
-	or	%g0, 0x1, %l5; \
-	sll	%l5, %l0, %l5; \
-	andcc	%l0, PSR_PS, %g0; \
-	bz	CONCAT1(label, 1); \
-	andcc	%l4, %l5, %g0; \
-	bz,a	CONCAT1(label, 0); \
-	sethi	%hi( C_LABEL(eintstack) ), %l7; \
-	TRAP_WIN_CLEAN \
-	sethi	%hi( C_LABEL(eintstack) ), %l7; \
-CONCAT1(label, 0): \
-	subcc	%fp, %l7, %g0; \
-	bge,a	CONCAT1(label, 3); \
-	sub	%l7, 0xb0, %sp; \
-	b	CONCAT1(label, 3); \
-	sub	%fp, 0xb0, %sp; \
-CONCAT1(label, 1): \
-	sethi	%hi( C_LABEL(current) ), %l6; \
-	ld	[%l6 + %lo( C_LABEL(current) )], %l6; \
-	ld	[%l6 + THREAD_WIM], %l5; \
-	and	%l0, 0x1f, %l7; \
-	cmp	%l5, %l7; \
-	ble,a	CONCAT1(label, 4); \
-	sethi	%hi( C_LABEL(nwindowsm1) ), %l4; \
-	sub	%l5, %l7, %l7; \
-	b	CONCAT1(label, 5); \
-	sub	%l7, 0x1, %l5; \
-CONCAT1(label, 4): \
-	ld	[%l4 + %lo( C_LABEL(nwindowsm1) )], %l4; \
-	sub	%l4, %l7, %l4; \
-	add	%l5, %l4, %l5; \
-CONCAT1(label, 5): \
-	st	%l5, [%l6 + THREAD_UWINDOWS]; \
-	bz,a	CONCAT1(label, 2); \
-	sethi	%hi( C_LABEL(eintstack) ), %l7; \
-	TRAP_WIN_CLEAN \
-	sethi	%hi( C_LABEL(eintstack) ), %l7; \
-CONCAT1(label, 2): \
-	sub	%l7, 0xb0, %sp; \
-CONCAT1(label, 3):
+	call	C_LABEL(handle_exception)
+	 add	%sp, STACKFRAME_SZ, %o0	! Pass address of registers
 
+	/* Load new kgdb register set. */
+	LOAD_KGDB_GLOBALS(sp)
+	LOAD_KGDB_INS(sp)
+	LOAD_KGDB_SREGS(sp, l0, l2)
+	ld	[%sp + STACKFRAME_SZ + KGDB_WIM], %l6
+	wr	%l0, 0x0, %y
+
+	sethi	%hi(in_trap_handler), %l4
+	ld	[%lo(in_trap_handler) + %l4], %l5
+	dec	%l5
+	st	%l5, [%lo(in_trap_handler) + %l4]
+
+	add	%sp,(16+1+6+1+72)*4,%sp	! Undo the kgdb trap frame.
+
+	/* Now take what kgdb did and place it into the pt_regs
+	 * frame which SparcLinux RESTORE_ALL understands.,
+	 */
+	STORE_PT_INS(sp)
+	STORE_PT_GLOBALS(sp)
+	STORE_PT_YREG(sp, g2)
+	STORE_PT_PRIV(sp, l1, l2, l3, l6)
+
+	/* Cross your fingers... */
+	RESTORE_ALL
+
+
+#ifdef CONFIG_BLK_DEV_FD
+	.align	4
+	.globl	C_LABEL(floppy_hardint)
+C_LABEL(floppy_hardint):
+	/* Can only use regs %l3->%l7:
+	 * %l3 -- base address of fdc registers
+	 * %l4 -- doing_pdma upon entry, AUXIO reg vaddr after
+	 * %l5 -- pdma_vaddr
+	 * %l6 -- pdma_size
+	 * %l7 -- floppy_softint
+	 */
+
+	/* Do we have work to do? */
+	sethi	%hi(C_LABEL(doing_pdma)), %l4
+	ld	[%l4 + %lo(C_LABEL(doing_pdma))], %l4
+	cmp	%l4, 0
+	be	floppy_dosoftint
+	 nop
+
+	/* Load fdc register base */
+	sethi	%hi(C_LABEL(fdc_status)), %l3
+	ld	[%l3 + %lo(C_LABEL(fdc_status))], %l3
+
+	/* Setup register addresses */
+	sethi	%hi(C_LABEL(pdma_vaddr)), %l5	! transfer buffer
+	ld	[%l5 + %lo(C_LABEL(pdma_vaddr))], %l4
+	sethi	%hi(C_LABEL(pdma_size)), %l5	! bytes to go
+	ld	[%l5 + %lo(C_LABEL(pdma_size))], %l6
+next_byte:
+	ldub	[%l3], %l7
+	andcc	%l7, 0x80, %g0		! Does fifo still have data
+	bz	floppy_fifo_emptied	! fifo has been emptied...
+	 andcc	%l7, 0x20, %g0		! in non-dma mode still?
+	bz	floppy_overrun		! nope, overrun
+	 andcc	%l7, 0x40, %g0		! 0=write 1=read
+	bz	floppy_write
+	 sub	%l6, 0x1, %l6
+
+	/* Ok, actually read this byte */
+	ldub	[%l3 + 1], %l7
+	orcc	%g0, %l6, %g0
+	stb	%l7, [%l4]
+	bne	next_byte
+	 add	%l4, 0x1, %l4
+
+	b	floppy_tdone
+	 nop
+
+floppy_write:
+	/* Ok, actually write this byte */
+	ldub	[%l4], %l7
+	orcc	%g0, %l6, %g0
+	stb	%l7, [%l3 + 1]
+	bne	next_byte
+	 add	%l4, 0x1, %l4
+
+	/* fall through... */
+floppy_tdone:
+	sethi	%hi(C_LABEL(pdma_vaddr)), %l5
+	st	%l4, [%l5 + %lo(C_LABEL(pdma_vaddr))]
+	sethi	%hi(C_LABEL(pdma_size)), %l5
+	st	%l6, [%l5 + %lo(C_LABEL(pdma_size))]
+	/* Flip terminal count pin */
+	sethi	%hi(AUXIO_VADDR), %l4
+	ldub	[%l4 + %lo(AUXIO_VADDR) + 0x3], %l5
+	or	%l5, 0xf4, %l5
+	stb	%l5, [%l4 + %lo(AUXIO_VADDR) + 0x3]
+
+	/* Kill some time so the bits set */
+	WRITE_PAUSE
+	WRITE_PAUSE
+
+	ldub	[%l4 + %lo(AUXIO_VADDR) + 0x3], %l5
+	andn	%l5, 0x04, %l5
+	or	%l5, 0xf0, %l5
+	stb	%l5, [%l4 + %lo(AUXIO_VADDR) + 0x3]
+
+	/* Prevent recursion */
+	sethi	%hi(C_LABEL(doing_pdma)), %l4
+	b	floppy_dosoftint
+	 st	%g0, [%l4 + %lo(C_LABEL(doing_pdma))]
+
+	/* We emptied the FIFO, but we haven't read everything
+	 * as of yet.  Store the current transfer address and
+	 * bytes left to read so we can continue when the next
+	 * fast IRQ comes in.
+	 */
+floppy_fifo_emptied:
+	sethi	%hi(C_LABEL(pdma_vaddr)), %l5
+	st	%l4, [%l5 + %lo(C_LABEL(pdma_vaddr))]
+	sethi	%hi(C_LABEL(pdma_size)), %l7
+	st	%l6, [%l7 + %lo(C_LABEL(pdma_size))]
 
-	.text
-	.align 4
+	/* Restore condition codes */
+	wr	%l0, 0x0, %psr
+	WRITE_PAUSE
 
-/* Bad trap handler */
-	.globl bad_trap_handler
-bad_trap_handler:
-	ENTER_TRAP(bad_trap_handler)
+	jmp	%l1
+	rett	%l2
 
-	or	%g0, %l3, %o0
-	or	%g0, %l0, %o1
-	call	C_LABEL(do_hw_interrupt)
-	or	%g0, %l1, %o2
+floppy_overrun:
+	sethi	%hi(C_LABEL(pdma_vaddr)), %l5
+	st	%l4, [%l5 + %lo(C_LABEL(pdma_vaddr))]
+	sethi	%hi(C_LABEL(pdma_size)), %l5
+	st	%l6, [%l5 + %lo(C_LABEL(pdma_size))]
+	/* Prevent recursion */
+	sethi	%hi(C_LABEL(doing_pdma)), %l4
+	st	%g0, [%l4 + %lo(C_LABEL(doing_pdma))]
 
-	jmp	%l1
-	rett %	l2
-	
-	.align 4
-	.globl sparc_timer
-sparc_timer:
-	ENTER_IRQ(sparc_timer)
-
-	sethi	%hi(C_LABEL(master_l10_limit)), %l4
-	ld	[%l4 + %lo(C_LABEL(master_l10_limit))], %l4
-	ld	[%l4], %g0			! read the limit register
-
-	std	%g2, [%sp + C_STACK + PT_G2]
-	or	%g0, %g1, %l7
-	rd	%y, %l6
-	std	%g4, [%sp + C_STACK + PT_G4]
-	andn	%l0, PSR_PIL, %l4
-/*	sll	%l3, 0x8, %l5 */
-	std	%g6, [%sp + C_STACK + PT_G6]
-/*	or	%l5, %l4, %l4 */
+	/* fall through... */
+floppy_dosoftint:
+	rd	%wim, %l3
+	SAVE_ALL
 
-	/* Magic, we can't increase PIL and set ET at the same
-	 * time or the chip calls prom_panic().
-	 */
-/*	wr	%l4, 0x0, %psr */
+	/* Set all IRQs off. */
+	or	%l0, PSR_PIL, %l4
+	wr	%l4, 0x0, %psr
 	wr	%l4, PSR_ET, %psr
+	WRITE_PAUSE
 
-	or	%g0, 10, %o0
-	add	%sp, C_STACK, %o1
-	call	C_LABEL(do_IRQ)
-	nop
-
-	or	%g0, %l7, %g1
-	wr	%l6, 0x0, %y
-	ldd	[%sp + C_STACK + PT_G2], %g2
-	ldd	[%sp + C_STACK + PT_G4], %g4
-	ldd	[%sp + C_STACK + PT_G6], %g6
+	mov	11, %o0			! floppy irq level
+	call	C_LABEL(floppy_interrupt)
+	 add	%sp, STACKFRAME_SZ, %o1	! struct pt_regs *regs
 
-	b	ret_trap_entry
-	wr	%l0, 0x0, %psr
+	RESTORE_ALL
+	
+#endif /* (CONFIG_BLK_DEV_FD) */
+
+	/* Bad trap handler */
+	.globl	bad_trap_handler
+bad_trap_handler:
+	SAVE_ALL
+	wr	%l0, PSR_ET, %psr
+	WRITE_PAUSE
 
+	mov	%l7, %o0		! trap number
+	mov	%l0, %o1		! psr
+	call	C_LABEL(do_hw_interrupt)
+	 mov	%l1, %o2		! pc
+	RESTORE_ALL
+	
 /* For now all IRQ's not registered get sent here. handler_irq() will
  * see if a routine is registered to handle this interrupt and if not
  * it will say so on the console.
  */
 
-	.align 4
-	.globl real_irq_entry
+	.align	4
+	.globl	real_irq_entry
 real_irq_entry:
-	ENTER_IRQ(real_irq_entry)
-	std	%g2, [%sp + C_STACK + PT_G2]
-	or	%g0, %g1, %l7
-	rd	%y, %l6
-	std	%g4, [%sp + C_STACK + PT_G4]
-	andn	%l0, PSR_PIL, %l4
-	sll	%l3, 0x8, %l5
-	std	%g6, [%sp + C_STACK + PT_G6]
-	or	%l5, %l4, %l4
+	SAVE_ALL
 
+	/* start atomic operation with respect to software interrupts */
+	sethi	%hi(C_LABEL(intr_count)), %l4
+	ld	[%l4 + %lo(C_LABEL(intr_count))], %l5
+	add	%l5, 0x1, %l5
+	st	%l5, [%l4 + %lo(C_LABEL(intr_count))]
+
+	/* Enable traps w/IRQs off, so we can call c-code properly.
+	 * Note how we are increasing PIL so we need to do two writes
+	 * to work around a MicroSPARC bug of sorts.
+	 */
+	or	%l0, PSR_PIL, %l4
 	wr	%l4, 0x0, %psr
 	wr	%l4, PSR_ET, %psr
+	WRITE_PAUSE
 
-	std	%l0, [%sp + C_STACK + PT_PSR]
-	std	%l2, [%sp + C_STACK + PT_NPC]
-	
-	or	%g0, %l3, %o0	
-	add	%sp, C_STACK, %o1
+	mov	%l7, %o0		! irq level
 	call	C_LABEL(handler_irq)
-	nop
-
-	or	%g0, %l7, %g1
-	wr	%l6, 0x0, %y
-	ldd	[%sp + C_STACK + PT_G2], %g2
-	ldd	[%sp + C_STACK + PT_G4], %g4
-	ldd	[%sp + C_STACK + PT_G6], %g6
-	b	ret_trap_entry
-	wr	%l0, 0x0, %psr
-
-
-/* This routine is optimized for kernel window fills. User fills take about two
- * or three extra jumps on the average. We'll see how this works out.
- */
-
-/* Don't use local labels, or if you do be REAL CAREFUL. TRAP_WIN_CLEAN is
- * full of them! If you think this routine is hairy, window fills are worse,
- * see below.
- */
-
-	.align 4
-	.globl spill_window_entry
-spill_window_entry:
-	andcc	%l0, PSR_PS, %g0	! see if this is a user window fill
-	bz,a	spill_from_user
-	nop
-
-	TRAP_WIN_CLEAN			/* danger, danger... */
-	wr	%l0, 0x0, %psr	
-	nop
-	jmp	%l1
-	rett	%l2
+	 add	%sp, STACKFRAME_SZ, %o1	! pt_regs ptr
 
-spill_from_user:
-	sethi	%hi( C_LABEL(current) ), %l6
-	ld	[%l6 + %lo( C_LABEL(current) )], %l6
-	ld	[%l6 + THREAD_WIM], %l5
-	and	%l0, 0x1f, %l3
-
-/* I don't know what's worse, the extra comparison here, or an extra load
- * from a lookup table, we'll see.
- */
-	cmp	%l5, %l3
-	ble,a	1f
-	sethi	%hi( C_LABEL(nwindowsm1) ), %l4
-	sub	%l5, %l3, %l3
-	b	2f
-	sub	%l3, 0x1, %l5
-1:
-	ld	[%l4 + %lo( C_LABEL(nwindowsm1) )], %l4
-	sub	%l4, %l3, %l4
-	add	%l5, %l4, %l5
+rie_checkbh:
+	sethi	%hi(C_LABEL(intr_count)), %l4
+	ld	[%l4 + %lo(C_LABEL(intr_count))], %l5
+	subcc	%l5, 0x1, %l5
+	bne	2f	/* IRQ within IRQ, get out of here... */
+	 nop
+	sethi	%hi(C_LABEL(bh_active)), %l3
+	ld	[%l3 + %lo(C_LABEL(bh_active))], %g2
+	sethi	%hi(C_LABEL(bh_mask)), %l3
+	ld	[%l3 + %lo(C_LABEL(bh_mask))], %g3
+	andcc	%g2, %g3, %g0
+	be	2f
+	 nop
+	call	C_LABEL(do_bottom_half)	
+	 nop
+	/* Try again... */
+	b	rie_checkbh
+	 nop
+	
 2:
-	st	%l5, [%l6 + THREAD_UWINDOWS]
-
-	TRAP_WIN_CLEAN		   /* danger, danger... */
-	sethi	%hi( C_LABEL(current) ), %l6
-	ld	[%l6 + %lo( C_LABEL(current) )], %l6
-	ld	[%l6 + THREAD_KSP], %sp
-	and	%l0, 0x1f, %l3
-	sethi	%hi(lnx_winmask), %l6
-	or	%l6, %lo(lnx_winmask), %l6
-	ldub	[%l6 + %l3], %l5
-	rd	%wim, %l4
-	jmp	%l1
-	rett	%l2
+	st	%l5, [%l4 + %lo(C_LABEL(intr_count))]
+	RESTORE_ALL
 
-/* A window spill has occurred.  This presents a weird situation, a restore
- * was attempted and a trap occurred. Therefore the restore attempt had no
- * effect on window movement and the trap saved, which means it went in the
- * other direction. :-( We are in a trap window which is two restores away
- * from the window we want to un-invalidate so to speak and three away from
- * the one which will become invalid after this routine. There are probably
- * bugs already this routine. Bugs suck.
- */
-
-/* This is a very complicated and hairy routine, don't expect to understand
- * it the first time. :>
- */
-
-	.align 4
-	.globl fill_window_entry
-fill_window_entry:
-	wr	%g0, 0, %wim		! Can not enter invalid register without this.
-	andcc	%l0, 0x40, %g0          ! From user?
-	restore				! restore to where trap occurred
-	bz	fill_from_user
-	restore				! enter invalid register, whee...
-	restore %g0, 0x1, %l1		! enter one-past invalid register
-	rd	%psr, %l0		! this is the window we need to save
-	and	%l0, 0x1f, %l0
-	sll	%l1, %l0, %l1
-	wr	%l1, 0x0, %wim
-	sethi	%hi( C_LABEL(current) ), %l1
-	ld	[%l1 + %lo( C_LABEL(current) )], %l1
-	st	%l0, [%l1 + THREAD_WIM]
-	save	%g0, %g0, %g0		! back to invalid register
-	ldd	[%sp], %l0		! load the window from stack
-	ldd	[%sp + 8], %l2
-	ldd	[%sp + 16], %l4
-	ldd	[%sp + 24], %l6
-	ldd	[%sp + 32], %i0
-	ldd	[%sp + 40], %i2
-	ldd	[%sp + 48], %i4
-	ldd	[%sp + 56], %i6
-	save	%g0, %g0, %g0		! to window where trap happened
-	save	%g0, %g0, %g0		! back to trap window, so rett works
-	wr	%l0, 0x0, %psr		! load condition codes
-	nop
-	jmp	%l1
-	rett	%l2			! are you as confused as I am?
+/* Soft IRQ's are handled just like hard IRQ's except that we
+ * need to clear the IRQ line ourselves (in the interrupt reg)
+ * and we don't take care of bottom-half handlers here.  We'll
+ * just deal with it at the next clock tick, and since software
+ * IRQ's relatively don't happen that often....
+ * XXX BIG XXX Turn the software IRQ bit we need to clear into
+ * XXX BIG XXX an element reference in an array that we can set
+ * XXX BIG XXX a boot time based upon arch type
+ * XXX BIG XXX OR... rewrite the appropriate IRQ trap table
+ * XXX BIG XXX entries once the arch is detected (sun4/4c or sun4m)
+ *
+ * XXX EVEN BIGGER XXX Linux has bh_handlers for software interrupts
+ * XXX EVEN BIGGER XXX so we do not even have to worry about this
+ * XXX EVEN BIGGER XXX brain damaged software interrupt mechanism.
+ */
+
+	.align	4
+	.globl	soft_irq_entry
+soft_irq_entry:
+	SAVE_ALL
+
+	/* We have tucked the bit to clear in the int reg into
+	 * %l4, take care of it now before we do anything else.
+	 */
+	sethi	%hi(INTREG_VADDR), %l5
+	ldsb	[%l5 + %lo(INTREG_VADDR)], %l6
+	andn	%l6, %l4, %l6
+	stb	%l6, [%l5 + %lo(INTREG_VADDR)]
+
+	/* start atomic operation with respect to software interrupts */
+	sethi	%hi(C_LABEL(intr_count)), %l4
+	ld	[%l4 + %lo(C_LABEL(intr_count))], %l5
+	add	%l5, 0x1, %l5
+	st	%l5, [%l4 + %lo(C_LABEL(intr_count))]
+
+	or	%l0, PSR_PIL, %l4
+	wr	%l4, 0x0, %psr		! grrr!
+	wr	%l4, PSR_ET, %psr	! double grrr!
 
-fill_from_user:
-	andcc	%sp, 0x7, %g0		! check for alignment of user stack
-	bne	fill_bad_stack
-	sra	%sp, 0x1e, %l7
-	cmp	%l7, 0x0
-	be,a	1f
-	andn	%sp, 0xfff, %l7
-	cmp	%l7, -1
-	bne	fill_bad_stack
-	andn	%sp, 0xfff, %l7
-1:
-	lda	[%l7] ASI_PTE, %l7
-	srl	%l7, 0x1d, %l7
-	andn	%l7, 0x2, %l7
-	cmp	%l7, 0x4
-	bne	fill_bad_stack
-	and	%sp, 0xfff, %l7
-	cmp	%l7, 0xfc1
-	bl,a	fill_stack_ok
-	restore	%g0, 1, %l1
-	add	%sp, 0x38, %l5
-	sra	%sp, 0x1e, %l7
-	cmp	%l7, 0x0
-	be,a	1f
-	andn	%sp, 0xfff, %l7
-	cmp	%l7, -1
-	bne	fill_bad_stack
-	andn	%sp, 0xfff, %l7
-1:
-	lda	[%l7] ASI_PTE, %l7
-	srl	%l7, 0x1d, %l7
-	andn	%l7, 0x2, %l7
-	cmp	%l7, 0x4
-	be,a	fill_stack_ok
-	restore	%g0, 0x1, %l1
-
-fill_bad_stack:
-	save	%g0, %g0, %g0			! save to where restore happened
-	save	%g0, 0x1, %l4			! save is an add remember? to trap window
-	sethi	%hi( C_LABEL(current) ), %l6
-	ld	[%l6 + %lo( C_LABEL(current) )], %l6
-	st	%l4, [%l6 + THREAD_UWINDOWS]	! update current->tss values
-	ld	[%l6 + THREAD_WIM], %l5
-	sll	%l4, %l5, %l4
-	wr	%l4, 0x0, %wim
-	ld	[%l6 + THREAD_KSP], %sp		! set to kernel stack pointer
-	wr	%l0, PSR_ET, %psr		! turn off traps
-	std	%l0, [%sp + C_STACK]		! set up thread_frame XXX
-	rd	%y, %l3
-	std	%l2, [%sp + C_STACK + 0x8]
-	or	%g0, 0x6, %o0			! so _sparc_trap knows what to do
-	st	%g1, [%sp + C_STACK + 0x14]	! no need to save %g0, always zero
-	or	%g0, %l0, %o1
-	std	%g2, [%sp + C_STACK + 0x18]
-	or	%g0, %l1, %o2
-	std	%g4, [%sp + C_STACK + 0x20]
-	add	%sp, C_STACK, %o3
-	std	%g6, [%sp + C_STACK + 0x28]
-	std	%i0, [%sp + C_STACK + 0x30]
-	std	%i2, [%sp + C_STACK + 0x38]
-	std	%i4, [%sp + C_STACK + 0x40]
-	nop					/* SHould trap here */
-	std	%i6, [%sp + C_STACK + 0x48]
-	
-	ldd	[%sp + C_STACK], %l0
-	ldd	[%sp + C_STACK + 0x8], %l2
-	wr	%l3, 0, %y
-	ld	[%sp + C_STACK + 0x14], %g1
-	ldd	[%sp + C_STACK + 0x18], %g2
-	ldd	[%sp + C_STACK + 0x20], %g4
-	ldd	[%sp + C_STACK + 0x28], %g6
-	ldd	[%sp + C_STACK + 0x30], %i0
-	ldd	[%sp + C_STACK + 0x38], %i2
-	ldd	[%sp + C_STACK + 0x40], %i4
-	wr	%l0, 0, %psr			! disable traps again
-	ldd	[%sp + C_STACK + 0x48], %i6
-	sethi	%hi( C_LABEL(current) ), %l6
-	ld	[%l6 + %lo( C_LABEL(current) )], %l6
-	ld	[%l6 + THREAD_W_SAVED], %l7
-	cmp	%l7, 0x0
-	bl,a	1f
-	wr	%g0, 0x0, %wim
-	/* Should trap here */
+	mov	%l7, %o0	
+	add	%sp, STACKFRAME_SZ, %o1
+	call	C_LABEL(handler_irq)
+	 nop
 
-1:
-	or	%g0, %g6, %l3
-	or	%g0, %l6, %g6
-	st	%g0, [%g6 + THREAD_W_SAVED]
-	restore	%g0, %g0, %g0
-	restore	%g0, %g0, %g0
-	restore	%g0, 0x1, %l1
-	rd	%psr, %l0
-	sll	%l1, %l0, %l1
-	wr	%l1, 0x0, %wim
-	and	%l0, 0x1f, %l0
-	st	%l0, [%g6 + THREAD_WIM]
-	nop
-	save	%g0, %g0, %g0
-	ldd	[%sp], %l0			! load number one
-	ldd	[%sp + 0x8], %l2
-	ldd	[%sp + 0x10], %l4
-	ldd	[%sp + 0x18], %l6
-	ldd	[%sp + 0x20], %i0
-	ldd	[%sp + 0x28], %i2
-	ldd	[%sp + 0x30], %i4
-	ldd	[%sp + 0x38], %i6
-	save	%g0, %g0, %g0
-	ldd	[%sp], %l0			! load number two
-	ldd	[%sp + 0x8], %l2	
-	ldd	[%sp + 0x10], %l4
-	ldd	[%sp + 0x18], %l6
-	ldd	[%sp + 0x20], %i0
-	ldd	[%sp + 0x28], %i2
-	ldd	[%sp + 0x30], %i4
-	ldd	[%sp + 0x38], %i6
-	save	%g0, %g0, %g0			! re-enter trap window
-	wr	%l0, 0x0, %psr			! restore condition codes
-	or	%g0, %l3, %g6			! restore scratch register
-	jmp	%l1
-	rett	%l2
+	sethi	%hi(C_LABEL(intr_count)), %l4
+	ld	[%l4 + %lo(C_LABEL(intr_count))], %l5
+	subcc	%l5, 0x1, %l5
+	st	%l5, [%l4 + %lo(C_LABEL(intr_count))]
 
-fill_stack_ok:
-	rd	%psr, %l0
-	sll	%l1, %l0, %l1
-	wr	%l1, 0x0, %wim
-	sethi	%hi( C_LABEL(current) ), %l2
-	ld	[%l2 + %lo( C_LABEL(current) )], %l2
-	and	%l0, 0x1f, %l0
-	st	%l0, [%l2 + THREAD_WIM]
-	save	%g0, %g0, %g0
-	ldd	[%sp], %l0			! only one load necessary
-	ldd	[%sp + 0x8], %l2
-	ldd	[%sp + 0x10], %l4
-	ldd	[%sp + 0x18], %l6
-	ldd	[%sp + 0x20], %i0
-	ldd	[%sp + 0x28], %i2
-	ldd	[%sp + 0x30], %i4
-	ldd	[%sp + 0x38], %i6
-	save	%g0, %g0, %g0
-	save	%g0, %g0, %g0			! save into trap window
-	wr	%l0, 0x0, %psr			! local number 0 here has cond codes
-	nop
-	jmp	%l1
-	rett	%l2
+	RESTORE_ALL
 
 	/* This routine handles illegal isntructions and privileged
 	 * instruction attempts from user code.
 	 */
-	.align 4
-	.globl bad_instruction
+	.align	4
+	.globl	bad_instruction
 bad_instruction:
-	ENTER_TRAP(bad_instruction)
-	st	%g1, [%sp + C_STACK + PT_G1]
-	rd	%y, %l4
-	std	%g2, [%sp + C_STACK + PT_G2]
-	std	%g4, [%sp + C_STACK + PT_G4]
-	std	%g6, [%sp + C_STACK + PT_G6]
+	SAVE_ALL
 	wr	%l0, PSR_ET, %psr		! re-enable traps
-	add	%sp, C_STACK, %o0
+	WRITE_PAUSE
+
+	add	%sp, STACKFRAME_SZ, %o0
 	mov	%l1, %o1
 	mov	%l2, %o2
-	cmp	%l3, 0x2
-	bne	1f
 	call	C_LABEL(do_illegal_instruction)
-	mov	%l0, %o3
-	b	2f
-	ld	[%sp + C_STACK + PT_G1], %g1
+	 mov	%l0, %o3
+	RESTORE_ALL
 
-1:
+	.align	4
+	.globl	priv_instruction
+priv_instruction:
+	SAVE_ALL
+	wr	%l0, PSR_ET, %psr
+	WRITE_PAUSE
+
+	add	%sp, STACKFRAME_SZ, %o0
+	mov	%l1, %o1
+	mov	%l2, %o2
 	call	C_LABEL(do_priv_instruction)
-	mov	%l0, %o3
-	ld	[%sp + C_STACK + PT_G1], %g1
-2:
-	wr	%l0, 0x0, %psr
-	ldd	[%sp + C_STACK + PT_G2], %g2
-	ldd	[%sp + C_STACK + PT_G4], %g4
-	ldd	[%sp + C_STACK + PT_G6], %g6
-	b	ret_trap_entry
-	wr	%l4, 0, %y
+	 mov	%l0, %o3
+	RESTORE_ALL
 
 	/* This routine handles unaligned data accesses.
 	 */
-	.align 4
-	.globl mna_handler
+	.align	4
+	.globl	mna_handler
 mna_handler:
-	ENTER_TRAP(mna_handler)
-	st	%g1, [%sp + C_STACK + PT_G1]
-	rd	%y, %l4
-	std	%g2, [%sp + C_STACK + PT_G2]
-	std	%g4, [%sp + C_STACK + PT_G4]
-	std	%g6, [%sp + C_STACK + PT_G6]
+	SAVE_ALL
 	wr	%l0, PSR_ET, %psr		! re-enable traps
-	add	%sp, C_STACK, %o0
+	WRITE_PAUSE
+
+	add	%sp, STACKFRAME_SZ, %o0
 	mov	%l1, %o1
 	mov	%l2, %o2
 	call	C_LABEL(do_memaccess_unaligned)
-	mov	%l0, %o3
-
-	ld	[%sp + C_STACK + PT_G1], %g1
-	wr	%l0, 0x0, %psr
-	ldd	[%sp + C_STACK + PT_G2], %g2
-	ldd	[%sp + C_STACK + PT_G4], %g4
-	ldd	[%sp + C_STACK + PT_G6], %g6
-	b	ret_trap_entry
-	wr	%l4, 0, %y
+	 mov	%l0, %o3
+	RESTORE_ALL
 
-	/* This routine handles floating point disabled traps.
-	 */
-	.align 4
-	.globl fpd_trap_handler
+	/* This routine handles floating point disabled traps. */
+	.align	4
+	.globl	fpd_trap_handler
 fpd_trap_handler:
-	ENTER_TRAP(fpd_trap_handler)
-	st	%g1, [%sp + C_STACK + PT_G1]
-	rd	%y, %l4
-	std	%g2, [%sp + C_STACK + PT_G2]
-	std	%g4, [%sp + C_STACK + PT_G4]
-	std	%g6, [%sp + C_STACK + PT_G6]
+	SAVE_ALL
 	wr	%l0, PSR_ET, %psr		! re-enable traps
-	add	%sp, C_STACK, %o0
+	WRITE_PAUSE
+
+	add	%sp, STACKFRAME_SZ, %o0
 	mov	%l1, %o1
 	mov	%l2, %o2
 	call	C_LABEL(do_fpd_trap)
-	mov	%l0, %o3
-
-	ld	[%sp + C_STACK + PT_G1], %g1
-	wr	%l0, 0x0, %psr
-	ldd	[%sp + C_STACK + PT_G2], %g2
-	ldd	[%sp + C_STACK + PT_G4], %g4
-	ldd	[%sp + C_STACK + PT_G6], %g6
-	b	ret_trap_entry
-	wr	%l4, 0, %y
+	 mov	%l0, %o3
+	RESTORE_ALL
 
-	/* This routine handles Floating Point Exceptions.
-	 */
-	.align 4
-	.globl fpe_trap_handler
+	/* This routine handles Floating Point Exceptions. */
+	.align	4
+	.globl	fpe_trap_handler
 fpe_trap_handler:
-	ENTER_TRAP(fpe_trap_handler)
-	st	%g1, [%sp + C_STACK + PT_G1]
-	rd	%y, %l4
-	std	%g2, [%sp + C_STACK + PT_G2]
-	std	%g4, [%sp + C_STACK + PT_G4]
-	std	%g6, [%sp + C_STACK + PT_G6]
+	SAVE_ALL
 	wr	%l0, PSR_ET, %psr		! re-enable traps
-	add	%sp, C_STACK, %o0
+	WRITE_PAUSE
+
+	add	%sp, STACKFRAME_SZ, %o0
 	mov	%l1, %o1
 	mov	%l2, %o2
 	call	C_LABEL(do_fpe_trap)
-	mov	%l0, %o3
-
-	ld	[%sp + C_STACK + PT_G1], %g1
-	wr	%l0, 0x0, %psr
-	ldd	[%sp + C_STACK + PT_G2], %g2
-	ldd	[%sp + C_STACK + PT_G4], %g4
-	ldd	[%sp + C_STACK + PT_G6], %g6
-	b	ret_trap_entry
-	wr	%l4, 0, %y
+	 mov	%l0, %o3
+	RESTORE_ALL
 
-	/* This routine handles Tag Overflow Exceptions.
-	 */
-	.align 4
-	.globl do_tag_overflow
+	/* This routine handles Tag Overflow Exceptions. */
+	.align	4
+	.globl	do_tag_overflow
 do_tag_overflow:
-	ENTER_TRAP(do_tag_overflow)
-	st	%g1, [%sp + C_STACK + PT_G1]
-	rd	%y, %l4
-	std	%g2, [%sp + C_STACK + PT_G2]
-	std	%g4, [%sp + C_STACK + PT_G4]
-	std	%g6, [%sp + C_STACK + PT_G6]
+	SAVE_ALL
 	wr	%l0, PSR_ET, %psr		! re-enable traps
-	add	%sp, C_STACK, %o0
+	WRITE_PAUSE
+
+	add	%sp, STACKFRAME_SZ, %o0
 	mov	%l1, %o1
 	mov	%l2, %o2
 	call	C_LABEL(handle_tag_overflow)
-	mov	%l0, %o3
+	 mov	%l0, %o3
+	RESTORE_ALL
 
-	ld	[%sp + C_STACK + PT_G1], %g1
-	wr	%l0, 0x0, %psr
-	ldd	[%sp + C_STACK + PT_G2], %g2
-	ldd	[%sp + C_STACK + PT_G4], %g4
-	ldd	[%sp + C_STACK + PT_G6], %g6
-	b	ret_trap_entry
-	wr	%l4, 0, %y
-
-	/* This routine handles Watchpoint Exceptions.
-	 */
-	.align 4
-	.globl do_watchpoint
+	/* This routine handles Watchpoint Exceptions. */
+	.align	4
+	.globl	do_watchpoint
 do_watchpoint:
-	ENTER_TRAP(do_watchpoint)
-	st	%g1, [%sp + C_STACK + PT_G1]
-	rd	%y, %l4
-	std	%g2, [%sp + C_STACK + PT_G2]
-	std	%g4, [%sp + C_STACK + PT_G4]
-	std	%g6, [%sp + C_STACK + PT_G6]
+	SAVE_ALL
 	wr	%l0, PSR_ET, %psr		! re-enable traps
-	add	%sp, C_STACK, %o0
+	WRITE_PAUSE
+
+	add	%sp, STACKFRAME_SZ, %o0
 	mov	%l1, %o1
 	mov	%l2, %o2
 	call	C_LABEL(handle_watchpoint)
-	mov	%l0, %o3
+	 mov	%l0, %o3
+	RESTORE_ALL
 
-	ld	[%sp + C_STACK + PT_G1], %g1
-	wr	%l0, 0x0, %psr
-	ldd	[%sp + C_STACK + PT_G2], %g2
-	ldd	[%sp + C_STACK + PT_G4], %g4
-	ldd	[%sp + C_STACK + PT_G6], %g6
-	b	ret_trap_entry
-	wr	%l4, 0, %y
-
-	/* This routine handles Register Access Exceptions.
-	 */
-	.align 4
-	.globl do_reg_access
+	/* This routine handles Register Access Exceptions. */
+	.align	4
+	.globl	do_reg_access
 do_reg_access:
-	ENTER_TRAP(do_reg_access)
-	st	%g1, [%sp + C_STACK + PT_G1]
-	rd	%y, %l4
-	std	%g2, [%sp + C_STACK + PT_G2]
-	std	%g4, [%sp + C_STACK + PT_G4]
-	std	%g6, [%sp + C_STACK + PT_G6]
+	SAVE_ALL
 	wr	%l0, PSR_ET, %psr		! re-enable traps
-	add	%sp, C_STACK, %o0
-	mov	%l1, %o1
-	mov	%l2, %o2
-	call	C_LABEL(handle_reg_access)
-	mov	%l0, %o3
-
-	ld	[%sp + C_STACK + PT_G1], %g1
-	wr	%l0, 0x0, %psr
-	ldd	[%sp + C_STACK + PT_G2], %g2
-	ldd	[%sp + C_STACK + PT_G4], %g4
-	ldd	[%sp + C_STACK + PT_G6], %g6
-	b	ret_trap_entry
-	wr	%l4, 0, %y
+	WRITE_PAUSE
 
-	/* This routine handles Instruction Access Errors.
-	 */
-	.align 4
-	.globl do_iacc_error
-do_iacc_error:
-	ENTER_TRAP(do_iacc_error)
-	st	%g1, [%sp + C_STACK + PT_G1]
-	rd	%y, %l4
-	std	%g2, [%sp + C_STACK + PT_G2]
-	std	%g4, [%sp + C_STACK + PT_G4]
-	std	%g6, [%sp + C_STACK + PT_G6]
-	wr	%l0, PSR_ET, %psr		! re-enable traps
-	add	%sp, C_STACK, %o0
+	add	%sp, STACKFRAME_SZ, %o0
 	mov	%l1, %o1
 	mov	%l2, %o2
-	call	C_LABEL(handle_iacc_error)
-	mov	%l0, %o3
-
-	ld	[%sp + C_STACK + PT_G1], %g1
-	wr	%l0, 0x0, %psr
-	ldd	[%sp + C_STACK + PT_G2], %g2
-	ldd	[%sp + C_STACK + PT_G4], %g4
-	ldd	[%sp + C_STACK + PT_G6], %g6
-	b	ret_trap_entry
-	wr	%l4, 0, %y
+	call	C_LABEL(handle_reg_access)
+	 mov	%l0, %o3
+	RESTORE_ALL
 
-	/* This routine handles Co-Processor Disabled Exceptions.
-	 */
-	.align 4
-	.globl do_cp_disabled
+	/* This routine handles Co-Processor Disabled Exceptions. */
+	.align	4
+	.globl	do_cp_disabled
 do_cp_disabled:
-	ENTER_TRAP(do_cp_disabled)
-	st	%g1, [%sp + C_STACK + PT_G1]
-	rd	%y, %l4
-	std	%g2, [%sp + C_STACK + PT_G2]
-	std	%g4, [%sp + C_STACK + PT_G4]
-	std	%g6, [%sp + C_STACK + PT_G6]
+	SAVE_ALL
 	wr	%l0, PSR_ET, %psr		! re-enable traps
-	add	%sp, C_STACK, %o0
+	WRITE_PAUSE
+
+	add	%sp, STACKFRAME_SZ, %o0
 	mov	%l1, %o1
 	mov	%l2, %o2
 	call	C_LABEL(handle_cp_disabled)
-	mov	%l0, %o3
-
-	ld	[%sp + C_STACK + PT_G1], %g1
-	wr	%l0, 0x0, %psr
-	ldd	[%sp + C_STACK + PT_G2], %g2
-	ldd	[%sp + C_STACK + PT_G4], %g4
-	ldd	[%sp + C_STACK + PT_G6], %g6
-	b	ret_trap_entry
-	wr	%l4, 0, %y
+	 mov	%l0, %o3
+	RESTORE_ALL
 
-	/* This routine handles Unimplemented FLUSH Exceptions.
-	 */
-	.align 4
-	.globl do_bad_flush
+	/* This routine handles Unimplemented FLUSH Exceptions. */
+	.align	4
+	.globl	do_bad_flush
 do_bad_flush:
-	ENTER_TRAP(do_bad_flush)
-	st	%g1, [%sp + C_STACK + PT_G1]
-	rd	%y, %l4
-	std	%g2, [%sp + C_STACK + PT_G2]
-	std	%g4, [%sp + C_STACK + PT_G4]
-	std	%g6, [%sp + C_STACK + PT_G6]
+	SAVE_ALL
 	wr	%l0, PSR_ET, %psr		! re-enable traps
-	add	%sp, C_STACK, %o0
+	WRITE_PAUSE
+
+	add	%sp, STACKFRAME_SZ, %o0
 	mov	%l1, %o1
 	mov	%l2, %o2
 	call	C_LABEL(handle_bad_flush)
-	mov	%l0, %o3
-
-	ld	[%sp + C_STACK + PT_G1], %g1
-	wr	%l0, 0x0, %psr
-	ldd	[%sp + C_STACK + PT_G2], %g2
-	ldd	[%sp + C_STACK + PT_G4], %g4
-	ldd	[%sp + C_STACK + PT_G6], %g6
-	b	ret_trap_entry
-	wr	%l4, 0, %y
+	 mov	%l0, %o3
+	RESTORE_ALL
 
-	/* This routine handles Co-Processor Exceptions.
-	 */
-	.align 4
-	.globl do_cp_exception
+	/* This routine handles Co-Processor Exceptions. */
+	.align	4
+	.globl	do_cp_exception
 do_cp_exception:
-	ENTER_TRAP(do_cp_exception)
-	st	%g1, [%sp + C_STACK + PT_G1]
-	rd	%y, %l4
-	std	%g2, [%sp + C_STACK + PT_G2]
-	std	%g4, [%sp + C_STACK + PT_G4]
-	std	%g6, [%sp + C_STACK + PT_G6]
+	SAVE_ALL
 	wr	%l0, PSR_ET, %psr		! re-enable traps
-	add	%sp, C_STACK, %o0
-	mov	%l1, %o1
-	mov	%l2, %o2
-	call	C_LABEL(handle_cp_exception)
-	mov	%l0, %o3
-
-	ld	[%sp + C_STACK + PT_G1], %g1
-	wr	%l0, 0x0, %psr
-	ldd	[%sp + C_STACK + PT_G2], %g2
-	ldd	[%sp + C_STACK + PT_G4], %g4
-	ldd	[%sp + C_STACK + PT_G6], %g6
-	b	ret_trap_entry
-	wr	%l4, 0, %y
+	WRITE_PAUSE
 
-	/* This routine handles Data Access Errors.
-	 */
-	.align 4
-	.globl do_dacc_error
-do_dacc_error:
-	ENTER_TRAP(do_dacc_error)
-	st	%g1, [%sp + C_STACK + PT_G1]
-	rd	%y, %l4
-	std	%g2, [%sp + C_STACK + PT_G2]
-	std	%g4, [%sp + C_STACK + PT_G4]
-	std	%g6, [%sp + C_STACK + PT_G6]
-	wr	%l0, PSR_ET, %psr		! re-enable traps
-	add	%sp, C_STACK, %o0
+	add	%sp, STACKFRAME_SZ, %o0
 	mov	%l1, %o1
 	mov	%l2, %o2
-	call	C_LABEL(handle_dacc_error)
-	mov	%l0, %o3
-
-	ld	[%sp + C_STACK + PT_G1], %g1
-	wr	%l0, 0x0, %psr
-	ldd	[%sp + C_STACK + PT_G2], %g2
-	ldd	[%sp + C_STACK + PT_G4], %g4
-	ldd	[%sp + C_STACK + PT_G6], %g6
-	b	ret_trap_entry
-	wr	%l4, 0, %y
+	call	C_LABEL(handle_cp_exception)
+	 mov	%l0, %o3
+	RESTORE_ALL
 
-	/* This routine handles Hardware Divide By Zero Exceptions.
-	 */
-	.align 4
-	.globl do_hw_divzero
+	/* This routine handles Hardware Divide By Zero Exceptions. */
+	.align	4
+	.globl	do_hw_divzero
 do_hw_divzero:
-	ENTER_TRAP(do_hw_divzero)
-	st	%g1, [%sp + C_STACK + PT_G1]
-	rd	%y, %l4
-	std	%g2, [%sp + C_STACK + PT_G2]
-	std	%g4, [%sp + C_STACK + PT_G4]
-	std	%g6, [%sp + C_STACK + PT_G6]
+	SAVE_ALL
 	wr	%l0, PSR_ET, %psr		! re-enable traps
-	add	%sp, C_STACK, %o0
-	mov	%l1, %o1
-	mov	%l2, %o2
-	call	C_LABEL(handle_hw_divzero)
-	mov	%l0, %o3
-
-	ld	[%sp + C_STACK + PT_G1], %g1
-	wr	%l0, 0x0, %psr
-	ldd	[%sp + C_STACK + PT_G2], %g2
-	ldd	[%sp + C_STACK + PT_G4], %g4
-	ldd	[%sp + C_STACK + PT_G6], %g6
-	b	ret_trap_entry
-	wr	%l4, 0, %y
+	WRITE_PAUSE
 
-	/* This routine handles Data Store Errors.
-	 */
-	.align 4
-	.globl do_dstore_err
-do_dstore_err:
-	ENTER_TRAP(do_dstore_err)
-	st	%g1, [%sp + C_STACK + PT_G1]
-	rd	%y, %l4
-	std	%g2, [%sp + C_STACK + PT_G2]
-	std	%g4, [%sp + C_STACK + PT_G4]
-	std	%g6, [%sp + C_STACK + PT_G6]
-	wr	%l0, PSR_ET, %psr		! re-enable traps
-	add	%sp, C_STACK, %o0
+	add	%sp, STACKFRAME_SZ, %o0
 	mov	%l1, %o1
 	mov	%l2, %o2
-	call	C_LABEL(handle_dstore_error)
-	mov	%l0, %o3
+	call	C_LABEL(handle_hw_divzero)
+	 mov	%l0, %o3
+	RESTORE_ALL
 
-	ld	[%sp + C_STACK + PT_G1], %g1
-	wr	%l0, 0x0, %psr
-	ldd	[%sp + C_STACK + PT_G2], %g2
-	ldd	[%sp + C_STACK + PT_G4], %g4
-	ldd	[%sp + C_STACK + PT_G6], %g6
-	b	ret_trap_entry
-	wr	%l4, 0, %y
+	.align	4
+	.globl	do_flush_windows
+do_flush_windows:
+	SAVE_ALL
 
-	/* This routine handles Data Access MMU-Miss Exceptions.
-	 */
-	.align 4
-	.globl do_dacc_mmu_miss
-do_dacc_mmu_miss:
-	ENTER_TRAP(do_dacc_mmu_miss)
-	st	%g1, [%sp + C_STACK + PT_G1]
-	rd	%y, %l4
-	std	%g2, [%sp + C_STACK + PT_G2]
-	std	%g4, [%sp + C_STACK + PT_G4]
-	std	%g6, [%sp + C_STACK + PT_G6]
-	wr	%l0, PSR_ET, %psr		! re-enable traps
-	add	%sp, C_STACK, %o0
-	mov	%l1, %o1
-	mov	%l2, %o2
-	call	C_LABEL(handle_dacc_mmu_miss)
-	mov	%l0, %o3
+	wr	%l0, PSR_ET, %psr
+	WRITE_PAUSE
 
-	ld	[%sp + C_STACK + PT_G1], %g1
-	wr	%l0, 0x0, %psr
-	ldd	[%sp + C_STACK + PT_G2], %g2
-	ldd	[%sp + C_STACK + PT_G4], %g4
-	ldd	[%sp + C_STACK + PT_G6], %g6
-	b	ret_trap_entry
-	wr	%l4, 0, %y
+	call	C_LABEL(flush_user_windows)
+	 nop
 
-	/* This routine handles Instruction Access MMU-Miss Exceptions.
-	 */
-	.align 4
-	.globl do_iacc_mmu_miss
-do_iacc_mmu_miss:
-	ENTER_TRAP(do_iacc_mmu_miss)
-	st	%g1, [%sp + C_STACK + PT_G1]
-	rd	%y, %l4
-	std	%g2, [%sp + C_STACK + PT_G2]
-	std	%g4, [%sp + C_STACK + PT_G4]
-	std	%g6, [%sp + C_STACK + PT_G6]
-	wr	%l0, PSR_ET, %psr		! re-enable traps
-	add	%sp, C_STACK, %o0
-	mov	%l1, %o1
-	mov	%l2, %o2
-	call	C_LABEL(handle_iacc_mmu_miss)
-	mov	%l0, %o3
+	/* Advance over the trap instruction. */
+	ld	[%sp + STACKFRAME_SZ + PT_NPC], %l1
+	add	%l1, 0x4, %l2
+	st	%l1, [%sp + STACKFRAME_SZ + PT_PC]
+	st	%l2, [%sp + STACKFRAME_SZ + PT_NPC]
 
-	ld	[%sp + C_STACK + PT_G1], %g1
-	wr	%l0, 0x0, %psr
-	ldd	[%sp + C_STACK + PT_G2], %g2
-	ldd	[%sp + C_STACK + PT_G4], %g4
-	ldd	[%sp + C_STACK + PT_G6], %g6
-	b	ret_trap_entry
-	wr	%l4, 0, %y
+	RESTORE_ALL
 
 	/* The getcc software trap.  The user wants the condition codes from
 	 * the %psr in register %g1.
 	 */
 
-	.align 4
-	.globl getcc_trap_handler
+	.align	4
+	.globl	getcc_trap_handler
 getcc_trap_handler:
-	/* Shit, one more instruction and I could do this inline. */
-	sll	%l0, 0x8, %g1
-	srl	%g1, 28, %g1
-	jmp	%l2
-	rett	%l2+0x4
+	srl	%l0, 20, %g1	! give user
+	and	%g1, 0xf, %g1	! only ICC bits in %psr
+	jmp	%l2		! advance over trap instruction
+	rett	%l2 + 0x4	! like this...
 
 	/* The setcc software trap.  The user has condition codes in %g1
 	 * that it would like placed in the %psr.  Be careful not to flip
-	 * any unintention bits!
+	 * any unintentional bits!
 	 */
 
-	.align 4
-	.globl setcc_trap_handler
+	.align	4
+	.globl	setcc_trap_handler
 setcc_trap_handler:
 	sll	%g1, 0x14, %l4
 	set	PSR_ICC, %l5
-	andn	%l0, %l5, %l0
-	or	%l4, %l0, %l4
-	wr	%l4, 0x0, %psr
-	WRITE_PAUSE
-	jmp	%l2
-	rett	%l2+0x4
+	andn	%l0, %l5, %l0	! clear ICC bits in current %psr
+	and	%l4, %l5, %l4	! clear non-ICC bits in user value
+	or	%l4, %l0, %l4	! or them in... mix mix mix
+	wr	%l4, 0x0, %psr	! set new %psr
+	WRITE_PAUSE		! TI scumbags...
 
-	.align 4
-NMI_STRING:	.asciz	"NMI received, dazed and confused, halting...\n"
+	jmp	%l2		! advance over trap instruction
+	rett	%l2 + 0x4	! like this...
 
-	.align 4
-	.globl linux_trap_nmi
-	.globl C_LABEL(interrupt_enable)
+	.align	4
+	.globl	linux_trap_nmi
 linux_trap_nmi:
-	sethi	%hi(C_LABEL(prom_vector_p)), %o0
-	ld	[%o0 + %lo(C_LABEL(prom_vector_p))], %o0
-	ld	[%o0 + 0x74], %o0
-	/* Ugh, until I figure out how to clear the IRQ line ;( */
-	call	%o0
-	nop
-
-	.align 4
-	.globl sparc_text_fault
-sparc_text_fault:
-	ENTER_TRAP(sparc_text_fault)
-	st	%g1, [%sp + C_STACK + PT_G1]
-	std	%g2, [%sp + C_STACK + PT_G2]
-	std	%g4, [%sp + C_STACK + PT_G4]
-	std	%g6, [%sp + C_STACK + PT_G6]
-	rd	%y, %l4
-	sethi	%hi(AC_SYNC_ERR), %o0
-	lda	[%o0] ASI_CONTROL, %o1
-	add	%o0, 0x4, %o0           ! go to sync vaddr
-	lda	[%o0] ASI_CONTROL, %o2
-	andcc	%o1, SUN4C_SYNC_NOMEM, %g0
-	bz,a	normal_page_fault
-	wr	%l0, PSR_ET, %psr	! re-enable traps
-
-	add	%o0, 0x4, %o0           ! go to async error register
-	lda	[%o0] ASI_CONTROL, %o3
-	add	%o0, 0x4, %o0		! go to async vaddr
-	subcc	%o4, %o2, %g0
-	be,a	is_sync_fault		! not an async fault
-	wr	%l0, PSR_ET, %psr
-
-	/* crap, an asynchronous error has occurred */
+	SAVE_ALL
+	/* Ugh, we need to clear the IRQ line.  This is now
+	 * a very sun4c specific trap hanler...
+	 */
 	sethi	%hi(C_LABEL(interrupt_enable)), %l5
-	ldub	[%l5 + %lo(C_LABEL(interrupt_enable))], %o0
-	andn	%o0, INTS_ENAB, %o0
-	stb	%o0, [%l5 + %lo(C_LABEL(interrupt_enable))]
-	wr	%l0, PSR_ET, %psr		! enable traps
-	call	C_LABEL(sparc_txtmem_error)	! call high level c-code
-	or	%g0, FAULT_ASYNC, %o0
+	ld	[%l5 + %lo(C_LABEL(interrupt_enable))], %l5
+	ldub	[%l5], %l6
+	andn	%l6, INTS_ENAB, %l6
+	stb	%l6, [%l5]
 
-	ld	[%sp + C_STACK + PT_G1], %g1
-	wr	%l0, 0x0, %psr
-	ldd	[%sp + C_STACK + PT_G2], %g2
-	ldd	[%sp + C_STACK + PT_G4], %g4
-	ldd	[%sp + C_STACK + PT_G6], %g6
-	ldub	[%l5 + %lo(C_LABEL(interrupt_enable))], %o1
-	or	%o1, INTS_ENAB, %o1
-	stb	%o1, [%l5 + %lo(C_LABEL(interrupt_enable))]
-	b	ret_trap_entry
-	wr	%l4, 0, %y
-
-is_sync_fault:
-	call	C_LABEL(sparc_txtmem_error)	! call high level c-code
-	or	%g0, FAULT_SYNC, %o0
-
-	ld	[%sp + C_STACK + PT_G1], %g1
-	ld	[%sp + C_STACK + PT_G2], %g2
-	ld	[%sp + C_STACK + PT_G4], %g4
-	ld	[%sp + C_STACK + PT_G6], %g6
-	wr	%l4, 0x0, %y
-	b	ret_trap_entry
-	wr	%l0, 0x0, %psr
-
-normal_page_fault:
-	std	%l0, [%sp + C_STACK + PT_PSR]
-	or	%g0, %l3, %o0
-	st	%l2, [%sp + C_STACK + PT_NPC]
-	st	%l4, [%sp + C_STACK + PT_Y]
-	or	%g0, %l1, %o3
-	std	%i0, [%sp + C_STACK + PT_I0]
-	std	%i2, [%sp + C_STACK + PT_I2]
-	or	%g0, %l0, %o4
-	std	%i4, [%sp + C_STACK + PT_I4]
-	std	%i6, [%sp + C_STACK + PT_I6]
-	call	C_LABEL(sparc_text_access_fault)
-	add	%sp, C_STACK, %o5
-
-	ldd	[%sp + C_STACK + PT_PSR], %l0
-	ldd	[%sp + C_STACK + PT_NPC], %l2
-	wr	%l3, 0x0, %y
-	ld	[%sp + C_STACK + PT_G1], %g1
-	ldd	[%sp + C_STACK + PT_G2], %g2
-	ldd	[%sp + C_STACK + PT_G4], %g4
-	ldd	[%sp + C_STACK + PT_G6], %g6
-	ldd	[%sp + C_STACK + PT_I0], %i0
-	ldd	[%sp + C_STACK + PT_I2], %i2
-	ldd	[%sp + C_STACK + PT_I4], %i4
-	ldd	[%sp + C_STACK + PT_I6], %i6
-
-	b	ret_trap_entry
-	wr	%l0, 0x0, %psr
+	/* Now it is safe to re-enable traps without recursion. */
+	or	%l0, PSR_PIL, %l0
+	wr	%l0, PSR_ET, %psr
+	WRITE_PAUSE
 
-	.align 4
-	.globl sparc_data_fault
-sparc_data_fault:
-	ENTER_TRAP(sparc_data_fault)
-	st	%g1, [%sp + C_STACK + PT_G1]
-	std	%g2, [%sp + C_STACK + PT_G2]
-	std	%g4, [%sp + C_STACK + PT_G4]
-	std	%g6, [%sp + C_STACK + PT_G6]
-	rd	%y, %l4
+	/* Now call the c-code with the pt_regs frame ptr and the
+	 * memory error registers as arguments.  The ordering chosen
+	 * here is due to unlatching semantics.
+	 */
 	sethi	%hi(AC_SYNC_ERR), %o0
-	lda	[%o0] ASI_CONTROL, %o1
-	add	%o0, 0x4, %o0           ! go to sync vaddr
-	lda	[%o0] ASI_CONTROL, %o2
-	andcc	%o1, SUN4C_SYNC_NOMEM, %g0
-	bz,a	normal_data_page_fault
+	add	%o0, 0x4, %o0
+	lda	[%o0] ASI_CONTROL, %o2	! sync vaddr
+	sub	%o0, 0x4, %o0
+	lda	[%o0] ASI_CONTROL, %o1	! sync error
+	add	%o0, 0xc, %o0
+	lda	[%o0] ASI_CONTROL, %o4	! async vaddr
+	sub	%o0, 0x4, %o0
+	lda	[%o0] ASI_CONTROL, %o3	! async error
+	call	C_LABEL(sparc_lvl15_nmi)
+	 add	%sp, STACKFRAME_SZ, %o0
+
+	RESTORE_ALL
+
+	.align	4
+	.globl	sparc_fault
+sparc_fault:
+	SAVE_ALL
+	rd	%tbr, %o1
 	wr	%l0, PSR_ET, %psr
+	WRITE_PAUSE
 
-	add	%o0, 0x4, %o0           ! go to async error register
-	lda	[%o0] ASI_CONTROL, %o3
-	add	%o0, 0x4, %o0		! go to async vaddr
-	subcc	%o4, %o2, %g0
-	be,a	is_data_sync_fault	! not an async fault
-	wr	%l0, PSR_ET, %psr
+	call	C_LABEL(do_sparc_fault)
+	 add	%sp, STACKFRAME_SZ, %o0
+	RESTORE_ALL
+
+	/* SunOS uses syscall zero as the 'indirect syscall' it looks
+	 * like indir_syscall(scall_num, arg0, arg1, arg2...);  etc.
+	 * This is complete brain damage.
+	 */
+	.globl	C_LABEL(sunos_indir)
+C_LABEL(sunos_indir):
+	ld	[%sp + STACKFRAME_SZ + PT_I0], %g1
+	cmp	%g1, NR_SYSCALLS
+	bleu,a	1f
+	 sll	%g1, 0x2, %g1
 
-	/* crap, an asynchronous error has occurred */
-	sethi	%hi(C_LABEL(interrupt_enable)), %l5
-	ldub	[%l5 + %lo(C_LABEL(interrupt_enable))], %o0
-	andn	%o0, INTS_ENAB, %o0
-	stb	%o0, [%l5 + %lo(C_LABEL(interrupt_enable))]
-	wr	%l0, PSR_ET, %psr
-	call	C_LABEL(sparc_datamem_error)	! call high level c-code
-	or	%g0, FAULT_ASYNC, %o0
+	set	C_LABEL(sunos_nosys), %l6
+	b	2f
+	 nop
 
-	ld	[%sp + C_STACK + PT_G1], %g1
-	wr	%l0, 0x0, %psr
-	ldd	[%sp + C_STACK + PT_G2], %g2
-	ldd	[%sp + C_STACK + PT_G4], %g4
-	ldd	[%sp + C_STACK + PT_G6], %g6
-	ldub	[%l5 + %lo(C_LABEL(interrupt_enable))], %o1
-	or	%o1, INTS_ENAB, %o1
-	stb	%o1, [%l5 + %lo(C_LABEL(interrupt_enable))]
-	b	ret_trap_entry
-	wr	%l4, 0, %y
-
-is_data_sync_fault:
-	call	C_LABEL(sparc_datamem_error)	! call high level c-code
-	or	%g0, FAULT_SYNC, %o0
-
-	ld	[%sp + C_STACK + PT_G1], %g1
-	ldd	[%sp + C_STACK + PT_G2], %g2
-	ldd	[%sp + C_STACK + PT_G4], %g4
-	ldd	[%sp + C_STACK + PT_G6], %g6
-	wr	%l4, 0x0, %y
-	b	ret_trap_entry
-	wr	%l0, 0x0, %psr
+1:
+	set	C_LABEL(sunos_sys_table), %l7
+	ld	[%l7 + %g1], %l6
 
-normal_data_page_fault:
-	std	%l0, [%sp + C_STACK + PT_PSR]	! store %psr and pc
-	or	%g0, %l3, %o0
-	st	%l2, [%sp + C_STACK + PT_NPC]	! store npc
-	st	%l4, [%sp + C_STACK + PT_Y]	! store %y
-	or	%g0, %l1, %o3
-
-	/* The globals have already been placed on the stack */
-	std	%i0, [%sp + C_STACK + PT_I0]	! store ins
-	std	%i2, [%sp + C_STACK + PT_I2]
-	or	%g0, %l0, %o4
-	std	%i4, [%sp + C_STACK + PT_I4]
-	std	%i6, [%sp + C_STACK + PT_I6]
-	call	C_LABEL(sparc_data_access_fault)
-	add	%sp, C_STACK, %o5
-
-	ldd	[%sp + C_STACK + PT_PSR], %l0
-	ldd	[%sp + C_STACK + PT_NPC], %l2
-	wr	%l3, 0x0, %y
-	ld	[%sp + C_STACK + PT_G1], %g1
-	ldd	[%sp + C_STACK + PT_G2], %g2
-	ldd	[%sp + C_STACK + PT_G4], %g4
-	ldd	[%sp + C_STACK + PT_G6], %g6
-	ldd	[%sp + C_STACK + PT_I0], %i0
-	ldd	[%sp + C_STACK + PT_I2], %i2
-	ldd	[%sp + C_STACK + PT_I4], %i4
-	ldd	[%sp + C_STACK + PT_I6], %i6
+2:	
+	ld	[%sp + STACKFRAME_SZ + PT_I1], %o0
+	ld	[%sp + STACKFRAME_SZ + PT_I2], %o1
+	ld	[%sp + STACKFRAME_SZ + PT_I3], %o2
+	ld	[%sp + STACKFRAME_SZ + PT_I4], %o3
+	call	%l6
+	 ld	[%sp + STACKFRAME_SZ + PT_I5], %o4
+
+	b	scall_store_args		/* so stupid... */
+	 nop
+
+	.align	4
+	.globl	C_LABEL(sys_execve)
+C_LABEL(sys_execve):
+	call	C_LABEL(sparc_execve)
+	 add	%sp, STACKFRAME_SZ, %o0		! pt_regs *regs arg
+
+	b	scall_store_args
+	 nop
+
+	.align	4
+	.globl	C_LABEL(sys_pipe)
+C_LABEL(sys_pipe):
+	call	C_LABEL(sparc_pipe)
+	 add	%sp, STACKFRAME_SZ, %o0		! pt_regs *regs arg
 
-	b	ret_trap_entry
-	wr	%l0, 0x0, %psr
+	b	C_LABEL(ret_sys_call)
+	 nop
 
+	.align	4
+	.globl	C_LABEL(sys_sigreturn)
+C_LABEL(sys_sigreturn):
+	call	C_LABEL(do_sigreturn)
+	 add	%sp, STACKFRAME_SZ, %o0
+
+	/* We don't want to muck with user registers like a
+	 * normal syscall, just return.
+	 */
+	RESTORE_ALL
+
+	/* Now that we have a real sys_clone, sys_fork() is
+	 * implemented in terms of it.  Our _real_ implementation
+	 * of SunOS vfork() will use sys_clone() instead.
+	 */
+	.align	4
+	.globl	C_LABEL(sys_fork), C_LABEL(sys_vfork)
+C_LABEL(sys_vfork):
+C_LABEL(sys_fork):
+	/* Save the kernel state as of now. */
+	FLUSH_ALL_KERNEL_WINDOWS;
+	STORE_WINDOW(sp)
+	LOAD_CURRENT(g6)
+	rd	%psr, %g4
+	rd	%wim, %g5
+	std	%g4, [%g6 + THREAD_KPSR]
+	std	%sp, [%g6 + THREAD_KSP]
+
+	mov	SIGCHLD, %o0			! arg0:	clone flags
+	mov	%fp, %o1			! arg1:	usp
+	call	C_LABEL(do_fork)
+	 add	%sp, STACKFRAME_SZ, %o2		! arg2:	pt_regs ptr
 
-	.align 4
-	.globl C_LABEL(srmmu_text_fault)
-C_LABEL(srmmu_text_fault):
-	ENTER_TRAP(srmmu_text_fault)
-	st	%g1, [%sp + C_STACK + PT_G1]
-	std	%g2, [%sp + C_STACK + PT_G2]
-	std	%g4, [%sp + C_STACK + PT_G4]
-	std	%g6, [%sp + C_STACK + PT_G6]
-	rd	%y, %l4
-	set	0x300, %o0
-	lda	[%o0] ASI_M_MMUREGS, %o1	! fault status
-	set	0x400, %o0
-	lda	[%o0] ASI_M_MMUREGS, %o2	! fault address
-	wr	%l0, PSR_ET, %psr		! traps back on
-	WRITE_PAUSE
-	std	%l0, [%sp + C_STACK + PT_PSR]
-	or	%g0, %l3, %o0
-	st	%l2, [%sp + C_STACK + PT_NPC]
-	st	%l4, [%sp + C_STACK + PT_Y]
-	or	%g0, %l1, %o3
-	std	%i0, [%sp + C_STACK + PT_I0]
-	std	%i2, [%sp + C_STACK + PT_I2]
-	or	%g0, %l0, %o4
-	std	%i4, [%sp + C_STACK + PT_I4]
-	std	%i6, [%sp + C_STACK + PT_I6]
-	call	C_LABEL(srmmu_text_access_fault)
-	add	%sp, C_STACK, %o5
-
-	ldd	[%sp + C_STACK + PT_PSR], %l0
-	ldd	[%sp + C_STACK + PT_NPC], %l2
-	wr	%l3, 0x0, %y
-	ld	[%sp + C_STACK + PT_G1], %g1
-	ldd	[%sp + C_STACK + PT_G2], %g2
-	ldd	[%sp + C_STACK + PT_G4], %g4
-	ldd	[%sp + C_STACK + PT_G6], %g6
-	ldd	[%sp + C_STACK + PT_I0], %i0
-	ldd	[%sp + C_STACK + PT_I2], %i2
-	ldd	[%sp + C_STACK + PT_I4], %i4
-	ldd	[%sp + C_STACK + PT_I6], %i6
+	b	scall_store_args
+	 nop
+	
+	/* Whee, kernel threads! */
+	.globl	C_LABEL(sys_clone)
+C_LABEL(sys_clone):
+	/* Save the kernel state as of now. */
+	FLUSH_ALL_KERNEL_WINDOWS;
+	STORE_WINDOW(sp)
+	LOAD_CURRENT(g6)
+	rd	%psr, %g4
+	rd	%wim, %g5
+	std	%g4, [%g6 + THREAD_KPSR]
+	std	%sp, [%g6 + THREAD_KSP]
 
-	b	ret_trap_entry
-	wr	%l0, 0x0, %psr
+	ldd	[%sp + STACKFRAME_SZ + PT_I0], %o0	! arg0,1: flags,usp
+	cmp	%o1, 0x0				! Is new_usp NULL?
+	be,a	1f
+	 mov	%fp, %o1				! yes, use current usp
+1:
+	call	C_LABEL(do_fork)
+	 add	%sp, STACKFRAME_SZ, %o2			! arg2:	pt_regs ptr
 
-	.align 4
-	.globl C_LABEL(srmmu_data_fault)
-C_LABEL(srmmu_data_fault):
-	ENTER_TRAP(srmmu_data_fault)
-	st	%g1, [%sp + C_STACK + PT_G1]
-	std	%g2, [%sp + C_STACK + PT_G2]
-	std	%g4, [%sp + C_STACK + PT_G4]
-	std	%g6, [%sp + C_STACK + PT_G6]
-	rd	%y, %l4
-
-	set	AC_M_SFSR, %o0
-	lda	[%o0] ASI_M_MMUREGS, %o1	! fault status
-	set	AC_M_SFAR, %o0
-	lda	[%o0] ASI_M_MMUREGS, %o2	! fault address
-	set	AC_M_AFSR, %o0
-	lda	[%o0] ASI_M_MMUREGS, %o3
-	set	AC_M_AFAR, %o0
-	lda	[%o0] ASI_M_MMUREGS, %o4
-	wr	%l0, PSR_ET, %psr		! traps back on
-	WRITE_PAUSE
-	std	%l0, [%sp + C_STACK + PT_PSR]
-	or	%g0, %l3, %o0
-	st	%l2, [%sp + C_STACK + PT_NPC]
-	st	%l4, [%sp + C_STACK + PT_Y]
-	std	%i0, [%sp + C_STACK + PT_I0]
-	std	%i2, [%sp + C_STACK + PT_I2]
-	std	%i4, [%sp + C_STACK + PT_I4]
-	std	%i6, [%sp + C_STACK + PT_I6]
-	call	C_LABEL(srmmu_data_access_fault)
-	add	%sp, C_STACK, %o5
-
-	ldd	[%sp + C_STACK + PT_PSR], %l0
-	ldd	[%sp + C_STACK + PT_NPC], %l2
-	wr	%l3, 0x0, %y
-	ld	[%sp + C_STACK + PT_G1], %g1
-	ldd	[%sp + C_STACK + PT_G2], %g2
-	ldd	[%sp + C_STACK + PT_G4], %g4
-	ldd	[%sp + C_STACK + PT_G6], %g6
-	ldd	[%sp + C_STACK + PT_I0], %i0
-	ldd	[%sp + C_STACK + PT_I2], %i2
-	ldd	[%sp + C_STACK + PT_I4], %i4
-	ldd	[%sp + C_STACK + PT_I6], %i6
+	b	scall_store_args
+	 nop
 
-	b	ret_trap_entry
-	wr	%l0, 0x0, %psr
+#if 0 /* XXX Much later... XXX */
+	/* Whee, vfork... */
+	.globl	C_LABEL(sys_vfork)
+C_LABEL(sys_vfork):
+	/* Save the kernel state as of now. */
+	FLUSH_ALL_KERNEL_WINDOWS;
+	STORE_WINDOW(sp)
+	LOAD_CURRENT(g6)
+	rd	%psr, %g4
+	rd	%wim, %g5
+	std	%g4, [%g6 + THREAD_KPSR]
+	std	%sp, [%g6 + THREAD_KSP]
 
-/* Normal Linux system calls enter here... */
-/* Trying to make this as generic and simple as possible. */
+	set	(0x2100 | SIGCHLD), %o0			! CLONE_VFORK,CLONE_VM,SIGCHLD
+	mov	%fp, %o1				! use current usp
+1:
+	call	C_LABEL(do_fork)
+	 add	%sp, STACKFRAME_SZ, %o2			! arg2:	pt_regs ptr
 
-	.align 4
-	.globl linux_sparc_syscall
+	b	scall_store_args
+	 nop
+#endif
+
+	/* All system calls enter here... */
+	.align	4
+	.globl	linux_sparc_syscall
 linux_sparc_syscall:
 	/* Don't dork with %l7, it holds the pointer to the
-	 * system call vector table.  ENTER_TRAP does not
+	 * system call vector table.  SAVE_ALL does not
 	 * modify its value.
 	 */
-	ENTER_TRAP(linux_sparc_syscall)
+	rd	%wim, %l3
+	SAVE_ALL
 
-	/* setup pt_regs stack frame, leave ints off...
-	 * First save all but the current window onto the stack.
-	 * This means nwindows-2 saves and nwindows-2 restores.
-	 */
-	andn	%l0, PSR_PIL, %l5
-	wr	%l5, 0xf00, %psr
-	wr	%l5, 0xf20, %psr	! no ints, traps on
+	wr	%l0, PSR_ET, %psr	/* Turn on traps + interrupts */
 	WRITE_PAUSE
-	
-	.globl nop7
-	/* Flush windows */
-	save	%sp, -C_STACK, %sp
-	save	%sp, -C_STACK, %sp
-	save	%sp, -C_STACK, %sp
-	save	%sp, -C_STACK, %sp
-	save	%sp, -C_STACK, %sp
-nop7:	save	%sp, -C_STACK, %sp
-	restore
-	restore
-	restore
-	restore
-	restore
-	restore
-
-	rd	%psr, %l6
-	and	%l6, PSR_CWP, %l6		! only care about CWP
-	andn	%l0, PSR_CWP, %l0
-	or	%l0, %l6, %l0			! %l0 is now the new %psr
-	
-	std	%l0, [%sp + C_STACK + PT_PSR]	! save it away
-	rd	%y, %l3
-	std	%l2, [%sp + C_STACK + PT_NPC]
-
-	/* Put %wim in %g0 slot, a hack.  This way we ensure that %wim
-	 * sits right behind the current window in %psr, which is what
-	 * we want.
-	 */
-	rd	%wim, %l4
-	st	%l4, [%sp + C_STACK + PT_G0]
-	st	%g1, [%sp + C_STACK + PT_G1]
-	std	%g2, [%sp + C_STACK + PT_G2]
-	std	%g4, [%sp + C_STACK + PT_G4]
-	std	%g6, [%sp + C_STACK + PT_G6]
-	std	%i0, [%sp + C_STACK + PT_I0]
-	std	%i2, [%sp + C_STACK + PT_I2]
-	std	%i4, [%sp + C_STACK + PT_I4]
-	std	%i6, [%sp + C_STACK + PT_I6]
-
-	wr	%l0, PSR_ET, %psr /* Turn on traps + interrupts */
-	WRITE_PAUSE
-
-	cmp	%i0, NR_SYSCALLS
-	bgu,a	C_LABEL(ret_sys_call)
-	or	%g0, -1, %i0
-
-	cmp	%i0, 0x2		! fork? Same number for all OSs
-	bne	not_fork
-	nop
-	call	C_LABEL(sys_fork)	! yep, load pt_regs into first arg
-	add	%sp, C_STACK, %o0
-	b	C_LABEL(ret_sys_call)
-	nop
-not_fork:
-	/* Remember, trap table entry loaded syscall table ptr in %l7 */
-	sll	%i0, 0x2, %o0
-	add	%l7, %o0, %l7
-	ld	[%l7], %o5		! load up ptr to syscall handler
-
-	mov	%i1, %o0		! load up arguments
-	mov	%i2, %o1
-	mov	%i3, %o2
-	mov	%i4, %o3
-	jmpl	%o5, %o7		! Make syscall
-	mov	%i5, %o4
-
-	.globl C_LABEL(ret_sys_call)  /* exported for copy_process() */
-C_LABEL(ret_sys_call):	 /* Child of a fork returns here */
-	/* dump the pt_regs back into their rightful places */
-	ldd	[%sp + C_STACK + PT_PSR], %l0
-	ldd	[%sp + C_STACK + PT_NPC], %l2
-	wr	%l3, 0x0, %y
-
-	ld	[%sp + C_STACK + PT_G1], %g1
-	ldd	[%sp + C_STACK + PT_G2], %g2
-	ldd	[%sp + C_STACK + PT_G4], %g4
-	ldd	[%sp + C_STACK + PT_G6], %g6
-	ldd	[%sp + C_STACK + PT_I0], %i0
-	ldd	[%sp + C_STACK + PT_I2], %i2
-	ldd	[%sp + C_STACK + PT_I4], %i4
-	ldd	[%sp + C_STACK + PT_I6], %i6
 
-	/* %i6 is our frame pointer, the restore done by the rett
-	 * instruction will automatically put us back on the users
-	 * stack.
-	 * Advance the pc and npc past the trap instruction, the copy_process()
-	 * code for fork() depends on this being done right before trap return.
-	 */
-	or	%l2, 0x0, %l5
+#if 0 /* Trace all system calls... */
+	add	%sp, STACKFRAME_SZ, %o0
+	call	C_LABEL(syscall_trace_entry)
+	 nop
+#endif
 
-	or	%l5, 0x0, %l1    /* pc = npc */
-	add	%l5, 0x4, %l2    /* npc= npc+4 */
+	/* SAVE_ALL may have blown away %g1, reload it. */
+	ld	[%sp + STACKFRAME_SZ + PT_G1], %g1
+	cmp	%g1, NR_SYSCALLS
+	bleu,a	1f
+	 sll	%g1, 0x2, %g1
 
-	wr	%l0, 0x0, %psr
-	WRITE_PAUSE	
-
-	/* Fall through to ret_trap_entry */
-
-/* Return from trap code.  I realized that I was duplicating a lot
- * of logic in the various trap handlers. Traps are off upon entry.
- */
-
-ret_trap_entry:
-	and	%l0, 0x1f, %l5
-	sethi	%hi(lnx_winmask), %l6
-	or	%l6, %lo(lnx_winmask), %l6
-	ldub	[%l6 + %l5], %l5
-	andcc	%l0, PSR_PS, %g0
-	bnz	ret_trap_kernel
-	rd	%wim, %l4
-
-	sethi	%hi(C_LABEL(current)), %l6
-	ld	[%l6 + %lo(C_LABEL(current))], %l6
-	ld	[%l6 + THREAD_W_SAVED], %l7
-	subcc	%g0, %l7, %g0
-	bz,a	ret_trap_user
-	nop
-
-	wr	%g0, 0, %wim
-	or	%g0, %g6, %l3
-	or	%g0, %l6, %g6
-	st	%g0, [%g6 + THREAD_W_SAVED]
-	restore
-	restore %g0, 1, %l1
-	rd	%psr, %l0
-	sll	%l1, %l0, %l1
-	wr	%l1, 0x0, %wim
-	and	%l0, 0x1f, %l0
-	st	%l0, [%g6 + THREAD_WIM]
-	nop
-	save	%g0, %g0, %g0
-	add	%g6, THREAD_REG_WINDOW, %g6
-	ldd	[%g6], %l0
-	ldd	[%g6 + 0x8], %l2
-	ldd	[%g6 + 0x10], %l4
-	ldd	[%g6 + 0x18], %l6
-	ldd	[%g6 + 0x20], %i0
-	ldd	[%g6 + 0x28], %i2
-	ldd	[%g6 + 0x30], %i4
-	ldd	[%g6 + 0x38], %i6
-
-	save	%g0, %g0, %g0
-	wr	%l0, 0x0, %psr
-	or	%g0, %l3, %g6
-	jmp	%l1
-	rett	%l2
-
-ret_trap_kernel:
-	andcc	%l4, %l5, %g0
-	bnz	1f
-	wr	%l0, 0x0, %psr       ! reset condition codes
-	nop
-	jmp	%l1
-	rett	%l2
+	set	C_LABEL(sys_ni_syscall), %l6
+	b	2f
+	 nop
 
 1:
-	wr	%g0, 0x0, %wim
-	WRITE_PAUSE
-	restore
-	restore %g0, 0x1, %l1
-	rd	%psr, %l0
-	and	%l0, 0x1f, %l0
-	sll	%l1, %l0, %l1
-	wr	%l1, 0x0, %wim
-	sethi	%hi(C_LABEL(current)), %l1
-	ld	[%l1 + %lo(C_LABEL(current))], %l1
-	st	%l0, [%l1 + THREAD_WIM]
-	save	%g0, %g0, %g0
-	ldd	[%sp], %l0
-	ldd	[%sp + 0x8], %l2
-	ldd	[%sp + 0x10], %l4
-	ldd	[%sp + 0x18], %l6
-	ldd	[%sp + 0x20], %i0
-	ldd	[%sp + 0x28], %i2
-	ldd	[%sp + 0x30], %i4
-	ldd	[%sp + 0x38], %i6
+	/* Syscall table ptr is in %l7. */
+	ld	[%l7 + %g1], %l6	! load up ptr to syscall handler
 
-	save	%g0, %g0, %g0
-	jmp	%l1
-	rett	%l2
+	/* Pt_regs is your friend... Make the syscall... */
+2:
+	ldd	[%sp + STACKFRAME_SZ + PT_I0], %o0
+	ldd	[%sp + STACKFRAME_SZ + PT_I2], %o2
+	ldd	[%sp + STACKFRAME_SZ + PT_I4], %o4
+	call	%l6
+	 nop
+
+scall_store_args:
+	st	%o0, [%sp + STACKFRAME_SZ + PT_I0]
+
+	.globl	C_LABEL(ret_sys_call)
+C_LABEL(ret_sys_call):
+	ld	[%sp + STACKFRAME_SZ + PT_I0], %o0
+	set	PSR_C, %l6
+	cmp	%o0, -ELIBSCN
+	bgeu	1f
+	 ld	[%sp + STACKFRAME_SZ + PT_PSR], %l5
 
-ret_trap_user:
-	andcc	%l4, %l5, %g0
-	bnz	1f
-	wr	%l0, 0x0, %psr
-	nop
-	jmp	%l1
-	rett	%l2
+	/* System call success, clear Carry condition code. */		
+	andn	%l5, %l6, %l5
+	b	2f
+	 st	%l5, [%sp + STACKFRAME_SZ + PT_PSR]	
 
 1:
-	wr	%g0, 0x0, %wim
-	wr	%l0, 0x0, %psr
-	WRITE_PAUSE
-	restore
-	restore	%g0, 0x1, %l1
-	rd	%psr, %l0
-	sll	%l1, %l0, %l1
-	wr	%l1, 0x0, %wim
-	sethi	%hi(C_LABEL(current)), %l1
-	ld	[%l1 + %lo(C_LABEL(current))], %l1
-	and	%l0, 0x1f, %l0
-	st	%l0, [%l1 + THREAD_WIM]
-	save	%g0, %g0, %g0
-	ldd	[%sp], %l0
-	ldd	[%sp + 0x8], %l2
-	ldd	[%sp + 0x10], %l4
-	ldd	[%sp + 0x18], %l6
-	ldd	[%sp + 0x20], %i0
-	ldd	[%sp + 0x28], %i2
-	ldd	[%sp + 0x30], %i4
-	ldd	[%sp + 0x38], %i6
-	save	%g0, %g0, %g0
-	jmp	%l1
-	rett	%l2
-
-/* Context switch code.  I don't feel like playing around with
- * inline gcc-assembly to do this right, so here it is.  The new
- * process's task_struct ptr is passed in %o0.
- *
- * This is still work in progress.
- * ONLY MAKE PROM CALLS FOR DIAGNOSTICS WHEN TRAPS ARE ON!!!!!
- *
- * First successful task switch 05/13/95 21:52:37
- *
- */
-	.align 4
-	.globl C_LABEL(sparc_switch_to)
-C_LABEL(sparc_switch_to):
-	or	%g0, %o0, %l5
-	sethi	%hi(C_LABEL(current)), %l6
-	ld	[%l6 + %lo(C_LABEL(current))], %l6
-	rd	%psr, %l0
-
-	or	%g0, %l0, %l4
-	andn	%l0, PSR_PIL, %l0   /* turn off IRQ level bits leave PSR_ET on */
-
-	wr	%l0, 0xf00, %psr    /* NO interrupts */
-	WRITE_PAUSE
-
-	/* Save state of old process */
-	.globl rnop7
-	save	%sp, -C_STACK, %sp
-	save	%sp, -C_STACK, %sp
-	save	%sp, -C_STACK, %sp
-	save	%sp, -C_STACK, %sp
-	save	%sp, -C_STACK, %sp
-rnop7:	save	%sp, -C_STACK, %sp
-	restore
-	restore
-	restore
-	restore
-	restore
-	restore
-
-	rd	%psr, %l3
-	and	%l3, PSR_CWP, %l3		! only care about CWP bits now
-	andn	%l0, PSR_CWP, %l0		! integrate with old %psr
-	or	%l3, %l0, %l0
-	
-	st	%l0, [%sp + C_STACK + PT_PSR]	! save new %psr
-	/* ??? We backtrack the PC two instructions due to retl's semantics ??? */
-	/*sub	%o7, 0x8, %o7 */
-	st	%o7, [%sp + C_STACK + PT_PC]	! save return PC
-	add	%o7, 0x4, %l3
-	st	%l3, [%sp + C_STACK + PT_NPC]   ! and NPC
-
-	rd	%y, %l3
-	st	%l3, [%sp + C_STACK + PT_Y]	! save %y
-
-	/* Save the %wim into %g0 slot, ensures that it sits behind CWP */
-	rd	%wim, %l3
-	st	%l3, [%sp + C_STACK + PT_G0]	! save new %wim
-	st	%g1, [%sp + C_STACK + PT_G1]
-	std	%g2, [%sp + C_STACK + PT_G2]
-	std	%g4, [%sp + C_STACK + PT_G4]
-	std	%g6, [%sp + C_STACK + PT_G6]
-	std	%i0, [%sp + C_STACK + PT_I0]
-	std	%i2, [%sp + C_STACK + PT_I2]
-	std	%i4, [%sp + C_STACK + PT_I4]
-	std	%i6, [%sp + C_STACK + PT_I6]
-
-	wr	%l0, (0xf20), %psr		! no traps, no intrs
-	WRITE_PAUSE
-
-	/* TRAPS ARE OFF, NO PROM CALLS WHATSOEVER FOR DEBUGGING!!! */
-	/* SO what we do is we put an imperical constant in %g2 and
-	 * a 'counter' in %g1 which we increment after every instruction
-	 * so we can figure out where the thing prom panics.  Then at the
-	 * prom prompt we print out the saved registers.  To drop into the
-	 * prom and look at the registers just execute 7 saves since that
-	 * will induce a window trap before the last one and traps are off,
-	 * thus a watchdog reset will occur.
-	 */
-
-	/* Grrr, this is hairy... be careful, again NO PROM CALLS YET! */
-	/* Load up the new 'current' */
-	sethi	%hi(C_LABEL(current)), %g1
-	st	%l5, [%g1 + %lo(C_LABEL(current))]
-	
-	/* Load up new processes stack, we always switch onto the kernel stack */
-	/* Be CAREFUL, use globals for temporaries, because after we change the
-	 * %psr the window could change and you will most likely be accessing
-	 * different outs, ins, and locals than you origionally were.
-	 */
-	or	%g0, %l5, %g6
-	ld	[%l5 + THREAD_KSP], %g3
-
-	/* New procs %psr */
-	ld	[%g3 + C_STACK + PT_PSR], %g4
-	wr	%g4, 0xf00, %psr         /* No ints, no traps */
-	WRITE_PAUSE
-
-	/* We could be in a different window NOW. Assume nothing about the
-	 * current set of in, out and local registers.
+	/* System call failure, set Carry condition code.
+	 * Also, get abs(errno) to return to the process.
 	 */
+	sub	%g0, %o0, %o0
+	st	%o0, [%sp + STACKFRAME_SZ + PT_I0]
+	or	%l5, %l6, %l5
+	st	%l5, [%sp + STACKFRAME_SZ + PT_PSR]
 
-	/* New procs %wim */
-	ld	[%g3 + C_STACK + PT_G0], %l4 /* %wim is here */
-	st	%l4, [%g6 + THREAD_WIM]      /* Update tss */
-	wr	%l4, 0x0, %wim               /* Use it */
-	WRITE_PAUSE
-
-	/* Finally, load the stack */
-	or	%g0, %g3, %sp
-
-	/* We are now sane, we have a good stack and our state is reflected
-	 * properly in 'current'.  Let it rip.
-	 */
-	/* Remember, you can't increase PIL and turn on traps at the
-	 * same time.
+	/* %i6 is our frame pointer, the restore done by the rett
+	 * instruction will automatically put us back on the users
+	 * stack.  Advance the pc and npc past the trap instruction.
 	 */
-	wr	%g4, 0xf00, %psr  /* Traps on, no interrupts. */
-	wr	%g4, 0xf20, %psr
-	WRITE_PAUSE
-	
-	sethi	%hi(C_LABEL(current)), %o0
-	ld	[%o0 + %lo(C_LABEL(current))], %o0
-	ld	[%o0 + THREAD_PC], %o7 /* Setup return address */
-
-	/* cross fingers */
-	retl
-	nop
-
-/* The following two things point to window management tables. The first
- * one is used to quickly look up how many user windows there are from
- * trap-land. The second is used in a trap handler to determine if a rett
- * instruction will land us smack inside the invalid window that possibly
- * the trap was called to fix-up.
- */
-
-/* For now these are static tables geared for a 7 window sparc.
- * But in head.S after we calculate this table based upon the
- * nwindows value.  This table is big enough for a 16 window sparc.
- */
-
+2:
+	ld	[%sp + STACKFRAME_SZ + PT_NPC], %l1	/* pc  = npc   */
+	add	%l1, 0x4, %l2				/* npc = npc+4 */
+	st	%l1, [%sp + STACKFRAME_SZ + PT_PC]
+	st	%l2, [%sp + STACKFRAME_SZ + PT_NPC]
+
+#if 0 /* Trace all system calls... */
+	add	%sp, STACKFRAME_SZ, %o0
+	call	C_LABEL(syscall_trace_exit)
+	 nop
+#endif
+
+	RESTORE_ALL
+
+	.globl	C_LABEL(flush_user_windows)
+C_LABEL(flush_user_windows):
+	LOAD_CURRENT(g2)
+	ld	[%g2 + THREAD_UMASK], %g1
+	orcc	%g0, %g1, %g0
+	be	3f
+	 clr	%g3
+1:
+	_SV
+	LOAD_CURRENT(g2)
+	ld	[%g2 + THREAD_UMASK], %g1
+	orcc	%g0, %g1, %g0
+	bne	1b
+	 add	%g3, 1, %g3
+2:
+	subcc	%g3, 1, %g3
+	bne	2b
+	 _RS
+3:
+	jmp	%o7 + 0x8
+	 nop
 
-		.data
-		.align 4
-		.globl lnx_winmask
-lnx_winmask:
-		.byte	2, 4, 8, 16, 32, 64, 1, 0
-		.byte	0, 0, 0, 0, 0, 0, 0, 0
-	
-		.align 4
-		.globl C_LABEL(sys_call_table)
-C_LABEL(sys_call_table):
-	.long C_LABEL(sys_setup)		/* 0 */
-	.long C_LABEL(sys_exit)
-	.long C_LABEL(sys_fork)
-	.long C_LABEL(sys_read)
-	.long C_LABEL(sys_write)
-	.long C_LABEL(sys_open)			/* 5 */
-	.long C_LABEL(sys_close)
-	.long C_LABEL(sys_waitpid)
-	.long C_LABEL(sys_creat)
-	.long C_LABEL(sys_link)
-	.long C_LABEL(sys_unlink)		/* 10 */
-	.long C_LABEL(sys_execve)
-	.long C_LABEL(sys_chdir)
-	.long C_LABEL(sys_time)
-	.long C_LABEL(sys_mknod)
-	.long C_LABEL(sys_chmod)		/* 15 */
-	.long C_LABEL(sys_chown)
-	.long C_LABEL(sys_break)
-	.long C_LABEL(sys_stat)
-	.long C_LABEL(sys_lseek)
-	.long C_LABEL(sys_getpid)		/* 20 */
-	.long C_LABEL(sys_mount)
-	.long C_LABEL(sys_umount)
-	.long C_LABEL(sys_setuid)
-	.long C_LABEL(sys_getuid)
-	.long C_LABEL(sys_stime)		/* 25 */
-	.long C_LABEL(sys_ni_syscall)		/* this will be sys_ptrace() */
-	.long C_LABEL(sys_alarm)
-	.long C_LABEL(sys_fstat)
-	.long C_LABEL(sys_pause)
-	.long C_LABEL(sys_utime)		/* 30 */
-	.long C_LABEL(sys_stty)
-	.long C_LABEL(sys_gtty)
-	.long C_LABEL(sys_access)
-	.long C_LABEL(sys_nice)
-	.long C_LABEL(sys_ftime)		/* 35 */
-	.long C_LABEL(sys_sync)
-	.long C_LABEL(sys_kill)
-	.long C_LABEL(sys_rename)
-	.long C_LABEL(sys_mkdir)
-	.long C_LABEL(sys_rmdir)		/* 40 */
-	.long C_LABEL(sys_dup)
-	.long C_LABEL(sys_pipe)
-	.long C_LABEL(sys_times)
-	.long C_LABEL(sys_prof)
-	.long C_LABEL(sys_brk)			/* 45 */
-	.long C_LABEL(sys_setgid)
-	.long C_LABEL(sys_getgid)
-	.long C_LABEL(sys_signal)
-	.long C_LABEL(sys_geteuid)
-	.long C_LABEL(sys_getegid)		/* 50 */
-	.long C_LABEL(sys_acct)
-	.long C_LABEL(sys_phys)
-	.long C_LABEL(sys_lock)
-	.long C_LABEL(sys_ioctl)
-	.long C_LABEL(sys_fcntl)		/* 55 */
-	.long C_LABEL(sys_mpx)
-	.long C_LABEL(sys_setpgid)
-	.long C_LABEL(sys_ulimit)
-	.long C_LABEL(sys_olduname)
-	.long C_LABEL(sys_umask)	/* 60 */
-	.long C_LABEL(sys_chroot)
-	.long C_LABEL(sys_ustat)
-	.long C_LABEL(sys_dup2)
-	.long C_LABEL(sys_getppid)
-	.long C_LABEL(sys_getpgrp)		/* 65 */
-	.long C_LABEL(sys_setsid)
-	.long C_LABEL(sys_sigaction)
-	.long C_LABEL(sys_sgetmask)
-	.long C_LABEL(sys_ssetmask)
-	.long C_LABEL(sys_setreuid)		/* 70 */
-	.long C_LABEL(sys_setregid)
-	.long C_LABEL(sys_sigsuspend)
-	.long C_LABEL(sys_sigpending)
-	.long C_LABEL(sys_sethostname)
-	.long C_LABEL(sys_setrlimit)		/* 75 */
-	.long C_LABEL(sys_getrlimit)
-	.long C_LABEL(sys_getrusage)
-	.long C_LABEL(sys_gettimeofday)
-	.long C_LABEL(sys_settimeofday)
-	.long C_LABEL(sys_getgroups)		/* 80 */
-	.long C_LABEL(sys_setgroups)
-	.long C_LABEL(sys_select)
-	.long C_LABEL(sys_symlink)
-	.long C_LABEL(sys_lstat)
-	.long C_LABEL(sys_readlink)		/* 85 */
-	.long C_LABEL(sys_uselib)
-	.long C_LABEL(sys_swapon)
-	.long C_LABEL(sys_reboot)
-	.long C_LABEL(sys_readdir)
-	.long C_LABEL(sys_mmap)			/* 90 */
-	.long C_LABEL(sys_munmap)
-	.long C_LABEL(sys_truncate)
-	.long C_LABEL(sys_ftruncate)
-	.long C_LABEL(sys_fchmod)
-	.long C_LABEL(sys_fchown)		/* 95 */
-	.long C_LABEL(sys_getpriority)
-	.long C_LABEL(sys_setpriority)
-	.long C_LABEL(sys_profil)
-	.long C_LABEL(sys_statfs)
-	.long C_LABEL(sys_fstatfs)		/* 100 */
-	.long C_LABEL(sys_ni_syscall)
-	.long C_LABEL(sys_socketcall)
-	.long C_LABEL(sys_syslog)
-	.long C_LABEL(sys_setitimer)
-	.long C_LABEL(sys_getitimer)		/* 105 */
-	.long C_LABEL(sys_newstat)
-	.long C_LABEL(sys_newlstat)
-	.long C_LABEL(sys_newfstat)
-	.long C_LABEL(sys_uname)
-	.long C_LABEL(sys_ni_syscall)		/* 110 */
-	.long C_LABEL(sys_vhangup)
-	.long C_LABEL(sys_idle)
-	.long C_LABEL(sys_ni_syscall)           /* was vm86, meaningless on Sparc */
-	.long C_LABEL(sys_wait4)
-	.long C_LABEL(sys_swapoff)		/* 115 */
-	.long C_LABEL(sys_sysinfo)
-	.long C_LABEL(sys_ipc)
-	.long C_LABEL(sys_fsync)
-	.long C_LABEL(sys_sigreturn)
-	.long C_LABEL(sys_ni_syscall)		/* 120 */
-	.long C_LABEL(sys_setdomainname)
-	.long C_LABEL(sys_newuname)
-	.long C_LABEL(sys_ni_syscall)
-	.long C_LABEL(sys_adjtimex)
-	.long C_LABEL(sys_mprotect)		/* 125 */
-	.long C_LABEL(sys_sigprocmask)
-	.long C_LABEL(sys_create_module)
-	.long C_LABEL(sys_init_module)
-	.long C_LABEL(sys_delete_module)
-	.long C_LABEL(sys_get_kernel_syms)	/* 130 */
-	.long C_LABEL(sys_ni_syscall)
-	.long C_LABEL(sys_getpgid)
-	.long C_LABEL(sys_fchdir)
-	.long C_LABEL(sys_bdflush)
-	.long C_LABEL(sys_sysfs)		/* 135 */
-	.long C_LABEL(sys_personality)
-	.long C_LABEL(sys_ni_syscall)		/* for afs_syscall */
-	.long C_LABEL(sys_setfsuid)
-	.long C_LABEL(sys_setfsgid)
-	.long C_LABEL(sys_llseek)		/* 140 */
-	.long C_LABEL(sys_ni_syscall)
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-
-	/* 150 */
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-
-	/* 160 */
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-
-	/* 170 */
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-
-	/* 180 */
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-
-	/* 190 */
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-
-	/* 200 */
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-
-	/* 210 */
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-
-	/* 220 */
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-
-	/* 230 */
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-
-	/* 240 */
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-
-	/* 250 */
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-	.long C_LABEL(sys_ni_syscall), C_LABEL(sys_ni_syscall)
-	.long C_LABEL(sys_ni_syscall)		/* 255 */
-	.align 4
+/* End of entry.S */
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/kernel/errtbls.c linux/arch/sparc/kernel/errtbls.c
--- v1.3.43/linux/arch/sparc/kernel/errtbls.c	Thu Jan  1 02:00:00 1970
+++ linux/arch/sparc/kernel/errtbls.c	Sat Nov 25 02:57:57 1995
@@ -0,0 +1,276 @@
+/* $Id: errtbls.c,v 1.2 1995/11/25 00:57:55 davem Exp $
+ * errtbls.c: Error number conversion tables between various syscall
+ *            OS semantics.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ *
+ * Based upon preliminary work which is:
+ *
+ * Copyright (C) 1995 Adrian M. Rodriguez (adrian@remus.rutgers.edu)
+ */
+
+#include <asm/bsderrno.h>        /* NetBSD (bsd4.4) errnos */
+#include <asm/solerrno.h>        /* Solaris errnos */
+
+/* Here are tables which convert between Linux/SunOS error number
+ * values to the equivalent in other OSs.  Note that since the Linux
+ * ones have been set up to match exactly those of SunOS, no
+ * translation table is needed for that OS.
+ */
+
+int solaris_errno[] = {
+	0,
+	SOL_EPERM,
+	SOL_ENOENT,
+	SOL_ESRCH,
+	SOL_EINTR,
+	SOL_EIO,
+	SOL_ENXIO,
+	SOL_E2BIG,
+	SOL_ENOEXEC,
+	SOL_EBADF,
+	SOL_ECHILD,
+	SOL_EAGAIN,
+	SOL_ENOMEM,
+	SOL_EACCES,
+	SOL_EFAULT,
+	SOL_NOTBLK,
+	SOL_EBUSY,
+	SOL_EEXIST,
+	SOL_EXDEV,
+	SOL_ENODEV,
+	SOL_ENOTDIR,
+	SOL_EISDIR,
+	SOL_EINVAL,
+	SOL_ENFILE,
+	SOL_EMFILE,
+	SOL_ENOTTY,
+	SOL_ETXTBSY,
+	SOL_EFBIG,
+	SOL_ENOSPC,
+	SOL_ESPIPE,
+	SOL_EROFS,
+	SOL_EMLINK,
+	SOL_EPIPE,
+	SOL_EDOM,
+	SOL_ERANGE,
+	SOL_EWOULDBLOCK,
+	SOL_EINPROGRESS,
+	SOL_EALREADY,
+	SOL_ENOTSOCK,
+	SOL_EDESTADDRREQ,
+	SOL_EMSGSIZE,
+	SOL_EPROTOTYPE,
+	SOL_ENOPROTOOPT,
+	SOL_EPROTONOSUPPORT,
+	SOL_ESOCKTNOSUPPORT,
+	SOL_EOPNOTSUPP,
+	SOL_EPFNOSUPPORT,
+	SOL_EAFNOSUPPORT,
+	SOL_EADDRINUSE,
+	SOL_EADDRNOTAVAIL,
+	SOL_ENETDOWN,
+	SOL_ENETUNREACH,
+	SOL_ENETRESET,
+	SOL_ECONNABORTED,
+	SOL_ECONNRESET,
+	SOL_ENOBUFS,
+	SOL_EISCONN,
+	SOL_ENOTONN,
+	SOL_ESHUTDOWN,
+	SOL_ETOOMANYREFS,
+	SOL_ETIMEDOUT,
+	SOL_ECONNREFUSED,
+	SOL_ELOOP,
+	SOL_ENAMETOOLONG,
+	SOL_EHOSTDOWN,
+	SOL_EHOSTUNREACH,
+	SOL_ENOTEMPTY,
+	SOL_EPROCLIM,
+	SOL_EUSERS,
+	SOL_EDQUOT,
+	SOL_ESTALE,
+	SOL_EREMOTE,
+	SOL_ENOSTR,
+	SOL_ETIME,
+	SOL_ENOSR,
+	SOL_ENOMSG,
+	SOL_EBADMSG,
+	SOL_IDRM,
+	SOL_EDEADLK,
+	SOL_ENOLCK,
+	SOL_ENONET,
+	SOL_ERREMOTE,
+	SOL_ENOLINK,
+	SOL_EADV,
+	SOL_ESRMNT,
+	SOL_ECOMM,
+	SOL_EPROTO,
+	SOL_EMULTIHOP,
+	SOL_EINVAL,    /* EDOTDOT XXX??? */
+	SOL_REMCHG,
+	SOL_NOSYS,
+	SOL_STRPIPE,
+	SOL_EOVERFLOW,
+	SOL_EBADFD,
+	SOL_ECHRNG,
+	SOL_EL2NSYNC,
+	SOL_EL3HLT,
+	SOL_EL3RST,
+	SOL_NRNG,
+	SOL_EUNATCH,
+	SOL_ENOCSI,
+	SOL_EL2HLT,
+	SOL_EBADE,
+	SOL_EBADR,
+	SOL_EXFULL,
+	SOL_ENOANO,
+	SOL_EBADRQC,
+	SOL_EBADSLT,
+	SOL_EDEADLOCK,
+	SOL_EBFONT,
+	SOL_ELIBEXEC,
+	SOL_ENODATA,
+	SOL_ELIBBAD,
+	SOL_ENOPKG,
+	SOL_ELIBACC,
+	SOL_ENOTUNIQ,
+	SOL_ERESTART,
+	SOL_EUCLEAN,
+	SOL_ENOTNAM,
+	SOL_ENAVAIL,
+	SOL_EISNAM,
+	SOL_EREMOTEIO,
+	SOL_EILSEQ,
+	SOL_ELIBMAX,
+	SOL_ELIBSCN,
+};
+
+int netbsd_errno[] = {
+	0,
+	BSD_EPERM,
+	BSD_ENOENT,
+	BSD_ESRCH,
+	BSD_EINTR,
+	BSD_EIO,
+	BSD_ENXIO,
+	BSD_E2BIG,
+	BSD_ENOEXEC,
+	BSD_EBADF,
+	BSD_ECHILD,
+	BSD_EAGAIN,
+	BSD_ENOMEM,
+	BSD_EACCES,
+	BSD_EFAULT,
+	BSD_NOTBLK,
+	BSD_EBUSY,
+	BSD_EEXIST,
+	BSD_EXDEV,
+	BSD_ENODEV,
+	BSD_ENOTDIR,
+	BSD_EISDIR,
+	BSD_EINVAL,
+	BSD_ENFILE,
+	BSD_EMFILE,
+	BSD_ENOTTY,
+	BSD_ETXTBSY,
+	BSD_EFBIG,
+	BSD_ENOSPC,
+	BSD_ESPIPE,
+	BSD_EROFS,
+	BSD_EMLINK,
+	BSD_EPIPE,
+	BSD_EDOM,
+	BSD_ERANGE,
+	BSD_EWOULDBLOCK,
+	BSD_EINPROGRESS,
+	BSD_EALREADY,
+	BSD_ENOTSOCK,
+	BSD_EDESTADDRREQ,
+	BSD_EMSGSIZE,
+	BSD_EPROTOTYPE,
+	BSD_ENOPROTOOPT,
+	BSD_EPROTONOSUPPORT,
+	BSD_ESOCKTNOSUPPORT,
+	BSD_EOPNOTSUPP,
+	BSD_EPFNOSUPPORT,
+	BSD_EAFNOSUPPORT,
+	BSD_EADDRINUSE,
+	BSD_EADDRNOTAVAIL,
+	BSD_ENETDOWN,
+	BSD_ENETUNREACH,
+	BSD_ENETRESET,
+	BSD_ECONNABORTED,
+	BSD_ECONNRESET,
+	BSD_ENOBUFS,
+	BSD_EISCONN,
+	BSD_ENOTONN,
+	BSD_ESHUTDOWN,
+	BSD_ETOOMANYREFS,
+	BSD_ETIMEDOUT,
+	BSD_ECONNREFUSED,
+	BSD_ELOOP,
+	BSD_ENAMETOOLONG,
+	BSD_EHOSTDOWN,
+	BSD_EHOSTUNREACH,
+	BSD_ENOTEMPTY,
+	BSD_EPROCLIM,
+	BSD_EUSERS,
+	BSD_EDQUOT,
+	BSD_ESTALE,
+	BSD_EREMOTE,
+	BSD_ENOSTR,
+	BSD_ETIME,
+	BSD_ENOSR,
+	BSD_ENOMSG,
+	BSD_EBADMSG,
+	BSD_IDRM,
+	BSD_EDEADLK,
+	BSD_ENOLCK,
+	BSD_ENONET,
+	BSD_ERREMOTE,
+	BSD_ENOLINK,
+	BSD_EADV,
+	BSD_ESRMNT,
+	BSD_ECOMM,
+	BSD_EPROTO,
+	BSD_EMULTIHOP,
+	BSD_EINVAL,    /* EDOTDOT XXX??? */
+	BSD_REMCHG,
+	BSD_NOSYS,
+	BSD_STRPIPE,
+	BSD_EOVERFLOW,
+	BSD_EBADFD,
+	BSD_ECHRNG,
+	BSD_EL2NSYNC,
+	BSD_EL3HLT,
+	BSD_EL3RST,
+	BSD_NRNG,
+	BSD_EUNATCH,
+	BSD_ENOCSI,
+	BSD_EL2HLT,
+	BSD_EBADE,
+	BSD_EBADR,
+	BSD_EXFULL,
+	BSD_ENOANO,
+	BSD_EBADRQC,
+	BSD_EBADSLT,
+	BSD_EDEADLOCK,
+	BSD_EBFONT,
+	BSD_ELIBEXEC,
+	BSD_ENODATA,
+	BSD_ELIBBAD,
+	BSD_ENOPKG,
+	BSD_ELIBACC,
+	BSD_ENOTUNIQ,
+	BSD_ERESTART,
+	BSD_EUCLEAN,
+	BSD_ENOTNAM,
+	BSD_ENAVAIL,
+	BSD_EISNAM,
+	BSD_EREMOTEIO,
+	BSD_EILSEQ,
+	BSD_ELIBMAX,
+	BSD_ELIBSCN,
+};
+
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/kernel/etrap.S linux/arch/sparc/kernel/etrap.S
--- v1.3.43/linux/arch/sparc/kernel/etrap.S	Thu Jan  1 02:00:00 1970
+++ linux/arch/sparc/kernel/etrap.S	Sat Nov 25 02:58:00 1995
@@ -0,0 +1,326 @@
+/* $Id: etrap.S,v 1.10 1995/11/25 00:57:58 davem Exp $
+ * etrap.S: Sparc trap window preparation for entry into the
+ *          Linux kernel.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#include <asm/cprefix.h>
+#include <asm/head.h>
+#include <asm/page.h>
+#include <asm/psr.h>
+#include <asm/ptrace.h>
+#include <asm/winmacro.h>
+
+/* Registers to not touch at all. */
+#define t_psr        l0 /* Set by caller */
+#define t_pc         l1 /* Set by caller */
+#define t_npc        l2 /* Set by caller */
+#define t_wim        l3 /* Set by caller */
+#define t_twinmask   l4 /* Set at beginning of this entry routine. */
+#define t_kstack     l5 /* Set right before pt_regs frame is built */
+#define t_retpc      l6 /* If you change this, change winmacro.h header file */
+#define t_systable   l7 /* Never touch this, could be the syscall table ptr. */
+#define curptr       g4 /* Set after pt_regs frame is built */
+
+	.text
+	.align 4
+
+	/* SEVEN WINDOW PATCH INSTRUCTIONS */
+	.globl	tsetup_7win_patch1, tsetup_7win_patch2
+	.globl	tsetup_7win_patch3, tsetup_7win_patch4
+	.globl	tsetup_7win_patch5, tsetup_7win_patch6
+tsetup_7win_patch1:	sll	%t_wim, 0x6, %t_wim
+tsetup_7win_patch2:	and	%g2, 0x7f, %g2
+tsetup_7win_patch3:	and	%g2, 0x7f, %g2
+tsetup_7win_patch4:	and	%g1, 0x7f, %g1
+tsetup_7win_patch5:	sll	%t_wim, 0x6, %t_wim
+tsetup_7win_patch6:	and	%g2, 0x7f, %g2
+	/* END OF PATCH INSTRUCTIONS */
+
+	/* At trap time, interrupts and all generic traps do the
+	 * following:
+	 *
+	 * rd	%psr, %l0
+	 * b	some_handler
+	 * rd	%wim, %l3
+	 * nop
+	 *
+	 * Then 'some_handler' if it needs a trap frame (ie. it has
+	 * to call c-code and the trap cannot be handled in-window)
+	 * then it does the SAVE_ALL macro in entry.S which does
+	 *
+	 * sethi	%hi(trap_setup), %l4
+	 * jmpl		%l4 + %lo(trap_setup), %l6
+	 * mov		1, %l4
+	 */
+
+	/* 2 3 4  window number
+	 * -----
+	 * O T S  mnemonic
+	 *
+	 * O == Current window before trap
+	 * T == Window entered when trap occurred
+	 * S == Window we will need to save if (1<<T) == %wim
+	 *
+	 * Before execution gets here, it must be guarenteed that
+	 * %l0 contains trap time %psr, %l1 and %l2 contain the
+	 * trap pc and npc, and %l3 contains the trap time %wim.
+	 */
+
+	.globl	trap_setup, tsetup_patch1, tsetup_patch2
+	.globl	tsetup_patch3, tsetup_patch4
+	.globl	tsetup_patch5, tsetup_patch6
+trap_setup:
+	/* Calculate mask of trap window.  See if from user
+	 * or kernel and branch conditionally.
+	 */
+	mov	1, %t_twinmask
+	sll	%t_twinmask, %t_psr, %t_twinmask ! t_twinmask = (1 << psr)
+	andcc	%t_psr, PSR_PS, %g0		 ! fromsupv_p = (psr & PSR_PS)
+	be	trap_setup_from_user		 ! nope, from user mode
+	 nop
+
+	/* From kernel, allocate more kernel stack and
+	 * build a pt_regs trap frame.
+	 */
+	sub	%fp, (STACKFRAME_SZ + TRACEREG_SZ), %t_kstack
+	STORE_PT_ALL(t_kstack, t_psr, t_pc, t_npc, t_wim, g2)
+
+	/* See if we are in the trap window. */
+	andcc	%t_twinmask, %t_wim, %g0
+	be	1f
+	 nop
+
+	b	trap_setup_kernel_spill		! in trap window, clean up
+	 nop
+
+	/* Trap from kernel with a window available.
+	 * Just do it...
+	 */
+1:
+	mov	%t_kstack, %sp		! jump onto new stack
+	jmpl	%t_retpc + 0x8, %g0	! return to caller
+	 nop
+
+trap_setup_kernel_spill:
+	LOAD_CURRENT(curptr)
+	ld	[%curptr + THREAD_UMASK], %g1
+	orcc	%g0, %g1, %g0
+	bne	trap_setup_user_spill	! there are some user windows, yuck
+	 nop
+
+		/* Spill from kernel, but only kernel windows, adjust
+		 * %wim and go.
+		 */
+		srl	%t_wim, 0x1, %g2	! begin computation of new %wim
+tsetup_patch1:	sll	%t_wim, 0x7, %t_wim	! patched on 7 window Sparcs
+		or	%t_wim, %g2, %g2
+tsetup_patch2:	and	%g2, 0xff, %g2		! patched on 7 window Sparcs
+
+	save	%g0, %g0, %g0
+
+	/* Set new %wim value */
+	wr	%g2, 0x0, %wim
+	WRITE_PAUSE
+
+	/* Save the kernel window onto the corresponding stack. */
+	STORE_WINDOW(sp)
+
+	restore	%g0, %g0, %g0
+
+	mov	%t_kstack, %sp		! and onto new kernel stack
+	jmpl	%t_retpc + 0x8, %g0	! return to caller
+	 nop
+
+trap_setup_from_user:
+	/* We can't use %curptr yet. */
+	LOAD_CURRENT(t_kstack)
+	ld	[%t_kstack + TASK_KSTACK_PG], %t_kstack
+
+	/* Build pt_regs frame. */
+	add	%t_kstack, (PAGE_SIZE - STACKFRAME_SZ - TRACEREG_SZ), %t_kstack
+	STORE_PT_ALL(t_kstack, t_psr, t_pc, t_npc, t_wim, g2)
+
+	/* Clear current->tss.w_saved */
+	LOAD_CURRENT(curptr)
+	st	%g0, [%curptr + THREAD_W_SAVED]
+
+	/* See if we are in the trap window. */
+	andcc	%t_twinmask, %t_wim, %g0
+	bne	trap_setup_user_spill		! yep we are
+	 orn	%g0, %t_twinmask, %g1		! negate trap win mask into %g1
+
+		/* Trap from user, but not into the invalid window.
+		 * Calculate new umask.  The way this works is,
+		 * any window from the %wim at trap time until
+		 * the window right before the one we are in now,
+		 * is a user window.  A diagram:
+		 *
+		 *      7 6 5 4 3 2 1 0    window number
+		 *      ---------------
+		 *        I     L T        mnemonic
+		 *
+		 * Window 'I' is the invalid window in our example,
+		 * window 'L' is the window the user was in when
+		 * the trap occurred, window T is the trap window
+		 * we are in now.  So therefore, windows 5, 4 and
+		 * 3 are user windows.  The following sequence
+		 * computes the user winmask to represent this.
+		 */
+		subcc	%t_wim, %t_twinmask, %g2
+		bneg,a	1f
+		 sub	%g2, 0x1, %g2
+1:
+		andn	%g2, %t_twinmask, %g2
+tsetup_patch3:	and	%g2, 0xff, %g2			! patched on 7win Sparcs
+		st	%g2, [%curptr + THREAD_UMASK]	! store new umask
+
+		mov	%t_kstack, %sp			! and onto kernel stack
+		jmpl	%t_retpc + 0x8, %g0		! return to caller
+		 nop
+
+trap_setup_user_spill:
+		/* A spill occured from either kernel or user mode
+		 * and there exist some user windows to deal with.
+		 * A mask of the currently valid user windows
+		 * is in %g1 upon entry to here.
+		 */
+
+tsetup_patch4:	and	%g1, 0xff, %g1		! patched on 7win Sparcs, mask
+		srl	%t_wim, 0x1, %g2	! compute new %wim
+tsetup_patch5:	sll	%t_wim, 0x7, %t_wim	! patched on 7win Sparcs
+		or	%t_wim, %g2, %g2	! %g2 is new %wim
+tsetup_patch6:	and	%g2, 0xff, %g2		! patched on 7win Sparcs
+		andn	%g1, %g2, %g1		! clear this bit in %g1
+		st	%g1, [%curptr + THREAD_UMASK]
+
+	save	%g0, %g0, %g0
+
+	wr	%g2, 0x0, %wim
+	WRITE_PAUSE
+
+	/* Call MMU-architecture dependant stack checking
+	 * routine.
+	 */
+	.globl	C_LABEL(tsetup_mmu_patchme)
+C_LABEL(tsetup_mmu_patchme):	b	C_LABEL(tsetup_sun4c_stackchk)
+				 andcc	%sp, 0x7, %g0
+
+trap_setup_user_stack_is_bolixed:
+	/* From user/kernel into invalid window w/bad user
+	 * stack. Save bad user stack, and return to caller.
+	 */
+	SAVE_BOLIXED_USER_STACK(curptr, g3)
+	restore	%g0, %g0, %g0
+	mov	%t_kstack, %sp
+	jmpl	%t_retpc + 0x8, %g0
+	 nop
+
+trap_setup_good_ustack:
+	STORE_WINDOW(sp)
+
+trap_setup_finish_up:
+	restore %g0, %g0, %g0
+	mov	%t_kstack, %sp
+	jmpl	%t_retpc + 0x8, %g0
+	 nop
+
+	/* Architecture specific stack checking routines.  When either
+	 * of these routines are called, the globals are free to use
+	 * as they have been safely stashed on the new kernel stack
+	 * pointer.  Thus the definition below for simplicity.
+	 */
+#define glob_tmp     g1
+
+	.globl	C_LABEL(tsetup_sun4c_stackchk)
+	.globl	C_LABEL(tsetup_srmmu_stackchk)
+C_LABEL(tsetup_sun4c_stackchk):
+	/* Done by caller: andcc %sp, 0x7, %g0 */
+	be	1f
+	 sra	%sp, 29, %glob_tmp
+
+	b	trap_setup_user_stack_is_bolixed
+	 nop
+
+1:
+	add	%glob_tmp, 0x1, %glob_tmp
+	andncc	%glob_tmp, 0x1, %g0
+	be	1f
+	 and	%sp, 0xfff, %glob_tmp		! delay slot
+
+	b	trap_setup_user_stack_is_bolixed
+	 nop
+
+	/* See if our dump area will be on more than one
+	 * page.
+	 */
+1:
+	add	%glob_tmp, 0x38, %glob_tmp
+	andncc	%glob_tmp, 0xff8, %g0
+	be	tsetup_sun4c_onepage		! only one page to check
+	 lda	[%sp] ASI_PTE, %glob_tmp	! have to check first page anyways
+
+tsetup_sun4c_twopages:
+	/* Is first page ok permission wise? */
+	srl	%glob_tmp, 29, %glob_tmp
+	cmp	%glob_tmp, 0x6
+	be	1f
+	 add	%sp, 0x38, %glob_tmp		/* Is second page in vma hole? */
+
+	b	trap_setup_user_stack_is_bolixed
+	 nop
+
+1:
+	sra	%glob_tmp, 29, %glob_tmp
+	add	%glob_tmp, 0x1, %glob_tmp
+	andncc	%glob_tmp, 0x1, %g0
+	be	1f
+	 add	%sp, 0x38, %glob_tmp
+
+	b	trap_setup_user_stack_is_bolixed
+	 nop
+
+1:
+	lda	[%glob_tmp] ASI_PTE, %glob_tmp
+
+tsetup_sun4c_onepage:
+	srl	%glob_tmp, 29, %glob_tmp
+	cmp	%glob_tmp, 0x6				! can user write to it?
+	be	trap_setup_good_ustack			! success
+	 nop
+
+	b	trap_setup_user_stack_is_bolixed
+	 nop
+
+C_LABEL(tsetup_srmmu_stackchk):
+	/* Check results of callers andcc %sp, 0x7, %g0 */
+	bne	trap_setup_user_stack_is_bolixed
+	 sethi	%hi(KERNBASE), %glob_tmp
+	cmp	%glob_tmp, %sp
+	bleu	trap_setup_user_stack_is_bolixed
+	 nop
+
+	/* Clear the fault status and turn on the no_fault bit. */
+	mov	AC_M_SFSR, %glob_tmp			! delay from above...
+	lda	[%glob_tmp] ASI_M_MMUREGS, %g0		! eat SFSR
+	lda	[%g0] ASI_M_MMUREGS, %glob_tmp		! read MMU control
+	or	%glob_tmp, 0x2, %glob_tmp		! or in no_fault bit
+	sta	%glob_tmp, [%g0] ASI_M_MMUREGS		! set it
+
+	/* Dump the registers and cross fingers. */
+	STORE_WINDOW(sp)
+
+	/* Clear the no_fault bit and check the status. */
+	andn	%glob_tmp, 0x2, %glob_tmp
+	sta	%glob_tmp, [%g0] ASI_M_MMUREGS
+	mov	AC_M_SFAR, %glob_tmp
+	lda	[%glob_tmp] ASI_M_MMUREGS, %g0
+	mov	AC_M_SFSR, %glob_tmp
+	lda	[%glob_tmp] ASI_M_MMUREGS, %glob_tmp
+	andcc	%glob_tmp, 0x2, %g0			! did we fault?
+	be	trap_setup_finish_up			! cool beans, success
+	 nop
+
+	b	trap_setup_user_stack_is_bolixed	! we faulted, ugh
+	 nop
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/kernel/head.S linux/arch/sparc/kernel/head.S
--- v1.3.43/linux/arch/sparc/kernel/head.S	Tue Jun 27 14:11:31 1995
+++ linux/arch/sparc/kernel/head.S	Sat Nov 25 02:58:04 1995
@@ -1,67 +1,23 @@
-/* head.S: The initial boot code for the Sparc port of Linux.
+/* $Id: head.S,v 1.39 1995/11/25 00:58:01 davem Exp $
+ * head.S: The initial boot code for the Sparc port of Linux.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- *
- *         This file has to serve three purposes.
- *
- *	   1) determine the prom-version and cpu/architecture
- *	   2) print enough useful info before we start to execute
- *	      c-code that I can possibly begin to debug things
- *	   3) Hold the vector of trap entry points
- *
- *  The Sparc offers many challenges to kernel design. Here I will
- * document those I have come across thus far. Upon bootup the boot
- * prom loads your a.out image into memory. This memory the prom has
- * already mapped for you in two places, however as far as I can tell
- * the virtual address cache is not turned on although the MMU is
- * translating things. You get loaded at 0x4000 exactly and you are
- * aliased to 0xf8004000 with the appropriate mmu entries. So, when
- * you link a boot-loadable object you want to do something like
- *
- *      ld -e start -Ttext 4000 -o mykernel myobj1.o myobj2.o ....
- *
- * to produce a proper image.
- *
- * At boot time you are given (as far as I can tell at this time)
- * one key to figure out what machine you are one and what devices
- * are available. The prom when it loads you leaves a pointer to
- * the 'rom vector' in register %o0 right before it jumps to your
- * starting address. This is a pointer to a struct that is full of
- * pointer to functions (ie. printf, halt, reboot), pointers to
- * linked lists (ie. memory mappings), and pointer to empirical
- * constants (ie. stdin and stdout magic cookies + rom version).
- * Starting with this piece of information you can figure out 
- * just about anything you want about the machine you are on.
- *
- * Although I don't use it now, if you are on a Multiprocessor and
- * therefore a v3 or above prom, register %o2 at boot contains a
- * function pointer you must call before you proceed to invoke the
- * other cpu's on the machine. I have no idea what kind of magic this
- * is, give me time.
+ * Copyright (C) 1995 Peter Zaitcev   (Zaitcev@ipmce.su)
  */
 
+#include <linux/version.h>
+
 #include <asm/cprefix.h>
 #include <asm/head.h>
-#include <linux/version.h>
 #include <asm/asi.h>
 #include <asm/contregs.h>
+#include <asm/ptrace.h>
 #include <asm/psr.h>
 #include <asm/page.h>
 #include <asm/kdebug.h>
+#include <asm/winmacro.h>
 
 	.data
-
-/* First thing to go in the data segment is the interrupt stack. */
-
-        .globl  C_LABEL(intstack)
-        .globl  C_LABEL(eintstack)
-	.align 4
-C_LABEL(intstack):
-        .skip   4 * PAGE_SIZE                ! 16k = 128 128-byte stack frames
-C_LABEL(eintstack):
-
-
-
 /* 
  * The following are used with the prom_vector node-ops to figure out
  * the cpu-type 
@@ -98,10 +54,7 @@
 C_LABEL(cputypvar_sun4m):
 	.asciz "compatible"
 
-/* WARNING: evil messages follow */
-
 	.align 4
-
 sun4_notsup:
 	.asciz  "Sparc-Linux sun4 support not implemented yet\n\n"
 	.align 4
@@ -118,302 +71,112 @@
         .asciz  "Sparc-Linux sun4u support does not exist\n\n"
 	.align 4
 
-/* Ok, things start to get interesting. We get linked such that 'start'
- * is the entry symbol. However, it is real low in kernel address space
- * and as such a nifty place to place the trap table. We achieve this goal
- * by just jumping to 'gokernel' for the first trap's entry as the sparc
- * never receives the zero trap as it is real special (hw reset).
- *
- * Each trap entry point is the size of 4 sparc instructions (or 4 bytes
- * * 4 insns = 16 bytes). There are 128 hardware traps (some undefined
- * or unimplemented) and 128 software traps (sys-calls, etc.).
- *
- * One of the instructions must be a branch. More often than not this
- * will be to a trap handler entry point because it is completely
- * impossible to handle any trap in 4 insns. I welcome anyone to 
- * challenge this theory. :-)
- *
- * On entry into this table the hardware has loaded the program counter
- * at which the trap occurred into register %l1 and the next program
- * counter into %l2, this way we can return from the trap with a simple
- *
- *         jmp %l1; rett %l2  ! poof...
- *
- * after properly servicing the trap. It wouldn't be a bad idea to load
- * some more information into the local regs since we have technically
- * 2 or 3 instructions to play with besides the jmp to the 'real' trap
- * handler (one can even go in the delay slot). For now I am going to put
- * the %psr (processor status register) and the trap-type value in %l0
- * and %l3 respectively. Also, for IRQ's I'll put the level in %l4.
- */
-
+	/* The Sparc trap table, bootloader gives us control at _start. */
 	.text
-
-	.globl	start
-	.globl 	_start  /* warning, solaris hack */
+	.globl	start, _stext, _start, __stext
 	.globl  C_LABEL(trapbase)
 _start:   /* danger danger */
+__stext:
+_stext:
 start:
 C_LABEL(trapbase):
-/* XXX Grrr, this table is basically sun4c specific, sort of... XXX */
 /* We get control passed to us here at t_zero. */
 t_zero:	b gokernel; nop; nop; nop;
-
-t_tflt:	TRAP_ENTRY(0x1, sparc_text_fault)    /* Inst. Access Exception        */
-t_bins:	TRAP_ENTRY(0x2, bad_instruction)     /* Illegal Instruction           */
-t_pins:	TRAP_ENTRY(0x3, bad_instruction)     /* Privileged Instruction        */
-t_fpd:	TRAP_ENTRY(0x4, fpd_trap_handler)    /* Floating Point Disabled       */
-t_wovf:	TRAP_ENTRY(0x5, spill_window_entry)  /* Window Overflow               */
-t_wunf:	TRAP_ENTRY(0x6, fill_window_entry)   /* Window Underflow              */
-t_mna:	TRAP_ENTRY(0x7, mna_handler)         /* Memory Address Not Aligned    */
-t_fpe:	TRAP_ENTRY(0x8, fpe_trap_handler)    /* Floating Point Exception      */
-t_dflt:	TRAP_ENTRY(0x9, sparc_data_fault)    /* Data Miss Exception           */
-t_tio:	TRAP_ENTRY(0xa, do_tag_overflow)     /* Tagged Instruction Ovrflw     */
-t_wpt:	TRAP_ENTRY(0xb, do_watchpoint)       /* Watchpoint Detected           */
-t_badc:	TRAP_ENTRY(0xc, bad_trap_handler)    /* Undefined...                  */
-t_badd:	TRAP_ENTRY(0xd, bad_trap_handler)    /* Undefined...                  */
-t_bade:	TRAP_ENTRY(0xe, bad_trap_handler)    /* Undefined...                  */
-t_badf:	TRAP_ENTRY(0xf, bad_trap_handler)    /* Undefined...                  */
-t_bad10:TRAP_ENTRY(0x10, bad_trap_handler)   /* Undefined...                  */
-t_irq1:	TRAP_ENTRY_INTERRUPT(1)	             /* IRQ Software/SBUS Level 1     */
-t_irq2:	TRAP_ENTRY_INTERRUPT(2)              /* IRQ SBUS Level 2              */
-t_irq3:	TRAP_ENTRY_INTERRUPT(3)              /* IRQ SCSI/DMA/SBUS Level 3     */
-t_irq4:	TRAP_ENTRY_INTERRUPT(4)              /* IRQ Software Level 4          */
-t_irq5:	TRAP_ENTRY_INTERRUPT(5)              /* IRQ SBUS/Ethernet Level 5     */
-t_irq6:	TRAP_ENTRY_INTERRUPT(6)              /* IRQ Software Level 6          */
-t_irq7:	TRAP_ENTRY_INTERRUPT(7)              /* IRQ Video/SBUS Level 5        */
-t_irq8:	TRAP_ENTRY_INTERRUPT(8)              /* IRQ SBUS Level 6              */
-t_irq9:	TRAP_ENTRY_INTERRUPT(9)              /* IRQ SBUS Level 7              */
-t_irq10:TRAP_ENTRY_TIMER                     /* IRQ Timer #1 (one we use)     */
-t_irq11:TRAP_ENTRY_INTERRUPT(11)             /* IRQ Floppy Intr.              */
-t_irq12:TRAP_ENTRY_INTERRUPT(12)             /* IRQ Zilog serial chip         */
-t_irq13:TRAP_ENTRY_INTERRUPT(13)             /* IRQ Audio Intr.               */
-t_irq14:TRAP_ENTRY_INTERRUPT(14)             /* IRQ Timer #2                  */
-t_nmi:	NMI_TRAP                             /* Level 15 (NMI)                */
-t_racc:	TRAP_ENTRY(0x20, do_reg_access)      /* General Register Access Error */
-t_iacce:TRAP_ENTRY(0x21, do_iacc_error)      /* Instruction Access Error      */
-t_bad22:TRAP_ENTRY(0x22, bad_trap_handler)   /* Undefined...                  */
-t_bad23:TRAP_ENTRY(0x23, bad_trap_handler)   /* Undefined...                  */
-t_cpdis:TRAP_ENTRY(0x24, do_cp_disabled)     /* Co-Processor Disabled         */
-t_uflsh:TRAP_ENTRY(0x25, do_bad_flush)       /* Unimplemented FLUSH inst.     */
-t_bad26:TRAP_ENTRY(0x26, bad_trap_handler)   /* Undefined...                  */
-t_bad27:TRAP_ENTRY(0x27, bad_trap_handler)   /* Undefined...                  */
-t_cpexc:TRAP_ENTRY(0x28, do_cp_exception)    /* Co-Processor Exception        */
-t_dacce:TRAP_ENTRY(0x29, do_dacc_error)      /* Data Access Error             */
-t_hwdz:	TRAP_ENTRY(0x2a, do_hw_divzero)      /* Division by zero, you lose... */
-t_dserr:TRAP_ENTRY(0x2b, do_dstore_err)      /* Data Store Error              */
-t_daccm:TRAP_ENTRY(0x2c, do_dacc_mmu_miss)   /* Data Access MMU-Miss          */
-t_bad2d:TRAP_ENTRY(0x2d, bad_trap_handler)   /* Undefined...                  */
-t_bad2e:TRAP_ENTRY(0x2e, bad_trap_handler)   /* Undefined...                  */
-t_bad2f:TRAP_ENTRY(0x2f, bad_trap_handler)   /* Undefined...                  */
-t_bad30:TRAP_ENTRY(0x30, bad_trap_handler)   /* Undefined...                  */
-t_bad31:TRAP_ENTRY(0x31, bad_trap_handler)   /* Undefined...                  */
-t_bad32:TRAP_ENTRY(0x32, bad_trap_handler)   /* Undefined...                  */
-t_bad33:TRAP_ENTRY(0x33, bad_trap_handler)   /* Undefined...                  */
-t_bad34:TRAP_ENTRY(0x34, bad_trap_handler)   /* Undefined...                  */
-t_bad35:TRAP_ENTRY(0x35, bad_trap_handler)   /* Undefined...                  */
-t_bad36:TRAP_ENTRY(0x36, bad_trap_handler)   /* Undefined...                  */
-t_bad37:TRAP_ENTRY(0x37, bad_trap_handler)   /* Undefined...                  */
-t_bad38:TRAP_ENTRY(0x38, bad_trap_handler)   /* Undefined...                  */
-t_bad39:TRAP_ENTRY(0x39, bad_trap_handler)   /* Undefined...                  */
-t_bad3a:TRAP_ENTRY(0x3a, bad_trap_handler)   /* Undefined...                  */
-t_bad3b:TRAP_ENTRY(0x3b, bad_trap_handler)   /* Undefined...                  */
-t_iaccm:TRAP_ENTRY(0x3c, do_iacc_mmu_miss)   /* Instruction Access MMU-Miss   */
-t_bad3d:TRAP_ENTRY(0x3d, bad_trap_handler)   /* Undefined...                  */
-t_bad3e:TRAP_ENTRY(0x3e, bad_trap_handler)   /* Undefined...                  */
-t_bad3f:TRAP_ENTRY(0x3f, bad_trap_handler)   /* Undefined...                  */
-t_bad40:TRAP_ENTRY(0x40, bad_trap_handler)   /* Undefined...                  */
-t_bad41:TRAP_ENTRY(0x41, bad_trap_handler)   /* Undefined...                  */
-t_bad42:TRAP_ENTRY(0x42, bad_trap_handler)   /* Undefined...                  */
-t_bad43:TRAP_ENTRY(0x43, bad_trap_handler)   /* Undefined...                  */
-t_bad44:TRAP_ENTRY(0x44, bad_trap_handler)   /* Undefined...                  */
-t_bad45:TRAP_ENTRY(0x45, bad_trap_handler)   /* Undefined...                  */
-t_bad46:TRAP_ENTRY(0x46, bad_trap_handler)   /* Undefined...                  */
-t_bad47:TRAP_ENTRY(0x47, bad_trap_handler)   /* Undefined...                  */
-t_bad48:TRAP_ENTRY(0x48, bad_trap_handler)   /* Undefined...                  */
-t_bad49:TRAP_ENTRY(0x49, bad_trap_handler)   /* Undefined...                  */
-t_bad4a:TRAP_ENTRY(0x4a, bad_trap_handler)   /* Undefined...                  */
-t_bad4b:TRAP_ENTRY(0x4b, bad_trap_handler)   /* Undefined...                  */
-t_bad4c:TRAP_ENTRY(0x4c, bad_trap_handler)   /* Undefined...                  */
-t_bad4d:TRAP_ENTRY(0x4d, bad_trap_handler)   /* Undefined...                  */
-t_bad4e:TRAP_ENTRY(0x4e, bad_trap_handler)   /* Undefined...                  */
-t_bad4f:TRAP_ENTRY(0x4f, bad_trap_handler)   /* Undefined...                  */
-t_bad50:TRAP_ENTRY(0x50, bad_trap_handler)   /* Undefined...                  */
-t_bad51:TRAP_ENTRY(0x51, bad_trap_handler)   /* Undefined...                  */
-t_bad52:TRAP_ENTRY(0x52, bad_trap_handler)   /* Undefined...                  */
-t_bad53:TRAP_ENTRY(0x53, bad_trap_handler)   /* Undefined...                  */
-t_bad54:TRAP_ENTRY(0x54, bad_trap_handler)   /* Undefined...                  */
-t_bad55:TRAP_ENTRY(0x55, bad_trap_handler)   /* Undefined...                  */
-t_bad56:TRAP_ENTRY(0x56, bad_trap_handler)   /* Undefined...                  */
-t_bad57:TRAP_ENTRY(0x57, bad_trap_handler)   /* Undefined...                  */
-t_bad58:TRAP_ENTRY(0x58, bad_trap_handler)   /* Undefined...                  */
-t_bad59:TRAP_ENTRY(0x59, bad_trap_handler)   /* Undefined...                  */
-t_bad5a:TRAP_ENTRY(0x5a, bad_trap_handler)   /* Undefined...                  */
-t_bad5b:TRAP_ENTRY(0x5b, bad_trap_handler)   /* Undefined...                  */
-t_bad5c:TRAP_ENTRY(0x5c, bad_trap_handler)   /* Undefined...                  */
-t_bad5d:TRAP_ENTRY(0x5d, bad_trap_handler)   /* Undefined...                  */
-t_bad5e:TRAP_ENTRY(0x5e, bad_trap_handler)   /* Undefined...                  */
-t_bad5f:TRAP_ENTRY(0x5f, bad_trap_handler)   /* Undefined...                  */
-t_bad60:TRAP_ENTRY(0x60, bad_trap_handler)   /* Impl-Dep Exception            */
-t_bad61:TRAP_ENTRY(0x61, bad_trap_handler)   /* Impl-Dep Exception            */
-t_bad62:TRAP_ENTRY(0x62, bad_trap_handler)   /* Impl-Dep Exception            */
-t_bad63:TRAP_ENTRY(0x63, bad_trap_handler)   /* Impl-Dep Exception            */
-t_bad64:TRAP_ENTRY(0x64, bad_trap_handler)   /* Impl-Dep Exception            */
-t_bad65:TRAP_ENTRY(0x65, bad_trap_handler)   /* Impl-Dep Exception            */
-t_bad66:TRAP_ENTRY(0x66, bad_trap_handler)   /* Impl-Dep Exception            */
-t_bad67:TRAP_ENTRY(0x67, bad_trap_handler)   /* Impl-Dep Exception            */
-t_bad68:TRAP_ENTRY(0x68, bad_trap_handler)   /* Impl-Dep Exception            */
-t_bad69:TRAP_ENTRY(0x69, bad_trap_handler)   /* Impl-Dep Exception            */
-t_bad6a:TRAP_ENTRY(0x6a, bad_trap_handler)   /* Impl-Dep Exception            */
-t_bad6b:TRAP_ENTRY(0x6b, bad_trap_handler)   /* Impl-Dep Exception            */
-t_bad6c:TRAP_ENTRY(0x6c, bad_trap_handler)   /* Impl-Dep Exception            */
-t_bad6d:TRAP_ENTRY(0x6d, bad_trap_handler)   /* Impl-Dep Exception            */
-t_bad6e:TRAP_ENTRY(0x6e, bad_trap_handler)   /* Impl-Dep Exception            */
-t_bad6f:TRAP_ENTRY(0x6f, bad_trap_handler)   /* Impl-Dep Exception            */
-t_bad70:TRAP_ENTRY(0x70, bad_trap_handler)   /* Impl-Dep Exception            */
-t_bad71:TRAP_ENTRY(0x71, bad_trap_handler)   /* Impl-Dep Exception            */
-t_bad72:TRAP_ENTRY(0x72, bad_trap_handler)   /* Impl-Dep Exception            */
-t_bad73:TRAP_ENTRY(0x73, bad_trap_handler)   /* Impl-Dep Exception            */
-t_bad74:TRAP_ENTRY(0x74, bad_trap_handler)   /* Impl-Dep Exception            */
-t_bad75:TRAP_ENTRY(0x75, bad_trap_handler)   /* Impl-Dep Exception            */
-t_bad76:TRAP_ENTRY(0x76, bad_trap_handler)   /* Impl-Dep Exception            */
-t_bad77:TRAP_ENTRY(0x77, bad_trap_handler)   /* Impl-Dep Exception            */
-t_bad78:TRAP_ENTRY(0x78, bad_trap_handler)   /* Impl-Dep Exception            */
-t_bad79:TRAP_ENTRY(0x79, bad_trap_handler)   /* Impl-Dep Exception            */
-t_bad7a:TRAP_ENTRY(0x7a, bad_trap_handler)   /* Impl-Dep Exception            */
-t_bad7b:TRAP_ENTRY(0x7b, bad_trap_handler)   /* Impl-Dep Exception            */
-t_bad7c:TRAP_ENTRY(0x7c, bad_trap_handler)   /* Impl-Dep Exception            */
-t_bad7d:TRAP_ENTRY(0x7d, bad_trap_handler)   /* Impl-Dep Exception            */
-t_bad7e:TRAP_ENTRY(0x7e, bad_trap_handler)   /* Impl-Dep Exception            */
-t_bad7f:TRAP_ENTRY(0x7f, bad_trap_handler)   /* Impl-Dep Exception            */
-t_sunos:SUNOS_SYSCALL_TRAP                   /* SunOS System Call             */
-t_sbkpt:TRAP_ENTRY(0x81, bad_trap_handler)   /* Software Breakpoint           */
-t_divz:	TRAP_ENTRY(0x82, bad_trap_handler)   /* Divide by zero trap           */
-t_flwin:TRAP_ENTRY(0x83, bad_trap_handler)   /* Flush Windows Trap            */
-t_clwin:TRAP_ENTRY(0x84, bad_trap_handler)   /* Clean Windows Trap            */
-t_rchk:	TRAP_ENTRY(0x85, bad_trap_handler)   /* Range Check                   */
-t_funal:TRAP_ENTRY(0x86, bad_trap_handler)   /* Fix Unaligned Access Trap     */
-t_iovf:	TRAP_ENTRY(0x87, bad_trap_handler)   /* Integer Overflow Trap         */
-t_slowl:SOLARIS_SYSCALL_TRAP                 /* Slowaris System Call          */
-t_netbs:NETBSD_SYSCALL_TRAP                  /* Net-B.S. System Call          */
-t_bad8a:TRAP_ENTRY(0x8a, bad_trap_handler)   /* Software Trap                 */
-t_bad8b:TRAP_ENTRY(0x8b, bad_trap_handler)   /* Software Trap                 */
-t_bad8c:TRAP_ENTRY(0x8c, bad_trap_handler)   /* Software Trap                 */
-t_bad8d:TRAP_ENTRY(0x8d, bad_trap_handler)   /* Software Trap                 */
-t_bad8e:TRAP_ENTRY(0x8e, bad_trap_handler)   /* Software Trap                 */
-t_bad8f:TRAP_ENTRY(0x8f, bad_trap_handler)   /* Software Trap                 */
-t_linux:LINUX_SYSCALL_TRAP                   /* Linux System Call             */
-t_bad91:TRAP_ENTRY(0x91, bad_trap_handler)   /* Software Trap                 */
-t_bad92:TRAP_ENTRY(0x92, bad_trap_handler)   /* Software Trap                 */
-t_bad93:TRAP_ENTRY(0x93, bad_trap_handler)   /* Software Trap                 */
-t_bad94:TRAP_ENTRY(0x94, bad_trap_handler)   /* Software Trap                 */
-t_bad95:TRAP_ENTRY(0x95, bad_trap_handler)   /* Software Trap                 */
-t_bad96:TRAP_ENTRY(0x96, bad_trap_handler)   /* Software Trap                 */
-t_bad97:TRAP_ENTRY(0x97, bad_trap_handler)   /* Software Trap                 */
-t_bad98:TRAP_ENTRY(0x98, bad_trap_handler)   /* Software Trap                 */
-t_bad99:TRAP_ENTRY(0x99, bad_trap_handler)   /* Software Trap                 */
-t_bad9a:TRAP_ENTRY(0x9a, bad_trap_handler)   /* Software Trap                 */
-t_bad9b:TRAP_ENTRY(0x9b, bad_trap_handler)   /* Software Trap                 */
-t_bad9c:TRAP_ENTRY(0x9c, bad_trap_handler)   /* Software Trap                 */
-t_bad9d:TRAP_ENTRY(0x9d, bad_trap_handler)   /* Software Trap                 */
-t_bad9e:TRAP_ENTRY(0x9e, bad_trap_handler)   /* Software Trap                 */
-t_bad9f:TRAP_ENTRY(0x9f, bad_trap_handler)   /* Software Trap                 */
-t_getcc:GETCC_TRAP                           /* Get Condition Codes           */
-t_setcc:SETCC_TRAP                           /* Set Condition Codes           */
-t_bada2:TRAP_ENTRY(0xa2, bad_trap_handler)   /* Software Trap                 */
-t_bada3:TRAP_ENTRY(0xa3, bad_trap_handler)   /* Software Trap                 */
-t_bada4:TRAP_ENTRY(0xa4, bad_trap_handler)   /* Software Trap                 */
-t_bada5:TRAP_ENTRY(0xa5, bad_trap_handler)   /* Software Trap                 */
-t_bada6:TRAP_ENTRY(0xa6, bad_trap_handler)   /* Software Trap                 */
-t_bada7:TRAP_ENTRY(0xa7, bad_trap_handler)   /* Software Trap                 */
-t_bada8:TRAP_ENTRY(0xa8, bad_trap_handler)   /* Software Trap                 */
-t_bada9:TRAP_ENTRY(0xa9, bad_trap_handler)   /* Software Trap                 */
-t_badaa:TRAP_ENTRY(0xaa, bad_trap_handler)   /* Software Trap                 */
-t_badab:TRAP_ENTRY(0xab, bad_trap_handler)   /* Software Trap                 */
-t_badac:TRAP_ENTRY(0xac, bad_trap_handler)   /* Software Trap                 */
-t_badad:TRAP_ENTRY(0xad, bad_trap_handler)   /* Software Trap                 */
-t_badae:TRAP_ENTRY(0xae, bad_trap_handler)   /* Software Trap                 */
-t_badaf:TRAP_ENTRY(0xaf, bad_trap_handler)   /* Software Trap                 */
-t_badb0:TRAP_ENTRY(0xb0, bad_trap_handler)   /* Software Trap                 */
-t_badb1:TRAP_ENTRY(0xb1, bad_trap_handler)   /* Software Trap                 */
-t_badb2:TRAP_ENTRY(0xb2, bad_trap_handler)   /* Software Trap                 */
-t_badb3:TRAP_ENTRY(0xb3, bad_trap_handler)   /* Software Trap                 */
-t_badb4:TRAP_ENTRY(0xb4, bad_trap_handler)   /* Software Trap                 */
-t_badb5:TRAP_ENTRY(0xb5, bad_trap_handler)   /* Software Trap                 */
-t_badb6:TRAP_ENTRY(0xb6, bad_trap_handler)   /* Software Trap                 */
-t_badb7:TRAP_ENTRY(0xb7, bad_trap_handler)   /* Software Trap                 */
-t_badb8:TRAP_ENTRY(0xb8, bad_trap_handler)   /* Software Trap                 */
-t_badb9:TRAP_ENTRY(0xb9, bad_trap_handler)   /* Software Trap                 */
-t_badba:TRAP_ENTRY(0xba, bad_trap_handler)   /* Software Trap                 */
-t_badbb:TRAP_ENTRY(0xbb, bad_trap_handler)   /* Software Trap                 */
-t_badbc:TRAP_ENTRY(0xbc, bad_trap_handler)   /* Software Trap                 */
-t_badbd:TRAP_ENTRY(0xbd, bad_trap_handler)   /* Software Trap                 */
-t_badbe:TRAP_ENTRY(0xbe, bad_trap_handler)   /* Software Trap                 */
-t_badbf:TRAP_ENTRY(0xbf, bad_trap_handler)   /* Software Trap                 */
-t_badc0:TRAP_ENTRY(0xc0, bad_trap_handler)   /* Software Trap                 */
-t_badc1:TRAP_ENTRY(0xc1, bad_trap_handler)   /* Software Trap                 */
-t_badc2:TRAP_ENTRY(0xc2, bad_trap_handler)   /* Software Trap                 */
-t_badc3:TRAP_ENTRY(0xc3, bad_trap_handler)   /* Software Trap                 */
-t_badc4:TRAP_ENTRY(0xc4, bad_trap_handler)   /* Software Trap                 */
-t_badc5:TRAP_ENTRY(0xc5, bad_trap_handler)   /* Software Trap                 */
-t_badc6:TRAP_ENTRY(0xc6, bad_trap_handler)   /* Software Trap                 */
-t_badc7:TRAP_ENTRY(0xc7, bad_trap_handler)   /* Software Trap                 */
-t_badc8:TRAP_ENTRY(0xc8, bad_trap_handler)   /* Software Trap                 */
-t_badc9:TRAP_ENTRY(0xc9, bad_trap_handler)   /* Software Trap                 */
-t_badca:TRAP_ENTRY(0xca, bad_trap_handler)   /* Software Trap                 */
-t_badcb:TRAP_ENTRY(0xcb, bad_trap_handler)   /* Software Trap                 */
-t_badcc:TRAP_ENTRY(0xcc, bad_trap_handler)   /* Software Trap                 */
-t_badcd:TRAP_ENTRY(0xcd, bad_trap_handler)   /* Software Trap                 */
-t_badce:TRAP_ENTRY(0xce, bad_trap_handler)   /* Software Trap                 */
-t_badcf:TRAP_ENTRY(0xcf, bad_trap_handler)   /* Software Trap                 */
-t_badd0:TRAP_ENTRY(0xd0, bad_trap_handler)   /* Software Trap                 */
-t_badd1:TRAP_ENTRY(0xd1, bad_trap_handler)   /* Software Trap                 */
-t_badd2:TRAP_ENTRY(0xd2, bad_trap_handler)   /* Software Trap                 */
-t_badd3:TRAP_ENTRY(0xd3, bad_trap_handler)   /* Software Trap                 */
-t_badd4:TRAP_ENTRY(0xd4, bad_trap_handler)   /* Software Trap                 */
-t_badd5:TRAP_ENTRY(0xd5, bad_trap_handler)   /* Software Trap                 */
-t_badd6:TRAP_ENTRY(0xd6, bad_trap_handler)   /* Software Trap                 */
-t_badd7:TRAP_ENTRY(0xd7, bad_trap_handler)   /* Software Trap                 */
-t_badd8:TRAP_ENTRY(0xd8, bad_trap_handler)   /* Software Trap                 */
-t_badd9:TRAP_ENTRY(0xd9, bad_trap_handler)   /* Software Trap                 */
-t_badda:TRAP_ENTRY(0xda, bad_trap_handler)   /* Software Trap                 */
-t_baddb:TRAP_ENTRY(0xdb, bad_trap_handler)   /* Software Trap                 */
-t_baddc:TRAP_ENTRY(0xdc, bad_trap_handler)   /* Software Trap                 */
-t_baddd:TRAP_ENTRY(0xdd, bad_trap_handler)   /* Software Trap                 */
-t_badde:TRAP_ENTRY(0xde, bad_trap_handler)   /* Software Trap                 */
-t_baddf:TRAP_ENTRY(0xdf, bad_trap_handler)   /* Software Trap                 */
-t_bade0:TRAP_ENTRY(0xe0, bad_trap_handler)   /* Software Trap                 */
-t_bade1:TRAP_ENTRY(0xe1, bad_trap_handler)   /* Software Trap                 */
-t_bade2:TRAP_ENTRY(0xe2, bad_trap_handler)   /* Software Trap                 */
-t_bade3:TRAP_ENTRY(0xe3, bad_trap_handler)   /* Software Trap                 */
-t_bade4:TRAP_ENTRY(0xe4, bad_trap_handler)   /* Software Trap                 */
-t_bade5:TRAP_ENTRY(0xe5, bad_trap_handler)   /* Software Trap                 */
-t_bade6:TRAP_ENTRY(0xe6, bad_trap_handler)   /* Software Trap                 */
-t_bade7:TRAP_ENTRY(0xe7, bad_trap_handler)   /* Software Trap                 */
-t_bade8:TRAP_ENTRY(0xe8, bad_trap_handler)   /* Software Trap                 */
-t_bade9:TRAP_ENTRY(0xe9, bad_trap_handler)   /* Software Trap                 */
-t_badea:TRAP_ENTRY(0xea, bad_trap_handler)   /* Software Trap                 */
-t_badeb:TRAP_ENTRY(0xeb, bad_trap_handler)   /* Software Trap                 */
-t_badec:TRAP_ENTRY(0xec, bad_trap_handler)   /* Software Trap                 */
-t_baded:TRAP_ENTRY(0xed, bad_trap_handler)   /* Software Trap                 */
-t_badee:TRAP_ENTRY(0xee, bad_trap_handler)   /* Software Trap                 */
-t_badef:TRAP_ENTRY(0xef, bad_trap_handler)   /* Software Trap                 */
-t_badf0:TRAP_ENTRY(0xf0, bad_trap_handler)   /* Software Trap                 */
-t_badf1:TRAP_ENTRY(0xf1, bad_trap_handler)   /* Software Trap                 */
-t_badf2:TRAP_ENTRY(0xf2, bad_trap_handler)   /* Software Trap                 */
-t_badf3:TRAP_ENTRY(0xf3, bad_trap_handler)   /* Software Trap                 */
-t_badf4:TRAP_ENTRY(0xf4, bad_trap_handler)   /* Software Trap                 */
-t_badf5:TRAP_ENTRY(0xf5, bad_trap_handler)   /* Software Trap                 */
-t_badf6:TRAP_ENTRY(0xf6, bad_trap_handler)   /* Software Trap                 */
-t_badf7:TRAP_ENTRY(0xf7, bad_trap_handler)   /* Software Trap                 */
-t_badf8:TRAP_ENTRY(0xf8, bad_trap_handler)   /* Software Trap                 */
-t_badf9:TRAP_ENTRY(0xf9, bad_trap_handler)   /* Software Trap                 */
-t_badfa:TRAP_ENTRY(0xfa, bad_trap_handler)   /* Software Trap                 */
-t_badfb:TRAP_ENTRY(0xfb, bad_trap_handler)   /* Software Trap                 */
-t_badfc:TRAP_ENTRY(0xfc, bad_trap_handler)   /* Software Trap                 */
-t_badfd:TRAP_ENTRY(0xfd, bad_trap_handler)   /* Software Trap                 */
-dbtrap:	TRAP_ENTRY(0xfe, bad_trap_handler)   /* Debugger/PROM breakpoint #1   */
-dbtrap2:TRAP_ENTRY(0xff, bad_trap_handler)   /* Debugger/PROM breakpoint #2   */	
+t_tflt:	TRAP_ENTRY(0x1, sparc_fault)        /* Inst. Access Exception        */
+t_bins:	TRAP_ENTRY(0x2, bad_instruction)    /* Illegal Instruction           */
+t_pins:	TRAP_ENTRY(0x3, priv_instruction)   /* Privileged Instruction        */
+t_fpd:	TRAP_ENTRY(0x4, fpd_trap_handler)   /* Floating Point Disabled       */
+t_wovf:	WINDOW_SPILL                        /* Window Overflow               */
+t_wunf:	WINDOW_FILL                         /* Window Underflow              */
+t_mna:	TRAP_ENTRY(0x7, mna_handler)        /* Memory Address Not Aligned    */
+t_fpe:	TRAP_ENTRY(0x8, fpe_trap_handler)   /* Floating Point Exception      */
+t_dflt:	TRAP_ENTRY(0x9, sparc_fault)        /* Data Miss Exception           */
+t_tio:	TRAP_ENTRY(0xa, do_tag_overflow)    /* Tagged Instruction Ovrflw     */
+t_wpt:	TRAP_ENTRY(0xb, do_watchpoint)      /* Watchpoint Detected           */
+t_badc:	BAD_TRAP(0xc) BAD_TRAP(0xd) BAD_TRAP(0xe) BAD_TRAP(0xf) BAD_TRAP(0x10)
+t_irq1:	TRAP_ENTRY_SOFTINT(1)               /* IRQ Software/SBUS Level 1     */
+t_irq2:	TRAP_ENTRY_INTERRUPT(2)             /* IRQ SBUS Level 2              */
+t_irq3:	TRAP_ENTRY_INTERRUPT(3)             /* IRQ SCSI/DMA/SBUS Level 3     */
+t_irq4:	TRAP_ENTRY_SOFTINT(4)               /* IRQ Software Level 4          */
+t_irq5:	TRAP_ENTRY_INTERRUPT(5)             /* IRQ SBUS/Ethernet Level 5     */
+t_irq6:	TRAP_ENTRY_SOFTINT(6)               /* IRQ Software Level 6          */
+t_irq7:	TRAP_ENTRY_INTERRUPT(7)             /* IRQ Video/SBUS Level 5        */
+t_irq8:	TRAP_ENTRY_INTERRUPT(8)             /* IRQ SBUS Level 6              */
+t_irq9:	TRAP_ENTRY_INTERRUPT(9)             /* IRQ SBUS Level 7              */
+t_irq10:TRAP_ENTRY_INTERRUPT(10)            /* IRQ Timer #1 (one we use)     */
+t_irq11:TRAP_ENTRY_INTERRUPT(11)            /* IRQ Floppy Intr.              */
+t_irq12:TRAP_ENTRY_INTERRUPT(12)            /* IRQ Zilog serial chip         */
+t_irq13:TRAP_ENTRY_INTERRUPT(13)            /* IRQ Audio Intr.               */
+t_irq14:TRAP_ENTRY_INTERRUPT(14)            /* IRQ Timer #2                  */
+t_nmi:	NMI_TRAP                            /* Level 15 (NMI)                */
+t_racc:	TRAP_ENTRY(0x20, do_reg_access)     /* General Register Access Error */
+t_iacce:TRAP_ENTRY(0x21, sparc_fault)       /* Instr Access Error    */
+t_bad22:BAD_TRAP(0x22) BAD_TRAP(0x23)
+t_cpdis:TRAP_ENTRY(0x24, do_cp_disabled)    /* Co-Processor Disabled         */
+t_uflsh:TRAP_ENTRY(0x25, do_bad_flush)      /* Unimplemented FLUSH inst.     */
+t_bad26:BAD_TRAP(0x26) BAD_TRAP(0x27)
+t_cpexc:TRAP_ENTRY(0x28, do_cp_exception)   /* Co-Processor Exception        */
+t_dacce:TRAP_ENTRY(0x29, sparc_fault)       /* Data Access Error     */
+t_hwdz:	TRAP_ENTRY(0x2a, do_hw_divzero)     /* Division by zero, you lose... */
+t_dserr:TRAP_ENTRY(0x2b, sparc_fault)       /* Data Store Error      */
+t_daccm:TRAP_ENTRY(0x2c, sparc_fault)       /* Data Access MMU-Miss  */
+t_bad2d:BAD_TRAP(0x2d) BAD_TRAP(0x2e) BAD_TRAP(0x2f) BAD_TRAP(0x30) BAD_TRAP(0x31)
+t_bad32:BAD_TRAP(0x32) BAD_TRAP(0x33) BAD_TRAP(0x34) BAD_TRAP(0x35) BAD_TRAP(0x36)
+t_bad37:BAD_TRAP(0x37) BAD_TRAP(0x38) BAD_TRAP(0x39) BAD_TRAP(0x3a) BAD_TRAP(0x3b)
+t_iaccm:TRAP_ENTRY(0x3c, sparc_fault)       /* Instr Access MMU-Miss */
+t_bad3d:BAD_TRAP(0x3d) BAD_TRAP(0x3e) BAD_TRAP(0x3f) BAD_TRAP(0x40) BAD_TRAP(0x41)
+t_bad42:BAD_TRAP(0x42) BAD_TRAP(0x43) BAD_TRAP(0x44) BAD_TRAP(0x45) BAD_TRAP(0x46)
+t_bad47:BAD_TRAP(0x47) BAD_TRAP(0x48) BAD_TRAP(0x49) BAD_TRAP(0x4a) BAD_TRAP(0x4b)
+t_bad4c:BAD_TRAP(0x4c) BAD_TRAP(0x4d) BAD_TRAP(0x4e) BAD_TRAP(0x4f) BAD_TRAP(0x50)
+t_bad51:BAD_TRAP(0x51) BAD_TRAP(0x52) BAD_TRAP(0x53) BAD_TRAP(0x54) BAD_TRAP(0x55)
+t_bad56:BAD_TRAP(0x56) BAD_TRAP(0x57) BAD_TRAP(0x58) BAD_TRAP(0x59) BAD_TRAP(0x5a)
+t_bad5b:BAD_TRAP(0x5b) BAD_TRAP(0x5c) BAD_TRAP(0x5d) BAD_TRAP(0x5e) BAD_TRAP(0x5f)
+t_bad60:BAD_TRAP(0x60) BAD_TRAP(0x61) BAD_TRAP(0x62) BAD_TRAP(0x63) BAD_TRAP(0x64)
+t_bad65:BAD_TRAP(0x65) BAD_TRAP(0x66) BAD_TRAP(0x67) BAD_TRAP(0x68) BAD_TRAP(0x69)
+t_bad6a:BAD_TRAP(0x6a) BAD_TRAP(0x6b) BAD_TRAP(0x6c) BAD_TRAP(0x6d) BAD_TRAP(0x6e)
+t_bad6f:BAD_TRAP(0x6f) BAD_TRAP(0x70) BAD_TRAP(0x71) BAD_TRAP(0x72) BAD_TRAP(0x73)
+t_bad74:BAD_TRAP(0x74) BAD_TRAP(0x75) BAD_TRAP(0x76) BAD_TRAP(0x77) BAD_TRAP(0x78)
+t_bad79:BAD_TRAP(0x79) BAD_TRAP(0x7a) BAD_TRAP(0x7b) BAD_TRAP(0x7c) BAD_TRAP(0x7d)
+t_bad7e:BAD_TRAP(0x7e) BAD_TRAP(0x7f)
+t_sunos:SUNOS_SYSCALL_TRAP                  /* SunOS System Call             */
+t_sbkpt:BAD_TRAP(0x81)                      /* Software Breakpoint/KGDB      */
+t_divz:	BAD_TRAP(0x82)                      /* Divide by zero trap           */
+t_flwin:TRAP_ENTRY(0x83, do_flush_windows)  /* Flush Windows Trap            */
+t_clwin:BAD_TRAP(0x84)                      /* Clean Windows Trap            */
+t_rchk:	BAD_TRAP(0x85)                      /* Range Check                   */
+t_funal:BAD_TRAP(0x86)                      /* Fix Unaligned Access Trap     */
+t_iovf:	BAD_TRAP(0x87)                      /* Integer Overflow Trap         */
+t_slowl:SOLARIS_SYSCALL_TRAP                /* Slowaris System Call          */
+t_netbs:NETBSD_SYSCALL_TRAP                 /* Net-B.S. System Call          */
+t_bad8a:BAD_TRAP(0x8a) BAD_TRAP(0x8b) BAD_TRAP(0x8c) BAD_TRAP(0x8d) BAD_TRAP(0x8e)
+t_bad8f:BAD_TRAP(0x8f)
+t_linux:LINUX_SYSCALL_TRAP                  /* Linux System Call             */
+t_bad91:BAD_TRAP(0x91) BAD_TRAP(0x92) BAD_TRAP(0x93) BAD_TRAP(0x94) BAD_TRAP(0x95)
+t_bad96:BAD_TRAP(0x96) BAD_TRAP(0x97) BAD_TRAP(0x98) BAD_TRAP(0x99) BAD_TRAP(0x9a)
+t_bad9b:BAD_TRAP(0x9b) BAD_TRAP(0x9c) BAD_TRAP(0x9d) BAD_TRAP(0x9e) BAD_TRAP(0x9f)
+t_getcc:GETCC_TRAP                          /* Get Condition Codes           */
+t_setcc:SETCC_TRAP                          /* Set Condition Codes           */
+t_bada2:BAD_TRAP(0xa2) BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6)
+t_bada7:BAD_TRAP(0xa7) BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab)
+t_badac:BAD_TRAP(0xac) BAD_TRAP(0xad) BAD_TRAP(0xae) BAD_TRAP(0xaf) BAD_TRAP(0xb0)
+t_badb1:BAD_TRAP(0xb1) BAD_TRAP(0xb2) BAD_TRAP(0xb3) BAD_TRAP(0xb4) BAD_TRAP(0xb5)
+t_badb6:BAD_TRAP(0xb6) BAD_TRAP(0xb7) BAD_TRAP(0xb8) BAD_TRAP(0xb9) BAD_TRAP(0xba)
+t_badbb:BAD_TRAP(0xbb) BAD_TRAP(0xbc) BAD_TRAP(0xbd) BAD_TRAP(0xbe) BAD_TRAP(0xbf)
+t_badc0:BAD_TRAP(0xc0) BAD_TRAP(0xc1) BAD_TRAP(0xc2) BAD_TRAP(0xc3) BAD_TRAP(0xc4)
+t_badc5:BAD_TRAP(0xc5) BAD_TRAP(0xc6) BAD_TRAP(0xc7) BAD_TRAP(0xc8) BAD_TRAP(0xc9)
+t_badca:BAD_TRAP(0xca) BAD_TRAP(0xcb) BAD_TRAP(0xcc) BAD_TRAP(0xcd) BAD_TRAP(0xce)
+t_badcf:BAD_TRAP(0xcf) BAD_TRAP(0xd0) BAD_TRAP(0xd1) BAD_TRAP(0xd2) BAD_TRAP(0xd3)
+t_badd4:BAD_TRAP(0xd4) BAD_TRAP(0xd5) BAD_TRAP(0xd6) BAD_TRAP(0xd7) BAD_TRAP(0xd8)
+t_badd9:BAD_TRAP(0xd9) BAD_TRAP(0xda) BAD_TRAP(0xdb) BAD_TRAP(0xdc) BAD_TRAP(0xdd)
+t_badde:BAD_TRAP(0xde) BAD_TRAP(0xdf) BAD_TRAP(0xe0) BAD_TRAP(0xe1) BAD_TRAP(0xe2)
+t_bade3:BAD_TRAP(0xe3) BAD_TRAP(0xe4) BAD_TRAP(0xe5) BAD_TRAP(0xe6) BAD_TRAP(0xe7)
+t_bade8:BAD_TRAP(0xe8) BAD_TRAP(0xe9) BAD_TRAP(0xea) BAD_TRAP(0xeb) BAD_TRAP(0xec)
+t_baded:BAD_TRAP(0xed) BAD_TRAP(0xee) BAD_TRAP(0xef) BAD_TRAP(0xf0) BAD_TRAP(0xf1)
+t_badf2:BAD_TRAP(0xf2) BAD_TRAP(0xf3) BAD_TRAP(0xf4) BAD_TRAP(0xf5) BAD_TRAP(0xf6)
+t_badf7:BAD_TRAP(0xf7) BAD_TRAP(0xf8) BAD_TRAP(0xf9) BAD_TRAP(0xfa) BAD_TRAP(0xfb)
+t_badfc:BAD_TRAP(0xfc) BAD_TRAP(0xfd)
+dbtrap:	BAD_TRAP(0xfe)                      /* Debugger/PROM breakpoint #1   */
+dbtrap2:BAD_TRAP(0xff)                      /* Debugger/PROM breakpoint #2   */	
 
 	.globl	C_LABEL(end_traptable)
 C_LABEL(end_traptable):
@@ -422,8 +185,6 @@
 
 /* This was the only reasonable way I could think of to properly align
  * these page-table data structures.
- *
- * XXX swapper_pg_dir is going to have to be 'per-CPU' for SMP support
  */
 
 	.globl C_LABEL(auxio_reg_addr)
@@ -435,11 +196,15 @@
 	.globl C_LABEL(int_reg_addr)
 C_LABEL(int_reg_addr):		.skip	(PAGE_SIZE*5)
 
+	.globl C_LABEL(bootup_user_stack)
+	.globl C_LABEL(bootup_kernel_stack)
 	.globl C_LABEL(pg0)
 	.globl C_LABEL(empty_bad_page)
 	.globl C_LABEL(empty_bad_page_table)
 	.globl C_LABEL(empty_zero_page)
 	.globl C_LABEL(swapper_pg_dir)
+C_LABEL(bootup_user_stack):		.skip 0x1000
+C_LABEL(bootup_kernel_stack):		.skip 0x1000
 C_LABEL(swapper_pg_dir):		.skip 0x1000
 C_LABEL(pg0):				.skip 0x1000
 C_LABEL(empty_bad_page):		.skip 0x1000
@@ -449,19 +214,7 @@
 
 /* Cool, here we go. Pick up the romvec pointer in %o0 and stash it in
  * %g7 and at prom_vector_p. And also quickly check whether we are on
- * a v0, v2, or v3 prom.  We also get a debug structure of some sort from
- * the boot loader (or is it the prom?) in %o1.  Finally a call back vector
- * is passed in %o2.  I think this is how you register yourself with a
- * debugger.  I do know that it wants my %o7 (return PC - 8) as it's
- * first argument.  I will poke around and figure out what the debug
- * vector is, it could contain useful stuff.
- */
-
-/* Grrr, in order to be Sparc ABI complient, the kernel has to live in
- * an address space above 0xe0000000  ;(  Must remain position independant
- * until we 'remap' ourselves from low to high addresses.  We only map the
- * first 3MB of addresses into upper ram as that is how much the PROM
- * promises to set up for us.
+ * a v0, v2, or v3 prom.
  */
 gokernel:
 		/* Ok, it's nice to know, as early as possible, if we
@@ -477,31 +230,28 @@
 
 		/* XXX Sparc V9 detection goes here XXX */
 
-		or	%g0, %o7, %g4		! Save %o7
+		mov	%o7, %g4		! Save %o7
 
 		/* Jump to it, and pray... */
 current_pc:
 		call	1f
-		nop
+		 nop
 
 1:
-		or	%g0, %o7, %g3
+		mov	%o7, %g3
 
 got_pc:
-		or	%g0, %g4, %o7	/* Previous %o7. */
+		mov	%g4, %o7		/* Previous %o7. */
 	
-		or	%g0, %o0, %l0		! stash away romvec
-		or	%g0, %o0, %g7		! put it here too
-		or	%g0, %o1, %l1		! stash away debug_vec too
-		rd	%psr, %l2		! Save psr
-		rd	%wim, %l3		! wim
-		rd	%tbr, %l4		! tbr
-		or	%g0, %o2, %l5		! and the possible magic func
+		mov	%o0, %l0		! stash away romvec
+		mov	%o0, %g7		! put it here too
+		mov	%o1, %l1		! stash away debug_vec too
 
 		/* Ok, let's check out our run time program counter. */
 		set	current_pc, %g5
 		cmp	%g3, %g5
 		be	already_mapped
+		 nop 
 
 		/* %l6 will hold the offset we have to subtract
 		 * from absolute symbols in order to access areas
@@ -511,10 +261,10 @@
 		 */
 		set	PAGE_OFFSET, %l6
 		b	copy_prom_lvl14
-		nop
+		 nop
 
 already_mapped:
-		or	%g0, %g0, %l6
+		mov	0, %l6
 
 		/* Copy over the Prom's level 14 clock handler. */
 copy_prom_lvl14:
@@ -544,46 +294,6 @@
 		ldd	[%g2 + 0x18], %g4
 		std	%g4, [%g3 + 0x18]
 
-copy_prom_done:
-		ld	[%o0 + 0x4], %g1
-		and	%g1, 0x3, %g1
-		subcc	%g1, 0x0, %g0
-		be	set_sane_psr		! Not on v0 proms
-		nop
-
-		subcc	%o2, 0x0, %g0		! check for boot routine pointer
-		bz	set_sane_psr
-		nop
-		jmpl    %o2, %o7		! call boot setup func
-		add	%o7, 0x8, %o0
-
-set_sane_psr:
-		/* Traps are on, kadb can be tracing through here.  But
-		 * we have no clue what the PIL is. So we set up a sane
-		 * %psr, but preserve CWP or our locals could disappear!
-		 */
-		rd	%psr, %g2
-		and	%g2, 0x1f, %g2			! %g2 has CWP now
-		set	(PSR_S|PSR_PIL), %g1		! Supervisor + PIL high
-		or	%g1, %g2, %g1			! mix mix mix
-		wr	%g1, 0x0, %psr			! let PIL set in
-		wr	%g1, PSR_ET, %psr		! now turn on traps
-
-		/* A note about the last two instructions...
-		 * If you are going to increase PIL and turn on
-		 * traps at the same time you are asking for trouble.
-		 * You MUST set a %psr with traps off containing
-		 * your new PIL, then turn on the ET bit with the
-		 * next write.  On certain buggy Sparc chips if you
-		 * set both at the same time you can get a Watchdog
-		 * Reset under certain conditions.  This is no fun.
-		 * Basically the PIL bits get there before the
-		 * EnableTrap bit does or something like that.
-		 */
-
-		/* Insane asylum... */
-		WRITE_PAUSE
-
 /* Must determine whether we are on a sun4c MMU, SRMMU, or SUN4/400 MUTANT
  * MMU so we can remap ourselves properly.  DONT TOUCH %l0 thru %l5 in these
  * remapping routines, we need their values afterwards!
@@ -593,27 +303,28 @@
 		/* Now check whether we are already mapped, if we
 		 * are we can skip all this garbage coming up.
 		 */
-		subcc	%l6, 0x0, %g0
-		bz	go_to_highmem		! this will be a nop then
-		nop
+copy_prom_done:
+		cmp	%l6, 0
+		be	go_to_highmem		! this will be a nop then
+		 nop
 
-		sethi	%hi(LOAD_ADDR), %g6
-		subcc	%g7, %g6, %g0
+		set	LOAD_ADDR, %g6
+		cmp	%g7, %g6
 		bne	remap_not_a_sun4	! This is not a Sun4
-		nop
+		 nop
 
 		or	%g0, 0x1, %g1
 		lduba	[%g1] ASI_CONTROL, %g1	! Only safe to try on Sun4.
 		subcc	%g1, 0x24, %g0		! Is this a mutant Sun4/400???
 		be	sun4_mutant_remap	! Ugh, it is...
-		nop
+		 nop
 
 remap_not_a_sun4:
 		lda	[%g0] ASI_M_MMUREGS, %g1 ! same as ASI_PTE on sun4c
 		and	%g1, 0x1, %g1		! Test SRMMU Enable bit ;-)
-		subcc	%g1, 0x0, %g0
-		bz	sun4c_remap		! A sun4c MMU or normal Sun4
-		nop
+		cmp	%g1, 0x0
+		be	sun4c_remap		! A sun4c MMU or normal Sun4
+		 nop
 srmmu_remap:
 		/* First, check for a viking (TI) module. */
 		set	0x40000000, %g2
@@ -621,7 +332,7 @@
 		and	%g2, %g3, %g3
 		subcc	%g3, 0x0, %g0
 		bz	srmmu_nviking
-		nop
+		 nop
 
 		/* Figure out what kind of viking we are on.
 		 * We need to know if we have to play with the
@@ -636,7 +347,7 @@
 		and	%g2, %g3, %g3
 		subcc	%g3, 0x0, %g0
 		bnz	srmmu_nviking			! is in mbus mode
-		nop
+		 nop
 		
 		rd	%psr, %g3			! DONT TOUCH %g3
 		andn	%g3, PSR_ET, %g2
@@ -702,7 +413,7 @@
 		 * place to another...  Jump to high memory.
 		 */
 		b	go_to_highmem
-		nop
+		 nop
 
 		/* This works on viking's in Mbus mode and all
 		 * other MBUS modules.  It is virtually the same as
@@ -721,7 +432,7 @@
 		add	%g1, 0x3c0, %g3			! XXX AWAY WITH IMPERICALS
 		sta	%g2, [%g3] ASI_M_BYPASS		! place at KERNBASE entry
 		b	go_to_highmem
-		nop					! wheee....
+		 nop					! wheee....
 
 		/* This remaps the kernel on Sun4/4xx machines
 		 * that have the Sun Mutant Three Level MMU.
@@ -754,18 +465,16 @@
 		add	%g4, %l6, %g4		! Move up high memory ptr
 		subcc	%g3, %g5, %g0		! Reached our limit?
 		blu	sun4_mutant_loop	! Nope, loop again
-		add	%g3, %l6, %g3		! delay, Move up low ptr
+		 add	%g3, %l6, %g3		! delay, Move up low ptr
 		b	go_to_highmem		! Jump to high memory.
-		nop
+		 nop
 
 /* The following works for normal (ie. non Sun4/400) Sun4 MMU's */
 sun4c_remap:
-		or	%g0, %g0, %g3		! source base
-		sethi	%hi(KERNBASE), %g4	! destination base
-		or	%g4, %lo(KERNBASE), %g4
-		sethi	%hi(0x300000), %g5
-		or	%g5, %lo(0x300000), %g5	! upper bound 3MB
-		or	%g0, 0x1, %l6
+		mov	0, %g3			! source base
+		set	KERNBASE, %g4		! destination base
+		set	0x300000, %g5		! upper bound 3MB
+		mov	1, %l6
 		sll	%l6, 18, %l6		! sun4c mmu segmap size
 sun4c_remap_loop:
 		lda	[%g3] ASI_SEGMAP, %g6	! load phys_seg
@@ -773,20 +482,20 @@
 		add	%g3, %l6, %g3		! Increment source ptr
 		subcc	%g3, %g5, %g0		! Reached limit?
 		bl	sun4c_remap_loop	! Nope, loop again
-		add	%g4, %l6, %g4		! delay, Increment dest ptr
+		 add	%g4, %l6, %g4		! delay, Increment dest ptr
 
 /* Now do a non-relative jump so that PC is in high-memory */
 go_to_highmem:
 		set	execute_in_high_mem, %g1
-		jmp	%g1
-		nop
+		jmpl	%g1, %g0
+		 nop
 
 /* Acquire boot time privileged register values, this will help debugging.
  * I figure out and store nwindows and nwindowsm1 later on.
  */
 execute_in_high_mem:
-		or	%g0, %l0, %o0		! put back romvec
-		or	%g0, %l1, %o1		! and debug_vec
+		mov	%l0, %o0		! put back romvec
+		mov	%l1, %o1		! and debug_vec
 
 		sethi	%hi( C_LABEL(prom_vector_p) ), %g1
 		st	%o0, [%g1 + %lo( C_LABEL(prom_vector_p) )]
@@ -797,14 +506,14 @@
 		ld	[%o0 + 0x4], %o3
 		and	%o3, 0x3, %o5			! get the version
 
-		subcc	%o3, 0x2, %g0			! a v2 prom?
+		cmp	%o3, 0x2			! a v2 prom?
 		be	found_version
-		nop
+		 nop
 
 		/* paul@sfe.com.au */
-		subcc	%o3, 0x3, %g0			! a v3 prom?
+		cmp	%o3, 0x3			! a v3 prom?
 		be	found_version
-		nop
+		 nop
 
 /* Old sun4's pass our load address into %o0 instead of the prom
  * pointer. On sun4's you have to hard code the romvec pointer into
@@ -812,33 +521,21 @@
  * trust their own "OpenBoot" specifications.
  */
 
-		sethi	%hi(LOAD_ADDR), %g6
-		subcc	%o0, %g6, %g0		! an old sun4?
+		set	LOAD_ADDR, %g6
+		cmp	%o0, %g6		! an old sun4?
 		be	no_sun4_here
-		nop
+		 nop
 
 found_version:
 
-/* Get the machine type via the mysterious romvec node operations.
- * Here we can find out whether we are on a sun4, sun4c, sun4m, 
- * sun4d, or a sun4e. The "nodes" are set up as a bunch of n-ary trees 
- * which you can traverse to get information about devices and such.
- * The information acquisition happens via the node-ops which are
- * defined in the openprom.h header file. Of particular interest
- * is the 'nextnode(int node)' function as it does the smart thing when
- * presented with a value of '0', it gives you the root node in the
- * tree. These node integers probably offset into some internal prom
- * pointer table the openboot has. It's completely undocumented, so
- * I'm not about to go sifting through the prom address space, but may
- * do so if I get suspicious enough. :-)
- */
+/* Get the machine type via the mysterious romvec node operations. */
 
 		or	%g0, %g7, %l1
 		add	%l1, 0x1c, %l1		
 		ld	[%l1], %l0
 		ld	[%l0], %l0
 		call 	%l0
-		or	%g0, %g0, %o0		! next_node(0) = first_node
+		 or	%g0, %g0, %o0		! next_node(0) = first_node
 		or	%o0, %g0, %g6
 
 		sethi	%hi( C_LABEL(cputypvar) ), %o1	! First node has cpu-arch
@@ -848,13 +545,13 @@
 		ld	[%l1], %l0		! 'compatibility' tells
 		ld	[%l0 + 0xc], %l0	! that we want 'sun4x' where
 		call	%l0			! x is one of '', 'c', 'm',
-		nop				! 'd' or 'e'. %o2 holds pointer
+		 nop				! 'd' or 'e'. %o2 holds pointer
 						! to a buf where above string
 						! will get stored by the prom.
 
 		subcc	%o0, %g0, %g0
 		bpos	got_prop		! Got the property
-		nop
+		 nop
 
 		or	%g6, %g0, %o0
 		sethi	%hi( C_LABEL(cputypvar_sun4m) ), %o1
@@ -864,55 +561,47 @@
 		ld	[%l1], %l0
 		ld	[%l0 + 0xc], %l0
 		call	%l0
-		nop
+		 nop
 
 got_prop:
-		sethi	%hi( C_LABEL(cputypval) ), %o2
-		or	%o2, %lo( C_LABEL(cputypval) ), %o2
-
+		set	C_LABEL(cputypval), %o2
 		ldub	[%o2 + 0x4], %l1
-		subcc	%l1, 'c', %g0		! We already know we are not
+
+		cmp	%l1, 'c'		! We already know we are not
 		be	1f			! on a plain sun4 because of
-		nop				! the check for 0x4000 in %o0
-		subcc	%l1, 'm', %g0		! at start
+		 nop				! the check for 0x4000 in %o0
+
+		cmp	%l1, 'm'		! at start
 		be	1f
-		nop
+		 nop
 
-		subcc	%l1, 'd', %g0
+		cmp	%l1, 'd'
 		be	no_sun4d_here		! God bless the person who
-		nop				! tried to run this on sun4d.
+		 nop				! tried to run this on sun4d.
 	
-		subcc	%l1, 'e', %g0
+		cmp	%l1, 'e'
 		be	no_sun4e_here		! Could be a sun4e.
-		nop
+		 nop
 
 		b	no_sun4u_here		! AIEEE, a V9 sun4u...
-		nop
+		 nop
 
 
 1:
-		or	%g0, PAGE_SHIFT, %g5
-
-		sethi	%hi( C_LABEL(cputypval) ), %l1
-		or	%l1, %lo( C_LABEL(cputypval) ), %l1
+		set	C_LABEL(cputypval), %l1
 		ldub	[%l1 + 0x4], %l1
-		subcc	%l1, 'm', %g0           ! Test for sun4d, sun4e ?
+		cmp	%l1, 'm'		! Test for sun4d, sun4e ?
 		be	sun4m_init
-		nop
+		 nop
 
-		sethi	%hi(AC_CONTEXT), %g1	! kernel context, safe now
-						! the only valid context
-						! until we call paging_init()
+		/* Jump into mmu context zero. */
+		set	AC_CONTEXT, %g1
 		stba	%g0, [%g1] ASI_CONTROL
 
 		b	sun4c_continue_boot
-		nop
+		 nop
 
 sun4m_init:
-/* P3: I just do not know what to do here. But I do know that ASI_CONTROL
- * will not serve on sun4m. Also I do not want to smash the current MMU
- * setup until we call paging_init().
- */
 
 /* Ok, the PROM could have done funny things and apple cider could still
  * be sitting in the fault status/address registers.  Read them all to
@@ -920,22 +609,28 @@
  */
 /* This sucks, aparently this makes Vikings call prom panic, will fix later */
 
-		set	(0x40000000), %o1
-		rd	%psr, %o0
-		andcc	%o0, %o1, %g0
-		bne	sun4c_continue_boot	! quick hack
-		nop
+		rd	%psr, %o1
+		srl	%o1, 28, %o1		! Get a type of the CPU
+
+		subcc	%o1, 4, %g0		! TI: Viking or MicroSPARC
+		be	sun4c_continue_boot
+		 nop
 
-clr_srmmu_fregs:
 		set	AC_M_SFSR, %o0
 		lda	[%o0] ASI_M_MMUREGS, %g0
 		set	AC_M_SFAR, %o0
 		lda	[%o0] ASI_M_MMUREGS, %g0
+
+		/* Fujitsu MicroSPARC-II has no asynchronous flavors of FARs */
+		subcc	%o1, 0, %g0
+		be	sun4c_continue_boot
+		 nop
+
 		set	AC_M_AFSR, %o0
 		lda	[%o0] ASI_M_MMUREGS, %g0
 		set	AC_M_AFAR, %o0
 		lda	[%o0] ASI_M_MMUREGS, %g0
-		nop
+		 nop
 
 
 sun4c_continue_boot:
@@ -948,141 +643,133 @@
 		sethi	%hi( C_LABEL(cputyp) ), %o0
 		st	%g4, [%o0 + %lo( C_LABEL(cputyp) )]
 
-		/* Turn on PreviousSupervisor, Supervisor, EnableFloating,
-		 * and all the PIL bits.  Also puts us in register window
-		 * zero.
+		/* Turn on Supervisor, EnableFloating, and all the PIL bits.
+		 * Also puts us in register window zero with traps off.
 		 */
-		sethi	%hi(PSR_PS | PSR_S | PSR_PIL | PSR_EF), %g2
-		or	%g2, %lo(PSR_PS | PSR_S | PSR_PIL | PSR_EF), %g2
+		set	(PSR_PS | PSR_S | PSR_PIL | PSR_EF), %g2
 		wr	%g2, 0x0, %psr
 		WRITE_PAUSE
 
-		wr	%g0, 0x2, %wim		! Make window 1 invalid.
-		WRITE_PAUSE
-
-		/* Initialize the WIM value for init_task. */
-		or	%g0, 0x1, %g1
-		sethi	%hi( C_LABEL(current) + THREAD_WIM), %g2
-		st	%g1, [%g2 + %lo( C_LABEL(current) + THREAD_WIM)]
-
-/* I want a kernel stack NOW! */
-/* Grrr, gotta be real careful about alignment here */
-
-		set	( C_LABEL(init_user_stack) + PAGE_SIZE - 96 - 96 - 80), %g1
-		andn	%g1, 0x7, %g1
-		or	%g1, 0x0, %fp
-		add	%fp, (96+80), %sp
-
-		/* Enable traps. */
-		rd	%psr, %l0
-		wr	%l0, PSR_ET, %psr
-		WRITE_PAUSE
-
-/*
- * Maybe the prom zeroes out our BSS section, maybe it doesn't. I certainly 
- * don't know, do you?
- */
+		/* I want a kernel stack NOW! */
+		set	C_LABEL(bootup_user_stack), %g1
+		add	%g1, (PAGE_SIZE - STACKFRAME_SZ - TRACEREG_SZ), %sp
+		mov	0, %fp			/* And for good luck */
 
+		/* Zero out our BSS section. */
 		set	C_LABEL(edata) , %o0	! First address of BSS
 		set	C_LABEL(end) , %o1	! Last address of BSS
-
-		/* Argh, ELF gets me again... */
-		andn	%o0, 0x3, %o0
-		andn	%o1, 0x3, %o1
-
-/* Friggin' bzero() kludge. */
-
+		add	%o0, 0x1, %o0
 1:	
-		st	%g0, [%o0]
-		add	%o0, 0x4, %o0
+		stb	%g0, [%o0]
 		subcc	%o0, %o1, %g0
 		bl	1b
-		nop
+		 add	%o0, 0x1, %o0
+
+		/* Initialize the umask value for init_task just in case.
+		 * But first make current_set[0] point to something useful.
+		 */
+		set	C_LABEL(init_task), %g4
+		set	C_LABEL(current_set), %g2
+		st	%g4, [%g2]
+
+		/* So now this should work. */
+		LOAD_CURRENT(g2)
+		set	C_LABEL(bootup_kernel_stack), %g4
+		st	%g4, [%g2 + TASK_KSTACK_PG]
+		st	%g0, [%g2 + THREAD_UMASK]
 
 /* Compute NWINDOWS and stash it away. Now uses %wim trick explained
  * in the V8 manual. Ok, this method seems to work, Sparc is cool...
  * No, it doesn't work, have to play the save/readCWP/restore trick.
  */
 
-		rd	%wim, %g1
-		rd	%psr, %g2
 		wr	%g0, 0x0, %wim			! so we dont get a trap
-		andn	%g2, 0x1f, %g3
-		wr	%g3, 0x0, %psr
 		WRITE_PAUSE
+
 		save
+
 		rd	%psr, %g3
+
 		restore
+
 		and	%g3, 0x1f, %g3
 		add	%g3, 0x1, %g3
-		wr	%g2, 0x0, %psr
-		wr	%g1, 0x0, %wim
 
-		cmp	%g3, 0x7
-		bne,a	2f
-		sethi	%hi( C_LABEL(nwindows) ), %g4
+		mov	2, %g1
+		wr	%g1, 0x0, %wim			! make window 1 invalid
+		WRITE_PAUSE
 
+		cmp	%g3, 0x7
+		bne	2f
+		 nop
 
-		/* Nop out one save and one restore in the save state code
-		 * and system call entry if this is a seven window Sparc.
+		/* Adjust our window handling routines to
+		 * do things correctly on 7 window Sparcs.
 		 */
-		sethi	%hi(nop7), %g5
-		or	%g5, %lo(nop7), %g5
-		sethi	%hi(NOP_INSN), %g6
-		or	%g6, %lo(NOP_INSN), %g6
-		/* patch 1 */
-		st	%g6, [%g5]
-		st	%g6, [%g5 + 0x4]
-		sethi	%hi(rnop7), %g5
-		or	%g5, %lo(rnop7), %g5
-		/* patch 2 */
-		st	%g6, [%g5]
-		st	%g6, [%g5 + 0x4]
 
-		sethi	%hi( C_LABEL(nwindows) ), %g4
+#define		PATCH_INSN(src, dest) \
+		set	src, %g5; \
+		set	dest, %g6; \
+		ld	[%g5], %g4; \
+		st	%g4, [%g6];
+	
+		/* Patch for window spills... */
+		PATCH_INSN(spnwin_patch1_7win, spnwin_patch1)
+		PATCH_INSN(spnwin_patch2_7win, spnwin_patch2)
+		PATCH_INSN(spnwin_patch3_7win, spnwin_patch3)
+
+		/* Patch for window fills... */
+		PATCH_INSN(fnwin_patch1_7win, fnwin_patch1)
+		PATCH_INSN(fnwin_patch2_7win, fnwin_patch2)
+
+		/* Patch for trap entry setup... */
+		PATCH_INSN(tsetup_7win_patch1, tsetup_patch1)
+		PATCH_INSN(tsetup_7win_patch2, tsetup_patch2)
+		PATCH_INSN(tsetup_7win_patch3, tsetup_patch3)
+		PATCH_INSN(tsetup_7win_patch4, tsetup_patch4)
+		PATCH_INSN(tsetup_7win_patch5, tsetup_patch5)
+		PATCH_INSN(tsetup_7win_patch6, tsetup_patch6)
+
+		/* Patch for returning from traps... */
+		PATCH_INSN(rtrap_7win_patch1, rtrap_patch1)
+		PATCH_INSN(rtrap_7win_patch2, rtrap_patch2)
+		PATCH_INSN(rtrap_7win_patch3, rtrap_patch3)
+		PATCH_INSN(rtrap_7win_patch4, rtrap_patch4)
+		PATCH_INSN(rtrap_7win_patch5, rtrap_patch5)
 
 2:		
+		sethi	%hi( C_LABEL(nwindows) ), %g4
 		st	%g3, [%g4 + %lo( C_LABEL(nwindows) )]	! store final value
 		sub	%g3, 0x1, %g3
 		sethi	%hi( C_LABEL(nwindowsm1) ), %g4
 		st	%g3, [%g4 + %lo( C_LABEL(nwindowsm1) )]
 
-		/* Initialize lnx_winmask. */
-		set	lnx_winmask, %g4
-		or	%g0, 0x2, %g5
-		or	%g0, 0x0, %g6
-msk_loop:
-		stb	%g5, [%g4 + %g6]
-		add	%g6, 0x1, %g6
-		cmp	%g6, %g3
-		bl,a	msk_loop
-		sll	%g5, 0x1, %g5
-		or	%g0, 0x1, %g5
-		stb	%g5, [%g4 + %g3]
-
-		/* Here we go */
+		/* Here we go, start using Linux's trap table... */
 		set	C_LABEL(trapbase), %g3
 		wr	%g3, 0x0, %tbr
 		WRITE_PAUSE
 
+		/* Finally, turn on traps so that we can call c-code. */
+		rd	%psr, %g3
+		wr	%g3, 0x0, %psr
+		wr	%g3, PSR_ET, %psr
+		WRITE_PAUSE
 
-/* First we call prom_init() to set up PROMLIB, then off to start_kernel() */
-/* XXX put this in setup_arch() */
+		/* First we call prom_init() to set up PROMLIB, then
+		 * off to start_kernel().
+		 */
 
 		sethi	%hi( C_LABEL(prom_vector_p) ), %g5
-		call	C_LABEL(prom_init)
 		ld	[%g5 + %lo( C_LABEL(prom_vector_p) )], %o0
-
-		subcc	%o0, 0x1, %g0
-		be	halt_me			! promlib init failed
-		nop
+		call	C_LABEL(prom_init)
+		 nop
 
 		call 	C_LABEL(start_kernel)
-		nop
+		 nop
 	
 		/* We should not get here. */
 		call	halt_me
-		nop
+		 nop
 
 /* There, happy now Adrian? */
 
@@ -1092,39 +779,39 @@
 		ld	[%o1 + %lo(SUN4_PROM_VECTOR+SUN4_PRINTF)], %o1
 		set	sun4_notsup, %o0
 		call	%o1
-		nop
+		 nop
 1:
 		ba	1b			! Cannot exit into KMON
-		nop
+		 nop
 
 no_sun4d_here:
 		ld	[%g7 + 0x68], %o1
 		set	sun4d_notsup, %o0
 		call	%o1
-		nop
+		 nop
 		b	halt_me
-		nop
+		 nop
 
 no_sun4e_here:
 		ld	[%g7 + 0x68], %o1
 		set	sun4e_notsup, %o0
 		call	%o1
-		nop
+		 nop
 		b	halt_me
-		nop
+		 nop
 
 no_sun4u_here:
 		ld	[%g7 + 0x68], %o1
 		set	sun4u_notsup, %o0
 		call	%o1
-		nop
+		 nop
 		b	halt_me
-		nop
+		 nop
 
 halt_me:
 		ld	[%g7 + 0x74], %o0
 		call	%o0			! Get us out of here...
-		nop				! Apparently Solaris is better.
+		 nop				! Apparently Solaris is better.
 
 	.data
 	.align 4
@@ -1135,30 +822,28 @@
  * gets initialized in c-code so all routines can use it.
  */
 
-			.globl C_LABEL(prom_vector_p)
-C_LABEL(prom_vector_p):	.skip 4
-
-	.align 4
+	.globl	C_LABEL(prom_vector_p)
+C_LABEL(prom_vector_p):
+		.word 0
 
 /* We calculate the following at boot time, window fills/spills and trap entry
  * code uses these to keep track of the register windows.
  */
 
-	.globl C_LABEL(nwindows)
-	.globl C_LABEL(nwindowsm1)
-C_LABEL(nwindows):	.skip 4
-C_LABEL(nwindowsm1):	.skip 4
-
 	.align 4
+	.globl	C_LABEL(nwindows)
+	.globl	C_LABEL(nwindowsm1)
+C_LABEL(nwindows):
+	.word	8
+C_LABEL(nwindowsm1):
+	.word	7
 
 /* Boot time debugger vector value.  We need this later on. */
 
-	.globl C_LABEL(linux_dbvec)
-C_LABEL(linux_dbvec):		.skip 4
-
 	.align 4
+	.globl	C_LABEL(linux_dbvec)
+C_LABEL(linux_dbvec):
+	.word	0
+	.word	0
 
-/* Just to get the kernel through the compiler for now */
-	.globl C_LABEL(floppy_track_buffer)
-C_LABEL(floppy_track_buffer):
-	.fill 512*2*36,1,0
+	.align 4
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/kernel/idprom.c linux/arch/sparc/kernel/idprom.c
--- v1.3.43/linux/arch/sparc/kernel/idprom.c	Tue Jun 27 14:11:31 1995
+++ linux/arch/sparc/kernel/idprom.c	Sat Nov 25 02:58:06 1995
@@ -1,4 +1,5 @@
-/* idprom.c: Routines to load the idprom into kernel addresses and
+/* $Id: idprom.c,v 1.18 1995/11/25 00:58:05 davem Exp $
+ * idprom.c: Routines to load the idprom into kernel addresses and
  *           interpret the data contained within.
  *
  * Because they use the IDPROM's machine type field, some of the
@@ -8,8 +9,8 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/types.h>
 
-#include <asm/types.h>
 #include <asm/oplib.h>
 #include <asm/idprom.h>
 #include <asm/machines.h>  /* Fun with Sun released architectures. */
@@ -77,8 +78,8 @@
 	sparc_display_systype(idprom->id_machtype);
 
 	printk("Ethernet address: %x:%x:%x:%x:%x:%x\n",
-	       idprom->id_eaddr[0], idprom->id_eaddr[1], idprom->id_eaddr[2],
-	       idprom->id_eaddr[3], idprom->id_eaddr[4], idprom->id_eaddr[5]);
+		    idprom->id_eaddr[0], idprom->id_eaddr[1], idprom->id_eaddr[2],
+		    idprom->id_eaddr[3], idprom->id_eaddr[4], idprom->id_eaddr[5]);
 
 	return;
 }
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/kernel/ioport.c linux/arch/sparc/kernel/ioport.c
--- v1.3.43/linux/arch/sparc/kernel/ioport.c	Tue Jun 27 14:11:31 1995
+++ linux/arch/sparc/kernel/ioport.c	Sat Nov 25 02:58:08 1995
@@ -1,4 +1,5 @@
-/* ioport.c:  Simple io mapping allocator.
+/* $Id: ioport.c,v 1.12 1995/11/25 00:58:07 davem Exp $
+ * ioport.c:  Simple io mapping allocator.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
@@ -17,10 +18,13 @@
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/ioport.h>
+#include <linux/mm.h>
 
 #include <asm/io.h>
 #include <asm/vaddrs.h>
 #include <asm/oplib.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
 
 /* This points to the next to use virtual memory for io mappings */
 static long next_free_region = IOBASE_VADDR;
@@ -48,25 +52,26 @@
 {
 	unsigned long vaddr, base_address;
 	unsigned long addr = (unsigned long) address;
-
+	unsigned long offset = (addr & (~PAGE_MASK));
 
 	if (virtual){
 		vaddr = (unsigned long) virtual;
 	} else {
 		vaddr = next_free_region;
 	}
-	
+		
+	len += offset;
 	if (((unsigned long) virtual + len) > (IOBASE_VADDR + IOBASE_LEN)){
 		printk ("alloc_io: Mapping ouside IOBASE area\n");
 		prom_halt ();
 	}
-	if (check_region (vaddr, len)){
+	if (check_region ((vaddr | offset), len)){
 		printk ("alloc_io: 0x%lx is already in use\n", vaddr);
 		prom_halt ();
 	}
 
 	/* Tell Linux resource manager about the mapping */
-	request_region (vaddr, len, name);
+	request_region ((vaddr | offset), len, name);
 
 	base_address = vaddr;
 	/* Do the actual mapping */
@@ -77,10 +82,18 @@
 		if (!virtual)
 			next_free_region += PAGE_SIZE;
 	}
-	return (void *) base_address;
+	return (void *) (base_address | offset);
 }
 
-/* Does DVMA allocations with PAGE_SIZE granulatity */
+/* Does DVMA allocations with PAGE_SIZE granulatity.  How this basically
+ * works is that the ESP chip can do DVMA transfers at ANY address with
+ * certain size and boundry restrictions.  But other devices that are
+ * attached to it and would like to do DVMA have to set things up in
+ * a special way, if the DVMA see's a device attached to it transfer data
+ * at addresses above DVMA_VADDR it will grab them, this way it does not
+ * now have to know the peculiarities of where to read the Lance data
+ * from. (for example)
+ */
 void *sparc_dvma_malloc (int len, char *name)
 {
 	unsigned long vaddr, base_address;
@@ -95,17 +108,15 @@
 		prom_halt ();
 	}
 
-	/* Tell Linux resource manager about the mapping */
-	request_region (vaddr, len, name);
-
+	/* Basically these can be mapped just like any old
+	 * IO pages, cacheable bit off, etc.  The physical
+	 * pages are pre-mapped in paging_init()
+	 */
 	base_address = vaddr;
-	/* Assign the memory area and remove the cache bit */
-	/* XXX EWWWWEE!!  Sun4c specific, fix now! XXX */
-	for (; len > 0; len -= PAGE_SIZE){
-		printk ("Len=%d\n", len);
-		put_pte (vaddr, get_pte (vaddr) | PTE_NC);
-		vaddr += PAGE_SIZE;
-		dvma_next_free += PAGE_SIZE;
-	}
+	/* Assign the memory area. */
+	dvma_next_free = PAGE_ALIGN(dvma_next_free+len);
+
+	request_region(base_address, len, name);
+
 	return (void *) base_address;
 }
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/kernel/irq.c linux/arch/sparc/kernel/irq.c
--- v1.3.43/linux/arch/sparc/kernel/irq.c	Tue Jun 27 14:11:31 1995
+++ linux/arch/sparc/kernel/irq.c	Sat Nov 25 02:58:10 1995
@@ -1,4 +1,5 @@
-/*  arch/sparc/kernel/irq.c:  Interrupt request handling routines. On the
+/*  $Id: irq.c,v 1.29 1995/11/25 00:58:08 davem 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
  *                            node trees to find out who's got which IRQ.
@@ -8,19 +9,6 @@
  *  Copyright (C) 1995 Pete A. Zaitcev (zaitcev@jamica.lab.ipmce.su)
  */
 
-/*
- * IRQ's are in fact implemented a bit like signal handlers for the kernel.
- * The same sigaction struct is used, and with similar semantics (ie there
- * is a SA_INTERRUPT flag etc). Naturally it's not a 1:1 relation, but there
- * are similarities.
- *
- * sa_handler(int irq_NR) is the default function called (0 if no).
- * sa_mask is horribly ugly (I won't even mention it)
- * sa_flags contains various info: SA_INTERRUPT etc
- * sa_restorer is the unused
- */
-
-#include <linux/config.h>
 #include <linux/ptrace.h>
 #include <linux/errno.h>
 #include <linux/linkage.h>
@@ -37,38 +25,28 @@
 #include <asm/timer.h>
 #include <asm/openprom.h>
 #include <asm/oplib.h>
+#include <asm/traps.h>
 #include <asm/irq.h>
 #include <asm/io.h>
 
 /* Pointer to the interrupt enable byte */
-/* XXX Ugh, this is so sun4c specific it's driving me nuts. XXX */
 unsigned char *interrupt_enable = 0;
 struct sun4m_intregs *sun4m_interrupts;
 
-/* XXX Needs to handle Sun4m semantics XXX */
 void
-disable_irq(unsigned int irq_nr)
+sun4c_disable_irq(unsigned int irq_nr)
 {
 	unsigned long flags;
 	unsigned char current_mask, new_mask;
 
-	if(sparc_cpu_model != sun4c) return;
-
-	save_flags(flags);
-	cli();
-
+	if(sparc_cpu_model != sun4c)
+		return;
+	save_flags(flags); cli();
 	current_mask = *interrupt_enable;
-
 	switch(irq_nr) {
 	case 1:
 		new_mask = ((current_mask) & (~(SUN4C_INT_E1)));
 		break;
-	case 4:
-		new_mask = ((current_mask) & (~(SUN4C_INT_E4)));
-		break;
-	case 6:
-		new_mask = ((current_mask) & (~(SUN4C_INT_E6)));
-		break;
 	case 8:
 		new_mask = ((current_mask) & (~(SUN4C_INT_E8)));
 		break;
@@ -79,42 +57,49 @@
 		new_mask = ((current_mask) & (~(SUN4C_INT_E14)));
 		break;
 	default:
-#if 0 /* Actually this is safe, as the floppy driver needs this */
-		printk("AIEEE, Illegal interrupt disable requested irq=%d\n", 
-		       (int) irq_nr);
-		prom_halt();
-#endif
-		break;
+		restore_flags(flags);
+		return;
 	};
   
+	*interrupt_enable = new_mask;
 	restore_flags(flags);
-	return;
 }
 
-/* XXX Needs to handle sun4m semantics XXX */
 void
-enable_irq(unsigned int irq_nr)
+sun4m_disable_irq(unsigned int irq_nr)
 {
-	unsigned long flags;
-	unsigned char current_mask, new_mask;
+	printk("IRQ routines not yet written for the sun4m\n");
+	panic("disable_irq: Unsupported arch.");
+}
 
-	if(sparc_cpu_model != sun4c) return;
+void
+disable_irq(unsigned int irq_nr)
+{
+	switch(sparc_cpu_model) {
+	case sun4c:
+		sun4c_disable_irq(irq_nr);
+		break;
+	case sun4m:
+		sun4m_disable_irq(irq_nr);
+	default:
+		panic("disable_irq: Unsupported arch.");
+	}
+}
 
-	save_flags(flags);
-	cli();
+void
+sun4c_enable_irq(unsigned int irq_nr)
+{
+	unsigned long flags;
+	unsigned char current_mask, new_mask;
 
+	if(sparc_cpu_model != sun4c)
+		return;
+	save_flags(flags); cli();
 	current_mask = *interrupt_enable;
-
 	switch(irq_nr) {
 	case 1:
 		new_mask = ((current_mask) | SUN4C_INT_E1);
 		break;
-	case 4:
-		new_mask = ((current_mask) | SUN4C_INT_E4);
-		break;
-	case 6:
-		new_mask = ((current_mask) | SUN4C_INT_E6);
-		break;
 	case 8:
 		new_mask = ((current_mask) | SUN4C_INT_E8);
 		break;
@@ -125,19 +110,34 @@
 		new_mask = ((current_mask) | SUN4C_INT_E14);
 		break;
 	default:
-#if 0  /* Floppy driver does this on sun4c's anyhow */
-		printk ("Interrupt does not need to enable IE\n");
-		return;
-#endif
 		restore_flags(flags);
 		return;
 	};
 
 	*interrupt_enable = new_mask;
-
 	restore_flags(flags);
+}
 
-	return;
+void
+sun4m_enable_irq(unsigned int irq_nr)
+{
+	printk("IRQ routines not written for the sun4m yet.\n");
+	panic("IRQ unsupported arch.");
+}
+
+void
+enable_irq(unsigned int irq_nr)
+{
+	switch(sparc_cpu_model) {
+	case sun4c:
+		sun4c_enable_irq(irq_nr);
+		break;
+	case sun4m:
+		sun4m_enable_irq(irq_nr);
+		break;
+	default:
+		panic("IRQ unsupported arch.");
+	}
 }
 
 /*
@@ -193,8 +193,7 @@
                 printk("Trying to free free IRQ%d\n", irq);
                 return;
         }
-        save_flags(flags);
-        cli();
+        save_flags(flags); cli();
         disable_irq(irq);
         action->handler = NULL;
         action->flags = 0;
@@ -210,14 +209,14 @@
 
         printk("IO device interrupt, irq = %d\n", irq);
         printk("PC = %08lx NPC = %08lx FP=%08lx\n", regs->pc, 
-	       regs->npc, regs->u_regs[14]);
+		    regs->npc, regs->u_regs[14]);
         printk("Expecting: ");
         for (i = 0; i < 16; i++)
                 if (irq_action[i].handler)
-                        printk("[%s:%d:0x%x] ", irq_action[i].name, (int) i,
+                        prom_printf("[%s:%d:0x%x] ", irq_action[i].name, (int) i,
 			       (unsigned int) irq_action[i].handler);
         printk("AIEEE\n");
-	prom_halt();
+	panic("bogus interrupt received");
 }
 
 void
@@ -225,11 +224,11 @@
 {
 	struct irqaction * action = irq_action + irq;
 
-	if (!action->handler) {
+	kstat.interrupts[irq]++;
+	if (!action->handler)
 		unexpected_irq(irq, regs);
-		return;
-	}
-	action->handler(irq, regs);
+	else
+		action->handler(irq, regs);
 }
 
 /*
@@ -262,6 +261,40 @@
 	return;
 }
 
+int
+request_fast_irq(unsigned int irq, void (*handler)(int, struct pt_regs *),
+		 unsigned long irqflags, const char *devname)
+{
+	struct irqaction *action;
+	unsigned long flags;
+
+	if(irq > 14)
+		return -EINVAL;
+	action = irq + irq_action;
+	if(action->handler)
+		return -EBUSY;
+	if(!handler)
+		return -EINVAL;
+
+	save_flags(flags); cli();
+
+	/* Dork with trap table if we get this far. */
+	sparc_ttable[SP_TRAP_IRQ1+(irq-1)].inst_one =
+		SPARC_BRANCH((unsigned long) handler,
+			     (unsigned long) &sparc_ttable[SP_TRAP_IRQ1+(irq-1)].inst_one);
+	sparc_ttable[SP_TRAP_IRQ1+(irq-1)].inst_two = SPARC_RD_PSR_L0;
+	sparc_ttable[SP_TRAP_IRQ1+(irq-1)].inst_three = SPARC_NOP;
+	sparc_ttable[SP_TRAP_IRQ1+(irq-1)].inst_four = SPARC_NOP;
+
+	action->handler = handler;
+	action->flags = irqflags;
+	action->mask = 0;
+	action->name = devname;
+
+	restore_flags(flags);
+	return 0;
+}
+
 extern void probe_clock(void);
 		
 int
@@ -271,44 +304,40 @@
 	struct irqaction *action;
 	unsigned long flags;
 
-	if(irq > 14)  /* Only levels 1-14 are valid on the Sparc. */
+	if(irq > 14)
 		return -EINVAL;
 
-	/* i386 keyboard interrupt request, just return */
-	if(irq == 1) return 0;
-
-	/* sched_init() requesting the timer IRQ */
-	if(irq == 0) {
-		irq = 10;
-	}
-
 	action = irq + irq_action;
-
 	if(action->handler)
 		return -EBUSY;
-
 	if(!handler)
 		return -EINVAL;
 
-	save_flags(flags);
-
-	cli();
-
+	save_flags(flags); cli();
 	action->handler = handler;
 	action->flags = irqflags;
 	action->mask = 0;
 	action->name = devname;
-
 	enable_irq(irq);
-
-	/* Init the timer/clocks if necessary. */
-	if(irq == 10) probe_clock();
-
+	if(irq == 10)
+		probe_clock();
 	restore_flags(flags);
-
 	return 0;
 }
 
+/* We really don't need these at all on the Sparc.  We only have
+ * stubs here because they are exported to modules.
+ */
+unsigned long probe_irq_on(void)
+{
+  return 0;
+}
+
+int probe_irq_off(unsigned long mask)
+{
+  return 0;
+}
+
 void
 sun4c_init_IRQ(void)
 {
@@ -317,10 +346,8 @@
 
 	ie_node = prom_searchsiblings (prom_getchild(prom_root_node),
 				       "interrupt-enable");
-	if(ie_node == 0) {
-		printk("Cannot find /interrupt-enable node\n");
-		prom_halt();
-	}
+	if(ie_node == 0)
+		panic("Cannot find /interrupt-enable node");
 	/* Depending on the "address" property is bad news... */
 	prom_getproperty(ie_node, "reg", (char *) int_regs, sizeof(int_regs));
 	sparc_alloc_io(int_regs[0].phys_addr, (void *) INTREG_VADDR,
@@ -330,16 +357,14 @@
 	interrupt_enable = (char *) INTREG_VADDR;
 
 	/* Default value, accept interrupts, but no one is actually active */
-	/* We also turn on level14 interrupts so PROM can run the console. */
-	*interrupt_enable = (SUN4C_INT_ENABLE | SUN4C_INT_E14);
-	sti(); /* As of NOW, L1-A works.  Turn irq's on full-blast. */
-	return;
+	*interrupt_enable = (SUN4C_INT_ENABLE);
+	sti(); /* Turn irq's on full-blast. */
 }
 
 void
 sun4m_init_IRQ(void)
 {
-	int ie_node, i;
+	int ie_node;
 
 	struct linux_prom_registers int_regs[PROMREG_MAX];
 	int num_regs;
@@ -349,10 +374,7 @@
 	if((ie_node = prom_searchsiblings(prom_getchild(prom_root_node), "obio")) == 0 ||
 	   (ie_node = prom_getchild (ie_node)) == 0 ||
 	   (ie_node = prom_searchsiblings (ie_node, "interrupt")) == 0)
-	{
-		printk("Cannot find /obio/interrupt node\n");
-		prom_halt();
-	}
+		panic("Cannot find /obio/interrupt node\n");
 	num_regs = prom_getproperty(ie_node, "reg", (char *) int_regs,
 				    sizeof(int_regs));
 	num_regs = (num_regs/sizeof(struct linux_prom_registers));
@@ -372,27 +394,7 @@
 		       int_regs[num_regs-1].which_io, 0x0);
 
 	sun4m_interrupts = (struct sun4m_intregs *) INTREG_VADDR;
-
-#if 0
-	printk("Interrupt register dump...\n");
-
-	for(i=0; i<NCPUS; i++)
-		printk("cpu%d: tbt %08x\n", i,
-		       sun4m_interrupts->cpu_intregs[i].tbt);
-
-	printk("Master tbt %08x\n", sun4m_interrupts->tbt);
-	printk("Master irqs %08x\n", sun4m_interrupts->irqs);
-	printk("Master set %08x\n", sun4m_interrupts->set);
-	printk("Master clear %08x\n", sun4m_interrupts->clear);
-	printk("Undirected ints taken by: %08x\n",
-	       sun4m_interrupts->undirected_target);
-
-	prom_halt();
-#endif
-
 	sti();
-
-	return;
 }
 
 void
@@ -406,10 +408,7 @@
 		sun4m_init_IRQ();
 		break;
 	default:
-		printk("Cannot initialize IRQ's on this Sun machine...\n");
-		halt();
+		panic("Cannot initialize IRQ's on this Sun machine...");
 		break;
 	};
-
-	return;
 }
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/kernel/mp.S linux/arch/sparc/kernel/mp.S
--- v1.3.43/linux/arch/sparc/kernel/mp.S	Tue Jun 27 14:11:31 1995
+++ linux/arch/sparc/kernel/mp.S	Sat Nov 25 02:58:12 1995
@@ -1,4 +1,5 @@
-/* mp.S:  Multiprocessor low-level routines on the Sparc.
+/* $Id: mp.S,v 1.2 1995/11/25 00:58:11 davem Exp $
+ * mp.S:  Multiprocessor low-level routines on the Sparc.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  */
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/kernel/probe.c linux/arch/sparc/kernel/probe.c
--- v1.3.43/linux/arch/sparc/kernel/probe.c	Tue Jun 27 14:11:32 1995
+++ linux/arch/sparc/kernel/probe.c	Sat Nov 25 02:58:17 1995
@@ -1,4 +1,5 @@
-/* probe.c: Preliminary device tree probing routines...
+/* $Id: probe.c,v 1.38 1995/11/25 00:58:14 davem Exp $
+ * probe.c: Preliminary device tree probing routines...
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  */
@@ -11,6 +12,7 @@
 #include <asm/oplib.h>
 #include <asm/vac-ops.h>
 #include <asm/idprom.h>
+#include <asm/machines.h>
 #include <asm/io.h>
 #include <asm/vaddrs.h>
 #include <asm/param.h>
@@ -24,12 +26,14 @@
 /* #define DEBUG_PROBING */
 
 /* XXX Grrr, this stuff should have it's own file, only generic stuff goes
- * XXX here.  Possibly clock.c and timer.c?
+ * XXX here.  Possibly clock.c and timer.c?  This file should get smaller
+ * XXX and smaller as time goes on...
  */
 enum sparc_clock_type sp_clock_typ;
 struct mostek48t02 *mstk48t02_regs;
 struct mostek48t08 *mstk48t08_regs;
 volatile unsigned int *master_l10_limit = 0;
+volatile unsigned int *master_l10_counter = 0;
 struct sun4m_timer_regs *sun4m_timers;
 
 static char node_str[128];
@@ -124,7 +128,7 @@
   { 7, 0, "Harvest VLSI Design Center, Inc. - unknown"},
   /* Gallium arsenide 200MHz, BOOOOGOOOOMIPS!!! */
   { 8, 0, "Systems and Processes Engineering Corporation (SPEC)"},
-  { 9, 0, "UNKNOWN CPU-VENDOR/TYPE"},
+  { 9, 0, "Fujitsu #3"},
   { 0xa, 0, "UNKNOWN CPU-VENDOR/TYPE"},
   { 0xb, 0, "UNKNOWN CPU-VENDOR/TYPE"},
   { 0xc, 0, "UNKNOWN CPU-VENDOR/TYPE"},
@@ -138,16 +142,6 @@
 char *sparc_cpu_type[NCPUS] = { "cpu-oops", "cpu-oops1", "cpu-oops2", "cpu-oops3" };
 char *sparc_fpu_type[NCPUS] = { "fpu-oops", "fpu-oops1", "fpu-oops2", "fpu-oops3" };
 
-/* various Virtual Address Cache parameters we find at boot time... */
-
-extern int vac_size, vac_linesize, vac_do_hw_vac_flushes;
-extern int vac_entries_per_context, vac_entries_per_segment;
-extern int vac_entries_per_page;
-
-extern int find_vac_size(void);
-extern int find_vac_linesize(void);
-extern int find_vac_hwflushes(void);
-
 static inline int find_mmu_num_contexts(int cpu)
 {
 	return prom_getintdefault(cpu, "mmu-nctx", 0x8);
@@ -158,99 +152,126 @@
 void
 probe_cpu(void)
 {
-  int psr_impl, psr_vers, fpu_vers;
-  int i, cpuid;
+	int psr_impl, psr_vers, fpu_vers;
+	int i, cpuid;
+
+	cpuid = get_cpuid();
 
-  cpuid = get_cpuid();
+	psr_impl = ((get_psr()>>28)&0xf);
+	psr_vers = ((get_psr()>>24)&0xf);
 
-  psr_impl = ((get_psr()>>28)&0xf);
-  psr_vers = ((get_psr()>>24)&0xf);
+	fpu_vers = ((get_fsr()>>17)&0x7);
 
-  fpu_vers = ((get_fsr()>>17)&0x7);
-
-  for(i = 0; i<NSPARCCHIPS; i++)
-    {
-      if(linux_sparc_chips[i].psr_impl == psr_impl)
-	if(linux_sparc_chips[i].psr_vers == psr_vers)
-	  {
-	    sparc_cpu_type[cpuid] = linux_sparc_chips[i].cpu_name;
-	    break;
-	  }
-    }
-
-  if(i==NSPARCCHIPS)
-    {
-      printk("No CPU type! You lose\n");
-      printk("DEBUG: psr.impl = 0x%x   psr.vers = 0x%x\n", psr_impl, 
-	     psr_vers);
-      printk("Send this information and the type of SUN and CPU/FPU type you have\n");
-      printk("to davem@caip.rutgers.edu so that this can be fixed.\n");
-      printk("halting...\n\r\n");
-      /* If I don't know about this CPU, I don't want people running on it
-       * until I do.....
-       */
-      halt();
-    }
-
-  for(i = 0; i<NSPARCFPU; i++)
-    {
-      if(linux_sparc_fpu[i].psr_impl == psr_impl)
-	if(linux_sparc_fpu[i].fp_vers == fpu_vers)
-	  {
-	    sparc_fpu_type[cpuid] = linux_sparc_fpu[i].fp_name;
-	    break;
-	  }
-    }
-
-  if(i == NSPARCFPU)
-    {
-      printk("No FPU type! You don't completely lose though...\n");
-      printk("DEBUG: psr.impl = 0x%x  fsr.vers = 0x%x\n", psr_impl, fpu_vers);
-      printk("Send this information and the type of SUN and CPU/FPU type you have\n");
-      printk("to davem@caip.rutgers.edu so that this can be fixed.\n");
-      sparc_fpu_type[cpuid] = linux_sparc_fpu[31].fp_name;
-    }
+	for(i = 0; i<NSPARCCHIPS; i++) {
+		if(linux_sparc_chips[i].psr_impl == psr_impl)
+			if(linux_sparc_chips[i].psr_vers == psr_vers) {
+				sparc_cpu_type[cpuid] = linux_sparc_chips[i].cpu_name;
+				break;
+			}
+	}
 
-  printk("cpu%d CPU: %s \n", cpuid, sparc_cpu_type[cpuid]);
-  printk("cpu%d FPU: %s \n", cpuid, sparc_fpu_type[cpuid]);
+	if(i==NSPARCCHIPS)
+		printk("DEBUG: psr.impl = 0x%x   psr.vers = 0x%x\n", psr_impl, 
+			    psr_vers);
+
+	for(i = 0; i<NSPARCFPU; i++) {
+		if(linux_sparc_fpu[i].psr_impl == psr_impl)
+			if(linux_sparc_fpu[i].fp_vers == fpu_vers) {
+				sparc_fpu_type[cpuid] = linux_sparc_fpu[i].fp_name;
+				break;
+			}
+	}
 
-  return;
+	if(i == NSPARCFPU) {
+		printk("DEBUG: psr.impl = 0x%x  fsr.vers = 0x%x\n", psr_impl,
+			    fpu_vers);
+		sparc_fpu_type[cpuid] = linux_sparc_fpu[31].fp_name;
+	}
+
+	printk("cpu%d CPU: %s \n", cpuid, sparc_cpu_type[cpuid]);
+	printk("cpu%d FPU: %s \n", cpuid, sparc_fpu_type[cpuid]);
 }
 
 void
 probe_vac(void)
 {
-	unsigned int x,y;
+	int propval;
+
+	sun4c_disable_vac();
+	sun4c_vacinfo.num_bytes = prom_getintdefault(prom_root_node,
+						     "vac-size", 65536);
+	sun4c_vacinfo.linesize = prom_getintdefault(prom_root_node,
+						    "vac-linesize", 16);
+	sun4c_vacinfo.num_lines =
+		(sun4c_vacinfo.num_bytes / sun4c_vacinfo.linesize);
+	switch(sun4c_vacinfo.linesize) {
+	case 16:
+		sun4c_vacinfo.log2lsize = 4;
+		break;
+	case 32:
+		sun4c_vacinfo.log2lsize = 5;
+		break;
+	default:
+		printk("probe_vac: Didn't expect vac-linesize of %d, halting\n",
+			    sun4c_vacinfo.linesize);
+	};
 
-	vac_size = find_vac_size();
-	vac_linesize = find_vac_linesize();
-	vac_do_hw_vac_flushes = find_vac_hwflushes();
+	propval = prom_getintdefault(prom_root_node, "vac_hwflush", -1);
+	sun4c_vacinfo.do_hwflushes = (propval == -1 ?
+				      prom_getintdefault(prom_root_node,
+							 "vac-hwflush", 0) :
+				      propval);
+
+	printk("SUN4C: VAC size %d line size %d using %s flushes ",
+	       sun4c_vacinfo.num_bytes, sun4c_vacinfo.linesize,
+	       (sun4c_vacinfo.do_hwflushes ? "hardware" : "software"));
+	if(sun4c_vacinfo.num_bytes != 65536) {
+		printk("WEIRD Sun4C VAC cache size, tell davem");
+		prom_halt();
+	}
 
-	/* Calculate various constants that make the cache-flushing code
-	 * mode speedy.
-	 */
+	/* setup the low-level assembly routine ptrs */
+	if(sun4c_vacinfo.do_hwflushes) {
+		if(sun4c_vacinfo.linesize == 16) {
+			sun4c_ctxflush = (unsigned long)sun4c_ctxflush_hw64KB16B;
+			sun4c_segflush = (unsigned long)sun4c_segflush_hw64KB16B;
+			sun4c_pgflush = (unsigned long)sun4c_pgflush_hw64KB16B;
+		} else if(sun4c_vacinfo.linesize == 32) {
+			sun4c_ctxflush = (unsigned long)sun4c_ctxflush_hw64KB32B;
+			sun4c_segflush = (unsigned long)sun4c_segflush_hw64KB32B;
+			sun4c_pgflush = (unsigned long)sun4c_pgflush_hw64KB32B;
+		} else {
+			printk("WEIRD Sun4C VAC cache line size, tell davem\n");
+			prom_halt();
+		}
+	} else {
+		if(sun4c_vacinfo.linesize == 16) {
+			sun4c_ctxflush = (unsigned long)sun4c_ctxflush_sw64KB16B;
+			sun4c_segflush = (unsigned long)sun4c_segflush_sw64KB16B;
+			sun4c_pgflush = (unsigned long)sun4c_pgflush_sw64KB16B;
+		} else if(sun4c_vacinfo.linesize == 32) {
+			sun4c_ctxflush = (unsigned long)sun4c_ctxflush_sw64KB32B;
+			sun4c_segflush = (unsigned long)sun4c_segflush_sw64KB32B;
+			sun4c_pgflush = (unsigned long)sun4c_pgflush_sw64KB32B;
+		} else {
+			printk("WEIRD Sun4C VAC cache line size, tell davem\n");
+			prom_halt();
+		}
+	}
 
-	vac_entries_per_segment = vac_entries_per_context = vac_size >> 12;
-	for(x=0,y=vac_linesize; ((1<<x)<y); x++);
-	if((1<<x) != vac_linesize) printk("Warning BOGUS VAC linesize 0x%x",
-					  vac_size);
-	vac_entries_per_page = x;
 
-	/* Here we want to 'invalidate' all the software VAC "tags"
-	 * just in case there is garbage in there. Then we enable it.
-	 */
+	sun4c_flush_all();
+	sun4c_enable_vac();
+	printk("enabled\n");
 
-	/* flush flush flush */
-	for(x=AC_CACHETAGS; x<(AC_CACHETAGS+vac_size); x+=vac_linesize)
-		__asm__("sta %%g0, [%0] %1" : : "r" (x), "i" (0x2));
-	x=enable_vac();
 	return;
 }
 
 extern int num_segmaps, num_contexts;
 
+/* XXX Only called on sun4c XXX */
 void
-probe_mmu(int prom_node_cpu)
+probe_mmu(void)
 {
 	int cpuid;
 
@@ -258,177 +279,146 @@
 	cpuid = get_cpuid();
 	switch(sparc_cpu_model) {
 	case sun4:
-		break;
 	case sun4c:
-		/* A sun4, sun4c. */
-		num_segmaps = prom_getintdefault(prom_node_cpu, "mmu-npmg", 128);
-		num_contexts = find_mmu_num_contexts(prom_node_cpu);
+	case sun4e:
+		/* A sun4, sun4c or sun4e. */
+		num_segmaps = prom_getintdefault(prom_root_node, "mmu-npmg", 128);
+		num_contexts = find_mmu_num_contexts(prom_root_node);
 
 		printk("cpu%d MMU segmaps: %d     MMU contexts: %d\n", cpuid,
-		       num_segmaps, num_contexts);
-		break;
-	case sun4m:
-	case sun4d:
-	case sun4e:
-		/* Any Reference MMU derivate should be handled here, hopefuly. */
-		num_segmaps = 0;
-		num_contexts = find_mmu_num_contexts(prom_node_cpu);
-		vac_linesize = prom_getint(prom_node_cpu, "cache-line-size");
-		vac_size = (prom_getint(prom_node_cpu, "cache-nlines")*vac_linesize);
-		printk("cpu%d MMU contexts: %d\n", cpuid, num_contexts);
-		printk("cpu%d CACHE linesize %d total size %d\n", cpuid, vac_linesize,
-		       vac_size);
+			    num_segmaps, num_contexts);
 		break;
 	default:
 		printk("cpu%d probe_mmu: sparc_cpu_model botch\n", cpuid);
 		break;
 	};
-
-	return;
 }
 
 /* Clock probing, we probe the timers here also. */
-/* #define DEBUG_PROBE_CLOCK */
 volatile unsigned int foo_limit;
 
 void
 probe_clock(int fchild)
 {
-  register int node, type;
-  struct linux_prom_registers clk_reg[2];
+	register int node, type;
+	struct linux_prom_registers clk_reg[2];
 
-  /* This will basically traverse the node-tree of the prom to see
-   * which timer chip is on this machine.
-   */
-
-  node = 0;
-  if(sparc_cpu_model == sun4) {
-	  printk("probe_clock: No SUN4 Clock/Timer support yet...\n");
-	  return;
-  }
-  if(sparc_cpu_model == sun4c) node=prom_getchild(prom_root_node);
-  else
-	  if(sparc_cpu_model == sun4m)
-		  node=prom_getchild(prom_searchsiblings(prom_getchild(prom_root_node), "obio"));
-  type = 0;
-  sp_clock_typ = MSTK_INVALID;
-  for(;;) {
-	  prom_getstring(node, "model", node_str, sizeof(node_str));
-	  if(strcmp(node_str, "mk48t02") == 0) {
-		  sp_clock_typ = MSTK48T02;
-		  if(prom_getproperty(node, "reg", (char *) clk_reg, sizeof(clk_reg)) == -1) {
-			  printk("probe_clock: FAILED!\n");
-			  halt();
-		  }
-		  prom_apply_obio_ranges(clk_reg, 1);
-		  /* Map the clock register io area read-only */
-		  mstk48t02_regs = (struct mostek48t02 *) 
-			  sparc_alloc_io((void *) clk_reg[0].phys_addr,
-					 (void *) 0, sizeof(*mstk48t02_regs),
-					 "clock", 0x0, 0x1);
-		  mstk48t08_regs = 0;  /* To catch weirdness */
-		  break;
-	  }
-
-	  if(strcmp(node_str, "mk48t08") == 0) {
-		  sp_clock_typ = MSTK48T08;
-		  if(prom_getproperty(node, "reg", (char *) clk_reg,
-				      sizeof(clk_reg)) == -1) {
-			  printk("probe_clock: FAILED!\n");
-			  halt();
-		  }
-		  prom_apply_obio_ranges(clk_reg, 1);
-		  /* Map the clock register io area read-only */
-		  mstk48t08_regs = (struct mostek48t08 *)
-			  sparc_alloc_io((void *) clk_reg[0].phys_addr,
-					 (void *) 0, sizeof(*mstk48t08_regs),
-					 "clock", 0x0, 0x1);
-
-		  mstk48t02_regs = &mstk48t08_regs->regs;
-		  break;
-	  }
-
-	  node = prom_getsibling(node);
-	  if(node == 0) {
-		  printk("Aieee, could not find timer chip type\n");
-		  return;
-	  }
-  }
-
-  if(sparc_cpu_model == sun4c) {
-
-  /* Map the Timer chip, this is implemented in hardware inside
-   * the cache chip on the sun4c.
-   */
-  sparc_alloc_io ((void *) SUN4C_TIMER_PHYSADDR, (void *) TIMER_VADDR,
-		  sizeof (*SUN4C_TIMER_STRUCT), "timer", 0x0, 0x0);
-
-  /* Have the level 10 timer tick at 100HZ.  We don't touch the
-   * level 14 timer limit since we are letting the prom handle
-   * them until we have a real console driver so L1-A works.
-   */
-  SUN4C_TIMER_STRUCT->timer_limit10 = (((1000000/HZ) + 1) << 10);
-  master_l10_limit = &(SUN4C_TIMER_STRUCT->timer_limit10);
-
-  } else {
-	  int reg_count;
-	  struct linux_prom_registers cnt_regs[PROMREG_MAX];
-	  int obio_node, cnt_node;
-
-	  cnt_node = 0;
-	  if((obio_node =
-	      prom_searchsiblings (prom_getchild(prom_root_node), "obio")) == 0 ||
-	     (obio_node = prom_getchild (obio_node)) == 0 ||
-	     (cnt_node = prom_searchsiblings (obio_node, "counter")) == 0) {
-		  printk ("Cannot find /obio/counter node\n");
-		  prom_halt ();
-	  }
-	  reg_count = prom_getproperty(cnt_node, "reg",
-				       (void *) cnt_regs, sizeof(cnt_regs));
-
-	  reg_count = (reg_count/sizeof(struct linux_prom_registers));
-
-	  /* Apply the obio ranges to the timer registers. */
-	  prom_apply_obio_ranges(cnt_regs, reg_count);
-
-	  /* Map the per-cpu Counter registers. */
-	  sparc_alloc_io(cnt_regs[0].phys_addr, (void *) TIMER_VADDR,
-			 PAGE_SIZE*NCPUS, "counters_percpu", cnt_regs[0].which_io, 0x0);
-
-	  /* Map the system Counter register. */
-	  sparc_alloc_io(cnt_regs[reg_count-1].phys_addr,
-			 (void *) TIMER_VADDR+(NCPUS*PAGE_SIZE),
-			 cnt_regs[reg_count-1].reg_size,
-			 "counters_system", cnt_regs[reg_count-1].which_io, 0x0);
-
-
-	  sun4m_timers = (struct sun4m_timer_regs *) TIMER_VADDR;
-
-	  foo_limit = (volatile) sun4m_timers->l10_timer_limit;
-
-/*	  printk("Timer register dump:\n"); */
-#if 0
-	  printk("cpu0: l14limit %08x l14curcount %08x\n",
-		 sun4m_timers->cpu_timers[0].l14_timer_limit,
-		 sun4m_timers->cpu_timers[0].l14_cur_count);
-#endif
-#if 0
-	  printk("sys: l10limit %08x l10curcount %08x\n",
-		 sun4m_timers->l10_timer_limit,
-		 sun4m_timers->l10_cur_count);
-#endif
-
-	  /* Must set the master pointer first or we will lose badly. */
-	  master_l10_limit =
-		  &(((struct sun4m_timer_regs *)TIMER_VADDR)->l10_timer_limit);
+	/* This will basically traverse the node-tree of the prom to see
+	 * which timer chip is on this machine.
+	 */
 
-          ((struct sun4m_timer_regs *)TIMER_VADDR)->l10_timer_limit =
-		  (((1000000/HZ) + 1) << 10);   /* 0x9c4000 */
+	node = 0;
+	if(sparc_cpu_model == sun4) {
+		printk("probe_clock: No SUN4 Clock/Timer support yet...\n");
+		return;
+	}
+	if(sparc_cpu_model == sun4c) node=prom_getchild(prom_root_node);
+	else
+		if(sparc_cpu_model == sun4m)
+			node=prom_getchild(prom_searchsiblings(prom_getchild(prom_root_node), "obio"));
+	type = 0;
+	sp_clock_typ = MSTK_INVALID;
+	for(;;) {
+		prom_getstring(node, "model", node_str, sizeof(node_str));
+		if(strcmp(node_str, "mk48t02") == 0) {
+			sp_clock_typ = MSTK48T02;
+			if(prom_getproperty(node, "reg", (char *) clk_reg, sizeof(clk_reg)) == -1) {
+				printk("probe_clock: FAILED!\n");
+				halt();
+			}
+			prom_apply_obio_ranges(clk_reg, 1);
+			/* Map the clock register io area read-only */
+			mstk48t02_regs = (struct mostek48t02 *) 
+				sparc_alloc_io((void *) clk_reg[0].phys_addr,
+					       (void *) 0, sizeof(*mstk48t02_regs),
+					       "clock", 0x0, 0x1);
+			mstk48t08_regs = 0;  /* To catch weirdness */
+			break;
+		}
 
-	  /* We should be getting level 10 interrupts now. */
-  }
+		if(strcmp(node_str, "mk48t08") == 0) {
+			sp_clock_typ = MSTK48T08;
+			if(prom_getproperty(node, "reg", (char *) clk_reg,
+					    sizeof(clk_reg)) == -1) {
+				printk("probe_clock: FAILED!\n");
+				halt();
+			}
+			prom_apply_obio_ranges(clk_reg, 1);
+			/* Map the clock register io area read-only */
+			mstk48t08_regs = (struct mostek48t08 *)
+				sparc_alloc_io((void *) clk_reg[0].phys_addr,
+					       (void *) 0, sizeof(*mstk48t08_regs),
+					       "clock", 0x0, 0x1);
 
-  return;
+			mstk48t02_regs = &mstk48t08_regs->regs;
+			break;
+		}
+
+		node = prom_getsibling(node);
+		if(node == 0) {
+			printk("Aieee, could not find timer chip type\n");
+			return;
+		}
+	}
+
+	if(sparc_cpu_model == sun4c) {
+		/* Map the Timer chip, this is implemented in hardware inside
+		 * the cache chip on the sun4c.
+		 */
+		sparc_alloc_io ((void *) SUN4C_TIMER_PHYSADDR, (void *) TIMER_VADDR,
+				sizeof (*SUN4C_TIMER_STRUCT), "timer", 0x0, 0x0);
+
+		/* Have the level 10 timer tick at 100HZ.  We don't touch the
+		 * level 14 timer limit since we are letting the prom handle
+		 * them until we have a real console driver so L1-A works.
+		 */
+		SUN4C_TIMER_STRUCT->timer_limit10 = (((1000000/HZ) + 1) << 10);
+		master_l10_limit = &(SUN4C_TIMER_STRUCT->timer_limit10);
+		master_l10_counter = &(SUN4C_TIMER_STRUCT->cur_count10);
+	} else {
+		int reg_count;
+		struct linux_prom_registers cnt_regs[PROMREG_MAX];
+		int obio_node, cnt_node;
+
+		cnt_node = 0;
+		if((obio_node =
+		    prom_searchsiblings (prom_getchild(prom_root_node), "obio")) == 0 ||
+		   (obio_node = prom_getchild (obio_node)) == 0 ||
+		   (cnt_node = prom_searchsiblings (obio_node, "counter")) == 0) {
+			printk ("Cannot find /obio/counter node\n");
+			prom_halt ();
+		}
+		reg_count = prom_getproperty(cnt_node, "reg",
+					     (void *) cnt_regs, sizeof(cnt_regs));
+		reg_count = (reg_count/sizeof(struct linux_prom_registers));
+
+		/* Apply the obio ranges to the timer registers. */
+		prom_apply_obio_ranges(cnt_regs, reg_count);
+
+		/* Map the per-cpu Counter registers. */
+		sparc_alloc_io(cnt_regs[0].phys_addr, (void *) TIMER_VADDR,
+			       PAGE_SIZE*NCPUS, "counters_percpu",
+			       cnt_regs[0].which_io, 0x0);
+
+		/* Map the system Counter register. */
+		sparc_alloc_io(cnt_regs[reg_count-1].phys_addr,
+			       (void *) TIMER_VADDR+(NCPUS*PAGE_SIZE),
+			       cnt_regs[reg_count-1].reg_size,
+			       "counters_system", cnt_regs[reg_count-1].which_io, 0x0);
+		sun4m_timers = (struct sun4m_timer_regs *) TIMER_VADDR;
+
+		/* Avoid interrupt bombs... */
+		foo_limit = (volatile) sun4m_timers->l10_timer_limit;
+
+		/* Must set the master pointer first or we will lose badly. */
+		master_l10_limit =
+			&(((struct sun4m_timer_regs *)TIMER_VADDR)->l10_timer_limit);
+		master_l10_counter =
+			&(((struct sun4m_timer_regs *)TIMER_VADDR)->l10_cur_count);
+
+		((struct sun4m_timer_regs *)TIMER_VADDR)->l10_timer_limit =
+			(((1000000/HZ) + 1) << 10);
+	}
 }
 
 /* Probe and map in the Auxiliaary I/O register */
@@ -455,15 +445,13 @@
 	sparc_alloc_io(auxregs[0].phys_addr, (void *) AUXIO_VADDR,
 		       auxregs[0].reg_size, "auxilliaryIO", auxregs[0].which_io, 0x0);
 	printk("Mapped AUXIO at paddr %08lx vaddr %08lx\n",
-	       (unsigned long) auxregs[0].phys_addr,
-	       (unsigned long) AUXIO_VADDR);
-	return;
+		    (unsigned long) auxregs[0].phys_addr,
+		    (unsigned long) AUXIO_VADDR);
 }
 
 extern unsigned long probe_memory(void);
 extern struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS];
 unsigned int phys_bytes_of_ram, end_of_phys_memory;
-extern unsigned long probe_sbus(int, unsigned long);
 extern void probe_mbus(void);
 
 /* #define DEBUG_PROBE_DEVICES */
@@ -473,54 +461,46 @@
 unsigned long
 probe_devices(unsigned long mem_start)
 {
-  int nd, i, prom_node_cpu, thismid;
-  int cpu_nds[NCPUS];  /* One node for each cpu */
-  int cpu_ctr = 0;
-
-  prom_getstring(prom_root_node, "device_type", node_str, sizeof(node_str));
-  if(strcmp(node_str, "cpu") == 0) {
-    cpu_nds[0] = prom_root_node;
-    cpu_ctr++;
-  } else {
-    int scan;
-    scan = prom_getchild(prom_root_node);
-    nd = 0;
-    while((scan = prom_getsibling(scan)) != 0) {
-      prom_getstring(scan, "device_type", node_str, sizeof(node_str));
-      if(strcmp(node_str, "cpu") == 0) {
-	      cpu_nds[cpu_ctr] = scan;
-	      linux_cpus[cpu_ctr].prom_node = scan;
-	      prom_getproperty(scan, "mid", (char *) &thismid, sizeof(thismid));
-	      linux_cpus[cpu_ctr].mid = thismid;
-	      cpu_ctr++;
-      }
-    };
-    if(cpu_ctr == 0) {
-      printk("No CPU nodes found, cannot continue.\n");
-      /* Probably a sun4d or sun4e, Sun is trying to trick us ;-) */
-      halt();
-    }
-    printk("Found %d CPU prom device tree node(s).\n", cpu_ctr);
-  };
-  prom_node_cpu = cpu_nds[0];
-
-  linux_num_cpus = cpu_ctr;
-  for(i=0; i<cpu_ctr; i++) {
-	  prom_getstring(cpu_nds[i], "name", node_str, sizeof(node_str));
-	  printk("cpu%d: %s \n", i, node_str);
-  }
-
-/* Ok, here will go a call to each specific device probe. We can
- * call these now that we have the 'root' node and the child of
- * this node to send to the routines. ORDER IS IMPORTANT!
- */
+	int nd, i, prom_node_cpu, thismid;
+	int cpu_nds[NCPUS];  /* One node for each cpu */
+	int cpu_ctr = 0;
+
+	prom_getstring(prom_root_node, "device_type", node_str, sizeof(node_str));
+	if(strcmp(node_str, "cpu") == 0) {
+		cpu_nds[0] = prom_root_node;
+		cpu_ctr++;
+	} else {
+		int scan;
+		scan = prom_getchild(prom_root_node);
+		nd = 0;
+		while((scan = prom_getsibling(scan)) != 0) {
+			prom_getstring(scan, "device_type", node_str, sizeof(node_str));
+			if(strcmp(node_str, "cpu") == 0) {
+				cpu_nds[cpu_ctr] = scan;
+				linux_cpus[cpu_ctr].prom_node = scan;
+				prom_getproperty(scan, "mid", (char *) &thismid, sizeof(thismid));
+				linux_cpus[cpu_ctr].mid = thismid;
+				cpu_ctr++;
+			}
+		};
+		if(cpu_ctr == 0) {
+			printk("No CPU nodes found, cannot continue.\n");
+			/* Probably a sun4d or sun4e, Sun is trying to trick us ;-) */
+			halt();
+		}
+		printk("Found %d CPU prom device tree node(s).\n", cpu_ctr);
+	};
+	prom_node_cpu = cpu_nds[0];
 
-  probe_cpu();
-  probe_auxio();
-  if(sparc_cpu_model == sun4c) probe_vac();
-  if(sparc_cpu_model != sun4c) probe_mbus(); /* Are MBUS's relevant on sun4c's? */
+	linux_num_cpus = cpu_ctr;
+	for(i=0; i<cpu_ctr; i++) {
+		prom_getstring(cpu_nds[i], "name", node_str, sizeof(node_str));
+		printk("cpu%d: %s \n", i, node_str);
+	}
 
-  mem_start = probe_sbus(prom_getchild(prom_root_node), mem_start);
+	probe_cpu();
+	probe_auxio();
+	if(sparc_cpu_model != sun4c) probe_mbus();
 
-  return mem_start;
+	return mem_start;
 }
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/kernel/process.c linux/arch/sparc/kernel/process.c
--- v1.3.43/linux/arch/sparc/kernel/process.c	Fri Oct  6 14:35:15 1995
+++ linux/arch/sparc/kernel/process.c	Sat Nov 25 02:58:19 1995
@@ -1,4 +1,4 @@
-/*
+/*  $Id: process.c,v 1.29 1995/11/25 00:58:17 davem Exp $
  *  linux/arch/sparc/kernel/process.c
  *
  *  Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -20,43 +20,63 @@
 #include <linux/user.h>
 #include <linux/a.out.h>
 
+#include <asm/auxio.h>
 #include <asm/oplib.h>
 #include <asm/segment.h>
 #include <asm/system.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
 #include <asm/processor.h>
+#include <asm/psr.h>
+
+int current_user_segment = USER_DS; /* the return value from get_fs */
 
 /*
- * The idle loop on a sparc... ;)
+ * the idle loop on a Sparc... ;)
  */
 asmlinkage int sys_idle(void)
 {
-
 	if (current->pid != 0)
 		return -EPERM;
 
-	printk("in sys_idle...\n");
-	/* Map out the low memory: it's no longer needed */
-	/* Sparc version RSN */
-
 	/* endless idle loop with no priority at all */
 	current->counter = -100;
 	for (;;) {
-	  printk("calling schedule() aieee!\n");
-	  schedule();
-	  printk("schedule() returned, halting...\n");
-	  halt();
+		schedule();
 	}
 }
 
 void hard_reset_now(void)
 {
-	prom_reboot("boot vmlinux");
+	prom_halt();
+}
+
+void show_regwindow(struct reg_window *rw)
+{
+	printk("l0:%08lx l1:%08lx l2:%08lx l3:%08lx l4:%08lx l5:%08lx l6:%08lx l7:%08lx\n",
+	       rw->locals[0], rw->locals[1], rw->locals[2], rw->locals[3],
+	       rw->locals[4], rw->locals[5], rw->locals[6], rw->locals[7]);
+	printk("i0:%08lx i1:%08lx i2:%08lx i3:%08lx i4:%08lx i5:%08lx i6:%08lx i7:%08lx\n",
+	       rw->ins[0], rw->ins[1], rw->ins[2], rw->ins[3],
+	       rw->ins[4], rw->ins[5], rw->ins[6], rw->ins[7]);
 }
 
 void show_regs(struct pt_regs * regs)
 {
-        printk("\nFP: %08lx PC: %08lx NPC: %08lx\n", regs->u_regs[14],
-	       regs->pc, regs->npc);
+        printk("PSR: %08lx PC: %08lx NPC: %08lx Y: %08lx\n", regs->psr,
+	       regs->pc, regs->npc, regs->y);
+	printk("%%g0: %08lx %%g1: %08lx %%g2: %08lx %%g3: %08lx\n",
+	       regs->u_regs[0], regs->u_regs[1], regs->u_regs[2],
+	       regs->u_regs[3]);
+	printk("%%g4: %08lx %%g5: %08lx %%g6: %08lx %%g7: %08lx\n",
+	       regs->u_regs[4], regs->u_regs[5], regs->u_regs[6],
+	       regs->u_regs[7]);
+	printk("%%o0: %08lx %%o1: %08lx %%o2: %08lx %%o3: %08lx\n",
+	       regs->u_regs[8], regs->u_regs[9], regs->u_regs[10],
+	       regs->u_regs[11]);
+	printk("%%o4: %08lx %%o5: %08lx %%sp: %08lx %%ret_pc: %08lx\n",
+	       regs->u_regs[12], regs->u_regs[13], regs->u_regs[14],
+	       regs->u_regs[15]);
 }
 
 /*
@@ -64,74 +84,92 @@
  */
 void exit_thread(void)
 {
-  halt();
+	if(last_task_used_math == current)
+		last_task_used_math = NULL;
+	mmu_exit_hook(current);
 }
 
-void flush_thread(void)
+/*
+ * Free old dead task when we know it can never be on the cpu again.
+ */
+void release_thread(struct task_struct *dead_task)
 {
-  halt();
+	mmu_release_hook(dead_task);
 }
 
-void release_thread(struct task_struct *dead_task)
+void flush_thread(void)
 {
-  halt();
+	/* Make sure old user windows don't get in the way. */
+	mmu_flush_hook(current);
+	flush_user_windows();
+	current->signal &= ~(1<<(SIGILL-1));
+	current->tss.w_saved = 0;
+	current->tss.uwinmask = 0;
+
+	current->tss.sig_address = 0;
+	current->tss.sig_desc = 0;
+
+	/* Signal stack state does not inherit. XXX Really? XXX */
+	current->tss.sstk_info.cur_status = 0;
+	current->tss.sstk_info.the_stack = 0;
+
+	memset(&current->tss.reg_window[0], 0,
+	       (sizeof(struct reg_window) * NSWINS));
+	memset(&current->tss.rwbuf_stkptrs[0], 0,
+	       (sizeof(unsigned long) * NSWINS));
 }
 
-extern void ret_sys_call(void);
-
 /*
- * Copy a Sparc thread.  The context of a process on the Sparc is
- * composed of the following:
- *  1) status registers  %psr (for condition codes + CWP) and %wim
- *  2) current register window (in's and global registers)
- *  3) the current live stack frame, it contains the register
- *     windows the child may 'restore' into, this is important
- *  4) kernel stack pointer, user stack pointer (which is %i6)
- *  5) The pc and npc the child returns to during a switch
+ * Copy a Sparc thread.  The fork() return value conventions
+ * under SunOS are nothing short of bletcherous:
+ * Parent -->  %o0 == childs  pid, %o1 == 0
+ * Child  -->  %o0 == parents pid, %o1 == 1
+ *
+ * I'm feeling sick...
  */
+extern void ret_sys_call(void);
 
 void copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
-		 struct task_struct * p, struct pt_regs * regs)
+		 struct task_struct *p, struct pt_regs *regs)
 {
 	struct pt_regs *childregs;
-	unsigned char *old_stack;
-	unsigned char *new_stack;
-	int i;
+	struct sparc_stackf *old_stack, *new_stack;
+	unsigned long stack_offset, kthread_usp = 0;
 
-	/* This process has no context yet. */
+	mmu_task_cacheflush(current);
 	p->tss.context = -1;
 
-	/* Grrr, Sparc stack alignment restrictions make things difficult. */
-	childregs = ((struct pt_regs *) 
-		     ((p->kernel_stack_page + PAGE_SIZE - 80)&(~7)));
-
+	/* Calculate offset to stack_frame & pt_regs */
+	stack_offset = (PAGE_SIZE - TRACEREG_SZ);
+	childregs = ((struct pt_regs *) (p->kernel_stack_page + stack_offset));
 	*childregs = *regs;
-
-	p->tss.usp = sp;    /* both processes have the same user stack */
-	/* See entry.S */
-
-	/* Allocate new processes kernel stack right under pt_regs.
-	 * Hopefully this should align things the right way.
+	new_stack = (((struct sparc_stackf *) childregs) - 1);
+	old_stack = (((struct sparc_stackf *) regs) - 1);
+	*new_stack = *old_stack;
+	p->tss.ksp = (unsigned long) new_stack;
+	p->tss.kpc = (((unsigned long) ret_sys_call) - 0x8);
+
+	/* As a special case, if this is a kernel fork we need
+	 * to give the child a new fresh stack for when it returns
+	 * from the syscall. (ie. the "user" stack)  This happens
+	 * only once and we count on the page acquisition happening
+	 * successfully.
 	 */
-	p->tss.ksp = (unsigned long) ((p->kernel_stack_page + PAGE_SIZE - 80 - 96)&(~7));
-	new_stack = (unsigned char *) (p->tss.ksp);
-	old_stack = (unsigned char *) (((unsigned long) regs) - 96);
-
-	/* Copy c-stack. */
-	for(i=0; i<96; i++) *new_stack++ = *old_stack++;
-
-	/* These pc values are only used when we switch to the child for
-	 * the first time, it jumps the child to ret_sys_call in entry.S
-	 * so that the child returns from the sys_call just like parent.
-	 */
-	p->tss.pc = (((unsigned long) ret_sys_call) - 8);
-	p->tss.npc = p->tss.pc+4;
+	if(regs->psr & PSR_PS) {
+		 unsigned long n_stack = get_free_page(GFP_KERNEL);
+		 childregs->u_regs[UREG_FP] = (n_stack | (sp & 0xfff));
+		 memcpy((char *)n_stack,(char *)(sp & PAGE_MASK),PAGE_SIZE);
+		 kthread_usp = n_stack;
+	}
 
-	/* Set the return values for both the parent and the child */
-	regs->u_regs[8] = p->pid;
-	childregs->u_regs[8] = 0;
+	/* Set the return value for the child. */
+	childregs->u_regs[UREG_I0] = current->pid;
+	childregs->u_regs[UREG_I1] = 1;
 
-	return;
+	/* Set the return value for the parent. */
+	regs->u_regs[UREG_I1] = 0;
+
+	mmu_fork_hook(p, kthread_usp);
 }
 
 /*
@@ -139,21 +177,57 @@
  */
 void dump_thread(struct pt_regs * regs, struct user * dump)
 {
-  return; /* solaris does this enough */
 }
 
-asmlinkage int sys_fork(struct pt_regs *regs)
+/*
+ * fill in the fpu structure for a core dump.
+ */
+int dump_fpu (void *fpu_structure)
 {
-  return do_fork(SIGCHLD, regs->u_regs[14], regs);
+	/* Currently we report that we couldn't dump the fpu structure */
+	return 0;
 }
 
 /*
- * sys_execve() executes a new program.
+ * sparc_execve() executes a new program after the asm stub has set
+ * things up for us.  This should basically do what I want it to.
  */
-asmlinkage int sys_execve(struct pt_regs regs)
+asmlinkage int sparc_execve(struct pt_regs *regs)
 {
-  printk("sys_execve()... halting\n");
-  halt();
-  return 0;
+	int error;
+	char *filename;
+
+	flush_user_windows();
+	mmu_task_cacheflush(current);
+	error = getname((char *) regs->u_regs[UREG_I0], &filename);
+	if(error)
+		return error;
+	error = do_execve(filename, (char **) regs->u_regs[UREG_I1],
+			  (char **) regs->u_regs[UREG_I2], regs);
+	putname(filename);
+	return error;
 }
 
+void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
+{
+	unsigned long saved_psr = (regs->psr & (PSR_CWP)) | PSR_S;
+
+	memset(regs, 0, sizeof(struct pt_regs));
+	regs->pc = ((pc & (~3)) - 4); /* whee borken a.out header fields... */
+	regs->npc = regs->pc + 4;
+	regs->psr = saved_psr;
+	regs->u_regs[UREG_G1] = sp; /* Base of arg/env stack area */
+
+	/* XXX More mysterious netbsd garbage... XXX */
+	regs->u_regs[UREG_G2] = regs->u_regs[UREG_G7] = regs->npc;
+
+	/* Allocate one reg window because the first jump into
+	 * user mode will restore one register window by definition
+	 * of the 'rett' instruction.  Also, SunOS crt.o code
+	 * depends upon the arg/envp area being _exactly_ one
+	 * register window above %sp when the process begins
+	 * execution.
+	 */
+	sp -= REGWIN_SZ;
+	regs->u_regs[UREG_FP] = sp;
+}
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/kernel/promops.c linux/arch/sparc/kernel/promops.c
--- v1.3.43/linux/arch/sparc/kernel/promops.c	Sun Feb 26 20:46:20 1995
+++ linux/arch/sparc/kernel/promops.c	Thu Jan  1 02:00:00 1970
@@ -1,107 +0,0 @@
-/* promops.c:  Prom node tree operations and Prom Vector initialization
- *             initialization routines.
- *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- */
-
-#include <linux/kernel.h>
-
-#include <asm/openprom.h>
-
-/* #define DEBUG_PROMOPS */
-#define MAX_PR_LEN   64           /* exotic hardware probably overshoots this */
-
-int prom_node_root;               /* initialized in init_prom */
-
-extern struct linux_romvec *romvec;
-
-/* These two functions return and siblings and direct child descendents
- * in the prom device tree respectively.
- */
-
-int
-node_get_sibling(int node)
-{
-  return (*(romvec->pv_nodeops->no_nextnode))(node);
-}
-
-int
-node_get_child(int node)
-{
-  return (*(romvec->pv_nodeops->no_child))(node);
-}
-
-/* The following routine is used during device probing to determine
- * an integer value property about a (perhaps virtual) device. This
- * could be anything, like the size of the mmu cache lines, etc.
- * the default return value is -1 is the prom has nothing interesting.
- */
-
-unsigned int prom_int_null;
-
-unsigned int *
-get_int_from_prom(int node, char *nd_prop, unsigned int *value)
-{
-  unsigned int pr_len;
-
-  *value = &prom_int_null;    /* duh, I was returning -1 as an unsigned int, prom_panic() */
-
-  pr_len = romvec->pv_nodeops->no_proplen(node, nd_prop);
-  if(pr_len > MAX_PR_LEN)
-    {
-#ifdef DEBUG_PROMOPS
-      printk("Bad pr_len in promops -- node: %d nd_prop: %s pr_len: %d",
-	     node, nd_prop, (int) pr_len);
-#endif
-      return value;      /* XXX */
-    }
-
-  romvec->pv_nodeops->no_getprop(node, nd_prop, (char *) value);
-
-  return value;
-}
-
-
-/* This routine returns what is termed a property string as opposed
- * to a property integer as above. This can be used to extract the
- * 'type' of device from the prom. An example could be the clock timer
- * chip type. By default you get returned a null string if garbage
- * is returned from the prom.
- */
-
-char *
-get_str_from_prom(int node, char *nd_prop, char *value)
-{
-  unsigned int pr_len;
-
-  *value='\n';
-
-  pr_len = romvec->pv_nodeops->no_proplen(node, nd_prop);
-  if(pr_len > MAX_PR_LEN)
-    {
-#ifdef DEBUG_PROMOPS
-      printk("Bad pr_len in promops -- node: %d nd_prop: %s pr_len: %d",
-	     node, nd_prop, pr_len);
-#endif
-      return value;      /* XXX */
-    }
-
-  romvec->pv_nodeops->no_getprop(node, nd_prop, value);
-  value[pr_len] = 0;
-
-  return value;
-}
-
-/* This gets called from head.S upon bootup to initialize the
- * prom vector pointer for the rest of the kernel.
- */
-
-void
-init_prom(struct linux_romvec *r_ptr)
-{
-  romvec = r_ptr;
-  prom_node_root = romvec->pv_nodeops->no_nextnode(0);
-  prom_int_null = 0;
-  
-  return;
-}
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/kernel/rtrap.S linux/arch/sparc/kernel/rtrap.S
--- v1.3.43/linux/arch/sparc/kernel/rtrap.S	Thu Jan  1 02:00:00 1970
+++ linux/arch/sparc/kernel/rtrap.S	Sat Nov 25 02:58:21 1995
@@ -0,0 +1,332 @@
+/* $Id: rtrap.S,v 1.11 1995/11/25 00:58:19 davem Exp $
+ * rtrap.S: Return from Sparc trap low-level code.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#include <asm/cprefix.h>
+#include <asm/page.h>
+#include <asm/ptrace.h>
+#include <asm/psr.h>
+#include <asm/asi.h>
+#include <asm/contregs.h>
+#include <asm/winmacro.h>
+
+#define t_psr     l0
+#define t_pc      l1
+#define t_npc     l2
+#define t_wim     l3
+#define twin_tmp1 l4
+#define twin_tmp2 l5
+#define twin_tmp3 l6
+
+	/* 7 WINDOW SPARC PATCH INSTRUCTIONS */
+	.globl	rtrap_7win_patch1, rtrap_7win_patch2, rtrap_7win_patch3
+	.globl	rtrap_7win_patch4, rtrap_7win_patch5
+rtrap_7win_patch1:	srl	%t_wim, 0x6, %twin_tmp2
+rtrap_7win_patch2:	and	%twin_tmp2, 0x7f, %twin_tmp2
+rtrap_7win_patch3:	srl	%g1, 7, %g2
+rtrap_7win_patch4:	srl	%g2, 6, %g2
+rtrap_7win_patch5:	and	%g1, 0x7f, %g1
+	/* END OF PATCH INSTRUCTIONS */
+
+	/* We need to check for a few things which are:
+	 * 1) The need to call schedule() because this
+	 *    processes quantum is up.
+	 * 2) Pending signals for this process, if any
+	 *    exist we need to call do_signal() to do
+	 *    the needy.
+	 *
+	 * Else we just check if the rett would land us
+	 * in an invalid window, if so we need to grab
+	 * it off the user/kernel stack first.
+	 */
+
+	.globl	ret_trap_entry, rtrap_patch1, rtrap_patch2
+	.globl	rtrap_patch3, rtrap_patch4, rtrap_patch5
+ret_trap_entry:
+	ld	[%sp + STACKFRAME_SZ + PT_PSR], %t_psr
+	andcc	%t_psr, PSR_PS, %g0
+	bne	ret_trap_kernel
+	 nop
+
+	sethi	%hi(C_LABEL(need_resched)), %twin_tmp1
+	ld	[%twin_tmp1 + %lo(C_LABEL(need_resched))], %twin_tmp2
+	LOAD_CURRENT(twin_tmp1)
+
+	cmp	%twin_tmp2, 0x0
+	be	signal_p
+	 nop
+
+	call	C_LABEL(schedule)
+	 nop
+
+	/* Try to return again... We are a different process,
+	 * most likely so load and then check if going back
+	 * to user or kernel this time.
+	 */
+	b	ret_trap_entry
+	 nop
+
+signal_p:
+	/* No signals for swapper. */
+	sethi	%hi(C_LABEL(init_task)), %twin_tmp3
+	or	%twin_tmp3, %lo(C_LABEL(init_task)), %twin_tmp3
+	cmp	%twin_tmp3, %twin_tmp1
+	be	ret_trap_continue
+	 nop
+
+	ld	[%twin_tmp1 + TASK_SIGNAL], %twin_tmp2
+	ld	[%twin_tmp1 + TASK_BLOCKED], %twin_tmp3
+	andncc	%twin_tmp2, %twin_tmp3, %twin_tmp2
+	be	ret_trap_continue
+	 nop
+
+	mov	%twin_tmp2, %o0		! oldmask
+	add	%sp, STACKFRAME_SZ, %o1	! pt_regs ptr
+	call	C_LABEL(do_signal)
+	 nop
+
+	/* Fall through... */
+ret_trap_continue:
+	wr	%t_psr, 0x0, %psr
+	WRITE_PAUSE
+
+	LOAD_CURRENT(twin_tmp2)
+	ld	[%twin_tmp2 + THREAD_W_SAVED], %twin_tmp1
+	orcc	%g0, %twin_tmp1, %g0
+	be	ret_trap_nobufwins
+	 nop
+
+	wr	%t_psr, 0x0, %psr
+	wr	%t_psr, PSR_ET, %psr
+	WRITE_PAUSE
+
+	mov	1, %o1
+	call	C_LABEL(do_sparc_winfault)
+	 add	%sp, STACKFRAME_SZ, %o0
+
+	b	ret_trap_entry
+	 nop
+
+ret_trap_nobufwins:
+	/* Load up the user's out registers so we can pull
+	 * a window from the stack, if necessary.
+	 */
+	LOAD_PT_INS(sp)
+
+	/* If there are already live user windows in the
+	 * set we can return from trap safely.
+	 */
+	ld	[%twin_tmp2 + THREAD_UMASK], %twin_tmp1
+	orcc	%g0, %twin_tmp1, %g0
+	bne	ret_trap_userwins_ok
+	 nop
+	
+		/* Calculate new %wim, we have to pull a register
+		 * window from the users stack.
+		 */
+		rd	%wim, %t_wim
+		sll	%t_wim, 0x1, %twin_tmp1
+rtrap_patch1:	srl	%t_wim, 0x7, %twin_tmp2
+		or	%twin_tmp2, %twin_tmp1, %twin_tmp2
+rtrap_patch2:	and	%twin_tmp2, 0xff, %twin_tmp2
+
+		wr	%twin_tmp2, 0x0, %wim
+		WRITE_PAUSE
+
+				/* Here comes the architecture specific 
+				 * branch to the user stack checking routine
+				 * for return from traps.
+				 */
+				.globl	C_LABEL(rtrap_mmu_patchme)
+C_LABEL(rtrap_mmu_patchme):	b	C_LABEL(sun4c_rett_stackchk)
+				 andcc	%fp, 0x7, %g0	
+
+ret_trap_userwins_ok:
+	LOAD_PT_PRIV(sp, t_psr, t_pc, t_npc)
+	or	%t_pc, %t_npc, %g2
+	andcc	%g2, 0x3, %g0
+	bne	ret_trap_unaligned_pc
+	 nop
+
+	LOAD_PT_YREG(sp, g1)
+	LOAD_PT_GLOBALS(sp)
+
+	wr	%t_psr, 0x0, %psr
+	WRITE_PAUSE
+
+	jmp	%t_pc
+	rett	%t_npc
+	
+ret_trap_unaligned_pc:
+	add	%sp, STACKFRAME_SZ, %o0
+	ld	[%sp + STACKFRAME_SZ + PT_PC], %o1
+	ld	[%sp + STACKFRAME_SZ + PT_NPC], %o2
+	ld	[%sp + STACKFRAME_SZ + PT_PSR], %o3
+
+	wr	%t_psr, 0x0, %psr
+	wr	%t_psr, PSR_ET, %psr
+	WRITE_PAUSE
+
+	call	C_LABEL(do_memaccess_unaligned)
+	 nop
+
+	b	ret_trap_entry
+	 nop
+
+ret_trap_kernel:
+	wr	%t_psr, 0x0, %psr
+	WRITE_PAUSE
+
+		/* Will the rett land us in the invalid window? */
+		mov	2, %g1
+		sll	%g1, %t_psr, %g1
+rtrap_patch3:	srl	%g1, 8, %g2
+		or	%g1, %g2, %g1
+		rd	%wim, %g2
+		andcc	%g2, %g1, %g0
+		be	1f		! Nope, just return from the trap
+		 nop
+
+		/* We have to grab a window before returning. */
+		sll	%g2, 0x1, %g1
+rtrap_patch4:	srl	%g2, 7,  %g2
+		or	%g1, %g2, %g1
+rtrap_patch5:	and	%g1, 0xff, %g1
+
+	wr	%g1, 0x0, %wim
+	WRITE_PAUSE
+
+	restore	%g0, %g0, %g0
+	LOAD_WINDOW(sp)
+	save	%g0, %g0, %g0
+
+	/* Reload the entire frame in case this is from a
+	 * kernel system call or whatever...
+	 */
+1:
+	LOAD_PT_ALL(sp, t_psr, t_pc, t_npc, g1)
+
+	wr	%t_psr, 0x0, %psr
+	WRITE_PAUSE
+
+	jmp	%t_pc
+	rett	%t_npc
+
+ret_trap_user_stack_is_bolixed:
+	wr	%t_wim, 0x0, %wim
+	WRITE_PAUSE
+
+	wr	%t_psr, 0x0, %psr
+	wr	%t_psr, PSR_ET, %psr
+	WRITE_PAUSE
+
+	mov	0, %o1
+	call	C_LABEL(do_sparc_winfault)
+	 add	%sp, STACKFRAME_SZ, %o0
+
+	/* Try it all again. */
+	b	ret_trap_entry
+	 nop
+
+	.globl	C_LABEL(sun4c_rett_stackchk)
+C_LABEL(sun4c_rett_stackchk):
+	be	1f
+	 and	%fp, 0xfff, %g1		! delay slot
+
+	b	ret_trap_user_stack_is_bolixed
+	 nop
+
+	/* See if we have to check the sanity of one page or two */
+1:
+	add	%g1, 0x38, %g1
+	sra	%fp, 29, %g2
+	add	%g2, 0x1, %g2
+	andncc	%g2, 0x1, %g0
+	be	1f
+	 andncc	%g1, 0xff8, %g0
+
+	/* %sp is in vma hole, yuck */
+	b	ret_trap_user_stack_is_bolixed
+	 nop
+
+1:
+	be	sun4c_rett_onepage	/* Only one page to check */
+	 lda	[%fp] ASI_PTE, %g2
+
+sun4c_rett_twopages:
+	add	%fp, 0x38, %g1
+	sra	%g1, 29, %g2
+	add	%g2, 0x1, %g2
+	andncc	%g2, 0x1, %g0
+	be	1f
+	 lda	[%g1] ASI_PTE, %g2
+
+	/* Second page is in vma hole */
+	b	ret_trap_user_stack_is_bolixed
+	 nop
+
+1:
+	srl	%g2, 29, %g2
+	andcc	%g2, 0x4, %g0
+	bne	sun4c_rett_onepage
+	 lda	[%fp] ASI_PTE, %g2
+
+	/* Second page has bad perms */
+	b	ret_trap_user_stack_is_bolixed
+	 nop
+
+sun4c_rett_onepage:
+	srl	%g2, 29, %g2
+	andcc	%g2, 0x4, %g0
+	bne	1f
+	 nop
+
+	/* A page had bad page permissions, losing... */
+	b	ret_trap_user_stack_is_bolixed
+	 nop
+
+	/* Whee, things are ok, load the window and continue. */
+1:
+	restore	%g0, %g0, %g0
+
+	LOAD_WINDOW(sp)
+
+	save	%g0, %g0, %g0
+	b	ret_trap_userwins_ok
+	 nop
+
+	.globl	C_LABEL(sun4c_rett_stackchk)
+C_LABEL(srmmu_rett_stackchk):
+	bne	ret_trap_user_stack_is_bolixed
+	 sethi	%hi(KERNBASE), %g1
+	cmp	%g1, %fp
+	bleu	ret_trap_user_stack_is_bolixed
+	 mov	AC_M_SFSR, %g1
+	lda	[%g1] ASI_M_MMUREGS, %g0
+
+	lda	[%g0] ASI_M_MMUREGS, %g1
+	or	%g1, 0x2, %g1
+	sta	%g1, [%g0] ASI_M_MMUREGS
+
+	restore	%g0, %g0, %g0
+
+	LOAD_WINDOW(sp)
+
+	save	%g0, %g0, %g0
+
+	andn	%g1, 0x2, %g1
+	sta	%g1, [%g0] ASI_M_MMUREGS
+
+	mov	AC_M_SFAR, %g2
+	lda	[%g2] ASI_M_MMUREGS, %g2
+
+	mov	AC_M_SFSR, %g1
+	lda	[%g1] ASI_M_MMUREGS, %g1
+	andcc	%g1, 0x2, %g0
+	bne	ret_trap_user_stack_is_bolixed
+	 nop
+
+	b	ret_trap_userwins_ok
+	 nop
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/kernel/setup.c linux/arch/sparc/kernel/setup.c
--- v1.3.43/linux/arch/sparc/kernel/setup.c	Tue Jun 27 14:11:32 1995
+++ linux/arch/sparc/kernel/setup.c	Sat Nov 25 02:58:23 1995
@@ -1,13 +1,9 @@
-/*
- *  linux/arch/alpha/kernel/setup.c
+/*  $Id: setup.c,v 1.41 1995/11/25 00:58:21 davem Exp $
+ *  linux/arch/sparc/kernel/setup.c
  *
  *  Copyright (C) 1995  David S. Miller (davem@caip.rutgers.edu)
  */
 
-/*
- * bootup setup stuff..
- */
-
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
@@ -24,27 +20,25 @@
 #include <asm/segment.h>
 #include <asm/system.h>
 #include <asm/io.h>
+#include <asm/kgdb.h>
 #include <asm/processor.h>
-#include <asm/oplib.h>    /* The PROM is your friend... */
+#include <asm/oplib.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/traps.h>
 #include <asm/vaddrs.h>
 #include <asm/kdebug.h>
 
-extern unsigned long probe_devices(unsigned long);
-
-/*
- * Gcc is hard to keep happy ;-)
- */
 struct screen_info screen_info = {
 	0, 0,			/* orig-x, orig-y */
 	{ 0, 0, },		/* unused */
 	0,			/* orig-video-page */
 	0,			/* orig-video-mode */
-	80,			/* orig-video-cols */
+	128,			/* orig-video-cols */
 	0,0,0,			/* ega_ax, ega_bx, ega_cx */
-	25			/* orig-video-lines */
+	54,			/* orig-video-lines */
+	0,                      /* orig-video-isVGA */
+	16                      /* orig-video-points */
 };
 
 char wp_works_ok = 0;
@@ -54,43 +48,45 @@
 	return memory_start;
 }
 
-/* Lame prom console routines, gets registered below. Thanks for the
- * tip Linus.  We now use a generic putchar prom routine through the
- * linux prom library.
- */
-
-void sparc_console_print(const char * p)
-{
-  unsigned char c;
-
-	while ((c = *(p++)) != 0)
-	  {
-	    if (c == '\n')
-	      prom_putchar('\r');
-	    prom_putchar(c);
-	  }
-
-  return;
-
-}
-
 /* Typing sync at the prom promptcalls the function pointed to by
  * romvec->pv_synchook which I set to the following function.
  * This should sync all filesystems and return, for now it just
  * prints out pretty messages and returns.
  */
+
+extern unsigned long trapbase;
+
+/* Pretty sick eh? */
 void prom_sync_me(void)
 {
-	printk("PROM SYNC COMMAND...\n");
+	unsigned long prom_tbr, flags;
+
+	save_flags(flags); cli();
+	__asm__ __volatile__("rd %%tbr, %0\n\t" : "=r" (prom_tbr));
+	__asm__ __volatile__("wr %0, 0x0, %%tbr\n\t"
+			     "nop\n\t"
+			     "nop\n\t"
+			     "nop\n\t" : : "r" (&trapbase));
+
+	prom_printf("PROM SYNC COMMAND...\n");
 	show_free_areas();
-	printk("Returning to prom\n");
+	prom_printf("Returning to prom\n");
+
+	__asm__ __volatile__("wr %0, 0x0, %%tbr\n\t"
+			     "nop\n\t"
+			     "nop\n\t"
+			     "nop\n\t" : : "r" (prom_tbr));
+	restore_flags(flags);
+
 	return;
 }
 
+extern void rs_kgdb_hook(int tty_num); /* sparc/serial.c */
+
 unsigned int boot_flags;
 #define BOOTME_DEBUG  0x1
 #define BOOTME_SINGLE 0x2
-#define BOOTME_KGDB   0x3
+#define BOOTME_KGDB   0x4
 
 /* This routine does no error checking, make sure your string is sane
  * before calling this!
@@ -100,8 +96,8 @@
 boot_flags_init(char *commands)
 {
 	int i;
-	for(i=0; i<strlen(commands); i++)
-		if(commands[i]=='-')
+	for(i=0; i<strlen(commands); i++) {
+		if(commands[i]=='-') {
 			switch(commands[i+1]) {
 			case 'd':
 				boot_flags |= BOOTME_DEBUG;
@@ -110,19 +106,34 @@
 				boot_flags |= BOOTME_SINGLE;
 				break;
 			case 'h':
-				printk("boot_flags_init: Found halt flag, doing so now...\n");
+				prom_printf("boot_flags_init: Found halt flag, doing so now...\n");
 				halt();
 				break;
-			case 'k':
-				printk("Found KGDB boot flag...\n");
-				boot_flags |= BOOTME_KGDB;
-				break;
 			default:
 				printk("boot_flags_init: Unknown boot arg (-%c)\n",
 				       commands[i+1]);
 				break;
 			};
-
+		} else {
+			if(commands[i]=='k' && commands[i+1]=='g' &&
+			   commands[i+2]=='d' && commands[i+3]=='b' &&
+			   commands[i+4]=='=' && commands[i+5]=='t' &&
+			   commands[i+6]=='t' && commands[i+7]=='y') {
+				printk("KGDB: Using serial line /dev/tty%c for "
+				       "session\n", commands[i+8]);
+				boot_flags |= BOOTME_KGDB;
+				if(commands[i+8]=='a')
+					rs_kgdb_hook(0);
+				else if(commands[i+8]=='b')
+					rs_kgdb_hook(1);
+				else {
+					printk("KGDB: whoops bogon tty line "
+					       "requested, disabling session\n");
+					boot_flags &= (~BOOTME_KGDB);
+				}
+			}
+		}
+	}
 	return;
 }
 
@@ -132,47 +143,29 @@
  * physical memory probe as on the alpha.
  */
 
-extern void register_console(void (*proc)(const char *));
 extern void load_mmu(void);
 extern int prom_probe_memory(void);
-extern void probe_mmu(int node);
+extern void probe_vac(void);
 extern void get_idprom(void);
-extern void srmmu_patch_fhandlers(void);
-extern unsigned int prom_iface_vers, end_of_phys_memory, phys_bytes_of_ram;
+extern unsigned int end_of_phys_memory;
 extern char cputypval;
-extern unsigned long start;
+extern unsigned long start, end, bootup_stack, bootup_kstack;
+
+
 char sparc_command_line[256];  /* Should be enough */
 enum sparc_cpu sparc_cpu_model;
 
 struct tt_entry *sparc_ttable;
 
-/* #define DEBUG_CMDLINE */
-
 void setup_arch(char **cmdline_p,
 	unsigned long * memory_start_p, unsigned long * memory_end_p)
 {
-	int counter, total, i, node;
-	char devtype[64];
+	int total, i;
 
 	sparc_ttable = (struct tt_entry *) &start;
 
-	register_console(sparc_console_print);
-
 	/* Initialize PROM console and command line. */
 	*cmdline_p = prom_getbootargs();
-	boot_flags_init(*cmdline_p);
-
-	/* Synchronize with debugger if necessary.  Grrr, have to check
-	 * the boot flags too. ;(
-	 */
-	if((boot_flags&BOOTME_DEBUG) && (linux_dbvec!=0) && 
-	   ((*(short *)linux_dbvec) != -1)) {
-		printk("Booted under debugger. Syncing up trap table.\n");
-		/* Sync us up... */
-		(*(linux_dbvec->teach_debugger))();
-
-		SP_ENTER_DEBUGGER;
-	}
 
 	/* Set sparc_cpu_model */
 	sparc_cpu_model = sun_unknown;
@@ -185,23 +178,10 @@
 	switch(sparc_cpu_model)
 	  {
 	  case sun4c:
-		  memset(phys_seg_map, 0x0, sizeof(phys_seg_map[PSEG_ENTRIES]));
-		  put_segmap(IOBASE_VADDR, IOBASE_SUN4C_SEGMAP);
-		  phys_seg_map[IOBASE_SUN4C_SEGMAP] = PSEG_RSV;
-		  node = prom_root_node;
-
 		  printk("SUN4C\n");
+		  probe_vac();
 		  break;
           case sun4m:
-		  node = prom_getchild(prom_root_node);
-		  prom_getproperty(node, "device_type", devtype, sizeof(devtype));
-		  while(strcmp(devtype, "cpu") != 0) {
-			  node = prom_getsibling(node);
-			  prom_getproperty(node, "device_type", devtype,
-					   sizeof(devtype));
-		  }
-		  /* Patch trap table. */
-		  srmmu_patch_fhandlers();
 		  printk("SUN4M\n");
 		  break;
 	  case sun4d:
@@ -218,51 +198,69 @@
 		  break;
 	  };
 
-	/* probe_devices() expects this to be done. */
-	get_idprom();
-
-	/* Probe the mmu constants. */
-	probe_mmu(node);
+	boot_flags_init(*cmdline_p);
+	if((boot_flags&BOOTME_DEBUG) && (linux_dbvec!=0) && 
+	   ((*(short *)linux_dbvec) != -1)) {
+		printk("Booted under KADB. Syncing trap table.\n");
+		(*(linux_dbvec->teach_debugger))();
+	}
+	if((boot_flags & BOOTME_KGDB)) {
+		set_debug_traps();
+		breakpoint();
+	}
 
-	/* Set pointers to memory management routines. */
+	get_idprom();
 	load_mmu();
-
-	/* Probe for memory. */
 	total = prom_probe_memory();
 	*memory_start_p = (((unsigned long) &end));
-
 	printk("Physical Memory: %d bytes (in hex %08lx)\n", (int) total,
-	       (unsigned long) total);
+		    (unsigned long) total);
 
 	for(i=0; sp_banks[i].num_bytes != 0; i++) {
 #if 0
 		printk("Bank %d:  base 0x%x  bytes %d\n", i,
-		       (unsigned int) sp_banks[i].base_addr, 
-		       (int) sp_banks[i].num_bytes);
+			    (unsigned int) sp_banks[i].base_addr, 
+			    (int) sp_banks[i].num_bytes);
 #endif
 		end_of_phys_memory = sp_banks[i].base_addr + sp_banks[i].num_bytes;
 	}
 
-	/* Set prom sync hook pointer */
 	prom_setsync(prom_sync_me);
 
-	init_task.mm->start_code = PAGE_OFFSET;
-	init_task.mm->end_code = PAGE_OFFSET + (unsigned long) &etext;
-	init_task.mm->end_data = PAGE_OFFSET + (unsigned long) &edata;
-	init_task.mm->brk = PAGE_OFFSET + (unsigned long) &end;
+	/* Due to stack alignment restrictions and assumptions... */
 	init_task.mm->mmap->vm_page_prot = PAGE_SHARED;
 
-	/* Grrr, wish I knew why I have to do this ;-( */
-	for(counter=1; counter<NR_TASKS; counter++) {
-		task[counter] = NULL;
-	}
-
-	*memory_end_p = (((unsigned long) (total) + PAGE_OFFSET));
+	*memory_end_p = (end_of_phys_memory + PAGE_OFFSET);
 
-	return;
+	{
+		extern int serial_console;  /* in console.c, of course */
+		int idev = prom_query_input_device();
+		int odev = prom_query_output_device();
+		if (idev == PROMDEV_IKBD && odev == PROMDEV_OSCREEN) {
+			serial_console = 0;
+		} else if (idev == PROMDEV_ITTYA && odev == PROMDEV_OTTYA) {
+			serial_console = 1;
+		} else if (idev == PROMDEV_ITTYB && odev == PROMDEV_OTTYB) {
+			prom_printf("Console on ttyb is not supported\n");
+			prom_halt();
+		} else {
+			prom_printf("Inconsistent console\n");
+			prom_halt();
+		}
+	}
 }
 
 asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on)
 {
 	return -EIO;
+}
+
+/*
+ * BUFFER is PAGE_SIZE bytes long.
+ *
+ * XXX Need to do better than this! XXX
+ */
+int get_cpuinfo(char *buffer)
+{
+	return sprintf(buffer, "Sparc RISC\n");
 }
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/kernel/signal.c linux/arch/sparc/kernel/signal.c
--- v1.3.43/linux/arch/sparc/kernel/signal.c	Sun Jan 22 23:02:31 1995
+++ linux/arch/sparc/kernel/signal.c	Sat Nov 25 02:58:25 1995
@@ -1,4 +1,4 @@
-/*
+/*  $Id: signal.c,v 1.19 1995/11/25 00:58:24 davem Exp $
  *  linux/arch/sparc/kernel/signal.c
  *
  *  Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -11,48 +11,239 @@
 #include <linux/wait.h>
 #include <linux/ptrace.h>
 #include <linux/unistd.h>
+#include <linux/mm.h>
 
 #include <asm/segment.h>
+#include <asm/bitops.h>
+#include <asm/ptrace.h>
 
 #define _S(nr) (1<<((nr)-1))
 
 #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
 
-asmlinkage int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options);
+asmlinkage int sys_waitpid(pid_t pid, unsigned long *stat_addr, int options);
+asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs);
 
 /*
  * atomically swap in the new signal mask, and wait for a signal.
+ * This is really tricky on the Sparc, watch out...
  */
-asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, unsigned long set)
+asmlinkage inline int _sigpause_common(unsigned int set, struct pt_regs *regs)
 {
 	unsigned long mask;
-	struct pt_regs * regs = (struct pt_regs *) &restart;
 
 	mask = current->blocked;
 	current->blocked = set & _BLOCKABLE;
+	/* Advance over the syscall instruction for when
+	 * we return.  We want setup_frame to save the proper
+	 * state, but then below we set ourselves backwards
+	 * to compensate for what ret_sys_call does. Ick!
+	 */
+	regs->pc += 4;
+	regs->npc += 4;
 
 	while (1) {
 		current->state = TASK_INTERRUPTIBLE;
 		schedule();
-		if (do_signal(mask,regs))
+		if (do_signal(mask, regs)) {
+			/* If we actually post the signal then we
+			 * will get our PCs advanced in entry.S, to
+			 * compensate we throw the PCs back one insn.
+			 */
+			regs->pc -= 4;
+			regs->npc -= 4;
 			return -EINTR;
+		}
 	}
 }
 
-asmlinkage int sys_sigreturn(unsigned long __unused)
+asmlinkage int sys_sigpause(unsigned int set)
+{
+	struct pt_regs *regs;
+	unsigned long fp;
+
+	__asm__ __volatile__("mov %%fp, %0\n\t" :
+			     "=r" (fp));
+	regs = ((struct pt_regs *) (fp + STACKFRAME_SZ));
+	return _sigpause_common(set, regs);
+}
+
+asmlinkage int sys_sigsuspend(unsigned int *sigmaskp)
+{
+	struct pt_regs *regs;
+	unsigned long fp;
+	unsigned int set;
+
+	__asm__ __volatile__("mov %%fp, %0\n\t" :
+			     "=r" (fp));
+	regs = ((struct pt_regs *) (fp + STACKFRAME_SZ));
+	if(verify_area(VERIFY_READ, sigmaskp, sizeof(unsigned int)))
+		return -EFAULT;
+	set = *sigmaskp;
+	return _sigpause_common(set, regs);
+}
+
+extern unsigned long nwindows;
+
+asmlinkage void do_sigreturn(struct pt_regs *regs)
 {
-  halt();
-  return 0;
+	int wsvd;
+	struct sigcontext_struct *scptr =
+		(struct sigcontext_struct *) regs->u_regs[UREG_I0];
+
+	/* Make the stack consistant. */
+	flush_user_windows();
+
+	/* Check sanity of the user arg. */
+	if(verify_area(VERIFY_READ, scptr, sizeof(struct sigcontext_struct)) ||
+	   ((((unsigned long) scptr)) & 0x3))
+		do_exit(SIGSEGV);
+
+	if((scptr->sigc_pc | scptr->sigc_npc) & 3)
+		return; /* Nice try. */
+
+	current->blocked = scptr->sigc_mask & _BLOCKABLE;
+	current->tss.sstk_info.cur_status = (scptr->sigc_onstack & 0x1);
+	regs->pc = scptr->sigc_pc;
+	regs->npc = scptr->sigc_npc;
+	regs->u_regs[UREG_FP] = scptr->sigc_sp;
+	regs->u_regs[UREG_I0] = scptr->sigc_o0;
+	regs->u_regs[UREG_G1] = scptr->sigc_g1;
+
+	/* User can only change condition codes in %psr. */
+	regs->psr &= (~PSR_ICC);
+	regs->psr |= (scptr->sigc_psr & PSR_ICC);
+}
+
+/* I love register windows...
+ * Basically, this tries to get as many of the current user
+ * windows on the stack as possible, even if unaligned.  Failing
+ * that the windows end up in the per-task window save buffer
+ * in the thread struct, these will be copied onto the signal
+ * stack for possible inspection by the process.
+ */
+static inline void
+do_magic_sparc_stuff(void)
+{
+	unsigned long sp;
+	int this_win;
+
+	flush_user_windows();
+	this_win = (current->tss.w_saved - 1);
+	while(this_win >= 0) {
+		sp = current->tss.rwbuf_stkptrs[this_win];
+		if(!(sp & 7) && !verify_area(VERIFY_WRITE, (char *)sp,
+		                             sizeof(struct reg_window))) {
+			memcpy((char *)sp,
+			       (char *)&current->tss.reg_window[this_win],
+			       sizeof(struct reg_window));
+			current->tss.w_saved--;
+			memcpy((char *)&current->tss.reg_window[this_win],
+			       (char *)&current->tss.reg_window[this_win+1],
+			       (sizeof(struct reg_window) *
+			       (current->tss.w_saved-this_win)));
+		}
+		this_win -= 1;
+	}
 }
 
 /*
- * Set up a signal frame... Make the stack look the way iBCS2 expects
- * it to look.
+ * Set up a signal frame... Make the stack look the way SunOS
+ * expects it to look which is basically:
+ *
+ * ---------------------------------- <-- %sp at signal time
+ * Struct sigcontext
+ * Signal address
+ * Ptr to sigcontext area above
+ * Signal code
+ * The signal number itself
+ * One register window
+ * ---------------------------------- <-- New %sp
  */
-void setup_frame(struct sigaction * sa, unsigned long ** fp, unsigned long eip,
-	struct pt_regs * regs, int signr, unsigned long oldmask)
+struct signal_sframe {
+	struct reg_window sig_window;
+	int sig_num;
+	int sig_code;
+	struct sigcontext_struct *sig_scptr;
+	int sig_address;
+	struct sigcontext_struct sig_context;
+};
+/* To align the structure properly. */
+#define SF_ALIGNEDSZ  (((sizeof(struct signal_sframe) + 7) & (~7)))
+
+static inline void
+setup_frame(struct sigaction *sa, struct sigcontext_struct **fp,
+	    unsigned long pc, struct pt_regs *regs, int signr,
+	    unsigned long oldmask)
 {
-  halt();
+	struct signal_sframe *sframep;
+	struct sigcontext_struct *sc;
+	int window = 0;
+	int old_status = current->tss.sstk_info.cur_status;
+
+	sframep = (struct signal_sframe *) *fp;
+	sframep = (struct signal_sframe *) (((unsigned long) sframep)-SF_ALIGNEDSZ);
+	sc = &sframep->sig_context;
+	if(verify_area(VERIFY_WRITE, sframep, sizeof(*sframep)) ||
+	   (((unsigned long) sframep) & 7) ||
+	   (((unsigned long) sframep) >= KERNBASE)) {
+		printk("%s [%d]: User has trashed signal stack\n",
+		       current->comm, current->pid);
+		printk("Sigstack ptr %p handler at pc<%08lx> for sig<%d>\n",
+		       sframep, pc, signr);
+		show_regs(regs);
+		/* Don't change signal code and address, so that
+		 * post mortem debuggers can have a look.
+		 */
+		current->sig->action[SIGILL-1].sa_handler = SIG_DFL;
+		current->blocked &= ~(1<<(SIGILL-1));
+		send_sig(SIGILL,current,1);
+		return;
+	}
+	*fp = (struct sigcontext_struct *) sframep;
+	do_magic_sparc_stuff();
+
+	sc->sigc_onstack = old_status;
+	sc->sigc_mask = oldmask;
+	sc->sigc_sp = regs->u_regs[UREG_FP];
+	sc->sigc_pc = regs->pc;
+	sc->sigc_npc = regs->npc;
+	sc->sigc_psr = regs->psr;
+	sc->sigc_g1 = regs->u_regs[UREG_G1];
+	sc->sigc_o0 = regs->u_regs[UREG_I0];
+	sc->sigc_oswins = current->tss.w_saved;
+	if(current->tss.w_saved)
+		for(window = 0; window < current->tss.w_saved; window++) {
+			sc->sigc_spbuf[window] =
+				(char *)current->tss.rwbuf_stkptrs[window];
+			memcpy(&sc->sigc_wbuf[window],
+			       &current->tss.reg_window[window],
+			       sizeof(struct reg_window));
+		}
+	else
+		/* This is so that gdb and friends can trace back
+		 * through the stack properly.  An alternative
+		 * is to set the fp in this new window to the
+		 * sp of the frame at the time of the signal and
+		 * I see some problems with that maneuver.
+		 */
+		memcpy(sframep, (char *)regs->u_regs[UREG_FP],
+		       sizeof(struct reg_window));
+
+	current->tss.w_saved = 0; /* So process is allowed to execute. */
+	sframep->sig_num = signr;
+	if(signr == SIGSEGV ||
+	   signr == SIGILL ||
+	   signr == SIGFPE ||
+	   signr == SIGBUS ||
+	   signr == SIGEMT) {
+		sframep->sig_code = current->tss.sig_desc;
+		sframep->sig_address = current->tss.sig_address;
+	} else {
+		sframep->sig_code = 0;
+		sframep->sig_address = 0;
+	}
+	sframep->sig_scptr = sc;
 }
 
 /*
@@ -64,8 +255,115 @@
  * the kernel can handle, and then we build all the user-level signal handling
  * stack-frames in one go after that.
  */
+
 asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
 {
-  halt();
-  return 1;
+	unsigned long mask = ~current->blocked;
+	unsigned long handler_signal = 0;
+	struct sigcontext_struct *frame = NULL;
+	unsigned long pc = 0;
+	unsigned long signr;
+	struct sigaction *sa;
+
+	while ((signr = current->signal & mask) != 0) {
+		signr = ffz(~signr);
+		clear_bit(signr, &current->signal);
+		sa = current->sig->action + signr;
+		signr++;
+		if((current->flags & PF_PTRACED) && signr != SIGKILL) {
+			current->exit_code = signr;
+			current->state = TASK_STOPPED;
+			notify_parent(current);
+			schedule();
+			if(!(signr = current->exit_code))
+				continue;
+			current->exit_code = 0;
+			if(signr == SIGSTOP)
+				continue;
+			if(_S(signr) & current->blocked) {
+				current->signal |= _S(signr);
+				continue;
+			}
+			sa = current->sig->action + signr - 1;
+		}
+		if(sa->sa_handler == SIG_IGN) {
+			if(signr != SIGCHLD)
+				continue;
+			while(sys_waitpid(-1,NULL,WNOHANG) > 0);
+			continue;
+		}
+		if(sa->sa_handler == SIG_DFL) {
+			if(current->pid == 1)
+				continue;
+			switch(signr) {
+			case SIGCONT: case SIGCHLD: case SIGWINCH:
+				continue;
+
+			case SIGSTOP: case SIGTSTP: case SIGTTIN: case SIGTTOU:
+				if(current->flags & PF_PTRACED)
+					continue;
+				current->state = TASK_STOPPED;
+				current->exit_code = signr;
+				if(!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags &
+				     SA_NOCLDSTOP))
+					notify_parent(current);
+				schedule();
+				continue;
+
+			case SIGQUIT: case SIGILL: case SIGTRAP:
+			case SIGABRT: case SIGFPE: case SIGSEGV:
+				if(current->binfmt && current->binfmt->core_dump) {
+					if(current->binfmt->core_dump(signr, regs))
+						signr |= 0x80;
+				}
+				/* fall through */
+			default:
+				current->signal |= _S(signr & 0x7f);
+				do_exit(signr);
+			}
+		}
+		/* OK, we're invoking a handler. */
+		handler_signal |= 1 << (signr - 1);
+		mask &= ~sa->sa_mask;
+	}
+	if(!handler_signal)
+		return 0;
+	pc = regs->pc;
+	frame = (struct sigcontext_struct *) regs->u_regs[UREG_FP];
+	signr = 1;
+	sa = current->sig->action;
+	for(mask = 1; mask; sa++, signr++, mask += mask) {
+		if(mask > handler_signal)
+			break;
+		if(!(mask & handler_signal))
+			continue;
+		setup_frame(sa, &frame, pc, regs, signr, oldmask);
+		pc = (unsigned long) sa->sa_handler;
+		if(sa->sa_flags & SA_ONESHOT)
+			sa->sa_handler = NULL;
+		current->blocked |= sa->sa_mask;
+		oldmask |= sa->sa_mask;
+	}
+	regs->u_regs[UREG_FP] = (unsigned long) frame;
+	regs->npc = (regs->pc = pc) + 4;
+	return 1;
+}
+
+asmlinkage int
+sys_sigstack(struct sigstack *ssptr, struct sigstack *ossptr)
+{
+	/* First see if old state is wanted. */
+	if(ossptr) {
+		if(verify_area(VERIFY_WRITE, ossptr, sizeof(struct sigstack)))
+			return -EFAULT;
+		memcpy(ossptr, &current->tss.sstk_info, sizeof(struct sigstack));
+	}
+
+	/* Now see if we want to update the new state. */
+	if(ssptr) {
+		if(verify_area(VERIFY_READ, ssptr, sizeof(struct sigstack)))
+			return -EFAULT;
+		memcpy(&current->tss.sstk_info, ssptr, sizeof(struct sigstack));
+	}
+	return 0;
 }
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/kernel/sparc-stub.c linux/arch/sparc/kernel/sparc-stub.c
--- v1.3.43/linux/arch/sparc/kernel/sparc-stub.c	Thu Jan  1 02:00:00 1970
+++ linux/arch/sparc/kernel/sparc-stub.c	Sat Nov 25 02:58:28 1995
@@ -0,0 +1,691 @@
+/* $Id: sparc-stub.c,v 1.7 1995/11/25 00:58:26 davem Exp $
+ * sparc-stub.c:  KGDB support for the Linux kernel.
+ *
+ * Modifications to run under Linux
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ *
+ * This file origionally came from the gdb sources, and the
+ * copyright notices have been retained below.
+ */
+
+/****************************************************************************
+
+		THIS SOFTWARE IS NOT COPYRIGHTED
+
+   HP offers the following for use in the public domain.  HP makes no
+   warranty with regard to the software or it's performance and the
+   user accepts the software "AS IS" with all faults.
+
+   HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
+   TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+****************************************************************************/
+
+/****************************************************************************
+ *  Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
+ *
+ *  Module name: remcom.c $
+ *  Revision: 1.34 $
+ *  Date: 91/03/09 12:29:49 $
+ *  Contributor:     Lake Stevens Instrument Division$
+ *
+ *  Description:     low level support for gdb debugger. $
+ *
+ *  Considerations:  only works on target hardware $
+ *
+ *  Written by:      Glenn Engel $
+ *  ModuleState:     Experimental $
+ *
+ *  NOTES:           See Below $
+ *
+ *  Modified for SPARC by Stu Grossman, Cygnus Support.
+ *
+ *  This code has been extensively tested on the Fujitsu SPARClite demo board.
+ *
+ *  To enable debugger support, two things need to happen.  One, a
+ *  call to set_debug_traps() is necessary in order to allow any breakpoints
+ *  or error conditions to be properly intercepted and reported to gdb.
+ *  Two, a breakpoint needs to be generated to begin communication.  This
+ *  is most easily accomplished by a call to breakpoint().  Breakpoint()
+ *  simulates a breakpoint by executing a trap #1.
+ *
+ *************
+ *
+ *    The following gdb commands are supported:
+ *
+ * command          function                               Return value
+ *
+ *    g             return the value of the CPU registers  hex data or ENN
+ *    G             set the value of the CPU registers     OK or ENN
+ *
+ *    mAA..AA,LLLL  Read LLLL bytes at address AA..AA      hex data or ENN
+ *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA      OK or ENN
+ *
+ *    c             Resume at current address              SNN   ( signal NN)
+ *    cAA..AA       Continue at address AA..AA             SNN
+ *
+ *    s             Step one instruction                   SNN
+ *    sAA..AA       Step one instruction from AA..AA       SNN
+ *
+ *    k             kill
+ *
+ *    ?             What was the last sigval ?             SNN   (signal NN)
+ *
+ *    bBB..BB	    Set baud rate to BB..BB		   OK or BNN, then sets
+ *							   baud rate
+ *
+ * All commands and responses are sent with a packet which includes a
+ * checksum.  A packet consists of
+ *
+ * $<packet info>#<checksum>.
+ *
+ * where
+ * <packet info> :: <characters representing the command or response>
+ * <checksum>    :: < two hex digits computed as modulo 256 sum of <packetinfo>>
+ *
+ * When a packet is received, it is first acknowledged with either '+' or '-'.
+ * '+' indicates a successful transfer.  '-' indicates a failed transfer.
+ *
+ * Example:
+ *
+ * Host:                  Reply:
+ * $m0,10#2a               +$00010203040506070809101112131415#42
+ *
+ ****************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+
+#include <asm/system.h>
+#include <asm/signal.h>
+#include <asm/oplib.h>
+#include <asm/head.h>
+#include <asm/traps.h>
+#include <asm/system.h>
+#include <asm/vac-ops.h>
+#include <asm/kgdb.h>
+
+/*
+ *
+ * external low-level support routines
+ */
+
+extern void putDebugChar(char);   /* write a single character      */
+extern char getDebugChar(void);   /* read and return a single char */
+
+/*
+ * BUFMAX defines the maximum number of characters in inbound/outbound buffers
+ * at least NUMREGBYTES*2 are needed for register packets
+ */
+#define BUFMAX 2048
+
+static int initialized = 0;	/* !0 means we've been initialized */
+
+static const char hexchars[]="0123456789abcdef";
+
+#define NUMREGS 72
+
+/* Number of bytes of registers.  */
+#define NUMREGBYTES (NUMREGS * 4)
+enum regnames {G0, G1, G2, G3, G4, G5, G6, G7,
+		 O0, O1, O2, O3, O4, O5, SP, O7,
+		 L0, L1, L2, L3, L4, L5, L6, L7,
+		 I0, I1, I2, I3, I4, I5, FP, I7,
+
+		 F0, F1, F2, F3, F4, F5, F6, F7,
+		 F8, F9, F10, F11, F12, F13, F14, F15,
+		 F16, F17, F18, F19, F20, F21, F22, F23,
+		 F24, F25, F26, F27, F28, F29, F30, F31,
+		 Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR };
+
+
+extern void trap_low(void);  /* In arch/sparc/kernel/entry.S */
+
+unsigned long get_sun4cpte(unsigned long addr)
+{
+	unsigned long entry;
+
+	__asm__ __volatile__("\n\tlda [%1] %2, %0\n\t" : 
+			     "=r" (entry) :
+			     "r" (addr), "i" (ASI_PTE));
+	return entry;
+}
+
+unsigned long get_sun4csegmap(unsigned long addr)
+{
+	unsigned long entry;
+
+	__asm__ __volatile__("\n\tlduba [%1] %2, %0\n\t" : 
+			     "=r" (entry) :
+			     "r" (addr), "i" (ASI_SEGMAP));
+	return entry;
+}
+
+/* Place where we save old trap entries for restoration */
+struct tt_entry kgdb_savettable[256];
+typedef void (*trapfunc_t)(void);
+
+/* Helper routine for manipulation of kgdb_savettable */
+static inline void copy_ttentry(struct tt_entry *src, struct tt_entry *dest)
+{
+	dest->inst_one = src->inst_one;
+	dest->inst_two = src->inst_two;
+	dest->inst_three = src->inst_three;
+	dest->inst_four = src->inst_four;
+}
+
+/* Initialize the kgdb_savettable so that debugging can commence */
+static void eh_init(void)
+{
+	int i, flags;
+
+	save_flags(flags); cli();
+	for(i=0; i < 256; i++)
+		copy_ttentry(&sparc_ttable[i], &kgdb_savettable[i]);
+	restore_flags(flags);
+}
+
+/* Install an exception handler for kgdb */
+static void exceptionHandler(int tnum, trapfunc_t trap_entry)
+{
+	unsigned long te_addr = (unsigned long) trap_entry;
+	int flags;
+
+	/* We are dorking with a live trap table, all irqs off */
+	save_flags(flags); cli();
+
+	/* Make new vector */
+	sparc_ttable[tnum].inst_one =
+		SPARC_BRANCH((unsigned long) te_addr,
+			     (unsigned long) &sparc_ttable[tnum].inst_one);
+	sparc_ttable[tnum].inst_two = SPARC_RD_PSR_L0;
+	sparc_ttable[tnum].inst_three = SPARC_NOP;
+	sparc_ttable[tnum].inst_four = SPARC_NOP;
+
+	restore_flags(flags);
+}
+
+/* Convert ch from a hex digit to an int */
+static int
+hex(unsigned char ch)
+{
+	if (ch >= 'a' && ch <= 'f')
+		return ch-'a'+10;
+	if (ch >= '0' && ch <= '9')
+		return ch-'0';
+	if (ch >= 'A' && ch <= 'F')
+		return ch-'A'+10;
+	return -1;
+}
+
+/* scan for the sequence $<data>#<checksum>     */
+static void
+getpacket(char *buffer)
+{
+	unsigned char checksum;
+	unsigned char xmitcsum;
+	int i;
+	int count;
+	unsigned char ch;
+
+	do {
+		/* wait around for the start character, ignore all other characters */
+		while ((ch = (getDebugChar() & 0x7f)) != '$') ;
+
+		checksum = 0;
+		xmitcsum = -1;
+
+		count = 0;
+
+		/* now, read until a # or end of buffer is found */
+		while (count < BUFMAX) {
+			ch = getDebugChar() & 0x7f;
+			if (ch == '#')
+				break;
+			checksum = checksum + ch;
+			buffer[count] = ch;
+			count = count + 1;
+		}
+
+		if (count >= BUFMAX)
+			continue;
+
+		buffer[count] = 0;
+
+		if (ch == '#') {
+			xmitcsum = hex(getDebugChar() & 0x7f) << 4;
+			xmitcsum |= hex(getDebugChar() & 0x7f);
+			if (checksum != xmitcsum)
+				putDebugChar('-');	/* failed checksum */
+			else {
+				putDebugChar('+'); /* successful transfer */
+				/* if a sequence char is present, reply the ID */
+				if (buffer[2] == ':') {
+					putDebugChar(buffer[0]);
+					putDebugChar(buffer[1]);
+					/* remove sequence chars from buffer */
+					count = strlen(buffer);
+					for (i=3; i <= count; i++)
+						buffer[i-3] = buffer[i];
+				}
+			}
+		}
+	} while (checksum != xmitcsum);
+}
+
+/* send the packet in buffer.  */
+
+static void
+putpacket(unsigned char *buffer)
+{
+	unsigned char checksum;
+	int count;
+	unsigned char ch, recv;
+
+	/*  $<packet info>#<checksum>. */
+	do {
+		putDebugChar('$');
+		checksum = 0;
+		count = 0;
+
+		while ((ch = buffer[count])) {
+			putDebugChar(ch);
+			checksum += ch;
+			count += 1;
+		}
+
+		putDebugChar('#');
+		putDebugChar(hexchars[checksum >> 4]);
+		putDebugChar(hexchars[checksum & 0xf]);
+		recv = getDebugChar();
+	} while ((recv & 0x7f) != '+');
+}
+
+static char remcomInBuffer[BUFMAX];
+static char remcomOutBuffer[BUFMAX];
+
+/* Convert the memory pointed to by mem into hex, placing result in buf.
+ * Return a pointer to the last char put in buf (null), in case of mem fault,
+ * return 0.
+ */
+
+static unsigned char *
+mem2hex(char *mem, char *buf, int count)
+{
+	unsigned char ch;
+
+	while (count-- > 0) {
+		ch = *mem++;
+		*buf++ = hexchars[ch >> 4];
+		*buf++ = hexchars[ch & 0xf];
+	}
+
+	*buf = 0;
+	return buf;
+}
+
+/* convert the hex array pointed to by buf into binary to be placed in mem
+ * return a pointer to the character AFTER the last byte written.
+*/
+static char *
+hex2mem(char *buf, char *mem, int count)
+{
+	int i;
+	unsigned char ch;
+
+	for (i=0; i<count; i++) {
+
+		ch = hex(*buf++) << 4;
+		ch |= hex(*buf++);
+		*mem++ = ch;
+	}
+	return mem;
+}
+
+/* This table contains the mapping between SPARC hardware trap types, and
+   signals, which are primarily what GDB understands.  It also indicates
+   which hardware traps we need to commandeer when initializing the stub. */
+
+static struct hard_trap_info
+{
+  unsigned char tt;		/* Trap type code for SPARC */
+  unsigned char signo;		/* Signal that we map this trap into */
+} hard_trap_info[] = {
+  {SP_TRAP_SBPT, SIGTRAP},      /* ta 1 - Linux/KGDB software breakpoint */
+  {0, 0}			/* Must be last */
+};
+
+/* Set up exception handlers for tracing and breakpoints */
+
+void
+set_debug_traps(void)
+{
+	struct hard_trap_info *ht;
+	unsigned char c;
+
+	/* Initialize our copy of the Linux Sparc trap table */
+	eh_init();
+
+	for (ht = hard_trap_info; ht->tt && ht->signo; ht++) {
+		/* Only if it doesn't destroy our fault handlers */
+		if((ht->tt != SP_TRAP_TFLT) && 
+		   (ht->tt != SP_TRAP_DFLT))
+			exceptionHandler(ht->tt, trap_low);
+	}
+
+	/* In case GDB is started before us, ack any packets (presumably
+	 * "$?#xx") sitting there.
+	 */
+
+	while((c = getDebugChar()) != '$');
+	while((c = getDebugChar()) != '#');
+	c = getDebugChar(); /* eat first csum byte */
+	c = getDebugChar(); /* eat second csum byte */
+	putDebugChar('+'); /* ack it */
+
+	initialized = 1; /* connect! */
+}
+
+/* Convert the SPARC hardware trap type code to a unix signal number. */
+
+static int
+computeSignal(int tt)
+{
+	struct hard_trap_info *ht;
+
+	for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
+		if (ht->tt == tt)
+			return ht->signo;
+
+	return SIGHUP;         /* default for things we don't know about */
+}
+
+/*
+ * While we find nice hex chars, build an int.
+ * Return number of chars processed.
+ */
+
+static int
+hexToInt(char **ptr, int *intValue)
+{
+	int numChars = 0;
+	int hexValue;
+
+	*intValue = 0;
+
+	while (**ptr) {
+		hexValue = hex(**ptr);
+		if (hexValue < 0)
+			break;
+
+		*intValue = (*intValue << 4) | hexValue;
+		numChars ++;
+
+		(*ptr)++;
+	}
+
+	return (numChars);
+}
+
+/*
+ * This function does all command procesing for interfacing to gdb.  It
+ * returns 1 if you should skip the instruction at the trap address, 0
+ * otherwise.
+ */
+
+extern void breakinst(void);
+
+void
+handle_exception (unsigned long *registers)
+{
+	int tt;       /* Trap type */
+	int sigval;
+	int addr;
+	int length;
+	char *ptr;
+	unsigned long *sp;
+
+	/* First, we must force all of the windows to be spilled out */
+
+	asm("save %sp, -64, %sp\n\t"
+	    "save %sp, -64, %sp\n\t"
+	    "save %sp, -64, %sp\n\t"
+	    "save %sp, -64, %sp\n\t"
+	    "save %sp, -64, %sp\n\t"
+	    "save %sp, -64, %sp\n\t"
+	    "save %sp, -64, %sp\n\t"
+	    "save %sp, -64, %sp\n\t"
+	    "restore\n\t"
+	    "restore\n\t"
+	    "restore\n\t"
+	    "restore\n\t"
+	    "restore\n\t"
+	    "restore\n\t"
+	    "restore\n\t"
+	    "restore\n\t");
+
+	if (registers[PC] == (unsigned long)breakinst) {
+		/* Skip over breakpoint trap insn */
+		registers[PC] = registers[NPC];
+		registers[NPC] += 4;
+	}
+
+	sp = (unsigned long *)registers[SP];
+
+	tt = (registers[TBR] >> 4) & 0xff;
+
+	/* reply to host that an exception has occurred */
+	sigval = computeSignal(tt);
+	ptr = remcomOutBuffer;
+
+	*ptr++ = 'T';
+	*ptr++ = hexchars[sigval >> 4];
+	*ptr++ = hexchars[sigval & 0xf];
+
+	*ptr++ = hexchars[PC >> 4];
+	*ptr++ = hexchars[PC & 0xf];
+	*ptr++ = ':';
+	ptr = mem2hex((char *)&registers[PC], ptr, 4);
+	*ptr++ = ';';
+
+	*ptr++ = hexchars[FP >> 4];
+	*ptr++ = hexchars[FP & 0xf];
+	*ptr++ = ':';
+	ptr = mem2hex((char *) (sp + 8 + 6), ptr, 4); /* FP */
+	*ptr++ = ';';
+
+	*ptr++ = hexchars[SP >> 4];
+	*ptr++ = hexchars[SP & 0xf];
+	*ptr++ = ':';
+	ptr = mem2hex((char *)&sp, ptr, 4);
+	*ptr++ = ';';
+
+	*ptr++ = hexchars[NPC >> 4];
+	*ptr++ = hexchars[NPC & 0xf];
+	*ptr++ = ':';
+	ptr = mem2hex((char *)&registers[NPC], ptr, 4);
+	*ptr++ = ';';
+
+	*ptr++ = hexchars[O7 >> 4];
+	*ptr++ = hexchars[O7 & 0xf];
+	*ptr++ = ':';
+	ptr = mem2hex((char *)&registers[O7], ptr, 4);
+	*ptr++ = ';';
+
+	*ptr++ = 0;
+
+	putpacket(remcomOutBuffer);
+
+	/* XXX We may want to add some features dealing with poking the
+	 * XXX page tables, the real ones on the srmmu, and what is currently
+	 * XXX loaded in the sun4/sun4c tlb at this point in time.  But this
+	 * XXX also required hacking to the gdb sources directly...
+	 */
+
+	while (1) {
+		remcomOutBuffer[0] = 0;
+
+		getpacket(remcomInBuffer);
+		switch (remcomInBuffer[0]) {
+		case '?':
+			remcomOutBuffer[0] = 'S';
+			remcomOutBuffer[1] = hexchars[sigval >> 4];
+			remcomOutBuffer[2] = hexchars[sigval & 0xf];
+			remcomOutBuffer[3] = 0;
+			break;
+
+		case 'd':
+			/* toggle debug flag */
+			break;
+
+		case 'g':		/* return the value of the CPU registers */
+		{
+			ptr = remcomOutBuffer;
+			/* G & O regs */
+			ptr = mem2hex((char *)registers, ptr, 16 * 4);
+			/* L & I regs */
+			ptr = mem2hex((char *) (sp + 0), ptr, 16 * 4);
+			/* Floating point */
+			memset(ptr, '0', 32 * 8);
+			/* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
+			mem2hex((char *)&registers[Y], (ptr + 32 * 4 * 2), (8 * 4));
+		}
+			break;
+
+		case 'G':	   /* set the value of the CPU registers - return OK */
+		{
+			unsigned long *newsp, psr;
+
+			psr = registers[PSR];
+
+			ptr = &remcomInBuffer[1];
+			/* G & O regs */
+			hex2mem(ptr, (char *)registers, 16 * 4);
+			/* L & I regs */
+			hex2mem(ptr + 16 * 4 * 2, (char *) (sp + 0), 16 * 4);
+			/* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
+			hex2mem(ptr + 64 * 4 * 2, (char *)&registers[Y], 8 * 4);
+
+			/* See if the stack pointer has moved.  If so,
+			 * then copy the saved locals and ins to the
+			 * new location.  This keeps the window
+			 * overflow and underflow routines happy.
+			 */
+
+			newsp = (unsigned long *)registers[SP];
+			if (sp != newsp)
+				sp = memcpy(newsp, sp, 16 * 4);
+
+			/* Don't allow CWP to be modified. */
+
+			if (psr != registers[PSR])
+				registers[PSR] = (psr & 0x1f) | (registers[PSR] & ~0x1f);
+
+			strcpy(remcomOutBuffer,"OK");
+		}
+			break;
+
+		case 'm':	  /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
+			/* Try to read %x,%x.  */
+
+			ptr = &remcomInBuffer[1];
+
+			if (hexToInt(&ptr, &addr)
+			    && *ptr++ == ','
+			    && hexToInt(&ptr, &length))	{
+				if (mem2hex((char *)addr, remcomOutBuffer, length))
+					break;
+
+				strcpy (remcomOutBuffer, "E03");
+			} else {
+				strcpy(remcomOutBuffer,"E01");
+			}
+			break;
+
+		case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
+			/* Try to read '%x,%x:'.  */
+
+			ptr = &remcomInBuffer[1];
+
+			if (hexToInt(&ptr, &addr)
+			    && *ptr++ == ','
+			    && hexToInt(&ptr, &length)
+			    && *ptr++ == ':') {
+				if (hex2mem(ptr, (char *)addr, length)) {
+					strcpy(remcomOutBuffer, "OK");
+				} else {
+					strcpy(remcomOutBuffer, "E03");
+				}
+			} else {
+				strcpy(remcomOutBuffer, "E02");
+			}
+			break;
+
+		case 'c':    /* cAA..AA    Continue at address AA..AA(optional) */
+			/* try to read optional parameter, pc unchanged if no parm */
+
+			ptr = &remcomInBuffer[1];
+			if (hexToInt(&ptr, &addr)) {
+				registers[PC] = addr;
+				registers[NPC] = addr + 4;
+			}
+
+/* Need to flush the instruction cache here, as we may have deposited a
+ * breakpoint, and the icache probably has no way of knowing that a data ref to
+ * some location may have changed something that is in the instruction cache.
+ */
+
+			/* Only instruction cache flushing on the sun4c/sun4
+			 * for now.  We assume control flow during the kgdb
+			 * transaction has not left the context in which it
+			 * was entered.
+			 */
+			if((sparc_cpu_model==sun4 || sparc_cpu_model==sun4c) &&
+			   (sun4c_vacinfo.num_bytes && sun4c_vacinfo.on))
+				sun4c_flush_context();
+			/* XXX SRMMU and on-chip v8 instruction cache
+			 * XXX flushing goes here!
+			 */
+
+			return;
+
+			/* kill the program */
+		case 'k' :		/* do nothing */
+			break;
+		case 'r':		/* Reset */
+			asm ("call 0\n\t"
+			     "nop\n\t");
+			break;
+		}			/* switch */
+
+		/* reply to the request */
+		putpacket(remcomOutBuffer);
+	} /* while(1) */
+}
+
+/* This function will generate a breakpoint exception.  It is used at the
+   beginning of a program to sync up with a debugger and can be used
+   otherwise as a quick means to stop program execution and "break" into
+   the debugger. */
+
+void
+breakpoint(void)
+{
+	if (!initialized)
+		return;
+
+	/* Again, watch those c-prefixes for solaris/elf kernels */
+#ifndef __svr4__
+	asm("	.globl _breakinst
+
+	     _breakinst: ta 1
+            ");
+#else
+	asm("	.globl breakinst
+
+	     breakinst: ta 1
+            ");
+#endif
+}
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/kernel/sunos_asm.S linux/arch/sparc/kernel/sunos_asm.S
--- v1.3.43/linux/arch/sparc/kernel/sunos_asm.S	Thu Jan  1 02:00:00 1970
+++ linux/arch/sparc/kernel/sunos_asm.S	Sat Nov 25 02:58:30 1995
@@ -0,0 +1,90 @@
+/* $Id: sunos_asm.S,v 1.8 1995/11/25 00:58:29 davem Exp $
+ * sunos_asm.S: SunOS system calls which must have a low-level
+ *              entry point to operate correctly.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ *
+ * Based upon preliminary work which is:
+ *
+ * Copyright (C) 1995 Adrian M. Rodriguez (adrian@remus.rutgers.edu)
+ */
+
+#include <asm/cprefix.h>
+#include <asm/ptrace.h>
+
+	/* Note that for dual value returning system calls we
+	 * need to store the second one ourselves in the pt_regs
+	 * trap-frame.  linux_sparc_syscall does %o0 for us
+	 * however.
+	 */
+
+	.text
+	.align 4
+
+	/* SunOS getpid() returns pid in %o0 and ppid in %o1 */
+	.globl	C_LABEL(sunos_getpid)
+C_LABEL(sunos_getpid):
+	save	%sp, -STACKFRAME_SZ, %sp
+	call	C_LABEL(sys_getpid)
+	nop
+
+	mov	%o0, %i0
+
+	call	C_LABEL(sys_getppid)
+	nop	
+
+	st	%o0, [%fp + STACKFRAME_SZ + PT_I1]
+
+	ret
+	restore
+
+	/* SunOS getuid() returns uid in %o0 and euid in %o1 */
+	.globl	C_LABEL(sunos_getuid)
+C_LABEL(sunos_getuid):
+	save	%sp, -STACKFRAME_SZ, %sp
+	call	C_LABEL(sys_getuid)
+	nop
+
+	mov	%o0, %i0
+
+	call	C_LABEL(sys_geteuid)
+	nop
+
+	st	%o0, [%fp + STACKFRAME_SZ + PT_I1]
+
+	ret
+	restore
+
+	/* SunOS getgid() returns gid in %o0 and egid in %o1 */
+	.globl	C_LABEL(sunos_getgid)
+C_LABEL(sunos_getgid):
+	save	%sp, -STACKFRAME_SZ, %sp
+	call	C_LABEL(sys_getgid)
+	nop
+
+	mov	%o0, %i0
+
+	call	C_LABEL(sys_getegid)
+	nop
+
+	st	%o0, [%fp + STACKFRAME_SZ + PT_I1]
+
+	ret
+	restore
+
+	/* SunOS's execv() call only specifies the argv argument, the
+	 * environment settings are the same as the calling processes.
+	 */
+	.globl	C_LABEL(sunos_execv)
+C_LABEL(sunos_execv):
+	save	%sp, -STACKFRAME_SZ, %sp
+
+	st	%g0, [%fp + STACKFRAME_SZ + PT_I2]
+	call	C_LABEL(sparc_execve)
+	add	%fp, STACKFRAME_SZ, %o0
+
+	st	%o0, [%fp + STACKFRAME_SZ + PT_I1]
+
+	ret
+	restore
+
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/kernel/sunos_ioctl.c linux/arch/sparc/kernel/sunos_ioctl.c
--- v1.3.43/linux/arch/sparc/kernel/sunos_ioctl.c	Thu Jan  1 02:00:00 1970
+++ linux/arch/sparc/kernel/sunos_ioctl.c	Sat Nov 25 02:58:32 1995
@@ -0,0 +1,109 @@
+/* $Id: sunos_ioctl.c,v 1.7 1995/11/25 00:58:30 davem Exp $
+ * sunos_ioctl.c: The Linux Operating system: SunOS ioctl compatibility.
+ * 
+ * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#include <asm/segment.h>
+
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/termios.h>
+#include <linux/ioctl.h>
+#include <linux/route.h>
+#include <linux/sockios.h>
+#include <linux/if.h>
+#include <linux/if_arp.h>
+#include <linux/fs.h>
+
+extern asmlinkage int sys_ioctl(unsigned int, unsigned int, unsigned long);
+
+asmlinkage int sunos_ioctl (int fd, unsigned long cmd, void *arg)
+{
+	struct file *filp;
+	
+	if (fd >= NR_OPEN || !(filp = current->files->fd [fd]))
+		return -EBADF;
+
+	/* SunOS networking ioctls. */
+	switch (cmd) {
+	case _IOW('r', 10, struct rtentry):
+		return sys_ioctl(fd, SIOCADDRT, arg);
+	case _IOW('r', 11, struct rtentry):
+		return sys_ioctl(fd, SIOCDELRT, arg);
+	case _IOW('i', 12, struct ifreq):
+		return sys_ioctl(fd, SIOCSIFADDR, arg);
+	case _IORW('i', 13, struct ifreq):
+		return sys_ioctl(fd, SIOCGIFADDR, arg);
+	case _IOW('i', 14, struct ifreq):
+		return sys_ioctl(fd, SIOCSIFDSTADDR, arg);
+	case _IORW('i', 15, struct ifreq):
+		return sys_ioctl(fd, SIOCGIFDSTADDR, arg);
+	case _IOW('i', 16, struct ifreq):
+		return sys_ioctl(fd, SIOCSIFFLAGS, arg);
+	case _IORW('i', 17, struct ifreq):
+		return sys_ioctl(fd, SIOCGIFFLAGS, arg);
+	case _IOW('i', 18, struct ifreq):
+		return sys_ioctl(fd, SIOCSIFMEM, arg);
+	case _IORW('i', 19, struct ifreq):
+		return sys_ioctl(fd, SIOCGIFMEM, arg);
+	case _IORW('i', 20, struct ifreq):
+		return sys_ioctl(fd, SIOCGIFCONF, arg);
+	case _IOW('i', 21, struct ifreq): /* SIOCSIFMTU */
+		return sys_ioctl(fd, SIOCSIFMTU, arg);
+	case _IORW('i', 22, struct ifreq): /* SIOCGIFMTU */
+		return sys_ioctl(fd, SIOCGIFMTU, arg);
+
+	case _IORW('i', 23, struct ifreq):
+		return sys_ioctl(fd, SIOCGIFBRDADDR, arg);
+	case _IOW('i', 24, struct ifreq):
+		return sys_ioctl(fd, SIOCGIFBRDADDR, arg);
+	case _IORW('i', 25, struct ifreq):
+		return sys_ioctl(fd, SIOCGIFNETMASK, arg);
+	case _IOW('i', 26, struct ifreq):
+		return sys_ioctl(fd, SIOCSIFNETMASK, arg);
+	case _IORW('i', 27, struct ifreq):
+		return sys_ioctl(fd, SIOCGIFMETRIC, arg);
+	case _IOW('i', 28, struct ifreq):
+		return sys_ioctl(fd, SIOCSIFMETRIC, arg);
+
+	case _IOW('i', 30, struct arpreq):
+		return sys_ioctl(fd, SIOCSARP, arg);
+	case _IOW('i', 31, struct arpreq):
+		return sys_ioctl(fd, SIOCGARP, arg);
+	case _IOW('i', 32, struct arpreq):
+		return sys_ioctl(fd, SIOCGARP, arg);
+
+	case _IOW('i', 40, struct ifreq): /* SIOCUPPER */
+	case _IOW('i', 41, struct ifreq): /* SIOCLOWER */
+	case _IOW('i', 44, struct ifreq): /* SIOCSETSYNC */
+	case _IOW('i', 45, struct ifreq): /* SIOCGETSYNC */
+	case _IOW('i', 46, struct ifreq): /* SIOCSSDSTATS */
+	case _IOW('i', 47, struct ifreq): /* SIOCSSESTATS */
+	case _IOW('i', 48, struct ifreq): /* SIOCSPROMISC */
+		return -EINVAL;
+
+	case _IOW('i', 49, struct ifreq):
+		return sys_ioctl(fd, SIOCADDMULTI, arg);
+	case _IOW('i', 50, struct ifreq):
+		return sys_ioctl(fd, SIOCDELMULTI, arg);
+
+	/* FDDI interface ioctls, unsupported. */
+	case _IOW('i', 51, struct ifreq): /* SIOCFDRESET */
+	case _IOW('i', 52, struct ifreq): /* SIOCFDSLEEP */
+	case _IOW('i', 53, struct ifreq): /* SIOCSTRTFMWAR */
+	case _IOW('i', 54, struct ifreq): /* SIOCLDNSTRTFW */
+	case _IOW('i', 55, struct ifreq): /* SIOCGETFDSTAT */
+	case _IOW('i', 56, struct ifreq): /* SIOCFDNMIINT */
+	case _IOW('i', 57, struct ifreq): /* SIOCFDEXUSER */
+	case _IOW('i', 58, struct ifreq): /* SIOCFDGNETMAP */
+	case _IOW('i', 59, struct ifreq): /* SIOCFDGIOCTL */
+		return -EINVAL;
+	}
+
+	return sys_ioctl (fd, cmd, arg);
+}
+
+
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/kernel/switch.S linux/arch/sparc/kernel/switch.S
--- v1.3.43/linux/arch/sparc/kernel/switch.S	Thu Jan  1 02:00:00 1970
+++ linux/arch/sparc/kernel/switch.S	Sat Nov 25 02:58:34 1995
@@ -0,0 +1,72 @@
+/* $Id: switch.S,v 1.9 1995/11/25 00:58:32 davem Exp $
+ * switch.S: Sparc task switch code.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#include <asm/head.h>
+#include <asm/asi.h>
+#include <asm/contregs.h>
+#include <asm/cprefix.h>
+#include <asm/psr.h>
+#include <asm/ptrace.h>
+#include <asm/winmacro.h>
+
+#define sw_ntask     g1
+#define sw_sp        g2
+#define sw_pc        g3
+#define sw_psr       g4
+#define sw_wim       g5
+#define sw_tmp       g6
+#define sw_ctx       g7
+
+/* Context switch code.  The new process's task_struct
+ * ptr is passed as the first parameter.
+ *
+ * First successful task switch 05/13/95 21:52:37
+ */
+	.align 4
+	.globl	C_LABEL(sparc_switch_to), C_LABEL(mmu_switch_lowlevel)
+C_LABEL(sparc_switch_to):
+	mov	%o0, %sw_ntask
+
+	/* Save kernel state. */
+	FLUSH_ALL_KERNEL_WINDOWS; 
+	STORE_WINDOW(sp)
+	rd	%psr, %sw_psr
+	sethi	%hi(PSR_EF), %sw_tmp
+	andn	%sw_psr, %sw_tmp, %sw_psr
+	LOAD_CURRENT(sw_tmp)
+	rd	%wim, %sw_wim
+	std	%sw_psr, [%sw_tmp + THREAD_KPSR]
+	std	%sp, [%sw_tmp + THREAD_KSP]
+
+	/* Load new kernel state. */
+	wr	%sw_psr, PSR_ET, %psr
+	sethi	%hi(C_LABEL(current_set)), %sw_tmp
+	st	%sw_ntask, [%sw_tmp + %lo(C_LABEL(current_set))]
+	ldd	[%sw_ntask + THREAD_KPSR], %sw_psr
+	ldd	[%sw_ntask + THREAD_KSP], %sw_sp
+	wr	%sw_psr, PSR_ET, %psr
+	WRITE_PAUSE
+	wr	%sw_wim, 0x0, %wim
+	WRITE_PAUSE
+	mov	%sw_sp, %sp
+	LOAD_WINDOW(sp)
+	mov	%sw_pc, %o7
+
+	/* Jump into the proper context. */
+	ld	[%sw_ntask + THREAD_CONTEXT], %sw_ctx
+	tst	%sw_ctx
+	bneg	1f			! this must be swapper
+	 nop
+
+C_LABEL(mmu_switch_lowlevel):
+	sethi	%hi(AC_CONTEXT), %sw_tmp	! else set new context
+	stba	%sw_ctx, [%sw_tmp] ASI_CONTROL
+1:
+	wr	%sw_psr, 0x0, %psr		! traps back on
+	WRITE_PAUSE
+
+	retl
+	 nop
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/kernel/sys_sparc.c linux/arch/sparc/kernel/sys_sparc.c
--- v1.3.43/linux/arch/sparc/kernel/sys_sparc.c	Thu Jan  1 02:00:00 1970
+++ linux/arch/sparc/kernel/sys_sparc.c	Sat Nov 25 02:58:36 1995
@@ -0,0 +1,135 @@
+/* $Id: sys_sparc.c,v 1.6 1995/11/25 00:58:34 davem Exp $
+ * linux/arch/sparc/kernel/sys_sparc.c
+ *
+ * This file contains various random system calls that
+ * have a non-standard calling sequence on the Linux/sparc
+ * platform.
+ */
+
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/sem.h>
+#include <linux/msg.h>
+#include <linux/shm.h>
+#include <linux/stat.h>
+#include <linux/mman.h>
+
+#include <asm/segment.h>
+
+/* XXX Make this per-binary type, this way we can detect the type of
+ * XXX a binary.  Every Sparc executable calls this very early on.
+ */
+asmlinkage unsigned long sys_getpagesize(void)
+{
+	return PAGE_SIZE; /* Possibly older binaries want 8192 on sun4's? */
+}
+
+/*
+ * sys_pipe() is the normal C calling standard for creating
+ * a pipe. It's not the way unix tranditionally does this, though.
+ */
+asmlinkage void sparc_pipe(struct pt_regs *regs)
+{
+	int fd[2];
+	int error;
+
+	error = do_pipe(fd);
+	if (error) {
+		regs->u_regs[UREG_I0] = error;
+	} else {
+		regs->u_regs[UREG_I0] = fd[0];
+		regs->u_regs[UREG_I1] = fd[1];
+	}
+}
+
+/*
+ * sys_ipc() is the de-multiplexer for the SysV IPC calls..
+ *
+ * This is really horribly ugly.
+ */
+asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr, long fifth)
+{
+	int version;
+
+	version = call >> 16; /* hack for backward compatibility */
+	call &= 0xffff;
+
+	if (call <= SEMCTL)
+		switch (call) {
+		case SEMOP:
+			return sys_semop (first, (struct sembuf *)ptr, second);
+		case SEMGET:
+			return sys_semget (first, second, third);
+		case SEMCTL: {
+			union semun fourth;
+			int err;
+			if (!ptr)
+				return -EINVAL;
+			if ((err = verify_area (VERIFY_READ, ptr, sizeof(long))))
+				return err;
+			fourth.__pad = (void *) get_fs_long(ptr);
+			return sys_semctl (first, second, third, fourth);
+			}
+		default:
+			return -EINVAL;
+		}
+	if (call <= MSGCTL) 
+		switch (call) {
+		case MSGSND:
+			return sys_msgsnd (first, (struct msgbuf *) ptr, 
+					   second, third);
+		case MSGRCV:
+			switch (version) {
+			case 0: {
+				struct ipc_kludge tmp;
+				int err;
+				if (!ptr)
+					return -EINVAL;
+				if ((err = verify_area (VERIFY_READ, ptr, sizeof(tmp))))
+					return err;
+				memcpy_fromfs (&tmp,(struct ipc_kludge *) ptr,
+					       sizeof (tmp));
+				return sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp, third);
+				}
+			case 1: default:
+				return sys_msgrcv (first, (struct msgbuf *) ptr, second, fifth, third);
+			}
+		case MSGGET:
+			return sys_msgget ((key_t) first, second);
+		case MSGCTL:
+			return sys_msgctl (first, second, (struct msqid_ds *) ptr);
+		default:
+			return -EINVAL;
+		}
+	if (call <= SHMCTL) 
+		switch (call) {
+		case SHMAT:
+			switch (version) {
+			case 0: default: {
+				ulong raddr;
+				int err;
+				if ((err = verify_area(VERIFY_WRITE, (ulong*) third, sizeof(ulong))))
+					return err;
+				err = sys_shmat (first, (char *) ptr, second, &raddr);
+				if (err)
+					return err;
+				put_fs_long (raddr, (ulong *) third);
+				return 0;
+				}
+			case 1:	/* iBCS2 emulator entry point */
+				if (get_fs() != get_ds())
+					return -EINVAL;
+				return sys_shmat (first, (char *) ptr, second, (ulong *) third);
+			}
+		case SHMDT: 
+			return sys_shmdt ((char *)ptr);
+		case SHMGET:
+			return sys_shmget (first, second, third);
+		case SHMCTL:
+			return sys_shmctl (first, second, (struct shmid_ds *) ptr);
+		default:
+			return -EINVAL;
+		}
+	return -EINVAL;
+}
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/kernel/sys_sunos.c linux/arch/sparc/kernel/sys_sunos.c
--- v1.3.43/linux/arch/sparc/kernel/sys_sunos.c	Thu Jan  1 02:00:00 1970
+++ linux/arch/sparc/kernel/sys_sunos.c	Sat Nov 25 02:58:41 1995
@@ -0,0 +1,801 @@
+/* $Id: sys_sunos.c,v 1.20 1995/11/25 00:58:37 davem Exp $
+ * sys_sunos.c: SunOS specific syscall compatability support.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
+ *
+ * Based upon preliminary work which is:
+ *
+ * Copyright (C) 1995 Adrian M. Rodriguez (adrian@remus.rutgers.edu)
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/mman.h>
+#include <linux/errno.h>
+#include <linux/mm.h>
+#include <linux/fs.h>
+#include <linux/resource.h>
+#include <linux/signal.h>
+#include <linux/uio.h>
+#include <linux/utsname.h>
+#include <linux/fs.h>
+#include <linux/major.h>
+
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/pconf.h>
+
+/* For the nfs mount emulation */
+#include <linux/socket.h>
+#include <linux/in.h>
+#include <linux/nfs.h>
+#include <linux/nfs_mount.h>
+
+/* for sunos_select */
+#include <linux/time.h>
+#include <linux/personality.h>
+
+static unsigned long get_sparc_unmapped_area(unsigned long len)
+{
+	unsigned long addr;
+	struct vm_area_struct * vmm;
+
+	if (len > TASK_SIZE)
+		return 0;
+	addr = 0xE8000000UL;    /* To make it work on a sun4c. */
+	for (vmm = current->mm->mmap; ; vmm = vmm->vm_next) {
+		if (TASK_SIZE - len < addr)
+			return 0;
+		if (!vmm)
+			return addr;
+		if (addr > vmm->vm_end)
+			continue;
+		if (addr + len > vmm->vm_start) {
+			addr = vmm->vm_end;
+			continue;
+		}
+		return addr;
+	}
+}
+
+/* We use the SunOS mmap() semantics. */
+asmlinkage unsigned long sunos_mmap(unsigned long addr, unsigned long len,
+				    unsigned long prot, unsigned long flags,
+				    unsigned long fd, unsigned long off)
+{
+	struct file * file = NULL;
+	unsigned long retval, ret_type;
+
+	if(flags & MAP_NORESERVE) {
+		printk("%s: unimplemented SunOS MAP_NORESERVE mmap() flag\n",
+		       current->comm);
+		flags &= ~MAP_NORESERVE;
+	}
+	if(!(flags & MAP_ANONYMOUS))
+		if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
+			return -EBADF;
+	if(!(flags & MAP_FIXED) && !addr) {
+		addr = get_sparc_unmapped_area(len);
+		if(!addr)
+			return -ENOMEM;
+	}
+	/* If this is ld.so or a shared library doing an mmap
+	 * of /dev/zero, transform it into an anonymous mapping.
+	 * SunOS is so stupid some times... hmph!
+	 */
+	if(MAJOR(file->f_inode->i_rdev) == MEM_MAJOR &&
+	   MINOR(file->f_inode->i_rdev) == 5) {
+		flags |= MAP_ANONYMOUS;
+		file = 0;
+	}
+	ret_type = flags & _MAP_NEW;
+	flags &= ~_MAP_NEW;
+	retval = do_mmap(file, addr, len, prot, flags, off);
+	if(ret_type)
+		return retval;
+	else
+		return ((retval < KERNBASE) ? 0 : retval);
+}
+
+/* Weird SunOS mm control function.. */
+asmlinkage int sunos_mctl(unsigned long addr, unsigned long len, int function, char *arg)
+{
+	printk("%s: Call to sunos_mctl(addr<%08lx>, len<%08lx>, function<%d>, arg<%p>) "
+	       "is unsupported\n", current->comm, addr, len, function, arg);
+	return -EAGAIN;
+}
+
+/* XXX This won't be necessary when I sync up to never kernel in 1.3.x series
+ * XXX which has the sys_msync() system call implemented properly.
+ */
+asmlinkage int sunos_msync(unsigned long addr, unsigned long len, unsigned long flags)
+{
+	printk("%s: Call to sunos_msync(addr<%08lx>, len<%08lx>, flags<%08lx>) "
+	       "is unsupported\n", current->comm, addr, len, flags);
+	return -EINVAL;
+}
+
+/* SunOS is completely broken... it returns 0 on success, otherwise
+ * ENOMEM.  For sys_sbrk() it wants the new brk value as a return
+ * on success and ENOMEM as before on failure.
+ */
+asmlinkage int sunos_brk(unsigned long brk)
+{
+	int freepages;
+	unsigned long rlim;
+	unsigned long newbrk, oldbrk;
+
+	if (brk < current->mm->end_code)
+		return -ENOMEM;
+
+	newbrk = PAGE_ALIGN(brk);
+	oldbrk = PAGE_ALIGN(current->mm->brk);
+	if (oldbrk == newbrk) {
+		current->mm->brk = brk;
+		return 0;
+	}
+
+	/*
+	 * Always allow shrinking brk
+	 */
+	if (brk <= current->mm->brk) {
+		current->mm->brk = brk;
+		do_munmap(newbrk, oldbrk-newbrk);
+		return 0;
+	}
+	/*
+	 * Check against rlimit and stack..
+	 */
+	rlim = current->rlim[RLIMIT_DATA].rlim_cur;
+	if (rlim >= RLIM_INFINITY)
+		rlim = ~0;
+	if (brk - current->mm->end_code > rlim)
+		return -ENOMEM;
+
+	/*
+	 * Check against existing mmap mappings.
+	 */
+	if (find_vma_intersection(current, oldbrk, newbrk+PAGE_SIZE))
+		return -ENOMEM;
+
+	/*
+	 * stupid algorithm to decide if we have enough memory: while
+	 * simple, it hopefully works in most obvious cases.. Easy to
+	 * fool it, but this should catch most mistakes.
+	 */
+	freepages = buffermem >> 12;
+	freepages += nr_free_pages;
+	freepages += nr_swap_pages;
+	freepages -= MAP_NR(high_memory) >> 4;
+	freepages -= (newbrk-oldbrk) >> 12;
+	if (freepages < 0)
+		return -ENOMEM;
+	/*
+	 * Ok, we have probably got enough memory - let it rip.
+	 */
+	current->mm->brk = brk;
+	do_mmap(NULL, oldbrk, newbrk-oldbrk,
+		PROT_READ|PROT_WRITE|PROT_EXEC,
+		MAP_FIXED|MAP_PRIVATE, 0);
+	return 0;
+}
+
+asmlinkage unsigned long sunos_sbrk(int increment)
+{
+	int error;
+
+	/* This should do it hopefully... */
+	error = sunos_brk(((int) current->mm->brk) + increment);
+	if(error == 0)
+		return current->mm->brk;
+	else
+		return error;
+}
+
+/* XXX Completely undocumented, and completely magic...
+ * XXX I belive it is to increase the size of the stack by
+ * XXX argument 'increment' and return the new end of stack
+ * XXX area.  Wheee...
+ */
+asmlinkage unsigned long sunos_sstk(int increment)
+{
+	printk("%s: Call to sunos_sstk(increment<%d>) is unsupported\n",
+	       current->comm, increment);
+	return -1;
+}
+
+/* Give hints to the kernel as to what paging strategy to use...
+ * Completely bogus, don't remind me.
+ */
+#define VA_NORMAL     0 /* Normal vm usage expected */
+#define VA_ABNORMAL   1 /* Abnormal/random vm usage probable */
+#define VA_SEQUENTIAL 2 /* Accesses will be of a sequential nature */
+#define VA_INVALIDATE 3 /* Page table entries should be flushed ??? */
+static char *vstrings[] = {
+	"VA_NORMAL",
+	"VA_ABNORMAL",
+	"VA_SEQUENTIAL",
+	"VA_INVALIDATE",
+};
+
+asmlinkage void sunos_vadvise(unsigned long strategy)
+{
+	/* I wanna see who uses this... */
+	printk("%s: Advises us to use %s paging strategy\n",
+	       current->comm,
+	       strategy <= 3 ? vstrings[strategy] : "BOGUS");
+	return; /* We don't do diddly... */
+}
+
+/* Same as vadvise, and just as bogus, but for a range of virtual
+ * process address space.
+ */
+#define MADV_NORMAL      0 /* Nothing special... */
+#define MADV_RANDOM      1 /* I am emacs... */
+#define MADV_SEQUENTIAL  2 /* I am researcher code... */
+#define MADV_WILLNEED    3 /* Pages in this range will be needed */
+#define MADV_DONTNEED    4 /* Pages in this range won't be needed */
+
+static char *mstrings[] = {
+	"MADV_NORMAL",
+	"MADV_RANDOM",
+	"MADV_SEQUENTIAL",
+	"MADV_WILLNEED",
+	"MADV_DONTNEED",
+};
+
+asmlinkage void sunos_madvise(unsigned long address, unsigned long len,
+			      unsigned long strategy)
+{
+	/* I wanna see who uses this... */
+	printk("%s: Advises us to use %s paging strategy for addr<%08lx> len<%08lx>\n",
+	       current->comm,
+	       strategy <= 4 ? mstrings[strategy] : "BOGUS",
+	       address, len);
+	return; /* We don't do diddly... */
+}
+
+/* Places into character array, the status of all the pages in the passed
+ * range from 'addr' to 'addr + len'.  -1 on failure, 0 on success...
+ * The encoding in each character is:
+ * low-bit is zero == Page is not in physical ram right now
+ * low-bit is one  == Page is currently residing in core
+ * All other bits are undefined within the character so there...
+ * Also, if you try to get stats on an area outside of the user vm area
+ * *or* the passed base address is not aligned on a page boundry you
+ * get an error.
+ */
+asmlinkage int sunos_mincore(unsigned long addr, unsigned long len, char *array)
+{
+	pgd_t *pgdp;
+	pmd_t *pmdp;
+	pte_t *ptep;
+	unsigned long limit;
+	int num_pages, pnum;
+
+	if(addr & (PAGE_SIZE - 1))
+		return -EINVAL;
+
+	num_pages = (len / PAGE_SIZE);
+	if(verify_area(VERIFY_WRITE, array, num_pages))
+		return -EFAULT; /* bum array, you lose... */
+	if((addr >= KERNBASE) || ((addr + len) > KERNBASE))
+		return -ENOMEM; /* I'm sure you're curious about kernel mappings.. */
+
+	/* Wheee, go through pte's */
+	pnum = 0;
+	for(limit = addr + len; addr < limit; addr += PAGE_SIZE, pnum++) {
+		pgdp = pgd_offset(current->mm, addr);
+		if(pgd_none(*pgdp))
+			return -ENOMEM; /* As per SunOS manpage */
+		pmdp = pmd_offset(pgdp, addr);
+		if(pmd_none(*pmdp))
+			return -ENOMEM; /* As per SunOS manpage */
+		ptep = pte_offset(pmdp, addr);
+		if(pte_none(*ptep))
+			return -ENOMEM; /* As per SunOS manpage */
+		/* Page in core or Swapped page? */
+		array[pnum] = pte_present(*ptep) ? 1 : 0;
+	}
+	return 0; /* Success... I think... */
+}
+
+/* This just wants the soft limit (ie. rlim_cur element) of the RLIMIT_NOFILE
+ * resource limit and is for backwards compatability with older sunos
+ * revs.
+ */
+asmlinkage long sunos_getdtablesize(void)
+{
+	return NR_OPEN;
+}
+#define _S(nr) (1<<((nr)-1))
+
+#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
+
+asmlinkage unsigned long sunos_sigblock(unsigned long blk_mask)
+{
+	unsigned long old = current->blocked;
+
+	current->blocked |= (blk_mask & _BLOCKABLE);
+	return old;
+}
+
+/* SunOS getdents is very similar to the newer Linux (iBCS2 compliant)    */
+/* getdents system call, the format of the structure just has a different */
+/* layout (d_off+d_ino instead of d_ino+d_off) */
+struct sunos_dirent {
+    long           d_off;
+    unsigned long  d_ino;
+    unsigned short d_reclen;
+    unsigned short d_namlen;
+    char           d_name[1];
+};
+
+struct sunos_dirent_callback {
+    struct sunos_dirent *curr;
+    struct sunos_dirent *previous;
+    int count;
+    int error;
+};
+
+#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
+#define ROUND_UP(x) (((x)+sizeof(long)-1) & ~(sizeof(long)-1))
+
+static int sunos_filldir(void * __buf, const char * name, int namlen,
+			 off_t offset, ino_t ino)
+{
+	struct sunos_dirent * dirent;
+	struct sunos_dirent_callback * buf = (struct sunos_dirent_callback *) __buf;
+	int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);
+
+	buf->error = -EINVAL;	/* only used if we fail.. */
+	if (reclen > buf->count)
+		return -EINVAL;
+	dirent = buf->previous;
+	if (dirent)
+		put_user(offset, &dirent->d_off);
+	dirent = buf->curr;
+	buf->previous = dirent;
+	put_user(ino, &dirent->d_ino);
+	put_user((strlen(name)), &dirent->d_namlen);
+	put_user(reclen, &dirent->d_reclen);
+	memcpy_tofs(dirent->d_name, name, namlen);
+	put_user(0, dirent->d_name + namlen);
+	((char *) dirent) += reclen;
+	buf->curr = dirent;
+	buf->count -= reclen;
+	return 0;
+}
+
+asmlinkage int sunos_getdents(unsigned int fd, void * dirent, int cnt)
+{
+	struct file * file;
+	struct sunos_dirent * lastdirent;
+	struct sunos_dirent_callback buf;
+	int error;
+
+	if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
+		return -EBADF;
+	if (!file->f_op || !file->f_op->readdir)
+		return -ENOTDIR;
+	if(verify_area(VERIFY_WRITE, dirent, cnt))
+		return -EFAULT;
+	if(cnt < (sizeof(struct sunos_dirent) + 255))
+		return -EINVAL;
+
+	buf.curr = (struct sunos_dirent *) dirent;
+	buf.previous = NULL;
+	buf.count = cnt;
+	buf.error = 0;
+	error = file->f_op->readdir(file->f_inode, file, &buf, sunos_filldir);
+	if (error < 0)
+		return error;
+	lastdirent = buf.previous;
+	if (!lastdirent)
+		return buf.error;
+	put_user(file->f_pos, &lastdirent->d_off);
+	return cnt - buf.count;
+}
+
+asmlinkage int sunos_getdomainname(char *name, int len)
+{
+	int error;
+
+	if(len > __NEW_UTS_LEN)
+		return -EFAULT;
+	error = verify_area(VERIFY_WRITE, name, len);
+	if(error)
+		return -EFAULT;
+	memcpy_tofs(name, system_utsname.domainname, len);
+	return 0;
+}
+
+struct sunos_utsname {
+	char sname[9];
+	char nname[9];
+	char nnext[56];
+	char rel[9];
+	char ver[9];
+	char mach[9];
+};
+
+asmlinkage int sunos_uname(struct sunos_utsname *name)
+{
+	int error;
+	if(!name)
+		return -EFAULT;
+	error = verify_area(VERIFY_WRITE, name, sizeof *name);
+	if(error)
+		return error;
+	memcpy_tofs(&name->sname[0], &system_utsname.sysname[0],
+		    sizeof(name->sname));
+	memcpy_tofs(&name->nname[0], &system_utsname.nodename[0],
+		    sizeof(name->nname));
+	name->nname[8] = '\0';
+	memcpy_tofs(&name->nnext[0], &system_utsname.nodename[9],
+		    sizeof(name->nnext));
+	memcpy_tofs(&name->rel[0], &system_utsname.release[0],
+		    sizeof(name->rel));
+	memcpy_tofs(&name->ver[0], &system_utsname.version[0],
+		    sizeof(name->ver));
+	memcpy_tofs(&name->mach[0], &system_utsname.machine[0],
+		    sizeof(name->mach));
+	return 0;
+}
+
+asmlinkage int sunos_nosys(void)
+{
+	struct pt_regs *regs;
+
+	regs = (struct pt_regs *) (((current->tss.ksp) & PAGE_MASK) +
+				   (PAGE_SIZE - TRACEREG_SZ));
+	current->tss.sig_address = regs->pc;
+	current->tss.sig_desc = regs->u_regs[UREG_G1];
+	send_sig(SIGSYS, current, 1);
+	printk("Process makes ni_syscall number %d, register dump:\n",
+	       (int) regs->u_regs[UREG_G1]);
+	show_regs(regs);
+	return -ENOSYS;
+}
+
+/* This is not a real and complete implementation yet, just to keep
+ * the easy SunOS binaries happy.
+ */
+asmlinkage int sunos_fpathconf(int fd, int name)
+{
+	switch(name) {
+	case _PCONF_LINK:
+		return LINK_MAX;
+	case _PCONF_CANON:
+		return MAX_CANON;
+	case _PCONF_INPUT:
+		return MAX_INPUT;
+	case _PCONF_NAME:
+		return NAME_MAX;
+	case _PCONF_PATH:
+		return PATH_MAX;
+	case _PCONF_PIPE:
+		return PIPE_BUF;
+	case _PCONF_CHRESTRICT:
+		return 1; /* XXX Investigate XXX */
+	case _PCONF_NOTRUNC:
+		return 0; /* XXX Investigate XXX */
+	case _PCONF_VDISABLE:
+		return 30; /* XXX Investigate XXX */
+	default:
+		return -EINVAL;
+	}
+}
+
+asmlinkage int sunos_pathconf(char *path, int name)
+{
+	return sunos_fpathconf(0, name); /* XXX cheese XXX */
+}
+
+/* SunOS mount system call emulation */
+extern asmlinkage int
+sys_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, struct timeval *tvp);
+
+asmlinkage int sunos_select(int width, fd_set *inp, fd_set *outp, fd_set *exp, struct timeval *tvp)
+{
+    /* SunOS binaries expect that select won't change the tvp contents */
+    current->personality |= STICKY_TIMEOUTS;
+    return sys_select (width, inp, outp, exp, tvp);
+}
+
+asmlinkage void sunos_nop(void)
+{
+	return;
+}
+
+/* SunOS mount/umount. */
+#define SMNT_RDONLY       1
+#define SMNT_NOSUID       2
+#define SMNT_NEWTYPE      4
+#define SMNT_GRPID        8
+#define SMNT_REMOUNT      16
+#define SMNT_NOSUB        32
+#define SMNT_MULTI        64
+#define SMNT_SYS5         128
+
+struct ufs_mntargs {
+	char *dev_name;
+};
+
+struct lo_mntargs {
+	char *dev_name;
+};
+
+struct ext2_mntargs {
+	char *dev_name;
+};
+
+struct iso9660_mntargs {
+	char *dev_name;
+};
+
+struct minix_mntargs {
+	char *dev_name;
+};
+
+struct ext_mntargs {
+	char *dev_name;
+};
+
+struct msdos_mntargs {
+	char *dev_name;
+};
+
+struct xiafs_mntargs {
+	char *dev_name;
+};
+
+struct sunos_fh_t {
+	char fh_data [NFS_FHSIZE];
+};
+
+struct sunos_nfs_mount_args {
+	struct sockaddr_in  *addr; /* file server address */
+	struct nfs_fh *fh;     /* File handle to be mounted */
+	int        flags;      /* flags */
+	int        wsize;      /* write size in bytes */
+	int        rsize;      /* read size in bytes */
+	int        timeo;      /* initial timeout in .1 secs */
+	int        retrans;    /* times to retry send */
+	char       *hostname;  /* server's hostname */
+	int        acregmin;   /* attr cache file min secs */
+	int        acregmax;   /* attr cache file max secs */
+	int        acdirmin;   /* attr cache dir min secs */
+	int        acdirmax;   /* attr cache dir max secs */
+	char       *netname;   /* server's netname */
+};
+
+extern asmlinkage int sys_mount(char *, char *, char *, unsigned long, void *);
+
+extern int do_mount(dev_t, const char *, char *, int, void *);
+extern dev_t get_unnamed_dev(void);
+extern void put_unnamed_dev(dev_t);
+
+extern sys_mount (char * dev_name, char * dir_name, char * type,
+		  unsigned long new_flags, void * data);
+
+extern asmlinkage int
+sys_connect(int fd, struct sockaddr *uservaddr, int addrlen);
+
+extern asmlinkage int
+sys_socket(int family, int type, int protocol);
+
+asmlinkage int
+sys_bind(int fd, struct sockaddr *umyaddr, int addrlen);
+
+
+/* Bind the socket on a local reserved port and connect it to the
+ * remote server.  This on Linux/i386 is done by the mount program,
+ * not by the kernel. 
+ */
+static int
+sunos_nfs_get_server_fd (int fd, struct sockaddr_in *addr)
+{
+	struct sockaddr_in local;
+	struct sockaddr_in server;
+	int    try_port;
+	int    ret;
+	struct socket *socket;
+	struct inode  *inode;
+	struct file   *file;
+
+	file = current->files->fd [fd];
+	inode = file->f_inode;
+	if (!inode || !inode->i_sock)
+		return 0;
+
+	socket = &inode->u.socket_i;
+	local.sin_family = AF_INET;
+	local.sin_addr.s_addr = INADDR_ANY;
+
+	/* IPPORT_RESERVED = 1024, can't find the definition in the kernel */
+	try_port = 1024;
+	do {
+		local.sin_port = htons (--try_port);
+		ret = socket->ops->bind(socket, (struct sockaddr*)&local,
+					sizeof(local));
+	} while (ret && try_port > (1024 / 2));
+
+	if (ret)
+		return 0;
+
+	server.sin_family = AF_INET;
+	server.sin_addr = addr->sin_addr;
+	server.sin_port = NFS_PORT;
+
+	/* Call sys_connect */
+	ret = socket->ops->connect (socket, (struct sockaddr *) &server,
+				    sizeof (server), file->f_flags);
+	if (ret < 0)
+		return 0;
+	return 1;
+}
+
+static int get_default (int value, int def_value)
+{
+    if (value)
+	return value;
+    else
+	return def_value;
+}
+
+asmlinkage int sunos_nfs_mount(char *dir_name, int linux_flags, void *data)
+{
+	int  ret = -ENODEV, error;
+	int  server_fd;
+	char *the_name;
+	struct nfs_mount_data linux_nfs_mount;
+	struct sunos_nfs_mount_args *sunos_mount = data;
+	dev_t dev;
+	struct pt_regs *regs;
+
+	error = verify_area(VERIFY_READ, data, sizeof (struct sunos_nfs_mount_args));
+	if (error)
+		return error;
+	/* Ok, here comes the fun part: Linux's nfs mount needs a
+	 * socket connection to the server, but SunOS mount does not
+	 * requiere this, so we use the information on the destination
+	 * address to create a socket and bind it to a reserved
+	 * port on this system
+	 */
+	server_fd = sys_socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+	if (server_fd < 0)
+		return -ENXIO;
+
+	if (!sunos_nfs_get_server_fd (server_fd, sunos_mount->addr)){
+		sys_close (server_fd);
+		return -ENXIO;
+	}
+
+	/* Now, bind it to a locally reserved port */
+	linux_nfs_mount.version  = NFS_MOUNT_VERSION;
+	linux_nfs_mount.flags    = sunos_mount->flags;
+	linux_nfs_mount.addr     = *sunos_mount->addr;
+	linux_nfs_mount.root     = *sunos_mount->fh;
+	linux_nfs_mount.fd       = server_fd;
+	
+	linux_nfs_mount.rsize    = get_default (sunos_mount->rsize, 8192);
+	linux_nfs_mount.wsize    = get_default (sunos_mount->wsize, 8192);
+	linux_nfs_mount.timeo    = get_default (sunos_mount->timeo, 10);
+	linux_nfs_mount.retrans  = sunos_mount->retrans;
+	
+	linux_nfs_mount.acregmin = sunos_mount->acregmin;
+	linux_nfs_mount.acregmax = sunos_mount->acregmax;
+	linux_nfs_mount.acdirmin = sunos_mount->acdirmin;
+	linux_nfs_mount.acdirmax = sunos_mount->acdirmax;
+
+	if (getname (sunos_mount->hostname, &the_name))
+		return -EFAULT;
+
+	strncpy (linux_nfs_mount.hostname, the_name, 254);
+	linux_nfs_mount.hostname [255] = 0;
+	putname (the_name);
+
+	dev = get_unnamed_dev ();
+	
+	ret = do_mount (dev, dir_name, "nfs", linux_flags, &linux_nfs_mount);
+	if (ret)
+	    put_unnamed_dev(dev);
+
+#if 0
+	/* Kill the process: the nfs directory is already mounted */
+	regs = (struct pt_regs *) (((current->tss.ksp) & PAGE_MASK) +
+				   (PAGE_SIZE - TRACEREG_SZ));
+	current->tss.sig_address = regs->pc;
+	current->tss.sig_desc = regs->u_regs[UREG_G1];
+	send_sig(SIGSYS, current, 1);
+#endif
+	return ret;
+}
+
+asmlinkage int
+sunos_mount(char *type, char *dir, int flags, void *data)
+{
+	int linux_flags = MS_MGC_MSK; /* new semantics */
+	int error;
+	char *dev_fname = 0;
+
+	/* We don't handle the integer fs type */
+	if ((flags & SMNT_NEWTYPE) == 0)
+		return -EINVAL;
+
+	/* Do not allow for those flags we don't support */
+	if (flags & (SMNT_GRPID|SMNT_NOSUB|SMNT_MULTI|SMNT_SYS5))
+		return -EINVAL;
+
+	if(flags & SMNT_REMOUNT)
+		linux_flags |= MS_REMOUNT;
+	if(flags & SMNT_RDONLY)
+		linux_flags |= MS_RDONLY;
+	if(flags & SMNT_NOSUID)
+		linux_flags |= MS_NOSUID;
+	error = verify_area(VERIFY_READ, type, 16);
+	if(error)
+		return error;
+	if(strcmp(type, "ext2") == 0) {
+		dev_fname = (char *) data;;
+	} else if(strcmp(type, "iso9660") == 0) {
+		dev_fname = (char *) data;
+	} else if(strcmp(type, "minix") == 0) {
+		dev_fname = (char *) data;
+	} else if(strcmp(type, "ext") == 0) {
+		dev_fname = (char *) data;
+	} else if(strcmp(type, "xiafs") == 0) {
+		dev_fname = (char *) data;
+	} else if(strcmp(type, "nfs") == 0) {
+		error = sunos_nfs_mount (dir, flags, data);
+		return error;
+        } else if(strcmp(type, "ufs") == 0) {
+		printk("Warning: UFS filesystem mounts unsupported.\n");
+		return -ENODEV;
+	} else if(strcmp(type, "proc")) {
+		return -ENODEV;
+	}
+	if(error)
+		return error;
+	error = sys_mount(dev_fname, dir, type, linux_flags, NULL);
+	printk("sys_mount(type<%s>, device<%s>) returns %d\n",
+	       type, dev_fname, error);
+	return error;
+}
+
+extern asmlinkage int sys_setsid(void);
+extern asmlinkage int sys_setpgid(pid_t, pid_t);
+
+asmlinkage int sunos_setpgrp(pid_t pid, pid_t pgid)
+{
+	/* So stupid... */
+	if((!pid || pid == current->pid) &&
+	   !pgid) {
+		sys_setsid();
+		return 0;
+	} else {
+		return sys_setpgid(pid, pgid);
+	}
+}
+
+/* So stupid... */
+extern asmlinkage int sys_wait4(pid_t, unsigned int *, int, struct rusage *);
+asmlinkage int sunos_wait4(pid_t pid, unsigned int *stat_addr, int options, struct rusage *ru)
+{
+	return sys_wait4((pid ? pid : -1), stat_addr, options, ru);
+}
+
+extern int kill_pg(int, int, int);
+asmlinkage int sunos_killpg(int pgrp, int sig)
+{
+	return kill_pg(pgrp, sig, 0);
+}
+
+extern asmlinkage sunos_audit ()
+{
+	printk ("sys_audit\n");
+	return -1;
+}
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/kernel/systbls.S linux/arch/sparc/kernel/systbls.S
--- v1.3.43/linux/arch/sparc/kernel/systbls.S	Thu Jan  1 02:00:00 1970
+++ linux/arch/sparc/kernel/systbls.S	Sat Nov 25 02:58:45 1995
@@ -0,0 +1,538 @@
+/* $Id: systbls.S,v 1.22 1995/11/25 00:58:42 davem Exp $
+ * systbls.S: System call entry point tables for OS compatability.
+ *            The native Linux system call table lives here also.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ *
+ * Based upon preliminary work which is:
+ *
+ * Copyright (C) 1995 Adrian M. Rodriguez (adrian@remus.rutgers.edu)
+ */
+
+#include <asm/cprefix.h>
+
+	.data
+	.align 4
+
+	/* First, the Linux native syscall table. */
+
+	.globl C_LABEL(sys_call_table)
+C_LABEL(sys_call_table):
+	.long C_LABEL(sys_setup)		/* 0 */
+	.long C_LABEL(sys_exit)
+	.long C_LABEL(sys_fork)
+	.long C_LABEL(sys_read)
+	.long C_LABEL(sys_write)
+	.long C_LABEL(sys_open)			/* 5 */
+	.long C_LABEL(sys_close)
+	.long C_LABEL(sys_wait4)
+	.long C_LABEL(sys_creat)
+	.long C_LABEL(sys_link)
+	.long C_LABEL(sys_unlink)		/* 10 */
+	.long C_LABEL(sunos_execv)
+	.long C_LABEL(sys_chdir)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_mknod)
+	.long C_LABEL(sys_chmod)		/* 15 */
+	.long C_LABEL(sys_chown)
+	.long C_LABEL(sys_brk)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_lseek)
+	.long C_LABEL(sys_getpid)		/* 20 */
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_setuid)
+	.long C_LABEL(sys_getuid)
+	.long C_LABEL(sys_ni_syscall)		/* 25 */
+	.long C_LABEL(sys_ni_syscall)		/* this will be sys_ptrace() */
+	.long C_LABEL(sys_alarm)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_pause)
+	.long C_LABEL(sys_utime)		/* 30 */
+	.long C_LABEL(sys_stty)
+	.long C_LABEL(sys_gtty)
+	.long C_LABEL(sys_access)
+	.long C_LABEL(sys_nice)
+	.long C_LABEL(sys_ftime)		/* 35 */
+	.long C_LABEL(sys_sync)
+	.long C_LABEL(sys_kill)
+	.long C_LABEL(sys_newstat)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_newlstat)		/* 40 */
+	.long C_LABEL(sys_dup)
+	.long C_LABEL(sys_pipe)
+	.long C_LABEL(sys_times)
+	.long C_LABEL(sys_profil)
+	.long C_LABEL(sys_ni_syscall)		/* 45 */
+	.long C_LABEL(sys_setgid)
+	.long C_LABEL(sys_getgid)
+	.long C_LABEL(sys_signal)
+	.long C_LABEL(sys_geteuid)
+	.long C_LABEL(sys_getegid)		/* 50 */
+	.long C_LABEL(sys_acct)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ioctl)
+	.long C_LABEL(sys_reboot)		/* 55 */
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_symlink)
+	.long C_LABEL(sys_readlink)
+	.long C_LABEL(sys_execve)
+	.long C_LABEL(sys_umask)		/* 60 */
+	.long C_LABEL(sys_chroot)
+	.long C_LABEL(sys_newfstat)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_getpagesize)
+	.long C_LABEL(sys_ni_syscall)		/* 65 */
+	.long C_LABEL(sys_vfork)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)		/* 70 */
+	.long C_LABEL(sunos_mmap)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_munmap)
+	.long C_LABEL(sys_mprotect)
+	.long C_LABEL(sys_ni_syscall)		/* 75 */
+	.long C_LABEL(sys_vhangup)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_getgroups)
+	.long C_LABEL(sys_setgroups)		/* 80 */
+	.long C_LABEL(sys_getpgrp)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_setitimer)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_swapon)		/* 85 */
+	.long C_LABEL(sys_getitimer)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_sethostname)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_dup2)			/* 90 */
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_fcntl)
+	.long C_LABEL(sys_select)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_fsync)		/* 95 */
+	.long C_LABEL(sys_setpriority)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_getpriority)		/* 100 */
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)		/* 105 */
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)		/* 110 */
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)		/* 115 */
+	.long C_LABEL(sys_gettimeofday)
+	.long C_LABEL(sys_getrusage)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)		/* 120 */
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_settimeofday)
+	.long C_LABEL(sys_fchown)
+	.long C_LABEL(sys_fchmod)
+	.long C_LABEL(sys_ni_syscall)		/* 125 */
+	.long C_LABEL(sys_setreuid)
+	.long C_LABEL(sys_setregid)
+	.long C_LABEL(sys_rename)
+	.long C_LABEL(sys_truncate)
+	.long C_LABEL(sys_ftruncate)		/* 130 */
+	.long C_LABEL(sys_flock)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)		/* 135 */
+	.long C_LABEL(sys_mkdir)
+	.long C_LABEL(sys_rmdir)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)		/* 140 */
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_getrlimit)
+	.long C_LABEL(sys_setrlimit)		/* 145 */
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)		/* 150 */
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)		/* 155 */
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_statfs)
+	.long C_LABEL(sys_fstatfs)
+	.long C_LABEL(sys_umount)
+	.long C_LABEL(sys_ni_syscall)		/* 160 */
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_setdomainname)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)		/* sys_quotactl -- 165 */
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_mount)
+	.long C_LABEL(sys_ustat)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)		/* 170 */
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_getdents)
+	.long C_LABEL(sys_setsid)		/* 175 */
+	.long C_LABEL(sys_fchdir)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)		/* 180 */
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_sigpending)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_setpgid)		/* 185 */
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_uname)
+	.long C_LABEL(sys_init_module)		/* 190 */
+	.long C_LABEL(sys_personality)
+	.long C_LABEL(sys_prof)
+	.long C_LABEL(sys_break)
+	.long C_LABEL(sys_lock)
+	.long C_LABEL(sys_mpx)			/* 195 */
+	.long C_LABEL(sys_ulimit)
+	.long C_LABEL(sys_getppid)
+	.long C_LABEL(sys_sigaction)
+	.long C_LABEL(sys_sgetmask)
+	.long C_LABEL(sys_ssetmask)		/* 200 */
+	.long C_LABEL(sys_sigsuspend)
+	.long C_LABEL(sys_newlstat)
+	.long C_LABEL(sys_uselib)
+	.long C_LABEL(old_readdir)
+	.long C_LABEL(sys_ni_syscall)		/* 205 */
+	.long C_LABEL(sys_socketcall)
+	.long C_LABEL(sys_syslog)
+	.long C_LABEL(sys_olduname)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_idle)			/* 210 */
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_waitpid)
+	.long C_LABEL(sys_swapoff)
+	.long C_LABEL(sys_sysinfo)
+	.long C_LABEL(sys_ipc)			/* 215 */
+	.long C_LABEL(sys_sigreturn)
+	.long C_LABEL(sys_clone)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_adjtimex)
+	.long C_LABEL(sys_sigprocmask)		/* 220 */
+	.long C_LABEL(sys_create_module)
+	.long C_LABEL(sys_delete_module)
+	.long C_LABEL(sys_get_kernel_syms)
+	.long C_LABEL(sys_getpgid)
+	.long C_LABEL(sys_bdflush)		/* 225 */
+	.long C_LABEL(sys_sysfs)
+	.long C_LABEL(sys_ni_syscall)		/* Andrew Filesystem Syscall */
+	.long C_LABEL(sys_setfsuid)
+	.long C_LABEL(sys_setfsgid)
+	.long C_LABEL(sys_llseek)		/* 230 Should be newselect... */
+	.long C_LABEL(sys_time)
+	.long C_LABEL(sys_ni_syscall) 		/* Should be oldstat... */
+	.long C_LABEL(sys_stime)
+	.long C_LABEL(sys_ni_syscall)           /* Should be oldfstat */
+	.long C_LABEL(sys_ni_syscall)		/* 235 - sys_phys */
+	.long C_LABEL(sys_llseek)
+
+	/* "We are the Knights of the Forest of Ni!!" */
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)		/* 240 */
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)		/* 245 */
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)		/* 250 */
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)
+	.long C_LABEL(sys_ni_syscall)		/* 255 */
+
+	/* Now the SunOS syscall table. */
+
+	.align 4
+	.globl C_LABEL(sunos_sys_table)
+C_LABEL(sunos_sys_table):
+	.long C_LABEL(sunos_indir)		/* so stupid... */
+	.long C_LABEL(sys_exit)
+	.long C_LABEL(sys_fork)
+	.long C_LABEL(sys_read)
+	.long C_LABEL(sys_write)
+	.long C_LABEL(sys_open)			/* 5 */
+	.long C_LABEL(sys_close)
+	.long C_LABEL(sunos_wait4)		/* broken... */
+	.long C_LABEL(sys_creat)
+	.long C_LABEL(sys_link)
+	.long C_LABEL(sys_unlink)		/* 10 */
+	.long C_LABEL(sunos_execv)
+	.long C_LABEL(sys_chdir)
+	.long C_LABEL(sunos_nosys)		/* Obsolete sys_time(), unused */
+	.long C_LABEL(sys_mknod)
+	.long C_LABEL(sys_chmod)		/* 15 */
+	.long C_LABEL(sys_chown)
+	.long C_LABEL(sunos_brk)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sys_lseek)
+	.long C_LABEL(sunos_getpid)		/* 20 */
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_getuid)
+	.long C_LABEL(sunos_nosys)		/* 25 */
+	.long C_LABEL(sunos_nosys)		/* this will be sys_ptrace() */
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)		/* Old SunOS fstat, unsupported */
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)		/* 30 */
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sys_access)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)		/* 35 */
+	.long C_LABEL(sys_sync)
+	.long C_LABEL(sys_kill)
+	.long C_LABEL(sys_newstat)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sys_newlstat)		/* 40 */
+	.long C_LABEL(sys_dup)
+	.long C_LABEL(sys_pipe)
+	.long C_LABEL(sunos_nosys)		/* SunOS sys_times() */
+	.long C_LABEL(sys_profil)
+	.long C_LABEL(sunos_nosys)		/* 45 */
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_getgid)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)		/* 50 */
+	.long C_LABEL(sys_acct)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_mctl)
+	.long C_LABEL(sunos_ioctl)
+	.long C_LABEL(sys_reboot)		/* 55 */
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sys_symlink)
+	.long C_LABEL(sys_readlink)
+	.long C_LABEL(sys_execve)
+	.long C_LABEL(sys_umask)		/* 60 */
+	.long C_LABEL(sys_chroot)
+	.long C_LABEL(sys_newfstat)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sys_getpagesize)
+	.long C_LABEL(sunos_msync)		/* 65 */
+	.long C_LABEL(sys_vfork)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_sbrk)
+	.long C_LABEL(sunos_sstk)		/* 70 */
+	.long C_LABEL(sunos_mmap)
+	.long C_LABEL(sunos_vadvise)
+	.long C_LABEL(sys_munmap)
+	.long C_LABEL(sys_mprotect)
+	.long C_LABEL(sunos_madvise)		/* 75 */
+	.long C_LABEL(sys_vhangup)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_mincore)
+	.long C_LABEL(sys_getgroups)
+	.long C_LABEL(sys_setgroups)		/* 80 */
+	.long C_LABEL(sys_getpgrp)
+	.long C_LABEL(sunos_setpgrp)
+	.long C_LABEL(sys_setitimer)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sys_swapon)		/* 85 */
+	.long C_LABEL(sys_getitimer)
+	.long C_LABEL(sys_gethostname)
+	.long C_LABEL(sys_sethostname)
+	.long C_LABEL(sunos_getdtablesize)
+	.long C_LABEL(sys_dup2)			/* 90 */
+	.long C_LABEL(sunos_nop)		/* getdopt() does nothing */
+	.long C_LABEL(sys_fcntl)
+	.long C_LABEL(sys_select)
+	.long C_LABEL(sunos_nop)		/* setdopt() also does nothing */
+	.long C_LABEL(sys_fsync)		/* 95 */
+	.long C_LABEL(sys_setpriority)
+	.long C_LABEL(sys_socket)
+	.long C_LABEL(sys_connect)
+	.long C_LABEL(sys_accept)
+	.long C_LABEL(sys_getpriority)		/* 100 */
+	.long C_LABEL(sys_send)
+	.long C_LABEL(sys_recv)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sys_bind)
+	.long C_LABEL(sys_setsockopt)		/* 105 */
+	.long C_LABEL(sys_listen)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sys_sigaction)		/* sigvec */
+	.long C_LABEL(sunos_sigblock)		/* sigblock */
+	.long C_LABEL(sys_ssetmask)		/* sigsetmask -- 110 */
+	.long C_LABEL(sys_sigpause)		/* sigpause */
+	.long C_LABEL(sys_sigstack)		/* sigstack */
+	.long C_LABEL(sunos_nosys)		/* recvmsg */
+	.long C_LABEL(sunos_nosys)		/* sendmsg */
+	.long C_LABEL(sunos_nosys)		/* vtrace -- 115 */
+	.long C_LABEL(sys_gettimeofday)
+	.long C_LABEL(sys_getrusage)
+	.long C_LABEL(sys_getsockopt)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sys_readv)		/* 120 */
+	.long C_LABEL(sys_writev)
+	.long C_LABEL(sys_settimeofday)
+	.long C_LABEL(sys_fchown)
+	.long C_LABEL(sys_fchmod)
+	.long C_LABEL(sys_recvfrom)		/* recvfrom -- 125 */
+	.long C_LABEL(sys_setreuid)
+	.long C_LABEL(sys_setregid)
+	.long C_LABEL(sys_rename)
+	.long C_LABEL(sys_truncate)
+	.long C_LABEL(sys_ftruncate)		/* 130 */
+	.long C_LABEL(sys_flock)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sys_sendto)		/* sendto */
+	.long C_LABEL(sys_shutdown)		/* shutdown */
+	.long C_LABEL(sunos_nosys)		/* socketpair -- 135 */
+	.long C_LABEL(sys_mkdir)
+	.long C_LABEL(sys_rmdir)
+	.long C_LABEL(sys_utimes)		/* utimes */
+	.long C_LABEL(sys_sigreturn)
+	.long C_LABEL(sunos_nosys)		/* adjtime -- 140 */
+	.long C_LABEL(sys_getpeername)		/* getpeername */
+	.long C_LABEL(sunos_nosys)		/* gethostid */
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sys_getrlimit)
+	.long C_LABEL(sys_setrlimit)		/* 145 */
+	.long C_LABEL(sunos_killpg)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sys_getsockname)		/* getsockname -- 150 */
+	.long C_LABEL(sunos_nosys)		/* getmsg */
+	.long C_LABEL(sunos_nosys)		/* putmsg */
+	.long C_LABEL(sunos_nosys)		/* poll */
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)		/* nfssvc -- 155 */
+	.long C_LABEL(sunos_nosys)		/* getdirectries */
+	.long C_LABEL(sys_statfs)
+	.long C_LABEL(sys_fstatfs)
+	.long C_LABEL(sys_umount)
+	.long C_LABEL(sunos_nosys)		/* async_daemon -- 160 */
+	.long C_LABEL(sunos_nosys)		/* getfh */
+	.long C_LABEL(sunos_getdomainname)	/* getdomainname */
+	.long C_LABEL(sys_setdomainname)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)		/* quotactl -- 165 */
+	.long C_LABEL(sunos_nosys)		/* exportfs */
+	.long C_LABEL(sunos_mount)
+	.long C_LABEL(sys_ustat)
+	.long C_LABEL(sunos_nosys)		/* semsys */
+	.long C_LABEL(sunos_nosys)		/* msgsys -- 170 */
+	.long C_LABEL(sunos_nosys)		/* shmsys */
+	.long C_LABEL(sunos_audit)		/* auditsys */
+	.long C_LABEL(sunos_nosys)		/* rfssys */
+	.long C_LABEL(sunos_getdents)
+	.long C_LABEL(sys_setsid)		/* 175 */
+	.long C_LABEL(sys_fchdir)
+	.long C_LABEL(sunos_nosys)		/* fchroot */
+	.long C_LABEL(sunos_nosys)		/* vpixsys ???XXX */
+	.long C_LABEL(sunos_nosys)		/* aioread */
+	.long C_LABEL(sunos_nosys)		/* aiowrite -- 180 */
+	.long C_LABEL(sunos_nosys)		/* aiowait */
+	.long C_LABEL(sunos_nosys)		/* aiocancel */
+	.long C_LABEL(sys_sigpending)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sys_setpgid)		/* 185 */
+	.long C_LABEL(sunos_pathconf)		/* pathconf */
+	.long C_LABEL(sunos_fpathconf)		/* fpathconf */
+	.long C_LABEL(sunos_nosys)		/* sysconf */
+	.long C_LABEL(sunos_uname)
+	.long C_LABEL(sunos_nosys)		/* 190 */
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)		/* 195 */
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)		/* 200 */
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)		/* 205 */
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)		/* 210 */
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)		/* 215 */
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)		/* 220 */
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)		/* 225 */
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)		/* 230 */
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)		/* 235 */
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)		/* 240 */
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)		/* 245 */
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)		/* 250 */
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)
+	.long C_LABEL(sunos_nosys)		/* 255 */
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/kernel/time.c linux/arch/sparc/kernel/time.c
--- v1.3.43/linux/arch/sparc/kernel/time.c	Thu Jan  1 02:00:00 1970
+++ linux/arch/sparc/kernel/time.c	Sat Nov 25 02:58:47 1995
@@ -0,0 +1,79 @@
+/* $Id: time.c,v 1.3 1995/11/25 00:58:45 davem Exp $
+ * linux/arch/sparc/kernel/time.c
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ *
+ * This file handles the Sparc specific time handling details.
+ */
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/timex.h>
+
+#include <asm/segment.h>
+#include <asm/timer.h>
+
+#define TIMER_IRQ  10    /* Also at level 14, but we ignore that one. */
+
+static int set_rtc_mmss(unsigned long);
+
+/*
+ * timer_interrupt() needs to keep up the real-time clock,
+ * as well as call the "do_timer()" routine every clocktick
+ */
+void timer_interrupt(int irq, struct pt_regs * regs)
+{
+	/* last time the cmos clock got updated */
+	static long last_rtc_update=0;
+	volatile unsigned int clear_intr;
+
+	/* First, clear the interrupt. */
+	clear_intr = *master_l10_limit;
+
+	do_timer(regs);
+
+	/* XXX I don't know if this is right for the Sparc yet. XXX */
+	if (time_state != TIME_BAD && xtime.tv_sec > last_rtc_update + 660 &&
+	    xtime.tv_usec > 500000 - (tick >> 1) &&
+	    xtime.tv_usec < 500000 + (tick >> 1))
+	  if (set_rtc_mmss(xtime.tv_sec) == 0)
+	    last_rtc_update = xtime.tv_sec;
+	  else
+	    last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
+}
+
+void time_init(void)
+{
+	request_irq(TIMER_IRQ, timer_interrupt, SA_INTERRUPT, "timer");
+	return;
+}
+/* Nothing fancy on the Sparc yet. */
+void do_gettimeofday(struct timeval *tv)
+{
+	unsigned long flags;
+
+	save_flags(flags);
+	cli();
+	*tv = xtime;
+	restore_flags(flags);
+}
+
+void do_settimeofday(struct timeval *tv)
+{
+	cli();
+	xtime = *tv;
+	time_state = TIME_BAD;
+	time_maxerror = 0x70000000;
+	time_esterror = 0x70000000;
+	sti();
+}
+
+/* XXX Mostek RTC code needs to be written XXX */
+static int set_rtc_mmss(unsigned long nowtime)
+{
+	/* Just say we succeeded for now. */
+	return 0;
+}
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/kernel/traps.c linux/arch/sparc/kernel/traps.c
--- v1.3.43/linux/arch/sparc/kernel/traps.c	Tue Jun 27 14:11:32 1995
+++ linux/arch/sparc/kernel/traps.c	Sat Nov 25 02:58:49 1995
@@ -1,4 +1,4 @@
-/*
+/* $Id: traps.c,v 1.18 1995/11/25 00:58:47 davem Exp $
  * arch/sparc/kernel/traps.c
  *
  * Copyright 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -21,6 +21,35 @@
 #include <asm/kdebug.h>
 
 void
+syscall_trace_entry(struct pt_regs *regs)
+{
+	printk("%s[%d]: sys[%d](%d, %d, %d, %d) ",
+	       current->comm, current->pid,
+	       regs->u_regs[UREG_G1], regs->u_regs[UREG_I0],
+	       regs->u_regs[UREG_I1], regs->u_regs[UREG_I2],
+	       regs->u_regs[UREG_I3]);
+	return;
+}
+
+void
+syscall_trace_exit(struct pt_regs *regs)
+{
+	printk("retvals[%d,%d] at pc<%08lx>\n",
+	       regs->u_regs[UREG_I0], regs->u_regs[UREG_I1],
+	       regs->pc, regs->npc);
+	return;
+}
+
+void
+do_cwp_assertion_failure(struct pt_regs *regs, unsigned long psr)
+{
+	printk("CWP return from trap assertion fails:\n");
+	printk("Current psr %08lx, new psr %08lx\n", psr, regs->psr);
+	show_regs(regs);
+	panic("bogus CWP");
+}
+
+void
 do_hw_interrupt(unsigned long type, unsigned long psr, unsigned long pc)
 {
 
@@ -37,7 +66,11 @@
 {
 	printk("Illegal instruction at PC %08lx NPC %08lx PSR %08lx\n",
 	       pc, npc, psr);
-	halt();
+	if(psr & PSR_PS)
+		panic("Kernel illegal instruction, how are ya!");
+	current->tss.sig_address = pc;
+	current->tss.sig_desc = SUBSIG_ILLINST;
+	send_sig(SIGILL, current, 1);
 	return;
 }
 
@@ -47,17 +80,25 @@
 {
 	printk("Privileged instruction at PC %08lx NPC %08lx PSR %08lx\n",
 	       pc, npc, psr);
-	halt();
+	current->tss.sig_address = pc;
+	current->tss.sig_desc = SUBSIG_PRIVINST;
+	send_sig(SIGILL, current, 1);
 	return;
 }
 
+/* XXX User may want to be allowed to do this. XXX */
+
 void
 do_memaccess_unaligned(struct pt_regs *regs, unsigned long pc, unsigned long npc,
 		       unsigned long psr)
 {
 	printk("Unaligned memory access at PC %08lx NPC %08lx PSR %08lx\n",
 	       pc, npc, psr);
-	halt();
+	if(regs->psr & PSR_PS)
+		panic("Kernel does unaligned memory access, yuck!");
+	current->tss.sig_address = pc;
+	current->tss.sig_desc = SUBSIG_PRIVINST;
+	send_sig(SIGBUS, current, 1);
 	return;
 }
 
@@ -65,19 +106,123 @@
 do_fpd_trap(struct pt_regs *regs, unsigned long pc, unsigned long npc,
 		       unsigned long psr)
 {
-	printk("Floating Point Disabled trap at PC %08lx NPC %08lx PSR %08lx\n",
-	       pc, npc, psr);
-	halt();
-	return;
+	/* Sanity check... */
+	if(psr & PSR_PS)
+		panic("FPE disabled trap from kernel, die die die...");
+
+	put_psr(get_psr() | PSR_EF);    /* Allow FPU ops. */
+	if(last_task_used_math == current) {
+		/* No state save necessary */
+		regs->psr |= PSR_EF;
+		return;
+	}
+	if(last_task_used_math) {
+		/* Other processes fpu state, save away */
+		__asm__ __volatile__("st %%fsr, [%0]\n\t" : :
+				     "r" (&current->tss.fsr) : "memory");
+
+		/* Save away the floating point queue if necessary. */
+		if(current->tss.fsr & 0x2000)
+			__asm__ __volatile__("mov 0x0, %%g2\n\t"
+					     "1: std %%fq, [%2 + %%g2]\n\t"
+					     "st %%fsr, [%0]\n\t"
+					     "ld [%0], %%g3\n\t"
+					     "andcc %%g3, %1, %%g0\n\t"
+					     "bne 1b\n\t"
+					     "add %%g2, 0x8, %%g2\n\t"
+					     "srl %%g2, 0x3, %%g2\n\t"
+					     "st %%g2, [%3]\n\t" : :
+					     "r" (&current->tss.fsr), "r" (0x2000),
+					     "r" (&current->tss.fpqueue[0]),
+					     "r" (&current->tss.fpqdepth) :
+					     "g2", "g3", "memory");
+		else
+			current->tss.fpqdepth = 0;
+
+		__asm__ __volatile__("std %%f0, [%0 + 0x00]\n\t"
+				     "std %%f2, [%0 + 0x08]\n\t"
+				     "std %%f4, [%0 + 0x10]\n\t"
+				     "std %%f6, [%0 + 0x18]\n\t"
+				     "std %%f8, [%0 + 0x20]\n\t"
+				     "std %%f10, [%0 + 0x28]\n\t"
+				     "std %%f12, [%0 + 0x30]\n\t"
+				     "std %%f14, [%0 + 0x38]\n\t"
+				     "std %%f16, [%0 + 0x40]\n\t"
+				     "std %%f18, [%0 + 0x48]\n\t"
+				     "std %%f20, [%0 + 0x50]\n\t"
+				     "std %%f22, [%0 + 0x58]\n\t"
+				     "std %%f24, [%0 + 0x60]\n\t"
+				     "std %%f26, [%0 + 0x68]\n\t"
+				     "std %%f28, [%0 + 0x70]\n\t"
+				     "std %%f30, [%0 + 0x78]\n\t" : :
+				     "r" (&current->tss.float_regs[0]) :
+				     "memory");
+	}
+	last_task_used_math = current;
+	if(current->used_math) {
+		/* Restore the old state. */
+		__asm__ __volatile__("ldd [%0 + 0x00], %%f0\n\t"
+				     "ldd [%0 + 0x08], %%f2\n\t"
+				     "ldd [%0 + 0x10], %%f4\n\t"
+				     "ldd [%0 + 0x18], %%f6\n\t"
+				     "ldd [%0 + 0x20], %%f8\n\t"
+				     "ldd [%0 + 0x28], %%f10\n\t"
+				     "ldd [%0 + 0x30], %%f12\n\t"
+				     "ldd [%0 + 0x38], %%f14\n\t"
+				     "ldd [%0 + 0x40], %%f16\n\t"
+				     "ldd [%0 + 0x48], %%f18\n\t"
+				     "ldd [%0 + 0x50], %%f20\n\t"
+				     "ldd [%0 + 0x58], %%f22\n\t"
+				     "ldd [%0 + 0x60], %%f24\n\t"
+				     "ldd [%0 + 0x68], %%f26\n\t"
+				     "ldd [%0 + 0x70], %%f28\n\t"
+				     "ldd [%0 + 0x78], %%f30\n\t"
+				     "ld  [%1], %%fsr\n\t" : :
+				     "r" (&current->tss.float_regs[0]),
+				     "r" (&current->tss.fsr));
+	} else {
+		/* Set initial sane state. */
+		auto unsigned long init_fsr = 0x0UL;
+		auto unsigned long init_fregs[32] __attribute__ ((aligned (8))) =
+		{ ~0UL, ~0UL, ~0UL, ~0UL, ~0UL, ~0UL, ~0UL, ~0UL,
+		  ~0UL, ~0UL, ~0UL, ~0UL, ~0UL, ~0UL, ~0UL, ~0UL,
+		  ~0UL, ~0UL, ~0UL, ~0UL, ~0UL, ~0UL, ~0UL, ~0UL,
+		  ~0UL, ~0UL, ~0UL, ~0UL, ~0UL, ~0UL, ~0UL, ~0UL };
+		__asm__ __volatile__("ldd [%0 + 0x00], %%f0\n\t"
+				     "ldd [%0 + 0x08], %%f2\n\t"
+				     "ldd [%0 + 0x10], %%f4\n\t"
+				     "ldd [%0 + 0x18], %%f6\n\t"
+				     "ldd [%0 + 0x20], %%f8\n\t"
+				     "ldd [%0 + 0x28], %%f10\n\t"
+				     "ldd [%0 + 0x30], %%f12\n\t"
+				     "ldd [%0 + 0x38], %%f14\n\t"
+				     "ldd [%0 + 0x40], %%f16\n\t"
+				     "ldd [%0 + 0x48], %%f18\n\t"
+				     "ldd [%0 + 0x50], %%f20\n\t"
+				     "ldd [%0 + 0x58], %%f22\n\t"
+				     "ldd [%0 + 0x60], %%f24\n\t"
+				     "ldd [%0 + 0x68], %%f26\n\t"
+				     "ldd [%0 + 0x70], %%f28\n\t"
+				     "ldd [%0 + 0x78], %%f30\n\t"
+				     "ld  [%1], %%fsr\n\t" : :
+				     "r" (&init_fregs[0]),
+				     "r" (&init_fsr) : "memory");
+		current->used_math = 1;
+	}
 }
 
 void
 do_fpe_trap(struct pt_regs *regs, unsigned long pc, unsigned long npc,
 		       unsigned long psr)
 {
-	printk("Floating Point Exception at PC %08lx NPC %08lx PSR %08lx\n",
-	       pc, npc, psr);
-	halt();
+	if(psr & PSR_PS)
+		panic("FPE exception trap from kernel, die die die...");
+	/* XXX Do something real... XXX */
+	regs->psr &= ~PSR_EF;
+	last_task_used_math = (struct task_struct *) 0;
+	current->tss.sig_address = pc;
+	current->tss.sig_desc = SUBSIG_FPERROR; /* as good as any */
+	send_sig(SIGFPE, current, 1);
 	return;
 }
 
@@ -87,7 +232,11 @@
 {
 	printk("Tag overflow trap at PC %08lx NPC %08lx PSR %08lx\n",
 	       pc, npc, psr);
-	halt();
+	if(psr & PSR_PS)
+		panic("KERNEL tag overflow trap, wowza!");
+	current->tss.sig_address = pc;
+	current->tss.sig_desc = SUBSIG_TAG; /* as good as any */
+	send_sig(SIGEMT, current, 1);
 	return;
 }
 
@@ -97,7 +246,9 @@
 {
 	printk("Watchpoint detected at PC %08lx NPC %08lx PSR %08lx\n",
 	       pc, npc, psr);
-	halt();
+	if(psr & PSR_PS)
+		panic("Tell me what a watchpoint trap is, and I'll then deal "
+		      "with such a beast...");
 	return;
 }
 
@@ -112,16 +263,6 @@
 }
 
 void
-handle_iacc_error(struct pt_regs *regs, unsigned long pc, unsigned long npc,
-		       unsigned long psr)
-{
-	printk("Instruction Access Error at PC %08lx NPC %08lx PSR %08lx\n",
-	       pc, npc, psr);
-	halt();
-	return;
-}
-
-void
 handle_cp_disabled(struct pt_regs *regs, unsigned long pc, unsigned long npc,
 		       unsigned long psr)
 {
@@ -152,16 +293,6 @@
 }
 
 void
-handle_dacc_error(struct pt_regs *regs, unsigned long pc, unsigned long npc,
-		       unsigned long psr)
-{
-	printk("Data Access Error at PC %08lx NPC %08lx PSR %08lx\n",
-	       pc, npc, psr);
-	halt();
-	return;
-}
-
-void
 handle_hw_divzero(struct pt_regs *regs, unsigned long pc, unsigned long npc,
 		       unsigned long psr)
 {
@@ -171,33 +302,9 @@
 	return;
 }
 
-void
-handle_dstore_error(struct pt_regs *regs, unsigned long pc, unsigned long npc,
-		       unsigned long psr)
+void do_ast(struct pt_regs *regs)
 {
-	printk("Data Store Error at PC %08lx NPC %08lx PSR %08lx\n",
-	       pc, npc, psr);
-	halt();
-	return;
-}
-
-void
-handle_dacc_mmu_miss(struct pt_regs *regs, unsigned long pc, unsigned long npc,
-		       unsigned long psr)
-{
-	printk("Data Access MMU-Miss Exception at PC %08lx NPC %08lx PSR %08lx\n",
-	       pc, npc, psr);
-	halt();
-	return;
-}
-
-void
-handle_iacc_mmu_miss(struct pt_regs *regs, unsigned long pc, unsigned long npc,
-		       unsigned long psr)
-{
-	printk("Instruction Access MMU-Miss Exception at PC %08lx NPC %08lx PSR %08lx\n",
-	       pc, npc, psr);
-	halt();
+	panic("Don't know how to handle AST traps yet ;-(\n");
 	return;
 }
 
@@ -214,8 +321,6 @@
 unsigned int thiscpus_tbr;
 int thiscpus_mid;
 
-/* #define SMP_TESTING */
-
 void
 trap_init(void)
 {
@@ -227,12 +332,12 @@
 		return;
 	}
 	if(sparc_cpu_model != sun4m) {
-		printk("trap_init: Multiprocessor on a non-sun4m! Aieee...\n");
-		printk("trap_init: Cannot continue, bailing out.\n");
+		prom_printf("trap_init: Multiprocessor on a non-sun4m! Aieee...\n");
+		prom_printf("trap_init: Cannot continue, bailing out.\n");
 		prom_halt();
 	}
 	/* Ok, we are on a sun4m with multiple cpu's */
-	printk("trap_init: Multiprocessor detected, initiating CPU-startup. cpus=%d\n",
+	prom_printf("trap_init: Multiprocessor detected, initiating CPU-startup. cpus=%d\n",
 	       linux_num_cpus);
 	linux_smp_still_initting = 1;
 	ctx_reg.which_io = 0x0;  /* real ram */
@@ -250,23 +355,14 @@
 			thiscpus_mid = linux_cpus[i].mid;
 			thiscpus_tbr = (unsigned int)
 				percpu_table[cpuid].trap_table;
-#ifdef SMP_TESTING
-			printk("thiscpus_tbr = %08x\n", thiscpus_tbr);
-			printk("About to fire up cpu %d mid %d cpuid %d\n", i,
-			       linux_cpus[i].mid, cpuid);
-#endif
 			prom_startcpu(linux_cpus[i].prom_node, &ctx_reg, 0x0,
 				      (char *) sparc_cpu_startup);
-			printk("Waiting for cpu %d to start up...\n", i);
+			prom_printf("Waiting for cpu %d to start up...\n", i);
 			while(percpu_table[cpuid].cpu_is_alive == 0) {
 				static int counter = 0;
 				counter++;
-				if(counter>200) {
-#ifdef SMP_TESTING
-					printk("UGH, CPU would not start up ;-( \n");
-#endif
+				if(counter>200)
 					break;
-				}
 				__delay(200000);
 			}
 		}
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/kernel/wof.S linux/arch/sparc/kernel/wof.S
--- v1.3.43/linux/arch/sparc/kernel/wof.S	Thu Jan  1 02:00:00 1970
+++ linux/arch/sparc/kernel/wof.S	Sat Nov 25 02:58:51 1995
@@ -0,0 +1,420 @@
+/* $Id: wof.S,v 1.14 1995/11/25 00:58:49 davem Exp $
+ * wof.S: Sparc window overflow handler.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#include <asm/cprefix.h>
+#include <asm/contregs.h>
+#include <asm/page.h>
+#include <asm/ptrace.h>
+#include <asm/psr.h>
+#include <asm/asi.h>
+#include <asm/winmacro.h>
+
+/* WARNING: This routine is hairy and _very_ complicated, but it
+ *          must be as fast as possible as it handles the allocation
+ *          of register windows to the user and kernel.  If you touch
+ *          this code be _very_ careful as many other pieces of the
+ *          kernel depend upon how this code behaves.  You have been
+ *          duly warned...
+ */
+
+/* We define macro's for registers which have a fixed
+ * meaning throughout this entire routine.  The 'T' in
+ * the comments mean that the register can only be
+ * accessed when in the 'trap' window, 'G' means
+ * accessible in any window.  Do not change these registers
+ * after they have been set, until you are ready to return
+ * from the trap.
+ */
+#define t_psr       l0 /* %psr at trap time                     T */
+#define t_pc        l1 /* PC for trap return                    T */
+#define t_npc       l2 /* NPC for trap return                   T */
+#define t_wim       l3 /* %wim at trap time                     T */
+#define saved_g5    l5 /* Global save register                  T */
+#define saved_g6    l6 /* Global save register                  T */
+#define curptr      g6 /* Gets set to 'current' then stays      G */
+
+/* Now registers whose values can change within the handler.      */
+#define twin_tmp    l4 /* Temp reg, only usable in trap window  T */
+#define glob_tmp    g5 /* Global temporary reg, usable anywhere G */
+
+	.text
+	.align	4
+	/* BEGINNING OF PATCH INSTRUCTIONS */
+	/* On a 7-window Sparc the boot code patches spnwin_*
+	 * instructions with the following ones.
+	 */
+	.globl	spnwin_patch1_7win, spnwin_patch2_7win, spnwin_patch3_7win
+spnwin_patch1_7win:	sll	%t_wim, 6, %glob_tmp
+spnwin_patch2_7win:	and	%glob_tmp, 0x7f, %glob_tmp
+spnwin_patch3_7win:	and	%twin_tmp, 0x7f, %twin_tmp
+	/* END OF PATCH INSTRUCTIONS */
+
+	/* The trap entry point has done the following:
+	 *
+	 * rd    %psr, %l0
+	 * rd    %wim, %l3
+	 * b     spill_window_entry
+	 * andcc %l0, PSR_PS, %g0
+	 */
+
+	/* Datum current->tss.uwinmask contains at all times a bitmask
+	 * where if any user windows are active, at least one bit will
+	 * be set in to mask.  If no user windows are active, the bitmask
+	 * will be all zeroes.
+	 */
+	.globl	spill_window_entry 
+	.globl	spnwin_patch1, spnwin_patch2, spnwin_patch3
+spill_window_entry:
+	/* LOCATION: Trap Window */
+
+	mov	%g5, %saved_g5		! save away global temp register
+	mov	%g6, %saved_g6		! save away 'current' ptr register
+
+	/* Compute what the new %wim will be if we save the
+	 * window properly in this trap handler.
+	 *
+	 * newwim = ((%wim>>1) | (%wim<<(nwindows - 1)));
+	 */
+		srl	%t_wim, 0x1, %twin_tmp
+spnwin_patch1:	sll	%t_wim, 7, %glob_tmp
+		or	%glob_tmp, %twin_tmp, %glob_tmp
+spnwin_patch2:	and	%glob_tmp, 0xff, %glob_tmp
+
+	/* The trap entry point has set the condition codes
+	 * up for us to see if this is from user or kernel.
+	 * Get the load of 'curptr' out of the way.
+	 */
+	LOAD_CURRENT(curptr)
+
+	andcc	%t_psr, PSR_PS, %g0
+	be	spwin_fromuser				! all user wins, branch
+	 nop
+	
+	/* See if any user windows are active in the set. */
+	ld	[%curptr + THREAD_UMASK], %twin_tmp	! grab currents win mask
+	orcc	%g0, %twin_tmp, %g0			! check for set bits
+	bne	spwin_exist_uwins			! yep, there are some
+	 nop
+
+	/* Save into the window which must be saved and do it.
+	 * Basically if we are here, this means that we trapped
+	 * from kernel mode with only kernel windows in the register
+	 * file.
+	 */
+	save	%g0, %g0, %g0		! save into the window to stash away
+	wr	%glob_tmp, 0x0, %wim	! set new %wim, this is safe now
+	WRITE_PAUSE			! burn cpu cycles due to bad engineering
+
+spwin_no_userwins_from_kernel:
+	/* LOCATION: Window to be saved */
+
+	STORE_WINDOW(sp)		! stash the window
+	restore	%g0, %g0, %g0		! go back into trap window
+
+	/* LOCATION: Trap window */
+	mov	%saved_g5, %g5		! restore %glob_tmp
+	mov	%saved_g6, %g6		! restore %curptr
+	wr	%t_psr, 0x0, %psr	! restore condition codes in %psr
+	WRITE_PAUSE			! waste some time
+	jmp	%t_pc			! Return from trap
+	rett	%t_npc			! we are done
+
+spwin_exist_uwins:
+	/* LOCATION: Trap window */
+
+	/* Wow, user windows have to be dealt with, this is dirty
+	 * and messy as all hell.  And difficult to follow if you
+	 * are approaching the infamous register window trap handling
+	 * problem for the first time. DONT LOOK!
+	 *
+	 * Note that how the execution path works out, the new %wim
+	 * will be left for us in the global temporary register,
+	 * %glob_tmp.  We cannot set the new %wim first because we
+	 * need to save into the appropriate window without inducing
+	 * a trap (traps are off, we'd get a watchdog wheee)...
+	 * But first, store the new user window mask calculated
+	 * above.
+	 */
+	andn	%twin_tmp, %glob_tmp, %twin_tmp		! compute new umask
+	st	%twin_tmp, [%curptr + THREAD_UMASK]
+
+spwin_fromuser:
+	/* LOCATION: Trap window */
+	save	%g0, %g0, %g0		! Go to where the saving will occur
+
+	/* LOCATION: Window to be saved */
+	wr	%glob_tmp, 0x0, %wim	! Now it is safe to set new %wim
+	WRITE_PAUSE			! burn baby burn
+
+	/* LOCATION: Window to be saved */
+
+	/* This instruction branches to a routine which will check
+	 * to validity of the users stack pointer by whatever means
+	 * are necessary.  This means that this is architecture
+	 * specific and thus this branch instruction will need to
+	 * be patched at boot time once the machine type is known.
+	 * This routine _shall not_ touch %curptr under any
+	 * circumstances whatsoever!  It will branch back to the
+	 * label 'spwin_good_ustack' if the stack is ok but still
+	 * needs to be dumped (SRMMU for instance will not need to
+	 * do this) or 'spwin_finish_up' if the stack is ok and the
+	 * registers have already been saved.  If the stack is found
+	 * to be bogus for some reason the routine shall branch to
+	 * the label 'spwin_user_stack_is_bolixed' which will take
+	 * care of things at that point.
+	 */
+				.globl	C_LABEL(spwin_mmu_patchme)
+C_LABEL(spwin_mmu_patchme):	b	C_LABEL(spwin_sun4c_stackchk)
+				 andcc	%sp, 0x7, %g0
+
+spwin_good_ustack:
+	/* LOCATION: Window to be saved */
+
+	/* The users stack is ok and we can safely save it at
+	 * %sp.
+	 */
+	STORE_WINDOW(sp)
+
+spwin_finish_up:
+	restore	%g0, %g0, %g0		/* Back to trap window. */
+
+	/* LOCATION: Trap window */
+
+	/* We have spilled successfully, and we have properly stored
+	 * the appropriate window onto the stack.
+	 */
+
+	/* Restore saved globals */
+	mov	%saved_g5, %g5
+	mov	%saved_g6, %g6
+	wr	%t_psr, 0x0, %psr
+	WRITE_PAUSE
+	jmp	%t_pc
+	rett	%t_npc
+
+spwin_user_stack_is_bolixed:
+	/* LOCATION: Window to be saved */
+
+	/* Wheee, user has trashed his/her stack.  We have to decide
+	 * how to proceed based upon whether we came from kernel mode
+	 * or not.  If we came from kernel mode, toss the window into
+	 * a special buffer and proceed, the kernel _needs_ a window
+	 * and we could be in an interrupt handler so timing is crucial.
+	 * If we came from user land we build a full stack frame and call
+	 * c-code to gun down the process.
+	 */
+	rd	%psr, %glob_tmp
+	andcc	%glob_tmp, PSR_PS, %g0
+	bne	spwin_bad_ustack_from_kernel
+	 nop
+
+	/* Oh well, throw this one window into the per-task window
+	 * buffer, the first one.
+	 */
+	st	%sp, [%curptr + THREAD_STACK_PTRS]
+	STORE_WINDOW(curptr + THREAD_REG_WINDOW)
+	restore	%g0, %g0, %g0
+
+	/* LOCATION: Trap Window */
+
+	/* Back in the trap window, update winbuffer save count. */
+	mov	1, %glob_tmp
+	st	%glob_tmp, [%curptr + THREAD_W_SAVED]
+
+		/* Compute new user window mask.  What we are basically
+		 * doing is taking two windows, the invalid one at trap
+		 * time and the one we attempted to throw onto the users
+		 * stack, and saying that everything else is an ok user
+		 * window.  umask = ((~(%t_wim | %wim)) & valid_wim_bits)
+		 */
+		rd	%wim, %twin_tmp
+		or	%twin_tmp, %t_wim, %twin_tmp
+		not	%twin_tmp
+spnwin_patch3:	and	%twin_tmp, 0xff, %twin_tmp	! patched on 7win Sparcs
+		st	%twin_tmp, [%curptr + THREAD_UMASK]
+
+	/* Jump onto kernel stack for this process... */
+	ld	[%curptr + TASK_KSTACK_PG], %sp
+	add	%sp, (PAGE_SIZE - TRACEREG_SZ - STACKFRAME_SZ), %sp
+
+	/* Restore the saved globals and build a pt_regs frame. */
+	mov	%saved_g5, %g5
+	mov	%saved_g6, %g6
+	rd	%wim, %twin_tmp
+	STORE_PT_ALL(sp, t_psr, t_pc, t_npc, twin_tmp, g1)
+
+	/* Turn on traps and call c-code to deal with it. */
+	wr	%t_psr, PSR_ET, %psr
+	WRITE_PAUSE
+
+	mov	1, %o1
+	call	C_LABEL(do_sparc_winfault)
+	 add	%sp, STACKFRAME_SZ, %o0
+
+	/* Return from trap if C-code actually fixes things, if it
+	 * doesn't then we never get this far as the process will
+	 * be given the look of death from Commander Peanut.
+	 */
+	b	ret_trap_entry
+	 nop
+
+spwin_bad_ustack_from_kernel:
+	/* LOCATION: Window to be saved */
+
+	/* The kernel provoked a spill window trap, but the window we
+	 * need to save is a user one and the process has trashed its
+	 * stack pointer.  We need to be quick, so we throw it into
+	 * a per-process window buffer until we can properly handle
+	 * this later on.
+	 */
+	SAVE_BOLIXED_USER_STACK(curptr, glob_tmp)
+	restore	%g0, %g0, %g0
+
+	/* LOCATION: Trap window */
+
+	/* Restore globals, condition codes in the %psr and
+	 * return from trap.
+	 */
+	mov	%saved_g5, %g5
+	mov	%saved_g6, %g6
+
+	wr	%t_psr, 0x0, %psr
+	WRITE_PAUSE
+
+	jmp	%t_pc
+	rett	%t_npc
+
+/* Undefine the register macros which would only cause trouble
+ * if used below.  This helps find 'stupid' coding errors that
+ * produce 'odd' behavior.  The routines below are allowed to
+ * make usage of glob_tmp and t_psr so we leave them defined.
+ */
+#undef twin_tmp
+#undef curptr
+#undef t_pc
+#undef t_npc
+#undef t_wim
+#undef saved_g5
+#undef saved_g6
+
+/* Now come the per-architecture window overflow stack checking routines.
+ * As noted above %curptr cannot be touched by this routine at all.
+ */
+
+	.globl	C_LABEL(spwin_sun4c_stackchk)
+C_LABEL(spwin_sun4c_stackchk):
+	/* LOCATION: Window to be saved on the stack */
+
+	/* See if the stack is in the address space hole but first,
+	 * check results of callers andcc %sp, 0x7, %g0
+	 */
+	be	1f
+	 sra	%sp, 29, %glob_tmp
+
+	b	spwin_user_stack_is_bolixed
+	 nop
+
+1:
+	add	%glob_tmp, 0x1, %glob_tmp
+	andncc	%glob_tmp, 0x1, %g0
+	be	1f
+	 and	%sp, 0xfff, %glob_tmp		! delay slot
+
+	b	spwin_user_stack_is_bolixed
+	 nop
+
+	/* See if our dump area will be on more than one
+	 * page.
+	 */
+1:
+	add	%glob_tmp, 0x38, %glob_tmp
+	andncc	%glob_tmp, 0xff8, %g0
+	be	spwin_sun4c_onepage		! only one page to check
+	 lda	[%sp] ASI_PTE, %glob_tmp	! have to check first page anyways
+
+spwin_sun4c_twopages:
+	/* Is first page ok permission wise? */
+	srl	%glob_tmp, 29, %glob_tmp
+	cmp	%glob_tmp, 0x6
+	be	1f
+	 add	%sp, 0x38, %glob_tmp	/* Is second page in vma hole? */
+
+	b	spwin_user_stack_is_bolixed
+	 nop
+
+1:
+	sra	%glob_tmp, 29, %glob_tmp
+	add	%glob_tmp, 0x1, %glob_tmp
+	andncc	%glob_tmp, 0x1, %g0
+	be	1f
+	 add	%sp, 0x38, %glob_tmp
+
+	b	spwin_user_stack_is_bolixed
+	 nop
+
+1:
+	lda	[%glob_tmp] ASI_PTE, %glob_tmp
+
+spwin_sun4c_onepage:
+	srl	%glob_tmp, 29, %glob_tmp
+	cmp	%glob_tmp, 0x6				! can user write to it?
+	be	spwin_good_ustack			! success
+	 nop
+
+	b	spwin_user_stack_is_bolixed
+	 nop
+
+	/* This is a generic SRMMU routine.  As far as I know this
+	 * works for all current v8/srmmu implementations, we'll
+	 * see...
+	 */
+	.globl	C_LABEL(spwin_srmmu_stackchk)
+C_LABEL(spwin_srmmu_stackchk):
+	/* LOCATION: Window to be saved on the stack */
+
+	/* Because of SMP concerns and speed we play a trick.
+	 * We disable fault traps in the MMU control register,
+	 * Execute the stores, then check the fault registers
+	 * to see what happens.  I can hear Linus now
+	 * "disgusting... broken hardware...".
+	 *
+	 * But first, check to see if the users stack has ended
+	 * up in kernel vma, then we would succeed for the 'wrong'
+	 * reason... ;(  Note that the 'sethi' below assumes the
+	 * kernel is page aligned, which should always be the case.
+	 */
+	/* Check results of callers andcc %sp, 0x7, %g0 */
+	bne	spwin_user_stack_is_bolixed
+	sethi	%hi(KERNBASE), %glob_tmp
+	cmp	%glob_tmp, %sp
+	bleu	spwin_user_stack_is_bolixed
+	 mov	AC_M_SFSR, %glob_tmp
+
+	/* Clear the fault status and turn on the no_fault bit. */
+	lda	[%glob_tmp] ASI_M_MMUREGS, %g0		! eat SFSR
+
+	lda	[%g0] ASI_M_MMUREGS, %glob_tmp		! read MMU control
+	or	%glob_tmp, 0x2, %glob_tmp		! or in no_fault bit
+	sta	%glob_tmp, [%g0] ASI_M_MMUREGS		! set it
+
+	/* Dump the registers and cross fingers. */
+	STORE_WINDOW(sp)
+
+	/* Clear the no_fault bit and check the status. */
+	andn	%glob_tmp, 0x2, %glob_tmp
+	sta	%glob_tmp, [%g0] ASI_M_MMUREGS
+
+	mov	AC_M_SFAR, %glob_tmp
+	lda	[%glob_tmp] ASI_M_MMUREGS, %g0
+
+	mov	AC_M_SFSR, %glob_tmp
+	lda	[%glob_tmp] ASI_M_MMUREGS, %glob_tmp
+	andcc	%glob_tmp, 0x2, %g0			! did we fault?
+	be	spwin_finish_up				! cool beans, success
+	 nop
+
+	b	spwin_user_stack_is_bolixed		! we faulted, ugh
+	 nop
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/kernel/wuf.S linux/arch/sparc/kernel/wuf.S
--- v1.3.43/linux/arch/sparc/kernel/wuf.S	Thu Jan  1 02:00:00 1970
+++ linux/arch/sparc/kernel/wuf.S	Sat Nov 25 02:58:53 1995
@@ -0,0 +1,351 @@
+/* $Id: wuf.S,v 1.13 1995/11/25 00:58:51 davem Exp $
+ * wuf.S: Window underflow trap handler for the Sparc.
+ *
+ * Copyright (C) 1995 David S. Miller
+ */
+
+#include <asm/cprefix.h>
+#include <asm/contregs.h>
+#include <asm/page.h>
+#include <asm/ptrace.h>
+#include <asm/psr.h>
+#include <asm/asi.h>
+#include <asm/winmacro.h>
+
+/* Just like the overflow handler we define macros for registers
+ * with fixed meanings in this routine.
+ */
+#define t_psr       l0
+#define t_pc        l1
+#define t_npc       l2
+#define t_wim       l3
+/* Don`t touch the above registers or else you die horribly... */
+
+/* Now macros for the available scratch registers in this routine. */
+#define twin_tmp1    l4
+#define twin_tmp2    l5
+
+	.text
+	.align	4
+
+	/* The trap entry point has executed the following:
+	 *
+	 * rd    %psr, %l0
+	 * rd    %wim, %l3
+	 * b     fill_window_entry
+	 * andcc %l0, PSR_PS, %g0
+	 */
+
+	/* Datum current->tss.uwinmask contains at all times a bitmask
+	 * where if any user windows are active, at least one bit will
+	 * be set in to mask.  If no user windows are active, the bitmask
+	 * will be all zeroes.
+	 */
+
+	/* To get an idea of what has just happened to cause this
+	 * trap take a look at this diagram:
+	 *
+	 *      1  2  3  4     <--  Window number
+	 *      ----------
+	 *      T  O  W  I     <--  Symbolic name
+	 *
+	 *      O == the window that execution was in when
+	 *           the restore was attempted
+	 *
+	 *      T == the trap itself has save'd us into this
+	 *           window
+	 *
+	 *      W == this window is the one which is now invalid
+	 *           and must be made valid plus loaded from the
+	 *           stack
+	 *
+	 *      I == this window will be the invalid one when we
+	 *           are done and return from trap if successful
+	 */
+
+	/* BEGINNING OF PATCH INSTRUCTIONS */
+
+	/* On 7-window Sparc the boot code patches fnwin_patch1
+	 * with the following instruction.
+	 */
+	.globl	fnwin_patch1_7win, fnwin_patch2_7win
+fnwin_patch1_7win:	srl	%t_wim, 6, %twin_tmp2
+fnwin_patch2_7win:	and	%twin_tmp1, 0x7f, %twin_tmp1
+	/* END OF PATCH INSTRUCTIONS */
+
+	.globl	fill_window_entry, fnwin_patch1, fnwin_patch2
+fill_window_entry:
+	/* LOCATION: Window 'T' */
+
+	/* Compute what the new %wim is going to be if we retrieve
+	 * the proper window off of the stack.
+	 */
+		sll	%t_wim, 1, %twin_tmp1
+fnwin_patch1:	srl	%t_wim, 7, %twin_tmp2
+		or	%twin_tmp1, %twin_tmp2, %twin_tmp1
+fnwin_patch2:	and	%twin_tmp1, 0xff, %twin_tmp1
+
+	wr	%twin_tmp1, 0x0, %wim	/* Make window 'I' invalid */
+	WRITE_PAUSE
+
+	andcc	%t_psr, PSR_PS, %g0
+	be	fwin_from_user
+	 restore	%g0, %g0, %g0		/* Restore to window 'O' */
+
+	/* Trapped from kernel, we trust that the kernel does not
+	 * 'over restore' sorta speak and just grab the window
+	 * from the stack and return.  Easy enough.
+	 */
+fwin_from_kernel:
+	/* LOCATION: Window 'O' */
+
+	restore %g0, %g0, %g0
+
+	/* LOCATION: Window 'W' */
+
+	LOAD_WINDOW(sp)	                /* Load it up */
+
+	/* Spin the wheel... */
+	save	%g0, %g0, %g0
+	save	%g0, %g0, %g0
+	/* I'd like to buy a vowel please... */
+
+	/* LOCATION: Window 'T' */
+
+	/* Now preserve the condition codes in %psr, pause, and
+	 * return from trap.  This is the simplest case of all.
+	 */
+	wr	%t_psr, 0x0, %psr
+	WRITE_PAUSE
+
+	jmp	%t_pc
+	rett	%t_npc
+
+fwin_from_user:
+	/* LOCATION: Window 'O' */
+
+	restore	%g0, %g0, %g0		/* Restore to window 'W' */
+
+	/* LOCATION: Window 'W' */
+
+	/* Branch to the architecture specific stack validation
+	 * routine.  They can be found below...
+	 */
+				.globl	C_LABEL(fwin_mmu_patchme)
+C_LABEL(fwin_mmu_patchme):	b	C_LABEL(sun4c_fwin_stackchk)
+				andcc	%sp, 0x7, %g0
+
+fwin_user_stack_is_bolixed:
+	/* LOCATION: Window 'W' */
+
+	/* Place a pt_regs frame on the kernel stack, save back
+	 * to the trap window and call c-code to deal with this.
+	 */
+	LOAD_CURRENT(l4)
+	ld	[%l4 + TASK_KSTACK_PG], %l5
+	add	%l5, (PAGE_SIZE - TRACEREG_SZ - STACKFRAME_SZ), %l5
+
+	/* Store globals into pt_regs frame. */
+	STORE_PT_GLOBALS(l5)
+	STORE_PT_YREG(l5, g3)
+
+	/* Save kernel %sp in global while we change windows */
+	mov	%l5, %g2
+
+	save	%g0, %g0, %g0
+
+	/* LOCATION: Window 'O' */
+
+	rd	%psr, %g3		/* Read %psr in live user window */
+
+	save	%g0, %g0, %g0
+
+	/* LOCATION: Window 'T' */
+
+	mov	%g2, %sp		/* Jump onto kernel %sp being held */
+
+	/* Build rest of pt_regs. */
+	STORE_PT_INS(sp)
+	STORE_PT_PRIV(sp, t_psr, t_pc, t_npc, t_wim)
+
+	/* re-set trap time %wim value */
+	wr	%t_wim, 0x0, %wim
+
+	/* Fix users window mask and buffer save count. */
+	mov	0x1, %g5
+	sll	%g5, %g3, %g5
+	LOAD_CURRENT(twin_tmp1)
+	st	%g5, [%twin_tmp1 + THREAD_UMASK]	! one live user window still
+	st	%g0, [%twin_tmp1 + THREAD_W_SAVED]	! no windows in the buffer
+
+	wr	%t_psr, 0x0, %psr
+	wr	%t_psr, PSR_ET, %psr			! enable traps
+	WRITE_PAUSE
+
+	mov	2, %o1
+	call	C_LABEL(do_sparc_winfault)		! call c-code
+	 add	%sp, STACKFRAME_SZ, %o0			! pt_regs ptr is arg0
+
+	/* Return from trap if C-code actually fixes things, if it
+	 * doesn't then we never get this far as the process will
+	 * be given the look of death from Commander Peanut.
+	 */
+	b	ret_trap_entry
+	 nop
+
+fwin_user_stack_is_ok:
+	/* LOCATION: Window 'W' */
+
+	/* The users stack area is kosher and mapped, load the
+	 * window and fall through to the finish up routine.
+	 */
+	LOAD_WINDOW(sp)
+
+	/* Round and round she goes... */
+	save	%g0, %g0, %g0		/* Save to window 'O' */
+	save	%g0, %g0, %g0		/* Save to window 'T' */
+	/* Where she'll trap nobody knows... */
+
+	/* LOCATION: Window 'T' */
+
+fwin_user_finish_up:
+	/* LOCATION: Window 'T' */
+
+	wr	%t_psr, 0x0, %psr
+	WRITE_PAUSE	
+
+	jmp	%t_pc
+	rett	%t_npc
+
+	/* Here come the architecture specific checks for stack.
+	 * mappings.  Note that unlike the window overflow handler
+	 * we only need to check whether the user can read from
+	 * the appropriate addresses.  Also note that we are in
+	 * an invalid window which will be loaded, and this means
+	 * that until we actually load the window up we are free
+	 * to use any of the local registers contained within.
+	 *
+	 * On success these routine branch to fwin_user_stack_is_ok
+	 * if the area at %sp is user readable and the window still
+	 * needs to be loaded, else fwin_user_finish_up if the
+	 * routine has done the loading itself.  On failure (bogus
+	 * user stack) the routine shall branch to the label called
+	 * fwin_user_stack_is_bolixed.
+	 *
+	 * Contrary to the arch-specific window overflow stack
+	 * check routines in wof.S, these routines are free to use
+	 * any of the local registers they want to as this window
+	 * does not belong to anyone at this point, however the
+	 * outs and ins are still verbotten as they are part of
+	 * 'someone elses' window possibly.
+	 */
+
+	.align	4
+	.globl	C_LABEL(sun4c_fwin_stackchk)
+C_LABEL(sun4c_fwin_stackchk):
+	/* LOCATION: Window 'W' */
+
+	/* Caller did 'andcc %sp, 0x7, %g0' */
+	be	1f
+	 and	%sp, 0xfff, %l0		! delay slot
+
+	b	fwin_user_stack_is_bolixed
+	 nop
+
+	/* See if we have to check the sanity of one page or two */
+1:
+	add	%l0, 0x38, %l0
+	sra	%sp, 29, %l5
+	add	%l5, 0x1, %l5
+	andncc	%l5, 0x1, %g0
+	be	1f
+	 andncc	%l0, 0xff8, %g0
+
+	b	fwin_user_stack_is_bolixed	/* %sp is in vma hole, yuck */
+	 nop
+
+1:
+	be	sun4c_fwin_onepage	/* Only one page to check */
+	 lda	[%sp] ASI_PTE, %l1
+sun4c_fwin_twopages:
+	add	%sp, 0x38, %l0
+	sra	%l0, 29, %l5
+	add	%l5, 0x1, %l5
+	andncc	%l5, 0x1, %g0
+	be	1f
+	 lda	[%l0] ASI_PTE, %l1
+
+	b	fwin_user_stack_is_bolixed	/* Second page in vma hole */
+	 nop
+
+1:
+	srl	%l1, 29, %l1
+	andcc	%l1, 0x4, %g0
+	bne	sun4c_fwin_onepage
+	 lda	[%sp] ASI_PTE, %l1	
+
+	b	fwin_user_stack_is_bolixed	/* Second page has bad perms */
+	 nop
+
+sun4c_fwin_onepage:
+	srl	%l1, 29, %l1
+	andcc	%l1, 0x4, %g0
+	bne	fwin_user_stack_is_ok
+	 nop
+
+	/* A page had bad page permissions, losing... */
+	b	fwin_user_stack_is_bolixed
+	 nop
+
+	.globl	C_LABEL(srmmu_fwin_stackchk)
+C_LABEL(srmmu_fwin_stackchk):
+	/* LOCATION: Window 'W' */
+
+	/* Caller did 'andcc %sp, 0x7, %g0' */
+	bne	fwin_user_stack_is_bolixed
+	 nop
+
+	/* Check if the users stack is in kernel vma, then our
+	 * trial and error technique below would succeed for
+	 * the 'wrong' reason.
+	 */
+	sethi	%hi(KERNBASE), %l5		! delay slot for above
+	mov	AC_M_SFSR, %l4
+	cmp	%l5, %sp
+	bleu	fwin_user_stack_is_bolixed
+	 lda	[%l4] ASI_M_MMUREGS, %g0	! clear fault status
+
+	/* The technique is, turn off faults on this processor,
+	 * just let the load rip, then check the sfsr to see if
+	 * a fault did occur.  Then we turn on fault traps again
+	 * and branch conditionally based upon what happened.
+	 */
+	lda	[%g0] ASI_M_MMUREGS, %l5	! read mmu-ctrl reg
+	or	%l5, 0x2, %l5			! turn on no-fault bit
+	sta	%l5, [%g0] ASI_M_MMUREGS	! store it
+
+	/* Cross fingers and go for it. */
+	LOAD_WINDOW(sp)
+
+	/* A penny 'saved'... */
+	save	%g0, %g0, %g0
+	save	%g0, %g0, %g0
+	/* Is a BADTRAP earned... */
+
+	/* LOCATION: Window 'T' */
+
+	lda	[%g0] ASI_M_MMUREGS, %twin_tmp1	! load mmu-ctrl again
+	andn	%twin_tmp1, 0x2, %twin_tmp1	! clear no-fault bit
+	sta	%twin_tmp1, [%g0] ASI_M_MMUREGS	! store it
+
+	mov	AC_M_SFAR, %twin_tmp2
+	lda	[%twin_tmp2] ASI_M_MMUREGS, %g0	! read fault address
+
+	mov	AC_M_SFSR, %twin_tmp2
+	lda	[%twin_tmp2] ASI_M_MMUREGS, %twin_tmp2	! read fault status
+	andcc	%twin_tmp2, 0x2, %g0			! did fault occur?
+	be	fwin_user_finish_up
+	 nop
+
+	b	fwin_user_stack_is_bolixed	! oh well
+	 nop
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/lib/Makefile linux/arch/sparc/lib/Makefile
--- v1.3.43/linux/arch/sparc/lib/Makefile	Tue Aug 15 20:39:00 1995
+++ linux/arch/sparc/lib/Makefile	Sat Nov 25 02:58:59 1995
@@ -1,4 +1,4 @@
-#
+# $Id: Makefile,v 1.5 1995/11/25 00:58:56 davem Exp $
 # Makefile for Sparc library files..
 #
 
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/lib/ashrdi3.S linux/arch/sparc/lib/ashrdi3.S
--- v1.3.43/linux/arch/sparc/lib/ashrdi3.S	Sun Jan 22 23:02:41 1995
+++ linux/arch/sparc/lib/ashrdi3.S	Sat Nov 25 02:59:00 1995
@@ -1,4 +1,5 @@
-/* ashrdi3.S:	The filesystem code creates all kinds of references to
+/* $Id: ashrdi3.S,v 1.2 1995/11/25 00:58:59 davem Exp $
+ * ashrdi3.S:	The filesystem code creates all kinds of references to
  *              this little routine on the sparc with gcc.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/lib/mul.S linux/arch/sparc/lib/mul.S
--- v1.3.43/linux/arch/sparc/lib/mul.S	Sun Jan 22 23:02:41 1995
+++ linux/arch/sparc/lib/mul.S	Sat Nov 25 02:59:02 1995
@@ -1,4 +1,5 @@
-/* mul.S:       This routine was taken from glibc-1.09 and is covered
+/* $Id: mul.S,v 1.2 1995/11/25 00:59:00 davem Exp $
+ * mul.S:       This routine was taken from glibc-1.09 and is covered
  *              by the GNU Library General Public License Version 2.
  */
 
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/lib/rem.S linux/arch/sparc/lib/rem.S
--- v1.3.43/linux/arch/sparc/lib/rem.S	Sun Jan 22 23:02:41 1995
+++ linux/arch/sparc/lib/rem.S	Sat Nov 25 02:59:04 1995
@@ -1,4 +1,5 @@
-/* rem.S:       This routine was taken from glibc-1.09 and is covered
+/* $Id: rem.S,v 1.2 1995/11/25 00:59:02 davem Exp $
+ * rem.S:       This routine was taken from glibc-1.09 and is covered
  *              by the GNU Library General Public License Version 2.
  */
 
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/lib/sdiv.S linux/arch/sparc/lib/sdiv.S
--- v1.3.43/linux/arch/sparc/lib/sdiv.S	Sun Jan 22 23:02:41 1995
+++ linux/arch/sparc/lib/sdiv.S	Sat Nov 25 02:59:06 1995
@@ -1,4 +1,5 @@
-/* sdiv.S:      This routine was taken from glibc-1.09 and is covered
+/* $Id: sdiv.S,v 1.2 1995/11/25 00:59:04 davem Exp $
+ * sdiv.S:      This routine was taken from glibc-1.09 and is covered
  *              by the GNU Library General Public License Version 2.
  */
 
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/lib/udiv.S linux/arch/sparc/lib/udiv.S
--- v1.3.43/linux/arch/sparc/lib/udiv.S	Sun Jan 22 23:02:41 1995
+++ linux/arch/sparc/lib/udiv.S	Sat Nov 25 02:59:08 1995
@@ -1,4 +1,5 @@
-/* udiv.S:      This routine was taken from glibc-1.09 and is covered
+/* $Id: udiv.S,v 1.2 1995/11/25 00:59:06 davem Exp $
+ * udiv.S:      This routine was taken from glibc-1.09 and is covered
  *              by the GNU Library General Public License Version 2.
  */
 
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/lib/umul.S linux/arch/sparc/lib/umul.S
--- v1.3.43/linux/arch/sparc/lib/umul.S	Sun Jan 22 23:02:41 1995
+++ linux/arch/sparc/lib/umul.S	Sat Nov 25 02:59:11 1995
@@ -1,4 +1,5 @@
-/* umul.S:      This routine was taken from glibc-1.09 and is covered
+/* $Id: umul.S,v 1.2 1995/11/25 00:59:08 davem Exp $
+ * umul.S:      This routine was taken from glibc-1.09 and is covered
  *              by the GNU Library General Public License Version 2.
  */
 
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/lib/urem.S linux/arch/sparc/lib/urem.S
--- v1.3.43/linux/arch/sparc/lib/urem.S	Sun Jan 22 23:02:41 1995
+++ linux/arch/sparc/lib/urem.S	Sat Nov 25 02:59:13 1995
@@ -1,4 +1,5 @@
-/* urem.S:      This routine was taken from glibc-1.09 and is covered
+/* $Id: urem.S,v 1.2 1995/11/25 00:59:11 davem Exp $
+ * urem.S:      This routine was taken from glibc-1.09 and is covered
  *              by the GNU Library General Public License Version 2.
  */
 
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/mm/Makefile linux/arch/sparc/mm/Makefile
--- v1.3.43/linux/arch/sparc/mm/Makefile	Tue Aug 15 20:39:00 1995
+++ linux/arch/sparc/mm/Makefile	Sat Nov 25 02:59:19 1995
@@ -1,4 +1,4 @@
-#
+# $Id: Makefile,v 1.14 1995/11/25 00:59:17 davem Exp $
 # Makefile for the linux Sparc-specific parts of the memory manager.
 #
 # Note! Dependencies are done automagically by 'make dep', which also
@@ -7,7 +7,21 @@
 #
 # Note 2! The CFLAGS definition is now in the main makefile...
 
+# Also note that s4ctlb.o _must_ be the last object file
+
+#.S.s:
+#	$(CPP) -D__ASSEMBLY__ -ansi $< -o $*.s
+.S.o:
+	$(CC) -D__ASSEMBLY__ -ansi -c $< -o $*.o
+
+all: mm.o
 O_TARGET := mm.o
-O_OBJS   := fault.o vac-flush.o init.o sun4c.o srmmu.o loadmmu.o
+O_OBJS   := fault.o sun4c_vac.o init.o sun4c.o srmmu.o loadmmu.o mbus.o \
+            s4cflush.o
+
+#s4cflush.o: s4cflush.s
+
+s4cflush.o: s4cflush.S
+	$(CC) -D__ASSEMBLY__ -ansi -c $*.S -o $*.o
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/mm/fault.c linux/arch/sparc/mm/fault.c
--- v1.3.43/linux/arch/sparc/mm/fault.c	Tue Jun 27 14:11:32 1995
+++ linux/arch/sparc/mm/fault.c	Sat Nov 25 02:59:22 1995
@@ -1,4 +1,5 @@
-/* fault.c:  Page fault handlers for the Sparc.
+/* $Id: fault.c,v 1.42 1995/11/25 00:59:20 davem Exp $
+ * fault.c:  Page fault handlers for the Sparc.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  */
@@ -19,6 +20,7 @@
 #include <asm/memreg.h>
 #include <asm/openprom.h>
 #include <asm/oplib.h>
+#include <asm/traps.h>
 #include <asm/kdebug.h>
 
 #define ELEMENTS(arr) (sizeof (arr)/sizeof (arr[0]))
@@ -57,40 +59,40 @@
 /* Nice, simple, prom library does all the sweating for us. ;) */
 int prom_probe_memory (void)
 {
-  register struct linux_mlist_v0 *mlist;
-  register unsigned long bytes, base_paddr, tally;
-  register int i;
-
-  i = 0;
-  mlist= *prom_meminfo()->v0_available;
-  bytes = tally = mlist->num_bytes;
-  base_paddr = (unsigned long) mlist->start_adr;
+	register struct linux_mlist_v0 *mlist;
+	register unsigned long bytes, base_paddr, tally;
+	register int i;
+
+	i = 0;
+	mlist= *prom_meminfo()->v0_available;
+	bytes = tally = mlist->num_bytes;
+	base_paddr = (unsigned long) mlist->start_adr;
   
-  sp_banks[0].base_addr = base_paddr;
-  sp_banks[0].num_bytes = bytes;
+	sp_banks[0].base_addr = base_paddr;
+	sp_banks[0].num_bytes = bytes;
 
-  while (mlist->theres_more != (void *) 0){
-    i++;
-    mlist = mlist->theres_more;
-    bytes = mlist->num_bytes;
-    tally += bytes;
-    if (i >= SPARC_PHYS_BANKS-1) {
-      printk ("The machine has more banks that this kernel can support\n"
-	      "Increase the SPARC_PHYS_BANKS setting (currently %d)\n",
-	      SPARC_PHYS_BANKS);
-      i = SPARC_PHYS_BANKS-1;
-      break;
-    }
+	while (mlist->theres_more != (void *) 0){
+		i++;
+		mlist = mlist->theres_more;
+		bytes = mlist->num_bytes;
+		tally += bytes;
+		if (i >= SPARC_PHYS_BANKS-1) {
+			printk ("The machine has more banks that this kernel can support\n"
+				"Increase the SPARC_PHYS_BANKS setting (currently %d)\n",
+				SPARC_PHYS_BANKS);
+			i = SPARC_PHYS_BANKS-1;
+			break;
+		}
     
-    sp_banks[i].base_addr = (unsigned long) mlist->start_adr;
-    sp_banks[i].num_bytes = mlist->num_bytes;
-  }
-
-  i++;
-  sp_banks[i].base_addr = 0xdeadbeef;
-  sp_banks[i].num_bytes = 0;
+		sp_banks[i].base_addr = (unsigned long) mlist->start_adr;
+		sp_banks[i].num_bytes = mlist->num_bytes;
+	}
+
+	i++;
+	sp_banks[i].base_addr = 0xdeadbeef;
+	sp_banks[i].num_bytes = 0;
 
-  return tally;
+	return tally;
 }
 
 /* Traverse the memory lists in the prom to see how much physical we
@@ -107,450 +109,195 @@
 	return total;
 }
 
-asmlinkage void sparc_txtmem_error(int type, unsigned long sync_err_reg,
-				   unsigned long sync_vaddr,
-				   unsigned long async_err_reg,
-				   unsigned long async_vaddr)
+/* Whee, a level 15 NMI interrupt memory error.  Let's have fun... */
+asmlinkage void sparc_lvl15_nmi(struct pt_regs *regs, unsigned long serr,
+				unsigned long svaddr, unsigned long aerr,
+				unsigned long avaddr)
 {
-  printk("Aieee, sparc text page access error, halting\n");
-  printk("type = %d  sync_err_reg = 0x%x  sync_vaddr = 0x%x\n",
-	 type, (unsigned int) sync_err_reg, (unsigned int) sync_vaddr);
-  printk("async_err_reg = 0x%x  async_vaddr = 0x%x\n",
-	 (unsigned int) async_err_reg, (unsigned int) async_vaddr);
-  halt();
-}
-
-/* #define DEBUG_SPARC_TEXT_ACCESS_FAULT */
-
-asmlinkage void sparc_text_access_fault(int type, unsigned long sync_err_reg,
-					unsigned long sync_vaddr,
-					unsigned long pc, unsigned long psr,
-					struct pt_regs *regs)
-{
-  struct vm_area_struct *vma;
-  unsigned long address;
-
-  address = sync_vaddr;
-#ifdef DEBUG_SPARC_TEXT_ACCESS_FAULT
-  printk("Text FAULT: address = %08lx  code = %08lx\n",
-	 (unsigned long) address, (unsigned long) sync_err_reg);
-  printk("PC = %08lx\n", (unsigned long) regs->pc);
-  SP_ENTER_DEBUGGER;
-  halt();
-#endif
-  vma = find_vma(current, address);
-  if(!vma) {
-    goto bad_area;
-  }
-  if(vma->vm_start <= address)
-    goto good_area;
-  goto bad_area;
-
-/*
- * Ok, we have a good vm_area for this memory access, so
- * we can handle it..
- */
-good_area:
-  handle_mm_fault(vma, address, 0);
-  return;
-
-/*
- * Something tried to access memory that isn't in our memory map..
- * Fix it, but check if it's kernel or user first..
- */
-bad_area:
-  if((unsigned long) address < PAGE_SIZE) {
-    printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
-  } else
-    printk(KERN_ALERT "Unable to handle kernel paging request");
-  printk(" at virtual address %08lx\n",address);
-  printk(KERN_ALERT "current->tss.pgd_ptr = %08lx\n",
-	 (unsigned long) current->tss.pgd_ptr);
-  halt();
-}
-
-asmlinkage void sparc_datamem_error(int type, unsigned long sync_err_reg,
-				    unsigned long sync_vaddr,
-				    unsigned long async_err_reg,
-				    unsigned long async_vaddr)
-{
-  printk("Aieee, sparc data page access error, halting\n");
-  printk("type = %d  sync_err_reg = 0x%x  sync_vaddr = 0x%x\n",
-	 type, (unsigned int) sync_err_reg, (unsigned int) sync_vaddr);
-  printk("async_err_reg = 0x%x  async_vaddr = 0x%x\n",
-	 (unsigned int) async_err_reg, (unsigned int) async_vaddr);
-  printk("SYNC PAGE has MMU entry %08lx\n",
-	 (unsigned long) get_pte(sync_vaddr));
-  halt();
-}
-
-/* #define DEBUG_SPARC_DATA_ACCESS_FAULT */
-
-asmlinkage void sparc_data_access_fault(int type, unsigned long sync_err_reg,
-					unsigned long sync_vaddr,
-					unsigned long pc, unsigned long psr,
-					struct pt_regs *regs)
-{
-  struct vm_area_struct *vma;
-  unsigned long address;
-  int error_code;
-
-  address = sync_vaddr;
-#ifdef DEBUG_SPARC_DATA_ACCESS_FAULT 
-  printk("Data FAULT: address = %08lx  code = %08lx\n",
-	 (unsigned long) address, (unsigned long) sync_err_reg);
-  printk("PC = %08lx\n", (unsigned long) regs->pc);
-  printk("PTE = %08lx\n", (unsigned long) get_pte(address));
-#endif
-  vma = find_vma(current, address);
-  if(!vma) {
-#ifdef DEBUG_SPARC_DATA_ACCESS_FAULT 
-    printk("NULL VMA\n");
-#endif
-    goto bad_area;
-  }
-  if(vma->vm_start <= address)
-    goto good_area;
-
-  if(!(vma->vm_flags & VM_GROWSDOWN)) {
-    goto bad_area;
-  }
-  if(vma->vm_end - address > current->rlim[RLIMIT_STACK].rlim_cur) {
-    goto bad_area;
-  }
-
-  vma->vm_offset -= vma->vm_start - (address & PAGE_MASK);
-  vma->vm_start = (address & PAGE_MASK);
-
-/*
- * Ok, we have a good vm_area for this memory access, so
- * we can handle it..
- */
-good_area:
-#ifdef DEBUG_SPARC_DATA_ACCESS_FAULT 
-  printk("Found good_area\n");
-#endif
-  if((sync_err_reg & SUN4C_SYNC_BADWRITE) &&
-     (sync_err_reg & SUN4C_SYNC_NPRESENT)) {
-    if(!(vma->vm_flags & VM_WRITE)) {
-#ifdef DEBUG_SPARC_DATA_ACCESS_FAULT 
-      printk("oops, vma not writable\n");
-#endif
-      goto bad_area;
-    }
-  } else {
-    if(sync_err_reg & SUN4C_SYNC_PROT) {
-#ifdef DEBUG_SPARC_DATA_ACCESS_FAULT 
-      printk("PROT violation\n");
-#endif
-      goto bad_area;
-    }
-    if(!(vma->vm_flags & (VM_READ | VM_EXEC))) {
-#ifdef DEBUG_SPARC_DATA_ACCESS_FAULT 
-      printk("vma not readable nor executable\n");
-#endif
-      goto bad_area;
-    }
-  }
-
-  if(sync_err_reg & SUN4C_SYNC_BADWRITE)
-    error_code = 0x2;
-  else
-    error_code = 0x0;
-
-#ifdef DEBUG_SPARC_DATA_ACCESS_FAULT 
-  printk("calling handle_mm_fault vma=%08lx addr=%08lx code=%d\n",
-	 (unsigned long) vma, (unsigned long) address,
-	 (int) error_code);
-#endif
-  handle_mm_fault(vma, address, error_code);
-  return;
-
-/*
- * Something tried to access memory that isn't in our memory map..
- * Fix it, but check if it's kernel or user first..
- */
-bad_area:
-  if (wp_works_ok < 0 && address == 0x0) {
-	  wp_works_ok = 1;
-	  pg0[0] = pte_val(mk_pte(PAGE_OFFSET, PAGE_SHARED));
-	  put_pte((unsigned long) 0x0, pg0[0]);
-	  printk("This Sparc honours the WP bit even when in supervisor mode. Good.\n");
-	  return;
-  }
-
-  if((unsigned long) address < PAGE_SIZE) {
-    printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
-  } else
-    printk(KERN_ALERT "Unable to handle kernel paging request");
-  printk(" at virtual address %08lx\n",address);
-  printk(KERN_ALERT "current->tss.pgd_ptr = %08lx\n",
-	 (unsigned long) current->tss.pgd_ptr);
-  halt();
-}
-
-/* Dump the contents of the SRMMU fsr in a human readable format. */
-void
-dump_srmmu_fsr(unsigned long fsr)
-{
-	unsigned long ebe, l, at, ft, fav, ow;
-
-	ebe = (fsr&SRMMU_FSR_EBE_MASK)>>10;
-	l = (fsr&SRMMU_FSR_L_MASK)>>8;
-	at = (fsr&SRMMU_FSR_AT_MASK)>>5;
-	ft = (fsr&SRMMU_FSR_FT_MASK)>>2;
-	fav = (fsr&SRMMU_FSR_FAV_MASK)>>1;
-	ow = (fsr&SRMMU_FSR_OW_MASK);
-
-	printk("FSR %08lx: ", fsr);
-
-	/* Ugh, the ebe is arch-dep, have to find out the meanings. */
-	printk("EBE<%s> ", (ebe == 0 ? "none" : (ebe == 1 ? "bus err" :
-						 (ebe == 2 ? "bus timeout" :
-						  (ebe == 4 ? "uncorrectable err" :
-						   (ebe == 8 ? "undefined err" :
-						    (ebe == 16 ? "parity err" :
-						     (ebe == 24 ? "tsunami parity err" :
-						      (ebe == 32 ? "store buf err" :
-						       (ebe == 64 ? "control space err" :
-							"VIKING emergency response team"))))))))));
-	printk("L<%s> ", (l == 0 ? "context table" : (l == 1 ? "level1" :
-						      (l == 2 ? "level2" :
-						       "level3"))));
-	printk("AT<%s> ", (at == 0 ? "user load" :
-			   (at == 1 ? "priv load" :
-			    (at == 2 ? "user rd/exec" :
-			     (at == 3 ? "priv rd/exec" :
-			      (at == 4 ? "user store data" :
-			       (at == 5 ? "priv store data" :
-				(at == 6 ? "user store inst" :
-				 "priv store inst"))))))));
-
-	printk("FT<%s> ", (ft == 0 ? "none" :
-			   (ft == 1 ? "invalid address" :
-			    (ft == 2 ? "prot violation" :
-			     (ft == 3 ? "priv violation" :
-			      (ft == 4 ? "translation error" :
-			       (ft == 5 ? "bus acc error" :
-				(ft == 6 ? "internal error" :
-				 "reserved"))))))));
-
-	printk("FAV<%s> ", (fav == 0 ? "faddr invalid" : "faddr valid"));
-	printk("OW<%s>\n", (ow == 0 ? "fsr not overwritten" : "fsr overwritten"));
-
-	return;
-}
-
-/* #define DEBUG_SRMMU_TEXT_ACCESS_FAULT */
-
-void
-really_bad_srmmu_fault(int type, unsigned long fstatus, unsigned long faddr)
-{
-	/* Learn how to handle these later... */
-	printk("REALLY BAD SRMMU FAULT DETECTED\n");
-	printk("Bailing out...\n");
-	dump_srmmu_fsr(fstatus);
+	printk("FAULT: NMI received\n");
+	printk("SREGS: Synchronous Error %08lx\n", serr);
+	printk("       Synchronous Vaddr %08lx\n", svaddr);
+	printk("      Asynchronous Error %08lx\n", aerr);
+	printk("      Asynchronous Vaddr %08lx\n", avaddr);
+	printk("REGISTER DUMP:\n");
+	show_regs(regs);
 	prom_halt();
-	return;
 }
 
-asmlinkage void srmmu_text_access_fault(int type, unsigned long fstatus,
-					unsigned long faddr,
-					unsigned long pc, unsigned long psr,
-					struct pt_regs *regs)
+/* Whee, looks like an i386 to me ;-) */
+asmlinkage void do_sparc_fault(struct pt_regs *regs, unsigned long tbr)
 {
-  struct vm_area_struct *vma;
-  unsigned long address;
-
-  /* Check for external bus errors and uncorrectable errors */
-  if(fstatus&SRMMU_FSR_EBE_MASK)
-	  printk("External Bus Error detected during a text fault.\n");
-
-  /* Check for multiple faults... */
-  if(fstatus&SRMMU_FSR_OW_MASK && (fstatus&SRMMU_FSR_FT_TRANS)) {
-	  printk("Multiple faults detected in text fault handler\n");
-	  printk("Fault number one: Text fault at addr %08lx", faddr);
-	  printk("Fault number two: Translation Error\n");
-	  printk("Giving up...\n");
-	  prom_halt();
-  }
-	  
-  if(fstatus&(SRMMU_FSR_EBE_BERR | SRMMU_FSR_EBE_BTIMEO | SRMMU_FSR_EBE_UNCOR))
-	  really_bad_srmmu_fault(type, fstatus, faddr);
-
-  /* Ok, we should be able to handle it at this point. */
-
-  address = faddr;
-#ifdef DEBUG_SRMMU_TEXT_ACCESS_FAULT
-  printk("Text FAULT: address = %08lx  code = %08lx\n",
-	 (unsigned long) address, (unsigned long) fstatus);
-  printk("PC = %08lx\n", (unsigned long) regs->pc);
-  dump_srmmu_fsr(fstatus);
-  halt();
-#endif
-
-  /* Ugh, how often does this happen? ;-( */
-  if(!(fstatus&SRMMU_FSR_FAV_MASK)) {
-	  printk("Fault address register is INVALID!  Since this is a text\n");
-	  printk("fault I'll use the value of the trapped PC instead...\n");
-	  address = regs->pc;
-  }
-
-  /* Ugh, I don't wanna know... */
-
-  vma = find_vma(current, address);
-  if(!vma) {
-    goto bad_area;
-  }
-  if(vma->vm_start <= address)
-    goto good_area;
-  goto bad_area;
-
-/*
- * Ok, we have a good vm_area for this memory access, so
- * we can handle it..
- */
+	struct vm_area_struct *vma;
+	unsigned long address, error_code, trap_type;
+	unsigned long from_user;
+
+	from_user = (((regs->psr & PSR_PS) >> 4) ^ FAULT_CODE_USER);
+	if(get_fault_info(&address, &error_code, from_user))
+		goto bad_area;
+	trap_type = ((tbr>>4)&0xff);
+	if(trap_type == SP_TRAP_TFLT) {
+		/* We play it 'safe'... */
+		address = regs->pc;
+		error_code = (from_user); /* no page, read */
+	} else if(trap_type != SP_TRAP_DFLT)
+		panic("Bad sparc trap, trap_type not data or text fault...");
+
+	/* Now actually handle the fault.  Do kernel faults special,
+	 * because on the sun4c we could have faulted trying to read
+	 * the vma area of the task and without the following code
+	 * we'd fault recursively until all our stack is gone. ;-(
+	 *
+	 * XXX I think there are races with this maneuver. XXX
+	 */
+	if(!from_user && address >= KERNBASE) {
+		update_mmu_cache(0, address, __pte(0));
+		return;
+	}
+
+	vma = find_vma(current, address);
+	if(!vma)
+		goto bad_area;
+	if(vma->vm_start <= address)
+		goto good_area;
+	if(!(vma->vm_flags & VM_GROWSDOWN))
+		goto bad_area;
+	if(expand_stack(vma, address))
+		goto bad_area;
+	/*
+	 * Ok, we have a good vm_area for this memory access, so
+	 * we can handle it..
+	 */
 good_area:
-  do_no_page(vma, address, 0);
-  return;
-
-/*
- * Something tried to access memory that isn't in our memory map..
- * Fix it, but check if it's kernel or user first..
- */
+	if(error_code & FAULT_CODE_WRITE) {
+		if(!(vma->vm_flags & VM_WRITE))
+			goto bad_area;
+	} else {
+		/* Allow reads even for write-only mappings */
+		if(!(vma->vm_flags & (VM_READ | VM_EXEC)))
+			goto bad_area;
+	}
+	handle_mm_fault(vma, address, error_code & FAULT_CODE_WRITE);
+	return;
+	/*
+	 * Something tried to access memory that isn't in our memory map..
+	 * Fix it, but check if it's kernel or user first..
+	 */
 bad_area:
-  if((unsigned long) address < PAGE_SIZE) {
-    printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
-  } else
-    printk(KERN_ALERT "Unable to handle kernel paging request");
-  printk(" at virtual address %08lx\n",address);
-  printk(KERN_ALERT "current->tss.pgd_ptr = %08lx\n",
-	 (unsigned long) current->tss.pgd_ptr);
-  halt();
+	if(error_code & FAULT_CODE_USER) {
+		current->tss.sig_address = address;
+		current->tss.sig_desc = SUBSIG_NOMAPPING;
+		send_sig(SIGSEGV, current, 1);
+		return;
+	}
+	/* Uh oh, a kernel fault.  Check for bootup wp_test... */
+	if (wp_works_ok < 0 && address == 0x0) {
+		wp_works_ok = 1;
+		printk("This Sparc honours the WP bit even when in supervisor mode. "
+		       "Good.\n");
+		/* Advance program counter over the store. */
+		regs->pc = regs->npc;
+		regs->npc += 4;
+		return;
+	}
+	if((unsigned long) address < PAGE_SIZE) {
+		printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
+	} else
+		printk(KERN_ALERT "Unable to handle kernel paging request");
+	printk(" at virtual address %08lx\n",address);
+	printk("At PC %08lx nPC %08lx\n", (unsigned long) regs->pc,
+	       (unsigned long) regs->npc);
+	printk(KERN_ALERT "current->tss.pgd_ptr = %08lx\n",
+	       (unsigned long) current->tss.pgd_ptr);
+	show_regs(regs);
+	panic("KERNAL FAULT");
 }
 
-/* #define DEBUG_SRMMU_DATA_ACCESS_FAULT */
-
-asmlinkage void srmmu_data_access_fault(int type, unsigned long fstatus,
-					unsigned long faddr,
-					unsigned long afstatus,
-					unsigned long afaddr,
-					struct pt_regs *regs)
-{
-  struct vm_area_struct *vma;
-  unsigned long address, pc, psr;
-  int error_code;
-
-  pc = regs->pc;
-  psr= regs->psr;
-  address = faddr;
-#ifdef DEBUG_SRMMU_DATA_ACCESS_FAULT 
-  printk("Data FAULT: address = %08lx  code = %08lx\n",
-	 (unsigned long) address, (unsigned long) fstatus);
-  printk("PC = %08lx\n", (unsigned long) pc);
-  printk("afsr = %08lx afaddr = %08lx\n", afstatus, afaddr);
-  dump_srmmu_fsr(fstatus);
-#endif
-
-  /* I figure if I make the panic's look like they came from SunOS or Solaris
-   * my life will be a lot easier ;-)
-   */
-  if(!(fstatus&SRMMU_FSR_FAV_MASK)) {
-	  dump_srmmu_fsr(fstatus);
-	  panic("hat_pteload: Fault address is invalid on a data fault, I'm confused...\n");
-  }
-
-#if 0 /* I see this all the time on supersparcs ;-( */
-  if(fstatus&SRMMU_FSR_OW_MASK) {
-	  dump_srmmu_fsr(fstatus);
-	  panic("hat_pteload: Multiple faults at once, giving up...\n");
-  }
-#endif
-
-  vma = find_vma(current, address);
-  if(!vma) {
-#ifdef DEBUG_SRMMU_DATA_ACCESS_FAULT 
-    printk("NULL VMA\n");
-#endif
-    goto bad_area;
-  }
-  if(vma->vm_start <= address)
-    goto good_area;
-
-  if(!(vma->vm_flags & VM_GROWSDOWN)) {
-    goto bad_area;
-  }
-  if(vma->vm_end - address > current->rlim[RLIMIT_STACK].rlim_cur) {
-    goto bad_area;
-  }
-
-  vma->vm_offset -= vma->vm_start - (address & PAGE_MASK);
-  vma->vm_start = (address & PAGE_MASK);
-
-/*
- * Ok, we have a good vm_area for this memory access, so
- * we can handle it..
+/* When the user does not have a mapped stack and we either
+ * need to read the users register window from that stack or
+ * we need to save a window to that stack, control flow
+ * ends up here to investigate the situation.  This is a
+ * very odd situation where a 'user fault' happens from
+ * kernel space.
  */
-good_area:
-#ifdef DEBUG_SRMMU_DATA_ACCESS_FAULT 
-  printk("Found good_area\n");
-#endif
-  if((fstatus & SUN4C_SYNC_BADWRITE) &&
-     (fstatus & SUN4C_SYNC_NPRESENT)) {
-    if(!(vma->vm_flags & VM_WRITE)) {
-#ifdef DEBUG_SRMMU_DATA_ACCESS_FAULT 
-      printk("oops, vma not writable\n");
-#endif
-      goto bad_area;
-    }
-  } else {
-    if(fstatus & SUN4C_SYNC_PROT) {
-#ifdef DEBUG_SRMMU_DATA_ACCESS_FAULT 
-      printk("PROT violation\n");
-#endif
-      goto bad_area;
-    }
-    if(!(vma->vm_flags & (VM_READ | VM_EXEC))) {
-#ifdef DEBUG_SRMMU_DATA_ACCESS_FAULT 
-      printk("vma not readable nor executable\n");
-#endif
-      goto bad_area;
-    }
-  }
-
-  if(fstatus & SUN4C_SYNC_BADWRITE)
-    error_code = 0x2;
-  else
-    error_code = 0x0;
-
-#ifdef DEBUG_SRMMU_DATA_ACCESS_FAULT 
-  printk("calling do_no_page vma=%08lx addr=%08lx code=%d\n",
-	 (unsigned long) vma, (unsigned long) address,
-	 (int) error_code);
-#endif
-  do_no_page(vma, address, error_code);
-  return;
 
-/*
- * Something tried to access memory that isn't in our memory map..
- * Fix it, but check if it's kernel or user first..
- */
-bad_area:
-  if (wp_works_ok < 0 && address == 0x0) {
-	  wp_works_ok = 1;
-	  /* Advance the PC and NPC over the test store. */
-	  regs->pc = regs->npc;
-	  regs->npc += 4;
-	  printk("This Sparc honours the WP bit even when in supervisor mode. Good.\n");
-	  return;
-  }
-
-  if((unsigned long) address < PAGE_SIZE) {
-    printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
-  } else
-    printk(KERN_ALERT "Unable to handle kernel paging request");
-  printk(" at virtual address %08lx\n",address);
-  printk(KERN_ALERT "current->tss.pgd_ptr = %08lx\n",
-	 (unsigned long) current->tss.pgd_ptr);
-  halt();
+/* #define DEBUG_WINFAULT */
+extern void show_regwindow(struct reg_window *);
+asmlinkage void do_sparc_winfault(struct pt_regs *regs, int push)
+{
+	int wincount = 0;
+	int signal = 0;
+	struct thread_struct *tsp = &current->tss;
+
+	flush_user_windows();
+#ifdef DEBUG_WINFAULT
+	{
+		int i;
+		printk("%s[%d]wfault<%d>: WINDOW DUMP --> ", current->comm,
+		       current->pid, push);
+		if(push==1)
+			for(i = 0; i < tsp->w_saved; i++)
+				printk("w[%d]sp<%08lx>, ",
+				       i, tsp->rwbuf_stkptrs[i]);
+		else
+			printk("w[0]sp<%08lx>", regs->u_regs[UREG_FP]);
+		if(push!=2)
+			printk("\n");
+	}
+#endif
+	if(push==1) {
+		/* We failed to push a window to users stack. */
+		while(wincount < tsp->w_saved) {
+			if ((tsp->rwbuf_stkptrs[wincount] & 7) ||
+			    (tsp->rwbuf_stkptrs[wincount] > KERNBASE) ||
+			    verify_area(VERIFY_WRITE,
+					(char *) tsp->rwbuf_stkptrs[wincount],
+					sizeof(struct reg_window))) {
+				signal = SIGILL;
+				break;
+			}			
+			/* Do it! */
+			memcpy((char *) tsp->rwbuf_stkptrs[wincount],
+			       (char *)&tsp->reg_window[wincount],
+			       sizeof(struct reg_window));
+			wincount++;
+		}
+	} else {
+		/* We failed to pull a window from users stack.
+		 * For a window underflow from userland we need
+		 * to verify two stacks, for a return from trap
+		 * we need only inspect the one at UREG_FP.
+		 */
+		if((regs->u_regs[UREG_FP] & 7) ||
+		   (regs->u_regs[UREG_FP] > KERNBASE) ||
+		   verify_area(VERIFY_READ,
+			       (char *) regs->u_regs[UREG_FP],
+			       sizeof(struct reg_window)))
+			signal = SIGILL;
+		else
+			memcpy((char *)&tsp->reg_window[0],
+			       (char *) regs->u_regs[UREG_FP],
+			       sizeof(struct reg_window));
+		if(push==2 && !signal) {
+			unsigned long sp = tsp->reg_window[0].ins[6];
+#ifdef DEBUG_WINFAULT
+			printk(", w[1]sp<%08lx>\n", sp);
+			show_regwindow(&tsp->reg_window[0]);
+#endif
+			if((sp & 7) || (sp > KERNBASE) ||
+			   verify_area(VERIFY_READ, (char *) sp,
+				       sizeof(struct reg_window)))
+				signal = SIGILL;
+			else
+				memcpy((char *)&tsp->reg_window[1],
+				       (char *) sp, sizeof(struct reg_window));
+		}
+	}
+	if(signal) {
+		printk("%s[%d]: User has trashed stack pointer pc<%08lx>sp<%08lx>\n",
+		       current->comm, current->pid, regs->pc, regs->u_regs[UREG_FP]);
+		tsp->sig_address = regs->pc;
+		tsp->sig_desc = SUBSIG_STACK;
+		send_sig(signal, current, 1);
+	} else
+		tsp->w_saved = 0;
 }
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/mm/init.c linux/arch/sparc/mm/init.c
--- v1.3.43/linux/arch/sparc/mm/init.c	Tue Jun 27 14:11:32 1995
+++ linux/arch/sparc/mm/init.c	Sat Nov 25 02:59:24 1995
@@ -1,4 +1,4 @@
-/*
+/*  $Id: init.c,v 1.26 1995/11/25 00:59:22 davem Exp $
  *  linux/arch/sparc/mm/init.c
  *
  *  Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -23,29 +23,10 @@
 #include <asm/pgtable.h>
 #include <asm/vaddrs.h>
 
-extern void scsi_mem_init(unsigned long);
-extern void sound_mem_init(void);
-extern void die_if_kernel(char *,struct pt_regs *,long);
 extern void show_net_buffers(void);
 
 struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS];
 
-/* The following number keeps track of which page table is to
- * next be allocated in a page.  This is necessary since there
- * are 16 page tables per page on the space.
- */
-unsigned long ptr_in_current_pgd;
-
-/* This keeps track of which physical segments are in use right now. */
-unsigned int phys_seg_map[PSEG_ENTRIES];
-unsigned int phys_seg_life[PSEG_ENTRIES];
-
-/* Context allocation. */
-struct task_struct *ctx_tasks[MAX_CTXS];
-int ctx_tasks_last_frd;
-
-extern int invalid_segment, num_segmaps, num_contexts;
-
 /*
  * BAD_PAGE is the page that is used for page faults when linux
  * is out-of-memory. Older versions of linux just did a
@@ -82,18 +63,18 @@
 	int i,free = 0,total = 0,reserved = 0;
 	int shared = 0;
 
-	printk("Mem-info:\n");
+	printk("\nMem-info:\n");
 	show_free_areas();
 	printk("Free swap:       %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
-	i = high_memory >> PAGE_SHIFT;
+	i = MAP_NR(high_memory);
 	while (i-- > 0) {
 		total++;
-		if (mem_map[i] & MAP_PAGE_RESERVED)
+		if (mem_map[i].reserved)
 			reserved++;
-		else if (!mem_map[i])
+		else if (!mem_map[i].count)
 			free++;
 		else
-			shared += mem_map[i]-1;
+			shared += mem_map[i].count-1;
 	}
 	printk("%d pages of RAM\n",total);
 	printk("%d free pages\n",free);
@@ -105,7 +86,6 @@
 #endif
 }
 
-extern unsigned long free_area_init(unsigned long, unsigned long);
 extern pgprot_t protection_map[16];
 
 /*
@@ -119,57 +99,51 @@
 
 unsigned long paging_init(unsigned long start_mem, unsigned long end_mem)
 {
-	int i;
-
 	switch(sparc_cpu_model) {
 	case sun4c:
+	case sun4e:
 		start_mem = sun4c_paging_init(start_mem, end_mem);
 		break;
 	case sun4m:
 	case sun4d:
-	case sun4e:
 		start_mem = srmmu_paging_init(start_mem, end_mem);
 		break;
 	default:
 		printk("paging_init: Cannot init paging on this Sparc\n");
 		printk("paging_init: sparc_cpu_model = %d\n", sparc_cpu_model);
 		printk("paging_init: Halting...\n");
-		halt();
+		panic("paging_init");
 	};
 
-	/* Initialize context map. */
-	for(i=0; i<MAX_CTXS; i++) ctx_tasks[i] = NULL;
-
-	/* Initialize the protection map */
-	protection_map[0] = __P000;
-	protection_map[1] = __P001;
-	protection_map[2] = __P010;
-	protection_map[3] = __P011;
-	protection_map[4] = __P100;
-	protection_map[5] = __P101;
-	protection_map[6] = __P110;
-	protection_map[7] = __P111;
-	protection_map[8] = __S000;
-	protection_map[9] = __S001;
-	protection_map[10] = __S010;
-	protection_map[11] = __S011;
-	protection_map[12] = __S100;
-	protection_map[13] = __S101;
-	protection_map[14] = __S110;
-	protection_map[15] = __S111;
-
-	start_mem = probe_devices(start_mem);
-
-	return start_mem;
+	/* Initialize the protection map with non-constant values
+	 * MMU dependant values.
+	 */
+	protection_map[0] = PAGE_NONE;
+	protection_map[1] = PAGE_READONLY;
+	protection_map[2] = PAGE_COPY;
+	protection_map[3] = PAGE_COPY;
+	protection_map[4] = PAGE_READONLY;
+	protection_map[5] = PAGE_READONLY;
+	protection_map[6] = PAGE_COPY;
+	protection_map[7] = PAGE_COPY;
+	protection_map[8] = PAGE_NONE;
+	protection_map[9] = PAGE_READONLY;
+	protection_map[10] = PAGE_SHARED;
+	protection_map[11] = PAGE_SHARED;
+	protection_map[12] = PAGE_READONLY;
+	protection_map[13] = PAGE_READONLY;
+	protection_map[14] = PAGE_SHARED;
+	protection_map[15] = PAGE_SHARED;
+	return probe_devices(start_mem);
 }
 
-extern unsigned long sun4c_test_wp(unsigned long);
+extern void sun4c_test_wp(void);
+extern void sun4c_lock_entire_kernel(unsigned long start_mem);
 extern void srmmu_test_wp(void);
 
 void mem_init(unsigned long start_mem, unsigned long end_mem)
 {
 	int codepages = 0;
-	int reservedpages = 0;
 	int datapages = 0;
 	unsigned long tmp2, addr;
 	extern char etext;
@@ -181,85 +155,75 @@
 
 	addr = PAGE_OFFSET;
 	while(addr < start_mem) {
-		mem_map[MAP_NR(addr)] = MAP_PAGE_RESERVED;
+		mem_map[MAP_NR(addr)].reserved = 1;
 		addr += PAGE_SIZE;
 	}
 
-	for(addr = start_mem; addr < end_mem; addr += PAGE_SIZE)
-			mem_map[MAP_NR(addr)] = 0;
-
-#ifdef CONFIG_SCSI
-	scsi_mem_init(high_memory);
-#endif
-
+	for(addr = start_mem; addr < end_mem; addr += PAGE_SIZE) {
+		for(tmp2=0; sp_banks[tmp2].num_bytes != 0; tmp2++) {
+			unsigned long phys_addr = (addr - PAGE_OFFSET);
+			unsigned long base = sp_banks[tmp2].base_addr;
+			unsigned long limit = base + sp_banks[tmp2].num_bytes;
+
+			if((phys_addr >= base) && (phys_addr < limit) &&
+			   ((phys_addr + PAGE_SIZE) < limit))
+				mem_map[MAP_NR(addr)].reserved = 0;
+		}
+	}
 	for (addr = PAGE_OFFSET; addr < end_mem; addr += PAGE_SIZE) {
-		if(mem_map[MAP_NR(addr)]) {
+		if(mem_map[MAP_NR(addr)].reserved) {
 			if (addr < (unsigned long) &etext)
 				codepages++;
 			else if(addr < start_mem)
 				datapages++;
-			else
-				reservedpages++;
 			continue;
 		}
-		mem_map[MAP_NR(addr)] = 1;
+		mem_map[MAP_NR(addr)].count = 1;
 		free_page(addr);
 	}
 
 	tmp2 = nr_free_pages << PAGE_SHIFT;
 
-	printk("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data)\n",
+	printk("Memory: %luk available (%dk kernel code, %dk data)\n",
 	       tmp2 >> 10,
-	       (high_memory - PAGE_OFFSET) >> 10,
 	       codepages << (PAGE_SHIFT-10),
-	       reservedpages << (PAGE_SHIFT-10),
 	       datapages << (PAGE_SHIFT-10));
 
-/* Heh, test write protection just like the i386, this is bogus but it is
- * fun to do ;)
- */
 	switch(sparc_cpu_model) {
 	case sun4c:
-		start_mem = sun4c_test_wp(start_mem);
+	case sun4e:
+		sun4c_lock_entire_kernel(start_mem);
+		sun4c_test_wp();
 		break;
 	case sun4m:
 	case sun4d:
-	case sun4e:
 		srmmu_test_wp();
 		break;
 	default:
 		printk("mem_init: Could not test WP bit on this machine.\n");
 		printk("mem_init: sparc_cpu_model = %d\n", sparc_cpu_model);
 		printk("mem_init: Halting...\n");
-		halt();
+		panic("mem_init()");
 	};
-
-#ifdef DEBUG_MEMINIT
-	printk("Breaker breaker...Roger roger.... Over and out...\n");
-#endif
-	invalidate();
-
-	return;
 }
 
 void si_meminfo(struct sysinfo *val)
 {
 	int i;
 
-	i = high_memory >> PAGE_SHIFT;
+	i = MAP_NR(high_memory);
 	val->totalram = 0;
 	val->sharedram = 0;
 	val->freeram = nr_free_pages << PAGE_SHIFT;
 	val->bufferram = buffermem;
 	while (i-- > 0)  {
-		if (mem_map[i] & MAP_PAGE_RESERVED)
+		if (mem_map[i].reserved)
 			continue;
 		val->totalram++;
-		if (!mem_map[i])
+		if (!mem_map[i].count)
 			continue;
-		val->sharedram += mem_map[i]-1;
+		val->sharedram += mem_map[i].count-1;
 	}
 	val->totalram <<= PAGE_SHIFT;
 	val->sharedram <<= PAGE_SHIFT;
-	return;
 }
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/mm/loadmmu.c linux/arch/sparc/mm/loadmmu.c
--- v1.3.43/linux/arch/sparc/mm/loadmmu.c	Sun Sep  3 12:26:49 1995
+++ linux/arch/sparc/mm/loadmmu.c	Sat Nov 25 02:59:26 1995
@@ -1,16 +1,38 @@
-/* loadmmu.c:  This code loads up all the mm function pointers once the
+/* $Id: loadmmu.c,v 1.13 1995/11/25 00:59:24 davem Exp $
+ * loadmmu.c:  This code loads up all the mm function pointers once the
  *             machine type has been determined.  It also sets the static
  *             mmu values such as PAGE_NONE, etc.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  */
 
+#include <linux/kernel.h>
+
 #include <asm/system.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 
+struct ctx_list *ctx_list_pool;
+struct ctx_list ctx_free;
+struct ctx_list ctx_used;
+
+void (*mmu_exit_hook)(void *);
+void (*mmu_fork_hook)(void *, unsigned long);
+void (*mmu_release_hook)(void *);
+void (*mmu_flush_hook)(void *);
+void (*mmu_task_cacheflush)(void *);
+
+char *(*mmu_lockarea)(char *, unsigned long);
+void  (*mmu_unlockarea)(char *, unsigned long);
+char *(*mmu_get_scsi_buffer)(char *, unsigned long);
+void  (*mmu_release_scsi_buffer)(char *, unsigned long);
+
+
+int (*get_fault_info)(unsigned long *, unsigned long *, unsigned long);
+void (*update_mmu_cache)(struct vm_area_struct *vma, unsigned long address, pte_t pte);
+
 void (*invalidate)(void);
-void (*set_pte)(pte_t *ptep, pte_t entry);
+void (*set_pte)(pte_t *pteptr, pte_t pteval);
 
 unsigned int pmd_shift, pmd_size, pmd_mask;
 unsigned int (*pmd_align)(unsigned int);
@@ -21,14 +43,13 @@
 pgprot_t page_none, page_shared, page_copy, page_readonly, page_kernel;
 pgprot_t page_invalid;
 
-/* Grrr... function pointers galore... */
 unsigned long (*pte_page)(pte_t);
 unsigned long (*pmd_page)(pmd_t);
 unsigned long (*pgd_page)(pgd_t);
 
 void (*sparc_update_rootmmu_dir)(struct task_struct *, pgd_t *pgdir);
 unsigned long (*(vmalloc_start))(void);
-void (*switch_to_context)(int);
+void (*switch_to_context)(void *vtask);
 
 int (*pte_none)(pte_t);
 int (*pte_present)(pte_t);
@@ -51,9 +72,9 @@
 void (*pgd_reuse)(pgd_t *);
 
 pte_t (*mk_pte)(unsigned long, pgprot_t);
-void (*pgd_set)(pgd_t *, pte_t *);
+void (*pgd_set)(pgd_t *, pmd_t *);
 pte_t (*pte_modify)(pte_t, pgprot_t);
-pgd_t * (*pgd_offset)(struct task_struct *, unsigned long);
+pgd_t * (*pgd_offset)(struct mm_struct *, unsigned long);
 pmd_t * (*pmd_offset)(pgd_t *, unsigned long);
 pte_t * (*pte_offset)(pmd_t *, unsigned long);
 void (*pte_free_kernel)(pte_t *);
@@ -70,10 +91,6 @@
 
 pgd_t * (*pgd_alloc)(void);
 
-/*
- * The following only work if pte_present() is true.
- * Undefined behaviour if not..
- */
 int (*pte_read)(pte_t);
 int (*pte_write)(pte_t);
 int (*pte_exec)(pte_t);
@@ -94,6 +111,9 @@
 pte_t (*pte_mkyoung)(pte_t);
 pte_t (*pte_mkcow)(pte_t);
 
+unsigned long (*sparc_virt_to_phys)(unsigned long);
+unsigned long (*sparc_phys_to_virt)(unsigned long);
+
 extern void ld_mmu_sun4c(void);
 extern void ld_mmu_srmmu(void);
 
@@ -110,10 +130,9 @@
 		ld_mmu_srmmu();
 		break;
 	default:
-		printk("load_mmu:  MMU support not available for this architecture\n");
-		printk("load_mmu:  sparc_cpu_model = %d\n", (int) sparc_cpu_model);
-		printk("load_mmu:  Halting...\n");
-		halt();
+		printk("load_mmu:MMU support not available for this architecture\n");
+		printk("load_mmu:sparc_cpu_model = %d\n", (int) sparc_cpu_model);
+		printk("load_mmu:Halting...\n");
+		panic("load_mmu()");
 	};
-	return;
 }
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/mm/mbus.c linux/arch/sparc/mm/mbus.c
--- v1.3.43/linux/arch/sparc/mm/mbus.c	Thu Jan  1 02:00:00 1970
+++ linux/arch/sparc/mm/mbus.c	Sat Nov 25 02:59:27 1995
@@ -0,0 +1,186 @@
+/* $Id: mbus.c,v 1.9 1995/11/25 00:59:26 davem Exp $
+ * mbus.c: MBUS probing routines, called from kernel/probe.c
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#include <linux/kernel.h>
+
+#include <asm/oplib.h>
+#include <asm/cache.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/asi.h>
+#include <asm/psr.h>
+#include <asm/vac-ops.h>
+#include <asm/mbus.h>
+
+/* #define DEBUG_MBUS */
+
+unsigned int viking_rev, swift_rev, cypress_rev;
+enum mbus_module srmmu_modtype;
+unsigned int hwbug_bitmask;
+
+void
+probe_mbus(void)
+{
+	register unsigned int mreg, vaddr;
+	register int impl, vers, syscntrl, pso, resv, nofault, enable;
+	register int mod_typ, mod_rev;
+
+	srmmu_modtype = SRMMU_INVAL_MOD;
+	hwbug_bitmask = 0;
+	vaddr = 0;
+
+	mreg = srmmu_get_mmureg();
+	impl = (mreg & SRMMU_CTREG_IMPL_MASK) >> SRMMU_CTREG_IMPL_SHIFT;
+	vers = (mreg & SRMMU_CTREG_VERS_MASK) >> SRMMU_CTREG_VERS_SHIFT;
+	syscntrl = (mreg & SRMMU_CTREG_SYSCNTRL_MASK) >> SRMMU_CTREG_SYSCNTRL_SHIFT;
+	pso = (mreg & SRMMU_CTREG_PSO_MASK) >> SRMMU_CTREG_PSO_SHIFT;
+	resv = (mreg & SRMMU_CTREG_RESV_MASK) >> SRMMU_CTREG_RESV_SHIFT;
+	nofault = (mreg & SRMMU_CTREG_NOFAULT_MASK) >> SRMMU_CTREG_NOFAULT_SHIFT;
+	enable = (mreg & SRMMU_CTREG_ENABLE_MASK) >> SRMMU_CTREG_ENABLE_SHIFT;
+
+#ifdef DEBUG_MBUS
+	printk("MMU REGISTER\n");
+	printk("IMPL<%01x> VERS<%01x> SYSCNTRL<%04x> PSO<%d> RESV<%02x> NOFAULT<%d> ENABLE<%d>\n",
+	       impl, vers, syscntrl, (int) pso, resv, (int) nofault, (int) enable);
+#endif
+
+	mod_typ = impl; mod_rev = vers;
+	printk("MBUS: ");
+
+	if(mod_typ == 0x1) /* Ross HyperSparc or Cypress */
+		if (mod_rev == 0x7) {
+			srmmu_modtype = HyperSparc;
+			hwbug_bitmask |= HWBUG_VACFLUSH_BITROT;
+			/* Turn off Cache Wrapping and copyback caching, I don't
+			 * understand them completely yet... */
+			printk("Enabling HyperSparc features...\n");
+			/* FUCK IT, I wanna see this baby chug! */
+			/* First, flush the cache */
+#if 0
+			for(vaddr = 0; vaddr != vac_size; vaddr+=vac_linesize)
+				flush_ei_ctx(vaddr);
+#endif
+			mreg &= (~HYPERSPARC_CWENABLE);
+			mreg &= (~HYPERSPARC_CMODE);
+			mreg &= (~HYPERSPARC_WBENABLE);
+			mreg |= (HYPERSPARC_CENABLE);
+			srmmu_set_mmureg(mreg);
+			/* Clear all the cache tags */
+#if 0
+			for(vaddr = 0; vaddr != vac_size; vaddr+=vac_linesize)
+				__asm__ __volatile__("sta %%g0, [%0] %1" : :
+						     "r" (vaddr), "i" (0xe));
+#endif
+			/* Flush the ICACHE */
+			flush_whole_icache();
+
+		} else {
+			cypress_rev = mod_rev;
+			if(mod_rev == 0xe) {
+				srmmu_modtype = Cypress_vE;
+				hwbug_bitmask |= HWBUG_COPYBACK_BROKEN;
+			} else
+				if(mod_rev == 0xd) {
+					srmmu_modtype = Cypress_vD;
+					hwbug_bitmask |= HWBUG_ASIFLUSH_BROKEN;
+				} else
+					srmmu_modtype = Cypress;
+
+			/* It is a Cypress module */
+			printk("ROSS Cypress Module %s\n",
+			       (srmmu_modtype == Cypress_vE ? "Rev. E" :
+				(srmmu_modtype == Cypress_vD ? "Rev. D" :
+				 "")));
+				/* Enable Cypress features */
+				printk("Enabling Cypress features...\n");
+				mreg &= (~CYPRESS_CMODE);
+				mreg |= (CYPRESS_CENABLE);
+				srmmu_set_mmureg(mreg);
+				/* Maybe play with Cypress 604/605 cache stuff here? */
+		}
+
+
+	if(((get_psr()>>0x18)&0xff)==0x04) {
+		__asm__ __volatile__("lda [%1] %2, %0\n\t" 
+				     "srl %0, 0x18, %0\n\t" :
+				     "=r" (swift_rev) :
+				     "r" (0x10003000), "i" (0x20));
+		printk("Fujitsu MB86904 or higher Swift module\n");  /* MB86905 etc. */
+		switch(swift_rev) {
+		case 0x11:
+		case 0x20:
+		case 0x23:
+		case 0x30:
+			srmmu_modtype = Swift_lots_o_bugs;
+			hwbug_bitmask |= HWBUG_KERN_ACCBROKEN;
+			hwbug_bitmask |= HWBUG_KERN_CBITBROKEN;
+			printk("Detected Swift with Lots 'o' Bugs\n");
+			break;
+		case 0x25:
+		case 0x31:
+			srmmu_modtype = Swift_bad_c;
+			hwbug_bitmask |= HWBUG_KERN_CBITBROKEN;
+			printk("Detected Swift with kernel pte C bit bug\n");
+			break;
+		default:
+			srmmu_modtype = Swift_ok;
+			printk("Detected Swift with no bugs...\n");
+			break;
+		}
+		/* Enable Fujitsu Swift specific features here... */
+		printk("Enabling Swift features...\n");
+		mreg |= 0;
+		srmmu_set_mmureg(mreg);
+	}
+
+	if((((get_psr()>>0x18)&0xff)==0x40 ||
+	    (((get_psr()>>0x18)&0xff)==0x41 && mod_typ==0 && mod_rev==0))) {
+		if(((get_psr()>>0x18)&0xf)==0 && mod_rev==0) {
+			srmmu_modtype = Viking_12;
+			hwbug_bitmask |= HWBUG_MODIFIED_BITROT;
+			hwbug_bitmask |= HWBUG_PC_BADFAULT_ADDR;
+		} else {
+			if(((get_psr()>>0x18)&0xf)!=0) {
+				srmmu_modtype = Viking_2x;
+				hwbug_bitmask |= HWBUG_PC_BADFAULT_ADDR;
+			} else
+				if(mod_rev==1) {
+					srmmu_modtype = Viking_30;
+					hwbug_bitmask |= HWBUG_PACINIT_BITROT;
+				} else  {
+					if (mod_rev<8)
+						srmmu_modtype = Viking_35;
+					else
+						srmmu_modtype = Viking_new;
+				}
+		}
+
+		/* SPARCclassic's STP1010 may be produced under other name */
+		printk("VIKING Module\n");
+		printk("Enabling Viking features...\n");
+		mreg |= (VIKING_DCENABLE | VIKING_ICENABLE | VIKING_SBENABLE |
+			 VIKING_TCENABLE | VIKING_DPENABLE);
+		srmmu_set_mmureg(mreg);
+	}
+   
+	if((((get_psr()>>0x18)&0xff)==0x41) && (mod_typ || mod_rev)) {
+		srmmu_modtype = Tsunami;
+		printk("Tsunami module\n");
+		/* Enable Tsunami features */
+	}
+
+	if(srmmu_modtype == SRMMU_INVAL_MOD) {
+		printk("Unknown SRMMU module type!\n");
+		printk("MMU_CREG: impl=%x vers=%x\n", mod_typ, mod_rev);
+		printk("PSR: impl=%x vers=%x\n", ((get_psr()>>28)&0xf),
+		       ((get_psr()>>24)&0xf));
+		panic("probe_mbus()");
+	}
+
+	/* AIEEE, should get this from the prom... */
+	printk("Boot processor ID %d Module ID %d (%s MBUS)\n",
+	       get_cpuid(), get_modid(), (get_modid() == 0x8 ? "Level 1" : "Level 2"));
+}
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/mm/s4cflush.S linux/arch/sparc/mm/s4cflush.S
--- v1.3.43/linux/arch/sparc/mm/s4cflush.S	Thu Jan  1 02:00:00 1970
+++ linux/arch/sparc/mm/s4cflush.S	Sat Nov 25 02:59:32 1995
@@ -0,0 +1,575 @@
+/* $Id: s4cflush.S,v 1.8 1995/11/25 00:59:29 davem Exp $
+ * s4cflush.S: Inline management of the sun4c cache.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#include <asm/head.h>
+#include <asm/cprefix.h>
+#include <asm/asi.h>
+#include <asm/page.h>
+
+/* We need to be able to call a routine which will in low-level
+ * assembly flush an entire segment from the virtual cache using
+ * a base virtual address and that will use as few registers as
+ * possible.  The address of that function is stored here.
+ * The register usage for this routine is defined as
+ * %l2 -- Address of Segment to flush
+ * %l4 -- Return address
+ * %l6 -- scratch
+ * %l7 -- scratch
+ */
+	.align	4
+	.globl	C_LABEL(sun4c_ctxflush), C_LABEL(sun4c_segflush)
+	.globl	C_LABEL(sun4c_pgflush)
+C_LABEL(sun4c_ctxflush):	.word	C_LABEL(sun4c_ctxflush_sw64KB16B)
+C_LABEL(sun4c_segflush):	.word	C_LABEL(sun4c_segflush_sw64KB16B)
+C_LABEL(sun4c_pgflush):		.word	C_LABEL(sun4c_pgflush_sw64KB16B)
+
+	.text
+
+	/* Here are the assembly in-line virtual cache flushing
+	 * routines on the sun4c.
+	 */
+
+	.align 4
+	.globl C_LABEL(sun4c_ctxflush_hw64KB16B)
+
+	/* Flush an entire context using hardware assisted flushes
+	 * for a cache of size 64KB with 16B lines.
+	 */
+C_LABEL(sun4c_ctxflush_hw64KB16B):
+	sethi	%hi(PAGE_SIZE), %l6
+	/* Now flush 16 pages starting at virtual address zero */
+	or	%g0, %g0, %l7	
+	sta	%g0, [%l7] ASI_HWFLUSHCONTEXT   /* One */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHCONTEXT   /* Two */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHCONTEXT   /* Three */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHCONTEXT   /* Four */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHCONTEXT   /* Five */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHCONTEXT   /* Six */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHCONTEXT   /* Seven */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHCONTEXT   /* Eight */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHCONTEXT   /* Nine */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHCONTEXT   /* Ten */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHCONTEXT   /* Eleven */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHCONTEXT   /* Twelve */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHCONTEXT   /* Thirteen */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHCONTEXT   /* Fourteen */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHCONTEXT   /* Fifteen */
+	add	%l7, %l6, %l7
+
+	/* Return to caller and flush the last page */
+	jmpl	%l4 + 0x8, %g0
+	sta	%g0, [%l7] ASI_HWFLUSHCONTEXT   /* Sixteen */
+
+
+	.globl C_LABEL(sun4c_ctxflush_sw64KB16B)
+
+	/* Flush an entire context using software flushes
+	 * for a cache of size 64KB with 16B lines.
+	 */
+C_LABEL(sun4c_ctxflush_sw64KB16B):
+	/* Starting at virtual address zero, software flush
+	 * 4096 lines at 16 byte intervals.
+	 */
+#define SWFLUSHCTX16_2LINES \
+	sta	%g0, [%l7] ASI_FLUSHCTX; \
+	add	%l7, 0x10, %l7; \
+	sta	%g0, [%l7] ASI_FLUSHCTX; \
+	add	%l7, 0x10, %l7; \
+
+#define SWFLUSHCTX16_4LINES \
+	SWFLUSHCTX16_2LINES \
+	SWFLUSHCTX16_2LINES \
+	
+#define SWFLUSHCTX16_8LINES \
+	SWFLUSHCTX16_4LINES \
+	SWFLUSHCTX16_4LINES \
+	
+#define SWFLUSHCTX16_16LINES \
+	SWFLUSHCTX16_8LINES \
+	SWFLUSHCTX16_8LINES \
+	
+#define SWFLUSHCTX16_32LINES \
+	SWFLUSHCTX16_16LINES \
+	SWFLUSHCTX16_16LINES \
+	
+#define SWFLUSHCTX16_64LINES \
+	SWFLUSHCTX16_32LINES \
+	SWFLUSHCTX16_32LINES \
+	
+#define SWFLUSHCTX16_128LINES \
+	SWFLUSHCTX16_64LINES \
+	SWFLUSHCTX16_64LINES \
+	
+#define SWFLUSHCTX16_256LINES \
+	SWFLUSHCTX16_128LINES \
+	SWFLUSHCTX16_128LINES \
+	
+	/* WHEE! */
+	or	%g0, %g0, %l7		/* Base register */
+	SWFLUSHCTX16_256LINES
+	SWFLUSHCTX16_256LINES
+	SWFLUSHCTX16_256LINES
+	SWFLUSHCTX16_256LINES
+	SWFLUSHCTX16_256LINES
+	SWFLUSHCTX16_256LINES
+	SWFLUSHCTX16_256LINES
+	SWFLUSHCTX16_256LINES
+	SWFLUSHCTX16_256LINES
+	SWFLUSHCTX16_256LINES
+	SWFLUSHCTX16_256LINES
+	SWFLUSHCTX16_256LINES
+	SWFLUSHCTX16_256LINES
+	SWFLUSHCTX16_256LINES
+	SWFLUSHCTX16_256LINES
+	SWFLUSHCTX16_256LINES
+
+	/* Done, return to caller */
+	jmpl	%l4 + 0x8, %g0
+	nop
+
+	.globl C_LABEL(sun4c_ctxflush_hw64KB32B)
+	/* Flush an entire context using hardware assisted flushes
+	 * for a cache of size 64KB with 32B lines.
+	 */
+C_LABEL(sun4c_ctxflush_hw64KB32B):
+	sethi	%hi(PAGE_SIZE), %l6
+	/* Now flush 16 pages starting at virtual address zero */
+	or	%g0, %g0, %l7	
+	sta	%g0, [%l7] ASI_HWFLUSHCONTEXT   /* One */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHCONTEXT   /* Two */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHCONTEXT   /* Three */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHCONTEXT   /* Four */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHCONTEXT   /* Five */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHCONTEXT   /* Six */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHCONTEXT   /* Seven */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHCONTEXT   /* Eight */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHCONTEXT   /* Nine */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHCONTEXT   /* Ten */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHCONTEXT   /* Eleven */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHCONTEXT   /* Twelve */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHCONTEXT   /* Thirteen */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHCONTEXT   /* Fourteen */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHCONTEXT   /* Fifteen */
+	add	%l7, %l6, %l7
+
+	/* Return to caller and flush the last page */
+	jmpl	%l4 + 0x8, %g0
+	sta	%g0, [%l7] ASI_HWFLUSHCONTEXT   /* Sixteen */
+
+	.globl C_LABEL(sun4c_ctxflush_sw64KB32B)
+
+	/* Flush an entire context using software flushes
+	 * for a cache of size 64KB with 32B lines.
+	 */
+C_LABEL(sun4c_ctxflush_sw64KB32B):
+	/* Starting at virtual address zero, software flush
+	 * 2048 lines at 32 byte intervals.
+	 */
+#define SWFLUSHCTX32_2LINES \
+	sta	%g0, [%l7] ASI_FLUSHCTX; \
+	add	%l7, 0x20, %l7; \
+	sta	%g0, [%l7] ASI_FLUSHCTX; \
+	add	%l7, 0x20, %l7; \
+	
+#define SWFLUSHCTX32_4LINES \
+	SWFLUSHCTX32_2LINES \
+	SWFLUSHCTX32_2LINES \
+
+#define SWFLUSHCTX32_8LINES \
+	SWFLUSHCTX32_4LINES \
+	SWFLUSHCTX32_4LINES \
+
+#define SWFLUSHCTX32_16LINES \
+	SWFLUSHCTX32_8LINES \
+	SWFLUSHCTX32_8LINES \
+
+#define SWFLUSHCTX32_32LINES \
+	SWFLUSHCTX32_16LINES \
+	SWFLUSHCTX32_16LINES \
+
+#define SWFLUSHCTX32_64LINES \
+	SWFLUSHCTX32_32LINES \
+	SWFLUSHCTX32_32LINES \
+
+#define SWFLUSHCTX32_128LINES \
+	SWFLUSHCTX32_64LINES \
+	SWFLUSHCTX32_64LINES \
+
+	/* WHEE! */
+	or	%g0, %g0, %l7		/* Base register */
+	SWFLUSHCTX32_128LINES
+	SWFLUSHCTX32_128LINES
+	SWFLUSHCTX32_128LINES
+	SWFLUSHCTX32_128LINES
+	SWFLUSHCTX32_128LINES
+	SWFLUSHCTX32_128LINES
+	SWFLUSHCTX32_128LINES
+	SWFLUSHCTX32_128LINES
+	SWFLUSHCTX32_128LINES
+	SWFLUSHCTX32_128LINES
+	SWFLUSHCTX32_128LINES
+	SWFLUSHCTX32_128LINES
+	SWFLUSHCTX32_128LINES
+	SWFLUSHCTX32_128LINES
+	SWFLUSHCTX16_256LINES
+	SWFLUSHCTX16_256LINES
+
+	jmpl	%l4 + 0x8, %g0
+	nop
+
+	.align 4
+	.globl C_LABEL(sun4c_segflush_hw64KB16B)
+
+	/* Flush an entire segment using hardware assisted flushes
+	 * for a cache of size 64KB with 16B lines.
+	 */
+C_LABEL(sun4c_segflush_hw64KB16B):
+	sethi	%hi(PAGE_SIZE), %l6	/* Increment */
+	sethi	%hi(0xfffc0000), %l7
+	and	%l2, %l7, %l7		/* Base address */
+
+	/* Now flush 16 pages starting at beginning of vseg */
+	sta	%g0, [%l7] ASI_HWFLUSHSEG   /* One */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHSEG   /* Two */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHSEG   /* Three */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHSEG   /* Four */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHSEG   /* Five */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHSEG   /* Six */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHSEG   /* Seven */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHSEG   /* Eight */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHSEG   /* Nine */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHSEG   /* Ten */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHSEG   /* Eleven */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHSEG   /* Twelve */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHSEG   /* Thirteen */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHSEG   /* Fourteen */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHSEG   /* Fifteen */
+	add	%l7, %l6, %l7
+
+	/* Return to caller and flush the last page */
+	jmpl	%l4 + 0x8, %g0
+	sta	%g0, [%l7] ASI_HWFLUSHSEG   /* Sixteen */
+
+	.globl C_LABEL(sun4c_segflush_sw64KB16B)
+
+	/* Flush an entire segment using software flushes
+	 * for a cache of size 64KB with 16B lines.
+	 */
+C_LABEL(sun4c_segflush_sw64KB16B):
+	/* Starting at virtual address in %l2, software flush
+	 * 4096 lines at 16 byte intervals.
+	 */
+#define SWFLUSHSEG16_2LINES \
+	sta	%g0, [%l7] ASI_FLUSHSEG; \
+	add	%l7, 0x10, %l7; \
+	sta	%g0, [%l7] ASI_FLUSHSEG; \
+	add	%l7, 0x10, %l7; \
+
+#define SWFLUSHSEG16_4LINES \
+	SWFLUSHSEG16_2LINES \
+	SWFLUSHSEG16_2LINES \
+
+#define SWFLUSHSEG16_8LINES \
+	SWFLUSHSEG16_4LINES \
+	SWFLUSHSEG16_4LINES \
+
+#define SWFLUSHSEG16_16LINES \
+	SWFLUSHSEG16_8LINES \
+	SWFLUSHSEG16_8LINES \
+
+#define SWFLUSHSEG16_32LINES \
+	SWFLUSHSEG16_16LINES \
+	SWFLUSHSEG16_16LINES \
+
+#define SWFLUSHSEG16_64LINES \
+	SWFLUSHSEG16_32LINES \
+	SWFLUSHSEG16_32LINES \
+
+#define SWFLUSHSEG16_128LINES \
+	SWFLUSHSEG16_64LINES \
+	SWFLUSHSEG16_64LINES \
+
+#define SWFLUSHSEG16_256LINES \
+	SWFLUSHSEG16_128LINES \
+	SWFLUSHSEG16_128LINES \
+
+	sethi	%hi(0xfffc0000), %l7
+	and	%l2, %l7, %l7		/* Base register */
+	SWFLUSHSEG16_256LINES
+	SWFLUSHSEG16_256LINES
+	SWFLUSHSEG16_256LINES
+	SWFLUSHSEG16_256LINES
+	SWFLUSHSEG16_256LINES
+	SWFLUSHSEG16_256LINES
+	SWFLUSHSEG16_256LINES
+	SWFLUSHSEG16_256LINES
+	SWFLUSHSEG16_256LINES
+	SWFLUSHSEG16_256LINES
+	SWFLUSHSEG16_256LINES
+	SWFLUSHSEG16_256LINES
+	SWFLUSHSEG16_256LINES
+	SWFLUSHSEG16_256LINES
+	SWFLUSHSEG16_256LINES
+	SWFLUSHSEG16_256LINES
+
+	/* Done, return to caller */
+	jmpl	%l4 + 0x8, %g0
+	nop
+
+	.globl C_LABEL(sun4c_segflush_hw64KB32B)
+
+	/* Flush an entire segment using hardware assisted flushes
+	 * for a cache of size 64KB with 32B lines.
+	 */
+C_LABEL(sun4c_segflush_hw64KB32B):
+	sethi	%hi(PAGE_SIZE), %l6	/* Increment */
+	sethi	%hi(0xfffc0000), %l7
+	and	%l2, %l7, %l7		/* Base register */
+
+	/* Now flush 16 pages starting at virtual address in %l7 */
+	sta	%g0, [%l7] ASI_HWFLUSHSEG   /* One */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHSEG   /* Two */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHSEG   /* Three */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHSEG   /* Four */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHSEG   /* Five */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHSEG   /* Six */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHSEG   /* Seven */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHSEG   /* Eight */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHSEG   /* Nine */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHSEG   /* Ten */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHSEG   /* Eleven */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHSEG   /* Twelve */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHSEG   /* Thirteen */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHSEG   /* Fourteen */
+	add	%l7, %l6, %l7
+	sta	%g0, [%l7] ASI_HWFLUSHSEG   /* Fifteen */
+	add	%l7, %l6, %l7
+
+	/* Return to caller and flush the last page */
+	jmpl	%l4 + 0x8, %g0
+	sta	%g0, [%l7] ASI_HWFLUSHSEG   /* Sixteen */
+	
+	.globl C_LABEL(sun4c_segflush_sw64KB32B)
+
+	/* Flush an entire segment using software flushes
+	 * for a cache of size 64KB with 32B lines.
+	 */
+C_LABEL(sun4c_segflush_sw64KB32B):
+	/* Starting at virtual address passed in %l2, software
+	 * flush 2048 lines at 32 byte intervals.
+	 */
+#define SWFLUSHSEG32_2LINES \
+	sta	%g0, [%l7] ASI_FLUSHSEG; \
+	add	%l7, 0x20, %l7; \
+	sta	%g0, [%l7] ASI_FLUSHSEG; \
+	add	%l7, 0x20, %l7; \
+
+#define SWFLUSHSEG32_4LINES \
+	SWFLUSHSEG32_2LINES \
+	SWFLUSHSEG32_2LINES \
+
+#define SWFLUSHSEG32_8LINES \
+	SWFLUSHSEG32_4LINES \
+	SWFLUSHSEG32_4LINES \
+
+#define SWFLUSHSEG32_16LINES \
+	SWFLUSHSEG32_8LINES \
+	SWFLUSHSEG32_8LINES \
+
+#define SWFLUSHSEG32_32LINES \
+	SWFLUSHSEG32_16LINES \
+	SWFLUSHSEG32_16LINES \
+
+#define SWFLUSHSEG32_64LINES \
+	SWFLUSHSEG32_32LINES \
+	SWFLUSHSEG32_32LINES \
+
+#define SWFLUSHSEG32_128LINES \
+	SWFLUSHSEG32_64LINES \
+	SWFLUSHSEG32_64LINES \
+
+	/* WHEE! */
+	sethi	%hi(0xfffc0000), %l7
+	and	%l2, %l7, %l7		/* Base register */
+	SWFLUSHSEG32_128LINES
+	SWFLUSHSEG32_128LINES
+	SWFLUSHSEG32_128LINES
+	SWFLUSHSEG32_128LINES
+	SWFLUSHSEG32_128LINES
+	SWFLUSHSEG32_128LINES
+	SWFLUSHSEG32_128LINES
+	SWFLUSHSEG32_128LINES
+	SWFLUSHSEG32_128LINES
+	SWFLUSHSEG32_128LINES
+	SWFLUSHSEG32_128LINES
+	SWFLUSHSEG32_128LINES
+	SWFLUSHSEG32_128LINES
+	SWFLUSHSEG32_128LINES
+	SWFLUSHSEG32_128LINES
+	SWFLUSHSEG32_128LINES
+
+	jmpl	%l4 + 0x8, %g0
+	nop
+
+	.align 4
+	.globl C_LABEL(sun4c_pgflush_hw64KB16B)
+	.globl C_LABEL(sun4c_pgflush_hw64KB32B)
+
+	/* Flush a page using hardware assisted flushes
+	 * for a cache of size 64KB with 16B or 32B lines.
+	 */
+C_LABEL(sun4c_pgflush_hw64KB16B):
+C_LABEL(sun4c_pgflush_hw64KB32B):
+	/* Easiest flush possible on sun4c */
+	jmpl	%l4 + 0x8, %g0
+	sta	%g0, [%l2] ASI_HWFLUSHPAGE
+
+	.globl	C_LABEL(sun4c_pgflush_sw64KB16B)
+	/* Flush a page using software flushes for a cache
+	 * of size 64KB with 16B lines.
+	 */
+C_LABEL(sun4c_pgflush_sw64KB16B):
+	/* Flush every line within the page */
+#define SWFLUSHPG16_2LINES \
+	sta	%g0, [%l7] ASI_FLUSHPG; \
+	add	%l7, 0x10, %l7; \
+	sta	%g0, [%l7] ASI_FLUSHPG; \
+	add	%l7, 0x10, %l7; \
+
+#define SWFLUSHPG16_4LINES \
+	SWFLUSHPG16_2LINES \
+	SWFLUSHPG16_2LINES \
+
+#define SWFLUSHPG16_8LINES \
+	SWFLUSHPG16_4LINES \
+	SWFLUSHPG16_4LINES \
+
+#define SWFLUSHPG16_16LINES \
+	SWFLUSHPG16_8LINES \
+	SWFLUSHPG16_8LINES \
+
+#define SWFLUSHPG16_32LINES \
+	SWFLUSHPG16_16LINES \
+	SWFLUSHPG16_16LINES \
+
+#define SWFLUSHPG16_64LINES \
+	SWFLUSHPG16_32LINES \
+	SWFLUSHPG16_32LINES \
+
+#define SWFLUSHPG16_128LINES \
+	SWFLUSHPG16_64LINES \
+	SWFLUSHPG16_64LINES \
+
+#define SWFLUSHPG16_256LINES \
+	SWFLUSHPG16_128LINES \
+	SWFLUSHPG16_128LINES \
+
+	or	%l2, %g0, %l7		/* Base address of page */
+	SWFLUSHPG16_256LINES
+
+	/* Return to caller and flush last line */
+	jmpl	%l4 + 0x8, %g0
+	nop
+
+	.globl	C_LABEL(sun4c_pgflush_sw64KB32B)
+	/* Flush a page using software flushes for a cache
+	 * of size 64KB with 32B lines.
+	 */
+C_LABEL(sun4c_pgflush_sw64KB32B):
+	/* Flush every line within the page */
+#define SWFLUSHPG32_2LINES \
+	sta	%g0, [%l7] ASI_FLUSHPG; \
+	add	%l7, 0x20, %l7; \
+	sta	%g0, [%l7] ASI_FLUSHPG; \
+	add	%l7, 0x20, %l7; \
+
+#define SWFLUSHPG32_4LINES \
+	SWFLUSHPG32_2LINES \
+	SWFLUSHPG32_2LINES \
+
+#define SWFLUSHPG32_8LINES \
+	SWFLUSHPG32_4LINES \
+	SWFLUSHPG32_4LINES \
+
+#define SWFLUSHPG32_16LINES \
+	SWFLUSHPG32_8LINES \
+	SWFLUSHPG32_8LINES \
+
+#define SWFLUSHPG32_32LINES \
+	SWFLUSHPG32_16LINES \
+	SWFLUSHPG32_16LINES \
+
+#define SWFLUSHPG32_64LINES \
+	SWFLUSHPG32_32LINES \
+	SWFLUSHPG32_32LINES \
+
+#define SWFLUSHPG32_128LINES \
+	SWFLUSHPG32_64LINES \
+	SWFLUSHPG32_64LINES \
+
+	or	%l2, %g0, %l7		/* Base address of page */
+	SWFLUSHPG32_128LINES
+
+	/* Return to caller and flush last line */
+	jmpl	%l4 + 0x8, %g0
+	nop
+
+/* All that crap just to flush a fucking virtual cache, sheesh... */
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/mm/srmmu.c linux/arch/sparc/mm/srmmu.c
--- v1.3.43/linux/arch/sparc/mm/srmmu.c	Sun Sep  3 12:26:49 1995
+++ linux/arch/sparc/mm/srmmu.c	Sat Nov 25 02:59:35 1995
@@ -1,4 +1,5 @@
-/* srmmu.c:  SRMMU specific routines for memory management.
+/* $Id: srmmu.c,v 1.22 1995/11/25 00:59:33 davem Exp $
+ * srmmu.c:  SRMMU specific routines for memory management.
  *
  * Copyright (C) 1995 David S. Miller  (davem@caip.rutgers.edu)
  * Copyright (C) 1995 Peter A. Zaitcev (zaitcev@lab.ipmce.su)
@@ -20,53 +21,6 @@
 unsigned int srmmu_pmd_align(unsigned int addr) { return SRMMU_PMD_ALIGN(addr); }
 unsigned int srmmu_pgdir_align(unsigned int addr) { return SRMMU_PGDIR_ALIGN(addr); }
 
-/* Idea taken from Hamish McDonald's MC680x0 Linux code, nice job.
- * Many of the page table/directory functions on the SRMMU use this
- * routine.
- *
- * Having a complete physical ram structure walk happen for each
- * invocation is quite costly.  However, this does do some nice
- * sanity checking and we'll see when our maps don't match.  Eventually
- * when I trust my code I will just do a direct mmu probe in mk_pte().
- */
-static inline unsigned int
-srmmu_virt_to_phys(unsigned int vaddr)
-{
-	unsigned int paddr = 0;
-	unsigned int voff = (vaddr - PAGE_OFFSET);
-	int i;
-
-	for(i=0; sp_banks[i].num_bytes != 0; i++) {
-		if(voff < paddr + sp_banks[i].num_bytes) {
-			/* This matches. */
-			return sp_banks[i].base_addr + voff - paddr;
-		} else
-			paddr += sp_banks[i].num_bytes;
-	}
-	/* Shit, gotta consult the MMU, this shouldn't happen... */
-	printk("srmmu_virt_to_phys: SRMMU virt to phys translation failed, halting\n");
-	halt();
-}		
-
-static inline unsigned long
-srmmu_phys_to_virt(unsigned long paddr)
-{
-        int i;
-        unsigned long offset = PAGE_OFFSET;
-
-        for (i=0; sp_banks[i].num_bytes != 0; i++)
-        {
-                if (paddr >= sp_banks[i].base_addr &&
-                    paddr < (sp_banks[i].base_addr
-                             + sp_banks[i].num_bytes)) {
-                        return (paddr - sp_banks[i].base_addr) + offset;
-                } else
-                        offset += sp_banks[i].num_bytes;
-        }
-	printk("srmmu_phys_to_virt: Could not make translation, halting...\n");
-	halt();
-}
-
 unsigned long
 srmmu_vmalloc_start(void)
 {
@@ -79,7 +33,7 @@
 	unsigned long page;
 
 	page = (pmd_val(pmd) & (SRMMU_PTD_PTP_MASK)) << SRMMU_PTD_PTP_PADDR_SHIFT;
-	return srmmu_phys_to_virt(page);
+	return (page + PAGE_OFFSET);
 }
 
 unsigned long
@@ -88,7 +42,7 @@
 	unsigned long page;
 
 	page = (pgd_val(pgd) & (SRMMU_PTD_PTP_MASK)) << SRMMU_PTD_PTP_PADDR_SHIFT;
-	return srmmu_phys_to_virt(page);
+	return (page + PAGE_OFFSET);
 }
 
 unsigned long 
@@ -97,18 +51,17 @@
 	unsigned long page;
 
 	page = (pte_val(pte) & (SRMMU_PTE_PPN_MASK)) << SRMMU_PTE_PPN_PADDR_SHIFT;
-	printk("srmmu_pte_page: page = %08lx\n", page);
-	return srmmu_phys_to_virt(page);
+	return (page + PAGE_OFFSET);
 }
 
 int srmmu_pte_none(pte_t pte)		{ return !pte_val(pte); }
 int srmmu_pte_present(pte_t pte)	{ return pte_val(pte) & SRMMU_ET_PTE; }
-int srmmu_pte_inuse(pte_t *ptep)        { return mem_map[MAP_NR(ptep)] != 1; }
+int srmmu_pte_inuse(pte_t *ptep)        { return mem_map[MAP_NR(ptep)].reserved || mem_map[MAP_NR(ptep)].count != 1; }
 void srmmu_pte_clear(pte_t *ptep)	{ pte_val(*ptep) = 0; }
 void srmmu_pte_reuse(pte_t *ptep)
 {
-  if(!(mem_map[MAP_NR(ptep)] & MAP_PAGE_RESERVED))
-    mem_map[MAP_NR(ptep)]++;
+  if(!mem_map[MAP_NR(ptep)].reserved)
+    mem_map[MAP_NR(ptep)].count++;
 }
 
 int srmmu_pmd_none(pmd_t pmd)		{ return !pmd_val(pmd); }
@@ -119,12 +72,12 @@
 }
 
 int srmmu_pmd_present(pmd_t pmd)	{ return pmd_val(pmd) & SRMMU_ET_PTD; }
-int srmmu_pmd_inuse(pmd_t *pmdp)        { return mem_map[MAP_NR(pmdp)] != 1; }
+int srmmu_pmd_inuse(pmd_t *pmdp)        { return mem_map[MAP_NR(pmdp)].reserved || mem_map[MAP_NR(pmdp)].count != 1; }
 void srmmu_pmd_clear(pmd_t *pmdp)	{ pmd_val(*pmdp) = 0; }
 void srmmu_pmd_reuse(pmd_t * pmdp)
 {
-        if (!(mem_map[MAP_NR(pmdp)] & MAP_PAGE_RESERVED))
-                mem_map[MAP_NR(pmdp)]++;
+        if (!mem_map[MAP_NR(pmdp)].reserved)
+                mem_map[MAP_NR(pmdp)].count++;
 }
 
 int srmmu_pgd_none(pgd_t pgd)		{ return !pgd_val(pgd); }
@@ -134,12 +87,12 @@
 		(srmmu_pgd_page(pgd) > high_memory);
 }
 int srmmu_pgd_present(pgd_t pgd)	{ return pgd_val(pgd) & SRMMU_ET_PTD; }
-int srmmu_pgd_inuse(pgd_t *pgdp)        { return mem_map[MAP_NR(pgdp)] != 1; }
+int srmmu_pgd_inuse(pgd_t *pgdp)        { return mem_map[MAP_NR(pgdp)].reserved; }
 void srmmu_pgd_clear(pgd_t * pgdp)	{ pgd_val(*pgdp) = 0; }
 void srmmu_pgd_reuse(pgd_t *pgdp)
 {
-  if (!(mem_map[MAP_NR(pgdp)] & MAP_PAGE_RESERVED))
-    mem_map[MAP_NR(pgdp)]++;
+  if (!mem_map[MAP_NR(pgdp)].reserved)
+    mem_map[MAP_NR(pgdp)].count++;
 }
 
 /*
@@ -179,7 +132,7 @@
 	pte_t pte;
 
 	if(page & (~PAGE_MASK)) panic("srmmu_mk_pte() called with unaligned page");
-	page = (srmmu_virt_to_phys(page) >> SRMMU_PTE_PPN_PADDR_SHIFT);
+	page = ((page - PAGE_OFFSET) >> SRMMU_PTE_PPN_PADDR_SHIFT);
 	pte_val(pte) = (page & SRMMU_PTE_PPN_MASK);
 	pte_val(pte) |= pgprot_val(pgprot);
 	return pte;
@@ -190,7 +143,7 @@
 {
 	unsigned long page = (unsigned long) pmdp;
 
-	page = (srmmu_virt_to_phys(page) >> SRMMU_PTD_PTP_PADDR_SHIFT);
+	page = ((page - PAGE_OFFSET) >> SRMMU_PTD_PTP_PADDR_SHIFT);
 
 	pgd_val(*pgdp) = ((page & SRMMU_PTD_PTP_MASK) | SRMMU_ET_PTD);
 }
@@ -200,7 +153,7 @@
 {
 	unsigned long page = (unsigned long) ptep;
 
-	page = (srmmu_virt_to_phys(page) >> SRMMU_PTD_PTP_PADDR_SHIFT);
+	page = ((page - PAGE_OFFSET) >> SRMMU_PTD_PTP_PADDR_SHIFT);
 
 	pmd_val(*pmdp) = ((page & SRMMU_PTD_PTP_MASK) | SRMMU_ET_PTD);
 }
@@ -214,10 +167,9 @@
 
 /* to find an entry in a top-level page table... */
 pgd_t *
-srmmu_pgd_offset(struct task_struct * tsk, unsigned long address)
+srmmu_pgd_offset(struct mm_struct * mm, unsigned long address)
 {
-	return ((pgd_t *) tsk->tss.pgd_ptr) +
-		((address >> SRMMU_PGDIR_SHIFT) & (SRMMU_PTRS_PER_PGD - 1));
+	return mm->pgd + ((address >> SRMMU_PGDIR_SHIFT) & (SRMMU_PTRS_PER_PGD - 1));
 }
 
 /* Find an entry in the second-level page table.. */
@@ -243,7 +195,7 @@
 	/* See if this process has a context entry already, like after execve() */
 	if(tsk->tss.context != -1) {
 		pgd_t *ctable_ptr = 0;
-		ctable_ptr = (pgd_t *) srmmu_phys_to_virt(srmmu_get_ctable_ptr());
+		ctable_ptr = (pgd_t *) (srmmu_get_ctable_ptr() + PAGE_OFFSET);
 		ctable_ptr += tsk->tss.context;
 		srmmu_pgd_set(ctable_ptr, (pmd_t *) pgdir);
 		/* Should flush caches here too... */
@@ -263,7 +215,7 @@
 void
 srmmu_pte_free_kernel(pte_t *pte)
 {
-	mem_map[MAP_NR(pte)] = 1;
+	mem_map[MAP_NR(pte)].reserved = 0;
 	free_page((unsigned long) pte);
 }
 
@@ -278,7 +230,7 @@
 		if (srmmu_pmd_none(*pmd)) {
 			if (page) {
 				srmmu_pmd_set(pmd, page);
-				mem_map[MAP_NR(page)] = MAP_PAGE_RESERVED;
+				mem_map[MAP_NR(page)].reserved = 1;
 				return page + address;
 			}
 			srmmu_pmd_set(pmd, (pte_t *) SRMMU_ET_PTDBAD);
@@ -298,7 +250,7 @@
 void
 srmmu_pmd_free_kernel(pmd_t *pmd)
 {
-	mem_map[MAP_NR(pmd)] = 1;
+	mem_map[MAP_NR(pmd)].reserved = 0;
 	free_page((unsigned long) pmd);
 }
 
@@ -313,7 +265,7 @@
 		if (srmmu_pgd_none(*pgd)) {
 			if (page) {
 				srmmu_pgd_set(pgd, page);
-				mem_map[MAP_NR(page)] = MAP_PAGE_RESERVED;
+				mem_map[MAP_NR(page)].reserved = 1;
 				return page + address;
 			}
 			srmmu_pgd_set(pgd, (pmd_t *) SRMMU_ET_PTDBAD);
@@ -346,7 +298,6 @@
 		if (srmmu_pmd_none(*pmd)) {
 			if (page) {
 				srmmu_pmd_set(pmd, page);
-				mem_map[MAP_NR(page)] = MAP_PAGE_RESERVED;
 				return page + address;
 			}
 			srmmu_pmd_set(pmd, (pte_t *) SRMMU_ET_PTDBAD);
@@ -383,7 +334,6 @@
 		if (srmmu_pgd_none(*pgd)) {
 			if (page) {
 				srmmu_pgd_set(pgd, page);
-				mem_map[MAP_NR(page)] = MAP_PAGE_RESERVED;
 				return page + address;
 			}
 			srmmu_pgd_set(pgd, (pmd_t *) SRMMU_ET_PTDBAD);
@@ -427,18 +377,19 @@
 	return;
 }
 
-void
-srmmu_set_pte(pte_t *ptep, pte_t entry)
+/* XXX Needs to be written */
+void srmmu_set_pte(pte_t *ptep, pte_t pteval)
 {
-	/* for now... */
-	*ptep = entry;
+	/* More than this is needed. */
+	*ptep = pteval;
 }
 
 /* XXX Needs to be written */
 void
-srmmu_switch_to_context(int context)
+srmmu_switch_to_context(void *vtask)
 {
-	printk("switching to context %d\n", context);
+	struct task_struct *tsk = vtask;
+	printk("switching to context %d\n", tsk->tss.context);
 
 	return;
 }
@@ -460,7 +411,7 @@
   pmd_t *pmdp;
   pte_t *ptep;
 
-  pgdp = srmmu_pgd_offset(&init_task, virt_addr);
+  pgdp = srmmu_pgd_offset(init_task.mm, virt_addr);
   pmdp = srmmu_pmd_offset(pgdp, virt_addr);
   ptep = srmmu_pte_offset(pmdp, virt_addr);
   pte_val(*ptep) = (physaddr >> SRMMU_PTE_PPN_PADDR_SHIFT) & SRMMU_PTE_PPN_MASK;
@@ -478,6 +429,25 @@
   return;
 }
 
+char *srmmu_lockarea(char *vaddr, unsigned long len)
+{
+	return vaddr;
+}
+
+void srmmu_unlockarea(char *vaddr, unsigned long len)
+{
+}
+
+char *srmmu_get_scsi_buffer(char *vaddr, unsigned long len)
+{
+	panic("sun4m: get_scsi_buffer() not implemented yet.");
+}
+
+void srmmu_release_scsi_buffer(char *vaddr, unsigned long len)
+{
+	panic("sun4m: release_scsi_buffer() not implemented yet.");
+}
+
 /* Perfom a some soft of MMU tablewalk.
  * Long contiguous mappings are not supported (yet ?).
  *
@@ -590,28 +560,13 @@
 	return (void*) ret;
 }
 
-extern unsigned long srmmu_data_fault, srmmu_text_fault;
-
-/* Patch in the SRMMU fault handlers for the trap table. */
-void
-srmmu_patch_fhandlers(void)
+/* Get fault information on an SRMMU. */
+int
+srmmu_get_fault_info(unsigned long *address, unsigned long *error_code,
+		     unsigned long from_user)
 {
-	/* Say the following ten times fast... */
-	sparc_ttable[SP_TRAP_TFLT].inst_one = SPARC_MOV_CONST_L3(0x1);
-	sparc_ttable[SP_TRAP_TFLT].inst_two =
-		SPARC_BRANCH((unsigned long) &srmmu_text_fault, 
-			     (unsigned long) &sparc_ttable[SP_TRAP_TFLT].inst_two);
-	sparc_ttable[SP_TRAP_TFLT].inst_three = SPARC_RD_PSR_L0;
-	sparc_ttable[SP_TRAP_TFLT].inst_four = SPARC_NOP;
-
-	sparc_ttable[SP_TRAP_DFLT].inst_one = SPARC_MOV_CONST_L3(0x9);
-	sparc_ttable[SP_TRAP_DFLT].inst_two =
-		SPARC_BRANCH((unsigned long) &srmmu_data_fault,
-			     (unsigned long) &sparc_ttable[SP_TRAP_DFLT].inst_two);
-	sparc_ttable[SP_TRAP_DFLT].inst_three = SPARC_RD_PSR_L0;
-	sparc_ttable[SP_TRAP_DFLT].inst_four = SPARC_NOP;
-
-	return;
+	/* XXX Foo, write this... XXX */
+	return 0;
 }
 
 /* Paging initialization on the Sparc Reference MMU. */
@@ -653,7 +608,7 @@
 
 	/* Make Linux physical page tables. */
 	for(vaddr = KERNBASE; vaddr < end_mem; vaddr+=PAGE_SIZE) {
-		pgdp = srmmu_pgd_offset(&init_task, vaddr);
+		pgdp = srmmu_pgd_offset(init_task.mm, vaddr);
 		if(srmmu_pgd_none(*pgdp)) {
 			pmdp = srmmu_init_alloc(&mempool,
 						SRMMU_PTRS_PER_PMD*sizeof(pmd_t));
@@ -674,7 +629,7 @@
 	/* Map IO areas. */
 	for(vaddr = IOBASE_VADDR; vaddr < (IOBASE_VADDR+IOBASE_LEN);
 	    vaddr += SRMMU_PMD_SIZE) {
-		pgdp = srmmu_pgd_offset(&init_task, vaddr);
+		pgdp = srmmu_pgd_offset(init_task.mm, vaddr);
 		if(srmmu_pgd_none(*pgdp)) {
 			pmdp = srmmu_init_alloc(&mempool,
 						SRMMU_PTRS_PER_PMD*sizeof(pmd_t));
@@ -688,12 +643,37 @@
 		}
 	}
 
+	/* Map DVMA areas. */
+	for(vaddr = (DVMA_VADDR); vaddr < (DVMA_VADDR + DVMA_LEN);
+	    vaddr += PAGE_SIZE) {
+		pgdp = srmmu_pgd_offset(init_task.mm, vaddr);
+		if(srmmu_pgd_none(*pgdp)) {
+			pmdp = srmmu_init_alloc(&mempool,
+						SRMMU_PTRS_PER_PMD*sizeof(pmd_t));
+			srmmu_pgd_set(pgdp, pmdp);
+		}
+		pmdp = srmmu_pmd_offset(pgdp, vaddr);
+		if(srmmu_pmd_none(*pmdp)) {
+			ptep = srmmu_init_alloc(&mempool,
+						SRMMU_PTRS_PER_PTE*sizeof(pte_t));
+			srmmu_pmd_set(pmdp, ptep);
+		}
+
+		ptep = srmmu_pte_offset(pmdp, vaddr);
+		*ptep = srmmu_mk_pte((unsigned int) srmmu_init_alloc(&mempool, PAGE_SIZE), SRMMU_PAGE_KERNEL);
+		pte_val(*ptep) &= ~(SRMMU_PTE_C_MASK);
+	}
+	srmmu_flush_whole_tlb();
+	flush_ei_ctx(0x0);
+
 	/* Map in the PERCPU areas in virtual address space. */
-	printk("PERCPU_VADDR + PERCPU_LEN = %08lx\n",
-	       (PERCPU_VADDR + PERCPU_LEN));
+#if 0
+	prom_printf("PERCPU_VADDR + PERCPU_LEN = %08lx\n",
+		    (PERCPU_VADDR + PERCPU_LEN));
+#endif
 	for(vaddr = PERCPU_VADDR; vaddr < (PERCPU_VADDR + PERCPU_LEN);
 	    vaddr += PERCPU_ENTSIZE) {
-		pgdp = srmmu_pgd_offset(&init_task, vaddr);
+		pgdp = srmmu_pgd_offset(init_task.mm, vaddr);
 		if(srmmu_pgd_none(*pgdp)) {
 			pmdp = srmmu_init_alloc(&mempool,
 						SRMMU_PTRS_PER_PMD*sizeof(pmd_t));
@@ -724,6 +704,10 @@
 	 * you will lose with video cards when we take over the ctx table.
 	 * Also, must take into consideration that prom might be using level
 	 * two or one PTE's. TODO
+	 *
+	 * XXX This still isn't right, the cg* graphics cards get their
+	 * XXX mapped screens all fucked up when I jump onto Linux's
+	 * XXX page tables.  Must investigate...
 	 */
 	for(vaddr = KADB_DEBUGGER_BEGVM; vaddr != 0x0;) {
 		unsigned int prom_pte;
@@ -731,7 +715,7 @@
 		prom_pte = srmmu_init_twalk(vaddr, 0);
 
 		if(prom_pte) {
-			pgdp = srmmu_pgd_offset(&init_task, vaddr);
+			pgdp = srmmu_pgd_offset(init_task.mm, vaddr);
 			if((prom_pte&0x3) == 0x0) {
 				prom_pte &= ~0x3;
 				prom_pte |= SRMMU_ET_PTE;
@@ -772,9 +756,9 @@
 	/* We probably do, and should do it just to be safe... -Davem */
 
 	/* Take the MMU over from the PROM */
-	printk("Taking over MMU from PROM.\n");
+	prom_printf("Taking over MMU from PROM.\n");
 
-	srmmu_set_ctable_ptr(srmmu_virt_to_phys((unsigned)lnx_root));
+	srmmu_set_ctable_ptr(((unsigned)lnx_root) - PAGE_OFFSET);
 
 	srmmu_flush_whole_tlb();
 
@@ -784,14 +768,14 @@
 	start_mem = PAGE_ALIGN(start_mem);
 
 #if 0
-	printk("Testing context switches...\n");
+	prom_printf("Testing context switches...\n");
 	for(i=0; i<num_contexts; i++)
 		srmmu_set_context(i);
-	printk("done...\n");
+	prom_printf("done...\n");
 	srmmu_set_context(0);
 #endif
 
-	printk("survived...\n");
+	prom_printf("survived...\n");
 	return start_mem;
 }
 
@@ -800,8 +784,6 @@
 srmmu_test_wp(void)
 {
 	pgd_t *pgdp;
-	pmd_t *pmdp;
-	pte_t *ptep;
 	
 	wp_works_ok = -1;
 	/* We mapped page zero as a read-only page in paging_init()
@@ -814,17 +796,54 @@
 	if (wp_works_ok < 0)
 		wp_works_ok = 0;
 
-	pgdp = srmmu_pgd_offset(&init_task, 0x0);
+	pgdp = srmmu_pgd_offset(init_task.mm, 0x0);
 	pgd_val(*pgdp) = 0x0;
 
 	return;
 }
 
+void srmmu_update_mmu_cache(struct vm_area_struct * vma,
+			    unsigned long address, pte_t pte)
+{
+	printk("WHOOPS, update_mmu_cache called on a SRMMU!\n");
+	panic("SRMMU bolixed...");
+}
+
+void
+srmmu_fork_hook(void *vtask, unsigned long kthread_usp)
+{
+	return; /* XXX */
+}
+
+void
+srmmu_exit_hook(void *vtask)
+{
+	return; /* XXX */
+}
+
+void
+srmmu_release_hook(void *vtask)
+{
+	return; /* XXX */
+}
+
+void
+srmmu_flush_hook(void *vtask)
+{
+	return; /* XXX */
+}
+
+void
+srmmu_task_cacheflush(void *vtask)
+{
+	return; /* XXX */
+}
+
 /* Load up routines and constants for sun4m mmu */
 void
 ld_mmu_srmmu(void)
 {
-	printk("Loading srmmu MMU routines\n");
+	prom_printf("Loading srmmu MMU routines\n");
 
 	/* First the constants */
 	pmd_shift = SRMMU_PMD_SHIFT;
@@ -880,7 +899,7 @@
 	pgd_reuse = srmmu_pgd_reuse;
 
 	mk_pte = srmmu_mk_pte;
-	pgd_set = srmmu_pgd_set;  /* XXX needs a cast */
+	pgd_set = srmmu_pgd_set;
 	pte_modify = srmmu_pte_modify;
 	pgd_offset = srmmu_pgd_offset;
 	pmd_offset = srmmu_pmd_offset;
@@ -914,7 +933,15 @@
 	pte_mkdirty = srmmu_pte_mkdirty;
 	pte_mkyoung = srmmu_pte_mkyoung;
 	pte_mkcow = srmmu_pte_mkcow;
-
-	return;
+	get_fault_info = srmmu_get_fault_info;
+	update_mmu_cache = srmmu_update_mmu_cache;
+	mmu_exit_hook = srmmu_exit_hook;
+	mmu_fork_hook = srmmu_fork_hook;
+	mmu_release_hook = srmmu_release_hook;
+	mmu_flush_hook = srmmu_flush_hook;
+	mmu_task_cacheflush = srmmu_task_cacheflush;
+	mmu_lockarea = srmmu_lockarea;
+	mmu_unlockarea = srmmu_unlockarea;
+	mmu_get_scsi_buffer = srmmu_get_scsi_buffer;
+	mmu_release_scsi_buffer = srmmu_release_scsi_buffer;
 }
-
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/mm/srmmuinv.c linux/arch/sparc/mm/srmmuinv.c
--- v1.3.43/linux/arch/sparc/mm/srmmuinv.c	Tue Jun 27 14:11:32 1995
+++ linux/arch/sparc/mm/srmmuinv.c	Sat Nov 25 02:59:37 1995
@@ -1,4 +1,5 @@
-/* srmmuinv.c:  Invalidate routines for the various different
+/* $Id: srmmuinv.c,v 1.2 1995/11/25 00:59:36 davem Exp $
+ * srmmuinv.c:  Invalidate routines for the various different
  *              SRMMU implementations.
  *
  * Copyright (C) 1995 David S. Miller
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/mm/sun4c.c linux/arch/sparc/mm/sun4c.c
--- v1.3.43/linux/arch/sparc/mm/sun4c.c	Sun Sep  3 12:26:50 1995
+++ linux/arch/sparc/mm/sun4c.c	Sat Nov 25 02:59:43 1995
@@ -1,4 +1,5 @@
-/* sun4c.c:  Sun4C specific mm routines.
+/* $Id: sun4c.c,v 1.56 1995/11/25 00:59:39 davem Exp $
+ * sun4c.c:  Sun4C specific mm routines.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  */
@@ -6,131 +7,79 @@
 /* The SUN4C has an MMU based upon a Translation Lookaside Buffer scheme
  * where only so many translations can be loaded at once.  As Linus said
  * in Boston, this is a broken way of doing things.
- *
- * NOTE:  Free page pool and tables now live in high memory, see
- *        asm-sparc/pgtsun4c.c and asm-sparc/page.h for details.
  */
 
-#include <linux/kernel.h>  /* for printk */
+#include <linux/kernel.h>
 #include <linux/sched.h>
 
-#include <asm/processor.h> /* for wp_works_ok */
+#include <asm/processor.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/vac-ops.h>
 #include <asm/vaddrs.h>
 #include <asm/asi.h>
+#include <asm/system.h>
 #include <asm/contregs.h>
+#include <asm/oplib.h>
+#include <asm/idprom.h>
+#include <asm/machines.h>
+#include <asm/memreg.h>
 #include <asm/kdebug.h>
 
-unsigned int sun4c_pmd_align(unsigned int addr) { return SUN4C_PMD_ALIGN(addr); }
-unsigned int sun4c_pgdir_align(unsigned int addr) { return SUN4C_PGDIR_ALIGN(addr); }
-
-extern int num_segmaps, num_contexts;
-
-/* Idea taken from Hamish McDonald's MC680x0 Linux code, nice job.
- * The only function that actually uses this is sun4c_mk_pte() and
- * to have a complete physical ram structure walk happen for each
- * invocation is quite costly.  However, this does do some nice
- * sanity checking and we'll see when our maps don't match.  Eventually
- * when I trust my code I will just do a direct mmu probe in mk_pte().
- */
-static inline unsigned int sun4c_virt_to_phys(unsigned int vaddr)
-{
-	unsigned int paddr = 0;
-	unsigned int voff = (vaddr - PAGE_OFFSET);
-	int i;
+/* Pseg allocation structures. */
+static struct pseg_list s4cpseg_pool[256];
 
-	for(i=0; sp_banks[i].num_bytes != 0; i++) {
-		if(voff < paddr + sp_banks[i].num_bytes) {
-			/* This matches. */
-			return sp_banks[i].base_addr + voff - paddr;
-		} else
-			paddr += sp_banks[i].num_bytes;
-	}
-	/* Shit, gotta consult the MMU, this shouldn't happen... */
-	printk("sun4c_virt_to_phys: Could not make translation for vaddr %08lx\n", (unsigned long) vaddr);
-	SP_ENTER_DEBUGGER;
-}		
+struct pseg_list s4cpseg_free;
+struct pseg_list s4cpseg_used;
+static struct pseg_list s4cpseg_locked;
+static struct pseg_list s4cpseg_per_context[16];
 
-static inline unsigned long
-sun4c_phys_to_virt(unsigned long paddr)
-{
-        int i;
-        unsigned long offset = PAGE_OFFSET;
+static unsigned char pseg_count_per_context[16];
 
-        for (i=0; sp_banks[i].num_bytes != 0; i++)
-        {
-                if (paddr >= sp_banks[i].base_addr &&
-                    paddr < (sp_banks[i].base_addr
-                             + sp_banks[i].num_bytes)) {
-                        return (paddr - sp_banks[i].base_addr) + offset;
-                } else
-                        offset += sp_banks[i].num_bytes;
-        }
-	printk("sun4c_phys_to_virt: Could not make translation for paddr %08lx\n", (unsigned long) paddr);
-	SP_ENTER_DEBUGGER;
-}
+unsigned int sun4c_pmd_align(unsigned int addr) { return SUN4C_PMD_ALIGN(addr); }
+unsigned int sun4c_pgdir_align(unsigned int addr) { return SUN4C_PGDIR_ALIGN(addr); }
 
-unsigned long
-sun4c_vmalloc_start(void)
-{
-	return ((high_memory + SUN4C_VMALLOC_OFFSET) & ~(SUN4C_VMALLOC_OFFSET-1));
-}
+extern int num_segmaps, num_contexts;
 
-/* Note that I have 16 page tables per page, thus four less
- * bits of shifting than normal.
+/* First the functions which the mid-level code uses to directly
+ * manipulate the software page tables.  Some defines since we are
+ * emulating the i386 page directory layout.
  */
+#define PGD_PRESENT  0x001
+#define PGD_RW       0x002
+#define PGD_USER     0x004
+#define PGD_ACCESSED 0x020
+#define PGD_DIRTY    0x040
+#define PGD_TABLE    (PGD_PRESENT | PGD_RW | PGD_USER | PGD_ACCESSED | PGD_DIRTY)
 
-unsigned long
-sun4c_pte_page(pte_t pte)
-{
-	unsigned long page;
-
-	page = ((pte_val(pte) & _SUN4C_PFN_MASK) << (PAGE_SHIFT));
-	return sun4c_phys_to_virt(page);
-}
-
-unsigned long 
-sun4c_pmd_page(pmd_t pmd)
+unsigned long sun4c_vmalloc_start(void)
 {
-	return ((pmd_val(pmd) & _SUN4C_PGD_PFN_MASK) << (_SUN4C_PGD_PAGE_SHIFT));
-}
-
-unsigned long
-sun4c_pgd_page(pgd_t pgd)
-{
-	return ((pgd_val(pgd) & _SUN4C_PGD_PFN_MASK) << (_SUN4C_PGD_PAGE_SHIFT));
+	return SUN4C_VMALLOC_START;
 }
 
 /* Update the root mmu directory on the sun4c mmu. */
-void
-sun4c_update_rootmmu_dir(struct task_struct *tsk, pgd_t *pgdir)
+void sun4c_update_rootmmu_dir(struct task_struct *tsk, pgd_t *pgdir)
 {
 	(tsk)->tss.pgd_ptr = (unsigned long) (pgdir);
-
-	/* May have to do some flushing here. */
-
-	return;
 }
 
 int sun4c_pte_none(pte_t pte)		{ return !pte_val(pte); }
 int sun4c_pte_present(pte_t pte)	{ return pte_val(pte) & _SUN4C_PAGE_VALID; }
-int sun4c_pte_inuse(pte_t *ptep)        { return mem_map[MAP_NR(ptep)] != 1; }
+int sun4c_pte_inuse(pte_t *ptep)        { return mem_map[MAP_NR(ptep)].reserved || mem_map[MAP_NR(ptep)].count != 1; }
 void sun4c_pte_clear(pte_t *ptep)	{ pte_val(*ptep) = 0; }
 void sun4c_pte_reuse(pte_t *ptep)
 {
-  if(!(mem_map[MAP_NR(ptep)] & MAP_PAGE_RESERVED))
-    mem_map[MAP_NR(ptep)]++;
+	if(!mem_map[MAP_NR(ptep)].reserved)
+		mem_map[MAP_NR(ptep)].count++;
 }
 
 int sun4c_pmd_none(pmd_t pmd)		{ return !pmd_val(pmd); }
 int sun4c_pmd_bad(pmd_t pmd)
 {
-	return ((pmd_val(pmd) & _SUN4C_PGD_MMU_MASK) != _SUN4C_PAGE_TABLE);
+	return (pmd_val(pmd) & ~PAGE_MASK) != PGD_TABLE || pmd_val(pmd) > high_memory;
 }
 
-int sun4c_pmd_present(pmd_t pmd)	{ return pmd_val(pmd) & _SUN4C_PAGE_VALID; }
+int sun4c_pmd_present(pmd_t pmd)	{ return pmd_val(pmd) & PGD_PRESENT; }
 int sun4c_pmd_inuse(pmd_t *pmdp)        { return 0; }
 void sun4c_pmd_clear(pmd_t *pmdp)	{ pmd_val(*pmdp) = 0; }
 void sun4c_pmd_reuse(pmd_t * pmdp)      { }
@@ -138,21 +87,16 @@
 int sun4c_pgd_none(pgd_t pgd)		{ return 0; }
 int sun4c_pgd_bad(pgd_t pgd)		{ return 0; }
 int sun4c_pgd_present(pgd_t pgd)	{ return 1; }
-int sun4c_pgd_inuse(pgd_t *pgdp)        { return mem_map[MAP_NR(pgdp)] != 1; }
+int sun4c_pgd_inuse(pgd_t *pgdp)        { return mem_map[MAP_NR(pgdp)].reserved; }
 void sun4c_pgd_clear(pgd_t * pgdp)	{ }
-void sun4c_pgd_reuse(pgd_t *pgdp)
-{
-  if (!(mem_map[MAP_NR(pgdp)] & MAP_PAGE_RESERVED))
-    mem_map[MAP_NR(pgdp)]++;
-}
 
 /*
  * The following only work if pte_present() is true.
  * Undefined behaviour if not..
  */
-int sun4c_pte_read(pte_t pte)		{ return pte_val(pte) & _SUN4C_PAGE_VALID; }
+int sun4c_pte_read(pte_t pte)		{ return !(pte_val(pte) & _SUN4C_PAGE_PRIV); }
 int sun4c_pte_write(pte_t pte)		{ return pte_val(pte) & _SUN4C_PAGE_WRITE; }
-int sun4c_pte_exec(pte_t pte)		{ return pte_val(pte) & _SUN4C_PAGE_VALID; }
+int sun4c_pte_exec(pte_t pte)		{ return !(pte_val(pte) & _SUN4C_PAGE_PRIV); }
 int sun4c_pte_dirty(pte_t pte)		{ return pte_val(pte) & _SUN4C_PAGE_DIRTY; }
 int sun4c_pte_young(pte_t pte)		{ return pte_val(pte) & _SUN4C_PAGE_REF; }
 int sun4c_pte_cow(pte_t pte)		{ return pte_val(pte) & _SUN4C_PAGE_COW; }
@@ -174,103 +118,287 @@
  * Conversion functions: convert a page and protection to a page entry,
  * and a page entry and page directory to the page they refer to.
  */
-pte_t
-sun4c_mk_pte(unsigned long page, pgprot_t pgprot)
+pte_t sun4c_mk_pte(unsigned long page, pgprot_t pgprot)
 {
-	pte_t pte;
+	return __pte(((page - PAGE_OFFSET) >> PAGE_SHIFT) | pgprot_val(pgprot));
+}
 
-	if(page & (~PAGE_MASK)) panic("sun4c_mk_pte() called with unaligned page");
-	page = sun4c_virt_to_phys(page);
-	pte_val(pte) = ((page>>PAGE_SHIFT)&_SUN4C_PFN_MASK);
-	pte_val(pte) |= (pgprot_val(pgprot) & _SUN4C_MMU_MASK);
-	return pte;
+pte_t sun4c_pte_modify(pte_t pte, pgprot_t newprot)
+{
+	return __pte((pte_val(pte) & _SUN4C_PAGE_CHG_MASK) | pgprot_val(newprot));
 }
 
-void
-sun4c_pgd_set(pgd_t * pgdp, pte_t * ptep)
+unsigned long sun4c_pte_page(pte_t pte)
 {
-	pgd_val(*pgdp) = (_SUN4C_PAGE_TABLE & _SUN4C_PGD_MMU_MASK);
-	pgd_val(*pgdp) |= (((((unsigned long) ptep)) >>
-			    (_SUN4C_PGD_PAGE_SHIFT)) & _SUN4C_PGD_PFN_MASK);
+	return (PAGE_OFFSET + ((pte_val(pte) & 0xffff) << (PAGE_SHIFT)));
 }
 
-pte_t
-sun4c_pte_modify(pte_t pte, pgprot_t newprot)
+unsigned long sun4c_pmd_page(pmd_t pmd)
 {
-	pte_val(pte) = (pte_val(pte) & _SUN4C_PAGE_CHG_MASK);
-	pte_val(pte) |= pgprot_val(newprot);
-	return pte;
+	return (pmd_val(pmd) & PAGE_MASK);
 }
 
 /* to find an entry in a page-table-directory */
-pgd_t *
-sun4c_pgd_offset(struct task_struct * tsk, unsigned long address)
+pgd_t *sun4c_pgd_offset(struct mm_struct * mm, unsigned long address)
 {
-	return ((pgd_t *) (tsk->tss.pgd_ptr)) +
-		(address >> SUN4C_PGDIR_SHIFT);
+	return mm->pgd + (address >> SUN4C_PGDIR_SHIFT);
 }
 
 /* Find an entry in the second-level page table.. */
-pmd_t *
-sun4c_pmd_offset(pgd_t * dir, unsigned long address)
+pmd_t *sun4c_pmd_offset(pgd_t * dir, unsigned long address)
 {
 	return (pmd_t *) dir;
 }
 
 /* Find an entry in the third-level page table.. */ 
-pte_t *
-sun4c_pte_offset(pmd_t * dir, unsigned long address)
+pte_t *sun4c_pte_offset(pmd_t * dir, unsigned long address)
 {
 	return (pte_t *) sun4c_pmd_page(*dir) +	((address >> PAGE_SHIFT) & (SUN4C_PTRS_PER_PTE - 1));
 }
 
-/*
- * Allocate and free page tables. The xxx_kernel() versions are
- * used to allocate a kernel page table - this turns on ASN bits
- * if any, and marks the page tables reserved.
+/* Here comes the sun4c mmu-tlb management engine.  It is here because
+ * some of the mid-level mm support needs to be able to lock down
+ * critical areas of kernel memory into the tlb.
  */
-void
-sun4c_pte_free_kernel(pte_t *pte)
+static inline void add_pseg_list(struct pseg_list *head, struct pseg_list *entry)
 {
-	mem_map[MAP_NR(pte)] = 1;
-	free_page((unsigned long) pte);
+	entry->next = head;
+	(entry->prev = head->prev)->next = entry;
+	head->prev = entry;
+}
+#define add_to_used_pseg_list(entry) add_pseg_list(&s4cpseg_used, entry)
+#define add_to_free_pseg_list(entry) add_pseg_list(&s4cpseg_free, entry)
+#define add_to_locked_pseg_list(entry) add_pseg_list(&s4cpseg_locked, entry)
+
+static inline void remove_pseg_list(struct pseg_list *entry)
+{
+	entry->next->prev = entry->prev;
+	entry->prev->next = entry->next;
+}
+
+static inline void add_pseg_ctxlist(struct pseg_list *entry, int ctx)
+{
+	struct pseg_list *head = &s4cpseg_per_context[ctx];
+
+	entry->ctx_next = head;
+	(entry->ctx_prev = head->ctx_prev)->ctx_next = entry;
+	head->ctx_prev = entry;
+	pseg_count_per_context[ctx]++;
 }
 
-static inline void
-sun4c_pmd_set(pmd_t * pmdp, pte_t * ptep)
+static inline void remove_pseg_ctxlist(struct pseg_list *entry, int ctx)
 {
-	pmd_val(*pmdp) = (_SUN4C_PAGE_TABLE & _SUN4C_PGD_MMU_MASK);
-	pmd_val(*pmdp) |= ((((unsigned long) ptep) >> (_SUN4C_PGD_PAGE_SHIFT)) & _SUN4C_PGD_PFN_MASK);
+	entry->ctx_next->ctx_prev = entry->ctx_prev;
+	entry->ctx_prev->ctx_next = entry->ctx_next;
+	pseg_count_per_context[ctx]--;
 }
 
+static inline void sun4c_init_pseg_lists(void)
+{
+	int i;
+
+	s4cpseg_free.prev = s4cpseg_free.next = &s4cpseg_free;
+	s4cpseg_used.prev = s4cpseg_used.next = &s4cpseg_used;
+	s4cpseg_locked.prev = s4cpseg_locked.next = &s4cpseg_locked;
+	for(i = 0; i < num_contexts; i++) {
+		s4cpseg_per_context[i].ctx_prev = s4cpseg_per_context[i].ctx_next =
+			&s4cpseg_per_context[i];
+	}
+	for(i = 0; i <= invalid_segment; i++) {
+		s4cpseg_pool[i].vaddr = 0;
+		s4cpseg_pool[i].context = 0;
+		s4cpseg_pool[i].ref_cnt = 0;
+		s4cpseg_pool[i].hardlock = 0;
+		s4cpseg_pool[i].pseg = i;
+	}
+	s4cpseg_pool[invalid_segment].hardlock = 1;
+}
+
+static inline void sun4c_distribute_kernel_mapping(unsigned long address,
+						   unsigned char pseg)
+{
+	unsigned int flags;
+	int ctx, save_ctx;
+
+	save_flags(flags); cli();
+	save_ctx = get_context();
+	flush_user_windows();
+	for(ctx = 0; ctx < num_contexts; ctx++) {
+		set_context(ctx);
+		put_segmap(address, pseg);
+	}
+	set_context(save_ctx);
+	restore_flags(flags);
+}
 
-pte_t *
-sun4c_pte_alloc_kernel(pmd_t *pmd, unsigned long address)
+static inline void sun4c_delete_kernel_mapping(unsigned long address)
 {
-	pte_t *page;
+	unsigned int flags;
+	int ctx, save_ctx;
 
+	save_flags(flags); cli();
+	save_ctx = get_context();
+	flush_user_windows();
 
+	/* Flush only needed in one context for kernel mappings. */
+	sun4c_flush_segment(address);
+	for(ctx = 0; ctx < num_contexts; ctx++) {
+		set_context(ctx);
+		put_segmap(address, invalid_segment);
+	}
+	set_context(save_ctx);
+	restore_flags(flags);
+}
+
+/* NOTE: You can only lock kernel tlb entries, attempts to lock
+ *       pages in user vm will bolix the entire system.
+ */
+static inline void sun4c_lock_tlb_entry(unsigned long address)
+{
+	unsigned long flags;
+	unsigned char pseg;
+
+	save_flags(flags); cli();
+	/* Fault it in. */
+	__asm__ __volatile__("ldub [%0], %%g0\n\t" : : "r" (address));
+	address &= SUN4C_REAL_PGDIR_MASK;
+	pseg = get_segmap(address);
+	if(address < KERNBASE)
+		panic("locking user address space into tlb!");
+	if(pseg == invalid_segment)
+		panic("cannot lock kernel tlb entry...");
+	if(!s4cpseg_pool[pseg].ref_cnt++ && !s4cpseg_pool[pseg].hardlock) {
+		/* Move from used to locked list. */
+		remove_pseg_list(&s4cpseg_pool[pseg]);
+		add_to_locked_pseg_list(&s4cpseg_pool[pseg]);
+	}
+	restore_flags(flags);
+}
+
+static inline void sun4c_unlock_tlb_entry(unsigned long address)
+{
+	unsigned long flags;
+	struct pseg_list *psegp;
+	unsigned char pseg;
+
+	save_flags(flags); cli();
+	address &= SUN4C_REAL_PGDIR_MASK;
+	pseg = get_segmap(address);
+	if(address < KERNBASE)
+		panic("unlocking user tlb entry!");
+	if(pseg == invalid_segment)
+		panic("unlocking non-locked kernel tlb entry...");
+	psegp = &s4cpseg_pool[pseg];
+	if(!--psegp->ref_cnt && !psegp->hardlock) {
+		/* Move from locked list to used list. */
+		remove_pseg_list(psegp);
+		add_to_used_pseg_list(psegp);
+	}
+	restore_flags(flags);
+}
+
+/* Anyone who calls this must turn _all_ interrupts off and flush
+ * any necessary user windows beforehand.
+ */
+static inline void sun4c_unload_context_from_tlb(unsigned char ctx)
+{
+	struct pseg_list *psegp, *pnextp;
+
+	if(pseg_count_per_context[ctx]) {
+		sun4c_flush_context(); /* Most efficient */
+		psegp = s4cpseg_per_context[ctx].ctx_next;
+		while(psegp != &s4cpseg_per_context[ctx]) {
+			pnextp = psegp->ctx_next;
+			if(psegp->vaddr >= KERNBASE)
+				panic("Unloading kernel from tlb, not good.");
+			put_segmap(psegp->vaddr, invalid_segment);
+			remove_pseg_ctxlist(psegp, ctx);
+			remove_pseg_list(psegp);
+			add_to_free_pseg_list(psegp);
+			psegp = pnextp;
+		}
+		if(pseg_count_per_context[ctx])
+			panic("pseg_count_per_context inconsistant after "
+			      "invalidate.");
+	}
+}
+
+/* This page must be a page in user vma... again all IRQ's gotta be off. */
+static inline void sun4c_unload_page_from_tlb(unsigned long addr,
+					      struct task_struct *tsk)
+{
+	unsigned char save_ctx;
+
+	if(tsk->tss.context != -1) {
+		save_ctx = get_context();
+		flush_user_windows();
+		set_context(tsk->tss.context);
+		sun4c_flush_page(addr);
+		put_pte(addr, 0);
+		set_context(save_ctx);
+	}
+}
+
+/* NOTE: When we have finer grained invalidate()'s (RSN) this
+ *       whole scheme will be much more efficient and need to
+ *       be re-written.  Also note that this routine only
+ *       unloads user page translations, this may need to
+ *       be changed at some point.
+ */
+void sun4c_invalidate(void)
+{
+	int orig_ctx, cur_ctx, flags;
+
+	save_flags(flags); cli();
+	flush_user_windows();
+	orig_ctx = get_context();
+	for(cur_ctx = 0; cur_ctx < num_contexts; cur_ctx++) {
+		set_context(cur_ctx);
+		sun4c_unload_context_from_tlb(cur_ctx);
+	}
+	set_context(orig_ctx);
+	restore_flags(flags);
+}
+
+/* We're only updating software tables on the sun4c. */
+void sun4c_set_pte(pte_t *ptep, pte_t pteval)
+{
+	*ptep = pteval;
+}
+
+/* Now back to the mid-level interface code:
+ *
+ * Allocate and free page tables. The xxx_kernel() versions are
+ * used to allocate a kernel page table - this turns on ASN bits
+ * if any, and marks the page tables reserved.
+ */
+void sun4c_pte_free_kernel(pte_t *pte)
+{
+	mem_map[MAP_NR(pte)].reserved = 0;
+	free_page((unsigned long) pte);
+}
+
+pte_t *sun4c_pte_alloc_kernel(pmd_t *pmd, unsigned long address)
+{
 	address = (address >> PAGE_SHIFT) & (SUN4C_PTRS_PER_PTE - 1);
 	if (sun4c_pmd_none(*pmd)) {
-		/* New scheme, use a whole page */
-		page = (pte_t *) get_free_page(GFP_KERNEL);
+		pte_t *page = (pte_t *) get_free_page(GFP_KERNEL);
 		if (sun4c_pmd_none(*pmd)) {
 			if (page) {
-				sun4c_pmd_set(pmd, page);
-				mem_map[MAP_NR(page)] = MAP_PAGE_RESERVED;
+				pmd_val(*pmd) = PGD_TABLE | (unsigned long) page;
+				mem_map[MAP_NR(page)].reserved = 1;
 				return page + address;
 			}
-			sun4c_pmd_set(pmd, (pte_t *) BAD_PAGETABLE);
+			pmd_val(*pmd) = PGD_TABLE | (unsigned long) BAD_PAGETABLE;
 			return NULL;
 		}
 		free_page((unsigned long) page);
 	}
 	if (sun4c_pmd_bad(*pmd)) {
 		printk("Bad pmd in pte_alloc_kernel: %08lx\n", pmd_val(*pmd));
-		sun4c_pmd_set(pmd, (pte_t *) BAD_PAGETABLE);
+		pmd_val(*pmd) = PGD_TABLE | (unsigned long) BAD_PAGETABLE;
 		return NULL;
 	}
-
 	return (pte_t *) sun4c_pmd_page(*pmd) + address;
 }
 
@@ -278,49 +406,41 @@
  * allocating and freeing a pmd is trivial: the 1-entry pmd is
  * inside the pgd, so has no extra memory associated with it.
  */
-void
-sun4c_pmd_free_kernel(pmd_t *pmd)
+void sun4c_pmd_free_kernel(pmd_t *pmd)
 {
-	return;
+	pmd_val(*pmd) = 0;
 }
 
-pmd_t *
-sun4c_pmd_alloc_kernel(pgd_t *pgd, unsigned long address)
+pmd_t *sun4c_pmd_alloc_kernel(pgd_t *pgd, unsigned long address)
 {
 	return (pmd_t *) pgd;
 }
 
-void
-sun4c_pte_free(pte_t *pte)
+void sun4c_pte_free(pte_t *pte)
 {
 	free_page((unsigned long) pte);
 }
 
-pte_t *
-sun4c_pte_alloc(pmd_t * pmd, unsigned long address)
+pte_t *sun4c_pte_alloc(pmd_t * pmd, unsigned long address)
 {
-	pte_t *page;
-
 	address = (address >> PAGE_SHIFT) & (SUN4C_PTRS_PER_PTE - 1);
 	if (sun4c_pmd_none(*pmd)) {
-		page = (pte_t *) get_free_page(GFP_KERNEL);
+		pte_t *page = (pte_t *) get_free_page(GFP_KERNEL);
 		if (sun4c_pmd_none(*pmd)) {
 			if (page) {
-				sun4c_pmd_set(pmd, page);
+				pmd_val(*pmd) = PGD_TABLE | (unsigned long) page;
 				return page + address;
 			}
-			sun4c_pmd_set(pmd, (pte_t *) BAD_PAGETABLE);
+			pmd_val(*pmd) = PGD_TABLE | (unsigned long) BAD_PAGETABLE;
 			return NULL;
 		}
 		free_page((unsigned long) page);
 	}
 	if (sun4c_pmd_bad(*pmd)) {
 		printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd));
-		sun4c_pmd_set(pmd, (pte_t *) BAD_PAGETABLE);
-		halt();
+		pmd_val(*pmd) = PGD_TABLE | (unsigned long) BAD_PAGETABLE;
 		return NULL;
 	}
-
 	return (pte_t *) sun4c_pmd_page(*pmd) + address;
 }
 
@@ -328,291 +448,610 @@
  * allocating and freeing a pmd is trivial: the 1-entry pmd is
  * inside the pgd, so has no extra memory associated with it.
  */
-void 
-sun4c_pmd_free(pmd_t * pmd)
+void sun4c_pmd_free(pmd_t * pmd)
 {
-	return;
+	pmd_val(*pmd) = 0;
 }
 
-pmd_t *
-sun4c_pmd_alloc(pgd_t * pgd, unsigned long address)
+pmd_t *sun4c_pmd_alloc(pgd_t * pgd, unsigned long address)
 {
 	return (pmd_t *) pgd;
 }
 
-/* This now works, as both our pgd's and pte's have 1024 entries. */
-void
-sun4c_pgd_free(pgd_t *pgd)
+void sun4c_pgd_free(pgd_t *pgd)
 {
 	free_page((unsigned long) pgd);
+	sun4c_unlock_tlb_entry((unsigned long) pgd);
 }
 
-/* A page directory on the sun4c needs 64k, thus we request an order of
- * four.  We must also clear it by hand, very inefficient.
- */
-
-pgd_t *
-sun4c_pgd_alloc(void)
+pgd_t *sun4c_pgd_alloc(void)
 {
-	return (pgd_t *) get_free_page(GFP_KERNEL);
+	unsigned long new_pgd = get_free_page(GFP_KERNEL);
+	sun4c_lock_tlb_entry(new_pgd);
+	return (pgd_t *) new_pgd;
 }
 
-void
-sun4c_invalidate(void)
+/* Jumping to and fro different contexts, the modifying of the pseg lists
+ * must be atomic during the switch, or else...
+ */
+void sun4c_switch_to_context(void *new_task)
 {
-	flush_vac_context();
+	struct task_struct *tsk = (struct task_struct *) new_task;
+	struct task_struct *old_tsk;
+	struct ctx_list *ctxp;
+	unsigned long flags;
+	int ctx = tsk->tss.context;
+
+	/* Swapper can execute in any context, or this task
+	 * has already been allocated a piece of the mmu real-
+	 * estate.
+	 */
+	if(tsk->pid == 0 || ctx != -1)
+		return;
+	ctxp = ctx_free.next;
+	if(ctxp != &ctx_free) {
+		save_flags(flags); cli();
+		ctx = ctxp->ctx_number;
+		remove_from_ctx_list(ctxp);
+		add_to_used_ctxlist(ctxp);
+		tsk->tss.context = ctx;
+		ctxp->ctx_task = tsk;
+		restore_flags(flags);
+		return;
+	}
+	save_flags(flags); cli();
+	ctxp = ctx_used.prev;
+	/* Don't steal from current, thank you. */
+	if(ctxp->ctx_task == current)
+		ctxp = ctxp->prev;
+	if(ctxp == &ctx_used)
+		panic("out of contexts");
+	remove_from_ctx_list(ctxp);
+	old_tsk = ctxp->ctx_task;
+	old_tsk->tss.context = -1;
+	ctxp->ctx_task = tsk;
+	tsk->tss.context = ctxp->ctx_number;
+	add_to_used_ctxlist(ctxp);
+	/* User windows flushed already by switch_to(p) macro. */
+	set_context(ctxp->ctx_number);
+	sun4c_unload_context_from_tlb(ctxp->ctx_number);
+	restore_flags(flags);
 }
 
-void
-sun4c_set_pte(pte_t *ptep, pte_t entry)
+/* Low level IO area allocation on the Sun4c MMU.  This function is called
+ * for each page of IO area you need.  Kernel code should not call this
+ * routine directly, use sparc_alloc_io() instead.
+ */
+void sun4c_mapioaddr(unsigned long physaddr, unsigned long virt_addr,
+		     int bus_type, int rdonly)
 {
-	/* for now... */
-	*ptep = entry;
+	unsigned long page_entry;
+
+	page_entry = ((physaddr >> PAGE_SHIFT) & 0xffff);
+	page_entry |= (_SUN4C_PAGE_VALID | _SUN4C_PAGE_WRITE |
+		       _SUN4C_PAGE_NOCACHE | _SUN4C_PAGE_IO);
+	if(rdonly)
+		page_entry &= (~_SUN4C_PAGE_WRITE);
+	sun4c_flush_page(virt_addr);
+	put_pte(virt_addr, page_entry);
 }
 
-void
-sun4c_switch_to_context(int context)
+/* These routines are used to lock down and unlock data transfer
+ * areas in the sun4c tlb.  If the pages need to be uncached the
+ * caller must do that himself.
+ */
+inline char *sun4c_lockarea(char *vaddr, unsigned long size)
 {
-	__asm__ __volatile__("stba %0, [%1] %2" : :
-			     "r" (context),
-			     "r" (AC_CONTEXT), "i" (ASI_CONTROL));
+	unsigned long flags;
+	unsigned long orig_addr = (unsigned long) vaddr;
+	unsigned long first_seg = (orig_addr & SUN4C_REAL_PGDIR_MASK);
+	unsigned long last_seg = ((orig_addr + size) & SUN4C_REAL_PGDIR_MASK);
+
+	save_flags(flags); cli();
+	for(; first_seg <= last_seg; first_seg += SUN4C_REAL_PGDIR_SIZE)
+		sun4c_lock_tlb_entry(first_seg);
 
-	return;
+	restore_flags(flags);
+	return vaddr;
 }
 
-int 
-sun4c_get_context(void)
+/* Note that when calling unlockarea you pass as 'vaddr' the address that
+ * was returned to you by lockarea for this pool above.
+ */
+inline void sun4c_unlockarea(char *vaddr, unsigned long size)
 {
-	register int ctx;
+	unsigned long flags;
+	unsigned long orig_addr = (unsigned long) vaddr;
+	unsigned long first_seg = (orig_addr & SUN4C_REAL_PGDIR_MASK);
+	unsigned long last_seg = ((orig_addr + size) & SUN4C_REAL_PGDIR_MASK);
 
-	__asm__ __volatile__("lduba [%1] %2, %0" :
-			     "=r" (ctx) :
-			     "r" (AC_CONTEXT), "i" (ASI_CONTROL));
+	save_flags(flags); cli();
+	for(; first_seg <= last_seg; first_seg += SUN4C_REAL_PGDIR_SIZE)
+		sun4c_unlock_tlb_entry(first_seg);
 
-	return ctx;
+	restore_flags(flags);
 }
 
-/* Low level IO area allocation on the Sun4c MMU.  This function is called
- * for each page of IO area you need.  Kernel code should not call this
- * routine directly, use sparc_alloc_io() instead.
- */
-void
-sun4c_mapioaddr(unsigned long physaddr, unsigned long virt_addr,
-		int bus_type, int rdonly)
+/* Getting and Releasing scsi dvma buffers. */
+char *sun4c_get_scsi_buffer(char *bufptr, unsigned long len)
 {
-  unsigned long page_entry;
+	unsigned long first_page = ((unsigned long) bufptr) & PAGE_MASK;
+	unsigned long last_page = (((unsigned long) bufptr) + len) & PAGE_MASK;
 
-  page_entry = ((physaddr >> PAGE_SHIFT) & _SUN4C_PFN_MASK);
+	/* First lock down the area. */
+	bufptr = sun4c_lockarea(bufptr, len);
 
-  if(!rdonly)
-	  page_entry |= (PTE_V | PTE_ACC | PTE_NC | PTE_IO);  /* kernel io addr */
-  else
-	  page_entry |= (PTE_V | PTE_P | PTE_NC | PTE_IO);  /* readonly io addr */
+	/* Uncache and flush all the pages. */
+	for(; first_page <= last_page; first_page += PAGE_SIZE) {
+		sun4c_flush_page(first_page);
+		put_pte(first_page, get_pte(first_page) | PTE_NC);
+	}
+	return bufptr;
+}
 
-  page_entry &= (~PTE_RESV);
+void sun4c_release_scsi_buffer(char *bufptr, unsigned long len)
+{
+	unsigned long first_page = ((unsigned long) bufptr) & PAGE_MASK;
+	unsigned long last_page = (((unsigned long) bufptr) + len) & PAGE_MASK;
 
-  /* Maybe have to do something with the bus_type on sun4c's? */
 
+	/* Recache all the pages. */
+	for(; first_page <= last_page; first_page += PAGE_SIZE)
+		put_pte(first_page, get_pte(first_page) & ~PTE_NC);
 
-  put_pte(virt_addr, page_entry);
-  return;
+	sun4c_unlockarea(bufptr, len);
 }
 
-/* Paging initialization on the Sun4c. */
-extern unsigned long free_area_init(unsigned long, unsigned long);
-extern unsigned long eintstack, intstack;
-
-/* This code was soooo krufty, I have to rewrite this now! XXX
- * Ok, things are cleaning up.  I have now decided that it makes
- * a lot of sense to put the free page pool in upper ram right
- * after the kernel.  We map these free pages to be virtually
- * contiguous, that way we don't get so many reserved pages
- * during mem_init().  I think this will work out nicely.
- */
-extern unsigned long start;
+/* Code to fill the sun4c tlb during a fault.  Plus fault helper routine. */
+int sun4c_get_fault_info(unsigned long *address, unsigned long *error_code,
+			 unsigned long from_user)
+{
+	unsigned long faddr, fstatus, new_code;
 
-static unsigned long mempool;  /* This allows us to work with elf bootloaders */
+	faddr = sun4c_get_synchronous_address();
+	*address = faddr;
+	if(faddr >= 0x20000000 && faddr < 0xe0000000) {
+		printk("SUN4C: Fault in vm hole at %08lx\n", faddr);
+		*error_code = from_user;
+		return 1;
+	}
+	fstatus = sun4c_get_synchronous_error();
+	if(fstatus & SUN4C_SYNC_BOLIXED)
+		panic("SUN4C: Unrecoverable fault type.");
+	new_code = 0;
+	if(fstatus & SUN4C_SYNC_PROT)
+		new_code |= FAULT_CODE_PROT;
+	if(fstatus & SUN4C_SYNC_BADWRITE)
+		new_code |= FAULT_CODE_WRITE;
+	*error_code = (new_code | from_user);
+	return 0;
+}
+
+static inline void sun4c_alloc_pseg(unsigned long address)
+{
+	struct pseg_list *psegp;
+	unsigned char cur_ctx = get_context();
+	int kernel_address = (address >= KERNBASE);
+	int user_address = !kernel_address;
+
+	psegp = s4cpseg_free.next;
+	if(psegp != &s4cpseg_free) {
+		remove_pseg_list(psegp);
+		add_to_used_pseg_list(psegp);
+		if(user_address)
+			add_pseg_ctxlist(psegp, cur_ctx);
+		psegp->vaddr = address;
+		psegp->context = cur_ctx;
+		/* No cache flush needed */
+		if(kernel_address)
+			sun4c_distribute_kernel_mapping(address, psegp->pseg);
+		else
+			put_segmap(address, psegp->pseg);
+		return;
+	}
+	psegp = s4cpseg_used.prev; /* Take last used list entry. */
+	if(psegp == &s4cpseg_used)
+		panic("Sun4c psegs have disappeared...");
+	if(psegp->vaddr >= KERNBASE) {
+		sun4c_delete_kernel_mapping(psegp->vaddr);
+	} else {
+		flush_user_windows();
+		set_context(psegp->context);
+		sun4c_flush_segment(psegp->vaddr);
+		put_segmap(psegp->vaddr, invalid_segment);
+		set_context(cur_ctx);
+	}
+	remove_pseg_list(psegp);
+	if(psegp->vaddr < KERNBASE)
+		remove_pseg_ctxlist(psegp, psegp->context);
+	psegp->vaddr = address;
+	psegp->context = cur_ctx;
+	if(kernel_address)
+		sun4c_distribute_kernel_mapping(address, psegp->pseg);
+	else
+		put_segmap(address, psegp->pseg);
+	add_to_used_pseg_list(psegp);
+	if(user_address)
+		add_pseg_ctxlist(psegp, cur_ctx);
+}
 
-unsigned long
-sun4c_paging_init(unsigned long start_mem, unsigned long end_mem)
+/*
+ * handle_mm_fault() gets here so that we can update our 'view'
+ * of a new address translation.  A lot of the time, mappings
+ * don't change and we are just 'working the tlb cache'.
+ */
+void sun4c_update_mmu_cache(struct vm_area_struct * vma,
+			    unsigned long address, pte_t pte)
 {
-	unsigned long addr, vaddr, kern_begin, kern_end;
-	unsigned long prom_begin, prom_end;
-	int phys_seg, i, min_prom_segmap;
-	pgd_t *pgdp;
-	pmd_t *pmdp;
-	pte_t *ptep;
+	unsigned long flags, segmap, segaddr, clean;
 
-	mempool = start_mem;
+	save_flags(flags); cli();
+	address &= PAGE_MASK;
+	segaddr = address & SUN4C_REAL_PGDIR_MASK;
+	segmap = get_segmap(segaddr);
+	if(segmap == invalid_segment) {
+		sun4c_alloc_pseg(segaddr);
+		/* XXX make segmap freeing routines do this. XXX */
+		for(clean = segaddr; clean < (segaddr + SUN4C_REAL_PGDIR_SIZE);
+		    clean += PAGE_SIZE)
+			put_pte(clean, 0);
+	}
 
-	/* 127 on most sun4c's, 255 on SS2 and IPX. */
-	invalid_segment = (num_segmaps - 1);
+	/* If this is a user fault, only load the one pte so that
+	 * the kernel's ref/mod bits accurately reflect what is
+	 * in the tlb.  handle_pte_fault() causes this to work.
+	 */
+	if(address < TASK_SIZE)
+		put_pte(address, pte_val(pte));
+	else {
+		/* We have a kernel fault here, load entire segment. */
+		pgd_t *pgdp;
+		pte_t *ptable;
+		int pnum = 64;
+
+		pgdp = sun4c_pgd_offset(&init_mm, segaddr);
+		ptable = sun4c_pte_offset((pmd_t *)pgdp, segaddr);
+		while(pnum--) {
+			put_pte(segaddr, pte_val(*ptable++));
+			segaddr += PAGE_SIZE;
+		};
+	}
+	restore_flags(flags);
+}
 
-	memset(swapper_pg_dir, 0, PAGE_SIZE);
-	memset(pg0, 0, PAGE_SIZE);
-	/* Delete low mapping of the kernel and sanitize invalid segmap. */
-	for(vaddr=0; vaddr<(4*1024*1024); vaddr+=SUN4C_REAL_PGDIR_SIZE) 
-		put_segmap(vaddr, invalid_segment);
-	for(vaddr=0; vaddr<(256*1024); vaddr+=PAGE_SIZE) put_pte(vaddr, 0);
-
-	/* Initialize phys_seg_map[] */
-	for(i=0; i<num_segmaps; i++) phys_seg_map[i] = PSEG_AVL;
-	for(i=num_segmaps; i<PSEG_ENTRIES; i++) phys_seg_map[i] = PSEG_RSV;
+/* Paging initialization on the Sun4c. */
+static inline void sun4c_free_all_nonlocked_psegs(void)
+{
+	struct pseg_list *plp;
+	int i;
 
-	kern_begin = KERNBASE;
-	kern_end = ((unsigned long) &end);
-	prom_begin = LINUX_OPPROM_BEGVM;
-	prom_end = LINUX_OPPROM_ENDVM;
+	for(i=0; i < invalid_segment; i++)
+		if(!s4cpseg_pool[i].hardlock)
+			add_to_free_pseg_list(&s4cpseg_pool[i]);
+	/* Now for every free pseg, make all the ptes invalid. */
+	plp = s4cpseg_free.next;
+	while(plp != &s4cpseg_free) {
+		put_segmap(0x0, plp->pseg);
+		for(i=0; i<64; i++)
+			put_pte((i * PAGE_SIZE), 0x0);
+		plp = plp->next;
+	}
+	put_segmap(0x0, invalid_segment);
+}
 
-	/* Set up swapper_pg_dir based upon three things:
-	 * 1) Where the kernel lives (KERNBASE)
-	 * 2) Where the PROM lives (PROM_BEGVM -> PROM_ENDVM)
-	 *    This is cheese, should do it dynamically XXX
-	 * 3) Where the valid physical pages are (sp_banks[])
-	 *    This is done first.
-	 *
-	 * I'm trying to concentrate this into one big loop and localize
-	 * the logic because it is so messy to do it in seperate loop
-	 * stages.  If anyone else has better ideas, let me know.
-	 */
+static inline struct pseg_list *sun4c_alloc_pseg_from_free_list(void)
+{
+	struct pseg_list *psegp;
 
-	if(sp_banks[0].base_addr != 0)
-		panic("sun4c_paging_init: First physical address in first bank is not zero!\n");
-	/* First, linearly map all physical RAM to the equivalent virtual pages.
-	 * Then, we invalidate everything the kernel uses by either invalidating
-	 * the entire segmep (if the whole segment is used by the kernel) or
-	 * just invalidating the relevant pte's.
-	 */
+	psegp = s4cpseg_free.next;
+	if(psegp != &s4cpseg_free) {
+		remove_pseg_list(psegp);
+		return psegp;
+	}
+	return 0;
+}
 
-	for(vaddr = KERNBASE; vaddr < end_mem; vaddr+=PAGE_SIZE) {
-		pgdp = sun4c_pgd_offset(current, vaddr);
-		pmdp = sun4c_pmd_offset(pgdp, vaddr);
-		if(sun4c_pmd_none(*pmdp)) {
-			pgd_set(pgdp, (pte_t *) mempool);
-			mempool += PAGE_SIZE;
+static inline void sun4c_init_lock_area(unsigned long start_addr,
+					unsigned long end_addr)
+{
+	struct pseg_list *psegp;
+	unsigned long a;
+	int ctx;
+
+	for(a = start_addr; a < end_addr; a += SUN4C_REAL_PGDIR_SIZE) {
+		psegp = sun4c_alloc_pseg_from_free_list();
+		if(!psegp) {
+			prom_printf("whoops...");
+			prom_halt();
 		}
-		ptep = sun4c_pte_offset(pmdp, vaddr);
-		*ptep = sun4c_mk_pte(vaddr, SUN4C_PAGE_KERNEL);
+		for(ctx=0;ctx<num_contexts;ctx++)
+			prom_putsegment(ctx,a,psegp->pseg);
+		add_to_locked_pseg_list(psegp);
+		psegp->hardlock = 1;
 	}
+}
 
-	/* Now map the kernel, and mark the segmaps as PSEG_KERN.
+static inline void sun4c_check_for_ss2_cache_bug(void)
+{
+	extern unsigned long start;
+
+	/* Well we've now got a problem, on the SS2 a cache bug
+	 * causes line entries to get severely corrupted if the
+	 * trap table is able to be cached.  A sane and simple
+	 * workaround, at least for now, is to mark the trap
+	 * table page as uncacheable.
 	 *
-	 * NOTE: The first address of the upper kernel mapping must be
-	 *       segment aligned.
+	 * XXX Investigate other possible workarounds and see
+	 * XXX if they help performance enough to warrant using
+	 * XXX them.                      -- 8/6/95 davem
 	 */
-	if(kern_begin & (~SUN4C_REAL_PGDIR_MASK)) {
-		panic("paging_init() Kernel not segmap aligned, halting...");
+	if(idprom->id_machtype == (SM_SUN4C | SM_4C_SS2)) {
+		/* Whee.. */
+		printk("SS2 cache bug detected, uncaching trap table page\n");
+		sun4c_flush_page((unsigned int) &start);
+		put_pte(((unsigned long) &start),
+			(get_pte((unsigned long) &start) | PTE_NC));
 	}
+}
 
-	/* Mark the segmaps so that our phys_seg allocator doesn't try to
-	 * use them for TLB misses.
-	 */
-	for(addr=kern_begin; addr < kern_end; addr += SUN4C_REAL_PGDIR_SIZE) {
-		if(get_segmap(addr) == invalid_segment) {
-			panic("paging_init() AIEEE, Kernel has invalid mapping, halting...");
+extern unsigned long free_area_init(unsigned long, unsigned long);
+
+/* Whee, this is now *ultra* clean and more managable */
+extern unsigned long end;
+extern void probe_mmu(void);
+
+unsigned long sun4c_paging_init(unsigned long start_mem, unsigned long end_mem)
+{
+	unsigned long addr, vaddr, kern_begin, kern_end;
+	unsigned long prom_begin, prom_end, kadb_begin;
+	pgd_t *pgdp;
+	pte_t *pg_table;
+	int phys_seg, i, ctx;
+
+	start_mem = PAGE_ALIGN(start_mem);
+
+	probe_mmu();
+	invalid_segment = (num_segmaps - 1);
+	sun4c_init_pseg_lists();
+	for(kern_begin = KERNBASE;
+	    kern_begin < (unsigned long) &end;
+	    kern_begin += SUN4C_REAL_PGDIR_SIZE) {
+		unsigned char pseg = get_segmap(kern_begin);
+
+		s4cpseg_pool[pseg].hardlock=1;
+		for(ctx=0; ctx<num_contexts;ctx++)
+			prom_putsegment(ctx,kern_begin,pseg);
+	}
+	for(kern_begin = SUN4C_REAL_PGDIR_ALIGN((unsigned long) &end);
+	    kern_begin < KADB_DEBUGGER_BEGVM;
+	    kern_begin += SUN4C_REAL_PGDIR_SIZE)
+		for(ctx=0; ctx<num_contexts;ctx++)
+			prom_putsegment(ctx, kern_begin, invalid_segment);
+	for(prom_begin = KADB_DEBUGGER_BEGVM;
+	    prom_begin < LINUX_OPPROM_ENDVM;
+	    prom_begin += SUN4C_REAL_PGDIR_SIZE) {
+		unsigned long pseg = get_segmap(prom_begin);
+
+		if(pseg != invalid_segment) {
+			s4cpseg_pool[pseg].hardlock=1;
+			for(ctx=0; ctx<num_contexts; ctx++)
+				prom_putsegment(ctx,prom_begin,pseg);
 		}
-		phys_seg = get_segmap(addr);
-		phys_seg_map[phys_seg] = PSEG_KERNEL;
-		/* Map this segment in every context */
-		for(i=0; i<num_contexts; i++)
-			(*romvec->pv_setctxt)(i, (char *) addr, phys_seg);
-	}
-
-	for(addr=((unsigned long) (&empty_zero_page)) + PAGE_SIZE; 
-	    addr < ((unsigned long) (&etext)); addr += PAGE_SIZE)
-		put_pte(addr, (get_pte(addr) & (~(PTE_W | PTE_NC))));
-
-	/* Finally map the prom's address space.  Any segments that
-	 * are not the invalid segment are marked as PSEG_RESV so
-	 * they are never re-allocated.  This guarentees the PROM
-	 * a sane state if we have to return execution over to it.
-	 * Our kernel static tables make it look like nothing is
-	 * mapped in these segments, if we get a page fault for
-	 * a prom address either the user is gonna die or the kernel
-	 * is doing something *really* bad.
+	}
+	/* Clean the MMU of excess garbage... */
+	for(ctx=0; ctx<num_contexts;ctx++) {
+		set_context(ctx);
+		for(vaddr = 0; vaddr < 0x20000000;
+		    vaddr += SUN4C_REAL_PGDIR_SIZE)
+			put_segmap(vaddr,invalid_segment);
+		for(vaddr = 0xe0000000; vaddr < KERNBASE;
+		    vaddr += SUN4C_REAL_PGDIR_SIZE)
+			put_segmap(vaddr,invalid_segment);
+		for(vaddr = LINUX_OPPROM_ENDVM; vaddr != 0;
+		    vaddr += SUN4C_REAL_PGDIR_SIZE)
+			put_segmap(vaddr,invalid_segment);
+	}
+	set_context(0);
+	sun4c_free_all_nonlocked_psegs();
+	/* Lock I/O and DVMA areas for the system. */
+	sun4c_init_lock_area(IOBASE_VADDR, IOBASE_END);
+	sun4c_init_lock_area(DVMA_VADDR, DVMA_END);
+	/* Zero out swapper_pg_dir and pg0 */
+	memset(swapper_pg_dir, 0, PAGE_SIZE);
+	memset(pg0, 0, PAGE_SIZE);
+	/* This makes us Solaris boot-loader 'safe' */
+	pgd_val(swapper_pg_dir[KERNBASE>>SUN4C_PGDIR_SHIFT]) =
+		PGD_TABLE | (unsigned long) pg0;
+
+	/* Initialize swapper_pg_dir to map the kernel
+	 * addresses in high memory.  Note that as soon as we get past
+	 * the 4MB lower mapping and start using dynamic memory from
+	 * start_mem we can start faulting and this is ok since our
+	 * pseg free list and the lower 4MB of the kernel is mapped
+	 * properly in the software page tables.
 	 */
-	if(prom_begin & (~SUN4C_REAL_PGDIR_MASK)) {
-		panic("paging_init() Boot PROM not segmap aligned, halting...");
-		halt();
-	}
-
-	min_prom_segmap = 254;
-	for(addr=KADB_DEBUGGER_BEGVM; addr < prom_end; addr += SUN4C_REAL_PGDIR_SIZE) {
-		if(get_segmap(addr) == invalid_segment)
-			continue;
-		phys_seg = get_segmap(addr);
-		if(phys_seg < min_prom_segmap) min_prom_segmap = phys_seg;
-		phys_seg_map[phys_seg] = PSEG_RSV;
-		/* Make the prom pages unaccessible from userland.  However, we
-		 * don't touch debugger segmaps/ptes.
-		 */
-		if((addr>=LINUX_OPPROM_BEGVM) && (addr<LINUX_OPPROM_ENDVM))
-			for(vaddr=addr; vaddr < (addr+SUN4C_REAL_PGDIR_SIZE); vaddr+=PAGE_SIZE)
-				put_pte(vaddr, (get_pte(vaddr) | PTE_P));
-
-		/* Map this segment in every context */
-		for(i=0; i<num_contexts; i++)
-			(*romvec->pv_setctxt)(i, (char *) addr, phys_seg);
-	}
-
-	/* Finally, unmap kernel page zero. */
-	put_pte(0x0, 0x0);
-
-	/* Hard pin down the IO area segmaps */
-	phys_seg = (min_prom_segmap - 1);
-	for(addr = (IOBASE_VADDR + SUN4C_REAL_PGDIR_SIZE); addr < (IOBASE_VADDR + IOBASE_LEN);
-	    addr += SUN4C_REAL_PGDIR_SIZE) {
-		if(addr & (~SUN4C_REAL_PGDIR_MASK)) {
-			panic("paging_init() IO segment not aligned, halting...");
+	pgdp = swapper_pg_dir;
+	kern_end = PAGE_ALIGN(end_mem);
+	kern_begin = KERNBASE;
+	while(kern_begin < kern_end) {
+		unsigned long pte, tmp;
+
+		/* We only need _one_ mapping, the high address one. */
+		pg_table = (pte_t *) (PAGE_MASK & pgd_val(pgdp[KERNBASE>>SUN4C_PGDIR_SHIFT]));
+		if(!pg_table) {
+			pg_table = (pte_t *) start_mem;
+			start_mem += PAGE_SIZE;
+		}
+		pgd_val(pgdp[KERNBASE>>SUN4C_PGDIR_SHIFT]) =
+			PGD_TABLE | (unsigned long) pg_table;
+		pgdp++;
+		for(tmp = 0; tmp < SUN4C_PTRS_PER_PTE; tmp++, pg_table++) {
+			if(kern_begin < kern_end)
+				sun4c_set_pte(pg_table,
+					      mk_pte(kern_begin,
+						     SUN4C_PAGE_SHARED));
+			else
+				sun4c_pte_clear(pg_table);
+			pte = get_pte(kern_begin);
+			if(pte & _SUN4C_PAGE_VALID) {
+				pte &= ~(_SUN4C_PAGE_NOCACHE);
+				pte |= (_SUN4C_PAGE_PRIV | _SUN4C_PAGE_WRITE |
+					_SUN4C_PAGE_REF | _SUN4C_PAGE_DIRTY);
+				put_pte(kern_begin, pte);
+			}
+			kern_begin += PAGE_SIZE;
 		}
-		phys_seg_map[phys_seg] = PSEG_RSV; /* Don't touch */
-		put_segmap(addr, phys_seg--);
 	}
-	phys_seg_map[IOBASE_SUN4C_SEGMAP] = PSEG_RSV;
+	sun4c_check_for_ss2_cache_bug();
+	/* Fix kadb/prom permissions. */
+	kadb_begin = KADB_DEBUGGER_BEGVM;
+	prom_end = LINUX_OPPROM_ENDVM;
+	for(; kadb_begin < prom_end; kadb_begin += PAGE_SIZE) {
+		unsigned long pte = get_pte(kadb_begin);
+		if(pte & _SUN4C_PAGE_VALID)
+			put_pte(kadb_begin, (pte | _SUN4C_PAGE_PRIV));
+	}
+	/* Allocate the DVMA pages */
+	addr = DVMA_VADDR;
+	start_mem = PAGE_ALIGN(start_mem);
+	while(addr < DVMA_END) {
+		unsigned long dvmapte = start_mem - PAGE_OFFSET;
 
-	start_mem = PAGE_ALIGN(mempool);
+		start_mem += PAGE_SIZE;
+		dvmapte = ((dvmapte>>PAGE_SHIFT) & 0xffff);
+		dvmapte |= (_SUN4C_PAGE_VALID |
+			    _SUN4C_PAGE_WRITE |
+			    _SUN4C_PAGE_NOCACHE);
+		put_pte(addr, dvmapte);
+		addr += PAGE_SIZE;
+	}
+	/* Tell the user our allocations */
+	for(phys_seg=0, i=0; i<=invalid_segment; i++)
+		if(s4cpseg_pool[i].hardlock)
+			phys_seg++;
+	printk("SUN4C: Hard locked %d boot-up psegs\n", phys_seg);
+	/* Init the context pool and lists */
+	ctx_list_pool = (struct ctx_list *) start_mem;
+	start_mem += (num_contexts * sizeof(struct ctx_list));
+	for(ctx = 0; ctx < num_contexts; ctx++) {
+		struct ctx_list *clist;
+
+		clist = (ctx_list_pool + ctx);
+		clist->ctx_number = ctx;
+		clist->ctx_task = 0;
+	}
+	ctx_free.next = ctx_free.prev = &ctx_free;
+	ctx_used.next = ctx_used.prev = &ctx_used;
+	for(ctx = 0; ctx < num_contexts; ctx++)
+		add_to_free_ctxlist(ctx_list_pool + ctx);
+	start_mem = PAGE_ALIGN(start_mem);
 	start_mem = free_area_init(start_mem, end_mem);
 	start_mem = PAGE_ALIGN(start_mem);
-
-	/* That should be it. */
-	invalidate();
-
 	return start_mem;
 }
 
 /* Test the WP bit on the sun4c. */
-unsigned long
-sun4c_test_wp(unsigned long start_mem)
+void sun4c_test_wp(void)
 {
-	unsigned long addr, segmap;
-	unsigned long page_entry;
-
 	wp_works_ok = -1;
-	page_entry = pte_val(sun4c_mk_pte(PAGE_OFFSET, SUN4C_PAGE_READONLY));
-	put_pte((unsigned long) 0x0, page_entry);
 
 	/* Let it rip... */
+	put_pte((unsigned long) 0x0, (PTE_V | PTE_P));
 	__asm__ __volatile__("st %%g0, [0x0]\n\t": : :"memory");
 	put_pte((unsigned long) 0x0, 0x0);
 	if (wp_works_ok < 0)
 		wp_works_ok = 0;
+}
 
-	/* Make all kernet static segmaps PSEG_KERNEL. */
-	for(addr=PAGE_OFFSET; addr<start_mem; addr+=SUN4C_REAL_PGDIR_SIZE)
-		phys_seg_map[get_segmap(addr)]=PSEG_KERNEL;
-
-	/* Map all the segmaps not valid on this machine as reserved. */
-	for(segmap=invalid_segment; segmap<PSEG_ENTRIES; segmap++)
-		phys_seg_map[segmap]=PSEG_RSV;
+void sun4c_lock_entire_kernel(unsigned long start_mem)
+{
+	unsigned long addr = (unsigned long) &end;
 
-	return start_mem;
+	addr = (addr & SUN4C_REAL_PGDIR_MASK);
+	start_mem = SUN4C_REAL_PGDIR_ALIGN(start_mem);
+	while(addr < start_mem) {
+		int pseg;
+
+		sun4c_lock_tlb_entry(addr);
+		pseg = get_segmap(addr);
+		if(!s4cpseg_pool[pseg].hardlock) {
+			s4cpseg_pool[pseg].hardlock = 1;
+			remove_pseg_list(&s4cpseg_pool[pseg]);
+		}
+		addr += SUN4C_REAL_PGDIR_SIZE;
+	}
+}
+
+static void sun4c_fork_hook(void *vtask, unsigned long kthread_usp)
+{
+	struct task_struct *new_task = vtask;
+
+	/* These pages must not cause a fault when traps
+	 * are off (such as in a window spill/fill) so
+	 * lock them down for the life of the task.
+	 */
+	sun4c_lock_tlb_entry((unsigned long) new_task);
+	sun4c_lock_tlb_entry(new_task->kernel_stack_page);
+	if(kthread_usp)
+		sun4c_lock_tlb_entry(kthread_usp);
+}
+
+static void sun4c_release_hook(void *vtask)
+{
+	struct task_struct *old_task = vtask;
+	struct ctx_list *ctx_old;
+	struct pt_regs *regs;
+	unsigned char this_ctx = get_context();
+	unsigned long flags;
+
+	save_flags(flags); cli();
+	if(old_task == &init_task)
+		panic("AIEEE releasing swapper");
+	if(old_task->tss.context != -1) {
+
+		/* Clear from the mmu, all notions of this dead task. */
+		flush_user_windows();
+		set_context(old_task->tss.context);
+		sun4c_unload_context_from_tlb(old_task->tss.context);
+		set_context(this_ctx);
+
+		ctx_old = ctx_list_pool + old_task->tss.context;
+		remove_from_ctx_list(ctx_old);
+		add_to_free_ctxlist(ctx_old);
+		old_task->tss.context = -1;
+	}
+	regs = (struct pt_regs *) 
+		(((old_task->tss.ksp & ~0xfff)) + (0x1000 - TRACEREG_SZ));
+	if(regs->u_regs[UREG_FP] > KERNBASE)
+		sun4c_unlock_tlb_entry(regs->u_regs[UREG_FP] & PAGE_MASK);
+	sun4c_unlock_tlb_entry(old_task->kernel_stack_page);
+	sun4c_unlock_tlb_entry((unsigned long) old_task);
+	restore_flags(flags);
+	/* bye bye... */
 }
 
-/* Real work gets done here. */
+static void sun4c_flush_hook(void *vtask)
+{
+	struct task_struct *dead_task = vtask;
+
+	if(dead_task->tss.context != -1)
+		sun4c_flush_context();
+}
+
+static void sun4c_task_cacheflush(void *vtask)
+{
+	struct task_struct *flush_task = vtask;
+
+	if(flush_task->tss.context != -1)
+		sun4c_flush_context();
+}
+
+static void sun4c_exit_hook(void *vtask)
+{
+}
 
 /* Load up routines and constants for sun4c mmu */
-void
-ld_mmu_sun4c(void)
+void ld_mmu_sun4c(void)
 {
 	printk("Loading sun4c MMU routines\n");
 
@@ -645,7 +1084,6 @@
 
 	pte_page = sun4c_pte_page;
 	pmd_page = sun4c_pmd_page;
-	pgd_page = sun4c_pgd_page;
 
 	sparc_update_rootmmu_dir = sun4c_update_rootmmu_dir;
 
@@ -667,10 +1105,8 @@
 	pgd_present = sun4c_pgd_present;
 	pgd_inuse = sun4c_pgd_inuse;
 	pgd_clear = sun4c_pgd_clear;
-	pgd_reuse = sun4c_pgd_reuse;
 
 	mk_pte = sun4c_mk_pte;
-	pgd_set = sun4c_pgd_set;
 	pte_modify = sun4c_pte_modify;
 	pgd_offset = sun4c_pgd_offset;
 	pmd_offset = sun4c_pmd_offset;
@@ -704,6 +1140,20 @@
 	pte_mkdirty = sun4c_pte_mkdirty;
 	pte_mkyoung = sun4c_pte_mkyoung;
 	pte_mkcow = sun4c_pte_mkcow;
-
-	return;
+	get_fault_info = sun4c_get_fault_info;
+	update_mmu_cache = sun4c_update_mmu_cache;
+	mmu_exit_hook = sun4c_exit_hook;
+	mmu_fork_hook = sun4c_fork_hook;
+	mmu_release_hook = sun4c_release_hook;
+	mmu_flush_hook = sun4c_flush_hook;
+	mmu_task_cacheflush = sun4c_task_cacheflush;
+	mmu_lockarea = sun4c_lockarea;
+	mmu_unlockarea = sun4c_unlockarea;
+	mmu_get_scsi_buffer = sun4c_get_scsi_buffer;
+	mmu_release_scsi_buffer = sun4c_release_scsi_buffer;
+
+	/* These should _never_ get called with two level tables. */
+	pgd_set = 0;
+	pgd_reuse = 0;
+	pgd_page = 0;
 }
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/mm/sun4c_vac.c linux/arch/sparc/mm/sun4c_vac.c
--- v1.3.43/linux/arch/sparc/mm/sun4c_vac.c	Thu Jan  1 02:00:00 1970
+++ linux/arch/sparc/mm/sun4c_vac.c	Sat Nov 25 02:59:45 1995
@@ -0,0 +1,37 @@
+/* $Id: sun4c_vac.c,v 1.5 1995/11/25 00:59:43 davem Exp $
+ * vac.c:   Routines for flushing various amount of the Sparc VAC
+ *          (virtual address cache) on the sun4c.
+ *
+ * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#include <linux/kernel.h>
+
+#include <asm/asi.h>
+#include <asm/contregs.h>
+#include <asm/vac-ops.h>
+#include <asm/page.h>
+
+struct sun4c_vac_props sun4c_vacinfo;
+
+/* Invalidate the entire sun4c VAC, it must be off at this point */
+void
+sun4c_flush_all(void)
+{
+	unsigned long begin, end;
+
+	if(sun4c_vacinfo.on)
+		panic("SUN4C: AIEEE, trying to invalidate vac while"
+                      " it is on.");
+
+	/* Clear 'valid' bit in all cache line tags */
+	begin = AC_CACHETAGS;
+	end = (AC_CACHETAGS + sun4c_vacinfo.num_bytes);
+	while(begin < end) {
+		__asm__ __volatile__("sta %%g0, [%0] %1\n\t" : :
+				     "r" (begin), "i" (ASI_CONTROL));
+		begin += sun4c_vacinfo.linesize;
+	}
+	return;
+}
+
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/mm/vac-flush.c linux/arch/sparc/mm/vac-flush.c
--- v1.3.43/linux/arch/sparc/mm/vac-flush.c	Thu Feb  2 08:45:28 1995
+++ linux/arch/sparc/mm/vac-flush.c	Thu Jan  1 02:00:00 1970
@@ -1,94 +0,0 @@
-/* vac.c:   Routines for flushing various amount of the Sparc VAC
-            (virtual address cache).
-
-   Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
-*/
-
-#include <asm/vac-ops.h>
-#include <asm/page.h>
-
-/* Flush all VAC entries for the current context */
-
-extern int vac_do_hw_vac_flushes, vac_size, vac_linesize;
-extern int vac_entries_per_context, vac_entries_per_segment;
-extern int vac_entries_per_page;
-
-void
-flush_vac_context()
-{
-  register int entries_left, offset;
-  register char* address;
-
-  entries_left = vac_entries_per_context;
-  address = (char *) 0;
-
-  if(vac_do_hw_vac_flushes)
-    {
-      while(entries_left-- >=0)
-	{
-	  hw_flush_vac_context_entry(address);
-	  address += PAGE_SIZE;
-	}
-    }
-  else
-    {
-      offset = vac_linesize;
-      while(entries_left-- >=0)
-	{
-	  sw_flush_vac_context_entry(address);
-	  address += offset;
-	}
-    }
-}
-
-void
-flush_vac_segment(register unsigned int segment)
-{
-  register int entries_left, offset;
-  register char* address = (char *) 0;
-  
-  entries_left = vac_entries_per_segment;
-  __asm__ __volatile__("sll %0, 18, %1\n\t"
-		       "sra %1, 0x2, %1\n\t"
-		       : "=r" (segment) : "0" (address));
-
-  if(vac_do_hw_vac_flushes)
-    {
-      while(entries_left-- >=0)
-	{
-	  hw_flush_vac_segment_entry(address);
-	  address += PAGE_SIZE;
-	}
-    }
-  else
-    {
-      offset = vac_linesize;
-      while(entries_left-- >=0)
-	{
-	  sw_flush_vac_segment_entry(address);
-	  address += offset;
-	}
-    }
-}
-
-void
-flush_vac_page(register unsigned int addr)
-{
-  register int entries_left, offset;
-
-  if(vac_do_hw_vac_flushes)
-    {
-      hw_flush_vac_page_entry((unsigned long *) addr);
-    }
-  else
-    {
-      entries_left = vac_entries_per_page;
-      offset = vac_linesize;
-      while(entries_left-- >=0)
-	{
-	  sw_flush_vac_page_entry((unsigned long *) addr);
-	  addr += offset;
-	}
-    }
-}
-  
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/prom/Makefile linux/arch/sparc/prom/Makefile
--- v1.3.43/linux/arch/sparc/prom/Makefile	Tue Aug 15 20:39:00 1995
+++ linux/arch/sparc/prom/Makefile	Sat Nov 25 02:59:51 1995
@@ -1,4 +1,4 @@
-#
+# $Id: Makefile,v 1.5 1995/11/25 00:59:48 davem Exp $
 # Makefile for the Sun Boot PROM interface library under
 # Linux.
 #
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/prom/bootstr.c linux/arch/sparc/prom/bootstr.c
--- v1.3.43/linux/arch/sparc/prom/bootstr.c	Tue Jun 27 14:11:32 1995
+++ linux/arch/sparc/prom/bootstr.c	Sat Nov 25 02:59:54 1995
@@ -1,4 +1,5 @@
-/* bootstr.c:  Boot string/argument acquisition from the PROM.
+/* $Id: bootstr.c,v 1.3 1995/11/25 00:59:51 davem Exp $
+ * bootstr.c:  Boot string/argument acquisition from the PROM.
  *
  * Copyright(C) 1995 David S. Miller (davem@caip.rutgers.edu)
  */
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/prom/console.c linux/arch/sparc/prom/console.c
--- v1.3.43/linux/arch/sparc/prom/console.c	Tue Jun 27 14:11:32 1995
+++ linux/arch/sparc/prom/console.c	Sat Nov 25 02:59:56 1995
@@ -1,4 +1,5 @@
-/* console.c: Routines that deal with sending and receiving IO
+/* $Id: console.c,v 1.5 1995/11/25 00:59:54 davem Exp $
+ * console.c: Routines that deal with sending and receiving IO
  *            to/from the current console device using the PROM.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -6,6 +7,7 @@
 
 #include <asm/openprom.h>
 #include <asm/oplib.h>
+#include <linux/string.h>
 
 /* Non blocking get character from console input device, returns -1
  * if no input was taken.  This can be used for polling.
@@ -71,3 +73,53 @@
 	return;
 }
 
+/* Query for input device type */
+enum prom_input_device
+prom_query_input_device()
+{
+	switch(*romvec->pv_stdin) {
+	case PROMDEV_KBD:	return PROMDEV_IKBD;
+	case PROMDEV_TTYA:	return PROMDEV_ITTYA;
+	case PROMDEV_TTYB:	return PROMDEV_ITTYB;
+	default:
+		return PROMDEV_I_UNK;
+	};
+}
+
+/* Query for output device type */
+
+enum prom_output_device
+prom_query_output_device()
+{
+	int st_p;
+	char propb[ sizeof("display") ];
+	int propl;
+
+	switch(prom_vers) {
+	case PROM_V0:
+		switch(*romvec->pv_stdin) {
+		case PROMDEV_SCREEN:	return PROMDEV_OSCREEN;
+		case PROMDEV_TTYA:	return PROMDEV_OTTYA;
+		case PROMDEV_TTYB:	return PROMDEV_OTTYB;
+		};
+		break;
+	case PROM_V2:
+	case PROM_V3:
+	case PROM_P1275:
+		st_p = (*romvec->pv_v2devops.v2_inst2pkg)(*romvec->pv_v2bootargs.fd_stdout);
+		propl = prom_getproperty(st_p, "device_type", propb, sizeof(propb));
+		if (propl >= 0 && propl == sizeof("display") &&
+			strncmp("display", propb, sizeof("display")) == 0)
+		{
+			return PROMDEV_OSCREEN;
+		}
+		/* This works on SS-2 (an early OpenFirmware) still. */
+		/* XXX fix for serial cases at SS-5.                 */
+		switch(*romvec->pv_stdin) {
+		case PROMDEV_TTYA:	return PROMDEV_OTTYA;
+		case PROMDEV_TTYB:	return PROMDEV_OTTYB;
+		};
+		break;
+	};
+	return PROMDEV_O_UNK;
+}
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/prom/devmap.c linux/arch/sparc/prom/devmap.c
--- v1.3.43/linux/arch/sparc/prom/devmap.c	Tue Jun 27 14:11:32 1995
+++ linux/arch/sparc/prom/devmap.c	Sat Nov 25 02:59:58 1995
@@ -1,4 +1,5 @@
-/* promdevmap.c:  Map device/IO areas to virtual addresses.
+/* $Id: devmap.c,v 1.2 1995/11/25 00:59:56 davem Exp $
+ * promdevmap.c:  Map device/IO areas to virtual addresses.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  */
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/prom/devops.c linux/arch/sparc/prom/devops.c
--- v1.3.43/linux/arch/sparc/prom/devops.c	Tue Jun 27 14:11:32 1995
+++ linux/arch/sparc/prom/devops.c	Sat Nov 25 03:00:00 1995
@@ -1,4 +1,5 @@
-/* devops.c:  Device operations using the PROM.
+/* $Id: devops.c,v 1.3 1995/11/25 00:59:59 davem Exp $
+ * devops.c:  Device operations using the PROM.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  */
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/prom/init.c linux/arch/sparc/prom/init.c
--- v1.3.43/linux/arch/sparc/prom/init.c	Tue Jun 27 14:11:32 1995
+++ linux/arch/sparc/prom/init.c	Sat Nov 25 03:00:02 1995
@@ -1,9 +1,12 @@
-/* init.c:  Initialize internal variables used by the PROM
+/* $Id: init.c,v 1.6 1995/11/25 01:00:01 davem Exp $
+ * init.c:  Initialize internal variables used by the PROM
  *          library functions.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  */
 
+#include <linux/kernel.h>
+
 #include <asm/openprom.h>
 #include <asm/oplib.h>
 
@@ -25,15 +28,11 @@
 extern void prom_meminit(void);
 extern void prom_ranges_init(void);
 
-int
+void
 prom_init(struct linux_romvec *rp)
 {
-	if(!rp) return 1;
 	romvec = rp;
-	if(romvec->pv_magic_cookie != LINUX_OPPROM_MAGIC)
-		return 1;
 
-	/* Ok, we seem to have a sane romvec here. */
 	switch(romvec->pv_romvers) {
 	case 0:
 		prom_vers = PROM_V0;
@@ -47,12 +46,12 @@
 	case 4:
 		prom_vers = PROM_P1275;
 		prom_printf("PROMLIB: Sun IEEE Prom not supported yet\n");
-		return 1;
+		prom_halt();
 		break;
 	default:
 		prom_printf("PROMLIB: Bad PROM version %d\n",
 			    romvec->pv_romvers);
-		return 1;
+		prom_halt();
 		break;
 	};
 
@@ -62,18 +61,19 @@
 
 	prom_root_node = prom_getsibling(0);
 	if((prom_root_node == 0) || (prom_root_node == -1))
-		return 1;
+		prom_halt();
 
 	if((((unsigned long) prom_nodeops) == 0) || 
 	   (((unsigned long) prom_nodeops) == -1))
-		return 1;
+		prom_halt();
 
 	prom_meminit();
+
 	prom_ranges_init();
 
-	prom_printf("PROMLIB: Sun Boot Prom Version %d Revision %d\n",
-		    romvec->pv_romvers, prom_rev);
+	printk("PROMLIB: Sun Boot Prom Version %d Revision %d\n",
+	       romvec->pv_romvers, prom_rev);
 
 	/* Initialization successful. */
-	return 0;
+	return;
 }
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/prom/memory.c linux/arch/sparc/prom/memory.c
--- v1.3.43/linux/arch/sparc/prom/memory.c	Tue Jun 27 14:11:32 1995
+++ linux/arch/sparc/prom/memory.c	Sat Nov 25 03:00:04 1995
@@ -1,4 +1,5 @@
-/* memory.c: Prom routine for acquiring various bits of information
+/* $Id: memory.c,v 1.4 1995/11/25 01:00:02 davem Exp $
+ * memory.c: Prom routine for acquiring various bits of information
  *           about RAM on the machine, both virtual and physical.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/prom/misc.c linux/arch/sparc/prom/misc.c
--- v1.3.43/linux/arch/sparc/prom/misc.c	Tue Jun 27 14:11:32 1995
+++ linux/arch/sparc/prom/misc.c	Sat Nov 25 03:00:06 1995
@@ -1,4 +1,5 @@
-/* misc.c:  Miscellaneous prom functions that don't belong
+/* $Id: misc.c,v 1.3 1995/11/25 01:00:04 davem Exp $
+ * misc.c:  Miscellaneous prom functions that don't belong
  *          anywhere else.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/prom/mp.c linux/arch/sparc/prom/mp.c
--- v1.3.43/linux/arch/sparc/prom/mp.c	Tue Jun 27 14:11:32 1995
+++ linux/arch/sparc/prom/mp.c	Sat Nov 25 03:00:08 1995
@@ -1,4 +1,5 @@
-/* mp.c:  OpenBoot Prom Multiprocessor support routines.  Don't call
+/* $Id: mp.c,v 1.4 1995/11/25 01:00:06 davem Exp $
+ * mp.c:  OpenBoot Prom Multiprocessor support routines.  Don't call
  *        these on a UP or else you will halt and catch fire. ;)
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/prom/palloc.c linux/arch/sparc/prom/palloc.c
--- v1.3.43/linux/arch/sparc/prom/palloc.c	Tue Jun 27 14:11:32 1995
+++ linux/arch/sparc/prom/palloc.c	Sat Nov 25 03:00:10 1995
@@ -1,4 +1,5 @@
-/* palloc.c:  Memory allocation from the Sun PROM.
+/* $Id: palloc.c,v 1.3 1995/11/25 01:00:08 davem Exp $
+ * palloc.c:  Memory allocation from the Sun PROM.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  */
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/prom/printf.c linux/arch/sparc/prom/printf.c
--- v1.3.43/linux/arch/sparc/prom/printf.c	Tue Jun 27 14:11:32 1995
+++ linux/arch/sparc/prom/printf.c	Sat Nov 25 03:00:12 1995
@@ -1,4 +1,5 @@
-/* printf.c:  Internal prom library printf facility.
+/* $Id: printf.c,v 1.4 1995/11/25 01:00:10 davem Exp $
+ * printf.c:  Internal prom library printf facility.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  */
@@ -7,102 +8,32 @@
  * about or use it!  It's simple and smelly anyway....
  */
 
-#include <stdarg.h>
+#include <linux/kernel.h>
 
 #include <asm/openprom.h>
 #include <asm/oplib.h>
 
-char hexstring[] = "0123456789abcdef";
+static char ppbuf[1024];
 
 void
 prom_printf(char *fmt, ...)
 {
 	va_list args;
-	unsigned int ui_val;
-	int i_val, n_ctr;
-	char c_val;
-	char nstr_buf[32];
-	char *s_val;
-	
+	char ch, *bptr;
+	int i;
+
 	va_start(args, fmt);
-	while(*fmt) {
-		if(*fmt != '%') {
-			if(*fmt == '\n')
-				prom_putchar('\r');
-			prom_putchar(*fmt++);
-			continue;
-		}
-
-		fmt++;
-		if(!*fmt) break;
-		n_ctr = 0;
-		switch(*fmt) {
-		case 'c':
-			c_val = va_arg(args, char);
-			if(c_val == '\n')
-				prom_putchar('\r');
-			prom_putchar(c_val);
-			fmt++;
-			break;
-		case 's':
-			s_val = va_arg(args, char *);
-			while(*s_val != 0) {
-				prom_putchar(*s_val);
-				s_val++;
-			}
-			fmt++;
-			break;
-		case 'd':
-			/* Base 10 */
-			i_val = va_arg(args, int);
-			if(i_val==0x0)
-				prom_putchar('0');
-			else
-				while(i_val != 0x0) {
-					nstr_buf[n_ctr] = hexstring[i_val%0xa];
-					i_val = ((unsigned long)i_val) / (unsigned) 0xa;
-					n_ctr++;
-				};
-			while(--n_ctr >= 0)
-				prom_putchar(nstr_buf[n_ctr]);
-			fmt++;
-			break;
-		case 'x':
-			/* Base 16 */
-			ui_val = va_arg(args, unsigned int);
-			if(ui_val==0x0)
-				prom_putchar('0');
-			else
-				while(ui_val != 0x0) {
-					nstr_buf[n_ctr] = hexstring[ui_val%0x10];
-					ui_val = ((unsigned long) ui_val) / (unsigned) 0x10;
-					n_ctr++;
-				};
-			while(--n_ctr >= 0)
-				prom_putchar(nstr_buf[n_ctr]);
-			fmt++;
-			break;
-		case 'o':
-			/* Base 8 */
-			ui_val = va_arg(args, unsigned int);
-			if(ui_val==0x0)
-				prom_putchar('0');
-			else
-				while(ui_val != 0x0) {
-					nstr_buf[n_ctr] = hexstring[ui_val%0x8];
-					ui_val = ((unsigned long) ui_val) / (unsigned) 0x8;
-				};
-			while(--n_ctr >= 0)
-				prom_putchar(nstr_buf[n_ctr]);
-			fmt++;
-			break;
-		default:
-			/* Uh oh, something we can't handle... skip it */
-			fmt++;
-			break;
-		};
+	i = vsprintf(ppbuf, fmt, args);
+
+	bptr = ppbuf;
+
+	while((ch = *(bptr++)) != 0) {
+		if(ch == '\n')
+			prom_putchar('\r');
+
+		prom_putchar(ch);
 	}
 
-	/* We are done... */
+	va_end(args);
 	return;
 }
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/prom/ranges.c linux/arch/sparc/prom/ranges.c
--- v1.3.43/linux/arch/sparc/prom/ranges.c	Tue Jun 27 14:11:32 1995
+++ linux/arch/sparc/prom/ranges.c	Sat Nov 25 03:00:14 1995
@@ -1,4 +1,5 @@
-/* ranges.c: Handle ranges in newer proms for obio.
+/* $Id: ranges.c,v 1.4 1995/11/25 01:00:12 davem Exp $
+ * ranges.c: Handle ranges in newer proms for obio/sbus.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  */
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/prom/segment.c linux/arch/sparc/prom/segment.c
--- v1.3.43/linux/arch/sparc/prom/segment.c	Tue Jun 27 14:11:32 1995
+++ linux/arch/sparc/prom/segment.c	Sat Nov 25 03:00:16 1995
@@ -1,4 +1,5 @@
-/* segment.c:  Prom routine to map segments in other contexts before
+/* $Id: segment.c,v 1.2 1995/11/25 01:00:14 davem Exp $
+ * segment.c:  Prom routine to map segments in other contexts before
  *             a standalone is completely mapped.  This is for sun4 and
  *             sun4c architectures only.
  *
diff -u --recursive --new-file v1.3.43/linux/arch/sparc/prom/tree.c linux/arch/sparc/prom/tree.c
--- v1.3.43/linux/arch/sparc/prom/tree.c	Tue Jun 27 14:11:32 1995
+++ linux/arch/sparc/prom/tree.c	Sat Nov 25 03:00:18 1995
@@ -1,4 +1,5 @@
-/* tree.c: Basic device tree traversal/scanning for the Linux
+/* $Id: tree.c,v 1.6 1995/11/25 01:00:16 davem Exp $
+ * tree.c: Basic device tree traversal/scanning for the Linux
  *         prom library.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
diff -u --recursive --new-file v1.3.43/linux/drivers/block/README.ide linux/drivers/block/README.ide
--- v1.3.43/linux/drivers/block/README.ide	Tue Nov 21 13:22:06 1995
+++ linux/drivers/block/README.ide	Sat Nov 25 11:46:06 1995
@@ -34,8 +34,6 @@
 		- PCI support is automatic
 		- for VLB, use kernel command line option:   ide0=cmd640_vlb
 		- this support also enables the secondary i/f on most cards
-		- experimental interface timing parameter support
-NEW!	- experimental support for UMC 8672 interfaces
 NEW!	- support for secondary interface on the FGI/Holtek HT-6560B VLB i/f
 		- use kernel command line option:   ide1=ht6560
 NEW!	- experimental "fast" speed support for QD6580 interfaces
@@ -47,10 +45,7 @@
 NEW!	- transparent support for DiskManager 6.0x and "Dynamic Disk Overlay"
 	- works with Linux fdisk, LILO, loadlin, bootln, etc..
 NEW!	- mostly transparent support for EZ-Drive
-NEW!		- to use LILO with EZ, install LILO on the linux partition
-		  rather than on the master boot record, and then mark the
-		  linux partition as "bootable" or "active" using fdisk.
-		  (courtesy of Juha Laiho <jlaiho@ichaos.nullnet.fi>).
+		- LILO is incompatible (also harmless) with EZ-Drive
 NEW!	- ide-cd.c now compiles separate from ide.c
 NEW!	- Bus-Master DMA support for Intel PCI Triton chipset IDE interfaces
 		- for details, see comments at top of triton.c
@@ -471,62 +466,24 @@
 
 ================================================================================
 
- 1995 Nov 16 at 08:25  EST
- from:       'dwhysong@dolphin.physics.ucsb.edu' (BNR400)
+ from:       'delman@mipg.upenn.edu'
+ subject:    rz1000
 
-[I'm cc'ing this to Mark Lord: FYI, I've got at DTC2278S VLB EIDE
-controller with a Connor CFA850A as /dev/hda and a Maxtor 7213A as
-/dev/hdb using Linux 1.2.13 w/patches for assembly strcpy and the kswap
-patches. I'm getting strange behavior and an unstable system when I try to
-use 32 bit VLB data transfer to the interface card. However, hdparm
-reports that the Connor is extremely fast when I can get the 32 bit mode
-enabled using hdparm -c1 /dev/hd(a|b). However, if I don't do hdparm -c1
-on both /dev/hda and /dev/hdb, then when I run "hdparm -t /dev/hda" the
-disk subsystem locks up... the disk LED comes on and stays on, and no
-other programs are able to get disk access (I can switch VC's, but I can't
-get past the username prompt). I thought you should know about this. I'm
-not sure if it's a problem with the support for the DTC cards, or a
-peculiarity with my hardware configuration. I doubt that my hardware
-itself is flaky, though that's always a possibility.]
-
-On Wed, 15 Nov 1995, Michael Faurot wrote:
-
-> > The trick is setting BOTH drives to use the 32 bit interface.
->
-> Congrats on getting it going.  Those are some great transfer
-> rates.  I noticed you did switch on the unmasking.  Noticed any
-> problems with things under extreme load or with serial transfers?
-
-I've never had any problems which I could trace to interrupt unmasking.
-Of course, my system usually doesn't have a really heavy load, either.
-These numbers seem way too high for a disk with something like 3500 (?)
-RPM.
-
-Sleepy# hdparm -t /dev/hda
-
-/dev/hda:
- Timing buffer-cache reads:   32 MB in  2.24 seconds =14.29 MB/sec
- Timing buffered disk reads:  16 MB in  3.63 seconds = 4.41 MB/sec
- Estimating raw driver speed: 16 MB in  2.51 seconds = 6.37 MB/sec
-
-> Not sure I was much help to you, but I'm glad to hear you got it
-> working--and pretty impressivly at that. :-)
-
-Mmm, well, about that... I've found that my Connor drive (/dev/hda) is
-pretty fast when I have my system configured like this. I'm still not
-sure I trust the "hdparm -t"  results, though. However, when I try
-"hdparm -t /dev/hdb" (/dev/hdb is an older Maxtor 7213A) I have the same
-problem I had before with my disk subsystem locking up.
-
-I've tried just about every possible combination of flags in ide.c and
-hdparm, and I can't get decent performance out of this drive/controller
-combination without some kind of instability creeping in. I'm living with
-the situation now only because /dev/hdb is a DOS-only drive, and I don't
-need it under Linux. However, I don't really like the situation.
+Hi Mark! Looks like you managed to get the info from Intel to disable
+the read-ahead feature of the RZ1000. My encounter with
+Zeos (subsidiary of Micron which owns PCTech) has not been as
+successful --- one guy needs to ask his supervisors about NDA, another
+guy thinks that there is too much of a performance hit with read-ahead
+disabled.
+
+Did the following benchmark to see how true the claim is.
+With Linux 1.2.13, average of 10 "hdparm -t" in MB/s:
+
+                       hdparm -c0        hdparm -c1
+read-ahead enabled        4.28              4.25
+read-ahead disabled       3.58              4.30
 
--Dave
-dwhysong@physics.ucsb.edu
-
-(Why can't this stuff be simple? Plug the card in, and it works? Every
-hardware manufacturer has to have their own way of doing things...)
+Maybe -c1 should be the default for the RZ1000, or as a suggestion in
+the README for people with the RZ1000.
 
+Cheers, Delman.
diff -u --recursive --new-file v1.3.43/linux/drivers/block/cmd640.c linux/drivers/block/cmd640.c
--- v1.3.43/linux/drivers/block/cmd640.c	Tue Nov 21 13:22:06 1995
+++ linux/drivers/block/cmd640.c	Thu Jan  1 02:00:00 1970
@@ -1,444 +0,0 @@
-/*
- *  linux/drivers/block/cmd640.c	Version 0.01  Nov 16, 1995
- *
- *  Copyright (C) 1995  Linus Torvalds & author (see below)
- */
-
-/*
- *  Principal Author/Maintainer:  abramov@cecmow.enet.dec.com (Igor)
- *
- *  This file provides support for the advanced features and bugs
- *  of IDE interfaces using the CMD Technologies 0640 IDE interface chip.
- *
- *  Version 0.01	Initial version, hacked out of ide.c,
- *			and #include'd rather than compiled separately.
- *			This will get cleaned up in a subsequent release.
- */
-
-/* Interface to access cmd640x registers */
-static void (*put_cmd640_reg)(int key, int reg_no, int val);
-static byte (*get_cmd640_reg)(int key, int reg_no);
-
-enum { none, vlb, pci1, pci2 };
-static int	bus_type = none;
-static int	cmd640_chip_version;
-static int	cmd640_key;
-static byte	is_cmd640[MAX_HWIFS];
-
-/*
- * For some unknown reasons pcibios functions which read and write registers
- * do not work with cmd640. We use direct io instead.
- */
-
-/* PCI method 1 access */
-
-static void put_cmd640_reg_pci1(int key, int reg_no, int val)
-{
-	unsigned long flags;
-
-	save_flags(flags);
-	cli();
-	outl_p((reg_no & 0xfc) | key, 0xcf8);
-	outb_p(val, (reg_no & 3) + 0xcfc);
-	restore_flags(flags);
-}
-
-static byte get_cmd640_reg_pci1(int key, int reg_no)
-{
-	byte b;
-	unsigned long flags;
-
-	save_flags(flags);
-	cli();
-	outl_p((reg_no & 0xfc) | key, 0xcf8);
-	b = inb(0xcfc + (reg_no & 3));
-	restore_flags(flags);
-	return b;
-}
-
-/* PCI method 2 access (from CMD datasheet) */
-
-static void put_cmd640_reg_pci2(int key, int reg_no, int val)
-{
-	unsigned long flags;
-
-	save_flags(flags);
-	cli();
-	outb_p(0x10, 0xcf8);
-	outb_p(val, key + reg_no);
-	outb_p(0, 0xcf8);
-	restore_flags(flags);
-}
-
-static byte get_cmd640_reg_pci2(int key, int reg_no)
-{
-	byte b;
-	unsigned long flags;
-
-	save_flags(flags);
-	cli();
-	outb_p(0x10, 0xcf8);
-	b = inb(key + reg_no);
-	outb_p(0, 0xcf8);
-	restore_flags(flags);
-	return b;
-}
-
-/* VLB access */
-
-static void put_cmd640_reg_vlb(int key, int reg_no, int val)
-{
-	unsigned long flags;
-
-	save_flags(flags);
-	cli();
-	outb(reg_no, key + 8);
-	outb(val, key + 0xc);
-	restore_flags(flags);
-}
-
-static byte get_cmd640_reg_vlb(int key, int reg_no)
-{
-	byte b;
-	unsigned long flags;
-
-	save_flags(flags);
-	cli();
-	outb(reg_no, key + 8);
-	b = inb(key + 0xc);
-	restore_flags(flags);
-	return b;
-}
-
-/*
- * Probe for CMD640x -- pci method 1
- */
-
-static int probe_for_cmd640_pci1(void)
-{
-	long id;
-	int	k;
-
-	for (k = 0x80000000; k <= 0x8000f800; k += 0x800) {
-		outl(k, 0xcf8);
-		id = inl(0xcfc);
-		if (id != 0x06401095)
-			continue;
-		put_cmd640_reg = put_cmd640_reg_pci1;
-		get_cmd640_reg = get_cmd640_reg_pci1;
-		cmd640_key = k;
-		return 1;
-	}
-	return 0;
-}
-
-/*
- * Probe for CMD640x -- pci method 2
- */
-
-static int probe_for_cmd640_pci2(void)
-{
-	int i;
-	int v_id;
-	int d_id;
-
-	for (i = 0xc000; i <= 0xcf00; i += 0x100) {
-		outb(0x10, 0xcf8);
-		v_id = inw(i);
-		d_id = inw(i + 2);
-		outb(0, 0xcf8);
-		if (v_id != 0x1095 || d_id != 0x640)
-			continue;
-		put_cmd640_reg = put_cmd640_reg_pci2;
-		get_cmd640_reg = get_cmd640_reg_pci2;
-		cmd640_key = i;
-		return 1;
-	}
-	return 0;
-}
-
-/*
- * Probe for CMD640x -- vlb
- */
-
-static int probe_for_cmd640_vlb(void) {
-	byte b;
-
-	outb(0x50, 0x178);
-	b = inb(0x17c);
-	if (b == 0xff || b == 0 || (b & 0x20)) {
-		outb(0x50, 0xc78);
-		b = inb(0x7c);
-		if (b == 0xff || b == 0 || !(b & 0x20))
-			return 0;
-		cmd640_key = 0x70;
-	} else {
-		cmd640_key = 0x170;
-	}
-	put_cmd640_reg = put_cmd640_reg_vlb;
-	get_cmd640_reg = get_cmd640_reg_vlb;
-	return 1;
-}
-
-/*
- * Probe for Cmd640x and initialize it if found
- */
-
-int ide_probe_for_cmd640x(void)
-{
-	int i;
-
-	for (i = 0; i < MAX_HWIFS; i++)
-		is_cmd640[i] = 0;
-
-	if (probe_for_cmd640_pci1()) {
-		bus_type = pci1;
-	} else if (probe_for_cmd640_pci2()) {
-		bus_type = pci2;
-	} else if (cmd640_vlb && probe_for_cmd640_vlb()) {
-		/* May be remove cmd640_vlb at all, and probe in any case */
-		bus_type = vlb;
-	} else {
-		return 0;
-	}
-
-	/*
-	 * Undocumented magic. (There is no 0x5b port in specs)
-	 */
-
-	put_cmd640_reg(cmd640_key, 0x5b, 0xbd);
-	if (get_cmd640_reg(cmd640_key, 0x5b) != 0xbd) {
-		printk("ide: can't initialize cmd640 -- wrong value in 0x5b\n");
-		return 0;
-	}
-	put_cmd640_reg(cmd640_key, 0x5b, 0);
-
-	/*
-	 * Documented magic.
-	 */
-
-	cmd640_chip_version = get_cmd640_reg(cmd640_key, 0x50) & 3;
-	if (cmd640_chip_version == 0) {
-		printk ("ide: wrong CMD640 version -- 0\n");
-		return 0;
-	}
-
-	put_cmd640_reg(cmd640_key, 0x51, get_cmd640_reg(cmd640_key, 0x51) | 0xc8);
-	put_cmd640_reg(cmd640_key, 0x57, 0);
-	put_cmd640_reg(cmd640_key, 0x57, get_cmd640_reg(cmd640_key, 0x57) | 0x0c);
-
-	serialized = 1;
-
-	printk("ide: buggy CMD640 interface at ");
-	switch (bus_type) {
-		case vlb :
-			printk("local bus, port 0x%x", cmd640_key);
-			break;
-		case pci1:
-			printk("pci, (0x%x)", cmd640_key);
-			break;
-		case pci2:
-			printk("pci,(access method 2) (0x%x)", cmd640_key);
-			break;
-	}
-
-	is_cmd640[0] = is_cmd640[1] = 1;
-
-	/*
-	 * Reset interface timings
-	 */
-
-	put_cmd640_reg(cmd640_key, 0x58, 0);
-	put_cmd640_reg(cmd640_key, 0x52, 0);
-
-	printk("\n ... serialized, disabled read-ahead, secondary interface enabled\n");
-
-	return 1;
-}
-
-static int as_clocks(int a) {
-	switch (a & 0xf0) {
-		case 0 :	return 4;
-		case 0x40 :	return 2;
-		case 0x80 :	return 3;
-		case 0xc0 :	return 5;
-		default :	return -1;
-	}
-}
-
-/*
- * Tuning of drive parameters
- */
-
-static void cmd640_set_timing(int if_num, int dr_num, int r1, int r2) {
-	int  b_reg;
-	byte b;
-	int  r52;
-
-	b_reg = if_num ? 0x57 : dr_num ? 0x55 : 0x53;
-
-	if (if_num == 0) {
-		put_cmd640_reg(cmd640_key, b_reg, r1);
-		put_cmd640_reg(cmd640_key, b_reg + 1, r2);
-	} else {
-		b = get_cmd640_reg(cmd640_key, b_reg);
-		if ((b&1) == 0) {
-			put_cmd640_reg(cmd640_key, b_reg, r1);
-		} else {
-			if (as_clocks(b) < as_clocks(r1))
-				put_cmd640_reg(cmd640_key, b_reg, r1);
-		}
-		b = get_cmd640_reg(cmd640_key, b_reg + 1);
-		if (b == 0) {
-			put_cmd640_reg(cmd640_key, b_reg + 1, r2);
-		} else {
-			r52 = (b&0xf) < (r2&0xf) ? (r2&0xf) : (b&0xf);
-			r52 |= (b&0xf0) < (r2&0xf0) ? (r2&0xf0) : (b&0xf0);
-			put_cmd640_reg(cmd640_key, b_reg+1, r52);
-		}
-	}
-
-	b = get_cmd640_reg(cmd640_key, 0x52);
-	if (b == 0) {
-		put_cmd640_reg(cmd640_key, 0x52, r2);
-	} else {
-		r52 = (b&0xf) < (r2&0xf) ? (r2&0xf) : (b&0xf);
-		r52 |= (b&0xf0) < (r2&0xf0) ? (r2&0xf0) : (b&0xf0);
-		put_cmd640_reg(cmd640_key, 0x52, r52);
-	}
-}
-
-static int bus_speed = 33; /* MHz */
-
-struct pio_timing {
-	int	mc_time;	/* Minimal cycle time (ns) */
-	int	av_time;	/* Address valid to DIOR-/DIOW- setup (ns) */
-	int	ds_time;	/* DIOR data setup	(ns) */
-} pio_timings[6] = {
-	{ 70,	165,	600 },	/* PIO Mode 0 */
-	{ 50,	125,	383 },	/* PIO Mode 1 */
-	{ 30,	100,	240 },	/* PIO Mode 2 */
-	{ 30,	80,	180 },	/* PIO Mode 3 */
-	{ 25,	70,	125 },	/* PIO Mode 4 */
-	{ 20,	50,	100 }	/* PIO Mode ? */
-};
-
-struct drive_pio_info {
-	const char	*name;
-	int		pio;
-} drive_pios[] = {
-	{ "Maxtor 7131 AT", 1 },
-	{ "Maxtor 7171 AT", 1 },
-	{ "Maxtor 7213 AT", 1 },
-	{ "Maxtor 7245 AT", 1 },
-	{ "SAMSUNG SHD-3122A", 1 },
-	{ "QUANTUM ELS127A", 0 },
-	{ "QUANTUM LPS240A", 0 },
-	{ "QUANTUM LPS270A", 3 },
-	{ "QUANTUM LPS540A", 3 },
-	{ NULL,	0 }
-};
-
-static int known_drive_pio(char* name) {
-	struct drive_pio_info* pi;
-
-	for (pi = drive_pios; pi->name != NULL; pi++) {
-		if (strcmp(pi->name, name) == 0)
-			return pi->pio;
-	}
-	return -1;
-}
-
-static void cmd640_timings_to_regvals(int mc_time, int av_time, int ds_time,
-				int clock_time,
-				int* r1, int* r2)
-{
-	int a, b;
-
-	a = (mc_time + clock_time - 1)/clock_time;
-	if (a <= 2) *r1 = 0x40;
-	else if (a == 3) *r1 = 0x80;
-	else if (a == 4) *r1 = 0;
-	else *r1 = 0xc0;
-
-	a = (av_time + clock_time - 1)/clock_time;
-	if (a < 2)
-		a = 2;
-	b = (ds_time + clock_time - 1)/clock_time - a;
-	if (b < 2)
-		b = 2;
-	if (b > 0x11) {
-		a += b - 0x11;
-		b = 0x11;
-	}
-	if (a > 0xf)
-		a = 0;
-	if (cmd640_chip_version > 1)
-		b -= 1;
-	if (b > 0xf)
-		b = 0;
-	*r2 = (a << 4) | b;
-}
-
-static void set_pio_mode(int if_num, int drv_num, int mode_num) {
-	int p_base;
-	int i;
-
-	p_base = if_num ? 0x170 : 0x1f0;
-	outb(3, p_base + 1);
-	outb(mode_num | 8, p_base + 2);
-	outb((drv_num | 0xa) << 4, p_base + 6);
-	outb(0xef, p_base + 7);
-	for (i = 0; (i < 100) && (inb (p_base + 7) & 0x80); i++)
-		delay_10ms();
-}
-
-void cmd640_tune_drive(ide_drive_t* drive) {
-	int interface_number;
-	int drive_number;
-	int clock_time; /* ns */
-	int max_pio;
-	int mc_time, av_time, ds_time;
-	struct hd_driveid* id;
-	int r1, r2;
-
-	/*
-	 * Determine if drive is under cmd640 control
-	 */
-	interface_number = HWIF(drive) - ide_hwifs;
-	if (!is_cmd640[interface_number])
-		return;
-
-	drive_number = drive - HWIF(drive)->drives;
-	clock_time = 1000/bus_speed;
-	id = drive->id;
-	if ((max_pio = known_drive_pio(id->model)) != -1) {
-		mc_time = pio_timings[max_pio].mc_time;
-		av_time = pio_timings[max_pio].av_time;
-		ds_time = pio_timings[max_pio].ds_time;
-	} else {
-		max_pio = id->tPIO;
-		mc_time = pio_timings[max_pio].mc_time;
-		av_time = pio_timings[max_pio].av_time;
-		ds_time = pio_timings[max_pio].ds_time;
-		if (id->field_valid & 2) {
-			if ((id->capability & 8) && (id->eide_pio_modes & 7)) {
-				if (id->eide_pio_modes & 4) max_pio = 5;
-				else if (id->eide_pio_modes & 2) max_pio = 4;
-				else max_pio = 3;
-				ds_time = id->eide_pio_iordy;
-				mc_time = pio_timings[max_pio].mc_time;
-				av_time = pio_timings[max_pio].av_time;
-			} else {
-				ds_time = id->eide_pio;
-			}
-			if (ds_time == 0)
-				ds_time = pio_timings[max_pio].ds_time;
-		}
-	}
-	cmd640_timings_to_regvals(mc_time, av_time, ds_time, clock_time,
-				&r1, &r2);
-	set_pio_mode(interface_number, drive_number, max_pio);
-	cmd640_set_timing(interface_number, drive_number, r1, r2);
-	printk ("Mode and Timing set to PIO%d (0x%x 0x%x)\n", max_pio, r1, r2);
-}
diff -u --recursive --new-file v1.3.43/linux/drivers/block/ide-cd.c linux/drivers/block/ide-cd.c
--- v1.3.43/linux/drivers/block/ide-cd.c	Wed Nov  8 07:11:30 1995
+++ linux/drivers/block/ide-cd.c	Wed Nov 22 13:42:41 1995
@@ -69,12 +69,12 @@
  *                       Fix handling of errors occuring before the
  *                        packet command is transferred.
  *                       Fix transfers with odd bytelengths.
+ * 3.03  Oct 27, 1995 -- Some Creative drives have an id of just `CD'.
+ *                       `DCI-2S10' drives are broken too.
+ * 3.04  Nov 20, 1995 -- So are Vertros drives.
  *
- * NOTE: I've tried to implement support for direct audio reads
- * in this version, but i haven't been able to fully test it
- * due to a lack of the proper hardware.  I'd  be interested in hearing
- * if you get anything other than a `Parameter not supported'
- * (asc=0x26, ascq=1) error when trying to do a direct audio read.
+ * NOTE: Direct audio reads will only work on some types of drive.
+ * So far, i've received reports of success for Sony and Toshiba drives.
  *
  * ATAPI cd-rom driver.  To be used with ide.c.
  *
@@ -2603,13 +2603,19 @@
     ((drive->id->config & 0x0060) == 0x20);
 
   /* Accommodate some broken drives... */
-  if (strcmp (drive->id->model, "CD220E") == 0)  /* Creative Labs */
+  if (strcmp (drive->id->model, "CD220E") == 0 ||
+      strcmp (drive->id->model, "CD")     == 0)        /* Creative Labs */
     CDROM_CONFIG_FLAGS (drive)->no_lba_toc = 1;
 
   else if (strcmp (drive->id->model, "TO-ICSLYAL") == 0 ||  /* Acer CD525E */
            strcmp (drive->id->model, "OTI-SCYLLA") == 0)
     CDROM_CONFIG_FLAGS (drive)->no_lba_toc = 1;
 
+  /* I don't know who makes this.
+     Francesco Messineo <sidera@ccii.unipi.it> says this one's broken too. */
+  else if (strcmp (drive->id->model, "DCI-2S10") == 0)
+    CDROM_CONFIG_FLAGS (drive)->no_lba_toc = 1;
+
   else if (strcmp (drive->id->model, "CDA26803I SE") == 0) /* Aztech */
     {
       CDROM_CONFIG_FLAGS (drive)->no_lba_toc = 1;
@@ -2618,6 +2624,12 @@
       CDROM_CONFIG_FLAGS (drive)->no_playaudio12 = 1;
     }
 
+  else if (strcmp (drive->id->model, "V003S0DS") == 0 ||  /* Vertros */
+	   strcmp (drive->id->model, "0V300SSD") == 0 ||
+	   strcmp (drive->id->model, "V004E0DT") == 0 ||
+	   strcmp (drive->id->model, "0V400ETD") == 0)
+    CDROM_CONFIG_FLAGS (drive)->no_lba_toc = 1;
+
   drive->cdrom_info.toc               = NULL;
   drive->cdrom_info.sector_buffer     = NULL;
   drive->cdrom_info.sector_buffered   = 0;
@@ -2635,4 +2647,6 @@
  *   duplicated functionality between read and ioctl paths?
  *  Establish interfaces for an IDE port driver, and break out the cdrom
  *   code into a loadable module.
+ *  Support changers.
+ *  Write some real documentation.
  */
diff -u --recursive --new-file v1.3.43/linux/drivers/block/ide.c linux/drivers/block/ide.c
--- v1.3.43/linux/drivers/block/ide.c	Tue Nov 21 13:22:07 1995
+++ linux/drivers/block/ide.c	Sat Nov 25 11:46:06 1995
@@ -1,11 +1,11 @@
 /*
- *  linux/drivers/block/ide.c	Version 5.18  Nov 16, 1995
+ *  linux/drivers/block/ide.c	Version 5.17  Nov 3, 1995
  *
  *  Copyright (C) 1994, 1995  Linus Torvalds & authors (see below)
  */
 
 /*
- * This is the multiple IDE interface driver, as evolved from hd.c.
+ * This is the multiple IDE interface driver, as evolved from hd.c.  
  * It supports up to four IDE interfaces, on one or more IRQs (usually 14 & 15).
  * There can be up to two drives per interface, as per the ATA-2 spec.
  *
@@ -13,17 +13,17 @@
  * Secondary i/f:  ide1: major=22; (hdc or hd1a) minor=0; (hdd or hd1b) minor=64
  * Tertiary i/f:   ide2: major=33; (hde)         minor=0; (hdf)         minor=64
  * Quaternary i/f: ide3: major=34; (hdg)         minor=0; (hdh)         minor=64
- *
+ * 
  * It is easy to extend ide.c to handle more than four interfaces:
  *
  *	Change the MAX_HWIFS constant in ide.h.
- *
+ * 
  *	Define some new major numbers (in major.h), and insert them into
  *	the ide_hwif_to_major table in ide.c.
- *
+ * 
  *	Fill in the extra values for the new interfaces into the two tables
  *	inside ide.c:  default_io_base[]  and  default_irqs[].
- *
+ * 
  *	Create the new request handlers by cloning "do_ide3_request()"
  *	for each new interface, and add them to the switch statement
  *	in the ide_init() function in ide.c.
@@ -56,7 +56,7 @@
  *  Maintained by Mark Lord (mlord@bnr.ca):  ide.c, ide.h, triton.c, hd.c, ..
  *
  *  This was a rewrite of just about everything from hd.c, though some original
- *  code is still sprinkled about.  Think of it as a major evolution, with
+ *  code is still sprinkled about.  Think of it as a major evolution, with 
  *  inspiration from lots of linux users, esp.  hamish@zot.apana.org.au
  *
  *  Version 1.0 ALPHA	initial code, primary i/f working okay
@@ -167,18 +167,15 @@
  *			remove "Huh?" from cmd640 code
  *			added qd6580 interface speed select from Colten Edwards
  *  Version 5.17	kludge around bug in BIOS32 on Intel triton motherboards
- *  Version 5.18	new CMD640 code, moved to cmd640.c, #include'd for now
- *			new UMC8672 code, moved to umc8672.c, #include'd for now
- *			disallow turning on DMA when h/w not capable of DMA
  *
  *  Driver compile-time options are in ide.h
  *
  *  To do, in likely order of completion:
- *	- make cmd640.c and umc8672.c compile separately from ide.c
  *	- add ALI M1443/1445 chipset support from derekn@vw.ece.cmu.edu
- *	- add ioctls to get/set interface timings on various interfaces
  *	- add Promise Caching controller support from peterd@pnd-pc.demon.co.uk
+ *	- add ioctls to get/set interface timings on various interfaces
  *	- modify kernel to obtain BIOS geometry for drives on 2nd/3rd/4th i/f
+ *	- improved CMD support:  handed this off to someone else
  *	- find someone to work on IDE *tape drive* support
  */
 
@@ -212,14 +209,9 @@
 
 #include "ide.h"
 
-#ifdef SUPPORT_CMD640
-void cmd640_tune_drive(ide_drive_t *);
-static int cmd640_vlb = 0;
-#endif
-
        ide_hwif_t	ide_hwifs[MAX_HWIFS];		/* hwif info */
 static ide_hwgroup_t	*irq_to_hwgroup [16];
-static const byte	ide_hwif_to_major[MAX_HWIFS] = {IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR};
+static const byte	ide_hwif_to_major[MAX_HWIFS]   = {IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR};
 
 static const unsigned short default_io_base[MAX_HWIFS] = {0x1f0, 0x170, 0x1e8, 0x168};
 static const byte	default_irqs[MAX_HWIFS]     = {14, 15, 11, 10};
@@ -1007,7 +999,7 @@
 
 /*
  * multwrite() transfers a block of one or more sectors of data to a drive
- * as part of a disk multwrite operation.
+ * as part of a disk multwrite operation.  
  */
 static void multwrite (ide_drive_t *drive)
 {
@@ -1240,7 +1232,7 @@
 	if (drive->select.b.lba) {
 #ifdef DEBUG
 		printk("%s: %sing: LBAsect=%ld, sectors=%ld, buffer=0x%08lx\n",
-			drive->name, (rq->cmd==READ)?"read":"writ",
+			drive->name, (rq->cmd==READ)?"read":"writ", 
 			block, rq->nr_sectors, (unsigned long) rq->buffer);
 #endif
 		OUT_BYTE(block,io_base+IDE_SECTOR_OFFSET);
@@ -1503,7 +1495,7 @@
 		printk("%s: marginal timeout\n", drive->name);
 	} else {				 /* drive not responding */
 		hwgroup->handler = NULL;
-		if (hwgroup->hwif->dmaproc)
+		if (hwgroup->hwif->dmaproc) 
 			(void) hwgroup->hwif->dmaproc (ide_dma_abort, drive);
 		if (!ide_error(drive, "irq timeout", GET_STAT()))
 			do_hwgroup_request (hwgroup);
@@ -1530,7 +1522,7 @@
  * In reality, this is a non-issue.  The new command is not sent unless the
  * drive is ready to accept one, in which case we know the drive is not
  * trying to interrupt us.  And ide_set_handler() is always invoked before
- * completing the issuance of any new drive command, so we will not be
+ * completing the issuance of any new drive command, so we will not be 
  * accidently invoked as a result of any valid command completion interrupt.
  *
  */
@@ -1814,24 +1806,24 @@
 		case BLKRAGET:
 			return write_fs_long(arg, read_ahead[MAJOR(inode->i_rdev)]);
 
-	 	case BLKGETSIZE:   /* Return device size */
+         	case BLKGETSIZE:   /* Return device size */
 			return write_fs_long(arg, drive->part[MINOR(inode->i_rdev)&PARTN_MASK].nr_sects);
 		case BLKRRPART: /* Re-read partition tables */
 			return revalidate_disk(inode->i_rdev);
 
-		case HDIO_GET_KEEPSETTINGS:
+                case HDIO_GET_KEEPSETTINGS:
 			return write_fs_long(arg, drive->keep_settings);
 
-		case HDIO_GET_UNMASKINTR:
+                case HDIO_GET_UNMASKINTR:
 			return write_fs_long(arg, drive->unmask);
 
-		case HDIO_GET_DMA:
+                case HDIO_GET_DMA:
 			return write_fs_long(arg, drive->using_dma);
 
-		case HDIO_GET_CHIPSET:
+                case HDIO_GET_CHIPSET:
 			return write_fs_long(arg, drive->chipset);
 
-		case HDIO_GET_MULTCOUNT:
+                case HDIO_GET_MULTCOUNT:
 			return write_fs_long(arg, drive->mult_count);
 
 		case HDIO_GET_IDENTITY:
@@ -1866,10 +1858,6 @@
 			cli();
 			switch (cmd) {
 				case HDIO_SET_DMA:
-					if (!(HWIF(drive)->dmaproc)) {
-						restore_flags(flags);
-						return -EPERM;
-					}
 					drive->using_dma = arg;
 					break;
 				case HDIO_SET_KEEPSETTINGS:
@@ -2058,7 +2046,7 @@
 		drive->present = 1;
 		drive->cyl     = drive->bios_cyl  = id->cyls;
 		drive->head    = drive->bios_head = id->heads;
-		drive->sect    = drive->bios_sect = id->sectors;
+		drive->sect    = drive->bios_sect = id->sectors; 
 	}
 	/* Handle logical geometry translation by the drive */
 	if ((id->field_valid & 1) && id->cur_cyls && id->cur_heads
@@ -2067,7 +2055,7 @@
 		/*
 		 * Extract the physical drive geometry for our use.
 		 * Note that we purposely do *not* update the bios info.
-		 * This way, programs that use it (like fdisk) will
+		 * This way, programs that use it (like fdisk) will 
 		 * still have the same logical view as the BIOS does,
 		 * which keeps the partition table from being screwed.
 		 *
@@ -2091,7 +2079,7 @@
 	if ((!drive->head || drive->head > 16) && id->heads && id->heads <= 16) {
 		drive->cyl  = id->cyls;
 		drive->head = id->heads;
-		drive->sect = id->sectors;
+		drive->sect = id->sectors; 
 	}
 	/* Correct the number of cyls if the bios value is too small */
 	if (drive->sect == drive->bios_sect && drive->head == drive->bios_head) {
@@ -2119,9 +2107,6 @@
 			printk(", DMA");
 	}
 	printk("\n");
-#ifdef SUPPORT_CMD640
-	cmd640_tune_drive(drive);	/* but can we tune a fish? */
-#endif
 }
 
 /*
@@ -2351,8 +2336,8 @@
  * The code enables the secondary IDE controller and the PIO4 (3?) timings on
  * the primary (EIDE). You may probably have to enable the 32-bit support to
  * get the full speed. You better get the disk interrupts disabled ( hdparm -u0
- * /dev/hd.. ) for the drives connected to the EIDE interface. (I get my
- * filesystem  corrupted with -u1, but under heavy disk load only :-)
+ * /dev/hd.. ) for the drives connected to the EIDE interface. (I get my 
+ * filesystem  corrupted with -u1, but under heavy disk load only :-)  
  *
  * From: mlord@bnr.ca -- this chipset is now forced to use the "serialize" feature,
  * which hopefully will make it more reliable to use.. maybe it has the same bugs
@@ -2432,13 +2417,59 @@
 }
 #endif /* SUPPORT_QD6580 */
 
-#ifdef SUPPORT_UMC8672
-#include "umc8672.c"	/* until we tidy up the interface some more */
-#endif
+#if SUPPORT_CMD640
+/*
+ * ??? fixme: 
+ */
+byte read_cmd640_vlb (byte port, byte reg)
+{
+	byte val;
+
+	unsigned long flags;
+	save_flags(flags);
+	cli();
+	outw(reg, port);
+	val = inb(port+4);
+	restore_flags(flags);
+	return val;
+}
+
+void write_cmd640_vlb (byte port, byte reg, byte val)
+{
+	unsigned long flags;
+	save_flags(flags);
+	cli();
+	outw(reg, port);
+	outw(val, port+4);
+	restore_flags(flags);
+}
+
+void init_cmd640_vlb (void)
+{
+	byte reg;
+	unsigned short port = 0x178;
 
-#ifdef SUPPORT_CMD640
-#include "cmd640.c"	/* until we tidy up the interface some more */
+	serialized = 1;
+ 	printk("ide: buggy CMD640 interface: serialized, ");
+	reg = read_cmd640_vlb(port, 0x50);
+	if (reg == 0xff || (reg & 0x90) != 0x90) {
+#if TRY_CMD640_VLB_AT_0x78
+		port = 0x78;
+		reg = read_cmd640_vlb(port, 0x50);
+		if (reg == 0xff || (reg & 0x90) != 0x90)
 #endif
+		{
+			disallow_unmask = 1;
+			printk("(probe failed) disabled unmasking\n");
+			return;
+		}
+	}
+	write_cmd640_vlb(port, 0x51, read_cmd640_vlb(port, 0x51)|0xc8);
+	write_cmd640_vlb(port, 0x57, read_cmd640_vlb(port, 0x57)|0x0c);
+	printk("disabled read-ahead, enabled secondary\n");
+
+}
+#endif /* SUPPORT_CMD640 */
 
 /*
  * stridx() returns the offset of c within s,
@@ -2457,7 +2488,7 @@
  * 2. if the remainder matches one of the supplied keywords,
  *     the index (1 based) of the keyword is negated and returned.
  * 3. if the remainder is a series of no more than max_vals numbers
- *     separated by commas, the numbers are saved in vals[] and a
+ *     separated by commas, the numbers are saved in vals[] and a 
  *     count of how many were saved is returned.  Base10 is assumed,
  *     and base16 is allowed when prefixed with "0x".
  * 4. otherwise, zero is returned.
@@ -2480,7 +2511,7 @@
 		/*
 		 * Look for a series of no more than "max_vals"
 		 * numeric values separated by commas, in base10,
-		 * or base16 when prefixed with "0x".
+		 * or base16 when prefixed with "0x".  
 		 * Return a count of how many were found.
 		 */
 		for (n = 0; (i = stridx(decimal, *s)) >= 0;) {
@@ -2590,18 +2621,11 @@
 	 * Look for interface options:  "idex="
 	 */
 	if (s[0] == 'i' && s[1] == 'd' && s[2] == 'e' && s[3] >= '0' && s[3] <= max_hwif) {
-		const char *ide_words[] = {"noprobe", "serialize", "dtc2278", "ht6560b",
-					"cmd640_vlb", "qd6580", "umc8672", NULL};
+		const char *ide_words[] = {"noprobe", "serialize", "dtc2278", "ht6560b", "cmd640_vlb", "qd6580", NULL};
 		hw = s[3] - '0';
 		hwif = &ide_hwifs[hw];
 
 		switch (match_parm(&s[4], ide_words, vals, 3)) {
-#if SUPPORT_UMC8672
-			case -7: /* "umc8672" */
-				if (hw != 0) goto bad_hwif;
-				init_umc8672();
-				goto done;
-#endif /* SUPPORT_UMC8672 */
 #if SUPPORT_QD6580
 			case -6: /* "qd6580" */
 				if (hw != 0) goto bad_hwif;
@@ -2611,7 +2635,8 @@
 #if SUPPORT_CMD640
 			case -5: /* "cmd640_vlb" */
 				if (hw > 1) goto bad_hwif;
-				cmd640_vlb = 1;
+				init_cmd640_vlb();
+				goto do_serialize; /* not necessary once we implement the above */
 				break;
 #endif /* SUPPORT_CMD640 */
 #if SUPPORT_HT6560B
@@ -2684,7 +2709,7 @@
 
 	drive->cyl  = drive->bios_cyl  = drive->id->cyls;
 	drive->head = drive->bios_head = drive->id->heads;
-	drive->sect = drive->bios_sect = drive->id->sectors;
+	drive->sect = drive->bios_sect = drive->id->sectors; 
 	drive->special.b.set_geometry = 1;
 
 	tracks = drive->bios_cyl * drive->bios_head * drive->bios_sect / 63;
@@ -2720,7 +2745,7 @@
  * drives in the system -- the ones reflected as drive 1 or 2.  The first
  * drive is stored in the high nibble of CMOS byte 0x12, the second in the low
  * nibble.  This will be either a 4 bit drive type or 0xf indicating use byte
- * 0x19 for an 8 bit type, drive 1, 0x1a for drive 2 in CMOS.  A non-zero value
+ * 0x19 for an 8 bit type, drive 1, 0x1a for drive 2 in CMOS.  A non-zero value 
  * means we have an AT controller hard disk for that drive.
  *
  * Of course, there is no guarantee that either drive is actually on the
@@ -2880,6 +2905,45 @@
 }
 #endif /* SUPPORT_RZ1000 */
 
+#if SUPPORT_CMD640
+void init_cmd640 (byte bus, byte fn)
+{
+	int rc;
+	unsigned char reg;
+
+	serialized = 1;
+	printk("ide: buggy CMD640 interface: ");
+
+#if 0	/* funny.. the cmd640b I tried this on claimed to not be enabled.. */
+	unsigned short sreg;
+	if ((rc = pcibios_read_config_word (bus, fn, PCI_COMMAND, &sreg))) {
+		ide_pci_access_error (rc);
+	} else if (!(sreg & 1)) {
+		printk("not enabled\n");
+	} else {
+
+	/*
+	 * The first part is undocumented magic from the DOS driver.
+	 * According to the datasheet, there is no port 0x5b on the cmd640.
+	 */
+	(void) pcibios_write_config_byte(bus, fn, 0x5b, 0xbd);
+	if (pcibios_write_config_byte(bus, fn, 0x5b, 0xbd) != 0xbd)
+		printk("init_cmd640: huh? 0x5b read back wrong\n");
+	(void) pcibios_write_config_byte(bus, fn, 0x5b, 0);
+#endif /* 0 */
+	/*
+	 * The rest is from the cmd640b datasheet.
+	 */
+	if ((rc = pcibios_read_config_byte(bus, fn, 0x51, &reg))
+	 || (rc =  pcibios_write_config_byte(bus, fn, 0x51, reg | 0xc0)) /* 0xc8 to enable 2nd i/f */
+	 || (rc =  pcibios_read_config_byte(bus, fn, 0x57, &reg))
+	 || (rc =  pcibios_write_config_byte(bus, fn, 0x57, reg | 0x0c)))
+		buggy_interface_fallback (rc);
+	else
+		printk("serialized, disabled read-ahead\n");
+}
+#endif /* SUPPORT_CMD640 */
+
 typedef void (ide_pci_init_proc_t)(byte, byte);
 
 /*
@@ -2902,7 +2966,7 @@
 
 /*
  * ide_init_pci() finds/initializes "known" PCI IDE interfaces
- *
+ * 
  * This routine should ideally be using pcibios_find_class() to find
  * all IDE interfaces, but that function causes some systems to "go weird".
  */
@@ -2911,6 +2975,9 @@
 #if SUPPORT_RZ1000
 	ide_probe_pci (PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1000, &init_rz1000, 0);
 #endif
+#if SUPPORT_CMD640
+	ide_probe_pci (PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_640, &init_cmd640, 0);
+#endif
 #ifdef CONFIG_BLK_DEV_TRITON
 	/*
 	 * Apparently the BIOS32 services on Intel motherboards are buggy,
@@ -2941,9 +3008,6 @@
 	if (pcibios_present())
 		ide_init_pci ();
 #endif /* CONFIG_PCI */
-#ifdef SUPPORT_CMD640
-	ide_probe_for_cmd640x();
-#endif
 
 	/*
 	 * Probe for drives in the usual way.. CMOS/BIOS, then poke at ports
diff -u --recursive --new-file v1.3.43/linux/drivers/block/ide.h linux/drivers/block/ide.h
--- v1.3.43/linux/drivers/block/ide.h	Tue Nov 21 13:22:07 1995
+++ linux/drivers/block/ide.h	Sat Nov 25 12:10:07 1995
@@ -40,9 +40,6 @@
 #ifndef SUPPORT_CMD640			/* 1 to support CMD640 chipset */
 #define SUPPORT_CMD640		1	/* 0 to reduce kernel size */
 #endif
-#ifndef SUPPORT_UMC8672			/* 1 to support UMC8672 chipset */
-#define SUPPORT_UMC8672		1	/* 0 to reduce kernel size */
-#endif
 #ifndef SUPPORT_HT6560B			/* 1 to support HT6560B chipset */
 #define SUPPORT_HT6560B		1	/* 0 to reduce kernel size */
 #endif
diff -u --recursive --new-file v1.3.43/linux/drivers/block/triton.c linux/drivers/block/triton.c
--- v1.3.43/linux/drivers/block/triton.c	Tue Nov 21 13:22:08 1995
+++ linux/drivers/block/triton.c	Sat Nov 25 11:46:06 1995
@@ -1,5 +1,5 @@
 /*
- *  linux/drivers/block/triton.c	Version 1.03  Nov 16, 1995
+ *  linux/drivers/block/triton.c	Version 1.02  Oct 13, 1995
  *
  *  Copyright (c) 1995  Mark Lord
  *  May be copied or modified under the terms of the GNU General Public License
@@ -64,12 +64,8 @@
  *	  the observation that WRITEs work most of the time, depending on
  *	  cache-buffer occupancy, but multi-sector reads seldom work.
  *
- * Testing was done with a Gigabyte GA-586 ATE system and the following drive:
- * (Uwe Bonnes - bon@elektron.ikp.physik.th-darmstadt.de)
- *
- *   Western Digital AC31600H (1.6Gig w/128kB buffer), DMA mode2, PIO mode4.
- *	- much better than its 1Gig cousin, this drive is reported to work
- *	  very well with DMA (7.3MB/sec).
+ * Drives like the AC31000H could likely be made to work if all DMA were done
+ * one sector at a time, but that would likely negate any advantage over PIO.
  *
  * If you have any drive models to add, email your results to:  mlord@bnr.ca
  * Keep an eye on /var/adm/messages for "DMA disabled" messages.
diff -u --recursive --new-file v1.3.43/linux/drivers/block/umc8672.c linux/drivers/block/umc8672.c
--- v1.3.43/linux/drivers/block/umc8672.c	Tue Nov 21 13:22:08 1995
+++ linux/drivers/block/umc8672.c	Thu Jan  1 02:00:00 1970
@@ -1,108 +0,0 @@
-/*
- *  linux/drivers/block/umc8672.c	Version 0.01  Nov 16, 1995
- *
- *  Copyright (C) 1995  Linus Torvalds & author (see below)
- */
-
-/*
- *  Principal Author/Maintainer:  PODIEN@hml2.atlas.de (Wolfram Podien)
- *
- *  This file provides support for the advanced features
- *  of the UMC 8672 IDE interface.
- *
- *  Version 0.01	Initial version, hacked out of ide.c,
- *			and #include'd rather than compiled separately.
- *			This will get cleaned up in a subsequent release.
- */
-
-/*
- * VLB Controller Support from 
- * Wolfram Podien
- * Rohoefe 3
- * D28832 Achim
- * Germany
- *
- * To enable UMC8672 support there must a lilo line like
- * append="hd=umc8672"...
- * To set the speed according to the abilities of the hardware there must be a
- * line like
- * #define UMC_DRIVE0 11
- * in the beginning of the driver, which sets the speed of drive 0 to 11 (there
- * are some lines present). 0 - 11 are allowed speed values. These values are
- * the results from the DOS speed test programm supplied from UMC. 11 is the 
- * highest speed (about PIO mode 3)
- */
-
-/*
- * The speeds will eventually become selectable using hdparm via ioctl's,
- * but for now they are coded here:
- */
-#define UMC_DRIVE0      11              /* DOS messured drive Speeds */
-#define UMC_DRIVE1      11              /* 0 - 11 allowed */
-#define UMC_DRIVE2      11              /* 11 = Highest Speed */
-#define UMC_DRIVE3      11              /* In case of crash reduce speed */
-
-void out_umc (char port,char wert)
-{
-	outb_p (port,0x108);
-	outb_p (wert,0x109);
-}
-
-byte in_umc (char port)
-{
-	outb_p (port,0x108);
-	return inb_p (0x109);
-}
-
-void init_umc8672(void)
-{
-	int i,tmp;
-	int speed [4];
-/*      0    1    2    3    4    5    6    7    8    9    10   11      */
-	char speedtab [3][12] = {
-	{0xf ,0xb ,0x2 ,0x2 ,0x2 ,0x1 ,0x1 ,0x1 ,0x1 ,0x1 ,0x1 ,0x1 },
-	{0x3 ,0x2 ,0x2 ,0x2 ,0x2 ,0x2 ,0x1 ,0x1 ,0x1 ,0x1 ,0x1 ,0x1 },
-	{0xff,0xcb,0xc0,0x58,0x36,0x33,0x23,0x22,0x21,0x11,0x10,0x0}};
-
-	cli ();
-	outb_p (0x5A,0x108); /* enable umc */
-	if (in_umc (0xd5) != 0xa0)
-	{
-		sti ();
-		printk ("UMC8672 not found\n");
-		return;  
-	}
-	speed[0] = UMC_DRIVE0;
-	speed[1] = UMC_DRIVE1;
-	speed[2] = UMC_DRIVE2;
-	speed[3] = UMC_DRIVE3;
-	for (i = 0;i < 4;i++)
-	{
-		if ((speed[i] < 0) || (speed[i] > 11))
-		{
-			sti ();
-			printk ("UMC 8672 drive speed out of range. Drive %d Speed %d\n",
-				i, speed[i]);
-			printk ("UMC support aborted\n");
-			return; 
-		}
-	}
-	out_umc (0xd7,(speedtab[0][speed[2]] | (speedtab[0][speed[3]]<<4)));
-	out_umc (0xd6,(speedtab[0][speed[0]] | (speedtab[0][speed[1]]<<4)));
-	tmp = 0;
-	for (i = 3; i >= 0; i--)
-	{
-		tmp = (tmp << 2) | speedtab[1][speed[i]];
-	}
-	out_umc (0xdc,tmp);
-	for (i = 0;i < 4; i++)
-	{
-		out_umc (0xd0+i,speedtab[2][speed[i]]);
-		out_umc (0xd8+i,speedtab[2][speed[i]]);
-	}
-	outb_p (0xa5,0x108); /* disable umc */
-	sti ();
-	printk ("Speeds for UMC8672 \n");
-	for (i = 0;i < 4;i++)
-		 printk ("Drive %d speed %d\n",i,speed[i]);
-}
diff -u --recursive --new-file v1.3.43/linux/drivers/cdrom/aztcd.c linux/drivers/cdrom/aztcd.c
--- v1.3.43/linux/drivers/cdrom/aztcd.c	Thu Nov  9 11:23:47 1995
+++ linux/drivers/cdrom/aztcd.c	Sat Nov 25 17:28:41 1995
@@ -1,5 +1,5 @@
-#define AZT_VERSION "1.90"
-/*      $Id: aztcd.c,v 1.90 1995/10/21 17:51:59 root Exp root $
+#define AZT_VERSION "2.0"
+/*      $Id: aztcd.c,v 2.0 1995/11/10 19:33:41 root Exp root $
 	linux/drivers/block/aztcd.c - AztechCD268 CDROM driver
 
 	Copyright (C) 1994,1995 Werner Zimmermann (zimmerma@rz.fht-esslingen.de)
@@ -128,14 +128,19 @@
                 Werner Zimmermann, August 8, 1995
         V1.70   Multisession support now is completed, but there is still not 
                 enough testing done. If you can test it, please contact me. For
-                details please read README.aztcd.
+                details please read /usr/src/linux/Documentation/cdrom/aztcd
                 Werner Zimmermann, August 19, 1995
         V1.80   Modification to suit the new kernel boot procedure introduced
                 with kernel 1.3.33. Will definitely not work with older kernels.
                 Programming done by Linus himself.
                 Werner Zimmermann, October 11, 1995
-	V1.90   Support for Conrad TXC drives, thank's to Jochen and Olaf.
+	V1.90   Support for Conrad TXC drives, thank's to Jochen Koch and Olaf Koluza.
 	        Werner Zimmermann, October 21, 1995
+        V2.00   Changed #include "blk.h" to <linux/blk.h> as the directory
+                structure was changed. README.aztcd is now /usr/src/docu-
+                mentation/cdrom/aztcd
+                Werner Zimmermann, November 10, 95
+
 	NOTE: 
 	Points marked with ??? are questionable !
 */
@@ -1526,7 +1531,7 @@
 	}
 	printk("aztcd: Aztech,Orchid,Okano,Wearnes,TXC CD-ROM Driver (C) 1994,1995 W.Zimmermann\n");
 	printk("aztcd: DriverVersion=%s BaseAddress=0x%x  For IDE/ATAPI-drives use ide-cd.c\n",AZT_VERSION,azt_port);
-	printk("aztcd: If you have problems, read /usr/src/linux/drivers/block/README.aztcd\n");
+	printk("aztcd: If you have problems, read /usr/src/linux/Documentation/cdrom/aztcd\n");
 
 	if (check_region(azt_port, 4)) {
 	  printk("aztcd: conflict, I/O port (%X) already used\n",
diff -u --recursive --new-file v1.3.43/linux/drivers/net/3c501.c linux/drivers/net/3c501.c
--- v1.3.43/linux/drivers/net/3c501.c	Thu Nov  9 11:23:49 1995
+++ linux/drivers/net/3c501.c	Fri Nov 24 16:39:53 1995
@@ -120,7 +120,7 @@
 static void el_reset(struct device *dev);
 static int  el1_close(struct device *dev);
 static struct enet_statistics *el1_get_stats(struct device *dev);
-static void set_multicast_list(struct device *dev, int num_addrs, void *addrs);
+static void set_multicast_list(struct device *dev);
 
 #define EL1_IO_EXTENT	16
 
@@ -647,29 +647,32 @@
     return &lp->stats;
 }
 
-/* Set or clear the multicast filter for this adaptor.
-   num_addrs == -2	All multicast hosts
-   num_addrs == -1	Promiscuous mode, receive all packets
-   num_addrs == 0	Normal mode, clear multicast list
-   num_addrs > 0	Multicast mode, receive normal and MC packets, and do
-			best-effort filtering.
+/*
+ *	Set or clear the multicast filter for this adaptor.
+ *			best-effort filtering.
  */
-static void
-set_multicast_list(struct device *dev, int num_addrs, void *addrs)
+
+static void set_multicast_list(struct device *dev)
 {
-    int ioaddr = dev->base_addr;
+	int ioaddr = dev->base_addr;
 
-    if (num_addrs > 0 || num_addrs==-2) {
-	outb(RX_MULT, RX_CMD);	/* Multicast or all multicast is the same */
-	inb(RX_STATUS);		/* Clear status. */
-    } else if (num_addrs < 0) {
-	outb(RX_PROM, RX_CMD);
-	inb(RX_STATUS);
-    } else {
-	outb(RX_NORM, RX_CMD);
-	inb(RX_STATUS);
-    }
+	if(dev->flags&IFF_PROMISC)
+	{    
+		outb(RX_PROM, RX_CMD);
+		inb(RX_STATUS);
+	}
+	else if (dev->mc_list || dev->flags&IFF_ALLMULTI)
+	{
+		outb(RX_MULT, RX_CMD);	/* Multicast or all multicast is the same */
+		inb(RX_STATUS);		/* Clear status. */
+	}
+	else 
+	{
+		outb(RX_NORM, RX_CMD);
+		inb(RX_STATUS);
+	}
 }
+
 #ifdef MODULE
 static char devicename[9] = { 0, };
 static struct device dev_3c501 = {
diff -u --recursive --new-file v1.3.43/linux/drivers/net/3c505.c linux/drivers/net/3c505.c
--- v1.3.43/linux/drivers/net/3c505.c	Mon Nov 13 12:36:44 1995
+++ linux/drivers/net/3c505.c	Fri Nov 24 16:39:53 1995
@@ -1173,21 +1173,26 @@
  ************************************************************/
 
 static void
-elp_set_mc_list (struct device *dev, int num_addrs, void *addrs)
+elp_set_mc_list (struct device *dev)
 {
 	elp_device *adapter = (elp_device *) dev->priv;
+	struct dev_mc_list *dmi=dev->mc_list;
 	int i;
 
 	if (elp_debug >= 3)
 		printk("%s: request to set multicast list\n", dev->name);
 
-	if (num_addrs != -1) {
+	if (!(dev->flags&(IFF_PROMISC|IFF_ALLMULTI)))
+	{
 		/* send a "load multicast list" command to the board, max 10 addrs/cmd */
 		/* if num_addrs==0 the list will be cleared */
 		adapter->tx_pcb.command = CMD_LOAD_MULTICAST_LIST;
-		adapter->tx_pcb.length  = 6*num_addrs;
-		for (i=0;i<num_addrs;i++)
-			memcpy(adapter->tx_pcb.data.multicast[i], addrs+6*i,6);
+		adapter->tx_pcb.length  = 6*dev->mc_count;
+		for (i=0;i<dev->mc_count;i++)
+		{
+			memcpy(adapter->tx_pcb.data.multicast[i], dmi->dmi_addr,6);
+			dmi=dmi->next;
+		}
 		adapter->got[CMD_LOAD_MULTICAST_LIST] = 0;
 		if (!send_pcb(dev, &adapter->tx_pcb))
 			printk("%s: couldn't send set_multicast command\n", dev->name);
@@ -1199,11 +1204,12 @@
 				TIMEOUT_MSG(__LINE__);
 			}
 		}
-		if (num_addrs)
+		if (dev->mc_count)
 			adapter->tx_pcb.data.configure = NO_LOOPBACK | RECV_BROAD | RECV_MULTI;
 		else /* num_addrs == 0 */
 			adapter->tx_pcb.data.configure = NO_LOOPBACK | RECV_BROAD;
-	} else /* num_addrs == -1 */
+	} 
+	else
 		adapter->tx_pcb.data.configure = NO_LOOPBACK | RECV_PROMISC;
 	/*
 	 * configure adapter to receive messages (as specified above)
diff -u --recursive --new-file v1.3.43/linux/drivers/net/3c509.c linux/drivers/net/3c509.c
--- v1.3.43/linux/drivers/net/3c509.c	Thu Nov  9 11:23:49 1995
+++ linux/drivers/net/3c509.c	Fri Nov 24 16:39:53 1995
@@ -107,9 +107,7 @@
 static struct enet_statistics *el3_get_stats(struct device *dev);
 static int el3_rx(struct device *dev);
 static int el3_close(struct device *dev);
-#ifdef HAVE_MULTICAST
-static void set_multicast_list(struct device *dev, int num_addrs, void *addrs);
-#endif
+static void set_multicast_list(struct device *dev);
 
 
 
@@ -259,9 +257,7 @@
 	dev->hard_start_xmit = &el3_start_xmit;
 	dev->stop = &el3_close;
 	dev->get_stats = &el3_get_stats;
-#ifdef HAVE_MULTICAST
 	dev->set_multicast_list = &set_multicast_list;
-#endif
 
 	/* Fill in the generic fields of the device structure. */
 	ether_setup(dev);
@@ -630,33 +626,32 @@
 	return 0;
 }
 
-#ifdef HAVE_MULTICAST
-/* Set or clear the multicast filter for this adaptor.
-   num_addrs == -1		Promiscuous mode, receive all packets
-   num_addrs == 0		Normal mode, clear multicast list
-   num_addrs > 0		Multicast mode, receive normal and MC packets, and do
-						best-effort filtering.
+/* 
+ *	Set or clear the multicast filter for this adaptor.
  */
-static void
-set_multicast_list(struct device *dev, int num_addrs, void *addrs)
+ 
+static void set_multicast_list(struct device *dev)
 {
 	short ioaddr = dev->base_addr;
 	if (el3_debug > 1) {
 		static int old = 0;
-		if (old != num_addrs) {
-			old = num_addrs;
-			printk("%s: Setting Rx mode to %d addresses.\n", dev->name, num_addrs);
+		if (old != dev->mc_count) {
+			old = dev->mc_count;
+			printk("%s: Setting Rx mode to %d addresses.\n", dev->name, dev->mc_count);
 		}
 	}
-	if (num_addrs > 0 || num_addrs == -2) {
+	if (dev->mc_count || (dev->flags&IFF_ALLMULTI)) 
+	{
 		outw(SetRxFilter|RxStation|RxMulticast|RxBroadcast, ioaddr + EL3_CMD);
-	} else if (num_addrs < 0) {
+	} 
+	else if (dev->flags&IFF_PROMISC) 
+	{
 		outw(SetRxFilter | RxStation | RxMulticast | RxBroadcast | RxProm,
 			 ioaddr + EL3_CMD);
-	} else
+	}
+	else
 		outw(SetRxFilter | RxStation | RxBroadcast, ioaddr + EL3_CMD);
 }
-#endif
 
 static int
 el3_close(struct device *dev)
diff -u --recursive --new-file v1.3.43/linux/drivers/net/8390.c linux/drivers/net/8390.c
--- v1.3.43/linux/drivers/net/8390.c	Fri Nov 17 08:42:25 1995
+++ linux/drivers/net/8390.c	Fri Nov 24 16:39:53 1995
@@ -32,6 +32,8 @@
   Much of this code should have been cleaned up, but every attempt 
   has broken some clone part.
   
+  Doesn't currently work on all shared memory cards.
+  
   Sources:
   The National Semiconductor LAN Databook, and the 3Com 3c503 databook.
   */
@@ -105,9 +107,7 @@
 /* Routines generic to NS8390-based boards. */
 static void NS8390_trigger_send(struct device *dev, unsigned int length,
 								int start_page);
-#ifdef HAVE_MULTICAST
-static void set_multicast_list(struct device *dev, int num_addrs, void *addrs);
-#endif
+static void set_multicast_list(struct device *dev);
 
 
 /* Open/initialize the board.  This routine goes all-out, setting everything
@@ -572,27 +572,27 @@
     return &ei_local->stat;
 }
 
-#ifdef HAVE_MULTICAST
-/* Set or clear the multicast filter for this adaptor.
-   num_addrs == -1	Promiscuous mode, receive all packets
-   num_addrs == 0	Normal mode, clear multicast list
-   num_addrs > 0	Multicast mode, receive normal and MC packets, and do
-   .   				best-effort filtering.
-   */
+/*
+ *	Set or clear the multicast filter for this adaptor.
+ */
+ 
 static void set_multicast_list(struct device *dev, int num_addrs, void *addrs)
 {
-    short ioaddr = dev->base_addr;
+	short ioaddr = dev->base_addr;
     
-    if (num_addrs > 0 || num_addrs == -2) {
+	if(dev->flags&IFF_PROMISC)
+	{
+		outb_p(E8390_RXCONFIG | 0x18, ioaddr + EN0_RXCR);
+	}
+	else if((dev->flags&IFF_ALLMULTI)||dev->mc_list)
+	{
 		/* The multicast-accept list is initialized to accept-all, and we
 		   rely on higher-level filtering for now. */
 		outb_p(E8390_RXCONFIG | 0x08, ioaddr + EN0_RXCR);
-    } else if (num_addrs < 0)
-		outb_p(E8390_RXCONFIG | 0x18, ioaddr + EN0_RXCR);
-    else
+	} 
+	else
 		outb_p(E8390_RXCONFIG, ioaddr + EN0_RXCR);
 }
-#endif
 
 /* Initialize the rest of the 8390 device structure. */
 int ethdev_init(struct device *dev)
@@ -680,6 +680,8 @@
 		outb_p(E8390_TXCONFIG, e8390_base + EN0_TXCR); /* xmit on. */
 		/* 3c503 TechMan says rxconfig only after the NIC is started. */
 		outb_p(E8390_RXCONFIG,	e8390_base + EN0_RXCR); /* rx on,  */
+		dev->set_multicast_list(dev);		/* Get the multicast status right if this
+							   was a reset. */
     }
     return;
 }
diff -u --recursive --new-file v1.3.43/linux/drivers/net/Config.in linux/drivers/net/Config.in
--- v1.3.43/linux/drivers/net/Config.in	Fri Nov 17 08:42:25 1995
+++ linux/drivers/net/Config.in	Tue Nov 21 16:35:07 1995
@@ -43,6 +43,7 @@
     bool 'NI5210 support' CONFIG_NI52
     bool 'NI6510 support' CONFIG_NI65
     tristate 'WaveLAN support' CONFIG_WAVELAN
+    tristate 'ICL EtherTeam 16i/32 support' CONFIG_ETH16I
   fi
   tristate 'HP PCLAN+ (27247B and 27252A) support' CONFIG_HPLAN_PLUS
   tristate 'HP PCLAN (27245 and other 27xxx series) support' CONFIG_HPLAN
@@ -60,7 +61,6 @@
   fi
   tristate 'Apricot Xen-II on board ethernet' CONFIG_APRICOT
   tristate 'DE425, DE434, DE435, DE500 support' CONFIG_DE4X5
-  tristate 'ICL EtherTeam 16i/32 support' CONFIG_ETH16
 # tristate 'DEC 21040 PCI support' CONFIG_DEC_ELCP
 # bool 'LPL T100V 100Mbs support' CONFIG_LPL_T100
 # bool 'PCnet32 (32 bit VLB and PCI LANCE) support' CONFIG_PCNET32
diff -u --recursive --new-file v1.3.43/linux/drivers/net/Makefile linux/drivers/net/Makefile
--- v1.3.43/linux/drivers/net/Makefile	Fri Nov 17 08:42:25 1995
+++ linux/drivers/net/Makefile	Tue Nov 21 16:35:07 1995
@@ -332,10 +332,10 @@
   endif
 endif
 
-ifeq ($(CONFIG_ETH16),y)
+ifeq ($(CONFIG_ETH16I),y)
 L_OBJS += eth16i.o
 else
-  ifeq ($(CONFIG_ETH16),m)
+  ifeq ($(CONFIG_ETH16I),m)
   M_OBJS += eth16i.o
   endif
 endif
diff -u --recursive --new-file v1.3.43/linux/drivers/net/README.multicast linux/drivers/net/README.multicast
--- v1.3.43/linux/drivers/net/README.multicast	Fri Oct 13 14:44:33 1995
+++ linux/drivers/net/README.multicast	Fri Nov 24 16:39:53 1995
@@ -22,14 +22,14 @@
 ac3200		YES		YES		YES		Software(#)
 apricot		YES		PROMISC		YES		Hardware
 arcnet		NO		NO		NO		N/A
-at1700		****		PROMISC		YES		Software
-atp		****		PROMISC		YES		Software
+at1700		PROMISC		PROMISC		YES		Software
+atp		PROMISC		PROMISC		YES		Software
 de4x5		YES		NO		YES		Hardware
 de600		NO		NO		NO		N/A
-de620		****		PROMISC		YES		Software
+de620		PROMISC		PROMISC		YES		Software
 depca		YES		PROMISC		YES		Hardware
 e2100		YES		YES		YES		Software(#)
-eepro		YES(*)		PROMISC		YES		Hardware
+eepro		YES		PROMISC		YES		Hardware
 eexpress	NO		NO		NO		N/A
 ewrk3		YES		PROMISC		YES		Hardware
 hp-plus		YES		YES		YES		Software(#)
@@ -49,10 +49,8 @@
 znet		YES		YES		YES		Software
 
 
-**** = This driver would take down your entire network if you use it in a
-       multicast kernel with IP forwarding enabled (patches sent to Linus)
-YES(*) = As above but only if >64 addresses are activated.
-PROMISC = All multicasts mode is in fact promiscuous mode.
+PROMISC = This multicasts mode is in fact promiscuous mode. Avoid using
+cards who go PROMISC on any multicast in a multicast kernel.
 (#) = Hardware multicast support is not used yet.
 
 
diff -u --recursive --new-file v1.3.43/linux/drivers/net/Space.c linux/drivers/net/Space.c
--- v1.3.43/linux/drivers/net/Space.c	Fri Nov 17 08:42:25 1995
+++ linux/drivers/net/Space.c	Tue Nov 21 16:35:07 1995
@@ -51,6 +51,7 @@
 extern int el3_probe(struct device *);
 extern int at1500_probe(struct device *);
 extern int at1700_probe(struct device *);
+extern int eth16i_probe(struct device *);
 extern int depca_probe(struct device *);
 extern int apricot_probe(struct device *);
 extern int ewrk3_probe(struct device *);
@@ -117,6 +118,9 @@
 #endif
 #ifdef CONFIG_AT1700
 	&& at1700_probe(dev)
+#endif
+#ifdef CONFIG_ETH16I
+	&& eth16i_probe(dev)	/* ICL EtherTeam 16i/32 */
 #endif
 #ifdef CONFIG_EL3		/* 3c509 */
 	&& el3_probe(dev)
diff -u --recursive --new-file v1.3.43/linux/drivers/net/apricot.c linux/drivers/net/apricot.c
--- v1.3.43/linux/drivers/net/apricot.c	Thu Nov  9 11:23:49 1995
+++ linux/drivers/net/apricot.c	Fri Nov 24 16:39:53 1995
@@ -188,9 +188,7 @@
 static struct enet_statistics *i596_get_stats(struct device *dev);
 static void i596_add_cmd(struct device *dev, struct i596_cmd *cmd);
 static void print_eth(char *);
-#ifdef HAVE_MULTICAST
-static void set_multicast_list(struct device *dev, int num_addrs, void *addrs);
-#endif
+static void set_multicast_list(struct device *dev);
 
 
 static inline int
@@ -729,9 +727,7 @@
     dev->stop = &i596_close;
     dev->hard_start_xmit = &i596_start_xmit;
     dev->get_stats = &i596_get_stats;
-#ifdef HAVE_MULTICAST
     dev->set_multicast_list = &set_multicast_list;
-#endif
 
     dev->mem_start = (int)kmalloc(sizeof(struct i596_private)+ 0x0f, GFP_KERNEL);
     /* align for scp */
@@ -954,49 +950,55 @@
     return &lp->stats;
 }
 
-#ifdef HAVE_MULTICAST
-/* Set or clear the multicast filter for this adaptor.
-   num_addrs == -1	Promiscuous mode, receive all packets
-   num_addrs == 0	Normal mode, clear multicast list
-   num_addrs > 0	Multicast mode, receive normal and MC packets, and do
-   			best-effort filtering.
+/*
+ *	Set or clear the multicast filter for this adaptor.
  */
-static void
-set_multicast_list(struct device *dev, int num_addrs, void *addrs)
+ 
+static void set_multicast_list(struct device *dev)
 {
-    struct i596_private *lp = (struct i596_private *)dev->priv;
-    struct i596_cmd *cmd;
+	struct i596_private *lp = (struct i596_private *)dev->priv;
+	struct i596_cmd *cmd;
 
-    if (i596_debug > 1)
-	printk ("%s: set multicast list %d\n", dev->name, num_addrs);
+	if (i596_debug > 1)
+		printk ("%s: set multicast list %d\n", dev->name, num_addrs);
 
-    if (num_addrs > 0) {
-	cmd = (struct i596_cmd *) kmalloc(sizeof(struct i596_cmd)+2+num_addrs*6, GFP_ATOMIC);
-	if (cmd == NULL)
-	{
-	    printk ("%s: set_multicast Memory squeeze.\n", dev->name);
-	    return;
-	}
-
-	    cmd->command = CmdMulticastList;
-	    *((unsigned short *) (cmd + 1)) = num_addrs * 6;
-	    memcpy (((char *)(cmd + 1))+2, addrs, num_addrs * 6);
-	    print_eth (((char *)(cmd + 1)) + 2);
-		
-	    i596_add_cmd(dev, cmd);
-    } else
-    {
-	if (lp->set_conf.next != (struct i596_cmd * ) I596_NULL) return;
-	if (num_addrs == 0)
-	    lp->i596_config[8] &= ~0x01;
+	if (dev->mc_count > 0) 
+	{
+		struct dev_mc_list *dmi;
+		char *cp;
+		cmd = (struct i596_cmd *) kmalloc(sizeof(struct i596_cmd)+2+dev->mc_count*6, GFP_ATOMIC);
+		if (cmd == NULL)
+		{
+			printk ("%s: set_multicast Memory squeeze.\n", dev->name);
+			return;
+		}
+		cmd->command = CmdMulticastList;
+		*((unsigned short *) (cmd + 1)) = dev->mc_count * 6;
+		cp=((char *)(cmd + 1))+2
+		for(dmi=dev->mc_list;dmi!=NULL;dmi=dmi->next)
+		{
+			memcpy(cp, addr,6);
+			cp+=6;
+		}
+		print_eth (((char *)(cmd + 1)) + 2);
+		i596_add_cmd(dev, cmd);
+	}
 	else
-	    lp->i596_config[8] |= 0x01;
-
-	i596_add_cmd(dev, &lp->set_conf);
-    }
+	{
+		if (lp->set_conf.next != (struct i596_cmd * ) I596_NULL) 
+			return;
+		if (dev->mc_count == 0 && !(dev->flags&(IFF_PROMISC|IFF_ALLMULTI)))
+		{
+			if(dev->flags&IFF_ALLMULTI)
+				dev->flags|=IFF_PROMISC;
+			lp->i596_config[8] &= ~0x01;
+		}
+		else
+			lp->i596_config[8] |= 0x01;
 
+		i596_add_cmd(dev, &lp->set_conf);
+	}
 }
-#endif
 
 #ifdef HAVE_DEVLIST
 static unsigned int apricot_portlist[] = {0x300, 0};
diff -u --recursive --new-file v1.3.43/linux/drivers/net/at1700.c linux/drivers/net/at1700.c
--- v1.3.43/linux/drivers/net/at1700.c	Thu Nov  9 11:23:49 1995
+++ linux/drivers/net/at1700.c	Fri Nov 24 16:39:53 1995
@@ -121,7 +121,7 @@
 static void net_rx(struct device *dev);
 static int net_close(struct device *dev);
 static struct enet_statistics *net_get_stats(struct device *dev);
-static void set_multicast_list(struct device *dev, int num_addrs, void *addrs);
+static void set_multicast_list(struct device *dev);
 
 
 /* Check for a network adaptor of this type, and return '0' iff one exists.
@@ -611,10 +611,10 @@
 			best-effort filtering.
  */
 static void
-set_multicast_list(struct device *dev, int num_addrs, void *addrs)
+set_multicast_list(struct device *dev)
 {
 	short ioaddr = dev->base_addr;
-	if (num_addrs) 
+	if (dev->mc_count || dev->flags&(IFF_PROMISC|IFF_ALLMULTI)) 
 	{
 		/*
 		 *	We must make the kernel realise we had to move
diff -u --recursive --new-file v1.3.43/linux/drivers/net/atp.c linux/drivers/net/atp.c
--- v1.3.43/linux/drivers/net/atp.c	Tue Oct 10 18:46:35 1995
+++ linux/drivers/net/atp.c	Fri Nov 24 16:39:53 1995
@@ -140,7 +140,7 @@
 static void read_block(short ioaddr, int length, unsigned char *buffer, int data_mode);
 static int net_close(struct device *dev);
 static struct enet_statistics *net_get_stats(struct device *dev);
-static void set_multicast_list(struct device *dev, int num_addrs, void *addrs);
+static void set_multicast_list(struct device *dev);
 
 
 /* Check for a network adapter of this type, and return '0' iff one exists.
@@ -754,17 +754,18 @@
 	return &lp->stats;
 }
 
-/* Set or clear the multicast filter for this adapter.
-   num_addrs == -1	Promiscuous mode, receive all packets
-   num_addrs == 0	Normal mode, clear multicast list
-   num_addrs > 0	Multicast mode, receive normal and MC packets, and do
-			best-effort filtering.
+/*
+ *	Set or clear the multicast filter for this adapter.
  */
-static void
-set_multicast_list(struct device *dev, int num_addrs, void *addrs)
+ 
+static void set_multicast_list(struct device *dev)
 {
 	struct net_local *lp = (struct net_local *)dev->priv;
 	short ioaddr = dev->base_addr;
+	int num_addrs=dev->mc_list;
+	
+	if(dev->flags&(IFF_ALLMULTI|IFF_PROMISC))
+		num_addrs=1;
 	/*
 	 *	We must make the kernel realise we had to move
 	 *	into promisc mode or we start all out war on
diff -u --recursive --new-file v1.3.43/linux/drivers/net/de4x5.c linux/drivers/net/de4x5.c
--- v1.3.43/linux/drivers/net/de4x5.c	Thu Nov  9 11:23:49 1995
+++ linux/drivers/net/de4x5.c	Fri Nov 24 16:39:53 1995
@@ -399,7 +399,7 @@
 static void    de4x5_interrupt(int irq, struct pt_regs *regs);
 static int     de4x5_close(struct device *dev);
 static struct  enet_statistics *de4x5_get_stats(struct device *dev);
-static void    set_multicast_list(struct device *dev, int num_addrs, void *addrs);
+static void    set_multicast_list(struct device *dev);
 static int     de4x5_ioctl(struct device *dev, struct ifreq *rq, int cmd);
 
 /*
@@ -1384,35 +1384,42 @@
 **	                Set all multicast bits (pass all multicasts).
 */
 static void
-set_multicast_list(struct device *dev, int num_addrs, void *addrs)
+set_multicast_list(struct device *dev)
 {
-  struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
-  u_long iobase = dev->base_addr;
+	struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
+	u_long iobase = dev->base_addr;
 
-  /* First, double check that the adapter is open */
-  if (irq2dev_map[dev->irq] != NULL) {
-    if (num_addrs >= 0) {
-      SetMulticastFilter(dev, num_addrs, (char *)addrs);
-      if (lp->setup_f == HASH_PERF) {
-	load_packet(dev, lp->setup_frame, TD_IC | HASH_F | TD_SET | 
+	/* First, double check that the adapter is open */
+	if (irq2dev_map[dev->irq] != NULL) 
+	{
+		if (num_addrs >= 0) 
+		{
+		   	SetMulticastFilter(dev);
+			if (lp->setup_f == HASH_PERF) 
+			{
+				load_packet(dev, lp->setup_frame, TD_IC | HASH_F | TD_SET | 
 		                                        SETUP_FRAME_LEN, NULL);
-      } else {
-	load_packet(dev, lp->setup_frame, TD_IC | PERFECT_F | TD_SET | 
+      			}
+      			else
+      			{
+				load_packet(dev, lp->setup_frame, TD_IC | PERFECT_F | TD_SET | 
 		                                        SETUP_FRAME_LEN, NULL);
-      }
-
-      lp->tx_new = (++lp->tx_new) % lp->txRingSize;
-      outl(POLL_DEMAND, DE4X5_TPD);                /* Start the TX */
-      dev->trans_start = jiffies;
-    } else { /* set promiscuous mode */
-      u32 omr;
-      omr = inl(DE4X5_OMR);
-      omr |= OMR_PR;
-      outl(omr, DE4X5_OMR);
-    }
-  }
+			}
 
-  return;
+			lp->tx_new = (++lp->tx_new) % lp->txRingSize;
+			outl(POLL_DEMAND, DE4X5_TPD);                /* Start the TX */
+			dev->trans_start = jiffies;
+		}
+		else
+		{ 
+			/* set promiscuous mode */
+			u32 omr;
+			omr = inl(DE4X5_OMR);
+			omr |= OMR_PR;
+			outl(omr, DE4X5_OMR);
+		}
+	}
+	return;
 }
 
 /*
@@ -1420,64 +1427,88 @@
 ** from a list of ethernet multicast addresses.
 ** Little endian crc one liner from Matt Thomas, DEC.
 */
-static void SetMulticastFilter(struct device *dev, int num_addrs, char *addrs)
+static void SetMulticastFilter(struct device *dev)
 {
   struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
+  struct dev_mc_list *dmi=dev->mc_list;
   u_long iobase = dev->base_addr;
   int i, j, bit, byte;
   u16 hashcode;
   u32 omr, crc, poly = CRC_POLYNOMIAL_LE;
   char *pa;
+  unsigned char *addrs;
 
   omr = inl(DE4X5_OMR);
   pa = build_setup_frame(dev, ALL);          /* Build the basic frame */
 
-  if (lp->setup_f == HASH_PERF) {
-    if (num_addrs == HASH_TABLE_LEN) {       /* Pass all multicasts */
-      omr |= OMR_PM;
-    } else {
-      omr &= ~OMR_PM;
+  if (lp->setup_f == HASH_PERF) 
+  {
+  	if (num_addrs >= HASH_TABLE_LEN || (dev->flags&IFF_ALLMULTI)) 
+  	{
+  		/* Pass all multicasts */
+     		omr |= OMR_PM;
+	}
+	else
+	{
+		omr &= ~OMR_PM;
                                              /* Now update the MCA table */
-      for (i=0;i<num_addrs;i++) {            /* for each address in the list */
-	if ((*addrs & 0x01) == 1) {          /* multicast address? */ 
-	  crc = 0xffffffff;                  /* init CRC for each address */
-	  for (byte=0;byte<ETH_ALEN;byte++) {/* for each address byte */
-	                                     /* process each address bit */ 
-	    for (bit = *addrs++,j=0;j<8;j++, bit>>=1) {
-	      crc = (crc >> 1) ^ (((crc ^ bit) & 0x01) ? poly : 0);
-	    }
-	  }
-	  hashcode = crc & HASH_BITS;        /* hashcode is 9 LSb of CRC */
-
-	  byte = hashcode >> 3;              /* bit[3-8] -> byte in filter */
-	  bit = 1 << (hashcode & 0x07);      /* bit[0-2] -> bit in byte */
-
-	  byte <<= 1;                        /* calc offset into setup frame */
-	  if (byte & 0x02) {
-	    byte -= 1;
-	  }
-	  lp->setup_frame[byte] |= bit;
+		for (i=0;i<num_addrs;i++) 
+		{     
+			/* for each address in the list */
+			addrs=dmi->dmi_addr;
+			dmi=dmi->next;
+			if ((*addrs & 0x01) == 1) 
+			{       
+				/* multicast address? */ 
+				crc = 0xffffffff;                  /* init CRC for each address */
+				for (byte=0;byte<ETH_ALEN;byte++) 
+				{
+					/* for each address byte */
+	                        	/* process each address bit */ 
+					for (bit = *addrs++,j=0;j<8;j++, bit>>=1) 
+					{
+						crc = (crc >> 1) ^ (((crc ^ bit) & 0x01) ? poly : 0);
+					}
+				}
+				hashcode = crc & HASH_BITS;        /* hashcode is 9 LSb of CRC */
+
+				byte = hashcode >> 3;              /* bit[3-8] -> byte in filter */
+				bit = 1 << (hashcode & 0x07);      /* bit[0-2] -> bit in byte */
+
+				byte <<= 1;                        /* calc offset into setup frame */
+				if (byte & 0x02) 
+				{
+					byte -= 1;
+				}
+				lp->setup_frame[byte] |= bit;
 	  
-	} else {                             /* skip this address */
-	  addrs += ETH_ALEN;
+			}
+			else
+			{                             /* skip this address */
+				addrs += ETH_ALEN;
+			}
+		}
+	}
+	else
+	{                                   /* Perfect filtering */
+		omr &= ~OMR_PM;
+		for (j=0; j<dev->mc_count; j++) 
+		{
+			addrs=dmi->dmi_addr;
+			dmi=dmi->next;
+			for (i=0; i<ETH_ALEN; i++) 
+			{ 
+				*(pa + (i&1)) = *addrs++;
+				if (i & 0x01) pa += 4;
+			}
+		}
 	}
-      }
-    }
-  } else {                                   /* Perfect filtering */
-    omr &= ~OMR_PM;
-    for (j=0; j<num_addrs; j++) {
-      for (i=0; i<ETH_ALEN; i++) { 
-	*(pa + (i&1)) = *addrs++;
-	if (i & 0x01) pa += 4;
-      }
-    }
-  }
 
-  if (num_addrs == 0)
-    omr &= ~OMR_PR;
-  outl(omr, DE4X5_OMR);
+	if (dev->mc_count == 0)
+		omr &= ~OMR_PR;
+	outl(omr, DE4X5_OMR);
 
-  return;
+	return;
 }
 
 /*
diff -u --recursive --new-file v1.3.43/linux/drivers/net/de620.c linux/drivers/net/de620.c
--- v1.3.43/linux/drivers/net/de620.c	Thu Nov  9 11:23:49 1995
+++ linux/drivers/net/de620.c	Fri Nov 24 16:39:53 1995
@@ -206,7 +206,7 @@
 static int	de620_open(struct device *);
 static int	de620_close(struct device *);
 static struct netstats *get_stats(struct device *);
-static void	de620_set_multicast_list(struct device *, int, void *);
+static void	de620_set_multicast_list(struct device *);
 static int	de620_start_xmit(struct sk_buff *, struct device *);
 
 /* Dispatch from interrupts. */
@@ -481,15 +481,11 @@
  * Set or clear the multicast filter for this adaptor.
  * (no real multicast implemented for the DE-620, but she can be promiscuous...)
  *
- * num_addrs == -1	Promiscuous mode, receive all packets
- * num_addrs == 0	Normal mode, clear multicast list
- * num_addrs > 0	Multicast mode, receive normal and MC packets, and do
- *			best-effort filtering.
  */
-static void
-de620_set_multicast_list(struct device *dev, int num_addrs, void *addrs)
+
+static void de620_set_multicast_list(struct device *dev)
 {
-	if (num_addrs) 
+	if (dev->mc_count || dev->flags&(IFF_ALLMULTI|IFF_PROMISC)) 
 	{ /* Enable promiscuous mode */
 		/*
 		 *	We must make the kernel realise we had to move
@@ -500,7 +496,8 @@
 	
 		de620_set_register(dev, W_TCR, (TCR_DEF & ~RXPBM) | RXALL);
 	}
-	else { /* Disable promiscuous mode, use normal mode */
+	else 
+	{ /* Disable promiscuous mode, use normal mode */
 		de620_set_register(dev, W_TCR, TCR_DEF);
 	}
 }
diff -u --recursive --new-file v1.3.43/linux/drivers/net/depca.c linux/drivers/net/depca.c
--- v1.3.43/linux/drivers/net/depca.c	Thu Nov  9 11:23:49 1995
+++ linux/drivers/net/depca.c	Fri Nov 24 16:39:53 1995
@@ -363,7 +363,7 @@
 static int    depca_close(struct device *dev);
 static int    depca_ioctl(struct device *dev, struct ifreq *rq, int cmd);
 static struct enet_statistics *depca_get_stats(struct device *dev);
-static void   set_multicast_list(struct device *dev,int num_addrs,void *addrs);
+static void   set_multicast_list(struct device *dev);
 
 /*
 ** Private functions
@@ -379,7 +379,7 @@
 static int    DevicePresent(u_long ioaddr);
 static int    get_hw_addr(struct device *dev);
 static int    EISA_signature(char *name, s32 eisa_id);
-static void   SetMulticastFilter(struct device *dev,int num_addrs,char *addrs);
+static void   SetMulticastFilter(struct device *dev);
 static void   isa_probe(struct device *dev, u_long iobase);
 static void   eisa_probe(struct device *dev, u_long iobase);
 static struct device *alloc_device(struct device *dev, u_long iobase);
@@ -788,7 +788,7 @@
   lp->init_block.rx_ring = ((u32)((u_long)lp->rx_ring)&LA_MASK) | lp->rx_rlen;
   lp->init_block.tx_ring = ((u32)((u_long)lp->tx_ring)&LA_MASK) | lp->tx_rlen;
 
-  SetMulticastFilter(dev, 0, NULL);
+  SetMulticastFilter(dev);
 
   for (i = 0; i < ETH_ALEN; i++) {
     lp->init_block.phys_addr[i] = dev->dev_addr[i];
@@ -1151,13 +1151,9 @@
 
 /*
 ** Set or clear the multicast filter for this adaptor.
-** num_addrs == -1	Promiscuous mode, receive all packets
-** num_addrs == 0	Normal mode, clear multicast list
-** num_addrs > 0	Multicast mode, receive normal and MC packets, and do
-** 			best-effort filtering.
 */
 static void
-set_multicast_list(struct device *dev, int num_addrs, void *addrs)
+set_multicast_list(struct device *dev)
 {
   struct depca_private *lp = (struct depca_private *)dev->priv;
   u_long ioaddr = dev->base_addr;
@@ -1170,13 +1166,15 @@
     STOP_DEPCA;                       /* Temporarily stop the depca.  */
     depca_init_ring(dev);             /* Initialize the descriptor rings */
 
-    if (num_addrs >= 0) {
-      SetMulticastFilter(dev, num_addrs, (char *)addrs);
-      lp->init_block.mode &= ~PROM;   /* Unset promiscuous mode */
-    } else {
-      lp->init_block.mode |= PROM;    /* Set promiscuous mode */
+    if (dev->flags&(IFF_ALLMULTI|IFF_PROMISC)) 
+    {
+	lp->init_block.mode |= PROM;    /* Set promiscuous mode */
+    }
+    else
+    {
+    	SetMulticastFilter(dev);
+    	lp->init_block.mode &= ~PROM;   /* Unset promiscuous mode */
     }
-
     LoadCSRs(dev);                    /* Reload CSR3 */
     InitRestartDepca(dev);            /* Resume normal operation. */
     dev->tbusy = 0;                   /* Unlock the TX ring */
@@ -1189,25 +1187,31 @@
 ** Big endian crc one liner is mine, all mine, ha ha ha ha!
 ** LANCE calculates its hash codes big endian.
 */
-static void SetMulticastFilter(struct device *dev, int num_addrs, char *addrs)
+static void SetMulticastFilter(struct device *dev)
 {
   struct depca_private *lp = (struct depca_private *)dev->priv;
   int i, j, bit, byte;
   u16 hashcode;
   s32 crc, poly = CRC_POLYNOMIAL_BE;
+  struct dev_mc_list *dmi=dev->mc_list;
 
-  if (num_addrs == HASH_TABLE_LEN) {       /* Set all multicast bits */
-    for (i=0; i<(HASH_TABLE_LEN>>3); i++) {
-      lp->init_block.mcast_table[i] = (char)0xff;
-    }
-  } else {
+  if (dev->mc_count >= HASH_TABLE_LEN) 
+  {       /* Set all multicast bits */
+  	for (i=0; i<(HASH_TABLE_LEN>>3); i++) 
+  	{
+		lp->init_block.mcast_table[i] = (char)0xff;
+	}
+  }
+  else {
     /* Clear the multicast table first */
     for (i=0; i<(HASH_TABLE_LEN>>3); i++){
       lp->init_block.mcast_table[i]=0;
     }
 
     /* Add multicast addresses */
-    for (i=0;i<num_addrs;i++) {            /* for each address in the list */
+    for (i=0;i<dev->mc_count;i++) {            /* for each address in the list */
+      unsigned char *addrs=dmi->dmi_addr;
+      dmi=dmi->next;
       if ((*addrs & 0x01) == 1) {          /* multicast address? */ 
 	crc = 0xffffffff;                  /* init CRC for each address */
 	for (byte=0;byte<ETH_ALEN;byte++) {/* for each address byte */
@@ -1741,6 +1745,7 @@
     }
 
     break;
+#if 0    
   case DEPCA_SET_MCA:                /* Set a multicast address */
     if (suser()) {
       if (ioc->len != HASH_TABLE_LEN) {         /* MCA changes */
@@ -1772,6 +1777,7 @@
     }
 
     break;
+#endif    
   case DEPCA_GET_STATS:              /* Get the driver statistics */
     cli();
     ioc->len = sizeof(lp->pktStats);
diff -u --recursive --new-file v1.3.43/linux/drivers/net/eepro.c linux/drivers/net/eepro.c
--- v1.3.43/linux/drivers/net/eepro.c	Thu Nov  9 11:23:49 1995
+++ linux/drivers/net/eepro.c	Fri Nov 24 16:39:53 1995
@@ -140,7 +140,7 @@
 static void 	eepro_transmit_interrupt(struct device *dev);
 static int	eepro_close(struct device *dev);
 static struct enet_statistics *eepro_get_stats(struct device *dev);
-static void set_multicast_list(struct device *dev, int num_addrs, void *addrs);
+static void set_multicast_list(struct device *dev);
 
 static int read_eeprom(int ioaddr, int location);
 static void hardware_send_packet(struct device *dev, void *buf, short length);
@@ -351,7 +351,7 @@
 				printk("%c%02x", i ? ':' : ' ', dev->dev_addr[i]);
 			}
 				
-			outb(BANK2_SELECT, ioaddr); /* be CAREFULL, BANK 2 now */
+			outb(BANK2_SELECT, ioaddr); /* be CAREFUL, BANK 2 now */
 			id = inb(ioaddr + REG3);
 			if (id & TPE_BIT)
 				dev->if_port = TPE;
@@ -441,13 +441,13 @@
 	int irqlist[] = { 5, 9, 10, 11, 4, 3, 0};	
 	int *irqp = irqlist, temp_reg, ioaddr = dev->base_addr;
 
-	outb(BANK1_SELECT, ioaddr); /* be CAREFULL, BANK 1 now */
+	outb(BANK1_SELECT, ioaddr); /* be CAREFUL, BANK 1 now */
 
 	/* Enable the interrupt line. */
 	temp_reg = inb(ioaddr + REG1);
 	outb(temp_reg | INT_ENABLE, ioaddr + REG1); 
 	
-	outb(BANK0_SELECT, ioaddr); /* be CAREFULL, BANK 0 now */
+	outb(BANK0_SELECT, ioaddr); /* be CAREFUL, BANK 0 now */
 
 	/* clear all interrupts */
 	outb(ALL_MASK, ioaddr + STATUS_REG); 
@@ -455,7 +455,7 @@
 	outb(ALL_MASK & ~(EXEC_MASK), ioaddr + INT_MASK_REG); 
 
 	do {
-		outb(BANK1_SELECT, ioaddr); /* be CAREFULL, BANK 1 now */
+		outb(BANK1_SELECT, ioaddr); /* be CAREFUL, BANK 1 now */
 
 		temp_reg = inb(ioaddr + INT_NO_REG);
 		outb((temp_reg & 0xf8) | irqrmap[*irqp], ioaddr + INT_NO_REG); 
@@ -522,7 +522,7 @@
 
 	/* Initialize the 82595. */
 
-	outb(BANK2_SELECT, ioaddr); /* be CAREFULL, BANK 2 now */
+	outb(BANK2_SELECT, ioaddr); /* be CAREFUL, BANK 2 now */
 	temp_reg = inb(ioaddr + EEPROM_REG);
 	if (temp_reg & 0x10) /* Check the TurnOff Enable bit */
 		outb(temp_reg & 0xef, ioaddr + EEPROM_REG);
@@ -540,7 +540,7 @@
 	outb(temp_reg & 0x3f, ioaddr + REG3); /* clear test mode */
 
 	/* Set the receiving mode */
-	outb(BANK1_SELECT, ioaddr); /* be CAREFULL, BANK 1 now */
+	outb(BANK1_SELECT, ioaddr); /* be CAREFUL, BANK 1 now */
 	
 	temp_reg = inb(ioaddr + INT_NO_REG);
 	outb((temp_reg & 0xf8) | irqrmap[dev->irq], ioaddr + INT_NO_REG); 
@@ -769,19 +769,17 @@
 }
 
 /* Set or clear the multicast filter for this adaptor.
-   num_addrs == -1	Promiscuous mode, receive all packets
-   num_addrs == 0	Normal mode, clear multicast list
-   num_addrs > 0	Multicast mode, receive normal and MC packets, and do
-			best-effort filtering.
  */
 static void
-set_multicast_list(struct device *dev, int num_addrs, void *addrs)
+set_multicast_list(struct device *dev)
 {
 	struct eepro_local *lp = (struct eepro_local *)dev->priv;
 	short ioaddr = dev->base_addr;
 	unsigned short mode;
+	struct dev_mc_list *dmi=dev->mc_list;
 
-	if (num_addrs <= -1 || num_addrs > 63) {
+	if (dev->flags&(IFF_ALLMULTI|IFF_PROMISC) || dev->mc_count > 63) 
+	{
 		/*
 		 *	We must make the kernel realise we had to move
 		 *	into promisc mode or we start all out war on
@@ -790,7 +788,7 @@
 		 */
 		dev->flags|=IFF_PROMISC;		
 
-		outb(BANK2_SELECT, ioaddr); /* be CAREFULL, BANK 2 now */
+		outb(BANK2_SELECT, ioaddr); /* be CAREFUL, BANK 2 now */
 		mode = inb(ioaddr + REG2);
 		outb(mode | PRMSC_Mode, ioaddr + REG2);	
 		mode = inb(ioaddr + REG3);
@@ -798,16 +796,18 @@
 		outb(BANK0_SELECT, ioaddr); /* Return to BANK 0 now */
 		printk("%s: promiscuous mode enabled.\n", dev->name);
 	} 
-	else if (num_addrs == 0) {
-		outb(BANK2_SELECT, ioaddr); /* be CAREFULL, BANK 2 now */
+	else if (dev->mc_count==0 ) 
+	{
+		outb(BANK2_SELECT, ioaddr); /* be CAREFUL, BANK 2 now */
 		mode = inb(ioaddr + REG2);
 		outb(mode & 0xd6, ioaddr + REG2); /* Turn off Multi-IA and PRMSC_Mode bits */
 		mode = inb(ioaddr + REG3);
 		outb(mode, ioaddr + REG3); /* writing reg. 3 to complete the update */
 		outb(BANK0_SELECT, ioaddr); /* Return to BANK 0 now */
 	}
-	else {
-		unsigned short status, *eaddrs = addrs;
+	else 
+	{
+		unsigned short status, *eaddrs;
 		int i, boguscount = 0;
 		
 		/* Disable RX and TX interrupts.  Neccessary to avoid
@@ -815,7 +815,7 @@
 		   service routines. */
 		outb(ALL_MASK, ioaddr + INT_MASK_REG);
 
-		outb(BANK2_SELECT, ioaddr); /* be CAREFULL, BANK 2 now */
+		outb(BANK2_SELECT, ioaddr); /* be CAREFUL, BANK 2 now */
 		mode = inb(ioaddr + REG2);
 		outb(mode | Multi_IA, ioaddr + REG2);	
 		mode = inb(ioaddr + REG3);
@@ -825,8 +825,11 @@
 		outw(MC_SETUP, ioaddr + IO_PORT);
 		outw(0, ioaddr + IO_PORT);
 		outw(0, ioaddr + IO_PORT);
-		outw(6*(num_addrs + 1), ioaddr + IO_PORT);
-		for (i = 0; i < num_addrs; i++) {
+		outw(6*(dev->mc_count + 1), ioaddr + IO_PORT);
+		for (i = 0; i < dev->mc_count; i++) 
+		{
+			eaddrs=(unsigned short *)dmi->dmi_addr;
+			dmi=dmi->next;
 			outw(*eaddrs++, ioaddr + IO_PORT);
 			outw(*eaddrs++, ioaddr + IO_PORT);
 			outw(*eaddrs++, ioaddr + IO_PORT);
@@ -839,8 +842,9 @@
 		outb(MC_SETUP, ioaddr);
 
 		/* Update the transmit queue */
-		i = lp->tx_end + XMT_HEADER + 6*(num_addrs + 1);
-		if (lp->tx_start != lp->tx_end) { 
+		i = lp->tx_end + XMT_HEADER + 6*(dev->mc_count + 1);
+		if (lp->tx_start != lp->tx_end) 
+		{ 
 			/* update the next address and the chain bit in the 
 			   last packet */
 			outw(lp->tx_last + XMT_CHAIN, ioaddr + HOST_ADDRESS_REG);
@@ -849,13 +853,15 @@
 			status = inw(ioaddr + IO_PORT);
 			outw(status | CHAIN_BIT, ioaddr + IO_PORT);
 			lp->tx_end = i ;
-		} else lp->tx_start = lp->tx_end = i ;
+		}
+		else lp->tx_start = lp->tx_end = i ;
 
 		/* Acknowledge that the MC setup is done */
 		do { /* We should be doing this in the eepro_interrupt()! */
 			SLOW_DOWN_IO;
 			SLOW_DOWN_IO;
-			if (inb(ioaddr + STATUS_REG) & 0x08) {
+			if (inb(ioaddr + STATUS_REG) & 0x08) 
+			{
 				i = inb(ioaddr);
 				outb(0x08, ioaddr + STATUS_REG);
 				if (i & 0x20) { /* command ABORTed */
@@ -864,7 +870,7 @@
 					break;
 				} else if ((i & 0x0f) == 0x03)	{ /* MC-Done */
 					printk("%s: set Rx mode to %d addresses.\n", 
-						dev->name, num_addrs);
+						dev->name, dev->mc_count);
 					break;
 				}
 			}
diff -u --recursive --new-file v1.3.43/linux/drivers/net/eexpress.c linux/drivers/net/eexpress.c
--- v1.3.43/linux/drivers/net/eexpress.c	Thu Nov  9 11:23:49 1995
+++ linux/drivers/net/eexpress.c	Fri Nov 24 16:39:53 1995
@@ -290,7 +290,7 @@
 static void eexp_rx(struct device *dev);
 static int	eexp_close(struct device *dev);
 static struct enet_statistics *eexp_get_stats(struct device *dev);
-static void set_multicast_list(struct device *dev, int num_addrs, void *addrs);
+static void set_multicast_list(struct device *dev);
 
 static int read_eeprom(int ioaddr, int location);
 static void hardware_send_packet(struct device *dev, void *buf, short length);
@@ -671,13 +671,9 @@
 }
 
 /* Set or clear the multicast filter for this adaptor.
-   num_addrs == -1	Promiscuous mode, receive all packets
-   num_addrs == 0	Normal mode, clear multicast list
-   num_addrs > 0	Multicast mode, receive normal and MC packets, and do
-			best-effort filtering.
  */
 static void
-set_multicast_list(struct device *dev, int num_addrs, void *addrs)
+set_multicast_list(struct device *dev)
 {
 /* This doesn't work yet */
 #if 0
diff -u --recursive --new-file v1.3.43/linux/drivers/net/eth16i.c linux/drivers/net/eth16i.c
--- v1.3.43/linux/drivers/net/eth16i.c	Mon Nov 13 12:36:44 1995
+++ linux/drivers/net/eth16i.c	Fri Nov 24 16:39:53 1995
@@ -1,4 +1,4 @@
-/* eth16i.c An ICL EtherTeam 16i/32 ethernet driver for Linux
+/* eth16i.c An ICL EtherTeam 16i and 32 EISA ethernet driver for Linux
 
    Written 1994-95 by Mika Kuoppala
 
@@ -8,11 +8,15 @@
    This software may be used and distributed according to the terms
    of the GNU Public Licence, incorporated herein by reference.
 
-   The author may be reached as miku@pupu.elt.icl.fi
+   The author may be reached as miku@elt.icl.fi
+
+   This driver supports following cards :
+	- ICL EtherTeam 16i
+	- ICL EtherTeam 32 EISA
 
    Sources:
      - skeleton.c  a sample network driver core for linux,
-       written by Donald Becker <becker@cesdis.gsfc.nasa.gov>
+       written by Donald Becker <becker@CESDIS.gsfc.nasa.gov>
      - at1700.c a driver for Allied Telesis AT1700, written 
        by Donald Becker.
      - e16iSRV.asm a Netware 3.X Server Driver for ICL EtherTeam16i
@@ -68,7 +72,7 @@
 */
 
 static char *version = 
-	"eth16i.c: v0.21 17-10-95 Mika Kuoppala (miku@pupu.elt.icl.fi)\n";
+	"eth16i.c: v0.21 17-10-95 Mika Kuoppala (miku@elt.icl.fi)\n";
 
 #include <linux/module.h>
 
@@ -1147,7 +1151,9 @@
 {
   short ioaddr = dev->base_addr;
   
-  if(num_addrs) {
+  if(dev->mc_count || dev->flags&(IFF_ALLMULTI|IFF_PROMISC)) 
+  {
+    dev->flags|=IFF_PROMISC;	/* Must do this */
     outb(3, ioaddr + RECEIVE_MODE_REG);    
   } else {
     outb(2, ioaddr + RECEIVE_MODE_REG);
@@ -1197,16 +1203,10 @@
 
 void cleanup_module(void)
 {
-	if (MOD_IN_USE)
-		printk("eth16i: Device busy, remove delayed\n");
-	else
-	{
-		unregister_netdev( &dev_eth16i );
-
-		free_irq( dev_eth16i.irq );
-		irq2dev_map[ dev_eth16i.irq ] = NULL;
-		release_region( dev_eth16i.base_addr, ETH16I_IO_EXTENT );
-	}
+	unregister_netdev( &dev_eth16i );
+	free_irq( dev_eth16i.irq );
+	irq2dev_map[ dev_eth16i.irq ] = NULL;
+	release_region( dev_eth16i.base_addr, ETH16I_IO_EXTENT );
 }
 
 #endif /* MODULE */
diff -u --recursive --new-file v1.3.43/linux/drivers/net/ewrk3.c linux/drivers/net/ewrk3.c
--- v1.3.43/linux/drivers/net/ewrk3.c	Thu Nov  9 11:23:49 1995
+++ linux/drivers/net/ewrk3.c	Fri Nov 24 16:39:53 1995
@@ -290,7 +290,7 @@
 static void ewrk3_interrupt(int irq, struct pt_regs *regs);
 static int ewrk3_close(struct device *dev);
 static struct enet_statistics *ewrk3_get_stats(struct device *dev);
-static void set_multicast_list(struct device *dev, int num_addrs, void *addrs);
+static void set_multicast_list(struct device *dev);
 static int ewrk3_ioctl(struct device *dev, struct ifreq *rq, int cmd);
 
 /*
@@ -303,7 +303,7 @@
 
 static void EthwrkSignature(char * name, char *eeprom_image);
 static int  DevicePresent(short iobase);
-static void SetMulticastFilter(struct device *dev, int num_addrs, char *addrs, char *multicast_table);
+static void SetMulticastFilter(struct device *dev, int num_addr, char *multicast_table);
 
 static int  Read_EEPROM(short iobase, unsigned char eaddr);
 static int  Write_EEPROM(short data, short iobase, unsigned char eaddr);
@@ -723,11 +723,15 @@
   struct ewrk3_private *lp = (struct ewrk3_private *)dev->priv;
   char csr, page;
   short iobase = dev->base_addr;
+  int flags=dev->flags;
   
   /* 
   ** Enable all multicasts 
   */
-  set_multicast_list(dev, HASH_TABLE_LEN, NULL);
+  
+  dev->flags|=IFF_ALLMULTI;
+  set_multicast_list(dev);
+  dev->flags=flags;
 
   /*
   ** Clean out any remaining entries in all the queues here
@@ -1207,7 +1211,7 @@
 ** 			best-effort filtering.
 */
 static void
-set_multicast_list(struct device *dev, int num_addrs, void *addrs)
+set_multicast_list(struct device *dev)
 {
   struct ewrk3_private *lp = (struct ewrk3_private *)dev->priv;
   int iobase = dev->base_addr;
@@ -1216,21 +1220,24 @@
 
   csr = inb(EWRK3_CSR);
 
-  if (lp->shmem_length == IO_ONLY) {
+  if (lp->shmem_length == IO_ONLY) 
+  {
     multicast_table = (char *) PAGE0_HTE;
   } else {
     multicast_table = (char *)(lp->shmem_base + PAGE0_HTE);
   }
 
-  if (num_addrs >= 0) {
-    SetMulticastFilter(dev, num_addrs, (char *)addrs, multicast_table);
-    csr &= ~PME;
-    csr |= MCE;
-    outb(csr, EWRK3_CSR);
-  } else {                             /* set promiscuous mode */
+  if (dev->flags&(IFF_ALLMULTI|IFF_PROMISC)) 
+  {
     csr |= PME;
     csr &= ~MCE;
     outb(csr, EWRK3_CSR);
+    dev->flags|=IFF_PROMISC;
+  } else {                             /* set promiscuous mode */
+    SetMulticastFilter(dev, dev->mc_count, multicast_table);
+    csr &= ~PME;
+    csr |= MCE;
+    outb(csr, EWRK3_CSR);
   }
 }
 
@@ -1242,83 +1249,110 @@
 ** Note that when clearing the table, the broadcast bit must remain asserted
 ** to receive broadcast messages.
 */
-static void SetMulticastFilter(struct device *dev, int num_addrs, char *addrs, char *multicast_table)
+static void SetMulticastFilter(struct device *dev, int num_addrs, char *multicast_table)
 {
-  struct ewrk3_private *lp = (struct ewrk3_private *)dev->priv;
-  int i, iobase = dev->base_addr;
-  char j, bit, byte;
-  short *p = (short *) multicast_table;
-  u_short hashcode;
-  u_long crc, poly = CRC_POLYNOMIAL_LE;
-
-  while (set_bit(0, (void *)&lp->lock) != 0); /* Wait for lock to free */
-
-  if (lp->shmem_length == IO_ONLY) {
-    outb(0, EWRK3_IOPR);
-    outw((short)((long)multicast_table), EWRK3_PIR1);
-  } else {
-    outb(0, EWRK3_MPR);
-  }
+	struct ewrk3_private *lp = (struct ewrk3_private *)dev->priv;
+	char *addrs;
+	struct dev_mc_list *dmi=dev->mc_list;
+	int i, iobase = dev->base_addr;
+	char j, bit, byte;
+	short *p = (short *) multicast_table;
+	u_short hashcode;
+	u_long crc, poly = CRC_POLYNOMIAL_LE;
 
-  if (num_addrs == HASH_TABLE_LEN) {
-    for (i=0; i<(HASH_TABLE_LEN >> 3); i++) {
-      if (lp->shmem_length == IO_ONLY) {
-	outb(0xff, EWRK3_DATA);
-      } else {                /* memset didn't work here */
-	*p++ = 0xffff;
-	i++;
-      }
-    }
-  } else {
-    /* Clear table except for broadcast bit */
-    if (lp->shmem_length == IO_ONLY) {
-      for (i=0; i<(HASH_TABLE_LEN >> 4) - 1; i++) {
-	outb(0x00, EWRK3_DATA);
-      } 
-      outb(0x80, EWRK3_DATA); i++;           /* insert the broadcast bit */
-      for (; i<(HASH_TABLE_LEN >> 3); i++) {
-	outb(0x00, EWRK3_DATA);
-      } 
-    } else {
-      memset(multicast_table, 0, (HASH_TABLE_LEN >> 3));
-      *(multicast_table + (HASH_TABLE_LEN >> 4) - 1) = 0x80;
-    }
+	while (set_bit(0, (void *)&lp->lock) != 0); /* Wait for lock to free */
 
-    /* Update table */
-    for (i=0;i<num_addrs;i++) {              /* for each address in the list */
-      if ((*addrs & 0x01) == 1) {            /* multicast address? */ 
-	crc = 0xffffffff;                    /* init CRC for each address */
-	for (byte=0;byte<ETH_ALEN;byte++) {  /* for each address byte */
-	                                     /* process each address bit */ 
-	  for (bit = *addrs++,j=0;j<8;j++, bit>>=1) {
-	    crc = (crc >> 1) ^ (((crc ^ bit) & 0x01) ? poly : 0);
-	  }
+	if (lp->shmem_length == IO_ONLY) 
+	{
+		outb(0, EWRK3_IOPR);
+		outw((short)((long)multicast_table), EWRK3_PIR1);
+	} 
+	else
+	{
+		outb(0, EWRK3_MPR);
 	}
-	hashcode = crc & ((1 << 9) - 1);     /* hashcode is 9 LSb of CRC */
 
-	byte = hashcode >> 3;                /* bit[3-8] -> byte in filter */
-	bit = 1 << (hashcode & 0x07);        /* bit[0-2] -> bit in byte */
+	if (num_addrs >= HASH_TABLE_LEN) 
+	{
+		for (i=0; i<(HASH_TABLE_LEN >> 3); i++) 
+		{
+			if (lp->shmem_length == IO_ONLY) 
+			{
+				outb(0xff, EWRK3_DATA);
+			}
+			else
+			{                /* memset didn't work here */
+				*p++ = 0xffff;
+				i++;
+			}
+		}
+	}
+	else
+	{
+		/* Clear table except for broadcast bit */
+		if (lp->shmem_length == IO_ONLY) 
+		{
+			for (i=0; i<(HASH_TABLE_LEN >> 4) - 1; i++) 
+			{
+				outb(0x00, EWRK3_DATA);
+			} 
+			outb(0x80, EWRK3_DATA); i++;           /* insert the broadcast bit */
+			for (; i<(HASH_TABLE_LEN >> 3); i++) 
+			{
+				outb(0x00, EWRK3_DATA);
+			} 
+		}
+		else
+		{
+			memset(multicast_table, 0, (HASH_TABLE_LEN >> 3));
+			*(multicast_table + (HASH_TABLE_LEN >> 4) - 1) = 0x80;
+		}
 
-	if (lp->shmem_length == IO_ONLY) {
-	  unsigned char tmp;
+		/* Update table */
 
-	  outw((short)((long)multicast_table) + byte, EWRK3_PIR1);
-	  tmp = inb(EWRK3_DATA);
-	  tmp |= bit;
-	  outw((short)((long)multicast_table) + byte, EWRK3_PIR1);
-	  outb(tmp, EWRK3_DATA); 
-	} else {
-	  multicast_table[byte] |= bit;
+		for (i=0;i<dev->mc_count;i++) 
+		{
+		        /* for each address in the list */
+		        addrs=dmi->dmi_addr;
+		        dmi=dmi->next;
+		        
+			if ((*addrs & 0x01) == 1) 
+			{            /* multicast address? */ 
+				crc = 0xffffffff;                    /* init CRC for each address */
+				for (byte=0;byte<ETH_ALEN;byte++) 
+				{  /* for each address byte */
+	                           /* process each address bit */ 
+					for (bit = *addrs++,j=0;j<8;j++, bit>>=1) 
+					{
+						crc = (crc >> 1) ^ (((crc ^ bit) & 0x01) ? poly : 0);
+					}
+				}
+				hashcode = crc & ((1 << 9) - 1);     /* hashcode is 9 LSb of CRC */
+
+				byte = hashcode >> 3;                /* bit[3-8] -> byte in filter */
+				bit = 1 << (hashcode & 0x07);        /* bit[0-2] -> bit in byte */
+
+				if (lp->shmem_length == IO_ONLY) 
+				{
+					unsigned char tmp;
+
+					outw((short)((long)multicast_table) + byte, EWRK3_PIR1);
+					tmp = inb(EWRK3_DATA);
+					tmp |= bit;
+					outw((short)((long)multicast_table) + byte, EWRK3_PIR1);
+					outb(tmp, EWRK3_DATA); 
+				}
+				else
+				{
+					multicast_table[byte] |= bit;
+				}
+			}
+		}
 	}
-      } else {                               /* skip this address */
-	addrs += ETH_ALEN;
-      }
-    }
-  }
 
-  lp->lock = 0;                              /* Unlock the page register */
+	lp->lock = 0;                              /* Unlock the page register */
 
-  return;
+	return;
 }
 
 #ifndef MODULE
@@ -1669,7 +1703,8 @@
 
     break;
   case EWRK3_SAY_BOO:                /* Say "Boo!" to the kernel log file */
-    printk("%s: Boo!\n", dev->name);
+    if(suser())
+    	printk("%s: Boo!\n", dev->name);
 
     break;
   case EWRK3_GET_MCA:                /* Get the multicast address table */
@@ -1692,6 +1727,8 @@
     lp->lock = 0;                               /* Unlock the page register */
 
     break;
+    
+#if 0    
   case EWRK3_SET_MCA:                /* Set a multicast address */
     if (suser()) {
       err = verify_area(VERIFY_READ, (void *)ioc->data, ETH_ALEN * ioc->len);
@@ -1725,6 +1762,7 @@
     }
 
     break;
+#endif
   case EWRK3_GET_STATS:              /* Get the driver statistics */
     err = verify_area(VERIFY_WRITE, (void *)ioc->data, sizeof(lp->pktStats));
     if (err) return err;
diff -u --recursive --new-file v1.3.43/linux/drivers/net/hp100.c linux/drivers/net/hp100.c
--- v1.3.43/linux/drivers/net/hp100.c	Thu Nov  9 11:23:49 1995
+++ linux/drivers/net/hp100.c	Fri Nov 24 16:39:53 1995
@@ -195,9 +195,7 @@
 static struct enet_statistics *hp100_get_stats( struct device *dev );
 static void hp100_update_stats( struct device *dev );
 static void hp100_clear_stats( int ioaddr );
-#ifdef HAVE_MULTICAST
-static void hp100_set_multicast_list( struct device *dev, int num_addrs, void *addrs );
-#endif
+static void hp100_set_multicast_list( struct device *dev);
 static void hp100_interrupt( int irq, struct pt_regs *regs );
 
 static void hp100_start_interface( struct device *dev );
@@ -430,9 +428,7 @@
   dev -> stop = hp100_close;
   dev -> hard_start_xmit = hp100_start_xmit;
   dev -> get_stats = hp100_get_stats;
-#ifdef HAVE_MULTICAST
   dev -> set_multicast_list = &hp100_set_multicast_list;
-#endif
 
   request_region( dev -> base_addr, HP100_REGION_SIZE, eid -> name );
 
@@ -846,37 +842,30 @@
  *  multicast setup
  */
 
-#ifdef HAVE_MULTICAST
-
 /*
  *  Set or clear the multicast filter for this adapter.
- *
- *  num_addrs == -1             Promiscuous mode, receive all packets
- *  num_addrs == 0              Normal mode, clear multicast list
- *  num_addrs > 0               Multicast mode, receive normal and MC packets,
- *                              best-effort filtering.
  */
                                                           
-static void hp100_set_multicast_list( struct device *dev, int num_addrs, void *addrs )
+static void hp100_set_multicast_list( struct device *dev)
 {
   int ioaddr = dev -> base_addr;
   struct hp100_private *lp = (struct hp100_private *)dev -> priv;
 
 #ifdef HP100_DEBUG_MULTI
-  printk( "hp100_set_multicast_list: num_addrs = %d\n", num_addrs );
+  printk( "hp100_set_multicast_list: num_addrs = %d\n", dev->mc_count);
 #endif
   cli();
   hp100_ints_off();
   hp100_page( MAC_CTRL );
   hp100_andb( ~(HP100_RX_EN | HP100_TX_EN), MAC_CFG_1 );	/* stop rx/tx */
 
-  if ( num_addrs == -1 )
+  if ( dev->flags&IFF_PROMISC)
     {
       lp -> mac2_mode = HP100_MAC2MODE6;  /* promiscuous mode, all good */
       lp -> mac1_mode = HP100_MAC1MODE6;  /* packets on the net */
     }
    else
-  if ( num_addrs != 0 )
+  if ( dev->mc_count || dev->flags&IFF_ALLMULTI )
     {
       lp -> mac2_mode = HP100_MAC2MODE5;  /* multicast mode, packets for me */
       lp -> mac1_mode = HP100_MAC1MODE5;  /* broadcasts and all multicasts */
@@ -896,8 +885,6 @@
   hp100_ints_on();
   sti();
 }
-
-#endif /* HAVE_MULTICAST */
 
 /*
  *  hardware interrupt handling
diff -u --recursive --new-file v1.3.43/linux/drivers/net/lance.c linux/drivers/net/lance.c
--- v1.3.43/linux/drivers/net/lance.c	Mon Oct 16 18:38:23 1995
+++ linux/drivers/net/lance.c	Fri Nov 24 16:39:53 1995
@@ -257,9 +257,7 @@
 static void lance_interrupt(int irq, struct pt_regs *regs);
 static int lance_close(struct device *dev);
 static struct enet_statistics *lance_get_stats(struct device *dev);
-#ifdef HAVE_MULTICAST
-static void set_multicast_list(struct device *dev, int num_addrs, void *addrs);
-#endif
+static void set_multicast_list(struct device *dev);
 
 
 
@@ -1076,24 +1074,27 @@
 }
 
 /* Set or clear the multicast filter for this adaptor.
-   num_addrs == -2		All multicasts
-   num_addrs == -1		Promiscuous mode, receive all packets
-   num_addrs == 0		Normal mode, clear multicast list
-   num_addrs > 0		Multicast mode, receive normal and MC packets, and do
-						best-effort filtering.
  */
-static void
-set_multicast_list(struct device *dev, int num_addrs, void *addrs)
+
+static void set_multicast_list(struct device *dev, int num_addrs, void *addrs)
 {
 	short ioaddr = dev->base_addr;
 
 	outw(0, ioaddr+LANCE_ADDR);
 	outw(0x0004, ioaddr+LANCE_DATA); /* Temporarily stop the lance.	 */
 
-	if (num_addrs >= 0 || num_addrs==-2) {
+	if (dev->flags&IFF_PROMISC) {
+		/* Log any net taps. */
+		printk("%s: Promiscuous mode enabled.\n", dev->name);
+		outw(15, ioaddr+LANCE_ADDR);
+		outw(0x8000, ioaddr+LANCE_DATA); /* Set promiscuous mode */
+	} else {
 		short multicast_table[4];
 		int i;
-		/* We don't use the multicast table, but rely on upper-layer filtering. */
+		int num_addrs=dev->mc_count;
+		if(dev->flags&IFF_ALLMULTI)
+			num_addrs=1;
+		/* FIXIT: We don't use the multicast table, but rely on upper-layer filtering. */
 		memset(multicast_table, (num_addrs == 0) ? 0 : -1, sizeof(multicast_table));
 		for (i = 0; i < 4; i++) {
 			outw(8 + i, ioaddr+LANCE_ADDR);
@@ -1101,11 +1102,6 @@
 		}
 		outw(15, ioaddr+LANCE_ADDR);
 		outw(0x0000, ioaddr+LANCE_DATA); /* Unset promiscuous mode */
-	} else {
-		/* Log any net taps. */
-		printk("%s: Promiscuous mode enabled.\n", dev->name);
-		outw(15, ioaddr+LANCE_ADDR);
-		outw(0x8000, ioaddr+LANCE_DATA); /* Set promiscuous mode */
 	}
 
 	lance_restart(dev, 0x0142, 0); /*  Resume normal operation */
diff -u --recursive --new-file v1.3.43/linux/drivers/net/ni52.c linux/drivers/net/ni52.c
--- v1.3.43/linux/drivers/net/ni52.c	Sat Sep  9 15:26:52 1995
+++ linux/drivers/net/ni52.c	Fri Nov 24 16:39:53 1995
@@ -51,6 +51,8 @@
  */
 
 /*
+ * 18.Nov.95: Mcast changes (AC).
+ *
  * 19.Jan.95: verified (MH)
  *
  * 19.Sep.94: Added Multicast support (not tested yet) (MH)
@@ -163,10 +165,10 @@
 static int     ni52_close(struct device *dev);
 static int     ni52_send_packet(struct sk_buff *,struct device *);
 static struct  enet_statistics *ni52_get_stats(struct device *dev);
-static void    set_multicast_list(struct device *dev, int num_addrs, void *addrs);
+static void    set_multicast_list(struct device *dev);
 
 /* helper-functions */
-static int     init586(struct device *dev,int num_addrs,void *addrs);
+static int     init586(struct device *dev);
 static int     check586(struct device *dev,char *where,unsigned size);
 static void    alloc586(struct device *dev);
 static void    startrecv586(struct device *dev);
@@ -221,7 +223,7 @@
 static int ni52_open(struct device *dev)
 {
   alloc586(dev);
-  init586(dev,0,NULL);  
+  init586(dev);  
   startrecv586(dev);
 
   if(request_irq(dev->irq, &ni52_interrupt,0,"ni52")) 
@@ -446,7 +448,7 @@
  * needs a correct 'allocated' memory
  */
 
-static int init586(struct device *dev,int num_addrs,void *addrs)
+static int init586(struct device *dev)
 {
   void *ptr;
   unsigned long s;
@@ -456,6 +458,8 @@
   volatile struct iasetup_cmd_struct *ias_cmd;
   volatile struct tdr_cmd_struct *tdr_cmd;
   volatile struct mcsetup_cmd_struct *mc_cmd;
+  struct dev_mc_list *dmi=dev->mc_list;
+  int num_addrs=dev->mc_count;
 
   ptr = (void *) ((char *)p->scb + sizeof(struct scb_struct));
 
@@ -472,7 +476,12 @@
   cfg_cmd->ifs        = 0x60;
   cfg_cmd->time_low   = 0x00;
   cfg_cmd->time_high  = 0xf2;
-  cfg_cmd->promisc    = (num_addrs < 0) ? 1 : 0;  /* promisc on/off */
+  cfg_cmd->promisc    = 0;
+  if(dev->flags&(IFF_ALLMULTI|IFF_PROMISC))
+  {
+	cfg_cmd->promisc=1;
+	dev->flags|=IFF_PROMISC;
+  }
   cfg_cmd->carr_coll  = 0x00;
  
   p->scb->cbl_offset = make16(cfg_cmd);
@@ -598,7 +607,7 @@
    * Multicast setup
    */
   
-  if(num_addrs > 0)
+  if(dev->mc_count)
   { /* I don't understand this: do we really need memory after the init? */
     int len = ((char *) p->iscp - (char *) ptr - 8) / 6;
     if(len <= 0)
@@ -609,6 +618,7 @@
     {
       if(len < num_addrs)
       {
+      	/* BUG - should go ALLMULTI in this case */
         num_addrs = len;
         printk("%s: Sorry, can only apply %d MC-Address(es).\n",dev->name,num_addrs);
       }
@@ -618,7 +628,10 @@
       mc_cmd->cmd_link = 0xffff;
       mc_cmd->mc_cnt = num_addrs * 6;
       for(i=0;i<num_addrs;i++)
-        memcpy((char *) mc_cmd->mc_list[i],((char (*)[6]) addrs)[i],6);
+      {
+		memcpy((char *) mc_cmd->mc_list[i], dmi->dmi_addr,6);
+		dmi=dmi->next;
+      }
       p->scb->cbl_offset = make16(mc_cmd);
       p->scb->cmd = CUC_START;
       ni_attn586();
@@ -1077,9 +1090,9 @@
  * Set MC list ..  
  */
 
-static void set_multicast_list(struct device *dev, int num_addrs, void *addrs)
+static void set_multicast_list(struct device *dev)
 {
-  if(!dev->start && !num_addrs)
+  if(!dev->start)
   {
     printk("%s: Can't apply promiscuous/multicastmode to a not running interface.\n",dev->name);
     return;
@@ -1087,7 +1100,7 @@
 
   dev->start = 0;
   alloc586(dev);
-  init586(dev,num_addrs,addrs);  
+  init586(dev);  
   startrecv586(dev);
   dev->start = 1;
 }
diff -u --recursive --new-file v1.3.43/linux/drivers/net/ni65.c linux/drivers/net/ni65.c
--- v1.3.43/linux/drivers/net/ni65.c	Tue Oct 10 18:46:36 1995
+++ linux/drivers/net/ni65.c	Fri Nov 24 16:39:53 1995
@@ -21,6 +21,8 @@
  */
 
 /*
+ * Nov.18: multicast tweaked (AC).
+ *
  * Aug.22: changes in xmit_intr (ack more than one xmitted-packet), ni65_send_packet (p->lock) (MH)
  *
  * July.16: fixed bugs in recv_skb and skb-alloc stuff  (MH)
@@ -121,7 +123,7 @@
 static int   ni65_close(struct device *dev);
 static struct enet_statistics *ni65_get_stats(struct device *);
 
-static void set_multicast_list(struct device *dev, int num_addrs, void *addrs);
+static void set_multicast_list(struct device *dev);
 
 struct priv 
 {
@@ -636,7 +638,7 @@
   return &((struct priv *) dev->priv)->stats;
 }
 
-static void set_multicast_list(struct device *dev, int num_addrs, void *addrs)
+static void set_multicast_list(struct device *dev)
 {
 }
 
diff -u --recursive --new-file v1.3.43/linux/drivers/net/seeq8005.c linux/drivers/net/seeq8005.c
--- v1.3.43/linux/drivers/net/seeq8005.c	Wed Nov  8 07:11:33 1995
+++ linux/drivers/net/seeq8005.c	Fri Nov 24 16:39:53 1995
@@ -85,7 +85,7 @@
 static void seeq8005_rx(struct device *dev);
 static int seeq8005_close(struct device *dev);
 static struct enet_statistics *seeq8005_get_stats(struct device *dev);
-static void set_multicast_list(struct device *dev, int num_addrs, void *addrs);
+static void set_multicast_list(struct device *dev);
 
 /* Example routines you must write ;->. */
 #define tx_done(dev)	(inw(SEEQ_STATUS) & SEEQSTAT_TX_ON)
@@ -608,7 +608,7 @@
 			best-effort filtering.
  */
 static void
-set_multicast_list(struct device *dev, int num_addrs, void *addrs)
+set_multicast_list(struct device *dev)
 {
 /*
  * I _could_ do upto 6 addresses here, but wont (yet?)
@@ -623,6 +623,7 @@
  
 	if (num_addrs) {			/* Enable promiscuous mode */
 		outw( (inw(SEEQ_CFG1) & ~SEEQCFG1_MATCH_MASK)| SEEQCFG1_MATCH_ALL,  SEEQ_CFG1);
+		dev->flags|=IFF_PROMISC;
 	} else {				/* Disable promiscuous mode, use normal mode */
 		outw( (inw(SEEQ_CFG1) & ~SEEQCFG1_MATCH_MASK)| SEEQCFG1_MATCH_BROAD, SEEQ_CFG1);
 	}
diff -u --recursive --new-file v1.3.43/linux/drivers/net/sk_g16.c linux/drivers/net/sk_g16.c
--- v1.3.43/linux/drivers/net/sk_g16.c	Tue Oct 10 18:46:37 1995
+++ linux/drivers/net/sk_g16.c	Fri Nov 24 16:39:53 1995
@@ -496,9 +496,7 @@
 
 unsigned int SK_rom_addr(void);
 
-#ifdef HAVE_MULTICAST
-static void set_multicast_list(struct device *dev, int num_addrs, void *addrs);
-#endif
+static void set_multicast_list(struct device *dev);
 
 /*
  * LANCE Functions
@@ -798,10 +796,7 @@
     dev->stop                   = &SK_close;
     dev->hard_start_xmit        = &SK_send_packet;
     dev->get_stats              = &SK_get_stats;
-
-#ifdef HAVE_MULTICAST
     dev->set_multicast_list     = &set_multicast_list;
-#endif
 
 
     /* Set the generic fields of the device structure */
@@ -1706,7 +1701,6 @@
 
 } /* End of SK_get_stats() */
 
-#ifdef HAVE_MULTICAST
 
 /*-
  * Function       : set_multicast_list
@@ -1724,32 +1718,27 @@
  *                  that all information on the net is not encrypted.
  *
  * Parameters     : I : struct device *dev - SK_G16 device Structure
- *                  I : int num_addrs      - explanation further down
- *                  I : void *addrs        - 
  * Return Value   : None
  * Errors         : None
  * Globals        : None
  * Update History :
  *     YY/MM/DD  uid  Description
+ *     95/10/18  ACox  Noew multicast calling scheme
 -*/
 
 
 /* Set or clear the multicast filter for SK_G16.
- *
- * num_addrs == -1      Promiscuous mode, receive all packets
- * num_addrs == 0       Normal mode, clear multicast list
- * num_addrs > 0        Multicast mode, receive normal and MC packets
  */
 
 static void set_multicast_list(struct device *dev, int num_addrs, void *addrs)
 {
 
-    if (num_addrs == -1)
+    if (dev->flags&IFF_PROMISC)
     {
 	/* Reinitialize LANCE with MODE_PROM set */
 	SK_lance_init(dev, MODE_PROM);
     }
-    else if (num_addrs == 0)
+    else if (dev->mc_count==0 && !(dev->flags&IFF_ALLMULTI))
     {
 	/* Reinitialize LANCE without MODE_PROM */
 	SK_lance_init(dev, MODE_NORMAL);
@@ -1757,6 +1746,8 @@
     else
     {
 	/* Multicast with logical address filter on */
+	/* Reinitialize LANCE without MODE_PROM */
+	SK_lance_init(dev, MODE_NORMAL);
 	
 	/* Not implemented yet. */
     }
diff -u --recursive --new-file v1.3.43/linux/drivers/net/skeleton.c linux/drivers/net/skeleton.c
--- v1.3.43/linux/drivers/net/skeleton.c	Thu Nov  9 11:23:50 1995
+++ linux/drivers/net/skeleton.c	Fri Nov 24 16:39:53 1995
@@ -102,7 +102,7 @@
 static void net_rx(struct device *dev);
 static int net_close(struct device *dev);
 static struct enet_statistics *net_get_stats(struct device *dev);
-static void set_multicast_list(struct device *dev, int num_addrs, void *addrs);
+static void set_multicast_list(struct device *dev);
 
 /* Example routines you must write ;->. */
 #define tx_done(dev) 1
@@ -514,13 +514,24 @@
 			best-effort filtering.
  */
 static void
-set_multicast_list(struct device *dev, int num_addrs, void *addrs)
+set_multicast_list(struct device *dev)
 {
 	short ioaddr = dev->base_addr;
-	if (num_addrs) {
-		outw(69, ioaddr);		/* Enable promiscuous mode */
-	} else
-		outw(99, ioaddr);		/* Disable promiscuous mode, use normal mode */
+	if (dev->flags&IFF_PROMISC) {
+		outw(MULTICAST|PROMISC, ioaddr);		/* Enable promiscuous mode */
+	}
+	else if((dev->flags&IFF_ALLMULTI) || dev->mc_count > HW_MAX_ADDRS)
+	{
+		hardware_set_filter(NULL);
+		outw(MULTICAST, ioaddr);		/* Disable promiscuous mode, use normal mode */
+	}
+	else if(dev->mc_count)
+	{
+		hardware_set_filter(dev->mc_list);	/* Walk the address list and load the filter */
+		outw(MULTICAST, ioaddr);
+	}
+	else 
+		outw(0, ioaddr);
 }
 
 #ifdef MODULE
diff -u --recursive --new-file v1.3.43/linux/drivers/net/slip.c linux/drivers/net/slip.c
--- v1.3.43/linux/drivers/net/slip.c	Thu Nov  9 11:23:50 1995
+++ linux/drivers/net/slip.c	Fri Nov 24 16:39:53 1995
@@ -998,7 +998,8 @@
 static int
 sl_set_dev_mac_address(struct device *dev, void *addr)
 {
-	memcpy(dev->dev_addr, addr, AX25_ADDR_LEN);
+	struct sockaddr *sa=addr;
+	memcpy(dev->dev_addr, sa->sa_data, AX25_ADDR_LEN);
 	return 0;
 }
 #endif /* CONFIG_AX25 */
diff -u --recursive --new-file v1.3.43/linux/drivers/net/sunlance.c linux/drivers/net/sunlance.c
--- v1.3.43/linux/drivers/net/sunlance.c	Thu Jan  1 02:00:00 1970
+++ linux/drivers/net/sunlance.c	Fri Nov 24 17:17:31 1995
@@ -0,0 +1,799 @@
+/* lance.c: Linux/Sparc/Lance driver */
+/*
+	Written 1995 by Miguel de Icaza
+  Sources:
+	The Linux  depca driver
+	The Linux  lance driver.
+	The Linux  skeleton driver.
+        The NetBSD Sparc/Lance driver.
+	Theo Deraadt (deraadt@theos.com)
+	NCR92C990 Lan Controller manual
+*/
+
+static char *version =
+	"lance.c:v1.2 29/Oct/95 Miguel de Icaza (miguel@nuclecu.unam.mx)\n";
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/interrupt.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/in.h>
+#include <linux/malloc.h>
+#include <linux/string.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <linux/errno.h>
+#include <asm/byteorder.h>	/* Used by the checksum routines */
+
+/* Used for the temporal inet entries and routing */
+#include <linux/socket.h>
+#include <linux/route.h>
+
+#include <asm/idprom.h>
+#include <asm/sbus.h>
+#include <asm/openprom.h>
+#include <asm/oplib.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+
+#define MASK_INTERRUPTS   1
+#define UNMASK_INTERRUPTS 0
+
+/* Define: 2^2 Tx buffers and 2^4 Rx buffers */
+#ifndef LANCE_LOG_TX_BUFFERS
+#define LANCE_LOG_TX_BUFFERS 2
+#define LANCE_LOG_RX_BUFFERS 4
+#endif
+
+#define LE_CSR0 0
+#define LE_CSR1 1
+#define LE_CSR2 2
+#define LE_CSR3 3
+
+#define LE_MO_PROM      0x8000  /* Enable promiscuous mode */
+
+#define	LE_C0_ERR	0x8000	/* Error: set if BAB, SQE, MISS or ME is set */
+#define	LE_C0_BABL	0x4000	/* BAB:  Babble: tx timeout. */
+#define	LE_C0_CERR	0x2000	/* SQE:  Signal quality error */
+#define	LE_C0_MISS	0x1000	/* MISS: Missed a packaed */
+#define	LE_C0_MERR	0x0800	/* ME:   Memory error */
+#define	LE_C0_RINT	0x0400	/* Received interrupt */
+#define	LE_C0_TINT	0x0200	/* Transmitter Interrupt */
+#define	LE_C0_IDON	0x0100	/* IFIN: Init finished. */
+#define	LE_C0_INTR	0x0080	/* Interrupt or error */
+#define	LE_C0_INEA	0x0040	/* Interrupt enable */
+#define	LE_C0_RXON	0x0020	/* Receiver on */
+#define	LE_C0_TXON	0x0010	/* Transmitter on */
+#define	LE_C0_TDMD	0x0008	/* Transmiter demand */
+#define	LE_C0_STOP	0x0004	/* Stop the card */
+#define	LE_C0_STRT	0x0002	/* Start the card */
+#define	LE_C0_INIT	0x0001	/* Init the card */
+
+#define	LE_C3_BSWP	0x4     /* SWAP */
+#define	LE_C3_ACON	0x2	/* ALE Control */
+#define	LE_C3_BCON	0x1	/* Byte control */
+
+/* Receive message descriptor 1 */
+#define LE_R1_OWN       0x80    /* Who owns the entry */
+#define LE_R1_ERR       0x40    /* Error: if FRA, OFL, CRC or BUF is set */
+#define LE_R1_FRA       0x20    /* FRA: Frame error */
+#define LE_R1_OFL       0x10    /* OFL: Frame overflow */
+#define LE_R1_CRC       0x08    /* CRC error */
+#define LE_R1_BUF       0x04    /* BUF: Buffer error */
+#define LE_R1_SOP       0x02    /* Start of packet */
+#define LE_R1_EOP       0x01    /* End of packet */
+#define LE_R1_POK       0x03    /* Packet is complete: SOP + EOP */
+
+#define LE_T1_OWN       0x80    /* Lance owns the packet */
+#define LE_T1_ERR       0x40    /* Error summary */
+#define LE_T1_EONE      0x08    /* Error: one retry needed */
+#define LE_T1_EDEF      0x04    /* Error: defered */
+#define LE_T1_SOP       0x02    /* Start of packet */
+#define LE_T1_EOP       0x01    /* End of packet */
+
+#define LE_T3_BUF       0x8000  /* Buffer error */
+#define LE_T3_UFL       0x4000  /* Error undeflow */
+#define LE_T3_LCOL      0x1000  /* Error late collision */
+#define LE_T3_CLOS      0x0800  /* Error carrier loss */
+#define LE_T3_RTY       0x0400  /* Error retry */
+#define LE_T3_TDR       0x03ff  /* Time Domain Reflectometry counter */
+
+#define TX_RING_SIZE			(1 << (LANCE_LOG_TX_BUFFERS))
+#define TX_RING_MOD_MASK		(TX_RING_SIZE - 1)
+#define TX_RING_LEN_BITS		((LANCE_LOG_TX_BUFFERS) << 29)
+
+#define RX_RING_SIZE			(1 << (LANCE_LOG_RX_BUFFERS))
+#define RX_RING_MOD_MASK		(RX_RING_SIZE - 1)
+#define RX_RING_LEN_BITS		((LANCE_LOG_RX_BUFFERS) << 29)
+
+#define PKT_BUF_SZ		1544
+#define RX_BUFF_SIZE            1536
+#define TX_BUFF_SIZE            1536
+
+struct lance_rx_desc {
+    unsigned short rmd0;        /* low address of packet */
+    unsigned char  rmd1_bits;   /* descriptor bits */
+    unsigned char  rmd1_hadr;   /* high address of packet */
+    short    length;    	/* This length is 2s complement (negative)! Buffer length */
+    unsigned short mblength;		/* This is the actual number of bytes received */
+};
+
+struct lance_tx_desc {
+    unsigned short tmd0;        /* low address of packet */
+    unsigned char  tmd1_bits;   /* descriptor bits */
+    unsigned char  tmd1_hadr;   /* high address of packet */
+    short length;          	/* Length is 2s complement (negative)! */
+    unsigned short misc;
+};
+		
+/* The LANCE initialization block, described in databook. */
+/* On the Sparc, this block should be on a DMA region     */
+struct lance_init_block {
+    unsigned short mode;		/* Pre-set mode (reg. 15) */
+    unsigned char phys_addr[6];         /* Physical ethernet address */
+    unsigned filter[2];			/* Multicast filter. */
+    
+    /* Receive and transmit ring base, along with extra bits. */
+    unsigned short rx_ptr;		/* receive descriptor addr */
+    unsigned short rx_len;		/* receive len and high addr */
+    unsigned short tx_ptr;		/* transmit descriptor addr */
+    unsigned short tx_len;		/* transmit len and high addr */
+    
+    /* The Tx and Rx ring entries must aligned on 8-byte boundaries. */
+    struct lance_rx_desc brx_ring[RX_RING_SIZE];
+    struct lance_tx_desc btx_ring[TX_RING_SIZE];
+    
+    char   rx_buf [RX_RING_SIZE][RX_BUFF_SIZE];
+    char   tx_buf [TX_RING_SIZE][TX_BUFF_SIZE];
+};
+
+struct lance_private {
+	char *name;
+	volatile struct lance_regs *ll;
+	volatile struct lance_init_block *init_block;
+	
+	int rx_new, tx_new;
+	int rx_old, tx_old;
+
+	struct enet_statistics stats;
+};
+
+#define TX_BUFFS_AVAIL ((lp->tx_old<=lp->tx_new)?\
+			lp->tx_old+TX_RING_MOD_MASK-lp->tx_new:\
+			lp->tx_old - lp->tx_new-1)
+
+/* On the sparc, the lance control ports are memory mapped */
+struct lance_regs {
+    unsigned short rdp;			/* register data port */
+    unsigned short rap;			/* register address port */
+};
+
+int sparc_lance_debug = 2;
+
+/* The Lance uses 24 bit addresses */
+/* The DVMA will provide the remaining bytes for us */
+#define LANCE_ADDR(x) ((int)(x) & ~0xff000000)
+
+/* Load the CSR registers */
+static void load_csrs (struct lance_private *lp)
+{
+    volatile struct lance_regs *ll = lp->ll;
+    volatile struct lance_init_block *ib = lp->init_block;
+    int leptr;
+
+    leptr = LANCE_ADDR (ib);
+    ll->rap = LE_CSR1;
+    ll->rdp = (leptr & 0xFFFF);
+    ll->rap = LE_CSR2;
+    ll->rdp = leptr >> 16;
+    ll->rap = LE_CSR3;
+    ll->rdp = LE_C3_BSWP | LE_C3_ACON | LE_C3_BCON;
+
+    /* Point back to csr0 */
+    ll->rap = LE_CSR0;
+}
+
+#define ZERO 0
+
+/* Setup the Lance Rx and Tx rings */
+/* Sets dev->tbusy */
+static void
+lance_init_ring (struct device *dev)
+{
+    struct lance_private *lp = (struct lance_private *) dev->priv;
+    volatile struct lance_init_block *ib = lp->init_block;
+    int leptr;
+    int i;
+    
+    /* Lock out other processes while setting up harware */
+    dev->tbusy = 1;
+    lp->rx_new = lp->tx_new = 0;
+    lp->rx_old = lp->tx_old = 0;
+
+    ib->mode = 0;
+
+    /* Copy the ethernet address to the lance init block
+     * Note that on the sparc you need to swap the ethernet address.
+     */
+    ib->phys_addr [0] = dev->dev_addr [1];
+    ib->phys_addr [1] = dev->dev_addr [0];
+    ib->phys_addr [2] = dev->dev_addr [3];
+    ib->phys_addr [3] = dev->dev_addr [2];
+    ib->phys_addr [4] = dev->dev_addr [5];
+    ib->phys_addr [5] = dev->dev_addr [4];
+
+    if (ZERO)
+	printk ("TX rings:\n");
+    
+    /* Setup the Tx ring entries */
+    for (i = 0; i <= TX_RING_SIZE; i++){
+	leptr = LANCE_ADDR(&ib->tx_buf[i][0]);
+	ib->btx_ring [i].tmd0      = leptr;
+	ib->btx_ring [i].tmd1_hadr = leptr >> 16;
+	ib->btx_ring [i].tmd1_bits = 0;
+	ib->btx_ring [i].length    = 0xf000; /* The ones required by tmd2 */
+	ib->btx_ring [i].misc      = 0;
+	if (i < 3)
+	    if (ZERO) printk ("%d: 0x%8.8x\n", i, leptr);
+    }
+
+    /* Setup the Rx ring entries */
+    if (ZERO) printk ("RX rings:\n");
+    for (i = 0; i < RX_RING_SIZE; i++){
+	leptr = LANCE_ADDR(&ib->rx_buf[i][0]);
+
+	ib->brx_ring [i].rmd0      = leptr;
+	ib->brx_ring [i].rmd1_hadr = leptr >> 16;
+	ib->brx_ring [i].rmd1_bits = LE_R1_OWN;
+	ib->brx_ring [i].length    = -RX_BUFF_SIZE | 0xf000;
+	ib->brx_ring [i].mblength  = 0;
+	if (i < 3)
+	    if (ZERO) printk ("%d: 0x%8.8x\n", i, leptr);
+    }
+
+    /* Setup the initialization block */
+    
+    /* Setup rx descriptor pointer */
+    leptr = LANCE_ADDR(&ib->brx_ring);
+    ib->rx_len = (LANCE_LOG_RX_BUFFERS << 13) | (leptr >> 16);
+    ib->rx_ptr = leptr;
+    if (ZERO) printk ("RX ptr: %8.8x\n", leptr);
+    
+    /* Setup tx descriptor pointer */
+    leptr = LANCE_ADDR(&ib->btx_ring);
+    ib->tx_len = (LANCE_LOG_TX_BUFFERS << 13) | (leptr >> 16);
+    ib->tx_ptr = leptr;
+    if (ZERO) printk ("TX ptr: %8.8x\n", leptr);
+
+    /* Clear the multicast filter */
+    ib->filter [0] = 0;
+    ib->filter [1] = 0;
+}
+
+static int init_restart_lance (struct lance_private *lp)
+{
+    volatile struct lance_regs *ll = lp->ll;
+    int i;
+
+    ll->rap = LE_CSR0;
+    ll->rdp = LE_C0_INIT;
+
+    /* Wait for the lance to complete initialization */
+    for (i = 0; (i < 100) && !(ll->rdp & (LE_C0_ERR | LE_C0_IDON)); i++)
+	;
+    if ((i == 100) || (ll->rdp & LE_C0_ERR)){
+	printk ("LANCE unopened after %d ticks, csr0=%4.4x.\n", i, ll->rdp);
+	return -1;
+    }
+
+    /* Clear IDON by writing a "1", enable interrupts and start lance */
+    ll->rdp = LE_C0_IDON;
+    ll->rdp = LE_C0_INEA | LE_C0_STRT;
+    printk ("LANCE opened after %d ticks, csr0=%4.4x\n", i, ll->rdp);
+    return 0;
+}
+
+static int
+lance_rx (struct device *dev)
+{
+    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;
+    volatile struct lance_rx_desc *rd;
+    int i;
+    int entry;
+    unsigned char bits;
+
+#ifdef TEST_HITS
+    printk ("[");
+    for (i = 0; i < RX_RING_SIZE; i++){
+	    if (i == lp->rx_new)
+		    printk ("%s", ib->brx_ring [i].rmd1_bits & LE_R1_OWN ? "_" : "X");
+	    else
+		    printk ("%s", ib->brx_ring [i].rmd1_bits & LE_R1_OWN ? "." : "1");
+    }
+    printk ("]");
+#endif
+    
+#ifdef OLD_METHOD
+    ll->rdp = LE_C0_RINT|LE_C0_INEA;
+    /* FIXME: Add slot prediction */
+    for (rd = &ib->brx_ring [i = 0]; i < RX_RING_SIZE; i++, rd++){
+	int bits;
+	
+	bits = rd->rmd1_bits;
+
+	/* Check if we own the packet */
+	if (bits & LE_R1_OWN)
+	    continue;
+
+	/* We got an incomplete frame? */
+	if ((bits & LE_R1_POK) != LE_R1_POK){
+	    /* Count only the end frame as a tx error, not the beginning */
+	    if (bits & LE_R1_EOP) lp->stats.rx_errors++;
+	    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++;
+	} else {
+	    int pkt_len = rd->mblength;
+	    struct sk_buff *skb;
+	    char *buf;
+	    
+	    skb = dev_alloc_skb (pkt_len+2);
+	    if (skb == NULL){
+		printk ("%s: Memory squeeze, deferring packet.\n", dev->name);
+		lp->stats.rx_dropped++;
+		rd->rmd1_bits = LE_R1_OWN;
+		return 0;
+	    }
+	    
+	    skb->dev = dev;
+	    skb_reserve (skb, 2);               /* 16 byte align */
+	    buf = skb_put (skb, pkt_len);       /* make room */
+	    memcpy (buf, &(ib->rx_buf [i][0]), pkt_len);
+	    skb->protocol = eth_type_trans (skb,dev);
+	    netif_rx (skb);
+	    lp->stats.rx_packets++;
+	}
+
+	/* Return the packet to the pool */
+	rd->rmd1_bits = LE_R1_OWN;
+    }
+#else
+    ll->rdp = LE_C0_RINT|LE_C0_INEA;
+    for (rd = &ib->brx_ring [lp->rx_new];
+	 !((bits = rd->rmd1_bits) & LE_R1_OWN);
+	 rd = &ib->brx_ring [lp->rx_new]){
+
+	/* We got an incomplete frame? */
+	if ((bits & LE_R1_POK) != LE_R1_POK){
+	    printk ("Incomplete frame\n");
+	    /* Count only the end frame as a tx error, not the beginning */
+	    if (bits & LE_R1_EOP) lp->stats.rx_errors++;
+	    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++;
+	} else {
+	    int pkt_len = rd->mblength;
+	    struct sk_buff *skb;
+	    char *buf;
+
+	    skb = dev_alloc_skb (pkt_len+2);
+	    if (skb == NULL){
+		printk ("%s: Memory squeeze, deferring packet.\n", dev->name);
+		lp->stats.rx_dropped++;
+		rd->rmd1_bits = LE_R1_OWN;
+		lp->rx_new = (lp->rx_new + 1) & RX_RING_MOD_MASK;
+		return 0;
+	    }
+	    
+	    skb->dev = dev;
+	    skb_reserve (skb, 2);               /* 16 byte align */
+	    buf = skb_put (skb, pkt_len);       /* make room */
+	    memcpy (buf, (char *) &(ib->rx_buf [lp->rx_new][0]), pkt_len);
+	    skb->protocol = eth_type_trans (skb,dev);
+	    netif_rx (skb);
+	    lp->stats.rx_packets++;
+	}
+
+	/* Return the packet to the pool */
+	rd->rmd1_bits = LE_R1_OWN;
+	lp->rx_new = (lp->rx_new + 1) & RX_RING_MOD_MASK;
+    }
+#endif
+    return 0;
+}
+
+static int
+lance_tx (struct device *dev)
+{
+    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;
+    volatile struct lance_tx_desc *td;
+    int i, j;
+    int status;
+
+    /* csr0 is 2f3 */
+    ll->rdp = LE_C0_TINT | LE_C0_INEA;
+    /* csr0 is 73 */
+    j = lp->tx_old;
+    for (i = 0; i < TX_RING_SIZE; i++){
+	td = &ib->btx_ring [j];
+
+	if (td->tmd1_bits & LE_T1_ERR){
+	    status = td->misc;
+	    
+	    if (status & LE_T3_RTY)  lp->stats.tx_aborted_errors++;
+	    if (status & LE_T3_CLOS) lp->stats.tx_carrier_errors++;
+	    if (status & LE_T3_LCOL) lp->stats.tx_window_errors++;
+
+	    /* buffer errors and underflows turn off the transmiter */
+	    /* Restart the adapter */
+	    if (status & (LE_T3_BUF|LE_T3_UFL)){
+		lp->stats.tx_fifo_errors++;
+
+		printk ("%s: Tx: ERR_BUF|ERR_UFL, restarting\n", dev->name);
+		/* Stop the lance */
+		ll->rdp = LE_CSR0;
+		ll->rap = LE_C0_STOP;
+		init_restart_lance (lp);
+	    }
+	}
+	
+	j = (j + 1) & TX_RING_MOD_MASK;
+    }
+    lp->tx_old = (lp->tx_old+1) & TX_RING_MOD_MASK;
+
+    ll->rdp = LE_C0_TINT | LE_C0_INEA;
+    return 0;
+}
+
+static void
+lance_interrupt (int irq, struct pt_regs *regs)
+{
+    struct device *dev = (struct device *) (irq2dev_map [irq]);
+    struct lance_private *lp;
+    volatile struct lance_regs *ll;
+    int csr0;
+    
+    lp = (struct lance_private *) dev->priv;
+    ll = lp->ll;
+
+    if (dev->interrupt)
+	printk ("%s: again", dev->name);
+    
+    dev->interrupt = 1;
+
+    csr0 = ll->rdp;
+    
+    /* Acknowledge all the interrupt sources ASAP */
+    ll->rdp = csr0 & 0x004f;
+    
+    if ((csr0 & LE_C0_ERR)){
+	/* Clear the error condition */
+	ll->rdp = LE_C0_BABL|LE_C0_ERR|LE_C0_MISS|LE_C0_INEA;
+    }
+    
+    if (csr0 & LE_C0_RINT){
+	lance_rx (dev);
+    }
+    
+    if (csr0 & LE_C0_TINT){
+	lance_tx (dev);
+    }
+    
+    if ((TX_BUFFS_AVAIL >= 0) && dev->tbusy){
+	dev->tbusy = 0;
+	mark_bh (NET_BH);
+    }
+    ll->rap = 0;
+    ll->rdp = 0x7940;
+
+    dev->interrupt = 0;
+}
+
+struct device *last_dev = 0;
+
+static int
+lance_open (struct device *dev)
+{
+    struct lance_private *lp = (struct lance_private *)dev->priv;
+    volatile struct lance_regs *ll = lp->ll;
+    int status = 0;
+
+    last_dev = dev;
+    
+    /* Stop the Lance */
+    ll->rap = LE_CSR0;
+    ll->rdp = LE_C0_STOP;
+
+    if (request_irq (dev->irq, &lance_interrupt, 0, "LANCE")){
+	printk ("Lance: Can't get irq %d\n", dev->irq);
+	return -EAGAIN;
+    }
+    irq2dev_map [dev->irq] = dev;
+
+    lance_init_ring (dev);
+    load_csrs (lp);
+
+    dev->tbusy = 0;
+    dev->interrupt = 0;
+    dev->start = 1;
+
+    status = init_restart_lance (lp);
+
+    /* To make life easier to us while Sparc Linux becomes self hosting: */
+    {
+	    struct rtentry server_route;
+	    struct sockaddr_in *sin;
+	    
+	    sin=(struct sockaddr_in *)&server_route.rt_dst;
+	    *sin=server;
+	    sin=(struct sockaddr_in *)&server_route.rt_genmask;
+	    sin->sin_family=AF_INET;
+	    sin->sin_addr.s_addr= ip_get_mask (dev->pa_addr);
+	    server_route.rt_dev[0]=dev;
+	    server_route.
+	    server_route.rt_flags=RTF_HOST|RTF_UP;
+
+	    if(ip_rt_new(&server_route)==-1)
+		    printk("Unable to add NFS server route.\n");
+    }
+    ip_rt_add (RTF_UP,
+	       dev->pa_addr & ip_get_mask (dev->pa_addr),
+	       ip_get_mask (dev->pa_addr),
+	       0, dev, dev->mtu, 0, 0);
+    return status;
+}
+
+static int
+lance_close (struct device *dev)
+{
+    struct lance_private *lp = (struct lance_private *) dev->priv;
+    volatile struct lance_regs *ll = lp->ll;
+
+    dev->start = 0;
+    dev->tbusy = 1;
+
+    /* Stop the card */
+    ll->rap = LE_CSR0;
+    ll->rdp = LE_C0_STOP;
+
+    free_irq (dev->irq);
+    irq2dev_map [dev->irq] = NULL;
+    
+    return 0;
+}
+
+inline static int lance_reset (struct device *dev)
+{
+    struct lance_private *lp = (struct lance_private *)dev->priv;
+    volatile struct lance_regs *ll = lp->ll;
+    int status;
+    
+    /* Stop the lance */
+    ll->rdp = LE_CSR0;
+    ll->rap = LE_C0_STOP;
+#ifdef DEBUG_DRIVER
+    printk ("Lance stopped: csr0=%4.4x\n", ll->rdp);
+#endif
+    lance_init_ring (dev);
+    load_csrs (lp);
+    dev->trans_start = jiffies;
+    dev->interrupt = 0;
+    dev->start = 1;
+    dev->tbusy = 0;
+    status = init_restart_lance (lp);
+#ifdef DEBUG_DRIVER
+    printk ("Lance restart=%d\n", status);
+#endif
+}
+
+static int lance_start_xmit (struct sk_buff *skb, struct device *dev)
+{
+    struct lance_private *lp = (struct lance_private *)dev->priv;
+    volatile struct lance_regs *ll = lp->ll;
+    volatile struct lance_init_block *ib = lp->init_block;
+    int entry, skblen, len;
+    int status = 0;
+    static int outs;
+
+    /* Transmitter timeout, serious problems */
+    if (dev->tbusy){
+	    int tickssofar = jiffies - dev->trans_start;
+	    
+	    if (tickssofar < 100)
+		    status = -1;
+	    else {
+		    printk ("%s: trasmit timed out, status %04x, resetting\n",
+			    dev->name, ll->rdp);
+		    lance_reset (dev);
+	    }
+	    return status;
+    }
+
+    if (skb == NULL){
+	dev_tint (dev);
+	printk ("skb is NULL\n");
+	return 0;
+    }
+
+    if (skb->len <= 0){
+	printk ("skb len is %ld\n", skb->len);
+	return 0;
+    }
+    /* Block a timer-based transmit from overlapping. */
+#ifdef OLD_METHOD
+    dev->tbusy = 1;
+#else
+    if (set_bit (0, (void *) &dev->tbusy) != 0){
+	printk ("Transmitter access conflict.\n");
+	return -1;
+    }
+#endif
+    skblen = skb->len;
+
+    if (!TX_BUFFS_AVAIL){
+	return -1;
+    }
+
+#ifdef DEBUG_DRIVER
+    /* dump the packet */
+    for (i = 0; i < 64; i++){
+	if ((i % 16) == 0) printk ("\n");
+	printk ("%2.2x ", skb->data [i]);
+    }
+#endif
+    len = (skblen < ETH_ZLEN) ? ETH_ZLEN : skblen;
+    entry = lp->tx_new & TX_RING_MOD_MASK;
+    ib->btx_ring [entry].length = (-len) | 0xf000;
+    ib->btx_ring [entry].misc = 0;
+    
+    memcpy ((char *)&ib->tx_buf [entry][0], skb->data, skblen);
+
+    /* Clear the slack of the packet, do I need this? */
+    if (len != skblen){
+	memset ((char *) &ib->tx_buf [entry][skblen], 0, len - skblen);
+    }
+
+    
+    /* Now, give the packet to the lance */
+    ib->btx_ring [entry].tmd1_bits = (LE_T1_SOP|LE_T1_EOP|LE_T1_OWN);
+    lp->tx_new = (lp->tx_new+1) & TX_RING_MOD_MASK;
+
+    outs++;
+    /* Kick the lance: transmit now */
+    ll->rdp = LE_C0_INEA | LE_C0_TDMD;
+    dev->trans_start = jiffies;
+    dev_kfree_skb (skb, FREE_WRITE);
+    
+    if (TX_BUFFS_AVAIL)
+	dev->tbusy = 0;
+
+    return status;
+}
+
+static struct enet_statistics *
+lance_get_stats (struct device *dev)
+{
+    struct lance_private *lp = (struct lance_private *) dev->priv;
+
+    return &lp->stats;
+}
+
+static void
+lance_set_multicast (struct device *dev)
+{
+#ifdef NOT_YET
+    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;
+
+    ll->rdp = LE_CSR0;
+    ll->rap = LE_C0_STOP;
+    lance_init_ring (dev);
+    if (num_addrs >= 0){
+	printk ("Ignoring set_multicast\n");
+    } else {
+	ib->mode |= LE_MO_PROM;
+    }
+    lance_init_ring (dev);
+    load_csrs (lp);
+    init_restart_lance (lp);
+    dev->tbusy = 0;
+#endif
+}
+
+int sparc_lance_probe (struct device *dev)
+{
+    static unsigned version_printed = 0;
+    int    i;
+    int    found = 0;
+    struct linux_sbus *bus;
+    struct linux_sbus_device *sdev = 0;
+    struct lance_private *lp;
+    volatile struct lance_regs *ll;
+
+#ifdef DEBUG_DRIVER
+    printk ("Lance probe...0x%p\n", SBus_chain);
+#endif
+    for_each_sbus (bus){
+	for_each_sbusdev (sdev, bus){
+	    if (strcmp (sdev->prom_name, "le") == 0){
+		found = 1;
+		break;
+	    }
+	}
+    }
+    if (!found)
+	return ENODEV;
+
+    if (dev == NULL){
+	printk ("LANCE buffer @0x0. You don't really want this\n");
+	dev = init_etherdev (0, sizeof (struct lance_private));
+    } else {
+	dev->priv = kmalloc (sizeof (struct lance_private), GFP_KERNEL);
+    }
+    if (sparc_lance_debug && version_printed++ == 0)
+	printk (version);
+
+    printk ("%s: LANCE ", dev->name);
+    /* Fill the dev fields */
+    dev->base_addr = (long) sdev;
+
+    /* Copy the IDPROM ethernet address to the device structure, later we
+     * will copy the address in the device structure to the lance initialization
+     * block
+     */
+    for (i = 0; i < 6; i++){
+	printk ("%2.2x%c", dev->dev_addr [i] = idprom->id_eaddr [i], i == 5 ? ' ': ':');
+    }
+    /* Get the IO region */
+    ll = sparc_alloc_io (sdev->reg_addrs [0].phys_addr, 0,
+			 sizeof (struct lance_regs), "Lance driver", 0x0, 0x0);
+    
+    /* Make certain the data structures used by the LANCE are aligned. */
+    dev->priv = (void *)(((int)dev->priv + 7) & ~7);
+    lp = (struct lance_private *) dev->priv;
+    
+    lp->init_block = (void *)
+	sparc_dvma_malloc (sizeof (struct lance_init_block), "LANCE");
+    
+    lp->ll = ll;
+    lp->name = "LANCE";
+
+    /* This should never happen. */
+    if ((int)(lp->init_block->brx_ring) & 0x07) {
+	printk(" **ERROR** LANCE Rx and Tx rings not on even boundary.\n");
+	return ENODEV;
+    }
+
+    dev->open = &lance_open;
+    dev->stop = &lance_close;
+    dev->hard_start_xmit = &lance_start_xmit;
+    dev->get_stats = &lance_get_stats;
+    dev->set_multicast_list = &lance_set_multicast;
+    
+    dev->irq = (unsigned char) sdev->irqs [0].pri;
+    dev->dma = 0;
+    ether_setup (dev);
+    
+    return 0;
+}
+/*
+ * Local variables:
+ *  compile-command: "gcc -DKERNEL -Wall -O6 -fomit-frame-pointer -I../../..//net/tcp -c lance.c"
+ *  version-control: t
+ *  kept-new-versions: 5
+ * End:
+ */
diff -u --recursive --new-file v1.3.43/linux/drivers/net/tulip.c linux/drivers/net/tulip.c
--- v1.3.43/linux/drivers/net/tulip.c	Thu Nov  9 11:23:50 1995
+++ linux/drivers/net/tulip.c	Fri Nov 24 16:39:54 1995
@@ -158,7 +158,7 @@
 static void tulip_interrupt(int irq, struct pt_regs *regs);
 static int tulip_close(struct device *dev);
 static struct enet_statistics *tulip_get_stats(struct device *dev);
-static void set_multicast_list(struct device *dev, int num_addrs, void *addrs);
+static void set_multicast_list(struct device *dev);
 static int set_mac_address(struct device *dev, void *addr);
 
 
@@ -254,12 +254,8 @@
 	dev->hard_start_xmit = &tulip_start_xmit;
 	dev->stop = &tulip_close;
 	dev->get_stats = &tulip_get_stats;
-#ifdef HAVE_MULTICAST
 	dev->set_multicast_list = &set_multicast_list;
-#endif
-#ifdef HAVE_SET_MAC_ADDR
 	dev->set_mac_address = &set_mac_address;
-#endif
 
 	return;
 }
@@ -673,36 +669,44 @@
 	return &tp->stats;
 }
 
-/* Set or clear the multicast filter for this adaptor.
-   num_addrs == -1		Promiscuous mode, receive all packets
-   num_addrs == 0		Normal mode, clear multicast list
-   num_addrs > 0		Multicast mode, receive normal and MC packets, and do
-						best-effort filtering.
+/*
+ *	Set or clear the multicast filter for this adaptor.
  */
-static void
-set_multicast_list(struct device *dev, int num_addrs, void *addrs)
+
+static void set_multicast_list(struct device *dev, int num_addrs, void *addrs)
 {
 	short ioaddr = dev->base_addr;
 	int csr6 = inl(ioaddr + CSR6) & ~0x00D5;
 
-	if (num_addrs > 15 || num_addrs == -2) {
-		/* Too many to filter perfectly -- accept all multicasts. */
-		outl(csr6 | 0x0080, ioaddr + CSR6);
-	} else if (num_addrs < 0) {			/* Set promiscuous. */
+	if (dev->flags&IFF_PROMISC) 
+	{			/* Set promiscuous. */
 		outl(csr6 | 0x00C0, ioaddr + CSR6);
 		/* Log any net taps. */
 		printk("%s: Promiscuous mode enabled.\n", dev->name);
-	} else {
+	}
+	else if (dev->mc_count > 15 || (dev->mc_flags&IFF_ALLMULTI)) 
+	{
+		/* Too many to filter perfectly -- accept all multicasts. */
+		outl(csr6 | 0x0080, ioaddr + CSR6);
+	}
+	else
+	{
 		struct tulip_private *tp = (struct tulip_private *)dev->priv;
+		struct dev_mc_list *dmi=dev->mc_list;
 		int *setup_frm = tp->setup_frame;
-		unsigned short *eaddrs = addrs;
+		unsigned short *eaddrs;
 		int i;
 
 		/* We have <= 15 addresses that we can use the wonderful
 		   16 address perfect filtering of the Tulip.  Note that only
 		   the low shortword of setup_frame[] is valid. */
 		outl(csr6 | 0x0000, ioaddr + CSR6);
-		for(i = 0; i < num_addrs; i++) {
+		i=0;
+		while(dmi) 
+		{
+			eaddrs=(unsigned short *)dmi->dmi_addr;
+			dmi=dmi->next;
+			i++;
 			*setup_frm++ = *eaddrs++;
 			*setup_frm++ = *eaddrs++;
 			*setup_frm++ = *eaddrs++;
diff -u --recursive --new-file v1.3.43/linux/drivers/net/wavelan.c linux/drivers/net/wavelan.c
--- v1.3.43/linux/drivers/net/wavelan.c	Thu Nov  9 11:23:50 1995
+++ linux/drivers/net/wavelan.c	Fri Nov 24 16:39:54 1995
@@ -80,7 +80,7 @@
 static void		wavelan_interrupt(int, struct pt_regs *);
 static int		wavelan_close(device *);
 static en_stats		*wavelan_get_stats(device *);
-static void		wavelan_set_multicast_list(device *, int, void *);
+static void		wavelan_set_multicast_list(device *);
 static int		wavelan_get_info(char*, char**, off_t, int, int);
 
 /*
@@ -1051,6 +1051,8 @@
 	 */
 	ether_setup(dev);
 
+	dev->flags &= ~IFF_MULTICAST;		/* Not yet supported */
+	
 	dev->mtu = WAVELAN_MTU;
 
 	if (wavelan_debug > 0)
@@ -2015,19 +2017,18 @@
 
 static
 void
-wavelan_set_multicast_list(device *dev, int num_addrs, void *addrs)
+wavelan_set_multicast_list(device *dev)
 {
 	net_local	*lp;
 	unsigned long	x;
 
 	if (wavelan_debug > 0)
-		printk("%s: ->wavelan_set_multicast_list(dev=0x%x, num_addrs=%d, addrs=0x%x)\n", dev->name, (unsigned int)dev, num_addrs, (unsigned int)addrs);
+		printk("%s: ->wavelan_set_multicast_list(dev=0x%x)", dev->name, dev);
 
 	lp = (net_local *)dev->priv;
 
-	switch (num_addrs)
+	if(dev->flags&IFF_PROMISC)
 	{
-	case -1:
 		/*
 		 * Promiscuous mode: receive all packets.
 		 */
@@ -2035,9 +2036,16 @@
 		x = wavelan_splhi();
 		(void)wavelan_hardware_reset(dev);
 		wavelan_splx(x);
-		break;
-
-	case 0:
+	}
+#if MULTICAST_IS_ADDED	
+	else if((dev->flags&IFF_ALLMULTI)||dev->mc_list)
+	{
+			
+	
+	}
+#endif	
+	else	
+	{
 		/*
 		 * Normal mode: disable promiscuous mode,
 		 * clear multicast list.
@@ -2046,14 +2054,6 @@
 		x = wavelan_splhi();
 		(void)wavelan_hardware_reset(dev);
 		wavelan_splx(x);
-		break;
-
-	default:
-		/*
-		 * Multicast mode: receive normal and
-		 * multicast packets and do best-effort filtering.
-		 */
-		break;
 	}
 
 	if (wavelan_debug > 0)
diff -u --recursive --new-file v1.3.43/linux/drivers/net/znet.c linux/drivers/net/znet.c
--- v1.3.43/linux/drivers/net/znet.c	Tue Oct 10 18:46:37 1995
+++ linux/drivers/net/znet.c	Fri Nov 24 16:39:54 1995
@@ -186,7 +186,7 @@
 static void	znet_rx(struct device *dev);
 static int	znet_close(struct device *dev);
 static struct enet_statistics *net_get_stats(struct device *dev);
-static void set_multicast_list(struct device *dev, int num_addrs, void *addrs);
+static void set_multicast_list(struct device *dev);
 static void hardware_init(struct device *dev);
 static void update_stop_hit(short ioaddr, unsigned short rx_stop_offset);
 
@@ -625,10 +625,6 @@
 
 #ifdef HAVE_MULTICAST
 /* Set or clear the multicast filter for this adaptor.
-   num_addrs == -1	Promiscuous mode, receive all packets
-   num_addrs == 0	Normal mode, clear multicast list
-   num_addrs > 0	Multicast mode, receive normal and MC packets, and do
-			best-effort filtering.
    As a side effect this routine must also initialize the device parameters.
    This is taken advantage of in open().
 
@@ -636,15 +632,15 @@
    mode change persistent, but must be changed if this code is moved to
    a multiple adaptor environment.
  */
-static void set_multicast_list(struct device *dev, int num_addrs, void *addrs)
+static void set_multicast_list(struct device *dev)
 {
 	short ioaddr = dev->base_addr;
 
-	if (num_addrs == -1) {
+	if (dev->flags&IFF_PROMISC) {
 		/* Enable promiscuous mode */
 		i593_init[7] &= ~3;		i593_init[7] |= 1;
 		i593_init[13] &= ~8;	i593_init[13] |= 8;
-	} else if (num_addrs != 0) {
+	} else if (dev->mc_list || (dev->flags&IFF_ALLMULTI)) {
 		/* Enable accept-all-multicast mode */
 		i593_init[7] &= ~3;		i593_init[7] |= 0;
 		i593_init[13] &= ~8;	i593_init[13] |= 8;
diff -u --recursive --new-file v1.3.43/linux/drivers/pci/pci.c linux/drivers/pci/pci.c
--- v1.3.43/linux/drivers/pci/pci.c	Fri Nov 17 08:42:26 1995
+++ linux/drivers/pci/pci.c	Tue Nov 21 16:27:33 1995
@@ -41,6 +41,7 @@
  * it is sequential by both vendor and device id.
  */
 struct pci_dev_info dev_info[] = {
+	DEVICE( COMPAQ,		COMPAQ_1280,	"QVision 1280/p"),
 	DEVICE( NCR,		NCR_53C810,	"53c810"),
 	DEVICE( NCR,		NCR_53C820,	"53c820"),
 	DEVICE( NCR,		NCR_53C825,	"53c825"),
@@ -88,12 +89,7 @@
 	DEVICE( SI,		SI_5511,		"85C5511"),
 	DEVICE( SI,		SI_5513,		"85C5513"),
 	DEVICE( HP,		HP_J2585A,	"J2585A"),
-#if 0
-	DEVICE( SMC,		SMC_37C665,	"FDC 37C665"),  /* 1042 ? */
-	DEVICE( SMC,		SMC_37C922,	"FDC 37C922"),
-#else
-	DEVICE( PCTECH,		PCTECH_RZ1000,  "RZ1000 (buggy)"), /* 1042 */
-#endif
+	DEVICE( PCTECH,		PCTECH_RZ1000,  "RZ1000 (buggy)"),
 	DEVICE( DPT,		DPT,		"SmartCache/Raid"),
 	DEVICE( OPTI,		OPTI_82C557,	"82C557"),
 	DEVICE( OPTI,		OPTI_82C558,	"82C558"),
@@ -101,6 +97,7 @@
 	DEVICE( OPTI,		OPTI_82C822,	"82C822"),
 	DEVICE( BUSLOGIC,	BUSLOGIC_946C_2,"946C"),
 	DEVICE( BUSLOGIC,	BUSLOGIC_946C,	"946C"),
+	DEVICE( BUSLOGIC,	BUSLOGIC_930,	"BT-930"),
 	DEVICE( PROMISE,	PROMISE_5300,	"DC5030"),
 	DEVICE( N9,		N9_I128,	"Imagine 128"),
 	DEVICE( UMC,		UMC_UM8673F,	"UM8673F"),
@@ -118,6 +115,7 @@
 	DEVICE( CMD,		CMD_646,	"646"),
 	DEVICE( VISION,		VISION_QD8500,	"QD-8500"),
 	DEVICE( VISION,		VISION_QD8580,	"QD-8580"),
+	DEVICE( SIERRA,		SIERRA_STB,	"STB Horizon 64"),
 	DEVICE( WINBOND,	WINBOND_83769,	"W83769F"),
 	DEVICE( 3COM,		3COM_3C590,	"3C590 10bT"),
 	DEVICE( 3COM,		3COM_3C595TX,	"3C595 100bTX"),
@@ -128,18 +126,22 @@
 	DEVICE( AL,		AL_M1451,	"M1451"),
 	DEVICE( AL,		AL_M1461,	"M1461"),
 	DEVICE( AL,		AL_M4803,	"M4803"),
+	DEVICE( ASP,		ASP_ABP940,	"ABP940"),
 	DEVICE( IMS,		IMS_8849,	"8849"),
+	DEVICE( TEKRAM2,	TEKRAM2_690c,	"DC690c"),
 	DEVICE( REALTEK,	REALTEK_8029,	"8029"),
 	DEVICE( VIA,		VIA_82C505,	"VT 82C505"),
 	DEVICE( VIA,		VIA_82C561,	"VT 82C561"),
 	DEVICE( VIA,		VIA_82C576,	"VT 82C576 3V"),
 	DEVICE( VORTEX,		VORTEX_GDT,	"GDT 6000b"),
-	DEVICE( EF,		EF_ATM,		"155P-MF1"),
+	DEVICE( EF,		EF_ATM_FPGA,		"155P-MF1 (FPGA)"),
+	DEVICE( EF,		EF_ATM_ASIC,	"155P-MF1 (ASIC)"),
 	DEVICE( IMAGINGTECH,	IMAGINGTECH_ICPCI, "MVC IC-PCI"),
 	DEVICE( PLX,		PLX_9060,	"PCI9060 i960 bridge"),
 	DEVICE( ALLIANCE,	ALLIANCE_PROVIDEO, "Provideo"),
 	DEVICE( MUTECH,		MUTECH_MV1000,	"MV-1000"),
-	DEVICE( ZEINET,		ZEINET_1221,	"1221"),
+	DEVICE( ZEITNET,	ZEITNET_1221,	"1221"),
+	DEVICE( HAL,		HAL_RIO,	"RIO host"),
 	DEVICE( CYCLADES,	CYCLADES_Y,	"Cyclome-Y"),
 	DEVICE( SYMPHONY,	SYMPHONY_101,	"82C101"),
 	DEVICE( TEKRAM,		TEKRAM_DC290,	"DC-290"),
@@ -160,14 +162,16 @@
 	DEVICE( INTEL,		INTEL_7116,	"SAA7116"),
 	DEVICE( INTEL,		INTEL_82596,	"82596"),
 	DEVICE( INTEL,		INTEL_82865,	"82865"),
+	DEVICE( INTEL,		INTEL_82557,	"82557"),
 	DEVICE( INTEL,		INTEL_82437,	"82437"),
 	DEVICE( INTEL,		INTEL_82371_0,	"82371 Triton PIIX"),
 	DEVICE( INTEL,		INTEL_82371_1,	"82371 Triton PIIX"),
-	DEVICE( INTEL,		INTEL_P6,	"Experimental P6 bridge"),
+	DEVICE( INTEL,		INTEL_P6,	"Orion P6"),
 	DEVICE( ADAPTEC,	ADAPTEC_7850,	"AIC-7850"),
 	DEVICE( ADAPTEC,	ADAPTEC_7870,	"AIC-7870"),
 	DEVICE( ADAPTEC,	ADAPTEC_7871,	"AIC-7871"),
 	DEVICE( ADAPTEC,	ADAPTEC_7872,	"AIC-7872"),
+	DEVICE( ADAPTEC,	ADAPTEC_7873,	"AIC-7873"),
 	DEVICE( ADAPTEC,	ADAPTEC_7880,	"AIC-7880U"),
 	DEVICE( ADAPTEC,	ADAPTEC_7881,	"AIC-7881U"),
 	DEVICE( ADAPTEC,	ADAPTEC_7882,	"AIC-7882U"),
@@ -368,61 +372,66 @@
 const char *pci_strvendor(unsigned int vendor)
 {
 	switch (vendor) {
+	      case PCI_VENDOR_ID_COMPAQ:	return "Compaq";
 	      case PCI_VENDOR_ID_NCR:		return "NCR";
-	      case PCI_VENDOR_ID_ADAPTEC:	return "Adaptec";
-	      case PCI_VENDOR_ID_DPT:		return "DPT";
-	      case PCI_VENDOR_ID_S3:		return "S3 Inc.";
-	      case PCI_VENDOR_ID_OPTI:		return "OPTI";
-	      case PCI_VENDOR_ID_UMC:		return "UMC";
-	      case PCI_VENDOR_ID_DEC:		return "DEC";
-	      case PCI_VENDOR_ID_MATROX:	return "Matrox";
-	      case PCI_VENDOR_ID_INTEL:		return "Intel";
-#if 0
-	      case PCI_VENDOR_ID_SMC:		return "SMC";
-#else
-	      case PCI_VENDOR_ID_PCTECH:	return "PCTECH";
-#endif
 	      case PCI_VENDOR_ID_ATI:		return "ATI";
+	      case PCI_VENDOR_ID_VLSI:		return "VLSI";
+	      case PCI_VENDOR_ID_ADL:		return "Advance Logic";
+	      case PCI_VENDOR_ID_NS:		return "NS";
+	      case PCI_VENDOR_ID_TSENG:		return "Tseng'Lab";
 	      case PCI_VENDOR_ID_WEITEK:	return "Weitek";
+	      case PCI_VENDOR_ID_DEC:		return "DEC";
 	      case PCI_VENDOR_ID_CIRRUS:	return "Cirrus Logic";
-	      case PCI_VENDOR_ID_BUSLOGIC:	return "BusLogic";
-	      case PCI_VENDOR_ID_N9:		return "Number Nine";
-	      case PCI_VENDOR_ID_AI:		return "Acer Incorporated";
-	      case PCI_VENDOR_ID_AL:		return "Acer Labs";
-	      case PCI_VENDOR_ID_TSENG:		return "Tseng'Lab";
-	      case PCI_VENDOR_ID_CMD:		return "CMD";
-	      case PCI_VENDOR_ID_VISION:	return "Vision";
+	      case PCI_VENDOR_ID_IBM:		return "IBM";
 	      case PCI_VENDOR_ID_AMD:		return "AMD";
-	      case PCI_VENDOR_ID_VLSI:		return "VLSI";
-	      case PCI_VENDOR_ID_ADL:		return "Advance Logic";
-	      case PCI_VENDOR_ID_SYMPHONY:	return "Symphony";
 	      case PCI_VENDOR_ID_TRIDENT:	return "Trident";
-	      case PCI_VENDOR_ID_CONTAQ:	return "Contaq";
-	      case PCI_VENDOR_ID_NS:		return "NS";
-	      case PCI_VENDOR_ID_VIA:		return "VIA Technologies";
-	      case PCI_VENDOR_ID_SI:		return "Silicon Integrated Systems";
-	      case PCI_VENDOR_ID_LEADTEK:	return "Leadtek Research";
-	      case PCI_VENDOR_ID_IMS:		return "IMS";
-	      case PCI_VENDOR_ID_ZEINET:	return "ZeiNet";
-	      case PCI_VENDOR_ID_EF:		return "Efficient Networks";
-	      case PCI_VENDOR_ID_HER:		return "Hercules";
-	      case PCI_VENDOR_ID_ATRONICS:	return "Atronics";
+	      case PCI_VENDOR_ID_AI:		return "Acer Incorporated";
+	      case PCI_VENDOR_ID_MATROX:	return "Matrox";
 	      case PCI_VENDOR_ID_CT:		return "Chips & Technologies";
 	      case PCI_VENDOR_ID_FD:		return "Future Domain";
-	      case PCI_VENDOR_ID_WINBOND:	return "Winbond";
-	      case PCI_VENDOR_ID_3COM:		return "3Com";
+	      case PCI_VENDOR_ID_SI:		return "Silicon Integrated Systems";
+	      case PCI_VENDOR_ID_HP:		return "Hewlett Packard";
+	      case PCI_VENDOR_ID_PCTECH:	return "PCTECH";
+	      case PCI_VENDOR_ID_DPT:		return "DPT";
+	      case PCI_VENDOR_ID_OPTI:		return "OPTI";
+	      case PCI_VENDOR_ID_BUSLOGIC:	return "BusLogic";
 	      case PCI_VENDOR_ID_PROMISE:	return "Promise Technology";
-	      case PCI_VENDOR_ID_QLOGIC:	return "Q Logic";
+	      case PCI_VENDOR_ID_N9:		return "Number Nine";
+	      case PCI_VENDOR_ID_UMC:		return "UMC";
 	      case PCI_VENDOR_ID_X:		return "X TECHNOLOGY";
+	      case PCI_VENDOR_ID_QLOGIC:	return "Q Logic";
+	      case PCI_VENDOR_ID_LEADTEK:	return "Leadtek Research";
+	      case PCI_VENDOR_ID_CONTAQ:	return "Contaq";
+	      case PCI_VENDOR_ID_OLICOM:	return "Olicom";
+	      case PCI_VENDOR_ID_CMD:		return "CMD";
+	      case PCI_VENDOR_ID_VISION:	return "Vision";
+	      case PCI_VENDOR_ID_SIERRA:	return "Sierra";
 	      case PCI_VENDOR_ID_ACC:		return "ACC MICROELECTRONICS";
+	      case PCI_VENDOR_ID_WINBOND:	return "Winbond";
+	      case PCI_VENDOR_ID_3COM:		return "3Com";
+	      case PCI_VENDOR_ID_AL:		return "Acer Labs";
+	      case PCI_VENDOR_ID_ASP:		return "Advanced System Products";
+	      case PCI_VENDOR_ID_IMS:		return "IMS";
+	      case PCI_VENDOR_ID_TEKRAM2:	return "Tekram";
+	      case PCI_VENDOR_ID_REALTEK:	return "Realtek";
+	      case PCI_VENDOR_ID_VIA:		return "VIA Technologies";
 	      case PCI_VENDOR_ID_VORTEX:	return "VORTEX";
-	      case PCI_VENDOR_ID_HP:		return "Hewlett Packard";
+	      case PCI_VENDOR_ID_EF:		return "Efficient Networks";
 	      case PCI_VENDOR_ID_IMAGINGTECH:	return "Imaging Technology";
+	      case PCI_VENDOR_ID_PLX:		return "PLX";
+	      case PCI_VENDOR_ID_ALLIANCE:	return "Alliance";
+	      case PCI_VENDOR_ID_MUTECH:	return "Mutech";
+	      case PCI_VENDOR_ID_ZEITNET:	return "ZeitNet";
+	      case PCI_VENDOR_ID_HAL:		return "HAL";
 	      case PCI_VENDOR_ID_CYCLADES:	return "Cyclades";
-	      case PCI_VENDOR_ID_OLICOM:	return "Olicom";
-	      case PCI_VENDOR_ID_IBM:		return "IBM";
+	      case PCI_VENDOR_ID_SYMPHONY:	return "Symphony";
+	      case PCI_VENDOR_ID_TEKRAM:	return "Tekram";
 	      case PCI_VENDOR_ID_AVANCE:	return "Avance";
-	      case PCI_VENDOR_ID_ALLIANCE:	return "Alliance";
+	      case PCI_VENDOR_ID_S3:		return "S3 Inc.";
+	      case PCI_VENDOR_ID_INTEL:		return "Intel";
+	      case PCI_VENDOR_ID_ADAPTEC:	return "Adaptec";
+	      case PCI_VENDOR_ID_ATRONICS:	return "Atronics";
+	      case PCI_VENDOR_ID_HER:		return "Hercules";
 	      default:				return "Unknown vendor";
 	}
 }
diff -u --recursive --new-file v1.3.43/linux/fs/fcntl.c linux/fs/fcntl.c
--- v1.3.43/linux/fs/fcntl.c	Fri Nov 17 08:42:27 1995
+++ linux/fs/fcntl.c	Fri Nov 24 07:17:31 1995
@@ -41,19 +41,9 @@
 		return -EBADF;
 	if (newfd == oldfd)
 		return newfd;
-	/*
-	 * errno's for dup2() are slightly different than for fcntl(F_DUPFD)
-	 * for historical reasons.
-	 */
-	if (newfd > NR_OPEN)	/* historical botch - should have been >= */
-		return -EBADF;	/* dupfd() would return -EINVAL */
-#if 1
-	if (newfd == NR_OPEN)
-		return -EBADF;	/* dupfd() does return -EINVAL and that may
-				 * even be the standard!  But that is too
-				 * weird for now.
-				 */
-#endif
+	if (newfd >= NR_OPEN)
+		return -EBADF;	/* following POSIX.1 6.2.1 */
+
 	sys_close(newfd);
 	return dupfd(oldfd,newfd);
 }
diff -u --recursive --new-file v1.3.43/linux/fs/isofs/inode.c linux/fs/isofs/inode.c
--- v1.3.43/linux/fs/isofs/inode.c	Thu Nov  9 11:23:51 1995
+++ linux/fs/isofs/inode.c	Sat Nov 25 18:03:12 1995
@@ -339,13 +339,13 @@
 	
 	brelse(bh);
 	
-	printk("Max size:%ld   Log zone size:%ld\n",
+	printk(KERN_DEBUG "Max size:%ld   Log zone size:%ld\n",
 	       s->u.isofs_sb.s_max_size, 
 	       1UL << s->u.isofs_sb.s_log_zone_size);
-	printk("First datazone:%ld   Root inode number %d\n",
+	printk(KERN_DEBUG "First datazone:%ld   Root inode number %d\n",
 	       s->u.isofs_sb.s_firstdatazone >> s -> u.isofs_sb.s_log_zone_size,
 	       isonum_733 (rootp->extent) << s -> u.isofs_sb.s_log_zone_size);
-	if(high_sierra) printk("Disc in High Sierra format.\n");
+	if(high_sierra) printk(KERN_DEBUG "Disc in High Sierra format.\n");
 	unlock_super(s);
 	/* set up enough so that it can read an inode */
 	
diff -u --recursive --new-file v1.3.43/linux/fs/nfs/nfsroot.c linux/fs/nfs/nfsroot.c
--- v1.3.43/linux/fs/nfs/nfsroot.c	Tue Nov 21 13:22:12 1995
+++ linux/fs/nfs/nfsroot.c	Fri Nov 24 16:42:09 1995
@@ -7,6 +7,14 @@
  *  is to first determine the local IP address via RARP. Then handle
  *  the RPC negotiation with the system which replied to the RARP. The
  *  actual mounting is done later, when init() is running.
+ *
+ * 	Changes:
+ *
+ *	Alan Cox	:	Removed get_address name clash with FPU.
+ *	Alan Cox	:	Reformatted a bit.
+ *
+ *	TODO:
+ *		Support bootp and dhcp as well as rarp.
  */
 
 
@@ -42,7 +50,6 @@
 #include <linux/nfs.h>
 #include <linux/nfs_fs.h>
 #include <linux/nfs_mount.h>
-/* #include <netinet/in.h> */
 
 #define IPPORT_RESERVED 1024
 
@@ -99,41 +106,51 @@
  *  For receiving rarp packets a packet type has to be registered. Also
  *  initialize all devices for usage by RARP.
  */
+
 static int root_rarp_open(void)
 {
-  struct open_dev *openp;
-  struct device *dev;
-  unsigned short old_flags;
-  int num;
-
-  /* Register the packet type */
-  rarp_packet_type.type=htons(ETH_P_RARP);
-  dev_add_pack(&rarp_packet_type);
-
-  /* Open all devices which allow RARP */
-  for (dev = dev_base, num = 0; dev != NULL; dev = dev->next) {
-	if (dev->type < ARPHRD_SLIP &&
-	    dev->family == AF_INET &&
-	    !(dev->flags & (IFF_LOOPBACK | IFF_POINTOPOINT | IFF_NOARP))) {
-		/* First up the interface */
-		old_flags = dev->flags;
-		dev->flags = IFF_UP | IFF_BROADCAST | IFF_RUNNING;
-		if (!(old_flags & IFF_UP) && dev_open(dev)) {
-			dev->flags = old_flags;
-			continue;
-		}
-		openp = (struct open_dev *) kmalloc(sizeof(struct open_dev),
+	struct open_dev *openp;
+	struct device *dev;
+	unsigned short old_flags;
+	int num;
+
+	/*
+	 *	Register the packet type 
+	 */
+	 
+	rarp_packet_type.type=htons(ETH_P_RARP);
+	dev_add_pack(&rarp_packet_type);
+
+	/*
+	 *	Open all devices which allow RARP 
+	 */
+	 
+	for (dev = dev_base, num = 0; dev != NULL; dev = dev->next) 
+	{
+		if (dev->type < ARPHRD_SLIP &&
+			dev->family == AF_INET &&
+			!(dev->flags & (IFF_LOOPBACK | IFF_POINTOPOINT | IFF_NOARP))) 
+		{
+			/* First up the interface */
+			old_flags = dev->flags;
+			dev->flags = IFF_UP | IFF_BROADCAST | IFF_RUNNING;
+			if (!(old_flags & IFF_UP) && dev_open(dev)) 
+			{
+				dev->flags = old_flags;
+				continue;
+			}
+			openp = (struct open_dev *) kmalloc(sizeof(struct open_dev),
 						GFP_ATOMIC);
-		if (openp == NULL)
-			continue;
-		openp->dev = dev;
-		openp->old_flags = old_flags;
-		openp->next = open_base;
-		open_base = openp;
-		num++;
+			if (openp == NULL)
+				continue;
+			openp->dev = dev;
+			openp->old_flags = old_flags;
+			openp->next = open_base;
+			open_base = openp;
+			num++;
+		}
 	}
-  }
-  return num;
+	return num;
 }
 
 
@@ -142,159 +159,204 @@
  *  and restore the state of the device. However, keep the root device
  *  open for the upcoming mount.
  */
+
 static void root_rarp_close(void)
 {
-  struct open_dev *openp;
-  struct open_dev *nextp;
-
-  /* Deregister the packet type */
-  rarp_packet_type.type=htons(ETH_P_RARP);
-  dev_remove_pack(&rarp_packet_type);
+	struct open_dev *openp;
+	struct open_dev *nextp;
 
-  /* Deactivate all previously opened devices except that one which is
-   * able to connect to a suitable server
-   */
-  openp = open_base;
-  while (openp != NULL) {
-	nextp = openp->next;
-	openp->next = NULL;
-	if (openp->dev != root_dev) {
-		if (!(openp->old_flags & IFF_UP))
-			dev_close(openp->dev);
-		openp->dev->flags = openp->old_flags;
+	/*
+	 *	Deregister the packet type 
+	 */
+	 
+	rarp_packet_type.type=htons(ETH_P_RARP);
+	dev_remove_pack(&rarp_packet_type);
+
+	/*
+	 *	Deactivate all previously opened devices except that one which is
+	 *	able to connect to a suitable server
+	 */
+
+	openp = open_base;
+	while (openp != NULL) 
+	{
+		nextp = openp->next;
+		openp->next = NULL;
+		if (openp->dev != root_dev) 
+		{
+			if (!(openp->old_flags & IFF_UP))
+				dev_close(openp->dev);
+			openp->dev->flags = openp->old_flags;
+		}
+		kfree_s(openp, sizeof(struct open_dev));
+		openp = nextp;
 	}
-	kfree_s(openp, sizeof(struct open_dev));
-	openp = nextp;
-  }
 }
 
 
 /*
- * Receive RARP packets.
+ *	Receive RARP packets.
  */
+ 
 static int root_rarp_recv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
 {
-  struct arphdr *rarp = (struct arphdr *)skb->h.raw;
-  unsigned char *rarp_ptr = (unsigned char *)(rarp+1);
-  unsigned long sip, tip;
-  unsigned char *sha, *tha;		/* s for "source", t for "target" */
+	struct arphdr *rarp = (struct arphdr *)skb->h.raw;
+	unsigned char *rarp_ptr = (unsigned char *)(rarp+1);
+	unsigned long sip, tip;
+	unsigned char *sha, *tha;		/* s for "source", t for "target" */
   
-  /* If this test doesn't pass, its not IP, or we should ignore it anyway */
-  if (rarp->ar_hln != dev->addr_len || dev->type != ntohs(rarp->ar_hrd)) {
-	kfree_skb(skb, FREE_READ);
-	return 0;
-  }
+	/*
+	 *	If this test doesn't pass, its not IP, or we should ignore it anyway 
+	 */
+	 
+	if (rarp->ar_hln != dev->addr_len || dev->type != ntohs(rarp->ar_hrd)) 
+	{
+		kfree_skb(skb, FREE_READ);
+		return 0;
+	}
 
-  /* If it's not a RARP reply, delete it. */
-  if (rarp->ar_op != htons(ARPOP_RREPLY)) {
-	kfree_skb(skb, FREE_READ);
-	return 0;
-  }
+	/*
+	 *	If it's not a RARP reply, delete it. 
+	 */
+	 
+	if (rarp->ar_op != htons(ARPOP_RREPLY)) 
+	{
+		kfree_skb(skb, FREE_READ);
+		return 0;
+	}
 
-  /* If it's not ethernet or AX25, delete it. */
-  if ((rarp->ar_pro != htons(ETH_P_IP) && dev->type != ARPHRD_AX25) || 
+	/*
+	 *	If it's not ethernet or AX25, delete it. 
+	 */
+	 
+	if ((rarp->ar_pro != htons(ETH_P_IP) && dev->type != ARPHRD_AX25) || 
 #ifdef CONFIG_AX25
-      (rarp->ar_pro != htons(AX25_P_IP) && dev->type == ARPHRD_AX25) ||
+		(rarp->ar_pro != htons(AX25_P_IP) && dev->type == ARPHRD_AX25) ||
 #endif
-       rarp->ar_pln != 4) {
-	kfree_skb(skb, FREE_READ);
-	return 0;
-  }
+		rarp->ar_pln != 4) 
+	{
+		kfree_skb(skb, FREE_READ);
+		return 0;
+	}
   
-  /* Extract variable width fields */
-  sha = rarp_ptr;
-  rarp_ptr += dev->addr_len;
-  memcpy(&sip, rarp_ptr, 4);
-  rarp_ptr += 4;
-  tha = rarp_ptr;
-  rarp_ptr += dev->addr_len;
-  memcpy(&tip, rarp_ptr, 4);
-
-  /* Discard packets which are not meant for us. */
-  if (memcmp(tha, dev->dev_addr, dev->addr_len)) {
-	kfree_skb(skb, FREE_READ);
-	return 0;
-  }
+	/*
+	 *	Extract variable width fields 
+	 */
+	 
+	sha = rarp_ptr;
+	rarp_ptr += dev->addr_len;
+	memcpy(&sip, rarp_ptr, 4);
+	rarp_ptr += 4;
+	tha = rarp_ptr;
+	rarp_ptr += dev->addr_len;
+	memcpy(&tip, rarp_ptr, 4);
+
+	/*
+	 *	Discard packets which are not meant for us. 
+	 */
+	 
+	if (memcmp(tha, dev->dev_addr, dev->addr_len)) 
+	{
+		kfree_skb(skb, FREE_READ);
+		return 0;
+	}
 
-  /* The packet is what we were looking for. Setup the global variables. */
-  cli();
-  if (root_dev != NULL) {
+	/*
+	 *	The packet is what we were looking for. Setup the global variables. 
+	 */
+
+	cli();
+	if (root_dev != NULL) 
+	{
+		sti();
+		kfree_skb(skb, FREE_READ);
+		return 0;
+	}
+	root_dev = dev;
 	sti();
-	kfree_skb(skb, FREE_READ);
-	return 0;
-  }
-  root_dev = dev;
-  sti();
 
-  myaddr.sin_family = dev->family;
-  myaddr.sin_addr.s_addr = tip;
-  server.sin_family = dev->family;
-  if (!server.sin_addr.s_addr)
-    server.sin_addr.s_addr = sip;
+	myaddr.sin_family = dev->family;
+	myaddr.sin_addr.s_addr = tip;
+	server.sin_family = dev->family;
+	if (!server.sin_addr.s_addr)
+		server.sin_addr.s_addr = sip;
 
-  kfree_skb(skb, FREE_READ);
-  return 0;
+	kfree_skb(skb, FREE_READ);
+	return 0;
 }
 
 
 /*
- * Send RARP request packet over all devices which allow RARP.
+ *	Send RARP request packet over all devices which allow RARP.
  */
+
 static void root_rarp_send(void)
 {
-  struct open_dev *openp;
-  struct device *dev;
+	struct open_dev *openp;
+	struct device *dev;
 
 #ifdef NFSROOT_DEBUG
-  printk(KERN_NOTICE "NFS: Sending RARP request...\n");
+	printk(KERN_NOTICE "NFS: Sending RARP request...\n");
 #endif
 
-  for (openp = open_base; openp != NULL; openp = openp->next) {
-	dev = openp->dev;
-	arp_send(ARPOP_RREQUEST, ETH_P_RARP, 0, dev, 0, NULL,
-						dev->dev_addr, dev->dev_addr);
-  }
+	for (openp = open_base; openp != NULL; openp = openp->next) 
+	{
+		dev = openp->dev;
+		arp_send(ARPOP_RREQUEST, ETH_P_RARP, 0, dev, 0, NULL,
+			dev->dev_addr, dev->dev_addr);
+	}
 }
 
 
 /*
- * Determine client and server IP numbers and appropriate device by using
- * the RARP protocol.
+ *	Determine client and server IP numbers and appropriate device by using
+ *	the RARP protocol.
  */
+
 static int do_rarp(void)
 {
-  int retries = 0;
-  unsigned long timeout;
+	int retries = 0;
+	unsigned long timeout;
+
+	/* 
+	 *	Open all devices and setup RARP protocol 
+	 */
+	 
+	if (!root_rarp_open()) 
+	{
+		printk(KERN_ERR "NFS: No network device found to send RARP request to\n");
+		return -1;
+	}
+
+	/*
+	 *	Send RARP request and wait, until we get an answer. This loop seems
+	 *	to be a terrible waste of cpu time, but actually there is no process
+	 *	running at all, so we don't need to use any scheduler functions.
+	 *	[Actually we could now, but the nothing else running note still 
+	 *	 applies.. - AC]
+	 */
+
+	for (retries = 0; retries < RARP_RETRIES && root_dev == NULL; retries++) 
+	{
+		root_rarp_send();
+		timeout = jiffies + (RARP_TIMEOUT * HZ);
+		while (jiffies < timeout && root_dev == NULL)
+			;;
+	}
+
+	if (root_dev == NULL) 
+	{
+		printk(KERN_ERR "NFS: Timed out while waiting for RARP answer\n");
+		return -1;
+	}
+
+	root_rarp_close();
 
-  /* Open all devices and setup RARP protocol */
-  if (!root_rarp_open()) {
-	printk(KERN_ERR "NFS: No network device found to send RARP request to\n");
-	return -1;
-  }
-
-  /* Send RARP request and wait, until we get an answer. This loop seems
-   * to be a terrible waste of cpu time, but actually there is no process
-   * running at all, so we don't need to use any scheduler functions.
-   */
-  for (retries = 0; retries < RARP_RETRIES && root_dev == NULL; retries++) {
-	root_rarp_send();
-	timeout = jiffies + (RARP_TIMEOUT * HZ);
-	while (jiffies < timeout && root_dev == NULL)
-		;;
-  }
-
-  if (root_dev == NULL) {
-	printk(KERN_ERR "NFS: Timed out while waiting for RARP answer\n");
-	return -1;
-  }
-
-  root_rarp_close();
-
-  printk(KERN_NOTICE "NFS: ");
-  printk("Got RARP answer from %s, ", in_ntoa(server.sin_addr.s_addr));
-  printk("my address is %s\n", in_ntoa(myaddr.sin_addr.s_addr));
+	printk(KERN_NOTICE "NFS: ");
+	printk("Got RARP answer from %s, ", in_ntoa(server.sin_addr.s_addr));
+	printk("my address is %s\n", in_ntoa(myaddr.sin_addr.s_addr));
 
-  return 0;
+	return 0;
 }
 
 
@@ -311,7 +373,10 @@
 			unsigned short mss, unsigned long window);
 
 
-/* The following integer options are recognized */
+/*
+ *	The following integer options are recognized
+ */
+ 
 static struct nfs_int_opts
 {
 	char *name;
@@ -329,7 +394,10 @@
 	{ NULL,		NULL }};
 
 
-/* And now the flag options */
+/*
+ *	And now the flag options 
+ */
+ 
 static struct nfs_bool_opts
 {
 	char *name;
@@ -346,125 +414,145 @@
 	{ "nocto",	~NFS_MOUNT_NOCTO,	NFS_MOUNT_NOCTO },
 	{ "ac",		~NFS_MOUNT_NOAC,	0 },
 	{ "noac",	~NFS_MOUNT_NOAC,	NFS_MOUNT_NOAC },
-	{ NULL,		0,			0 }};
+	{ NULL,		0,			0 }
+};
 
 
-static unsigned long get_address (char **str)
+static unsigned long nfs_get_address (char **str)
 {
-   unsigned long l;
-   unsigned int val;
-   int i;
+	unsigned long l;
+	unsigned int val;
+	int i;
    
-   l = 0;
-   for (i = 0; i < 4; i++) 
-     {
-	
-	l <<= 8;
-	if (**str != '\0')
-	  {
-	     
-	     val = 0;
-	     while (**str != '\0' && **str != '.' && **str != ':')
-	       {
-		  
-		  val *= 10;
-		  val += **str - '0';
-		  (*str)++;
-	       }
-	     
-	     l |= val;
-	     if (**str != '\0') 
-	       (*str)++;
-	  }
-	
-     }
-   
-   return(htonl(l));
+	l = 0;
+	for (i = 0; i < 4; i++) 
+	{
+		l <<= 8;
+		if (**str != '\0')
+		{
+	     		val = 0;
+	     		while (**str != '\0' && **str != '.' && **str != ':')
+	       		{
+		  		val *= 10;
+		  		val += **str - '0';
+				(*str)++;
+			}
+			l |= val;
+			if (**str != '\0') 
+				(*str)++;
+		}
+	}
+   	return(htonl(l));
 }
 
 /*
- * Prepare the NFS data structure and parse any options
+ *	Prepare the NFS data structure and parse any options
  */
+ 
 static int root_nfs_parse(char *name)
 {
-  char buf[NFS_MAXPATHLEN];
-  char *cp, *options, *val;
+	char buf[NFS_MAXPATHLEN];
+	char *cp, *options, *val;
+
+	/*
+	 *	Get the host ip number 
+	 */
+	 
+	if (*name >= '0' && *name <= '9')
+	{
+		server.sin_addr.s_addr = nfs_get_address (&name);
+	}
 
-  /* get the host ip number */
-  if (*name >= '0' && *name <= '9'){
-    server.sin_addr.s_addr = get_address (&name);
-  }
-  /* Setup the server hostname */
-  cp = in_ntoa(server.sin_addr.s_addr);
-  strncpy(nfs_data.hostname, cp, 255);
-  nfs_data.addr = server;
-
-  /* Set the name of the directory to mount */
-  cp = in_ntoa(myaddr.sin_addr.s_addr);
-  strncpy(buf, name, 255);
-  if ((options = strchr(buf, ',')))
-	*options++ = '\0';
-  if (strlen(buf) + strlen(cp) > NFS_MAXPATHLEN) {
-	printk(KERN_ERR "NFS: Pathname for remote directory too long\n");
-	return -1;
-  }
-  sprintf(nfs_path, buf, cp);
-
-  /* Set some default values */
-  nfs_port          = -1;
-  nfs_data.version  = NFS_MOUNT_VERSION;
-  nfs_data.flags    = 0;
-  nfs_data.rsize    = NFS_DEF_FILE_IO_BUFFER_SIZE;
-  nfs_data.wsize    = NFS_DEF_FILE_IO_BUFFER_SIZE;
-  nfs_data.timeo    = 7;
-  nfs_data.retrans  = 3;
-  nfs_data.acregmin = 3;
-  nfs_data.acregmax = 60;
-  nfs_data.acdirmin = 30;
-  nfs_data.acdirmax = 60;
-
-  /* Process any options */
-  if (options) {
-	cp = strtok(options, ",");
-	while (cp) {
-		if ((val = strchr(cp, '='))) {
-			struct nfs_int_opts *opts = root_int_opts;
-			*val++ = '\0';
-			while (opts->name && strcmp(opts->name, cp))
-				opts++;
-			if (opts->name)
-				*(opts->val) = (int) simple_strtoul(val, NULL, 10);
-		} else {
-			struct nfs_bool_opts *opts = root_bool_opts;
-			while (opts->name && strcmp(opts->name, cp))
-				opts++;
-			if (opts->name) {
-				nfs_data.flags &= opts->and_mask;
-				nfs_data.flags |= opts->or_mask;
+	/*
+	 *	Setup the server hostname 
+	 */
+	 
+	cp = in_ntoa(server.sin_addr.s_addr);
+	strncpy(nfs_data.hostname, cp, 255);
+	nfs_data.addr = server;
+
+	/*
+	 *	Set the name of the directory to mount 
+	 */
+	 
+	cp = in_ntoa(myaddr.sin_addr.s_addr);
+	strncpy(buf, name, 255);
+	if ((options = strchr(buf, ',')))
+		*options++ = '\0';
+	if (strlen(buf) + strlen(cp) > NFS_MAXPATHLEN) 
+	{
+		printk(KERN_ERR "NFS: Pathname for remote directory too long\n");
+		return -1;
+	}
+	sprintf(nfs_path, buf, cp);
+
+	/*
+	 *	Set some default values 
+	 */
+	 
+	nfs_port          = -1;
+	nfs_data.version  = NFS_MOUNT_VERSION;
+	nfs_data.flags    = 0;
+	nfs_data.rsize    = NFS_DEF_FILE_IO_BUFFER_SIZE;
+	nfs_data.wsize    = NFS_DEF_FILE_IO_BUFFER_SIZE;
+	nfs_data.timeo    = 7;
+	nfs_data.retrans  = 3;
+	nfs_data.acregmin = 3;
+	nfs_data.acregmax = 60;
+	nfs_data.acdirmin = 30;
+	nfs_data.acdirmax = 60;
+
+	/*
+	 *	Process any options
+	 */
+
+	if (options) 
+	{
+		cp = strtok(options, ",");
+		while (cp) 
+		{
+			if ((val = strchr(cp, '='))) 
+			{
+				struct nfs_int_opts *opts = root_int_opts;
+				*val++ = '\0';
+				while (opts->name && strcmp(opts->name, cp))
+					opts++;
+				if (opts->name)
+					*(opts->val) = (int) simple_strtoul(val, NULL, 10);
 			}
+			else
+			{
+				struct nfs_bool_opts *opts = root_bool_opts;
+				while (opts->name && strcmp(opts->name, cp))
+					opts++;
+				if (opts->name) 
+				{
+					nfs_data.flags &= opts->and_mask;
+					nfs_data.flags |= opts->or_mask;
+				}
+			}
+			cp = strtok(NULL, ",");
 		}
-		cp = strtok(NULL, ",");
 	}
-  }
-
-  return 0;
+	return 0;
 }
 
 
 /*
- * Tell the user what's going on.
+ *	Tell the user what's going on.
  */
+
 static void root_nfs_print(void)
 {
 #ifdef NFSROOT_DEBUG
-  printk(KERN_NOTICE "NFS: Mounting %s on server %s as root\n",
+	printk(KERN_NOTICE "NFS: Mounting %s on server %s as root\n",
 		nfs_path, nfs_data.hostname);
-  printk(KERN_NOTICE "NFS:     rsize = %d, wsize = %d, timeo = %d, retrans = %d\n",
+	printk(KERN_NOTICE "NFS:     rsize = %d, wsize = %d, timeo = %d, retrans = %d\n",
 		nfs_data.rsize, nfs_data.wsize, nfs_data.timeo, nfs_data.retrans);
-  printk(KERN_NOTICE "NFS:     acreg (min,max) = (%d,%d), acdir (min,max) = (%d,%d)\n",
+	printk(KERN_NOTICE "NFS:     acreg (min,max) = (%d,%d), acdir (min,max) = (%d,%d)\n",
 		nfs_data.acregmin, nfs_data.acregmax,
 		nfs_data.acdirmin, nfs_data.acdirmax);
-  printk(KERN_NOTICE "NFS:     port = %d, flags = %08x\n",
+	printk(KERN_NOTICE "NFS:     port = %d, flags = %08x\n",
 		nfs_port, nfs_data.flags);
 #endif
 }
@@ -475,53 +563,62 @@
  */
 static void root_nfs_setup(void)
 {
-  struct rtentry server_route;
-  struct sockaddr_in *sin;
+	struct rtentry server_route;
+	struct sockaddr_in *sin;
 
-  /* Setup the device correctly */
-  root_dev->family     = myaddr.sin_family;
-  root_dev->pa_addr    = myaddr.sin_addr.s_addr;
-  root_dev->pa_mask    = ip_get_mask(myaddr.sin_addr.s_addr);
-  root_dev->pa_brdaddr = root_dev->pa_addr | ~root_dev->pa_mask;
-  root_dev->pa_dstaddr = 0;
-
-  sin=(struct sockaddr_in *)&server_route.rt_dst;
-  *sin=server;
-  sin=(struct sockaddr_in *)&server_route.rt_genmask;
-  sin->sin_family=AF_INET;
-  sin->sin_addr.s_addr= root_dev->pa_mask;
-  server_route.rt_dev=NULL;
-  server_route.rt_flags=RTF_HOST|RTF_UP;
+	/* 
+	 *	Setup the device correctly
+	 */
+	 
+	root_dev->family     = myaddr.sin_family;
+	root_dev->pa_addr    = myaddr.sin_addr.s_addr;
+	root_dev->pa_mask    = ip_get_mask(myaddr.sin_addr.s_addr);
+	root_dev->pa_brdaddr = root_dev->pa_addr | ~root_dev->pa_mask;
+	root_dev->pa_dstaddr = 0;
+
+	sin=(struct sockaddr_in *)&server_route.rt_dst;
+	*sin=server;
+	sin=(struct sockaddr_in *)&server_route.rt_genmask;
+	sin->sin_family=AF_INET;
+	sin->sin_addr.s_addr= root_dev->pa_mask;
+	server_route.rt_dev=NULL;
+	server_route.rt_flags=RTF_HOST|RTF_UP;
   
-  /* Now add a route to the server */
-  if(ip_rt_new(&server_route)==-1)
-  	printk("Unable to add NFS server route.\n");
+	/*
+	 *	Now add a route to the server
+	 */
+ 
+	if(ip_rt_new(&server_route)==-1)
+	  	printk("Unable to add NFS server route.\n");
 }
 
 
 /*
- * Get the necessary IP addresses and prepare for mounting the required
- * NFS filesystem.
+ *	Get the necessary IP addresses and prepare for mounting the required
+ *	NFS filesystem.
  */
+
 int nfs_root_init(char *nfsname)
 {
-  /* Initialize network device and get local and server IP address */
-  if (do_rarp() < 0)
-	return -1;
-
-  /* Initialize the global variables necessary for NFS. The server
-   * directory is actually mounted after init() has been started.
-   */
-  if (root_nfs_parse(nfsname) < 0)
-	return -1;
-  root_nfs_print();
-  root_nfs_setup();
-  return 0;
+	/*
+	 *	Initialize network device and get local and server IP address 
+	 */
+
+	if (do_rarp() < 0)
+		return -1;
+
+	/*
+	 *	Initialize the global variables necessary for NFS. The server
+	 *	directory is actually mounted after init() has been started.
+	 */
+
+	if (root_nfs_parse(nfsname) < 0)
+		return -1;
+	root_nfs_print();
+	root_nfs_setup();
+	return 0;
 }
 
-
-
-
 /***************************************************************************
 
 		Routines to actually mount the root directory
@@ -537,313 +634,385 @@
 
 
 /*
- * Open a UDP socket.
+ *	Open a UDP socket.
  */
+
 static int root_nfs_open(void)
 {
-  struct file *filp;
-  unsigned long opt[] = { AF_INET, SOCK_DGRAM, IPPROTO_UDP };
+	struct file *filp;
+	unsigned long opt[] = { AF_INET, SOCK_DGRAM, IPPROTO_UDP };
 
-  /* Open the socket */
-  if ((nfs_data.fd = sys_socketcall(SYS_SOCKET, opt)) < 0) {
-	printk(KERN_ERR "NFS: Cannot open UDP socket\n");
-	return -1;
-  }
-
-  /* Copy the file and inode data area so that we can remove the
-   * file lateron without killing the socket. After all this the
-   * closing routine just needs to remove the file pointer from
-   * the init-task descriptor.
-   */
-  filp = current->files->fd[nfs_data.fd];
-  memcpy(&nfs_file, filp, sizeof(struct file));
-  nfs_file.f_next = nfs_file.f_prev = NULL;
-  current->files->fd[nfs_data.fd] = &nfs_file;
-  filp->f_count = 0;		/* Free the file descriptor */
-
-  memcpy(&nfs_inode, nfs_file.f_inode, sizeof(struct inode));
-  nfs_inode.i_hash_next = nfs_inode.i_hash_prev = NULL;
-  nfs_inode.i_next = nfs_inode.i_prev = NULL;
-  clear_inode(nfs_file.f_inode);
-  nfs_file.f_inode = &nfs_inode;
-  nfs_inode.u.socket_i.inode = &nfs_inode;
-  nfs_file.private_data = NULL;
-
-  return 0;
+	/*
+	 *	Open the socket 
+	 */
+
+	if ((nfs_data.fd = sys_socketcall(SYS_SOCKET, opt)) < 0) 
+	{
+		printk(KERN_ERR "NFS: Cannot open UDP socket\n");
+		return -1;
+	}
+
+	/*	
+	 *	Copy the file and inode data area so that we can remove the
+	 *	file lateron without killing the socket. After all this the
+	 *	closing routine just needs to remove the file pointer from
+	 *	the init-task descriptor.
+	 */
+
+	filp = current->files->fd[nfs_data.fd];
+	memcpy(&nfs_file, filp, sizeof(struct file));
+	nfs_file.f_next = nfs_file.f_prev = NULL;
+	current->files->fd[nfs_data.fd] = &nfs_file;
+	filp->f_count = 0;		/* Free the file descriptor */
+
+	memcpy(&nfs_inode, nfs_file.f_inode, sizeof(struct inode));
+	nfs_inode.i_hash_next = nfs_inode.i_hash_prev = NULL;
+	nfs_inode.i_next = nfs_inode.i_prev = NULL;
+	clear_inode(nfs_file.f_inode);
+	nfs_file.f_inode = &nfs_inode;
+	nfs_inode.u.socket_i.inode = &nfs_inode;
+	nfs_file.private_data = NULL;
+
+	return 0;
 }
 
 
 /*
- * Close the UDP file descriptor. The main part of preserving the socket
- * has already been done after opening it. Now we have to remove the
- * file descriptor from the init task.
+ *	Close the UDP file descriptor. The main part of preserving the socket
+ *	has already been done after opening it. Now we have to remove the
+ *	file descriptor from the init task.
  */
+
 static void root_nfs_close(int close_all)
 {
-  /* Remove the file from the list of open files */
-  current->files->fd[nfs_data.fd] = NULL;
-  if (current->files->count > 0)
-	current->files->count--;
-
-  /* Clear memory use by the RPC packet */
-  if (rpc_packet != NULL)
-	kfree_s(rpc_packet, nfs_data.wsize + 1024);
-
-  /* In case of an error we also have to close the socket again (sigh) */
-  if (close_all) {
-	nfs_inode.u.socket_i.inode = NULL;	/* The inode is already cleared */
-	if (nfs_file.f_op->release)
-		nfs_file.f_op->release(&nfs_inode, &nfs_file);
-  }
+	/*
+	 *	Remove the file from the list of open files 
+	 */
+
+	current->files->fd[nfs_data.fd] = NULL;
+	if (current->files->count > 0)
+		current->files->count--;
+
+	/*
+	 *	Clear memory use by the RPC packet 
+	 */
+	 
+	if (rpc_packet != NULL)
+		kfree_s(rpc_packet, nfs_data.wsize + 1024);
+
+	/*
+	 *	In case of an error we also have to close the socket again (sigh)
+	 */
+	 
+	if (close_all) 
+	{
+		nfs_inode.u.socket_i.inode = NULL;	/* The inode is already cleared */
+		if (nfs_file.f_op->release)
+			nfs_file.f_op->release(&nfs_inode, &nfs_file);
+	}
 }
 
 
 /*
- * Find a suitable listening port and bind to it
+ *	Find a suitable listening port and bind to it
  */
+
 static int root_nfs_bind(void)
 {
-  int res = -1;
-  short port = STARTPORT;
-  struct sockaddr_in *sin = &myaddr;
-  int i;
-
-  if (nfs_inode.u.socket_i.ops->bind) {
-	for (i = 0; i < NPORTS && res < 0; i++) {
-		sin->sin_port = htons(port++);
-		if (port > ENDPORT) {
-			port = STARTPORT;
+	int res = -1;
+	short port = STARTPORT;
+	struct sockaddr_in *sin = &myaddr;
+	int i;
+
+	if (nfs_inode.u.socket_i.ops->bind) 
+	{
+		for (i = 0; i < NPORTS && res < 0; i++) 
+		{
+			sin->sin_port = htons(port++);
+			if (port > ENDPORT) 
+			{
+				port = STARTPORT;
+			}
+			res = nfs_inode.u.socket_i.ops->bind(&nfs_inode.u.socket_i,
+				(struct sockaddr *) sin, sizeof(struct sockaddr_in));
 		}
-		res = nfs_inode.u.socket_i.ops->bind(&nfs_inode.u.socket_i,
-			(struct sockaddr *) sin, sizeof(struct sockaddr_in));
 	}
-  }
-  if (res < 0) {
-	printk(KERN_ERR "NFS: Cannot find a suitable listening port\n");
-	root_nfs_close(1);
-	return -1;
-  }
-
+	if (res < 0) 
+	{
+		printk(KERN_ERR "NFS: Cannot find a suitable listening port\n");
+		root_nfs_close(1);
+		return -1;
+	}
 #ifdef NFSROOT_DEBUG
-  printk(KERN_NOTICE "NFS: Binding to listening port %d\n", port);
+	printk(KERN_NOTICE "NFS: Binding to listening port %d\n", port);
 #endif
-  return 0;
+	return 0;
 }
 
 
 /*
- * Send an RPC request and wait for the answer
+ *	Send an RPC request and wait for the answer
  */
+
 static int *root_nfs_call(int *end)
 {
-  struct file *filp;
-  struct socket *sock;
-  int dummylen;
-  static struct nfs_server s =
-	{ &nfs_file, /* struct file * */
-	  0,         /* struct rsock * */
-	  {
-	     0, "",
-	  },         /* toaddr */
-          0,         /* lock */
-	  NULL,      /* wait queue */
-	  NFS_MOUNT_SOFT, /* flags */
-	  0, 0,           /* rsize, wsize */
-	  0,              /* timeo */
-	  0,              /* retrans */
-	  3*HZ, 60*HZ, 30*HZ, 60*HZ, "\0" };
+	struct file *filp;
+	struct socket *sock;
+	int dummylen;
+	static struct nfs_server s = {
+		&nfs_file, /* struct file * */
+		0,         /* struct rsock * */
+		{
+			0, "",
+		},         /* toaddr */
+		0,         /* lock */
+		NULL,      /* wait queue */
+		NFS_MOUNT_SOFT, /* flags - this seems a ___BAD___ default - AC */
+		0, 0,           /* rsize, wsize */
+		0,              /* timeo */
+		0,              /* retrans */
+		3*HZ, 60*HZ, 30*HZ, 60*HZ, "\0" 
+	};
 
-  filp = &nfs_file;
-  sock = &((filp->f_inode)->u.socket_i);
+	filp = &nfs_file;
+	sock = &((filp->f_inode)->u.socket_i);
     
-  /* extract the other end of the socket into server->toaddr */
-  sock->ops->getname(sock, &(s.toaddr), &dummylen, 1) ;
-  ((struct sockaddr_in *) &s.toaddr)->sin_port   = server.sin_port;
-  ((struct sockaddr_in *) &s.toaddr)->sin_family = server.sin_family;
-  ((struct sockaddr_in *) &s.toaddr)->sin_addr.s_addr = server.sin_addr.s_addr;
+	/*
+	 *	extract the other end of the socket into server->toaddr 
+	 */
+	 
+	sock->ops->getname(sock, &(s.toaddr), &dummylen, 1) ;
+	((struct sockaddr_in *) &s.toaddr)->sin_port   = server.sin_port;
+	((struct sockaddr_in *) &s.toaddr)->sin_family = server.sin_family;
+	((struct sockaddr_in *) &s.toaddr)->sin_addr.s_addr = server.sin_addr.s_addr;
   
-  s.rsock = rpc_makesock(filp);
-  s.flags = nfs_data.flags;
-  s.rsize = nfs_data.rsize;
-  s.wsize = nfs_data.wsize;
-  s.timeo = nfs_data.timeo * HZ / 10;
-  s.retrans = nfs_data.retrans;
-  strcpy(s.hostname, nfs_data.hostname);
-
-  /* First connect the UDP socket to a server port, then send the packet
-   * out, and finally check wether the answer is OK.
-   */
-  if (nfs_inode.u.socket_i.ops->connect &&
-      nfs_inode.u.socket_i.ops->connect(&nfs_inode.u.socket_i,
+	s.rsock	= rpc_makesock(filp);
+	s.flags = nfs_data.flags;
+	s.rsize = nfs_data.rsize;
+	s.wsize = nfs_data.wsize;
+	s.timeo = nfs_data.timeo * HZ / 10;
+	s.retrans = nfs_data.retrans;
+	strcpy(s.hostname, nfs_data.hostname);
+
+	/*
+	 *	First connect the UDP socket to a server port, then send the packet
+	 *	out, and finally check wether the answer is OK.
+	 */
+	 
+	if (nfs_inode.u.socket_i.ops->connect &&
+		nfs_inode.u.socket_i.ops->connect(&nfs_inode.u.socket_i,
 		(struct sockaddr *) &server, sizeof(struct sockaddr_in),
 		nfs_file.f_flags) < 0)
-	return NULL;
-  if (nfs_rpc_call(&s, rpc_packet, end, nfs_data.wsize) < 0)
-	return NULL;
-  return rpc_verify(rpc_packet);
+	{
+		return NULL;
+	}
+
+	if (nfs_rpc_call(&s, rpc_packet, end, nfs_data.wsize) < 0)
+		return NULL;
+	return rpc_verify(rpc_packet);
 }
 
 
 /*
- * Create an RPC packet header
+ *	Create an RPC packet header
  */
+ 
 static int *root_nfs_header(int proc, int program, int version)
 {
-  int groups[] = { 0, NOGROUP };
+	int groups[] = { 0, NOGROUP };
 
-  if (rpc_packet == NULL) {
-	if (!(rpc_packet = kmalloc(nfs_data.wsize + 1024, GFP_NFS))) {
-		printk(KERN_ERR "NFS: Cannot allocate UDP buffer\n");
-		return NULL;
+	if (rpc_packet == NULL) 
+	{
+		if (!(rpc_packet = kmalloc(nfs_data.wsize + 1024, GFP_NFS))) 
+		{
+			printk(KERN_ERR "NFS: Cannot allocate UDP buffer\n");
+			return NULL;
+		}
 	}
-  }
-  strcpy(system_utsname.nodename, in_ntoa(myaddr.sin_addr.s_addr));
-  return rpc_header(rpc_packet, proc, program, version, 0, 0, groups);
+	strcpy(system_utsname.nodename, in_ntoa(myaddr.sin_addr.s_addr));
+	return rpc_header(rpc_packet, proc, program, version, 0, 0, groups);
 }
 
 
 /*
- * Query server portmapper for the port of a daemon program
+ *	Query server portmapper for the port of a daemon program
  */
+
 static int root_nfs_get_port(int program, int version)
 {
-  int *p;
+	int *p;
 
-  /* Prepare header for portmap request */
-  server.sin_port = htons(NFS_PMAP_PORT);
-  p = root_nfs_header(NFS_PMAP_PROC, NFS_PMAP_PROGRAM, NFS_PMAP_VERSION);
-  if (!p)
-	return -1;
+	/*
+	 *	Prepare header for portmap request
+	 */
+	 
+	server.sin_port = htons(NFS_PMAP_PORT);
+	p = root_nfs_header(NFS_PMAP_PROC, NFS_PMAP_PROGRAM, NFS_PMAP_VERSION);
+	if (!p)
+		return -1;
 
-  /* Set arguments for portmapper */
-  *p++ = htonl(program);
-  *p++ = htonl(version);
-  *p++ = htonl(IPPROTO_UDP);
-  *p++ = 0;
+	/*
+	 *	Set arguments for portmapper
+	 */
+	 
+	*p++ = htonl(program);
+	*p++ = htonl(version);
+	*p++ = htonl(IPPROTO_UDP);
+	*p++ = 0;
 
-  /* Send request to server portmapper */
-  if ((p = root_nfs_call(p)) == NULL)
-	return -1;
+	/*
+	 *	Send request to server portmapper
+	 */
+	 
+	if ((p = root_nfs_call(p)) == NULL)
+		return -1;
 
-  return ntohl(*p);
+	return ntohl(*p);
 }
 
 
 /*
- * Get portnumbers for mountd and nfsd from server
+ *	Get portnumbers for mountd and nfsd from server
  */
+ 
 static int root_nfs_ports(void)
 {
-  int port;
+	int port;
 
-  if (nfs_port < 0) {
-	if ((port = root_nfs_get_port(NFS_NFS_PROGRAM, NFS_NFS_VERSION)) < 0) {
-		printk(KERN_ERR "NFS: Unable to get nfsd port number from server, using default\n");
-		port = NFS_NFS_PORT;
-	}
-	nfs_port = port;
+	if (nfs_port < 0) 
+	{
+		if ((port = root_nfs_get_port(NFS_NFS_PROGRAM, NFS_NFS_VERSION)) < 0) 
+		{
+			printk(KERN_ERR "NFS: Unable to get nfsd port number from server, using default\n");
+			port = NFS_NFS_PORT;
+		}
+		nfs_port = port;
 #ifdef NFSROOT_DEBUG
-	printk(KERN_NOTICE "NFS: Portmapper on server returned %d as nfsd port\n", port);
+		printk(KERN_NOTICE "NFS: Portmapper on server returned %d as nfsd port\n", port);
 #endif
-  }
+	}
 
-  if ((port = root_nfs_get_port(NFS_MOUNT_PROGRAM, NFS_MOUNT_VERSION)) < 0) {
-	printk(KERN_ERR "NFS: Unable to get mountd port number from server, using default\n");
-	port = NFS_MOUNT_PORT;
-  }
-  server.sin_port = htons(port);
+	if ((port = root_nfs_get_port(NFS_MOUNT_PROGRAM, NFS_MOUNT_VERSION)) < 0) 
+	{
+		printk(KERN_ERR "NFS: Unable to get mountd port number from server, using default\n");
+		port = NFS_MOUNT_PORT;
+	}
+	server.sin_port = htons(port);
 #ifdef NFSROOT_DEBUG
-  printk(KERN_NOTICE "NFS: Portmapper on server returned %d as mountd port\n", port);
+	printk(KERN_NOTICE "NFS: Portmapper on server returned %d as mountd port\n", port);
 #endif
-
-  return 0;
+	return 0;
 }
 
 
 /*
- * Get a file handle from the server for the directory which is to be mounted
+ *	Get a file handle from the server for the directory which is to be mounted
  */
+ 
 static int root_nfs_get_handle(void)
 {
-  int len, status, *p;
+	int len, status, *p;
+
+	/*
+	 *	Prepare header for mountd request 
+	 */
+	 
+	p = root_nfs_header(NFS_MOUNT_PROC, NFS_MOUNT_PROGRAM, NFS_MOUNT_VERSION);
+	if (!p) 
+	{
+		root_nfs_close(1);
+		return -1;
+	}
 
-  /* Prepare header for mountd request */
-  p = root_nfs_header(NFS_MOUNT_PROC, NFS_MOUNT_PROGRAM, NFS_MOUNT_VERSION);
-  if (!p) {
-	root_nfs_close(1);
-	return -1;
-  }
-
-  /* Set arguments for mountd */
-  len = strlen(nfs_path);
-  *p++ = htonl(len);
-  memcpy(p, nfs_path, len);
-  len = (len + 3) >> 2;
-  p[len] = 0;
-  p += len;
-
-  /* Send request to server portmapper */
-  if ((p = root_nfs_call(p)) == NULL) {
-	root_nfs_close(1);
-	return -1;
-  }
-
-  status = ntohl(*p++);
-  if (status == 0) {
-	nfs_data.root = *((struct nfs_fh *) p);
-  } else {
-	printk(KERN_ERR "NFS: Server returned error %d while mounting %s\n",
-							status, nfs_path);
-	root_nfs_close(1);
-	return -1;
-  }
+	/*
+	 *	Set arguments for mountd
+	 */
+
+	len = strlen(nfs_path);
+	*p++ = htonl(len);
+	memcpy(p, nfs_path, len);
+	len = (len + 3) >> 2;
+	p[len] = 0;
+	p += len;
+
+	/*
+	 *	Send request to server portmapper 
+	 */
+
+	if ((p = root_nfs_call(p)) == NULL)
+	{
+		root_nfs_close(1);
+		return -1;
+	}
 
-  return 0;
+	status = ntohl(*p++);
+	if (status == 0) 
+	{
+		nfs_data.root = *((struct nfs_fh *) p);
+	} 
+	else
+	{
+		printk(KERN_ERR "NFS: Server returned error %d while mounting %s\n",
+			status, nfs_path);
+		root_nfs_close(1);
+		return -1;
+	}
+	return 0;
 }
 
 
 /*
- * Now actually mount the given directory
+ *	Now actually mount the given directory
  */
+
 static int root_nfs_do_mount(struct super_block *sb)
 {
-  /* First connect to the nfsd port on the server */
-  server.sin_port = htons(nfs_port);
-  nfs_data.addr = server;
-  if (nfs_inode.u.socket_i.ops->connect &&
-      nfs_inode.u.socket_i.ops->connect(&nfs_inode.u.socket_i,
+	/*
+	 *	First connect to the nfsd port on the server 
+	 */
+
+	server.sin_port = htons(nfs_port);
+	nfs_data.addr = server;
+	if (nfs_inode.u.socket_i.ops->connect &&
+		nfs_inode.u.socket_i.ops->connect(&nfs_inode.u.socket_i,
 		(struct sockaddr *) &server, sizeof(struct sockaddr_in),
-		nfs_file.f_flags) < 0) {
-	root_nfs_close(1);
-	return -1;
-  }
+		nfs_file.f_flags) < 0) 
+	{
+		root_nfs_close(1);
+		return -1;
+	}
 
-  /* Now (finally ;-)) read the super block for mounting */
-  if (nfs_read_super(sb, &nfs_data, 1) == NULL) {
-	root_nfs_close(1);
-	return -1;
-  }
+	/*
+	 *	Now (finally ;-)) read the super block for mounting
+	 */
+
+	if (nfs_read_super(sb, &nfs_data, 1) == NULL) 
+	{
+		root_nfs_close(1);
+		return -1;
+	}
 
-  return 0;
+	return 0;
 }
 
 
 /*
- * Get the NFS port numbers and file handle, and then read the super-
- * block for mounting.
+ *	Get the NFS port numbers and file handle, and then read the super-
+ *	block for mounting.
  */
+
 int nfs_root_mount(struct super_block *sb)
 {
-  if (root_nfs_open() < 0)
-	return -1;
-  if (root_nfs_bind() < 0)
-	return -1;
-  if (root_nfs_ports() < 0)
-	return -1;
-  if (root_nfs_get_handle() < 0)
-	return -1;
-  if (root_nfs_do_mount(sb) < 0)
-	return -1;
-  root_nfs_close(0);
-  return 0;
+	if (root_nfs_open() < 0)
+		return -1;
+	if (root_nfs_bind() < 0)
+		return -1;
+	if (root_nfs_ports() < 0)
+		return -1;
+	if (root_nfs_get_handle() < 0)
+		return -1;
+	if (root_nfs_do_mount(sb) < 0)
+		return -1;
+	root_nfs_close(0);
+	return 0;
 }
diff -u --recursive --new-file v1.3.43/linux/fs/pipe.c linux/fs/pipe.c
--- v1.3.43/linux/fs/pipe.c	Wed Aug  2 13:21:15 1995
+++ linux/fs/pipe.c	Fri Nov 24 07:46:12 1995
@@ -240,10 +240,6 @@
 	return 0;
 }
 
-/*
- * Ok, these three routines NOW keep track of readers/writers,
- * Linus previously did it with inode->i_count checking.
- */
 static void pipe_read_release(struct inode * inode, struct file * filp)
 {
 	PIPE_READERS(*inode)--;
@@ -263,6 +259,25 @@
 	wake_up_interruptible(&PIPE_WAIT(*inode));
 }
 
+static int pipe_read_open(struct inode * inode, struct file * filp)
+{
+	PIPE_READERS(*inode)++;
+	return 0;
+}
+
+static int pipe_write_open(struct inode * inode, struct file * filp)
+{
+	PIPE_WRITERS(*inode)++;
+	return 0;
+}
+
+static int pipe_rdwr_open(struct inode * inode, struct file * filp)
+{
+	PIPE_READERS(*inode)++;
+	PIPE_WRITERS(*inode)++;
+	return 0;
+}
+
 /*
  * The file_operations structs are not static because they
  * are also used in linux/fs/fifo.c to do operations on fifo's.
@@ -275,7 +290,7 @@
 	connect_select,
 	pipe_ioctl,
 	NULL,		/* no mmap on pipes.. surprise */
-	NULL,		/* no special open code */
+	pipe_read_open,
 	pipe_read_release,
 	NULL
 };
@@ -288,7 +303,7 @@
 	fifo_select,
 	pipe_ioctl,
 	NULL,		/* no mmap on pipes.. surprise */
-	NULL,		/* no special open code */
+	pipe_read_open,
 	pipe_read_release,
 	NULL
 };
@@ -301,7 +316,7 @@
 	fifo_select,
 	pipe_ioctl,
 	NULL,		/* mmap */
-	NULL,		/* no special open code */
+	pipe_write_open,
 	pipe_write_release,
 	NULL
 };
@@ -314,7 +329,7 @@
 	fifo_select,
 	pipe_ioctl,
 	NULL,		/* mmap */
-	NULL,		/* no special open code */
+	pipe_rdwr_open,
 	pipe_rdwr_release,
 	NULL
 };
@@ -327,7 +342,7 @@
 	pipe_select,
 	pipe_ioctl,
 	NULL,		/* no mmap on pipes.. surprise */
-	NULL,		/* no special open code */
+	pipe_read_open,
 	pipe_read_release,
 	NULL
 };
@@ -340,7 +355,7 @@
 	pipe_select,
 	pipe_ioctl,
 	NULL,		/* mmap */
-	NULL,		/* no special open code */
+	pipe_write_open,
 	pipe_write_release,
 	NULL
 };
@@ -353,7 +368,7 @@
 	pipe_select,
 	pipe_ioctl,
 	NULL,		/* mmap */
-	NULL,		/* no special open code */
+	pipe_rdwr_open,
 	pipe_rdwr_release,
 	NULL
 };
diff -u --recursive --new-file v1.3.43/linux/fs/proc/fd.c linux/fs/proc/fd.c
--- v1.3.43/linux/fs/proc/fd.c	Mon Sep 18 14:54:07 1995
+++ linux/fs/proc/fd.c	Fri Nov 24 07:17:49 1995
@@ -50,7 +50,7 @@
 	NULL			/* permission */
 };
 
-static int proc_lookupfd(struct inode * dir,const char * name, int len,
+static int proc_lookupfd(struct inode * dir, const char * name, int len,
 	struct inode ** result)
 {
 	unsigned int ino, pid, fd, c;
@@ -167,7 +167,7 @@
 		if (filldir(dirent, buf+j, NUMBUF-j, fd+2, ino) < 0)
 			break;
 
-		/* filldir() migth have slept, so we must re-validate "p" */
+		/* filldir() might have slept, so we must re-validate "p" */
 		if (p != task[task_nr] || p->pid != pid)
 			break;
 	}
diff -u --recursive --new-file v1.3.43/linux/include/asm-alpha/io.h linux/include/asm-alpha/io.h
--- v1.3.43/linux/include/asm-alpha/io.h	Thu Nov  9 11:23:52 1995
+++ linux/include/asm-alpha/io.h	Thu Nov 23 11:26:03 1995
@@ -128,6 +128,20 @@
 # define outb_p		outb
 #endif
 
+#ifndef inw_p
+# define inw_p		inw
+#endif
+#ifndef outw_p
+# define outw_p		outw
+#endif
+
+#ifndef inl_p
+# define inl_p		inl
+#endif
+#ifndef outl_p
+# define outl_p		outl
+#endif
+
 /*
  * The "address" in IO memory space is not clearly either a integer or a
  * pointer. We will accept both, thus the casts.
diff -u --recursive --new-file v1.3.43/linux/include/asm-alpha/segment.h linux/include/asm-alpha/segment.h
--- v1.3.43/linux/include/asm-alpha/segment.h	Tue Jun 27 14:11:44 1995
+++ linux/include/asm-alpha/segment.h	Sat Nov 25 11:54:56 1995
@@ -4,6 +4,16 @@
 #include <linux/string.h>
 
 /*
+ * This is a gcc optimization barrier, which essentially
+ * inserts a sequence point in the gcc RTL tree that gcc
+ * can't move code around. This is needed when we enter
+ * or exit a critical region (in this case around user-level
+ * accesses that may sleep, and we can't let gcc optimize
+ * global state around them).
+ */
+#define __gcc_barrier() __asm__ __volatile__("": : :"memory")
+
+/*
  * Uh, these should become the main single-value transfer routines..
  * They automatically use the right size if we just have the right
  * pointer type..
@@ -21,6 +31,7 @@
 /* I should make this use unaligned transfers etc.. */
 static inline void __put_user(unsigned long x, void * y, int size)
 {
+	__gcc_barrier();
 	switch (size) {
 		case 1:
 			*(char *) y = x;
@@ -37,84 +48,58 @@
 		default:
 			bad_user_access_length();
 	}
+	__gcc_barrier();
 }
 
 /* I should make this use unaligned transfers etc.. */
 static inline unsigned long __get_user(const void * y, int size)
 {
+	unsigned long result;
+
+	__gcc_barrier();
 	switch (size) {
 		case 1:
-			return *(unsigned char *) y;
+			result = *(unsigned char *) y;
+			break;
 		case 2:
-			return *(unsigned short *) y;
+			result = *(unsigned short *) y;
+			break;
 		case 4:
-			return *(unsigned int *) y;
+			result = *(unsigned int *) y;
+			break;
 		case 8:
-			return *(unsigned long *) y;
+			result = *(unsigned long *) y;
+			break;
 		default:
-			return bad_user_access_length();
+			result = bad_user_access_length();
 	}
+	__gcc_barrier();
+	return result;
 }
 
-static inline unsigned char get_user_byte(const char * addr)
-{
-	return *addr;
-}
-
-#define get_fs_byte(addr) get_user_byte((char *)(addr))
-
-static inline unsigned short get_user_word(const short *addr)
-{
-	return *addr;
-}
-
-#define get_fs_word(addr) get_user_word((short *)(addr))
-
-static inline unsigned long get_user_long(const int *addr)
-{
-	return *addr;
-}
-
-#define get_fs_long(addr) get_user_long((int *)(addr))
-
-static inline unsigned long get_user_quad(const long *addr)
-{
-	return *addr;
-}
+#define get_fs_byte(addr) get_user((unsigned char *)(addr))
+#define get_fs_word(addr) get_user((unsigned short *)(addr))
+#define get_fs_long(addr) get_user((unsigned int *)(addr))
+#define get_fs_quad(addr) get_user((unsigned long *)(addr))
 
-#define get_fs_quad(addr) get_user_quad((long *)(addr))
+#define put_fs_byte(x,addr) put_user((x),(char *)(addr))
+#define put_fs_word(x,addr) put_user((x),(short *)(addr))
+#define put_fs_long(x,addr) put_user((x),(int *)(addr))
+#define put_fs_quad(x,addr) put_user((x),(long *)(addr))
 
-static inline void put_user_byte(char val,char *addr)
+static inline void memcpy_fromfs(void * to, const void * from, unsigned long n)
 {
-	*addr = val;
+	__gcc_barrier();
+	memcpy(to, from, n);
+	__gcc_barrier();
 }
 
-#define put_fs_byte(x,addr) put_user_byte((x),(char *)(addr))
-
-static inline void put_user_word(short val,short * addr)
+static inline void memcpy_tofs(void * to, const void * from, unsigned long n)
 {
-	*addr = val;
+	__gcc_barrier();
+	memcpy(to, from, n);
+	__gcc_barrier();
 }
-
-#define put_fs_word(x,addr) put_user_word((x),(short *)(addr))
-
-static inline void put_user_long(unsigned long val,int * addr)
-{
-	*addr = val;
-}
-
-#define put_fs_long(x,addr) put_user_long((x),(int *)(addr))
-
-static inline void put_user_quad(unsigned long val,long * addr)
-{
-	*addr = val;
-}
-
-#define put_fs_quad(x,addr) put_user_quad((x),(long *)(addr))
-
-#define memcpy_fromfs(to, from, n) memcpy((to),(from),(n))
-
-#define memcpy_tofs(to, from, n) memcpy((to),(from),(n))
 
 /*
  * For segmented architectures, these are used to specify which segment
diff -u --recursive --new-file v1.3.43/linux/include/asm-alpha/system.h linux/include/asm-alpha/system.h
--- v1.3.43/linux/include/asm-alpha/system.h	Mon Nov 13 12:36:46 1995
+++ linux/include/asm-alpha/system.h	Sat Nov 25 11:54:56 1995
@@ -79,7 +79,7 @@
 	"bis %0,%0,$16\n\t" \
 	"call_pal 53" \
 	: : "r" (__new_ipl) \
-	: "$0", "$1", "$16", "$22", "$23", "$24", "$25")
+	: "$0", "$1", "$16", "$22", "$23", "$24", "$25", "memory")
 
 #define swpipl(__new_ipl) \
 ({ unsigned long __old_ipl; \
@@ -89,7 +89,7 @@
 	"bis $0,$0,%0" \
 	: "=r" (__old_ipl) \
 	: "r" (__new_ipl) \
-	: "$0", "$1", "$16", "$22", "$23", "$24", "$25"); \
+	: "$0", "$1", "$16", "$22", "$23", "$24", "$25", "memory"); \
 __old_ipl; })
 
 #define cli()			setipl(7)
diff -u --recursive --new-file v1.3.43/linux/include/asm-i386/socket.h linux/include/asm-i386/socket.h
--- v1.3.43/linux/include/asm-i386/socket.h	Tue Jul 11 10:02:59 1995
+++ linux/include/asm-i386/socket.h	Fri Nov 24 16:39:54 1995
@@ -25,6 +25,7 @@
 #define SO_NO_CHECK	11
 #define SO_PRIORITY	12
 #define SO_LINGER	13
-/* To add :#define SO_REUSEPORT 14 */
+#define SO_BSDCOMPAT	14
+/* To add :#define SO_REUSEPORT 15 */
 
 #endif /* _ASM_SOCKET_H */
diff -u --recursive --new-file v1.3.43/linux/include/asm-i386/unistd.h linux/include/asm-i386/unistd.h
--- v1.3.43/linux/include/asm-i386/unistd.h	Tue Nov 21 13:22:13 1995
+++ linux/include/asm-i386/unistd.h	Fri Nov 24 16:13:33 1995
@@ -152,6 +152,7 @@
 #define __NR_msync		144
 #define __NR_readv		145
 #define __NR_writev		146
+#define __NR_getsid		147
 
 #define __NR_mlock		150
 #define __NR_munlock		151
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/a.out.h linux/include/asm-sparc/a.out.h
--- v1.3.43/linux/include/asm-sparc/a.out.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-sparc/a.out.h	Sat Nov 25 04:31:10 1995
@@ -0,0 +1,50 @@
+/* $Id: a.out.h,v 1.8 1995/11/25 02:31:09 davem Exp $ */
+#ifndef __SPARC_A_OUT_H__
+#define __SPARC_A_OUT_H__
+
+#define SPARC_PGSIZE    0x2000        /* Thanks to the sun4 architecture... */
+#define SEGMENT_SIZE    SPARC_PGSIZE  /* whee... */
+
+struct exec {
+	unsigned char a_dynamic:1;      /* A __DYNAMIC is in this image */
+	unsigned char a_toolversion:7;
+	unsigned char a_machtype;
+	unsigned short a_info;
+	unsigned long a_text;		/* length of text, in bytes */
+	unsigned long a_data;		/* length of data, in bytes */
+	unsigned long a_bss;		/* length of bss, in bytes */
+	unsigned long a_syms;		/* length of symbol table, in bytes */
+	unsigned long a_entry;		/* where program begins */
+	unsigned long a_trsize;
+	unsigned long a_drsize;
+};
+
+/* Where in the file does the text information begin? */
+#define N_TXTOFF(x)     (N_MAGIC(x) == ZMAGIC ? 0 : sizeof (struct exec))
+
+/* Where do the Symbols start? */
+#define N_SYMOFF(x)     (N_TXTOFF(x) + (x).a_text +   \
+                         (x).a_data + (x).a_trsize +  \
+                         (x).a_drsize)
+
+/* Where does text segment go in memory after being loaded? */
+#define N_TXTADDR(x)    (((N_MAGIC(x) == ZMAGIC) &&        \
+	                 ((x).a_entry < SPARC_PGSIZE)) ?   \
+                          0 : SPARC_PGSIZE)
+
+/* And same for the data segment.. */
+#define N_DATADDR(x) (N_MAGIC(x)==OMAGIC ?         \
+                      (N_TXTADDR(x) + (x).a_text)  \
+                       : (_N_SEGMENT_ROUND (_N_TXTENDADDR(x))))
+
+#define N_TRSIZE(a)	((a).a_trsize)
+#define N_DRSIZE(a)	((a).a_drsize)
+#define N_SYMSIZE(a)	((a).a_syms)
+
+#ifdef __KERNEL__
+
+#define STACK_TOP	TASK_SIZE
+
+#endif
+
+#endif /* __SPARC_A_OUT_H__ */
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/asi.h linux/include/asm-sparc/asi.h
--- v1.3.43/linux/include/asm-sparc/asi.h	Wed Nov  8 07:11:41 1995
+++ linux/include/asm-sparc/asi.h	Sat Nov 25 04:31:12 1995
@@ -1,3 +1,4 @@
+/* $Id: asi.h,v 1.11 1995/11/25 02:31:11 davem Exp $ */
 #ifndef _SPARC_ASI_H
 #define _SPARC_ASI_H
 
@@ -9,39 +10,29 @@
  * Joint edition for sun4c+sun4m: Pete A. Zaitcev <zaitcev@ipmce.su>
  */
 
-/* These are sun4c, beware on other architectures. Although things should
- * be similar under regular sun4's.
- */
+/* The first batch are for the sun4c. */
 
-#define ASI_NULL1        0x0
-#define ASI_NULL2        0x1
+#define ASI_NULL1           0x00
+#define ASI_NULL2           0x01
 
 /* sun4c and sun4 control registers and mmu/vac ops */
-#define ASI_CONTROL          0x2
-#define ASI_SEGMAP           0x3
-#define ASI_PTE              0x4
-#define ASI_HWFLUSHSEG       0x5      /* These are to initiate hw flushes of the cache */
-#define ASI_HWFLUSHPAGE      0x6
-#define ASI_REGMAP           0x6      /* Top level segmaps on Sun4's with MUTANT MMU */
-#define ASI_HWFLUSHCONTEXT   0x7
-
-
-#define ASI_USERTXT      0x8
-#define ASI_KERNELTXT    0x9
-#define ASI_USERDATA     0xa
-#define ASI_KERNELDATA   0xb
+#define ASI_CONTROL         0x02
+#define ASI_SEGMAP          0x03
+#define ASI_PTE             0x04
+#define ASI_HWFLUSHSEG      0x05
+#define ASI_HWFLUSHPAGE     0x06
+#define ASI_REGMAP          0x06
+#define ASI_HWFLUSHCONTEXT  0x07
+
+#define ASI_USERTXT         0x08
+#define ASI_KERNELTXT       0x09
+#define ASI_USERDATA        0x0a
+#define ASI_KERNELDATA      0x0b
 
 /* VAC Cache flushing on sun4c and sun4 */
-
-#define ASI_FLUSHSEG     0xc      /* These are for "software" flushes of the cache */
-#define ASI_FLUSHPG      0xd
-#define ASI_FLUSHCTX     0xe
-
-/* The following are now not so SS5 specific any more, it is pretty
- * much a complete generic sun4m/V8 ASI assignment listing now.
- *
- * -- davem@caip.rutgers.edu
- */
+#define ASI_FLUSHSEG        0x0c
+#define ASI_FLUSHPG         0x0d
+#define ASI_FLUSHCTX        0x0e
 
 /* SPARCstation-5: only 6 bits are decoded. */
 /* wo = Write Only, rw = Read Write;        */
@@ -64,8 +55,8 @@
 #define ASI_M_DATAC_DATA    0x0F   /* Data Cache Data; rw, ss */
 
 /* The following cache flushing ASIs work only with the 'sta'
- * instruction results are unpredictable for 'swap' and 'ldstuba' etc.
- * So don't do it.
+ * instruction. Results are unpredictable for 'swap' and 'ldstuba',
+ * so don't do it.
  */
 
 /* These ASI flushes affect external caches too. */
@@ -75,7 +66,7 @@
 #define ASI_M_FLUSH_CTX     0x13   /* Flush I&D Cache Line (context); wo, ss */
 #define ASI_M_FLUSH_USER    0x14   /* Flush I&D Cache Line (user); wo, ss */
 
-/* Block-copy operations are available on certain V8 cpus */
+/* Block-copy operations are available only on certain V8 cpus. */
 #define ASI_M_BCOPY         0x17   /* Block copy */
 
 /* These affect only the ICACHE and are Ross HyperSparc specific. */
@@ -108,7 +99,7 @@
 
 #define ASI_M_DCDR         0x39   /* Data Cache Diagnostics Registerl rw, ss */
 
-/* Sparc V9 TI UltraSparc ASI's */
+/* Sparc V9 TI UltraSparc ASI's (V8 ploos ploos) */
 
 /* ASIs 0x0-0x7f are Supervisor Only.  0x80-0xff are for anyone. */
 
@@ -126,9 +117,9 @@
 #define ASI_V9_USER_SEC    0x11   /* User secondary address space */
 
 #define ASI_V9_MMUPASS     0x14   /* OBMEM (external cache, no data cache) */
-#define ASI_V9_IOPASS      0x15   /* Like MMUPASS but for I/O areas (uncached) */
-#define ASI_V9_USER_PRIML  0x18   /* User primary address space, little-endian. */
-#define ASI_V9_USER_SECL   0x19   /* User secondary address space, little-endian. */
+#define ASI_V9_IOPASS      0x15   /* Like MMUPASS, for I/O areas (uncached) */
+#define ASI_V9_USER_PRIML  0x18   /* User primary addr space, lil-endian. */
+#define ASI_V9_USER_SECL   0x19   /* User secondary addr space, lil-endian. */
 #define ASI_V9_MMUPASSL    0x1C   /* OBMEM little-endian */
 #define ASI_V9_IOPASSL     0x1D   /* Like IOPASS but little-endian */
 #define ASI_V9_ATOMICQ     0x24   /* Atomic 128-bit load address space */
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/asi4m.h linux/include/asm-sparc/asi4m.h
--- v1.3.43/linux/include/asm-sparc/asi4m.h	Sun Feb 26 20:46:20 1995
+++ linux/include/asm-sparc/asi4m.h	Thu Jan  1 02:00:00 1970
@@ -1,29 +0,0 @@
-#ifndef _SPARC_ASI4M_H
-#define _SPARC_ASI4M_H
-
-/* asi4m.h: Address Space Identifier values for sun4m
- 
-   Copyright (C) 1995 Paul Hatchman (paul@sfe.com.au)
-*/
-
-#define ASI_PTE 0x0
-
-#define ASI_NULL1			0x0
-#define ASI_NULL2			0x1
-#define	ASI_CONTROL			0x4	/* hmm? */
-#define	ASI_USERTXT			0x8	/* user text */
-#define	ASI_KERNELTXT		0x9	/* kernel text */
-#define	ASI_USERDATA		0xA	/* user data */
-#define	ASI_KERNELDATA		0xB	/* kernel data */
-
-/* cache flushing */
-#define ASI_FLUSHPG			0x10 
-#define ASI_FLUSHSEG		0x11
-#define ASI_FLUSHRGN		0x12
-#define ASI_FLUSHCTX		0x13
-
-/* MMU REGS */
-#define SRMMU_CTL 0x000
-#define SRMMU_CTP 0x100		/* set/get context pointer */
-#define SRMMU_CTX 0x200 	/* get/set context */
-#endif _SPARC_ASI4M_H
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/auxio.h linux/include/asm-sparc/auxio.h
--- v1.3.43/linux/include/asm-sparc/auxio.h	Tue Jun 27 14:11:44 1995
+++ linux/include/asm-sparc/auxio.h	Sat Nov 25 04:31:14 1995
@@ -1,35 +1,69 @@
-/* auxio.h:  Definitons and code for the Auxiliary I/O register.
+/* $Id: auxio.h,v 1.8 1995/11/25 02:31:13 davem Exp $
+ * auxio.h:  Definitons and code for the Auxiliary I/O register.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  */
 #ifndef _SPARC_AUXIO_H
 #define _SPARC_AUXIO_H
 
-/* This defines the register as I know it on the Sun4c, it may be
- * different or not exist at all on sun4m's.
- */
-
-#define AUXIO_IOADDR  0xf7400000  /* Physical address is IO space */
+#include <asm/system.h>
+#include <asm/vaddrs.h>
 
 /* This register is an unsigned char in IO space.  It does two things.
  * First, it is used to control the front panel LED light on machines
  * that have it (good for testing entry points to trap handlers and irq's)
- * Secondly, it controls various floppy drive parameters on machines that
- * have a drive.
+ * Secondly, it controls various floppy drive parameters.
  */
 
 #define AUXIO_ORMEIN      0xf0    /* All writes must set these bits. */
-#define AUXIO_FLPY_DENS   0x20    /* Floppy density, high if set. */
-#define AUXIO_FLPY_DCHG   0x10    /* A disk change occurred. */
-#define AUXIO_FLPY_DSEL   0x08    /* Drive select, 0 'a drive' 1 'b drive'. */
-#define AUXIO_FLPY_TCNT   0x04    /* Floppy terminal count... ??? */
-#define AUXIO_FLPY_EJCT   0x02    /* Eject floppy disk. */
-#define AUXIO_LED         0x01    /* On if set, off if unset. */
-
-#define AUXREG ((volatile unsigned char *)(AUXIO_VADDR + 3))
-
-#define TURN_ON_LED  *AUXREG = AUXIO_ORMEIN | AUXIO_FLPY_EJCT | AUXIO_LED
-#define TURN_OFF_LED *AUXREG = AUXIO_ORMEIN | AUXIO_FLPY_EJCT
-#define FLIP_LED     *AUXREG = (*AUXREG | AUXIO_ORMEIN) ^ AUXIO_LED
+#define AUXIO_ORMEIN4M    0xc0    /* sun4m - All writes must set these bits. */
+#define AUXIO_FLPY_DENS   0x20    /* Floppy density, high if set. Read only. */
+#define AUXIO_FLPY_DCHG   0x10    /* A disk change occurred.  Read only. */
+#define AUXIO_EDGE_ON     0x10    /* sun4m - On means Jumper block is in. */
+#define AUXIO_FLPY_DSEL   0x08    /* Drive select/start-motor. Write only. */
+
+/* Set the following to one, then zero, after doing a pseudo DMA transfer. */
+#define AUXIO_FLPY_TCNT   0x04    /* Floppy terminal count. Write only. */
+
+/* Set the following to zero to eject the floppy. */
+#define AUXIO_FLPY_EJCT   0x02    /* Eject floppy disk.  Write only. */
+#define AUXIO_LED         0x01    /* On if set, off if unset. Read/Write */
+
+#define AUXREG   ((volatile unsigned char *)(AUXIO_VADDR + 3))
+#define AUXREG4M ((volatile unsigned char *)(AUXIO_VADDR))
+
+#define TURN_ON_LED   *AUXREG = (*AUXREG | AUXIO_ORMEIN | AUXIO_LED)
+#define TURN_OFF_LED  *AUXREG = ((*AUXREG | AUXIO_ORMEIN) & (~AUXIO_LED))
+#define FLIP_LED      *AUXREG = ((*AUXREG | AUXIO_ORMEIN) ^ AUXIO_LED)
+#define FLPY_MOTORON  *AUXREG = ((*AUXREG | AUXIO_ORMEIN) | AUXIO_FLPY_DSEL)
+#define FLPY_MOTOROFF *AUXREG = ((*AUXREG | AUXIO_ORMEIN) & (~AUXIO_FLPY_DSEL))
+#define FLPY_TCNTON   *AUXREG = ((*AUXREG | AUXIO_ORMEIN) | AUXIO_FLPY_TCNT)
+#define FLPY_TCNTOFF  *AUXREG = ((*AUXREG | AUXIO_ORMEIN) & (~AUXIO_FLPY_TCNT))
+
+#ifndef __ASSEMBLY__
+extern inline void set_auxio(unsigned char bits_on, unsigned char bits_off)
+{
+	unsigned char regval;
+
+	cli();
+
+	switch(sparc_cpu_model) {
+	case sun4c:
+		regval = *AUXREG;
+		*AUXREG = ((regval | bits_on) & ~bits_off) | AUXIO_ORMEIN;
+		break;
+	case sun4m:
+		regval = *AUXREG4M;
+		*AUXREG4M = ((regval | bits_on) & ~bits_off) | AUXIO_ORMEIN4M;
+		break;
+	default:
+		panic("Can't set AUXIO register on this machine.");
+	};
+
+	sti();
+
+	return;
+}
+#endif /* !(__ASSEMBLY__) */
 
 #endif /* !(_SPARC_AUXIO_H) */
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/bitops.h linux/include/asm-sparc/bitops.h
--- v1.3.43/linux/include/asm-sparc/bitops.h	Tue Aug 15 20:39:04 1995
+++ linux/include/asm-sparc/bitops.h	Sat Nov 25 04:31:16 1995
@@ -1,13 +1,17 @@
+/* $Id: bitops.h,v 1.17 1995/11/25 02:31:15 davem Exp $
+ * bitops.h: Bit string operations on the Sparc.
+ *
+ * Copyright 1995, David S. Miller (davem@caip.rutgers.edu).
+ */
+
 #ifndef _SPARC_BITOPS_H
 #define _SPARC_BITOPS_H
 
 #include <linux/kernel.h>
-#include <asm/system.h>
-
-/*
- * Copyright 1995, David S. Miller (davem@caip.rutgers.edu).
- */
 
+#ifdef __KERNEL__
+#include <asm/system.h>
+#endif
 
 /* Set bit 'nr' in 32-bit quantity at address 'addr' where bit '0'
  * is in the highest of the four bytes and bit '31' is the high bit
@@ -15,264 +19,67 @@
  * all bit-ops return 0 if bit was previously clear and != 0 otherwise.
  */
 
-/* For now, the sun4c implementation will disable and enable traps
- * in order to insure atomicity. Things will have to be different
- * for sun4m (ie. SMP) no doubt.
- */
-
-/* These routines now do things in little endian byte order. */
-
-/* Our unsigned long accesses on the Sparc look like this:
- * Big Endian:
- *    byte 0    byte 1      byte 2    byte 3
- *  0000 0000  0000 0000  0000 0000  0000 0000
- *  31     24  23     16  15      8  7       0
- *
- * We want to set the bits in a little-endian fashion:
- * Little Endian:
- *    byte 3    byte 2      byte 1    byte 0
- *  0000 0000  0000 0000  0000 0000  0000 0000
- *  31     24  23     16  15      8  7       0
- */
-
-/* #define __LITTLE_ENDIAN_BITOPS */
-
-extern __inline__ unsigned int set_bit(unsigned int nr, void *vaddr)
+extern __inline__ unsigned long set_bit(unsigned long nr, void *addr)
 {
+	int mask, flags;
+	unsigned long *ADDR = (unsigned long *) addr;
+	unsigned long oldbit;
 
-
-#ifdef __LITTLE_ENDIAN_BITOPS
-
-
-        int retval;
-        unsigned char *addr = (unsigned char *)vaddr;
-	unsigned char mask;
-#ifndef TEST_BITOPS
-        unsigned long flags;
-#endif
-
-        addr += nr >> 3;
-        mask = 1 << (nr & 0x7);
-
-#ifndef TEST_BITOPS
-	save_flags(flags);
-	cli();
-#endif
-
-        retval = (mask & *addr) != 0;
-        *addr |= mask;
-
-#ifndef TEST_BITOPS
-	restore_flags(flags);
-#endif
-
-        return retval;
-
-#else  /* BIG ENDIAN BITOPS */
-
-
-	int retval;
-	unsigned long *addr = vaddr;
-	unsigned long mask;
-#ifndef TEST_BITOPS
-	unsigned long flags;
-#endif
-
-	addr += nr>>5;
-	mask = 1 << (nr&31);
-
-#ifndef TEST_BITOPS
-	save_flags(flags);
-	cli();
-#endif
-
-	retval = (mask & *addr) != 0;
-	*addr |= mask;
-
-#ifndef TEST_BITOPS
+	ADDR += nr >> 5;
+	mask = 1 << (nr & 31);
+	save_flags(flags); cli();
+	oldbit = (mask & *ADDR);
+	*ADDR |= mask;
 	restore_flags(flags);
-#endif
-
-	return retval;
-
-
-#endif
+	return oldbit != 0;
 }
 
-extern __inline__ unsigned int clear_bit(unsigned int nr, void *vaddr)
+extern __inline__ unsigned long clear_bit(unsigned long nr, void *addr)
 {
-#ifdef __LITTLE_ENDIAN_BITOPS
-
-
-        int retval;
-        unsigned char *addr = (unsigned char *)vaddr;
-	unsigned char mask;
-#ifndef TEST_BITOPS
-        unsigned long flags;
-#endif
-
-        addr += nr >> 3;
-        mask = 1 << (nr & 7);
-
-#ifndef TEST_BITOPS
-	save_flags(flags);
-	cli();
-#endif
+	int mask, flags;
+	unsigned long *ADDR = (unsigned long *) addr;
+	unsigned long oldbit;
 
-        retval = (mask & *addr) != 0;
-        *addr &= ~mask;
-
-#ifndef TEST_BITOPS
+	ADDR += nr >> 5;
+	mask = 1 << (nr & 31);
+	save_flags(flags); cli();
+	oldbit = (mask & *ADDR);
+	*ADDR &= ~mask;
 	restore_flags(flags);
-#endif
-
-        return retval;
-
-
-#else   /* BIG ENDIAN BITOPS */
-
-
-	int retval;
-	unsigned long *addr = vaddr;
-	unsigned long mask;
-#ifndef TEST_BITOPS
-	unsigned long flags;
-#endif
-
-	addr += nr>>5;
-	mask = 1 << (nr&31);
-
-#ifndef TEST_BITOPS
-	save_flags(flags);
-	cli();
-#endif
-
-	retval = (mask & *addr) != 0;
-	*addr &= ~mask;
-
-#ifndef TEST_BITOPS
-	restore_flags(flags);
-#endif
-
-	return retval;
-
-
-#endif
+	return oldbit != 0;
 }
 
-extern __inline__ unsigned int change_bit(unsigned int nr, void *vaddr)
+extern __inline__ unsigned long change_bit(unsigned long nr, void *addr)
 {
-#ifdef __LITTLE_ENDIAN_BITOPS
-
-
-        int retval;
-        unsigned char *addr = (unsigned char *)vaddr;
-	unsigned char mask;
-#ifndef TEST_BITOPS
-        unsigned long flags;
-#endif
-
-        addr += nr >> 3;
-        mask = 1 << (nr & 7);
-
-#ifndef TEST_BITOPS
-	save_flags(flags);
-	cli();
-#endif
-
-        retval = (mask & *addr) != 0;
-        *addr ^= mask;
-
-#ifndef TEST_BITOPS
-	restore_flags(flags);
-#endif
-
-        return retval;
-
-
-#else   /* BIG ENDIAN BITOPS */
-
-
-	int retval;
-	unsigned long *addr = vaddr;
-	unsigned long mask;
-#ifndef TEST_BITOPS
-	unsigned long flags;
-#endif
-
-	addr += nr>>5;
-	mask = 1 << (nr&31);
-
-#ifndef TEST_BITOPS
-	save_flags(flags);
-	cli();
-#endif
+	int mask, flags;
+	unsigned long *ADDR = (unsigned long *) addr;
+	unsigned long oldbit;
 
-	retval = (mask & *addr) != 0;
-	*addr ^= mask;
-
-#ifndef TEST_BITOPS
+	ADDR += nr >> 5;
+	mask = 1 << (nr & 31);
+	save_flags(flags); cli();
+	oldbit = (mask & *ADDR);
+	*ADDR ^= mask;
 	restore_flags(flags);
-#endif
-
-	return retval;
-
-
-#endif
+	return oldbit != 0;
 }
 
 /* The following routine need not be atomic. */
-
-extern __inline__ unsigned int test_bit(int nr, void *vaddr)
+extern __inline__ unsigned long test_bit(int nr, const void *addr)
 {
-#ifdef __LITTLE_ENDIAN_BITOPS
-
-        unsigned char mask;
-        unsigned char *addr = (unsigned char *)vaddr;
-
-        addr += nr >> 3;
-        mask = 1 << (nr & 7);
-        return ((mask & *addr) != 0);
-
-#else   /* BIG ENDIAN BITOPS */
-
-	unsigned long mask;
-	unsigned long *addr = vaddr;
-
-	addr += (nr>>5);
-	mask = 1 << (nr&31);
-	return ((mask & *addr) != 0);
-
-#endif
+	return 1UL & (((int *) addr)[nr >> 5] >> (nr & 31));
 }
 
-/* There has to be a faster way to do this, sigh... */
-
+/* The easy/cheese version for now. */
 extern __inline__ unsigned long ffz(unsigned long word)
 {
-  register unsigned long cnt;
-
-  cnt = 0;
-
-#ifdef __LITTLE_ENDIAN_BITOPS
-
-  for(int byte_bit = 24; byte_bit >=0; byte_bit -= 8)
-	  for(int bit = 0; bit<8; bit++)
-		  if((word>>(byte_bit+bit))&1)
-			  cnt++;
-		  else
-			  return cnt;
-
-#else /* BIT ENDIAN BITOPS */
-  while(cnt<32) {
-	  if(!((word>>cnt)&1))
-		  return cnt;
-	  else
-		  cnt++;
-  }
-  return cnt;
-#endif
+	unsigned long result = 0;
 
+	while(word & 1) {
+		result++;
+		word >>= 1;
+	}
+	return result;
 }
 
 /* find_next_zero_bit() finds the first zero bit in a bit string of length
@@ -280,15 +87,9 @@
  * on Linus's ALPHA routines, which are pretty portable BTW.
  */
 
-extern __inline__ unsigned long
-find_next_zero_bit(void *addr, unsigned long size, unsigned long offset)
+extern __inline__ unsigned long find_next_zero_bit(void *addr, unsigned long size, unsigned long offset)
 {
-#ifdef __LITTLE_ENDIAN_BITOPS
-
-	/* FOO, needs to be written */
-
-#else   /* BIG ENDIAN BITOPS */
-	unsigned long *p = ((unsigned long *) addr) + (offset >> 6);
+	unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
 	unsigned long result = offset & ~31UL;
 	unsigned long tmp;
 
@@ -296,10 +97,9 @@
 		return size;
 	size -= result;
 	offset &= 31UL;
-	if (offset) 
-	{
+	if (offset) {
 		tmp = *(p++);
-		tmp |= ~0UL >> (32-offset);
+		tmp |= ~0UL << (32-offset);
 		if (size < 32)
 			goto found_first;
 		if (~tmp)
@@ -307,8 +107,7 @@
 		size -= 32;
 		result += 32;
 	}
-	while (size & ~32UL) 
-	{
+	while (size & ~31UL) {
 		if (~(tmp = *(p++)))
 			goto found_middle;
 		result += 32;
@@ -319,10 +118,9 @@
 	tmp = *p;
 
 found_first:
-	tmp |= ~0UL << size;
+	tmp |= ~0UL >> size;
 found_middle:
 	return result + ffz(tmp);
-#endif
 }
 
 /* Linus sez that gcc can optimize the following correctly, we'll see if this
@@ -332,6 +130,85 @@
 #define find_first_zero_bit(addr, size) \
         find_next_zero_bit((addr), (size), 0)
 
+/* Now for the ext2 filesystem bit operations and helper routines. */
+
+extern __inline__ int ext2_set_bit(int nr,void * addr)
+{
+	int		mask, retval, flags;
+	unsigned char	*ADDR = (unsigned char *) addr;
+
+	ADDR += nr >> 3;
+	mask = 1 << (nr & 0x07);
+	save_flags(flags); cli();
+	retval = (mask & *ADDR) != 0;
+	*ADDR |= mask;
+	restore_flags(flags);
+	return retval;
+}
+
+extern __inline__ int ext2_clear_bit(int nr, void * addr)
+{
+	int		mask, retval, flags;
+	unsigned char	*ADDR = (unsigned char *) addr;
+
+	ADDR += nr >> 3;
+	mask = 1 << (nr & 0x07);
+	save_flags(flags); cli();
+	retval = (mask & *ADDR) != 0;
+	*ADDR &= ~mask;
+	restore_flags(flags);
+	return retval;
+}
+
+extern __inline__ int ext2_test_bit(int nr, const void * addr)
+{
+	int			mask;
+	const unsigned char	*ADDR = (const unsigned char *) addr;
+
+	ADDR += nr >> 3;
+	mask = 1 << (nr & 0x07);
+	return ((mask & *ADDR) != 0);
+}
+
+#define ext2_find_first_zero_bit(addr, size) \
+        ext2_find_next_zero_bit((addr), (size), 0)
+
+extern __inline__ unsigned long ext2_find_next_zero_bit(void *addr, unsigned long size, unsigned long offset)
+{
+	unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
+	unsigned long result = offset & ~31UL;
+	unsigned long tmp;
+
+	if (offset >= size)
+		return size;
+	size -= result;
+	offset &= 31UL;
+	if(offset) {
+		tmp = *(p++);
+		tmp |= ~0UL << (32-offset);
+		if(size < 32)
+			goto found_first;
+		if(~tmp)
+			goto found_middle;
+		size -= 32;
+		result += 32;
+	}
+	while(size & ~31UL) {
+		if(~(tmp = *(p++)))
+			goto found_middle;
+		result += 32;
+		size -= 32;
+	}
+	if(!size)
+		return result;
+	tmp = *p;
+
+found_first:
+	tmp |= ~0UL << size;
+found_middle:
+	tmp = ((tmp>>24) | ((tmp>>8)&0xff00) | ((tmp<<8)&0xff0000) | (tmp<<24));
+	return result + ffz(tmp);
+}
 
 #endif /* defined(_SPARC_BITOPS_H) */
 
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/bsderrno.h linux/include/asm-sparc/bsderrno.h
--- v1.3.43/linux/include/asm-sparc/bsderrno.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-sparc/bsderrno.h	Sat Nov 25 04:31:17 1995
@@ -0,0 +1,94 @@
+/* $Id: bsderrno.h,v 1.2 1995/11/25 02:31:17 davem Exp $
+ * bsderrno.h: Error numbers for NetBSD binary compatability
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef _SPARC_BSDERRNO_H
+#define _SPARC_BSDERRNO_H
+
+#define BSD_EPERM         1      /* Operation not permitted */
+#define BSD_ENOENT        2      /* No such file or directory */
+#define BSD_ESRCH         3      /* No such process */
+#define BSD_EINTR         4      /* Interrupted system call */
+#define BSD_EIO           5      /* Input/output error */
+#define BSD_ENXIO         6      /* Device not configured */
+#define BSD_E2BIG         7      /* Argument list too long */
+#define BSD_ENOEXEC       8      /* Exec format error */
+#define BSD_EBADF         9      /* Bad file descriptor */
+#define BSD_ECHILD        10     /* No child processes */
+#define BSD_EDEADLK       11     /* Resource deadlock avoided */
+#define BSD_ENOMEM        12     /* Cannot allocate memory */
+#define BSD_EACCES        13     /* Permission denied */
+#define BSD_EFAULT        14     /* Bad address */
+#define BSD_ENOTBLK       15     /* Block device required */
+#define BSD_EBUSY         16     /* Device busy */
+#define BSD_EEXIST        17     /* File exists */
+#define BSD_EXDEV         18     /* Cross-device link */
+#define BSD_ENODEV        19     /* Operation not supported by device */
+#define BSD_ENOTDIR       20     /* Not a directory */
+#define BSD_EISDIR        21     /* Is a directory */
+#define BSD_EINVAL        22     /* Invalid argument */
+#define BSD_ENFILE        23     /* Too many open files in system */
+#define BSD_EMFILE        24     /* Too many open files */
+#define BSD_ENOTTY        25     /* Inappropriate ioctl for device */
+#define BSD_ETXTBSY       26     /* Text file busy */
+#define BSD_EFBIG         27     /* File too large */
+#define BSD_ENOSPC        28     /* No space left on device */
+#define BSD_ESPIPE        29     /* Illegal seek */
+#define BSD_EROFS         30     /* Read-only file system */
+#define BSD_EMLINK        31     /* Too many links */
+#define BSD_EPIPE         32     /* Broken pipe */
+#define BSD_EDOM          33     /* Numerical argument out of domain */
+#define BSD_ERANGE        34     /* Result too large */
+#define BSD_EAGAIN        35     /* Resource temporarily unavailable */
+#define BSD_EWOULDBLOCK   EAGAIN /* Operation would block */
+#define BSD_EINPROGRESS   36     /* Operation now in progress */
+#define BSD_EALREADY      37     /* Operation already in progress */
+#define BSD_ENOTSOCK      38     /* Socket operation on non-socket */
+#define BSD_EDESTADDRREQ  39     /* Destination address required */
+#define BSD_EMSGSIZE      40     /* Message too long */
+#define BSD_EPROTOTYPE    41     /* Protocol wrong type for socket */
+#define BSD_ENOPROTOOPT   42     /* Protocol not available */
+#define BSD_EPROTONOSUPPORT  43  /* Protocol not supported */
+#define BSD_ESOCKTNOSUPPORT  44  /* Socket type not supported */
+#define BSD_EOPNOTSUPP    45     /* Operation not supported */
+#define BSD_EPFNOSUPPORT  46     /* Protocol family not supported */
+#define BSD_EAFNOSUPPORT  47     /* Address family not supported by protocol family */
+#define BSD_EADDRINUSE    48     /* Address already in use */
+#define BSD_EADDRNOTAVAIL 49     /* Can't assign requested address */
+#define BSD_ENETDOWN      50     /* Network is down */
+#define BSD_ENETUNREACH   51     /* Network is unreachable */
+#define BSD_ENETRESET     52     /* Network dropped connection on reset */
+#define BSD_ECONNABORTED  53     /* Software caused connection abort */
+#define BSD_ECONNRESET    54     /* Connection reset by peer */
+#define BSD_ENOBUFS       55     /* No buffer space available */
+#define BSD_EISCONN       56     /* Socket is already connected */
+#define BSD_ENOTCONN      57     /* Socket is not connected */
+#define BSD_ESHUTDOWN     58     /* Can't send after socket shutdown */
+#define BSD_ETOOMANYREFS  59     /* Too many references: can't splice */
+#define BSD_ETIMEDOUT     60     /* Operation timed out */
+#define BSD_ECONNREFUSED  61     /* Connection refused */
+#define BSD_ELOOP         62     /* Too many levels of symbolic links */
+#define BSD_ENAMETOOLONG  63     /* File name too long */
+#define BSD_EHOSTDOWN     64     /* Host is down */
+#define BSD_EHOSTUNREACH  65     /* No route to host */
+#define BSD_ENOTEMPTY     66     /* Directory not empty */
+#define BSD_EPROCLIM      67     /* Too many processes */
+#define BSD_EUSERS        68     /* Too many users */
+#define BSD_EDQUOT        69     /* Disc quota exceeded */
+#define BSD_ESTALE        70     /* Stale NFS file handle */
+#define BSD_EREMOTE       71     /* Too many levels of remote in path */
+#define BSD_EBADRPC       72     /* RPC struct is bad */
+#define BSD_ERPCMISMATCH  73     /* RPC version wrong */
+#define BSD_EPROGUNAVAIL  74     /* RPC prog. not avail */
+#define BSD_EPROGMISMATCH 75     /* Program version wrong */
+#define BSD_EPROCUNAVAIL  76     /* Bad procedure for program */
+#define BSD_ENOLCK        77     /* No locks available */
+#define BSD_ENOSYS        78     /* Function not implemented */
+#define BSD_EFTYPE        79     /* Inappropriate file type or format */
+#define BSD_EAUTH         80     /* Authentication error */
+#define BSD_ENEEDAUTH     81     /* Need authenticator */
+#define BSD_ELAST         81     /* Must be equal largest errno */
+
+#endif /* !(_SPARC_BSDERRNO_H) */
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/bugs.h linux/include/asm-sparc/bugs.h
--- v1.3.43/linux/include/asm-sparc/bugs.h	Tue Jun 27 14:11:45 1995
+++ linux/include/asm-sparc/bugs.h	Sat Nov 25 04:31:19 1995
@@ -1,49 +1,7 @@
-/*  include/asm-sparc/bugs.h:  Sparc probes for various bugs.
+/*  $Id: bugs.h,v 1.5 1995/11/25 02:31:18 davem Exp $
+ *  include/asm-sparc/bugs.h:  Sparc probes for various bugs.
  *
  *  Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
  */
 
-/*
- * This is included by init/main.c to check for architecture-dependent bugs.
- *
- * Needs:
- *	void check_bugs(void);
- */
-
-#define CONFIG_BUGSPARC
-
-#include <asm/openprom.h>
-#include <asm/page.h>
-
-extern pgd_t swapper_pg_dir[16384];
-
-static void check_mmu(void)
-{
-  register struct linux_romvec *lvec;
-  register int root_node;
-  unsigned int present;
-
-  lvec = romvec;
-
-  root_node = (*(romvec->pv_nodeops->no_nextnode))(0);
-
-  present = 0;
-  (*(romvec->pv_nodeops->no_getprop))(root_node, "buserr-type", 
-				      (char *) &present);
-  if(present == 1)
-    {
-      printk("MMU bug found: uncaching trap table\n");
-      for(present = (unsigned long) &trapbase; present < (unsigned long)
-	  &swapper_pg_dir; present+=PAGE_SIZE)
-	      put_pte(present, (get_pte(present) | PTE_NC));
-    }
-
-  return;
-}
-
-
-static void 
-check_bugs(void)
-{
-  check_mmu();
-}
+static void check_bugs(void) { }
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/byteorder.h linux/include/asm-sparc/byteorder.h
--- v1.3.43/linux/include/asm-sparc/byteorder.h	Tue Aug 15 20:39:04 1995
+++ linux/include/asm-sparc/byteorder.h	Sat Nov 25 04:31:21 1995
@@ -1,85 +1,15 @@
+/* $Id: byteorder.h,v 1.6 1995/11/25 02:31:20 davem Exp $ */
 #ifndef _SPARC_BYTEORDER_H
 #define _SPARC_BYTEORDER_H
 
-#undef ntohl
-#undef ntohs
-#undef htonl
-#undef htons
+#define ntohl(x) x
+#define ntohs(x) x
+#define htonl(x) x
+#define htons(x) x
 
+#ifdef __KERNEL__
 #define __BIG_ENDIAN
-#define __BIG_ENDIAN_BITFIELD
-
-extern unsigned long int	ntohl(unsigned long int);
-extern unsigned short int	ntohs(unsigned short int);
-extern unsigned long int	htonl(unsigned long int);
-extern unsigned short int	htons(unsigned short int);
-
-extern unsigned long int	__ntohl(unsigned long int);
-extern unsigned short int	__ntohs(unsigned short int);
-extern unsigned long int	__constant_ntohl(unsigned long int);
-extern unsigned short int	__constant_ntohs(unsigned short int);
-
-/*
- * The constant and non-constant versions here are the same.
- * Maybe I'll come up with an alpha-optimized routine for the
- * non-constant ones (the constant ones don't need it: gcc
- * will optimize it to the correct constant)
- */
-
-extern __inline__ unsigned long int
-__ntohl(unsigned long int x)
-{
-	return (((x & 0x000000ffU) << 24) |
-		((x & 0x0000ff00U) <<  8) |
-		((x & 0x00ff0000U) >>  8) |
-		((x & 0xff000000U) >> 24));
-}
-
-extern __inline__ unsigned long int
-__constant_ntohl(unsigned long int x)
-{
-	return (((x & 0x000000ffU) << 24) |
-		((x & 0x0000ff00U) <<  8) |
-		((x & 0x00ff0000U) >>  8) |
-		((x & 0xff000000U) >> 24));
-}
-
-extern __inline__ unsigned short int
-__ntohs(unsigned short int x)
-{
-	return (((x & 0x00ff) << 8) |
-		((x & 0xff00) >> 8));
-}
-
-extern __inline__ unsigned short int
-__constant_ntohs(unsigned short int x)
-{
-	return (((x & 0x00ff) << 8) |
-		((x & 0xff00) >> 8));
-}
-
-#define __htonl(x) __ntohl(x)
-#define __htons(x) __ntohs(x)
-#define __constant_htonl(x) __constant_ntohl(x)
-#define __constant_htons(x) __constant_ntohs(x)
-
-#ifdef  __OPTIMIZE__
-#  define ntohl(x) \
-(__builtin_constant_p((long)(x)) ? \
- __constant_ntohl((x)) : \
- __ntohl((x)))
-#  define ntohs(x) \
-(__builtin_constant_p((short)(x)) ? \
- __constant_ntohs((x)) : \
- __ntohs((x)))
-#  define htonl(x) \
-(__builtin_constant_p((long)(x)) ? \
- __constant_htonl((x)) : \
- __htonl((x)))
-#  define htons(x) \
-(__builtin_constant_p((short)(x)) ? \
- __constant_htons((x)) : \
- __htons((x)))
 #endif
+#define __BIG_ENDIAN_BITFIELD
 
 #endif /* !(_SPARC_BYTEORDER_H) */
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/cache.h linux/include/asm-sparc/cache.h
--- v1.3.43/linux/include/asm-sparc/cache.h	Tue Jun 27 14:11:45 1995
+++ linux/include/asm-sparc/cache.h	Sat Nov 25 04:31:23 1995
@@ -1,4 +1,5 @@
-/* cache.h:  Cache specific code for the Sparc.  These include flushing
+/* $Id: cache.h,v 1.3 1995/11/25 02:31:22 davem Exp $
+ * cache.h:  Cache specific code for the Sparc.  These include flushing
  *           and direct tag/data line access.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -38,7 +39,6 @@
 	__asm__ __volatile__("sta %0, [%1] %2\n\t" : :
 			     "r" (entry), "r" (vaddr), "i" (ASI_M_TXTC_TAG) :
 			     "memory");
-	return;
 }
 
 /* Second cache-data access.  The data is returned two-32bit quantities
@@ -49,7 +49,8 @@
 {
 	unsigned int value1, value2, vaddr;
 
-	vaddr = ((setnum&0x1) << 12) | ((tagnum&0x7f) << 5) | ((subblock&0x3) << 3);
+	vaddr = ((setnum&0x1) << 12) | ((tagnum&0x7f) << 5) |
+		((subblock&0x3) << 3);
 	__asm__ __volatile__("ldda [%2] %3, %%g2\n\t"
 			     "or %%g0, %%g2, %0\n\t"
 			     "or %%g0, %%g3, %1\n\t" :
@@ -57,7 +58,6 @@
 			     "r" (vaddr), "i" (ASI_M_TXTC_DATA) :
 			     "g2", "g3");
 	data[0] = value1; data[1] = value2;
-	return;
 }
 
 extern inline void put_icache_data(int setnum, int tagnum, int subblock,
@@ -65,7 +65,8 @@
 {
 	unsigned int value1, value2, vaddr;
 
-	vaddr = ((setnum&0x1) << 12) | ((tagnum&0x7f) << 5) | ((subblock&0x3) << 3);
+	vaddr = ((setnum&0x1) << 12) | ((tagnum&0x7f) << 5) |
+		((subblock&0x3) << 3);
 	value1 = data[0]; value2 = data[1];
 	__asm__ __volatile__("or %%g0, %0, %%g2\n\t"
 			     "or %%g0, %1, %%g3\n\t"
@@ -73,7 +74,6 @@
 			     "r" (value1), "r" (value2), 
 			     "r" (vaddr), "i" (ASI_M_TXTC_DATA) :
 			     "g2", "g3", "memory" /* no joke */);
-	return;
 }
 
 /* Different types of flushes with the ICACHE.  Some of the flushes
@@ -90,7 +90,6 @@
 	__asm__ __volatile__("sta %%g0, [%0] %1\n\t" : :
 			     "r" (addr), "i" (ASI_M_FLUSH_PAGE) :
 			     "memory");
-	return;
 }
 
 extern inline void flush_ei_seg(unsigned int addr)
@@ -98,7 +97,6 @@
 	__asm__ __volatile__("sta %%g0, [%0] %1\n\t" : :
 			     "r" (addr), "i" (ASI_M_FLUSH_SEG) :
 			     "memory");
-	return;
 }
 
 extern inline void flush_ei_region(unsigned int addr)
@@ -106,7 +104,6 @@
 	__asm__ __volatile__("sta %%g0, [%0] %1\n\t" : :
 			     "r" (addr), "i" (ASI_M_FLUSH_REGION) :
 			     "memory");
-	return;
 }
 
 extern inline void flush_ei_ctx(unsigned int addr)
@@ -114,7 +111,6 @@
 	__asm__ __volatile__("sta %%g0, [%0] %1\n\t" : :
 			     "r" (addr), "i" (ASI_M_FLUSH_CTX) :
 			     "memory");
-	return;
 }
 
 extern inline void flush_ei_user(unsigned int addr)
@@ -122,7 +118,6 @@
 	__asm__ __volatile__("sta %%g0, [%0] %1\n\t" : :
 			     "r" (addr), "i" (ASI_M_FLUSH_USER) :
 			     "memory");
-	return;
 }
 
 #endif /* !(_SPARC_CACHE_H) */
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/checksum.h linux/include/asm-sparc/checksum.h
--- v1.3.43/linux/include/asm-sparc/checksum.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-sparc/checksum.h	Sat Nov 25 04:31:24 1995
@@ -0,0 +1,162 @@
+/* $Id: checksum.h,v 1.10 1995/11/25 02:31:23 davem Exp $ */
+#ifndef __SPARC_CHECKSUM_H
+#define __SPARC_CHECKSUM_H
+
+/*  checksum.h:  IP/UDP/TCP checksum routines on the Sparc.
+ *
+ *  Copyright(C) 1995 Linus Torvalds
+ *  Copyright(C) 1995 Miguel de Icaza
+ */
+
+
+/* 32 bits version of the checksum routines written for the Alpha by Linus */
+extern inline unsigned short from32to16(unsigned long x)
+{
+	/* add up 16-bit and 17-bit words for 17+c bits */
+	x = (x & 0xffff) + (x >> 16);
+	/* add up 16-bit and 2-bit for 16+c bit */
+	x = (x & 0xffff) + (x >> 16);
+	/* add up carry.. */
+	x = (x & 0xffff) + (x >> 16);
+	return x;
+}
+
+extern inline unsigned long
+do_csum(unsigned char * buff, int len)
+{
+	int odd, count;
+	unsigned long result = 0;
+
+	if (len <= 0)
+		goto out;
+	odd = 1 & (unsigned long) buff;
+	if (odd) {
+		result = *buff << 8;
+		len--;
+		buff++;
+	}
+	count = len >> 1;		/* nr of 16-bit words.. */
+	if (count) {
+		if (2 & (unsigned long) buff) {
+			result += *(unsigned short *) buff;
+			count--;
+			len -= 2;
+			buff += 2;
+		}
+		count >>= 1;		/* nr of 32-bit words.. */
+		if (count) {
+		        unsigned long carry = 0;
+			do {
+				unsigned long w = *(unsigned long *) buff;
+				count--;
+				buff += 4;
+				len -= 4;
+				result += carry;
+				result += w;
+				carry = (w > result);
+			} while (count);
+			result += carry;
+			result = (result & 0xffff) + (result >> 16);
+		}
+		if (len & 2) {
+			result += *(unsigned short *) buff;
+			buff += 2;
+		}
+	}
+	if (len & 1)
+		result += (*buff) << 8;
+	result = from32to16(result);
+	if (odd)
+		result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
+out:
+	return result;
+}
+
+extern inline unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl)
+{
+	return ~do_csum(iph,ihl*4);
+}
+
+/*
+ * computes the checksum of a memory block at buff, length len,
+ * and adds in "sum" (32-bit)
+ *
+ * returns a 32-bit number suitable for feeding into itself
+ * or csum_tcpudp_magic
+ *
+ * this function must be called with even lengths, except
+ * for the last fragment, which may be odd
+ *
+ * it's best to have buff aligned on a 32-bit boundary
+ */
+extern inline unsigned int csum_partial(unsigned char * buff, int len, unsigned int sum)
+{
+	unsigned long result = do_csum(buff, len);
+
+	/* add in old sum, and carry.. */
+	result += sum;
+	/* 32+c bits -> 32 bits */
+	result = (result & 0xffff) + (result >> 16);
+	return result;
+}
+
+/*
+ * the same as csum_partial, but copies from fs:src while it
+ * checksums
+ *
+ * here even more important to align src and dst on a 32-bit (or even
+ * better 64-bit) boundary
+ */
+extern inline unsigned int csum_partial_copy(char *src, char *dst, int len, int sum)
+{
+	/*
+	 * The whole idea is to do the copy and the checksum at
+	 * the same time, but we do it the easy way now.
+	 *
+	 * At least csum on the source, not destination, for cache
+	 * reasons..
+	 */
+	sum = csum_partial(src, len, sum);
+	memcpy(dst, src, len);
+	return sum;
+}
+
+/*
+ * this routine is used for miscellaneous IP-like checksums, mainly
+ * in icmp.c
+ */
+extern inline unsigned short ip_compute_csum(unsigned char * buff, int len)
+{
+	return ~from32to16(do_csum(buff,len));
+}
+
+#define csum_partial_copy_fromuser(s, d, l, w)  \
+                       csum_partial_copy((char *) (s), (d), (l), (w))
+
+/*
+ *	Fold a partial checksum without adding pseudo headers
+ */
+
+static inline unsigned short csum_fold(unsigned int sum)
+{
+	sum = (sum & 0xffff) + (sum >> 16);
+	sum = (sum & 0xffff) + (sum >> 16);
+	return ~sum;
+}
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented
+ */
+extern inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
+					   unsigned long daddr,
+					   unsigned short len,
+					   unsigned short proto,
+					   unsigned int sum)
+{
+	return ~from32to16 (((saddr >> 16) + (saddr & 0xffff) + (daddr >> 16)
+			     + (daddr & 0xffff) + (sum >> 16) +
+			     (sum & 0xffff) + proto + len));
+}
+
+#endif /* !(__SPARC_CHECKSUM_H) */
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/clock.h linux/include/asm-sparc/clock.h
--- v1.3.43/linux/include/asm-sparc/clock.h	Tue Jun 27 14:11:45 1995
+++ linux/include/asm-sparc/clock.h	Sat Nov 25 04:31:26 1995
@@ -1,4 +1,5 @@
-/* clock.h:  Definitions for clock operations on the Sparc.
+/* $Id: clock.h,v 1.3 1995/11/25 02:31:25 davem Exp $
+ * clock.h:  Definitions for clock operations on the Sparc.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  */
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/contregs.h linux/include/asm-sparc/contregs.h
--- v1.3.43/linux/include/asm-sparc/contregs.h	Tue Jun 27 14:11:45 1995
+++ linux/include/asm-sparc/contregs.h	Sat Nov 25 04:31:28 1995
@@ -1,3 +1,4 @@
+/* $Id: contregs.h,v 1.6 1995/11/25 02:31:27 davem Exp $ */
 #ifndef _SPARC_CONTREGS_H
 #define _SPARC_CONTREGS_H
 
@@ -7,43 +8,43 @@
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  */
 
-/* 4 = sun4 (as in sun4 sysmaint student book), c = sun4c (according to davem) */
+/* 4=sun4 (as in sun4 sysmaint student book), c=sun4c (according to davem) */
 
-#define AC_IDPROM     0x00000000    /* 4  ID PROM, R/O, byte, 32 bytes                        */
-#define AC_CONTEXT    0x30000000    /* 4c current mmu-context, handy for invalidate()'s ;-)   */
-#define AC_SENABLE    0x40000000    /* 4c system dvma/cache enable, plus special reset poking */
-#define AC_UDVMA_ENB  0x50000000    /* 4  Not used on Sun boards, byte                        */
-#define AC_BUS_ERROR  0x60000000    /* 4  Cleared on read, byte. Probably same as sun4c.      */
-#define AC_SYNC_ERR   0x60000000    /*  c what type of synchronous memory error happened      */
-#define AC_SYNC_VA    0x60000004    /*  c what virtual address caused the error to occur      */
-#define AC_ASYNC_ERR  0x60000008    /*  c what type of asynchronous mem-error happened        */
-#define AC_ASYNC_VA   0x6000000c    /*  c what virtual address caused the async-err to happen */
-#define AC_LEDS       0x70000000    /* 4  Zero turns on LEDs, byte                            */
-#define AC_CACHETAGS  0x80000000    /* 4c direct access to the VAC cache, unused...           */
-#define AC_CACHEDDATA 0x90000000    /*  c where the actual VAC cached data sits               */
-#define AC_UDVMA_MAP  0xD0000000    /* 4  Not used on Sun boards, byte                        */
-#define AC_VME_VECTOR 0xE0000000    /* 4  For non-Autovector VME, byte                        */
-#define AC_BOOT_SCC   0xF0000000    /* 4  To bypass MMU and access Zilog 8530 on boot. byte.  */
+#define AC_IDPROM     0x00000000    /* 4  ID PROM, R/O, byte, 32 bytes       */
+#define AC_CONTEXT    0x30000000    /* 4c current mmu-context                */
+#define AC_SENABLE    0x40000000    /* 4c system dvma/cache/reset enable reg */
+#define AC_UDVMA_ENB  0x50000000    /* 4  Not used on Sun boards, byte       */
+#define AC_BUS_ERROR  0x60000000    /* 4  Cleared on read, byte.             */
+#define AC_SYNC_ERR   0x60000000    /*  c fault type                         */
+#define AC_SYNC_VA    0x60000004    /*  c fault virtual address              */
+#define AC_ASYNC_ERR  0x60000008    /*  c asynchronous fault type            */
+#define AC_ASYNC_VA   0x6000000c    /*  c async fault virtual address        */
+#define AC_LEDS       0x70000000    /* 4  Zero turns on LEDs, byte           */
+#define AC_CACHETAGS  0x80000000    /* 4c direct access to the VAC tags      */
+#define AC_CACHEDDATA 0x90000000    /*  c direct access to the VAC data      */
+#define AC_UDVMA_MAP  0xD0000000    /* 4  Not used on Sun boards, byte       */
+#define AC_VME_VECTOR 0xE0000000    /* 4  For non-Autovector VME, byte       */
+#define AC_BOOT_SCC   0xF0000000    /* 4  bypass to access Zilog 8530. byte. */
 
-/* SPARCstation-5. I changed Paul's names to the hardware guy's ones. --P3 */
-#define AC_M_PCR      0x0000        /* 5  Processor Control Register */
-#define AC_M_CTPR     0x0100        /* 5  Context Table Pointer Register  */
-#define AC_M_CXR      0x0200        /* 5  Context Register */
-#define AC_M_SFSR     0x0300        /* 5  Synchronous Fault Status Register */
-#define AC_M_SFAR     0x0400        /* 5  Synchronous Fault Address Register */
-#define AC_M_AFSR     0x0500        /* 5  Asynchronous Fault Status Register */
-#define AC_M_AFAR     0x0600        /* 5  Asynchronous Fault Address Register */
-#define AC_M_RESET    0x0700        /* 5  Reset Register  Aieee! */
-#define AC_M_RPR      0x1000        /* 5  Root Pointer Register */
-#define AC_M_TSUTRCR  0x1000        /* 5  TLB Replacement Control Reg on Tsunami */
-#define AC_M_IAPTP    0x1100        /* 5  Instruction Access PTP */
-#define AC_M_DAPTP    0x1200        /* 5  Data Access PTP */
-#define AC_M_ITR      0x1300        /* 5  Index Tag Register */
-#define AC_M_TRCR     0x1400        /* 5  TLB Replacement Control Register */
-
-/* The following are Ross HyperSparc only. */
-#define AC_M_RPR1     0x1500        /* 5  Root Pointer Register (entry 2) */
-#define AC_M_IAPTP1   0x1600        /* 5  Instruction Access PTP (entry 2) */
-#define AC_M_DAPTP1   0x1700        /* 5  Data Access PTP (entry 2) */
+/* s=Swift, h=Ross_HyperSPARC, v=TI_Viking, t=Tsunami, r=Ross_Cypress        */
+#define AC_M_PCR      0x0000        /* shv Processor Control Reg             */
+#define AC_M_CTPR     0x0100        /* shv Context Table Pointer Reg         */
+#define AC_M_CXR      0x0200        /* shv Context Register                  */
+#define AC_M_SFSR     0x0300        /* shv Synchronous Fault Status Reg      */
+#define AC_M_SFAR     0x0400        /* shv Synchronous Fault Address Reg     */
+#define AC_M_AFSR     0x0500        /*  hv Asynchronous Fault Status Reg     */
+#define AC_M_AFAR     0x0600        /*  hv Asynchronous Fault Address Reg    */
+#define AC_M_RESET    0x0700        /*  hv Reset Reg                         */
+#define AC_M_RPR      0x1000        /*  hv Root Pointer Reg                  */
+#define AC_M_TSUTRCR  0x1000        /* s   TLB Replacement Ctrl Reg          */
+#define AC_M_IAPTP    0x1100        /*  hv Instruction Access PTP            */
+#define AC_M_DAPTP    0x1200        /*  hv Data Access PTP                   */
+#define AC_M_ITR      0x1300        /*  hv Index Tag Register                */
+#define AC_M_TRCR     0x1400        /*  hv TLB Replacement Control Reg       */
+#define AC_M_SFSRX    0x1300        /* s   Synch Fault Status Reg prim       */
+#define AC_M_SFARX    0x1400        /* s   Synch Fault Address Reg prim      */
+#define AC_M_RPR1     0x1500        /*  h  Root Pointer Reg (entry 2)        */
+#define AC_M_IAPTP1   0x1600        /*  h  Instruction Access PTP (entry 2)  */
+#define AC_M_DAPTP1   0x1700        /*  h  Data Access PTP (entry 2)         */
 
 #endif /* _SPARC_CONTREGS_H */
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/cprefix.h linux/include/asm-sparc/cprefix.h
--- v1.3.43/linux/include/asm-sparc/cprefix.h	Mon Feb  6 20:42:52 1995
+++ linux/include/asm-sparc/cprefix.h	Tue Nov 21 12:31:53 1995
@@ -6,7 +6,8 @@
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  */
-
+#ifndef __SPARC_CPREFIX_H
+#define __SPARC_CPREFIX_H
 
 #ifndef __svr4__
 #define C_LABEL_PREFIX _
@@ -14,7 +15,9 @@
 #define C_LABEL_PREFIX
 #endif
 
-#define CONCAT1(a, b) CONCAT2(a, b)
+#define CONCAT(a, b) CONCAT2(a, b)
 #define CONCAT2(a, b) a##b
 
-#define C_LABEL(name) CONCAT1(C_LABEL_PREFIX, name)
+#define C_LABEL(name) CONCAT(C_LABEL_PREFIX, name)
+
+#endif /* !(__SPARC_CPREFIX_H) */
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/cypress.h linux/include/asm-sparc/cypress.h
--- v1.3.43/linux/include/asm-sparc/cypress.h	Tue Jun 27 14:11:45 1995
+++ linux/include/asm-sparc/cypress.h	Sat Nov 25 04:31:30 1995
@@ -1,4 +1,5 @@
-/* cypress.h: Cypress module specific definitions and defines.
+/* $Id: cypress.h,v 1.2 1995/11/25 02:31:29 davem Exp $
+ * cypress.h: Cypress module specific definitions and defines.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  */
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/delay.h linux/include/asm-sparc/delay.h
--- v1.3.43/linux/include/asm-sparc/delay.h	Tue Jun 27 14:11:45 1995
+++ linux/include/asm-sparc/delay.h	Sat Nov 25 04:31:33 1995
@@ -1,38 +1,41 @@
-#ifndef __SPARC_DELAY_H
-#define __SPARC_DELAY_H
-
-extern unsigned long loops_per_sec;
-
-/*
- * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu).
+/* $Id: delay.h,v 1.7 1995/11/25 02:31:32 davem Exp $
+ * delay.h: Linux delay routines on the Sparc.
  *
- * Delay quick inlined code using 'loops_per_second' which is
- * calculated in calibrate_delay() in main.c (ie. BogoMIPS :-)
+ * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu).
  */
 
-extern __inline__ void __delay(unsigned int loops)
+#ifndef __SPARC_DELAY_H
+#define __SPARC_DELAY_H
+
+extern __inline__ void __delay(unsigned long loops)
 {
-  __asm__ __volatile__("\n1:\tcmp %0, 0\n\t"
-		       "bne,a 1b\n\t"
-		       "sub %0, 1, %0\n": "=&r" (loops) : "0" (loops));
+	__asm__ __volatile__("cmp %0, 0\n\t"
+			     "1: bne 1b\n\t"
+			     "subcc %0, 1, %0\n" :
+			     "=&r" (loops) :
+			     "0" (loops));
 }
 
-/* udelay(usecs) is used for very short delays up to 1 millisecond. */
+/* udelay(usecs) is used for very short delays up to 1 millisecond. On
+ * the Sparc (both sun4c and sun4m) we have a free running usec counter
+ * available to us already.
+ */
+extern volatile unsigned int *master_l10_counter;
 
 extern __inline__ void udelay(unsigned int usecs)
 {
-  usecs *= 0x000010c6;         /* Sparc is 32-bit just like ix86 */
-
-  __delay(loops_per_sec*usecs);
+	unsigned int ccnt;
 
+	if(!master_l10_counter)
+		return;
+	ccnt=*master_l10_counter;
+	for(usecs+=1; usecs; usecs--, ccnt=*master_l10_counter)
+		while(*master_l10_counter == ccnt)
+			__asm__("": : :"memory");
 }
 
 /* calibrate_delay() wants this... */
-
-extern __inline__ unsigned long muldiv(unsigned long a, unsigned long b, unsigned long c)
-{
-	return ((a*b)/c);
-}
+#define muldiv(a, b, c)    (((a)*(b))/(c))
 
 #endif /* defined(__SPARC_DELAY_H) */
 
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/dma.h linux/include/asm-sparc/dma.h
--- v1.3.43/linux/include/asm-sparc/dma.h	Tue Jun 27 14:11:45 1995
+++ linux/include/asm-sparc/dma.h	Sat Nov 25 04:31:36 1995
@@ -1,29 +1,30 @@
-/*
+/* $Id: dma.h,v 1.12 1995/11/25 02:31:34 davem Exp $
  * include/asm-sparc/dma.h
  *
- * Don't even ask, I am figuring out how this crap works
- * on the Sparc. It may end up being real hairy to plug
- * into this code, maybe not, we'll see.
- *
  * Copyright 1995 (C) David S. Miller (davem@caip.rutgers.edu)
  */
 
 #ifndef _ASM_SPARC_DMA_H
 #define _ASM_SPARC_DMA_H
 
+#include <linux/kernel.h>
+
 #include <asm/vac-ops.h>  /* for invalidate's, etc. */
 #include <asm/sbus.h>
 #include <asm/delay.h>
 #include <asm/oplib.h>
 
-/* DMA probing routine */
-extern unsigned long probe_dma(unsigned long);
-
 /* These are irrelevant for Sparc DMA, but we leave it in so that
  * things can compile.
  */
 #define MAX_DMA_CHANNELS 8
-#define MAX_DMA_ADDRESS  0x0
+#define MAX_DMA_ADDRESS  (~0UL)
+#define DMA_MODE_READ    1
+#define DMA_MODE_WRITE   2
+
+/* Useful constants */
+#define SIZE_16MB      (16*1024*1024)
+#define SIZE_64K       (64*1024)
 
 /* Structure to describe the current status of DMA registers on the Sparc */
 struct sparc_dma_registers {
@@ -33,120 +34,162 @@
   volatile unsigned long dma_test;   /* DMA test register */
 };
 
+/* DVMA chip revisions */
+enum dvma_rev {
+	dvmarev0,
+	dvmaesc1,
+	dvmarev1,
+	dvmarev2,
+	dvmarev3,
+	dvmarevplus
+};
+
+#define DMA_HASCOUNT(rev)  ((rev)==dvmaesc1)
+
 /* Linux DMA information structure, filled during probe. */
 struct Linux_SBus_DMA {
-  struct linux_sbus_device *SBus_dev;   /* pointer to sbus device struct */
-  struct sparc_dma_registers *DMA_regs; /* Pointer to DMA regs in IO space */
+	struct Linux_SBus_DMA *next;
+	struct linux_sbus_device *SBus_dev;
+	struct sparc_dma_registers *regs;
+
+	/* Status, misc info */
+	int node;                /* Prom node for this DMA device */
+	int running;             /* Are we doing DMA now? */
+	int allocated;           /* Are we "owned" by anyone yet? */
+
+	/* Transfer information. */
+	unsigned long addr;      /* Start address of current transfer */
+	int nbytes;              /* Size of current transfer */
+	int realbytes;           /* For splitting up large transfers, etc. */
 
-  /* Status, misc info */
-  int node;                /* Prom node for this DMA device */
-  int dma_running;         /* Are we using the DMA now? */
-
-  /* DMA revision: 0=REV0 1=REV1 2=REV2 3=DMA_PLUS */
-  int dma_rev;
+	/* DMA revision */
+	enum dvma_rev revision;
 };
 
-extern struct Linux_SBus_DMA Sparc_DMA;
+extern struct Linux_SBus_DMA *dma_chain;
+
+/* Broken hardware... */
+#define DMA_ISBROKEN(dma)    ((dma)->revision == dvmarev1)
+#define DMA_ISESC1(dma)      ((dma)->revision == dvmaesc1)
 
 /* Main routines in dma.c */
 extern void dump_dma_regs(struct sparc_dma_registers *);
-extern unsigned long probe_dma(unsigned long);
-extern void sparc_dma_init_transfer(struct sparc_dma_registers *,
-				    unsigned long, int, int);
-extern int sparc_dma_interrupt(struct sparc_dma_registers *);
+extern unsigned long dvma_init(struct linux_sbus *, unsigned long);
 
 /* Fields in the cond_reg register */
 /* First, the version identification bits */
 #define DMA_DEVICE_ID    0xf0000000        /* Device identification bits */
 #define DMA_VERS0        0x00000000        /* Sunray DMA version */
+#define DMA_ESCV1        0x40000000        /* DMA ESC Version 1 */
 #define DMA_VERS1        0x80000000        /* DMA rev 1 */
 #define DMA_VERS2        0xa0000000        /* DMA rev 2 */
 #define DMA_VERSPLUS     0x90000000        /* DMA rev 1 PLUS */
 
-#define DMA_HNDL_INTR    0x00000001        /* An interrupt needs to be handled */
-#define DMA_HNDL_ERROR   0x00000002        /* We need to take care of an error */
+#define DMA_HNDL_INTR    0x00000001        /* An IRQ needs to be handled */
+#define DMA_HNDL_ERROR   0x00000002        /* We need to take an error */
 #define DMA_FIFO_ISDRAIN 0x0000000c        /* The DMA FIFO is draining */
 #define DMA_INT_ENAB     0x00000010        /* Turn on interrupts */
 #define DMA_FIFO_INV     0x00000020        /* Invalidate the FIFO */
 #define DMA_ACC_SZ_ERR   0x00000040        /* The access size was bad */
 #define DMA_FIFO_STDRAIN 0x00000040        /* DMA_VERS1 Drain the FIFO */
 #define DMA_RST_SCSI     0x00000080        /* Reset the SCSI controller */
-#define DMA_ST_WRITE     0x00000100        /* If set, write from device to memory */
+#define DMA_ST_WRITE     0x00000100        /* write from device to memory */
 #define DMA_ENABLE       0x00000200        /* Fire up DMA, handle requests */
-#define DMA_PEND_READ    0x00000400        /* DMA_VERS1/0/PLUS Read is pending */
+#define DMA_PEND_READ    0x00000400        /* DMA_VERS1/0/PLUS Pendind Read */
 #define DMA_BCNT_ENAB    0x00002000        /* If on, use the byte counter */
 #define DMA_TERM_CNTR    0x00004000        /* Terminal counter */
 #define DMA_CSR_DISAB    0x00010000        /* No FIFO drains during csr */
 #define DMA_SCSI_DISAB   0x00020000        /* No FIFO drains during reg */
+#define DMA_ADD_ENABLE   0x00040000        /* Special ESC DVMA optimization */
 #define DMA_BRST_SZ      0x000c0000        /* SBUS transfer r/w burst size */
 #define DMA_ADDR_DISAB   0x00100000        /* No FIFO drains during addr */
-#define DMA_2CLKS        0x00200000        /* Each transfer equals 2 clock ticks */
-#define DMA_3CLKS        0x00400000        /* Each transfer equals 3 clock ticks */
-#define DMA_CNTR_DISAB   0x00800000        /* No intr's when DMA_TERM_CNTR is set */
-#define DMA_AUTO_NADDR   0x01000000        /* Use "auto next address" feature */
+#define DMA_2CLKS        0x00200000        /* Each transfer = 2 clock ticks */
+#define DMA_3CLKS        0x00400000        /* Each transfer = 3 clock ticks */
+#define DMA_CNTR_DISAB   0x00800000        /* No IRQ when DMA_TERM_CNTR set */
+#define DMA_AUTO_NADDR   0x01000000        /* Use "auto nxt addr" feature */
 #define DMA_SCSI_ON      0x02000000        /* Enable SCSI dma */
 #define DMA_LOADED_ADDR  0x04000000        /* Address has been loaded */
 #define DMA_LOADED_NADDR 0x08000000        /* Next address has been loaded */
 
-/* Only 24-bits of the byte count are significant */
-#define DMA_BYTE_CNT_MASK  0x00ffffff
+/* Values describing the burst-size property from the PROM */
+#define DMA_BURST1       0x01
+#define DMA_BURST2       0x02
+#define DMA_BURST4       0x04
+#define DMA_BURST8       0x08
+#define DMA_BURST16      0x10
+#define DMA_BURST32      0x20
+#define DMA_BURST64      0x40
+#define DMA_BURSTBITS    0x7f
+
+/* Determine highest possible final transfer address given a base */
+#define DMA_MAXEND(addr) (0x01000000UL-(((unsigned long)(addr))&0x00ffffffUL))
+
+/* Yes, I hack a lot of elisp in my spare time... */
+#define DMA_ERROR_P(regs)  ((((regs)->cond_reg) & DMA_HNDL_ERROR))
+#define DMA_IRQ_P(regs)    ((((regs)->cond_reg) & DMA_HNDL_INTR))
+#define DMA_WRITE_P(regs)  ((((regs)->cond_reg) & DMA_ST_WRITE))
+#define DMA_OFF(regs)      ((((regs)->cond_reg) &= (~DMA_ENABLE)))
+#define DMA_INTSOFF(regs)  ((((regs)->cond_reg) &= (~DMA_INT_ENAB)))
+#define DMA_INTSON(regs)   ((((regs)->cond_reg) |= (DMA_INT_ENAB)))
+#define DMA_PUNTFIFO(regs) ((((regs)->cond_reg) |= DMA_FIFO_INV))
+#define DMA_SETSTART(regs, addr)  ((((regs)->st_addr) = (char *) addr))
+#define DMA_BEGINDMA_W(regs) \
+        ((((regs)->cond_reg |= (DMA_ST_WRITE|DMA_ENABLE|DMA_INT_ENAB))))
+#define DMA_BEGINDMA_R(regs) \
+        ((((regs)->cond_reg |= ((DMA_ENABLE|DMA_INT_ENAB)&(~DMA_ST_WRITE)))))
+
+/* For certain DMA chips, we need to disable ints upon irq entry
+ * and turn them back on when we are done.  So in any ESP interrupt
+ * handler you *must* call DMA_IRQ_ENTRY upon entry and DMA_IRQ_EXIT
+ * when leaving the handler.  You have been warned...
+ */
+#define DMA_IRQ_ENTRY(dma, dregs) do { \
+        if(DMA_ISBROKEN(dma)) DMA_INTSOFF(dregs); \
+   } while (0)
+
+#define DMA_IRQ_EXIT(dma, dregs) do { \
+	if(DMA_ISBROKEN(dma)) DMA_INTSON(dregs); \
+   } while(0)
 
 /* Pause until counter runs out or BIT isn't set in the DMA condition
  * register.
  */
-extern inline void sparc_dma_pause(struct sparc_dma_registers *dma_regs,
+extern inline void sparc_dma_pause(struct sparc_dma_registers *regs,
 				   unsigned long bit)
 {
-  int ctr = 50000;   /* Let's find some bugs ;) */
-
-  /* Busy wait until the bit is not set any more */
-  while((dma_regs->cond_reg&bit) && (ctr>0)) {
-    ctr--;
-    __delay(1);
-  }
-
-  /* Check for bogus outcome. */
-  if(ctr==0) {
-    printk("DMA Grrr:  I tried for wait for the assertion of bit %08xl to clear",
-	   (unsigned int) bit);
-    printk("           in the DMA condition register and it did not!\n");
-    printk("Cannot continue, halting...\n");
-    prom_halt();
-  }
-
-  return;
-}
-
-/* Enable DMA interrupts */
-extern inline void sparc_dma_enable_interrupts(struct sparc_dma_registers *dma_regs)
-{
-  dma_regs->cond_reg |= DMA_INT_ENAB;
-}
+	int ctr = 50000;   /* Let's find some bugs ;) */
 
-/* Disable DMA interrupts from coming in */
-extern inline void sparc_dma_disable_interrupts(struct sparc_dma_registers *dma_regs)
-{
-  dma_regs->cond_reg &= ~(DMA_INT_ENAB);
+	/* Busy wait until the bit is not set any more */
+	while((regs->cond_reg&bit) && (ctr>0)) {
+		ctr--;
+		__delay(5);
+	}
+
+	/* Check for bogus outcome. */
+	if(!ctr)
+		panic("DMA timeout");
 }
 
-/* Reset the DMA module. */
-extern inline void sparc_dma_reset(struct sparc_dma_registers *dma_regs)
-{
-  /* Let the current FIFO drain itself */
-  sparc_dma_pause(dma_regs, (DMA_FIFO_ISDRAIN));
-
-  /* Reset the logic */
-  dma_regs->cond_reg |= (DMA_RST_SCSI);     /* assert */
-  __delay(400);                             /* let the bits set ;) */
-  dma_regs->cond_reg &= ~(DMA_RST_SCSI);    /* de-assert */
-
-  sparc_dma_enable_interrupts(dma_regs);    /* Re-enable interrupts */
-
-  /* Enable FAST transfers if available */
-  if(Sparc_DMA.dma_rev>1) { dma_regs->cond_reg |= DMA_3CLKS; }
-  Sparc_DMA.dma_running = 0;
-
-  return;
-}
+/* Reset the friggin' thing... */
+#define DMA_RESET(dma) do { \
+	struct sparc_dma_registers *regs = dma->regs;                      \
+	/* Let the current FIFO drain itself */                            \
+	sparc_dma_pause(regs, (DMA_FIFO_ISDRAIN));                         \
+	/* Reset the logic */                                              \
+	regs->cond_reg |= (DMA_RST_SCSI);     /* assert */                 \
+	__delay(400);                         /* let the bits set ;) */    \
+	regs->cond_reg &= ~(DMA_RST_SCSI);    /* de-assert */              \
+	sparc_dma_enable_interrupts(regs);    /* Re-enable interrupts */   \
+	/* Enable FAST transfers if available */                           \
+	if(dma->revision>dvmarev1) regs->cond_reg |= DMA_3CLKS;            \
+	dma->running = 0;                                                  \
+} while(0)
+
+#define for_each_dvma(dma) \
+        for((dma) = dma_chain; (dma); (dma) = (dma)->next)
+
+extern int get_dma_list(char *);
+extern int request_dma(unsigned int, const char *);
+extern void free_dma(unsigned int);
 
 #endif /* !(_ASM_SPARC_DMA_H) */
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/ecc.h linux/include/asm-sparc/ecc.h
--- v1.3.43/linux/include/asm-sparc/ecc.h	Tue Jun 27 14:11:45 1995
+++ linux/include/asm-sparc/ecc.h	Sat Nov 25 04:31:38 1995
@@ -1,4 +1,5 @@
-/* ecc.h: Definitions and defines for the external cache/memory
+/* $Id: ecc.h,v 1.2 1995/11/25 02:31:37 davem Exp $
+ * ecc.h: Definitions and defines for the external cache/memory
  *        controller on the sun4m.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/eeprom.h linux/include/asm-sparc/eeprom.h
--- v1.3.43/linux/include/asm-sparc/eeprom.h	Tue Jun 27 14:11:45 1995
+++ linux/include/asm-sparc/eeprom.h	Sat Nov 25 04:31:39 1995
@@ -1,4 +1,5 @@
-/* eeprom.h:  Definitions for the Sun eeprom.
+/* $Id: eeprom.h,v 1.3 1995/11/25 02:31:38 davem Exp $
+ * eeprom.h:  Definitions for the Sun eeprom.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  */
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/elf.h linux/include/asm-sparc/elf.h
--- v1.3.43/linux/include/asm-sparc/elf.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-sparc/elf.h	Sat Nov 25 04:31:41 1995
@@ -0,0 +1,18 @@
+/* $Id: elf.h,v 1.2 1995/11/25 02:31:40 davem Exp $ */
+#ifndef __ASMSPARC_ELF_H
+#define __ASMSPARC_ELF_H
+
+/*
+ * ELF register definitions..
+ */
+
+#include <asm/ptrace.h>
+
+typedef unsigned long elf_greg_t;
+
+#define ELF_NGREG (sizeof (struct pt_regs) / sizeof(elf_greg_t))
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+typedef unsigned long elf_fpregset_t;
+
+#endif
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/errno.h linux/include/asm-sparc/errno.h
--- v1.3.43/linux/include/asm-sparc/errno.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-sparc/errno.h	Sat Nov 25 04:31:42 1995
@@ -0,0 +1,133 @@
+/* $Id: errno.h,v 1.4 1995/11/25 02:31:41 davem Exp $ */
+#ifndef _SPARC_ERRNO_H
+#define _SPARC_ERRNO_H
+
+/* These match the SunOS error numbering scheme. */
+#define	EPERM		 1	/* Operation not permitted */
+#define	ENOENT		 2	/* No such file or directory */
+#define	ESRCH		 3	/* No such process */
+#define	EINTR		 4	/* Interrupted system call */
+#define	EIO		 5	/* I/O error */
+#define	ENXIO		 6	/* No such device or address */
+#define	E2BIG		 7	/* Arg list too long */
+#define	ENOEXEC		 8	/* Exec format error */
+#define	EBADF		 9	/* Bad file number */
+#define	ECHILD		10	/* No child processes */
+#define	EAGAIN		11	/* Try again */
+#define	ENOMEM		12	/* Out of memory */
+#define	EACCES		13	/* Permission denied */
+#define	EFAULT		14	/* Bad address */
+#define	ENOTBLK		15	/* Block device required */
+#define	EBUSY		16	/* Device or resource busy */
+#define	EEXIST		17	/* File exists */
+#define	EXDEV		18	/* Cross-device link */
+#define	ENODEV		19	/* No such device */
+#define	ENOTDIR		20	/* Not a directory */
+#define	EISDIR		21	/* Is a directory */
+#define	EINVAL		22	/* Invalid argument */
+#define	ENFILE		23	/* File table overflow */
+#define	EMFILE		24	/* Too many open files */
+#define	ENOTTY		25	/* Not a typewriter */
+#define	ETXTBSY		26	/* Text file busy */
+#define	EFBIG		27	/* File too large */
+#define	ENOSPC		28	/* No space left on device */
+#define	ESPIPE		29	/* Illegal seek */
+#define	EROFS		30	/* Read-only file system */
+#define	EMLINK		31	/* Too many links */
+#define	EPIPE		32	/* Broken pipe */
+#define	EDOM		33	/* Math argument out of domain of func */
+#define	ERANGE		34	/* Math result not representable */
+#define	EWOULDBLOCK	35	/* Operation would block */
+#define	EINPROGRESS	36	/* Operation now in progress */
+#define	EALREADY	37	/* Operation already in progress */
+#define	ENOTSOCK	38	/* Socket operation on non-socket */
+#define	EDESTADDRREQ	39	/* Destination address required */
+#define	EMSGSIZE	40	/* Message too long */
+#define	EPROTOTYPE	41	/* Protocol wrong type for socket */
+#define	ENOPROTOOPT	42	/* Protocol not available */
+#define	EPROTONOSUPPORT	43	/* Protocol not supported */
+#define	ESOCKTNOSUPPORT	44	/* Socket type not supported */
+#define	EOPNOTSUPP	45	/* Op not supported on transport endpoint */
+#define	EPFNOSUPPORT	46	/* Protocol family not supported */
+#define	EAFNOSUPPORT	47	/* Address family not supported by protocol */
+#define	EADDRINUSE	48	/* Address already in use */
+#define	EADDRNOTAVAIL	49	/* Cannot assign requested address */
+#define	ENETDOWN	50	/* Network is down */
+#define	ENETUNREACH	51	/* Network is unreachable */
+#define	ENETRESET	52	/* Net dropped connection because of reset */
+#define	ECONNABORTED	53	/* Software caused connection abort */
+#define	ECONNRESET	54	/* Connection reset by peer */
+#define	ENOBUFS		55	/* No buffer space available */
+#define	EISCONN		56	/* Transport endpoint is already connected */
+#define	ENOTCONN	57	/* Transport endpoint is not connected */
+#define	ESHUTDOWN	58	/* No send after transport endpoint shutdown */
+#define	ETOOMANYREFS	59	/* Too many references: cannot splice */
+#define	ETIMEDOUT	60	/* Connection timed out */
+#define	ECONNREFUSED	61	/* Connection refused */
+#define	ELOOP		62	/* Too many symbolic links encountered */
+#define	ENAMETOOLONG	63	/* File name too long */
+#define	EHOSTDOWN	64	/* Host is down */
+#define	EHOSTUNREACH	65	/* No route to host */
+#define	ENOTEMPTY	66	/* Directory not empty */
+#define EPROCLIM        67      /* SUNOS: Too many processes */
+#define	EUSERS		68	/* Too many users */
+#define	EDQUOT		69	/* Quota exceeded */
+#define	ESTALE		70	/* Stale NFS file handle */
+#define	EREMOTE		71	/* Object is remote */
+#define	ENOSTR		72	/* Device not a stream */
+#define	ETIME		73	/* Timer expired */
+#define	ENOSR		74	/* Out of streams resources */
+#define	ENOMSG		75	/* No message of desired type */
+#define	EBADMSG		76	/* Not a data message */
+#define	EIDRM		77	/* Identifier removed */
+#define	EDEADLK		78	/* Resource deadlock would occur */
+#define	ENOLCK		79	/* No record locks available */
+#define	ENONET		80	/* Machine is not on the network */
+#define ERREMOTE        81      /* SunOS: Too many lvls of remote in path */
+#define	ENOLINK		82	/* Link has been severed */
+#define	EADV		83	/* Advertise error */
+#define	ESRMNT		84	/* Srmount error */
+#define	ECOMM		85      /* Communication error on send */
+#define	EPROTO		86	/* Protocol error */
+#define	EMULTIHOP	87	/* Multihop attempted */
+#define	EDOTDOT		88	/* RFS specific error */
+#define	EREMCHG		89	/* Remote address changed */
+#define	ENOSYS		90	/* Function not implemented */
+
+/* The rest have no SunOS equivalent. */
+#define	ESTRPIPE	91	/* Streams pipe error */
+#define	EOVERFLOW	92	/* Value too large for defined data type */
+#define	EBADFD		93	/* File descriptor in bad state */
+#define	ECHRNG		94	/* Channel number out of range */
+#define	EL2NSYNC	95	/* Level 2 not synchronized */
+#define	EL3HLT		96	/* Level 3 halted */
+#define	EL3RST		97	/* Level 3 reset */
+#define	ELNRNG		98	/* Link number out of range */
+#define	EUNATCH		99	/* Protocol driver not attached */
+#define	ENOCSI		100	/* No CSI structure available */
+#define	EL2HLT		101	/* Level 2 halted */
+#define	EBADE		102	/* Invalid exchange */
+#define	EBADR		103	/* Invalid request descriptor */
+#define	EXFULL		104	/* Exchange full */
+#define	ENOANO		105	/* No anode */
+#define	EBADRQC		106	/* Invalid request code */
+#define	EBADSLT		107	/* Invalid slot */
+#define	EDEADLOCK	108	/* File locking deadlock error */
+#define	EBFONT		109	/* Bad font file format */
+#define	ELIBEXEC	110	/* Cannot exec a shared library directly */
+#define	ENODATA		111	/* No data available */
+#define	ELIBBAD		112	/* Accessing a corrupted shared library */
+#define	ENOPKG		113	/* Package not installed */
+#define	ELIBACC		114	/* Can not access a needed shared library */
+#define	ENOTUNIQ	115	/* Name not unique on network */
+#define	ERESTART	116	/* Interrupted syscall should be restarted */
+#define	EUCLEAN		117	/* Structure needs cleaning */
+#define	ENOTNAM		118	/* Not a XENIX named type file */
+#define	ENAVAIL		119	/* No XENIX semaphores available */
+#define	EISNAM		120	/* Is a named type file */
+#define	EREMOTEIO	121	/* Remote I/O error */
+#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 */
+
+#endif
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/fcntl.h linux/include/asm-sparc/fcntl.h
--- v1.3.43/linux/include/asm-sparc/fcntl.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-sparc/fcntl.h	Sat Nov 25 04:31:44 1995
@@ -0,0 +1,65 @@
+/* $Id: fcntl.h,v 1.5 1995/11/25 02:31:43 davem Exp $ */
+#ifndef _SPARC_FCNTL_H
+#define _SPARC_FCNTL_H
+
+/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
+   located on an ext2 file system */
+#define O_RDONLY	0x0000
+#define O_WRONLY	0x0001
+#define O_RDWR		0x0002
+#define O_ACCMODE	0x0003
+#define O_NDELAY	0x0004
+#define O_APPEND	0x0008
+#define FASYNC		0x0040	/* fcntl, for BSD compatibility */
+#define O_CREAT		0x0200	/* not fcntl */
+#define O_EXCL		0x0800	/* not fcntl */
+#define O_NOCTTY	0x8000	/* not fcntl */
+#define O_TRUNC		0x0400	/* not fcntl */
+#define O_SYNC		0x2000
+#define O_NONBLOCK	0x4000
+
+#define F_DUPFD		0	/* dup */
+#define F_GETFD		1	/* get f_flags */
+#define F_SETFD		2	/* set f_flags */
+#define F_GETFL		3	/* more flags (cloexec) */
+#define F_SETFL		4
+#define F_GETOWN	5	/*  for sockets. */
+#define F_SETOWN	6	/*  for sockets. */
+#define F_GETLK		7
+#define F_SETLK		8
+#define F_SETLKW	9
+
+/* for F_[GET|SET]FL */
+#define FD_CLOEXEC	1	/* actually anything with low bit set goes */
+
+/* for posix fcntl() and lockf() */
+#define F_RDLCK		1
+#define F_WRLCK		2
+#define F_UNLCK		3
+
+/* for old implementation of bsd flock () */
+#define F_EXLCK		4	/* or 3 */
+#define F_SHLCK		8	/* or 4 */
+
+/* operations for bsd flock(), also used by the kernel implementation */
+#define LOCK_SH		1	/* shared lock */
+#define LOCK_EX		2	/* exclusive lock */
+#define LOCK_NB		4	/* or'd with one of the above to prevent
+				   blocking */
+#define LOCK_UN		8	/* remove lock */
+
+#ifdef __KERNEL__
+#define F_POSIX		1
+#define F_FLOCK		2
+#endif /* __KERNEL__ */
+
+struct flock {
+	short l_type;
+	short l_whence;
+	off_t l_start;
+	off_t l_len;
+	pid_t l_pid;
+	short __unused;
+};
+
+#endif
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/floppy.h linux/include/asm-sparc/floppy.h
--- v1.3.43/linux/include/asm-sparc/floppy.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-sparc/floppy.h	Sat Nov 25 04:31:46 1995
@@ -0,0 +1,357 @@
+/* $Id: floppy.h,v 1.8 1995/11/25 02:31:45 davem Exp $
+ * asm-sparc/floppy.h: Sparc specific parts of the Floppy driver.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef __ASM_SPARC_FLOPPY_H
+#define __ASM_SPARC_FLOPPY_H
+
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/idprom.h>
+#include <asm/machines.h>
+#include <asm/oplib.h>
+#include <asm/auxio.h>
+#include <asm/irq.h>
+
+/* References:
+ * 1) Netbsd Sun floppy driver.
+ * 2) NCR 82077 controller manual
+ * 3) Intel 82077 controller manual
+ */
+struct sun_flpy_controller {
+	volatile unsigned char status_82072;  /* Main Status reg. */
+#define dcr_82072              status_82072   /* Digital Control reg. */
+#define status1_82077          status_82072   /* Auxiliary Status reg. 1 */
+
+	volatile unsigned char data_82072;    /* Data fifo. */
+#define status2_82077          data_82072     /* Auxiliary Status reg. 2 */
+
+	volatile unsigned char dor_82077;     /* Digital Output reg. */
+	volatile unsigned char tapectl_82077; /* What the? Tape control reg? */
+
+	volatile unsigned char status_82077;  /* Main Status Register. */
+#define drs_82077              status_82077   /* Digital Rate Select reg. */
+
+	volatile unsigned char data_82077;    /* Data fifo. */
+	volatile unsigned char ___unused;
+	volatile unsigned char dir_82077;     /* Digital Input reg. */
+#define dcr_82077              dir_82077      /* Config Control reg. */
+};
+
+/* You'll only ever find one controller on a SparcStation anyways. */
+static struct sun_flpy_controller *sun_fdc = NULL;
+volatile unsigned char *fdc_status;
+
+struct sun_floppy_ops {
+	unsigned char (*fd_inb)(int port);
+	void (*fd_outb)(unsigned char value, int port);
+};
+
+static struct sun_floppy_ops sun_fdops;
+
+#define fd_inb(port)              sun_fdops.fd_inb(port)
+#define fd_outb(value,port)       sun_fdops.fd_outb(value,port)
+#define fd_enable_dma()           sun_fd_enable_dma()
+#define fd_disable_dma()          sun_fd_disable_dma()
+#define fd_request_dma()          (0) /* nothing... */
+#define fd_free_dma()             /* nothing... */
+#define fd_clear_dma_ff()         /* nothing... */
+#define fd_set_dma_mode(mode)     sun_fd_set_dma_mode(mode)
+#define fd_set_dma_addr(addr)     sun_fd_set_dma_addr(addr)
+#define fd_set_dma_count(count)   sun_fd_set_dma_count(count)
+#define fd_enable_irq()           /* nothing... */
+#define fd_disable_irq()          /* nothing... */
+#define fd_cacheflush(addr, size) /* nothing... */
+#define fd_request_irq()          sun_fd_request_irq()
+#define fd_free_irq()             /* nothing... */
+
+/* It's all the same... */
+#define virt_to_bus(x)            (x)
+#define bus_to_virt(x)            (x)
+
+/* XXX This isn't really correct. XXX */
+#define get_dma_residue(x)        (0)
+
+#define FLOPPY0_TYPE  4
+#define FLOPPY1_TYPE  0
+
+/* Super paranoid... */
+#undef HAVE_DISABLE_HLT
+
+/* Here is where we catch the floppy driver trying to initialize,
+ * therefore this is where we call the PROM device tree probing
+ * routine etc. on the Sparc.
+ */
+#define FDC1                      sun_floppy_init()
+
+static int FDC2=-1;
+
+#define N_FDC    1
+#define N_DRIVE  8
+
+/* No 64k boundry crossing problems on the Sparc. */
+#define CROSS_64KB(a,s) (0)
+
+/* Routines unique to each controller type on a Sun. */
+static unsigned char sun_82072_fd_inb(int port)
+{
+	switch(port & 7) {
+	default:
+		printk("floppy: Asked to read unknown port %d\n", port);
+		panic("floppy: Port bolixed.");
+	case 4: /* FD_STATUS */
+		return sun_fdc->status_82072 & ~STATUS_DMA;
+	case 5: /* FD_DATA */
+		return sun_fdc->data_82072;
+	case 7: /* FD_DIR */
+		/* Always return 0, the disk never changes
+		 * without the kernel explicitly doing so.
+		 */
+		return 0;
+	};
+	panic("sun_82072_fd_inb: How did I get here?");
+}
+
+static void sun_82072_fd_outb(unsigned char value, int port)
+{
+	switch(port & 7) {
+	default:
+		printk("floppy: Asked to write to unknown port %d\n", port);
+		panic("floppy: Port bolixed.");
+	case 2: /* FD_DOR */
+		/* Oh geese, 82072 on the Sun has no DOR register,
+		 * the functionality is implemented via the AUXIO
+		 * I/O register.  So we must emulate the behavior.
+		 *
+		 * ASSUMPTIONS:  There will only ever be one floppy
+		 *               drive attached to a Sun controller
+		 *               and it will be at drive zero.
+		 */
+		if(value & 0xf0)
+			set_auxio(AUXIO_FLPY_DSEL, 0);
+#if 0
+		else
+			set_auxio(0, AUXIO_FLPY_DSEL);
+#endif
+		break;
+	case 5: /* FD_DATA */
+		sun_fdc->data_82072 = value;
+		break;
+	case 7: /* FD_DCR */
+		sun_fdc->dcr_82072 = value;
+		break;
+	case 4: /* FD_STATUS */
+		sun_fdc->status_82072 = value;
+		break;
+	};
+	return;
+}
+
+static unsigned char sun_82077_fd_inb(int port)
+{
+	switch(port & 7) {
+	default:
+		printk("floppy: Asked to read unknown port %d\n", port);
+		panic("floppy: Port bolixed.");
+	case 4: /* FD_STATUS */
+		return sun_fdc->status_82077 & ~STATUS_DMA;
+	case 5: /* FD_DATA */
+		return sun_fdc->data_82077;
+	case 7: /* FD_DIR */
+		/* Always return 0, the disk never changes
+		 * without the kernel explicitly ejecting it.
+		 */
+		return 0;
+	};
+	panic("sun_82072_fd_inb: How did I get here?");
+}
+
+static void sun_82077_fd_outb(unsigned char value, int port)
+{
+	switch(port & 7) {
+	default:
+		printk("floppy: Asked to write to unknown port %d\n", port);
+		panic("floppy: Port bolixed.");
+	case 2: /* FD_DOR */
+		/* Happily, the 82077 has a real DOR register. */
+		sun_fdc->dor_82077 = value;
+		break;
+	case 5: /* FD_DATA */
+		sun_fdc->data_82077 = value;
+		break;
+	case 7: /* FD_DCR */
+		sun_fdc->dcr_82077 = value;
+		break;
+	case 4: /* FD_STATUS */
+		sun_fdc->status_82077 = value;
+		break;
+	};
+	return;
+}
+
+/* For pseudo-dma (Sun floppy drives have no real DMA available to
+ * them so we must eat the data fifo bytes directly ourselves) we have
+ * three state variables.  doing_pdma tells our inline low-level
+ * assembly floppy interrupt entry point whether it should sit and eat
+ * bytes from the fifo or just transfer control up to the higher level
+ * floppy interrupt c-code.  I tried very hard but I could not get the
+ * pseudo-dma to work in c-code without getting many overruns and
+ * underruns.  If non-zero, doing_pdma encodes the direction of
+ * the transfer for debugging.  1=read 2=write
+ */
+char *pdma_vaddr;
+char *pdma_vsave;
+unsigned long pdma_size;
+int doing_pdma = 0;
+
+/* Common routines to all controller types on the Sparc. */
+static inline void virtual_dma_init(void)
+{
+	/* nothing... */
+}
+
+static inline void sun_fd_disable_dma(void)
+{
+	doing_pdma = 0;
+}
+
+static inline void sun_fd_set_dma_mode(int mode)
+{
+	switch(mode) {
+	case DMA_MODE_READ:
+		doing_pdma = 1;
+		break;
+	case DMA_MODE_WRITE:
+		doing_pdma = 2;
+		break;
+	default:
+		printk("Unknown dma mode %d\n", mode);
+		panic("floppy: Giving up...");
+	}
+}
+
+static inline void sun_fd_set_dma_addr(char *buffer)
+{
+	pdma_vaddr = buffer;
+}
+
+static inline void sun_fd_set_dma_count(int length)
+{
+	pdma_size = length;
+}
+
+static inline void sun_fd_enable_dma(void)
+{
+	/* We're about to let it rip, lock any tlb entries necessary. */
+	pdma_vaddr = pdma_vsave = mmu_lockarea(pdma_vaddr, pdma_size);
+}
+
+/* Our low-level entry point in arch/sparc/kernel/entry.S */
+extern void floppy_hardint(int irq, struct pt_regs *regs);
+
+static int sun_fd_request_irq(void)
+{
+	static int once = 0;
+	int error;
+
+	if(!once) {
+		once = 1;
+		error = request_fast_irq(FLOPPY_IRQ, floppy_hardint, SA_INTERRUPT, "floppy");
+		return ((error == 0) ? 0 : -1);
+	} else return 0;
+}
+
+static struct linux_prom_registers fd_regs[2];
+
+static int sun_floppy_init(void)
+{
+	char state[128];
+	int tnode, fd_node, num_regs;
+
+	FLOPPY_IRQ = 11;
+	/* Forget it if we aren't on a machine that could possibly
+	 * ever have a floppy drive.
+	 */
+	if((sparc_cpu_model != sun4c && sparc_cpu_model != sun4m) ||
+	   ((idprom->id_machtype == (SM_SUN4C | SM_4C_SLC)) ||
+	    (idprom->id_machtype == (SM_SUN4C | SM_4C_ELC)))) {
+		/* We certainly don't have a floppy controller. */
+		goto no_sun_fdc;
+	}
+	/* Well, try and find one. */
+	tnode = prom_getchild(prom_root_node);
+	fd_node = prom_searchsiblings(tnode, "obio");
+	if(fd_node != 0) {
+		tnode = prom_getchild(fd_node);
+		fd_node = prom_searchsiblings(tnode, "SUNW,fdtwo");
+	} else {
+		fd_node = prom_searchsiblings(tnode, "fd");
+	}
+	if(fd_node == 0) {
+		goto no_sun_fdc;
+	}
+
+	/* The sun4m lets us know if the controller is actually usable. */
+	if(sparc_cpu_model == sun4m) {
+		prom_getproperty(fd_node, "status", state, sizeof(state));
+		if(!strcmp(state, "disabled")) {
+			goto no_sun_fdc;
+		}
+	}
+	num_regs = prom_getproperty(fd_node, "reg", (char *) fd_regs, sizeof(fd_regs));
+	num_regs = (num_regs / sizeof(fd_regs[0]));
+	prom_apply_obio_ranges(fd_regs, num_regs);
+	sun_fdc = (struct sun_flpy_controller *) sparc_alloc_io(fd_regs[0].phys_addr,
+								0x0,
+								fd_regs[0].reg_size,
+								"floppy",
+								fd_regs[0].which_io,
+								0x0);
+	/* Last minute sanity check... */
+	if(sun_fdc->status_82072 == 0xff) {
+		sun_fdc = NULL;
+		goto no_sun_fdc;
+	}
+
+	/* We need the version as early as possible to set up the
+	 * function pointers correctly.  Assume 82077 for probing
+	 * purposes.
+	 */
+	sun_fdops.fd_inb = sun_82077_fd_inb;
+	sun_fdops.fd_outb = sun_82077_fd_outb;
+	fdc_status = &sun_fdc->status_82077;
+
+	/* This controller detection technique is from the netbsd
+	 * Sun floppy driver, origionally Chris Torek of BSDI came
+	 * up with this.  It seems to work pretty well.
+	 */
+	if(sun_fdc->dor_82077 == 0x80) {
+		sun_fdc->dor_82077 = 2;
+		if(sun_fdc->dor_82077 == 0x80) {
+			/* Ok, it's really an 82072. */
+			sun_fdops.fd_inb = sun_82072_fd_inb;
+			sun_fdops.fd_outb = sun_82072_fd_outb;
+			fdc_status = &sun_fdc->status_82072;
+		}
+	}
+
+	/* P3: The only realiable way which I found for ejection
+	 * of boot floppy. AUXIO_FLPY_EJCT is not enougth alone.
+	 */
+	set_auxio(AUXIO_FLPY_EJCT, 0);
+	udelay(1000);
+	set_auxio(AUXIO_FLPY_DSEL, AUXIO_FLPY_EJCT);
+	udelay(1000);
+	set_auxio(0, AUXIO_FLPY_DSEL);
+
+	/* Success... */
+	return (int) sun_fdc;
+
+no_sun_fdc:
+	return -1;
+}
+
+#endif /* !(__ASM_SPARC_FLOPPY_H) */
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/head.h linux/include/asm-sparc/head.h
--- v1.3.43/linux/include/asm-sparc/head.h	Tue Jun 27 14:11:45 1995
+++ linux/include/asm-sparc/head.h	Sat Nov 25 04:31:48 1995
@@ -1,27 +1,30 @@
+/* $Id: head.h,v 1.19 1995/11/25 02:31:47 davem Exp $ */
 #ifndef __SPARC_HEAD_H
 #define __SPARC_HEAD_H
 
 #define KERNBASE        0xf0000000  /* First address the kernel will eventually be */
 #define LOAD_ADDR       0x4000      /* prom jumps to us here unless this is elf /boot */
-#define C_STACK         96
 #define SUN4C_SEGSZ     (1 << 18)
 #define SRMMU_L1_KBASE_OFFSET ((KERNBASE>>24)<<2)  /* Used in boot remapping. */
-#define INTS_ENAB   0x01            /* entry.S uses this. */
+#define INTS_ENAB        0x01           /* entry.S uses this. */
 
-#define NCPUS           4            /* Architectual limit of sun4m. */
+#define NCPUS            4              /* Architectual limit of sun4m. */
 
-#define  SUN4_PROM_VECTOR   0xFFE81000    /* To safely die on a SUN4 */
-#define  SUN4_PRINTF   0x84               /* Offset into SUN4_PROM_VECTOR */
+#define SUN4_PROM_VECTOR 0xFFE81000     /* To safely die on a SUN4 */
+#define SUN4_PRINTF      0x84           /* Offset into SUN4_PROM_VECTOR */
 
-#define WRITE_PAUSE     nop; nop; nop;
-
-#define NOP_INSN        0x01000000        /* Used to patch sparc_save_state */
+#define WRITE_PAUSE      nop; nop; nop; /* Have to do this after %wim/%psr chg */
+#define NOP_INSN         0x01000000     /* Used to patch sparc_save_state */
 
 /* Here are some trap goodies */
 
 /* Generic trap entry. */
 #define TRAP_ENTRY(type, label) \
-	mov (type), %l3; b label; rd %psr, %l0; nop;
+	rd %psr, %l0; b label; rd %wim, %l3; nop;
+
+/* This is for traps we should NEVER get. */
+#define BAD_TRAP(num) \
+        rd %psr, %l0; mov num, %l7; b bad_trap_handler; rd %wim, %l3;
 
 /* Notice that for the system calls we pull a trick.  We load up a
  * different pointer to the system call vector table in %l7, but call
@@ -31,19 +34,31 @@
 
 /* Software trap for Linux system calls. */
 #define LINUX_SYSCALL_TRAP \
-        sethi %hi(C_LABEL(sys_call_table)), %l7; or %l7, %lo(C_LABEL(sys_call_table)), %l7; b linux_sparc_syscall; mov %psr, %l0;
+        sethi %hi(C_LABEL(sys_call_table)), %l7; \
+        or %l7, %lo(C_LABEL(sys_call_table)), %l7; \
+        b linux_sparc_syscall; \
+        rd %psr, %l0;
 
 /* Software trap for SunOS4.1.x system calls. */
 #define SUNOS_SYSCALL_TRAP \
-        sethi %hi(C_LABEL(sys_call_table)), %l7; or %l7, %lo(C_LABEL(sys_call_table)), %l7; b linux_sparc_syscall; mov %psr, %l0;
+        sethi %hi(C_LABEL(sunos_sys_table)), %l7; \
+        or %l7, %lo(C_LABEL(sunos_sys_table)), %l7; \
+        b linux_sparc_syscall; \
+        rd %psr, %l0;
 
 /* Software trap for Slowaris system calls. */
 #define SOLARIS_SYSCALL_TRAP \
-        sethi %hi(C_LABEL(sys_call_table)), %l7; or %l7, %lo(C_LABEL(sys_call_table)), %l7; b linux_sparc_syscall; mov %psr, %l0;
+        sethi %hi(C_LABEL(sys_call_table)), %l7; \
+        or %l7, %lo(C_LABEL(sys_call_table)), %l7; \
+        b linux_sparc_syscall; \
+        rd %psr, %l0;
 
 /* Software trap for Sparc-netbsd system calls. */
 #define NETBSD_SYSCALL_TRAP \
-        sethi %hi(C_LABEL(sys_call_table)), %l7; or %l7, %lo(C_LABEL(sys_call_table)), %l7; b linux_sparc_syscall; mov %psr, %l0;
+        sethi %hi(C_LABEL(sys_call_table)), %l7; \
+        or %l7, %lo(C_LABEL(sys_call_table)), %l7; \
+        b linux_sparc_syscall; \
+        rd %psr, %l0;
 
 /* The Get Condition Codes software trap for userland. */
 #define GETCC_TRAP \
@@ -57,65 +72,31 @@
  * gets handled with another macro.
  */
 #define TRAP_ENTRY_INTERRUPT(int_level) \
-        mov int_level, %l3; b real_irq_entry; rd %psr, %l0; nop;
+        mov int_level, %l7; rd %psr, %l0; b real_irq_entry; rd %wim, %l3;
+
+/* This is for software interrupts, which currently (atleast on the sun4c)
+ * correspond to IRQ levels 1, 4, and 6.
+ */
+#define TRAP_ENTRY_SOFTINT(int_level) \
+        mov int_level, %l7; rd %psr, %l0; b soft_irq_entry; rd %wim, %l3;
 
 /* NMI's (Non Maskable Interrupts) are special, you can't keep them
  * from coming in, and basically if you get one, the shows over. ;(
+ * On the sun4c they are usually asyncronous memory errors, on the
+ * the sun4m they could be either due to mem errors or a software
+ * initiated interrupt from the prom/kern on an SMP box saying "I
+ * command you to do CPU tricks, read your mailbox for more info."
  */
 #define NMI_TRAP \
-        b linux_trap_nmi; mov %psr, %l0; nop; nop
-
-/* The above two macros are for generic traps. The following is made
- * especially for timer interrupts at IRQ level 14.
- */
-#define TRAP_ENTRY_TIMER \
-        rd %psr, %l0; b sparc_timer; nop; nop;
+        rd %wim, %l3; b linux_trap_nmi; mov %psr, %l0; nop;
 
-/* Trap entry code in entry.S needs the offsets into task_struct
- * to get at the thread_struct goodies during window craziness.
- *
- * NOTE: We need to keep these values under 0x3ff in order to do
- *       efficient load/stores in the window fill/spill handlers.
- *       See TRAP_WIN_CLEAN in entry.S for details.
+/* Window overflows/underflows are special and we need to try and be as
+ * efficient as possible here....
  */
+#define WINDOW_SPILL \
+        rd %psr, %l0; rd %wim, %l3; b spill_window_entry; andcc %l0, PSR_PS, %g0;
 
-/* First generic task_struct offsets */
-#define TASK_STATE        0x000
-#define TASK_PRI          0x008
-#define TASK_KSTACK_PG    0x250
-
-#define THREAD_UWINDOWS   0x3b8
-#define THREAD_WIM        0x3bc
-#define THREAD_W_SAVED    0x3c0
-#define THREAD_KSP        0x3c4
-#define THREAD_USP        0x3c8
-#define THREAD_PSR        0x3cc
-#define THREAD_PC         0x3d0
-#define THREAD_NPC        0x3d4
-#define THREAD_Y          0x3d8
-#define THREAD_REG_WINDOW 0x3e0
-
-/* More fun offset macros. These are for pt_regs. */
-
-#define PT_PSR    0x0
-#define PT_PC     0x4
-#define PT_NPC    0x8
-#define PT_Y      0xc
-#define PT_G0     0x10
-#define PT_G1     0x14
-#define PT_G2     0x18
-#define PT_G3     0x1c
-#define PT_G4     0x20
-#define PT_G5     0x24
-#define PT_G6     0x28
-#define PT_G7     0x2c
-#define PT_I0     0x30
-#define PT_I1     0x34
-#define PT_I2     0x38
-#define PT_I3     0x3c
-#define PT_I4     0x40
-#define PT_I5     0x44
-#define PT_I6     0x48
-#define PT_I7     0x4c
+#define WINDOW_FILL \
+        rd %psr, %l0; rd %wim, %l3; b fill_window_entry; andcc %l0, PSR_PS, %g0;
 
 #endif __SPARC_HEAD_H
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/idprom.h linux/include/asm-sparc/idprom.h
--- v1.3.43/linux/include/asm-sparc/idprom.h	Tue Jun 27 14:11:45 1995
+++ linux/include/asm-sparc/idprom.h	Sat Nov 25 04:31:49 1995
@@ -1,4 +1,5 @@
-/* idprom.h: Macros and defines for idprom routines
+/* $Id: idprom.h,v 1.5 1995/11/25 02:31:49 davem Exp $
+ * idprom.h: Macros and defines for idprom routines
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  */
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/io.h linux/include/asm-sparc/io.h
--- v1.3.43/linux/include/asm-sparc/io.h	Tue Jun 27 14:11:45 1995
+++ linux/include/asm-sparc/io.h	Sat Nov 25 04:31:51 1995
@@ -1,3 +1,4 @@
+/* $Id: io.h,v 1.8 1995/11/25 02:31:50 davem Exp $ */
 #ifndef __SPARC_IO_H
 #define __SPARC_IO_H
 
@@ -15,42 +16,42 @@
 
 extern inline unsigned long inb_local(unsigned long addr)
 {
-  return 0;
+	return 0;
 }
 
 extern inline void outb_local(unsigned char b, unsigned long addr)
 {
-  return;
+	return;
 }
 
 extern inline unsigned long inb(unsigned long addr)
 {
-  return 0;
+	return 0;
 }
 
 extern inline unsigned long inw(unsigned long addr)
 {
-  return 0;
+	return 0;
 }
 
 extern inline unsigned long inl(unsigned long addr)
 {
-  return 0;
+	return 0;
 }
 
 extern inline void outb(unsigned char b, unsigned long addr)
 {
-  return;
+	return;
 }
 
 extern inline void outw(unsigned short b, unsigned long addr)
 {
-  return;
+	return;
 }
 
 extern inline void outl(unsigned int b, unsigned long addr)
 {
-  return;
+	return;
 }
 
 /*
@@ -58,32 +59,32 @@
  */
 extern inline unsigned long readb(unsigned long addr)
 {
-  return 0;
+	return 0;
 }
 
 extern inline unsigned long readw(unsigned long addr)
 {
-  return 0;
+	return 0;
 }
 
 extern inline unsigned long readl(unsigned long addr)
 {
-  return 0;
+	return 0;
 }
 
 extern inline void writeb(unsigned short b, unsigned long addr)
 {
-  return;
+	return;
 }
 
 extern inline void writew(unsigned short b, unsigned long addr)
 {
-  return;
+	return;
 }
 
 extern inline void writel(unsigned int b, unsigned long addr)
 {
-  return;
+	return;
 }
 
 #define inb_p inb
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/ioctl.h linux/include/asm-sparc/ioctl.h
--- v1.3.43/linux/include/asm-sparc/ioctl.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-sparc/ioctl.h	Sat Nov 25 04:31:53 1995
@@ -0,0 +1,43 @@
+/* $Id: ioctl.h,v 1.4 1995/11/25 02:31:52 davem Exp $ */
+#ifndef _SPARC_IOCTL_H
+#define _SPARC_IOCTL_H
+
+#define _IOC_NRBITS      8
+#define _IOC_TYPEBITS    8
+#define _IOC_SIZEBITS    8
+#define _IOC_RESVBITS    5
+#define _IOC_DIRBITS     3
+
+#define _IOC_NRMASK      ((1 << _IOC_NRBITS)-1)
+#define _IOC_TYPEMASK    ((1 << _IOC_TYPEBITS)-1)
+#define _IOC_RESVMASK    ((1 << _IOC_RESVBITS)-1)
+#define _IOC_SIZEMASK    ((1 << _IOC_SIZEBITS)-1)
+#define _IOC_DIRMASK     ((1 << _IOC_DIRBITS)-1)
+
+#define _IOC_NRSHIFT     0
+#define _IOC_TYPESHIFT   (_IOC_NRSHIFT + _IOC_NRBITS)
+#define _IOC_SIZESHIFT   (_IOC_TYPESHIFT + _IOC_TYPEBITS)
+#define _IOC_RESVSHIFT   (_IOC_SIZESHIFT + _IOC_SIZEBITS)
+#define _IOC_DIRSHIFT    (_IOC_RESVSHIFT + _IOC_RESVBITS)
+
+#define _IOC_NONE        1U
+#define _IOC_READ        2U
+#define _IOC_WRITE       4U
+
+#define _IOC(dir,type,nr,size) \
+        (((dir)  << _IOC_DIRSHIFT) | \
+         ((type) << _IOC_TYPESHIFT) | \
+         ((nr)   << _IOC_NRSHIFT) | \
+         ((size) << _IOC_SIZESHIFT))
+
+#define _IO(type,nr)        _IOC(_IOC_NONE,(type),(nr),0)
+#define _IOR(type,nr,size)  _IOC(_IOC_READ,(type),(nr),sizeof(size))
+#define _IOW(type,nr,size)  _IOC(_IOC_WRITE,(type),(nr),sizeof(size))
+#define _IORW(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
+
+#define _IOC_DIR(nr)        (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
+#define _IOC_TYPE(nr)       (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
+#define _IOC_NR(nr)         (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
+#define _IOC_SIZE(nr)       (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)
+
+#endif /* !(_SPARC_IOCTL_H) */
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/ipsum.h linux/include/asm-sparc/ipsum.h
--- v1.3.43/linux/include/asm-sparc/ipsum.h	Tue Jun 27 14:11:45 1995
+++ linux/include/asm-sparc/ipsum.h	Thu Jan  1 02:00:00 1970
@@ -1,49 +0,0 @@
-#ifndef __SPARC_IPSUM_H
-#define __SPARC_IPSUM_H
-/*  ipsum.h:  IP/UDP/TCP checksum routines on the Sparc.
- *
- *  Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- */
-
-/*
- *      This routine computes a UDP checksum. 
- */
-extern inline unsigned short udp_check(struct udphdr *uh, int len, u32 saddr, u32 daddr)
-{
-        /* uhh.. eventually */
-        return 0;
-}
-
-/*
- *      This routine computes a TCP checksum. 
- */
-extern inline unsigned short tcp_check(struct tcphdr *th, int len, u32 saddr, u32 daddr)
-{     
-        /* uhh.. eventually */
-        return 0;
-}
-
-
-/*
- * This routine does all the checksum computations that don't
- * require anything special (like copying or special headers).
- */
-
-extern inline unsigned short ip_compute_csum(unsigned char * buff, int len)
-{
-        /* uhh.. eventually */
-        return 0;
-}
-
-/*
- *      This is a version of ip_compute_csum() optimized for IP headers, which
- *      always checksum on 4 octet boundaries.
- */
-
-static inline unsigned short ip_fast_csum(unsigned char * buff, int wlen)
-{
-        /* uhh.. eventually */
-        return 0;
-}
-
-#endif /* !(__SPARC_IPSUM_H) */
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/irq.h linux/include/asm-sparc/irq.h
--- v1.3.43/linux/include/asm-sparc/irq.h	Tue Jun 27 14:11:45 1995
+++ linux/include/asm-sparc/irq.h	Sat Nov 25 04:31:54 1995
@@ -1,19 +1,23 @@
-#ifndef _ALPHA_IRQ_H
-#define _ALPHA_IRQ_H
-
-/*
- *	linux/include/asm-sparc/irq.h
+/* $Id: irq.h,v 1.8 1995/11/25 02:31:54 davem Exp $
+ * irq.h: IRQ registers on the Sparc.
  *
- *	Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  */
 
+#ifndef _SPARC_IRQ_H
+#define _SPARC_IRQ_H
+
 #include <linux/linkage.h>
 
 #include <asm/system.h>     /* For NCPUS */
 
+#define NR_IRQS    15
+
 extern void disable_irq(unsigned int);
 extern void enable_irq(unsigned int);
 
+extern int request_fast_irq(unsigned int irq, void (*handler)(int, struct pt_regs *), unsigned long flags, const char *devname);
+
 /* On the sun4m, just like the timers, we have both per-cpu and master
  * interrupt registers.
  */
@@ -64,37 +68,5 @@
 #define SUN4M_INT_ENABLE  0x80000000
 #define SUN4M_INT_E14     0x00000080
 #define SUN4M_INT_E10     0x00080000
-
-#if 0 /* These aren't used on the Sparc (yet), but kept for
-       * future reference, they could come in handy.
-       */
-#define __STR(x) #x
-#define STR(x) __STR(x)
- 
-#define SAVE_ALL "xx"
-
-#define SAVE_MOST "yy"
-
-#define RESTORE_MOST "zz"
-
-#define ACK_FIRST(mask) "aa"
-
-#define ACK_SECOND(mask) "dummy"
-
-#define UNBLK_FIRST(mask) "dummy"
-
-#define UNBLK_SECOND(mask) "dummy"
-
-#define IRQ_NAME2(nr) nr##_interrupt(void)
-#define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr)
-#define FAST_IRQ_NAME(nr) IRQ_NAME2(fast_IRQ##nr)
-#define BAD_IRQ_NAME(nr) IRQ_NAME2(bad_IRQ##nr)
-	
-#define BUILD_IRQ(chip,nr,mask) \
-asmlinkage void IRQ_NAME(nr); \
-asmlinkage void FAST_IRQ_NAME(nr); \
-asmlinkage void BAD_IRQ_NAME(nr); \
-asm code comes here
-#endif
 
 #endif
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/kdebug.h linux/include/asm-sparc/kdebug.h
--- v1.3.43/linux/include/asm-sparc/kdebug.h	Tue Jun 27 14:11:45 1995
+++ linux/include/asm-sparc/kdebug.h	Sat Nov 25 04:31:56 1995
@@ -1,4 +1,5 @@
-/* kdebug.h:  Defines and definitions for debugging the Linux kernel
+/* $Id: kdebug.h,v 1.7 1995/11/25 02:31:55 davem Exp $
+ * kdebug.h:  Defines and definitions for debugging the Linux kernel
  *            under various kernel debuggers.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -13,7 +14,7 @@
  */
 
 #define DEBUG_FIRSTVADDR       0xffc00000
-#define DEBUG_LASTVADDR       LINUX_OPPROM_BEGVM
+#define DEBUG_LASTVADDR        LINUX_OPPROM_BEGVM
 
 /* Breakpoints are enter through trap table entry 126.  So in sparc assembly
  * if you want to drop into the debugger you do:
@@ -53,7 +54,6 @@
 /* Use this macro in C-code to enter the debugger. */
 extern __inline__ void sp_enter_debugger(void)
 {
-	printk("Entering debugger in file %s line %d\n", __FILE__, __LINE__);
 	__asm__ __volatile__("jmpl %0, %%o7\n\t"
 			     "nop\n\t" : :
 			     "r" (linux_dbvec) : "o7", "memory");
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/kgdb.h linux/include/asm-sparc/kgdb.h
--- v1.3.43/linux/include/asm-sparc/kgdb.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-sparc/kgdb.h	Sat Nov 25 04:31:58 1995
@@ -0,0 +1,90 @@
+/* $Id: kgdb.h,v 1.6 1995/11/25 02:31:57 davem Exp $
+ * kgdb.h: Defines and declarations for serial line source level
+ *         remote debugging of the Linux kernel using gdb.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+#ifndef _SPARC_KGDB_H
+#define _SPARC_KGDB_H
+
+#ifndef __ASSEMBLY__
+/* To init the kgdb engine. */
+extern void set_debug_traps(void);
+
+/* To enter the debugger explicitly. */
+extern void breakpoint(void);
+
+/* For convenience we define the format of a kgdb trap breakpoint
+ * frame here also.
+ */
+struct kgdb_frame {
+	unsigned long globals[8];
+	unsigned long outs[8];
+	unsigned long locals[8];
+	unsigned long ins[8];
+	unsigned long fpregs[32];
+	unsigned long y;
+	unsigned long psr;
+	unsigned long wim;
+	unsigned long tbr;
+	unsigned long pc;
+	unsigned long npc;
+	unsigned long fpsr;
+	unsigned long cpsr;
+};
+#endif /* !(__ASSEMBLY__) */
+
+/* Macros for assembly usage of the kgdb breakpoint frame. */
+#define KGDB_G0     0x000
+#define KGDB_G1     0x004
+#define KGDB_G2     0x008
+#define KGDB_G4     0x010
+#define KGDB_G6     0x018
+#define KGDB_I0     0x020
+#define KGDB_I2     0x028
+#define KGDB_I4     0x030
+#define KGDB_I6     0x038
+#define KGDB_Y      0x100
+#define KGDB_PSR    0x104
+#define KGDB_WIM    0x108
+#define KGDB_TBR    0x10c
+#define KGDB_PC     0x110
+#define KGDB_NPC    0x114
+
+#define SAVE_KGDB_GLOBALS(reg) \
+        std     %g0, [%reg + STACKFRAME_SZ + KGDB_G0]; \
+        std     %g2, [%reg + STACKFRAME_SZ + KGDB_G2]; \
+        std     %g4, [%reg + STACKFRAME_SZ + KGDB_G4]; \
+        std     %g6, [%reg + STACKFRAME_SZ + KGDB_G6];
+
+#define SAVE_KGDB_INS(reg) \
+        std     %i0, [%reg + STACKFRAME_SZ + KGDB_I0]; \
+        std     %i2, [%reg + STACKFRAME_SZ + KGDB_I2]; \
+        std     %i4, [%reg + STACKFRAME_SZ + KGDB_I4]; \
+        std     %i6, [%reg + STACKFRAME_SZ + KGDB_I6];
+
+#define SAVE_KGDB_SREGS(reg, reg_y, reg_psr, reg_wim, reg_tbr, reg_pc, reg_npc) \
+        st      %reg_y, [%reg + STACKFRAME_SZ + KGDB_Y]; \
+        st      %reg_psr, [%reg + STACKFRAME_SZ + KGDB_PSR]; \
+        st      %reg_wim, [%reg + STACKFRAME_SZ + KGDB_WIM]; \
+        st      %reg_tbr, [%reg + STACKFRAME_SZ + KGDB_TBR]; \
+        st      %reg_pc, [%reg + STACKFRAME_SZ + KGDB_PC]; \
+        st      %reg_npc, [%reg + STACKFRAME_SZ + KGDB_NPC];
+
+#define LOAD_KGDB_GLOBALS(reg) \
+        ld      [%reg + STACKFRAME_SZ + KGDB_G1], %g1; \
+        ldd     [%reg + STACKFRAME_SZ + KGDB_G2], %g2; \
+        ldd     [%reg + STACKFRAME_SZ + KGDB_G4], %g4; \
+        ldd     [%reg + STACKFRAME_SZ + KGDB_G6], %g6;
+
+#define LOAD_KGDB_INS(reg) \
+        ldd     [%reg + STACKFRAME_SZ + KGDB_I0], %i0; \
+        ldd     [%reg + STACKFRAME_SZ + KGDB_I2], %i2; \
+        ldd     [%reg + STACKFRAME_SZ + KGDB_I4], %i4; \
+        ldd     [%reg + STACKFRAME_SZ + KGDB_I6], %i6;
+
+#define LOAD_KGDB_SREGS(reg, reg_y_and_psr, reg_pc_and_npc) \
+        ldd     [%reg + STACKFRAME_SZ + KGDB_Y], %reg_y_and_psr; \
+        ldd     [%reg + STACKFRAME_SZ + KGDB_PC], %reg_pc_and_npc;
+
+#endif /* !(_SPARC_KGDB_H) */
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/machines.h linux/include/asm-sparc/machines.h
--- v1.3.43/linux/include/asm-sparc/machines.h	Tue Jun 27 14:11:45 1995
+++ linux/include/asm-sparc/machines.h	Sat Nov 25 04:31:59 1995
@@ -1,4 +1,5 @@
-/* machines.h:  Defines for taking apart the machine type value in the
+/* $Id: machines.h,v 1.4 1995/11/25 02:31:58 davem Exp $
+ * machines.h:  Defines for taking apart the machine type value in the
  *              idprom and determining the kind of machine we are on.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/mbus.h linux/include/asm-sparc/mbus.h
--- v1.3.43/linux/include/asm-sparc/mbus.h	Tue Jun 27 14:11:45 1995
+++ linux/include/asm-sparc/mbus.h	Sat Nov 25 04:32:01 1995
@@ -1,4 +1,5 @@
-/* mbus.h:  Various defines for MBUS modules.
+/* $Id: mbus.h,v 1.5 1995/11/25 02:32:00 davem Exp $
+ * mbus.h:  Various defines for MBUS modules.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  */
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/memerr.h linux/include/asm-sparc/memerr.h
--- v1.3.43/linux/include/asm-sparc/memerr.h	Tue Jun 27 14:11:45 1995
+++ linux/include/asm-sparc/memerr.h	Thu Jan  1 02:00:00 1970
@@ -1,32 +0,0 @@
-#ifndef _SPARC_MEMERR_H
-#define _SPARC_MEMERR_H
-
-/* memerr.h:  Bit fields in the asynchronous and synchronous memory error
- *            registers used to determine what 'type' of error has just
- *	      induced a trap.
- *
- * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
- */
-
-/* synchronous error register fields come first... */
-
-#define SYNCER_WRITE    0x8000        /* write error...                               */
-#define SYNCER_INVAL    0x0080        /* invalid page access was attempted            */
-#define SYNCER_PROT     0x0040        /* protection violation                         */
-#define SYNCER_TIMEOUT  0x0020        /* mem-bus access timeout (mem does not exist). */
-#define SYNCER_SBUSERR  0x0010        /* same as above, but for an SBUS access        */
-#define SYNCER_MEMERR   0x0008        /* Bus parity error, lose lose... panic time    */
-#define SYNCER_SZERR    0x0002        /* an attempted access was of BAD size, whoops  */
-#define SYNCER_WATCHDOG 0x0001        /* although we never see these, the prom will.. */
-
-/* asynchronous error bits go here */
-
-#define ASYNCER_WBINVAL   0x80        /* situation arose where the cache tried to write
-                                       * back a page for which the valid bit was not set
-				       * within the mmu. This is due to bad mm kernel bugs.
-				       */
-
-#define ASYNCER_TIMEOUT   0x20        /* mem-access bus timeout... */
-#define ASYNCER_DVMAERR   0x10        /* dvma transfer to/from memory bombed... */
-
-#endif /* _SPARC_MEMERR_H */
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/memreg.h linux/include/asm-sparc/memreg.h
--- v1.3.43/linux/include/asm-sparc/memreg.h	Tue Jun 27 14:11:45 1995
+++ linux/include/asm-sparc/memreg.h	Sat Nov 25 04:32:02 1995
@@ -1,3 +1,4 @@
+/* $Id: memreg.h,v 1.4 1995/11/25 02:32:02 davem Exp $ */
 #ifndef _SPARC_MEMREG_H
 #define _SPARC_MEMREG_H
 /* memreg.h:  Definitions of the values found in the synchronous
@@ -11,28 +12,25 @@
  * normal page faults.
  */
 
-#define SUN4C_SYNC_WDRESET   0x1  /* watchdog reset, only the prom sees this */
-#define SUN4C_SYNC_SIZE      0x2  /* bad access size? whuz this? */
-#define SUN4C_SYNC_PARITY    0x8  /* bad ram chips caused a parity error */
-#define SUN4C_SYNC_SBUS      0x10 /* the SBUS had some problems... */
-#define SUN4C_SYNC_NOMEM     0x20 /* translation pointed to non-existant ram */
-#define SUN4C_SYNC_PROT      0x40 /* access violated pte protection settings */
-#define SUN4C_SYNC_NPRESENT  0x80 /* pte said that page was not present */
+#define SUN4C_SYNC_WDRESET   0x0001  /* watchdog reset */
+#define SUN4C_SYNC_SIZE      0x0002  /* bad access size? whuz this? */
+#define SUN4C_SYNC_PARITY    0x0008  /* bad ram chips caused a parity error */
+#define SUN4C_SYNC_SBUS      0x0010  /* the SBUS had some problems... */
+#define SUN4C_SYNC_NOMEM     0x0020  /* translation to non-existant ram */
+#define SUN4C_SYNC_PROT      0x0040  /* access violated pte protections */
+#define SUN4C_SYNC_NPRESENT  0x0080  /* pte said that page was not present */
 #define SUN4C_SYNC_BADWRITE  0x8000  /* while writing something went bogus */
 
+#define SUN4C_SYNC_BOLIXED  \
+        (SUN4C_SYNC_WDRESET|SUN4C_SYNC_SIZE|SUN4C_SYNC_SBUS|SUN4C_SYNC_NOMEM)
+
 /* Now the asynchronous error codes, these are almost always produced
  * by the cache writing things back to memory and getting a bad translation.
  * Bad DVMA transactions can cause these faults too.
  */
 
-#define SUN4C_ASYNC_BADDVMA  0x10 /* error during DVMA access */
-#define SUN4C_ASYNC_NOMEM    0x20 /* write back pointed to bad phys addr */
-#define SUN4C_ASYNC_BADWB    0x80 /* write back points to non-present page */
-
-/* These are the values passed as the first arguement to the fault
- * entry c-code from the assembly entry points.
- */
-#define FAULT_ASYNC          0x0
-#define FAULT_SYNC           0x1
+#define SUN4C_ASYNC_BADDVMA 0x0010  /* error during DVMA access */
+#define SUN4C_ASYNC_NOMEM   0x0020  /* write back pointed to bad phys addr */
+#define SUN4C_ASYNC_BADWB   0x0080  /* write back points to non-present page */
 
 #endif /* !(_SPARC_MEMREG_H) */
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/mman.h linux/include/asm-sparc/mman.h
--- v1.3.43/linux/include/asm-sparc/mman.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-sparc/mman.h	Sat Nov 25 04:32:04 1995
@@ -0,0 +1,45 @@
+/* $Id: mman.h,v 1.5 1995/11/25 02:32:03 davem Exp $ */
+#ifndef __SPARC_MMAN_H__
+#define __SPARC_MMAN_H__
+
+/* SunOS'ified... */
+
+#define PROT_READ	0x1		/* page can be read */
+#define PROT_WRITE	0x2		/* page can be written */
+#define PROT_EXEC	0x4		/* page can be executed */
+#define PROT_NONE	0x0		/* page can not be accessed */
+
+#define MAP_SHARED	0x01		/* Share changes */
+#define MAP_PRIVATE	0x02		/* Changes are private */
+#define MAP_TYPE	0x0f		/* Mask for type of mapping */
+#define MAP_FIXED	0x10		/* Interpret addr exactly */
+#define MAP_ANONYMOUS	0x20		/* don't use a file */
+#define MAP_RENAME      MAP_ANONYMOUS   /* In SunOS terminology */
+#define MAP_NORESERVE   0x40            /* don't reserve swap pages */
+#define MAP_INHERIT     0x80            /* SunOS doesn't do this, but... */
+#define MAP_LOCKED      0x100           /* lock the mapping */
+#define _MAP_NEW        0x80000000      /* Binary compatability is fun... */
+
+#define MAP_GROWSDOWN	0x0100		/* stack-like segment */
+#define MAP_DENYWRITE	0x0800		/* ETXTBSY */
+#define MAP_EXECUTABLE	0x1000		/* mark it as a executable */
+
+#define MS_ASYNC	1		/* sync memory asynchronously */
+#define MS_INVALIDATE	2		/* invalidate the caches */
+#define MS_SYNC		4		/* synchronous memory sync */
+
+#define MCL_CURRENT     0x2000          /* lock all currently mapped pages */
+#define MCL_FUTURE      0x4000          /* lock all additions to address space */
+
+/* XXX Need to add flags to SunOS's mctl, mlockall, and madvise system
+ * XXX calls.
+ */
+
+/* SunOS sys_mctl() stuff... */
+#define MC_SYNC         1  /* Sync pages in memory with storage (usu. a file) */
+#define MC_LOCK         2  /* Lock pages into core ram, do not allow swapping of them */
+#define MC_UNLOCK       3  /* Unlock pages locked via previous mctl() with MC_LOCK arg */
+#define MC_LOCKAS       5  /* Lock an entire address space of the calling process */
+#define MC_UNLOCKAS     6  /* Unlock entire address space of calling process */
+
+#endif /* __SPARC_MMAN_H__ */
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/mostek.h linux/include/asm-sparc/mostek.h
--- v1.3.43/linux/include/asm-sparc/mostek.h	Tue Jun 27 14:11:45 1995
+++ linux/include/asm-sparc/mostek.h	Sat Nov 25 04:32:06 1995
@@ -1,4 +1,5 @@
-/* mostek.h:  Describes the various Mostek time of day clock registers.
+/* $Id: mostek.h,v 1.4 1995/11/25 02:32:05 davem Exp $
+ * mostek.h:  Describes the various Mostek time of day clock registers.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  */
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/mp.h linux/include/asm-sparc/mp.h
--- v1.3.43/linux/include/asm-sparc/mp.h	Tue Jun 27 14:11:45 1995
+++ linux/include/asm-sparc/mp.h	Sat Nov 25 04:32:08 1995
@@ -1,4 +1,5 @@
-/* mp.h:  Multiprocessing definitions for the Sparc.
+/* $Id: mp.h,v 1.2 1995/11/25 02:32:06 davem Exp $
+ * mp.h:  Multiprocessing definitions for the Sparc.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  */
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/mpmbox.h linux/include/asm-sparc/mpmbox.h
--- v1.3.43/linux/include/asm-sparc/mpmbox.h	Tue Jun 27 14:11:45 1995
+++ linux/include/asm-sparc/mpmbox.h	Sat Nov 25 04:32:10 1995
@@ -1,4 +1,5 @@
-/* mpmbox.h:  Interface and defines for the OpenProm mailbox
+/* $Id: mpmbox.h,v 1.3 1995/11/25 02:32:09 davem Exp $
+ * mpmbox.h:  Interface and defines for the OpenProm mailbox
  *               facilities for MP machines under Linux.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/mxcc.h linux/include/asm-sparc/mxcc.h
--- v1.3.43/linux/include/asm-sparc/mxcc.h	Tue Jun 27 14:11:45 1995
+++ linux/include/asm-sparc/mxcc.h	Sat Nov 25 04:32:12 1995
@@ -1,4 +1,5 @@
-/* mxcc.h:  Definitions of the Viking MXCC registers
+/* $Id: mxcc.h,v 1.2 1995/11/25 02:32:11 davem Exp $
+ * mxcc.h:  Definitions of the Viking MXCC registers
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  */
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/openprom.h linux/include/asm-sparc/openprom.h
--- v1.3.43/linux/include/asm-sparc/openprom.h	Tue Jun 27 14:11:45 1995
+++ linux/include/asm-sparc/openprom.h	Sat Nov 25 04:32:14 1995
@@ -1,3 +1,4 @@
+/* $Id: openprom.h,v 1.15 1995/11/25 02:32:13 davem Exp $ */
 #ifndef __SPARC_OPENPROM_H
 #define __SPARC_OPENPROM_H
 
@@ -7,297 +8,176 @@
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  */
 
-/* In the v0 interface of the openboot prom we could traverse a nice
- * little list structure to figure out where in vm-space the prom had
- * mapped itself and how much space it was taking up. In the v2 prom
- * interface we have to rely on 'magic' values. :-( Most of the machines
- * I have checked on have the prom mapped here all the time though.
- */
-
+/* Imperical constants... */
 #define KADB_DEBUGGER_BEGVM     0xffc00000    /* Where kern debugger is in virt-mem */
-
 #define	LINUX_OPPROM_BEGVM	0xffd00000
 #define	LINUX_OPPROM_ENDVM	0xfff00000
-
 #define	LINUX_OPPROM_MAGIC      0x10010407
 
 #ifndef __ASSEMBLY__
-/* The device functions structure for the v0 prom. Nice and neat, open,
- * close, read & write divvied up between net + block + char devices. We
- * also have a seek routine only usable for block devices. The divide
- * and conquer strategy of this struct becomes unnecessary for v2.
- *
- * V0 device names are limited to two characters, 'sd' for scsi-disk,
- * 'le' for local-ethernet, etc. Note that it is technically possible
- * to boot a kernel off of a tape drive and use the tape as the root
- * partition! In order to do this you have to have 'magic' formatted
- * tapes from Sun supposedly :-)
- */
-
+/* V0 prom device operations. */
 struct linux_dev_v0_funcs {
-	int	(*v0_devopen)(char *device_str);
-	int	(*v0_devclose)(int dev_desc);
-	int	(*v0_rdblkdev)(int dev_desc, int num_blks, int blk_st, char*  buf);
-	int	(*v0_wrblkdev)(int dev_desc, int num_blks, int blk_st, char*  buf);
-	int	(*v0_wrnetdev)(int dev_desc, int num_bytes, char*  buf);
-	int	(*v0_rdnetdev)(int dev_desc, int num_bytes, char*  buf);
-	int	(*v0_rdchardev)(int dev_desc, int num_bytes, int dummy, char*  buf);
-	int	(*v0_wrchardev)(int dev_desc, int num_bytes, int dummy, char*  buf);
-	int	(*v0_seekdev)(int dev_desc, long logical_offst, int from);
+	int (*v0_devopen)(char *device_str);
+	int (*v0_devclose)(int dev_desc);
+	int (*v0_rdblkdev)(int dev_desc, int num_blks, int blk_st, char *buf);
+	int (*v0_wrblkdev)(int dev_desc, int num_blks, int blk_st, char *buf);
+	int (*v0_wrnetdev)(int dev_desc, int num_bytes, char *buf);
+	int (*v0_rdnetdev)(int dev_desc, int num_bytes, char *buf);
+	int (*v0_rdchardev)(int dev_desc, int num_bytes, int dummy, char *buf);
+	int (*v0_wrchardev)(int dev_desc, int num_bytes, int dummy, char *buf);
+	int (*v0_seekdev)(int dev_desc, long logical_offst, int from);
 };
 
-/* The OpenBoot Prom device operations for version-2 interfaces are both
- * good and bad. They now allow you to address ANY device whatsoever
- * that is in the machine via these funny "device paths". They look like
- * this:
- *
- *   "/sbus/esp@0,0xf004002c/sd@3,1"
- *
- * You can basically reference any device on the machine this way, and
- * you pass this string to the v2 dev_ops. Producing these strings all
- * the time can be a pain in the rear after a while. Why v2 has memory
- * allocations in here are beyond me. Perhaps they figure that if you
- * are going to use only the prom's device drivers then your memory
- * management is either non-existent or pretty sad. :-)
- */
-
+/* V2 and later prom device operations. */
 struct linux_dev_v2_funcs {
-	int	(*v2_inst2pkg)(int d);	/* Convert ihandle to phandle */
-
-	/* "dumb" prom memory management routines, probably
-	 *  only safe to use for mapping device address spaces...
-         */
-
-	char* 	(*v2_dumb_mem_alloc)(char*  va, unsigned sz);
-	void	(*v2_dumb_mem_free)(char*  va, unsigned sz);
-
-	/* "dumb" mmap() munmap(), copy on write? what's that? */
-	char* 	(*v2_dumb_mmap)(char*  virta, int which_io, unsigned paddr, unsigned sz);
-	void	(*v2_dumb_munmap)(char*  virta, unsigned size);
-
-	/* Basic Operations, self-explanatory */
-	int	(*v2_dev_open)(char *devpath);
-	void	(*v2_dev_close)(int d);
-	int	(*v2_dev_read)(int d, char*  buf, int nbytes);
-	int	(*v2_dev_write)(int d, char*  buf, int nbytes);
-	void	(*v2_dev_seek)(int d, int hi, int lo);
+	int (*v2_inst2pkg)(int d);	/* Convert ihandle to phandle */
+	char * (*v2_dumb_mem_alloc)(char *va, unsigned sz);
+	void (*v2_dumb_mem_free)(char *va, unsigned sz);
+
+	/* To map devices into virtual I/O space. */
+	char * (*v2_dumb_mmap)(char *virta, int which_io, unsigned paddr, unsigned sz);
+	void (*v2_dumb_munmap)(char *virta, unsigned size);
+
+	int (*v2_dev_open)(char *devpath);
+	void (*v2_dev_close)(int d);
+	int (*v2_dev_read)(int d, char *buf, int nbytes);
+	int (*v2_dev_write)(int d, char *buf, int nbytes);
+	void (*v2_dev_seek)(int d, int hi, int lo);
 
 	/* Never issued (multistage load support) */
-	void	(*v2_wheee2)(void);
-	void	(*v2_wheee3)(void);
+	void (*v2_wheee2)(void);
+	void (*v2_wheee3)(void);
 };
 
-/* Just like the device ops, they slightly screwed up the mem-list
- * from v0 to v2. Probably easier on the prom-writer dude, sucks for
- * us though. See above comment about prom-vm mapped address space
- * magic numbers. :-(
- */
-
 struct linux_mlist_v0 {
-	struct	linux_mlist_v0 *theres_more;
-	char* 	start_adr;
+	struct linux_mlist_v0 *theres_more;
+	char *start_adr;
 	unsigned num_bytes;
 };
 
-/* The linux_mlist_v0's are pointed to by this structure. One list
- * per description. This means one list for total physical memory,
- * one for prom's address mapping, and one for physical mem left after
- * the kernel is loaded.
- */
-
 struct linux_mem_v0 {
-	struct	linux_mlist_v0 **v0_totphys;	/* all of physical */
-	struct	linux_mlist_v0 **v0_prommap;	/* addresses map'd by prom */
-	struct  linux_mlist_v0 **v0_available;	/* what phys. is left over */
+	struct linux_mlist_v0 **v0_totphys;
+	struct linux_mlist_v0 **v0_prommap;
+	struct linux_mlist_v0 **v0_available; /* What we can use */
 };
 
 /* Arguments sent to the kernel from the boot prompt. */
-
 struct linux_arguments_v0 {
-	char	*argv[8];		/* argv format for boot string */
-	char	args[100];		/* string space */
-	char	boot_dev[2];		/* e.g., "sd" for `b sd(...' */
-	int	boot_dev_ctrl;		/* controller # */
-	int	boot_dev_unit;		/* unit # */
-	int	dev_partition;		/* partition # */
-	char	*kernel_file_name;	/* kernel to boot, e.g., "vmunix" */
-	void	*aieee1;		/* give me some time  :> */
+	char *argv[8];
+	char args[100];
+	char boot_dev[2];
+	int boot_dev_ctrl;
+	int boot_dev_unit;
+	int dev_partition;
+	char *kernel_file_name;
+	void *aieee1;           /* XXX */
 };
 
-/* Prom version-2 gives us the raw strings for boot arguments and
- * boot device path. We also get the stdin and stdout file pseudo
- * descriptors for use with the mungy v2 device functions.
- */
+/* V2 and up boot things. */
 struct linux_bootargs_v2 {
-	char	**bootpath;		/* V2: Path to boot device */
-	char	**bootargs;		/* V2: Boot args */
-	int	*fd_stdin;		/* V2: Stdin descriptor */
-	int	*fd_stdout;		/* V2: Stdout descriptor */
+	char **bootpath;
+	char **bootargs;
+	int *fd_stdin;
+	int *fd_stdout;
 };
 
-/* This is the actual Prom Vector from which everything else is accessed
- * via struct and function pointers, etc. The prom when it loads us into
- * memory plops a pointer to this master structure in register %o0 before
- * it jumps to the kernel start address. I will update this soon to cover
- * the v3 semantics (cpu_start, cpu_stop and other SMP fun things). :-)
- */
-
+/* The top level PROM vector. */
 struct linux_romvec {
 	/* Version numbers. */
-	unsigned int	pv_magic_cookie;      /* Magic Mushroom... */
-	unsigned int	pv_romvers;	      /* iface vers (0, 2, or 3) */
-	unsigned int	pv_plugin_revision;   /* revision relative to above vers */
-	unsigned int	pv_printrev;	      /* print revision */
-
-	/* Version 0 memory descriptors (see below). */
-	struct linux_mem_v0 pv_v0mem;	      /* V0: Memory description lists. */
+	unsigned int pv_magic_cookie;
+	unsigned int pv_romvers;
+	unsigned int pv_plugin_revision;
+	unsigned int pv_printrev;
+
+	/* Version 0 memory descriptors. */
+	struct linux_mem_v0 pv_v0mem;
 
-	/* Node operations (see below). */
-	struct	linux_nodeops *pv_nodeops;   /* node functions, gets device data */
+	/* Node operations. */
+	struct linux_nodeops *pv_nodeops;
 
-	char	**pv_bootstr;		    /* Boot command, eg sd(0,0,0)vmunix */
+	char **pv_bootstr;
+	struct linux_dev_v0_funcs pv_v0devops;
 
-	struct	linux_dev_v0_funcs pv_v0devops; 	/* V0: device ops */
-
-	/*
-	 * PROMDEV_* cookies.  I fear these may vanish in lieu of fd0/fd1
-	 * (see below) in future PROMs, but for now they work fine.
-	 */
-	char	*pv_stdin;		/* stdin cookie */
-	char	*pv_stdout;		/* stdout cookie */
+	char *pv_stdin;
+	char *pv_stdout;
 #define	PROMDEV_KBD	0		/* input from keyboard */
 #define	PROMDEV_SCREEN	0		/* output to screen */
 #define	PROMDEV_TTYA	1		/* in/out to ttya */
 #define	PROMDEV_TTYB	2		/* in/out to ttyb */
 
 	/* Blocking getchar/putchar.  NOT REENTRANT! (grr) */
-	int	(*pv_getchar)(void);
-	void	(*pv_putchar)(int ch);
+	int (*pv_getchar)(void);
+	void (*pv_putchar)(int ch);
 
-	/* Non-blocking variants that return -1 on error. */
-	int	(*pv_nbgetchar)(void);
-	int	(*pv_nbputchar)(int ch);
+	/* Non-blocking variants. */
+	int (*pv_nbgetchar)(void);
+	int (*pv_nbputchar)(int ch);
 
-	/* Put counted string (can be very slow). */
-	void	(*pv_putstr)(char *str, int len);
+	void (*pv_putstr)(char *str, int len);
 
 	/* Miscellany. */
-	void	(*pv_reboot)(char *bootstr);
-	void	(*pv_printf)(const char *fmt, ...);
-	void	(*pv_abort)(void);	/* BREAK key abort */
-	int	*pv_ticks;		/* milliseconds since last reset */
-	void    (*pv_halt)(void);	/* End the show */
-	void	(**pv_synchook)(void);	/* "sync" ptr to function */
-
-	/*
-	 * This eval's a FORTH string.  Unfortunately, its interface
-	 * changed between V0 and V2, which gave us much pain.
-	 */
+	void (*pv_reboot)(char *bootstr);
+	void (*pv_printf)(const char *fmt, ...);
+	void (*pv_abort)(void);
+	int *pv_ticks;
+	void (*pv_halt)(void);
+	void (**pv_synchook)(void);
+
+	/* Evaluate a forth string, not different proto for V0 and V2->up. */
 	union {
-		void	(*v0_eval)(int len, char *str);
-		void	(*v2_eval)(char *str);
+		void (*v0_eval)(int len, char *str);
+		void (*v2_eval)(char *str);
 	} pv_fortheval;
 
-	struct	linux_arguments_v0 **pv_v0bootargs; /* V0: Boot args */
+	struct linux_arguments_v0 **pv_v0bootargs;
 
-	/* Extract Ethernet address from network device. */
-	unsigned int	(*pv_enaddr)(int d, char *enaddr);
+	/* Get ether address. */
+	unsigned int (*pv_enaddr)(int d, char *enaddr);
 
-	struct	linux_bootargs_v2 pv_v2bootargs;    /* V2: Boot args+std-in/out */
-	struct	linux_dev_v2_funcs pv_v2devops;	    /* V2: device operations */
+	struct linux_bootargs_v2 pv_v2bootargs;
+	struct linux_dev_v2_funcs pv_v2devops;
 
-	int	filler[15];
-
-	/*
-	 * The following is machine-dependent.
-	 *
-	 * The sun4c needs a PROM function to set a PMEG for another
-	 * context, so that the kernel can map itself in all contexts.
-	 * It is not possible simply to set the context register, because
-	 * contexts 1 through N may have invalid translations for the
-	 * current program counter.  The hardware has a mode in which
-	 * all memory references go to the PROM, so the PROM can do it
-	 * easily.
-	 */
-	void	(*pv_setctxt)(int ctxt, char*  va, int pmeg);
+	int filler[15];
+
+	/* This one is sun4c/sun4 only. */
+	void (*pv_setctxt)(int ctxt, char *va, int pmeg);
 
 	/* Prom version 3 Multiprocessor routines. This stuff is crazy.
 	 * No joke. Calling these when there is only one cpu probably
 	 * crashes the machine, have to test this. :-)
-         */
+	 */
 
 	/* v3_cpustart() will start the cpu 'whichcpu' in mmu-context
 	 * 'thiscontext' executing at address 'prog_counter'
-         */
-
+	 */
 	int (*v3_cpustart)(unsigned int whichcpu, int ctxtbl_ptr,
-			   int thiscontext, char* prog_counter);
+			   int thiscontext, char *prog_counter);
 
 	/* v3_cpustop() will cause cpu 'whichcpu' to stop executing
 	 * until a resume cpu call is made.
 	 */
-
 	int (*v3_cpustop)(unsigned int whichcpu);
 
 	/* v3_cpuidle() will idle cpu 'whichcpu' until a stop or
 	 * resume cpu call is made.
 	 */
-
 	int (*v3_cpuidle)(unsigned int whichcpu);
 
 	/* v3_cpuresume() will resume processor 'whichcpu' executing
 	 * starting with whatever 'pc' and 'npc' were left at the
 	 * last 'idle' or 'stop' call.
 	 */
-
 	int (*v3_cpuresume)(unsigned int whichcpu);
-
 };
 
-/*
- * In addition to the global stuff defined in the PROM vectors above,
- * the PROM has quite a collection of `nodes'.  A node is described by
- * an integer---these seem to be internal pointers, actually---and the
- * nodes are arranged into an N-ary tree.  Each node implements a fixed
- * set of functions, as described below.  The first two deal with the tree
- * structure, allowing traversals in either breadth- or depth-first fashion.
- * The rest deal with `properties'.
- *
- * A node property is simply a name/value pair.  The names are C strings
- * (NUL-terminated); the values are arbitrary byte strings (counted strings).
- * Many values are really just C strings.  Sometimes these are NUL-terminated,
- * sometimes not, depending on the the interface version; v0 seems to
- * terminate and v2 not.  Many others are simply integers stored as four
- * bytes in machine order: you just get them and go.  The third popular
- * format is an `address', which is made up of one or more sets of three
- * integers as defined below.
- *
- * One uses these functions to traverse the device tree to see what devices
- * this machine has attached to it.
- *
- * N.B.: for the `next' functions, next(0) = first, and next(last) = 0.
- * Whoever designed this part had good taste.  On the other hand, these
- * operation vectors are global, rather than per-node, yet the pointers
- * are not in the openprom vectors but rather found by indirection from
- * there.  So the taste balances out.
- */
-
+/* Routines for traversing the prom device tree. */
 struct linux_nodeops {
-	/*
-	 * Tree traversal.
-	 */
-	int	(*no_nextnode)(int node);	/* next(node) */
-	int	(*no_child)(int node);	/* first child */
-
-	/*
-	 * Property functions.  Proper use of getprop requires calling
-	 * proplen first to make sure it fits.  Kind of a pain, but no
-	 * doubt more convenient for the PROM coder.
-	 */
-	int	(*no_proplen)(int node, char*  name);
-	int	(*no_getprop)(int node, char*  name, char*  val);
-	int	(*no_setprop)(int node, char*  name, char*  val, int len);
-	char* 	(*no_nextprop)(int node, char*  name);
+	int (*no_nextnode)(int node);
+	int (*no_child)(int node);
+	int (*no_proplen)(int node, char *name);
+	int (*no_getprop)(int node, char *name, char *val);
+	int (*no_setprop)(int node, char *name, char *val, int len);
+	char * (*no_nextprop)(int node, char *name);
 };
 
 /* More fun PROM structures for device probing. */
@@ -306,23 +186,23 @@
 #define PROMINTR_MAX    15
 
 struct linux_prom_registers {
-  int which_io;         /* is this in OBIO space? */
-  char *phys_addr;      /* The physical address of this register */
-  int reg_size;         /* How many bytes does this register take up? */
+	int which_io;         /* is this in OBIO space? */
+	char *phys_addr;      /* The physical address of this register */
+	int reg_size;         /* How many bytes does this register take up? */
 };
 
 struct linux_prom_irqs {
-  int pri;    /* IRQ priority */
-  int vector; /* This is foobar, what does it do? */
+	int pri;    /* IRQ priority */
+	int vector; /* This is foobar, what does it do? */
 };
 
 /* Element of the "ranges" vector */
 struct linux_prom_ranges {
-	unsigned int	ot_child_space;
-	unsigned int	ot_child_base;		/* Bus feels this */
-	unsigned int	ot_parent_space;
-	unsigned int	ot_parent_base;		/* CPU looks from here */
-	unsigned int	or_size;
+	unsigned int ot_child_space;
+	unsigned int ot_child_base;		/* Bus feels this */
+	unsigned int ot_parent_space;
+	unsigned int ot_parent_base;		/* CPU looks from here */
+	unsigned int or_size;
 };
 
 #endif /* !(__ASSEMBLY__) */
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/oplib.h linux/include/asm-sparc/oplib.h
--- v1.3.43/linux/include/asm-sparc/oplib.h	Tue Jun 27 14:11:45 1995
+++ linux/include/asm-sparc/oplib.h	Sat Nov 25 04:32:16 1995
@@ -1,4 +1,5 @@
-/* oplib.h:  Describes the interface and available routines in the
+/* $Id: oplib.h,v 1.5 1995/11/25 02:32:14 davem Exp $
+ * oplib.h:  Describes the interface and available routines in the
  *           Linux Prom library.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -40,7 +41,7 @@
 /* You must call prom_init() before using any of the library services,
  * preferably as early as possible.  Pass it the romvec pointer.
  */
-extern int prom_init(struct linux_romvec *rom_ptr);
+extern void prom_init(struct linux_romvec *rom_ptr);
 
 /* Boot argument acquisition, returns the boot command line string. */
 extern char *prom_getbootargs(void);
@@ -148,6 +149,28 @@
 
 /* Prom's internal printf routine, don't use in kernel/boot code. */
 void prom_printf(char *fmt, ...);
+
+/* Query for input device type */
+
+enum prom_input_device {
+	PROMDEV_IKBD,			/* input from keyboard */
+	PROMDEV_ITTYA,			/* input from ttya */
+	PROMDEV_ITTYB,			/* input from ttyb */
+	PROMDEV_I_UNK,
+};
+
+extern enum prom_input_device prom_query_input_device(void);
+
+/* Query for output device type */
+
+enum prom_output_device {
+	PROMDEV_OSCREEN,		/* to screen */
+	PROMDEV_OTTYA,			/* to ttya */
+	PROMDEV_OTTYB,			/* to ttyb */
+	PROMDEV_O_UNK,
+};
+
+extern enum prom_output_device prom_query_output_device(void);
 
 /* Multiprocessor operations... */
 
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/page.h linux/include/asm-sparc/page.h
--- v1.3.43/linux/include/asm-sparc/page.h	Wed Nov  8 07:11:41 1995
+++ linux/include/asm-sparc/page.h	Sat Nov 25 04:32:17 1995
@@ -1,4 +1,5 @@
-/* page.h:  Various defines and such for MMU operations on the Sparc for
+/* $Id: page.h,v 1.22 1995/11/25 02:32:16 davem Exp $
+ * page.h:  Various defines and such for MMU operations on the Sparc for
  *          the Linux kernel.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -12,15 +13,17 @@
 #include <asm/head.h>       /* for KERNBASE */
 
 #define PAGE_SHIFT   12             /* This is the virtual page... */
-#define PAGE_OFFSET    KERNBASE
+#define PAGE_OFFSET  KERNBASE
 #define PAGE_SIZE    (1 << PAGE_SHIFT)
 
 /* to mask away the intra-page address bits */
-#define PAGE_MASK         (~(PAGE_SIZE-1))
+#define PAGE_MASK    (~(PAGE_SIZE-1))
 
 #ifdef __KERNEL__
 #ifndef __ASSEMBLY__
 
+#include <asm/processor.h>
+
 /* The following structure is used to hold the physical
  * memory configuration of the machine.  This is filled in
  * probe_memory() and is later used by mem_init() to set up
@@ -86,7 +89,12 @@
  */
 
 extern void (*invalidate)(void);
-extern void (*set_pte)(pte_t *ptep, pte_t entry);
+
+/* Certain architectures need to do special things when pte's
+ * within a page table are directly modified.  Thus, the following
+ * hook is made available.
+ */
+extern void (*set_pte)(pte_t *pteptr, pte_t pteval);
 
 /* to align the pointer to the (next) page boundary */
 #define PAGE_ALIGN(addr)  (((addr)+PAGE_SIZE-1)&PAGE_MASK)
@@ -94,9 +102,7 @@
 /* We now put the free page pool mapped contiguously in high memory above
  * the kernel.
  */
-#define MAP_NR(addr) ((((unsigned long)addr) - PAGE_OFFSET) >> PAGE_SHIFT)
-#define MAP_PAGE_RESERVED (1<<15)
-
+#define MAP_NR(addr) ((((unsigned long) (addr)) - PAGE_OFFSET) >> PAGE_SHIFT)
 
 #endif /* !(__ASSEMBLY__) */
 
@@ -249,17 +255,18 @@
 {
   register unsigned long entry;
 
-  __asm__ __volatile__("lduba [%1] %2, %0" : 
+  __asm__ __volatile__("\n\tlduba [%1] %2, %0\n\t" : 
 		       "=r" (entry) :
 		       "r" (addr), "i" (ASI_SEGMAP));
 
-  return (entry&0xff);
+  return entry;
 }
 
 extern __inline__ void put_segmap(unsigned long addr, unsigned long entry)
 {
 
-  __asm__ __volatile__("stba %1, [%0] %2" : : "r" (addr), "r" (entry&0xff),
+  __asm__ __volatile__("\n\tstba %1, [%0] %2\n\t" : :
+		       "r" (addr), "r" (entry),
 		       "i" (ASI_SEGMAP));
 
   return;
@@ -269,7 +276,7 @@
 {
   register unsigned long entry;
 
-  __asm__ __volatile__("lda [%1] %2, %0" : 
+  __asm__ __volatile__("\n\tlda [%1] %2, %0\n\t" : 
 		       "=r" (entry) :
 		       "r" (addr), "i" (ASI_PTE));
   return entry;
@@ -277,27 +284,33 @@
 
 extern __inline__ void put_pte(unsigned long addr, unsigned long entry)
 {
-  __asm__ __volatile__("sta %1, [%0] %2" : :
+  __asm__ __volatile__("\n\tsta %1, [%0] %2\n\t" : :
 		       "r" (addr), 
 		       "r" (entry), "i" (ASI_PTE));
 
   return;
 }
 
-extern void (*switch_to_context)(int);
+extern void (*switch_to_context)(void *tsk);
 
 extern __inline__ int get_context(void)
 {
   register int ctx;
 
-  __asm__ __volatile__("lduba [%1] %2, %0" :
+  __asm__ __volatile__("\n\tlduba [%1] %2, %0\n\t" :
 		       "=r" (ctx) :
 		       "r" (AC_CONTEXT), "i" (ASI_CONTROL));
 
   return ctx;
 }
 
-typedef unsigned short mem_map_t;
+extern __inline__ int set_context(int ctx)
+{
+  __asm__ __volatile__("\n\tstba %0, [%1] %2\n\t" : :
+		       "r" (ctx), "r" (AC_CONTEXT), "i" (ASI_CONTROL));
+
+  return ctx;
+}
 
 #endif /* __ASSEMBLY__ */
 
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/param.h linux/include/asm-sparc/param.h
--- v1.3.43/linux/include/asm-sparc/param.h	Thu Feb  2 08:42:35 1995
+++ linux/include/asm-sparc/param.h	Sat Nov 25 04:32:19 1995
@@ -1,3 +1,4 @@
+/* $Id: param.h,v 1.3 1995/11/25 02:32:18 davem Exp $ */
 #ifndef _ASMSPARC_PARAM_H
 #define _ASMSPARC_PARAM_H
 
@@ -5,7 +6,7 @@
 #define HZ 100
 #endif
 
-#define EXEC_PAGESIZE	4096
+#define EXEC_PAGESIZE	8192    /* Thanks for sun4's we carry baggage... */
 
 #ifndef NGROUPS
 #define NGROUPS		32
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/pconf.h linux/include/asm-sparc/pconf.h
--- v1.3.43/linux/include/asm-sparc/pconf.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-sparc/pconf.h	Sat Nov 25 04:32:21 1995
@@ -0,0 +1,25 @@
+/* $Id: pconf.h,v 1.2 1995/11/25 02:32:20 davem Exp $
+ * pconf.h: pathconf() and fpathconf() defines for SunOS
+ *          system call compatability.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef _SPARC_PCONF_H
+#define _SPARC_PCONF_H
+
+#include <linux/fs.h>
+#include <linux/limits.h>
+
+#define _PCONF_LINK       1 /* Max number of links to an object        */
+#define _PCONF_CANON      2 /* TTY input buffer line size              */
+#define _PCONF_INPUT      3 /* Biggest packet a tty can inbibe at once */
+#define _PCONF_NAME       4 /* Filename length max                     */
+#define _PCONF_PATH       5 /* Max size of a pathname                  */
+#define _PCONF_PIPE       6 /* Buffer size for a pipe                  */
+#define _PCONF_CHRESTRICT 7 /* Can only root chown files?              */
+#define _PCONF_NOTRUNC    8 /* Are pathnames truncated if too big?     */
+#define _PCONF_VDISABLE   9 /* Magic char to disable special tty chars */
+#define _PCONF_MAXPCONF   9
+
+#endif /* !(_SPARC_PCONF_H) */
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/pgtable.h linux/include/asm-sparc/pgtable.h
--- v1.3.43/linux/include/asm-sparc/pgtable.h	Tue Jun 27 14:11:45 1995
+++ linux/include/asm-sparc/pgtable.h	Sat Nov 25 04:32:23 1995
@@ -1,3 +1,4 @@
+/* $Id: pgtable.h,v 1.25 1995/11/25 02:32:22 davem Exp $ */
 #ifndef _SPARC_PGTABLE_H
 #define _SPARC_PGTABLE_H
 
@@ -11,9 +12,26 @@
 #include <asm/asi.h>
 #include <asm/pgtsun4c.h>
 #include <asm/pgtsrmmu.h>
+#include <asm/vac-ops.h>
+#include <asm/oplib.h>
 
 extern void load_mmu(void);
 
+/* mmu-specific process creation/cloning/etc hooks. */
+extern void (*mmu_exit_hook)(void *);
+extern void (*mmu_fork_hook)(void *, unsigned long);
+extern void (*mmu_release_hook)(void *);
+extern void (*mmu_flush_hook)(void *);
+extern void (*mmu_task_cacheflush)(void *);
+
+/* Routines for data transfer buffers. */
+extern char *(*mmu_lockarea)(char *, unsigned long);
+extern void  (*mmu_unlockarea)(char *, unsigned long);
+
+/* Routines for getting a dvma scsi buffer. */
+extern char *(*mmu_get_scsi_buffer)(char *, unsigned long);
+extern void  (*mmu_release_scsi_buffer)(char *, unsigned long);
+
 extern unsigned int pmd_shift;
 extern unsigned int pmd_size;
 extern unsigned int pmd_mask;
@@ -67,69 +85,38 @@
 /* Page table for 0-4MB for everybody, on the Sparc this
  * holds the same as on the i386.
  */
-extern unsigned long pg0[1024];
+extern pte_t pg0[1024];
 
 extern unsigned long ptr_in_current_pgd;
 
 /* the no. of pointers that fit on a page: this will go away */
 #define PTRS_PER_PAGE   (PAGE_SIZE/sizeof(void*))
 
-/* I define these like the i386 does because the check for text or data fault
- * is done at trap time by the low level handler. Maybe I can set these bits
- * then once determined. I leave them like this for now though.
- */
-#define __P000  PAGE_NONE
-#define __P001  PAGE_READONLY
-#define __P010  PAGE_COPY
-#define __P011  PAGE_COPY
-#define __P100  PAGE_READONLY
-#define __P101  PAGE_READONLY
-#define __P110  PAGE_COPY
-#define __P111  PAGE_COPY
-
-#define __S000	PAGE_NONE
-#define __S001	PAGE_READONLY
-#define __S010	PAGE_SHARED
-#define __S011	PAGE_SHARED
-#define __S100	PAGE_READONLY
-#define __S101	PAGE_READONLY
-#define __S110	PAGE_SHARED
-#define __S111	PAGE_SHARED
-
-/* Contexts on the Sparc. */
-#define MAX_CTXS 256
-#define NO_CTX   0xffff     /* In tss.context means task has no context currently */
-extern struct task_struct * ctx_tasks[MAX_CTXS];
-extern int ctx_tasks_last_frd;
+/* Here is a trick, since mmap.c need the initializer elements for
+ * protection_map[] to be constant at compile time, I set the following
+ * to all zeros.  I set it to the real values after I link in the
+ * appropriate MMU page table routines at boot time.
+ */
+#define __P000  __pgprot(0)
+#define __P001  __pgprot(0)
+#define __P010  __pgprot(0)
+#define __P011  __pgprot(0)
+#define __P100  __pgprot(0)
+#define __P101  __pgprot(0)
+#define __P110  __pgprot(0)
+#define __P111  __pgprot(0)
+
+#define __S000	__pgprot(0)
+#define __S001	__pgprot(0)
+#define __S010	__pgprot(0)
+#define __S011	__pgprot(0)
+#define __S100	__pgprot(0)
+#define __S101	__pgprot(0)
+#define __S110	__pgprot(0)
+#define __S111	__pgprot(0)
 
 extern int num_contexts;
 
-/* This routine allocates a new context.  And 'p' must not be 'current'! */
-extern inline int alloc_mmu_ctx(struct task_struct *p)
-{
-	int i;
-
-	for(i=0; i<num_contexts; i++)
-		if(ctx_tasks[i] == NULL) break;
-
-	if(i<num_contexts) {
-		p->tss.context = i;
-		ctx_tasks[i] = p;
-		return i;
-	}
-
-	/* Have to free one up */
-	ctx_tasks_last_frd++;
-	if(ctx_tasks_last_frd >= num_contexts) ctx_tasks_last_frd=0;
-	/* Right here is where we invalidate the user mappings that were
-	 * present.  TODO
-	 */
-        ctx_tasks[ctx_tasks_last_frd]->tss.context = NO_CTX;
-	ctx_tasks[ctx_tasks_last_frd] = p;
-	p->tss.context = ctx_tasks_last_frd;
-	return ctx_tasks_last_frd;
-}
-
 /*
  * BAD_PAGETABLE is used when we need a bogus page-table, while
  * BAD_PAGE is used for a bogus page.
@@ -142,7 +129,6 @@
 
 extern unsigned long __zero_page(void);
 
-
 #define BAD_PAGETABLE __bad_pagetable()
 #define BAD_PAGE __bad_page()
 #define ZERO_PAGE __zero_page()
@@ -153,7 +139,6 @@
 /* to align the pointer to a pointer address */
 #define PTR_MASK          (~(sizeof(void*)-1))
 
-
 #define SIZEOF_PTR_LOG2   2
 
 extern unsigned long (*pte_page)(pte_t);
@@ -168,15 +153,12 @@
  * all the pages since not all can be loaded at once in the mmu.
  *
  * Actually on the SRMMU things do work exactly like the i386, the
- * page tables live in real physical ram, no funky TLB buisness.  But
- * we have to do lots of flushing. And we have to update the root level
- * page table pointer for this process if it has a context.
+ * page tables live in real physical ram, no funky TLB buisness.
  */
 
 extern void (*sparc_update_rootmmu_dir)(struct task_struct *, pgd_t *pgdir);
 
-#define SET_PAGE_DIR(tsk,pgdir) \
-do { sparc_update_rootmmu_dir(tsk, pgdir); } while (0)
+#define SET_PAGE_DIR(tsk,pgdir) sparc_update_rootmmu_dir(tsk, pgdir)
        
 /* to find an entry in a page-table */
 #define PAGE_PTR(address) \
@@ -234,12 +216,12 @@
  */
 extern pte_t (*mk_pte)(unsigned long, pgprot_t);
 
-extern void (*pgd_set)(pgd_t *, pte_t *);
+extern void (*pgd_set)(pgd_t *, pmd_t *);
 
 extern pte_t (*pte_modify)(pte_t, pgprot_t);
 
 /* to find an entry in a page-table-directory */
-extern pgd_t * (*pgd_offset)(struct task_struct *, unsigned long);
+extern pgd_t * (*pgd_offset)(struct mm_struct *, unsigned long);
 
 /* Find an entry in the second-level page table.. */
 extern pmd_t * (*pmd_offset)(pgd_t *, unsigned long);
@@ -278,75 +260,45 @@
 
 extern void (*pgd_free)(pgd_t *);
 
-/* A page directory on the sun4c needs 16k, thus we request an order of
- * two.
- *
- * I need 16k for a sun4c page table, so I use kmalloc since kmalloc_init()
- * is called before pgd_alloc ever is (I think).
- */
-
 extern pgd_t * (*pgd_alloc)(void);
 
+/* Fault handler stuff... */
+#define FAULT_CODE_PROT     0x1
+#define FAULT_CODE_WRITE    0x2
+#define FAULT_CODE_USER     0x4
+extern int (*get_fault_info)(unsigned long *, unsigned long *, unsigned long);
+extern void (*update_mmu_cache)(struct vm_area_struct *vma, unsigned long address, pte_t pte);
+
 extern int invalid_segment;
 
-/* Sun4c specific routines.  They can stay inlined. */
-extern inline int alloc_sun4c_pseg(void)
-{
-	int oldseg, i;
-	/* First see if any are free already */
-	for(i=0; i<PSEG_ENTRIES; i++)
-		if(phys_seg_map[i]==PSEG_AVL) return i;
-
-	/* Uh-oh, gotta unallocate a TLB pseg */
-	oldseg=0;
-	for(i=0; i<PSEG_ENTRIES; i++) {
-		/* Can not touch PSEG_KERNEL and PSEG_RSV segmaps */
-		if(phys_seg_map[i]!=PSEG_USED) continue;
-		/* Ok, take a look at it's lifespan */
-		oldseg = (phys_seg_life[i]>oldseg) ? phys_seg_life[i] : oldseg;
-	}
-	phys_seg_life[oldseg]=PSEG_BORN;
-	return oldseg;
-}
+#define SWP_TYPE(entry) (((entry) >> 1) & 0x7f)
+#define SWP_OFFSET(entry) ((entry) >> 8)
+#define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8))
+
+struct ctx_list {
+	struct ctx_list *next;
+	struct ctx_list *prev;
+	unsigned char ctx_number;
+	struct task_struct *ctx_task; /* Who has it now, if not free */
+};
+
+extern struct ctx_list *ctx_list_pool;  /* Dynamically allocated */
+extern struct ctx_list ctx_free;        /* Head of free list */
+extern struct ctx_list ctx_used;        /* Head of used contexts list */
 
-/* Age all psegs except pseg_skip */
-extern inline void age_sun4c_psegs(int pseg_skip)
+extern inline void remove_from_ctx_list(struct ctx_list *entry)
 {
-	int i;
-
-	for(i=0; i<pseg_skip; i++) phys_seg_life[i]++;
-	i++;
-	while(i<PSEG_ENTRIES) phys_seg_life[i++]++;
-	return;
+	entry->next->prev = entry->prev;
+	entry->prev->next = entry->next;
 }
 
-/*
- * This is only ever called when the sun4c page fault routines run
- * so we can keep this here as the srmmu code will never get to it.
- */
-extern inline void update_mmu_cache(struct vm_area_struct * vma,
-	unsigned long address, pte_t pte)
+extern inline void add_to_ctx_list(struct ctx_list *head, struct ctx_list *entry)
 {
-  unsigned long clr_addr;
-  int segmap;
-
-  segmap = (int) get_segmap(address & SUN4C_REAL_PGDIR_MASK);
-  if(segmap == invalid_segment) {
-    segmap = alloc_sun4c_pseg();
-    put_segmap((address & SUN4C_REAL_PGDIR_MASK), segmap);
-    phys_seg_map[segmap] = PSEG_USED;
-
-    /* We got a segmap, clear all the pte's in it. */
-    for(clr_addr=(address&SUN4C_REAL_PGDIR_MASK); clr_addr<((address&SUN4C_REAL_PGDIR_MASK) + SUN4C_REAL_PGDIR_SIZE); 
-	clr_addr+=PAGE_SIZE)
-	    put_pte(clr_addr, 0);
-  }
-
-  /* Do aging */
-  age_sun4c_psegs(segmap);
-  put_pte((address & PAGE_MASK), pte_val(pte));
-  return;
-
+	entry->next = head;
+	(entry->prev = head->prev)->next = entry;
+	head->prev = entry;
 }
+#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)
 
 #endif /* !(_SPARC_PGTABLE_H) */
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/pgtsfmmu.h linux/include/asm-sparc/pgtsfmmu.h
--- v1.3.43/linux/include/asm-sparc/pgtsfmmu.h	Tue Jun 27 14:11:45 1995
+++ linux/include/asm-sparc/pgtsfmmu.h	Thu Jan  1 02:00:00 1970
@@ -1,29 +0,0 @@
-/* pgtsfmmu.h:  Spitfire V9 MMU support goes here.
- *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- */
-
-#ifndef _SPARC_PGTSFMMU_H
-#define _SPARC_PGTSFMMU_H
-
-/* Spitfire is four-level.... I think... It also has a seperate TLB for
- * data and instruction mappings.
- */
-#define SFMMU_PMD_SHIFT       16
-#define SFMMU_PMD_SIZE        (1UL << SFMMU_PMD_SHIFT)
-#define SFMMU_PMD_MASK        (~(SFMMU_PMD_SIZE-1))
-#define SFMMU_PMD_ALIGN(addr) (((addr)+SFMMU_PMD_SIZE-1)&SFMMU_PMD_MASK)
-
-#define SFMMU_PGDIR_SHIFT     19
-#define SFMMU_PGDIR_SIZE        (1UL << SFMMU_PGDIR_SHIFT)
-#define SFMMU_PGDIR_MASK        (~(SFMMU_PGDIR_SIZE-1))
-#define SFMMU_PGDIR_ALIGN(addr) (((addr)+SFMMU_PGDIR_SIZE-1)&SFMMU_PGDIR_MASK)
-
-#define SFMMU_PGMAP_SHIFT     22
-#define SFMMU_PGDIR_SIZE        (1UL << SFMMU_PGDIR_SHIFT)
-#define SFMMU_PGDIR_MASK        (~(SFMMU_PGDIR_SIZE-1))
-#define SFMMU_PGDIR_ALIGN(addr) (((addr)+SFMMU_PGDIR_SIZE-1)&SFMMU_PGDIR_MASK)
-
-
-#endif /* !(_SPARC_PGTSFMMU_H) */
-
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/pgtsrmmu.h linux/include/asm-sparc/pgtsrmmu.h
--- v1.3.43/linux/include/asm-sparc/pgtsrmmu.h	Tue Jun 27 14:11:45 1995
+++ linux/include/asm-sparc/pgtsrmmu.h	Sat Nov 25 04:32:25 1995
@@ -1,4 +1,5 @@
-/* pgtsrmmu.h:  SRMMU page table defines and code.
+/* $Id: pgtsrmmu.h,v 1.9 1995/11/25 02:32:24 davem Exp $
+ * pgtsrmmu.h:  SRMMU page table defines and code.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  */
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/pgtsun4.h linux/include/asm-sparc/pgtsun4.h
--- v1.3.43/linux/include/asm-sparc/pgtsun4.h	Tue Jun 27 14:11:45 1995
+++ linux/include/asm-sparc/pgtsun4.h	Sat Nov 25 04:32:27 1995
@@ -1,4 +1,5 @@
-/* pgtsun4.c:  Regular Sun4 MMU support goes in here.
+/* $Id: pgtsun4.h,v 1.2 1995/11/25 02:32:26 davem Exp $
+ * pgtsun4.c:  Regular Sun4 MMU support goes in here.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  */
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/pgtsun4c.h linux/include/asm-sparc/pgtsun4c.h
--- v1.3.43/linux/include/asm-sparc/pgtsun4c.h	Tue Jun 27 14:11:46 1995
+++ linux/include/asm-sparc/pgtsun4c.h	Sat Nov 25 04:32:29 1995
@@ -1,18 +1,11 @@
-/* pgtsun4c.h:  Sun4c specific pgtable.h defines and code.
+/* $Id: pgtsun4c.h,v 1.16 1995/11/25 02:32:28 davem Exp $
+ * pgtsun4c.h:  Sun4c specific pgtable.h defines and code.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  */
 #ifndef _SPARC_PGTSUN4C_H
 #define _SPARC_PGTSUN4C_H
 
-#define SUN4C_PAGE_TABLE_SIZE 0x100   /* 64 entries, 4 bytes a piece */
-
-/* NOTE:  Now we put the free page pool and the page structures
- *        up in high memory above the kernel image which itself
- *        starts at KERNBASE.  Also note PAGE_OFFSET in page.h
- *        This is just like what Linus does on the ALPHA.
- */
-
 /* PMD_SHIFT determines the size of the area a second-level page table can map */
 #define SUN4C_PMD_SHIFT       22
 #define SUN4C_PMD_SIZE        (1UL << SUN4C_PMD_SHIFT)
@@ -25,7 +18,7 @@
 #define SUN4C_PGDIR_MASK        (~(SUN4C_PGDIR_SIZE-1))
 #define SUN4C_PGDIR_ALIGN(addr) (((addr)+SUN4C_PGDIR_SIZE-1)&SUN4C_PGDIR_MASK)
 
-/* To make sun4c_paging_init() happy, I provide the following macros. */
+/* To represent how the sun4c mmu really lays things out. */
 #define SUN4C_REAL_PGDIR_SHIFT  18
 #define SUN4C_REAL_PGDIR_SIZE        (1UL << SUN4C_REAL_PGDIR_SHIFT)
 #define SUN4C_REAL_PGDIR_MASK        (~(SUN4C_REAL_PGDIR_SIZE-1))
@@ -34,92 +27,83 @@
 /*
  * To be efficient, and not have to worry about allocating such
  * a huge pgd, we make the kernel sun4c tables each hold 1024
- * entries and the pgd similarly.
+ * entries and the pgd similarly just like the i386 tables.
  */
-
 #define SUN4C_PTRS_PER_PTE    1024
 #define SUN4C_PTRS_PER_PMD    1
 #define SUN4C_PTRS_PER_PGD    1024
 
-/* Just any arbitrary offset to the start of the vmalloc VM area: the
- * current 8MB value just means that there will be a 8MB "hole" after the
- * physical memory until the kernel virtual memory starts.  That means that
- * any out-of-bounds memory accesses will hopefully be caught.
- * The vmalloc() routines leaves a hole of 4kB between each vmalloced
- * area for the same reason. ;)
+/* On the sun4c the physical ram limit is 128MB.  We set up our I/O
+ * translations at KERNBASE + 128MB for 1MB, then we begin the VMALLOC
+ * area, makes sense.  This works out to the value below.
  */
-#define SUN4C_VMALLOC_OFFSET  (8*1024*1024)
-#define SUN4C_VMALLOC_START ((high_memory + SUN4C_VMALLOC_OFFSET) & ~(SUN4C_VMALLOC_OFFSET-1))
+#define SUN4C_VMALLOC_START   (0xfe100000)
 
 /*
- * Sparc SUN4C page table fields. (for now, basically the same as the i386)
+ * Sparc SUN4C pte fields.
  */
-
 #define _SUN4C_PAGE_VALID     0x80000000   /* valid page */
 #define _SUN4C_PAGE_WRITE     0x40000000   /* can be written to */
+#define _SUN4C_PAGE_PRIV      0x20000000   /* bit to signify privileged page */
 #define _SUN4C_PAGE_USER      0x00000000   /* User page */
 #define _SUN4C_PAGE_NOCACHE   0x10000000   /* non-cacheable page */
-#define _SUN4C_PAGE_PRIV      0x20000000   /* bit to signify privileged page */
+#define _SUN4C_PAGE_IO        0x04000000   /* I/O page */
 #define _SUN4C_PAGE_REF       0x02000000   /* Page has been accessed/referenced */
 #define _SUN4C_PAGE_DIRTY     0x01000000   /* Page has been modified, is dirty */
 #define _SUN4C_PAGE_COW       0x00800000   /* COW page */
 
-/* Sparc sun4c mmu has only a writable bit. Thus if a page is valid it can be
- * read in a load, and executed as code automatically. Although, the memory 
- * fault hardware does make a distinction between data-read faults and 
- * insn-read faults which is determined by which trap happened plus magic
- * sync/async fault register values which must be checked in the actual
- * fault handler.
- */
-
-#define _SUN4C_PFN_MASK       0x0000ffff    /* just the page frame number */
-#define _SUN4C_MMU_MASK       0xffff0000    /* just the non-page pte bits */
-
-/* The following are for pgd/pmd's */
-#define _SUN4C_PGD_PFN_MASK   0x00ffffff    /* bits to hold page tables address */
-#define _SUN4C_PGD_MMU_MASK   0xff000000    /* pgd/pfn protection bits          */
-#define _SUN4C_PGD_PAGE_SHIFT 8             /* bits to shift to obtain address  */
-
-/* We want the swapper not to swap out page tables, thus dirty and writable
- * so that the kernel can change the entries as needed. Also valid for
- * obvious reasons.
- */
-#define _SUN4C_PAGE_TABLE     (_SUN4C_PAGE_VALID | _SUN4C_PAGE_WRITE | _SUN4C_PAGE_REF | _SUN4C_PAGE_DIRTY | _SUN4C_PAGE_PRIV | _SUN4C_PAGE_NOCACHE) /* No cache for now */
-#define _SUN4C_PAGE_CHG_MASK  (_SUN4C_PAGE_REF | _SUN4C_PAGE_DIRTY | _SUN4C_PFN_MASK)
-#define _SUN4C_PGD_CHG_MASK   (_SUN4C_PAGE_REF | _SUN4C_PAGE_DIRTY | _SUN4C_PGD_PFN_MASK)
-
-#define SUN4C_PAGE_NONE       __pgprot(_SUN4C_PAGE_VALID | _SUN4C_PAGE_REF)
-#define SUN4C_PAGE_SHARED     __pgprot(_SUN4C_PAGE_VALID | _SUN4C_PAGE_WRITE | _SUN4C_PAGE_REF)
-#define SUN4C_PAGE_COPY       __pgprot(_SUN4C_PAGE_VALID | _SUN4C_PAGE_REF | _SUN4C_PAGE_COW)
-#define SUN4C_PAGE_READONLY   __pgprot(_SUN4C_PAGE_VALID | _SUN4C_PAGE_REF)
-#define SUN4C_PAGE_KERNEL     __pgprot(_SUN4C_PAGE_VALID | _SUN4C_PAGE_WRITE | _SUN4C_PAGE_PRIV | _SUN4C_PAGE_REF | _SUN4C_PAGE_DIRTY | _SUN4C_PAGE_NOCACHE)
-#define SUN4C_PAGE_INVALID    __pgprot(0)
-
-#define _SUN4C_PAGE_NORMAL(x) __pgprot(_SUN4C_PAGE_VALID | _SUN4C_PAGE_REF | (x))
-
-/* The Sun4c mmu physical segment map allocation data structure.
- * For each physical segmap available on the mmu we have one entry,
- * 127 on the sun4c (except SparcStation 2's which seem to have 255)
- * and 512 on the sun4.  Each segmap can be in various stages of
- * allocation.
- */
-#define PSEG_ENTRIES  513     /* We allocate 513 entries for simplicity */
-extern unsigned int phys_seg_map[PSEG_ENTRIES];
-extern unsigned int phys_seg_life[PSEG_ENTRIES];
-
-/* for phys_seg_map entries */
-#define PSEG_AVL      0x0     /* Physical segment is available/free */
-#define PSEG_USED     0x1     /* A segmap currently being used */
-#define PSEG_RSV      0x2     /* This segmap is reserved (used for proms addr space) */
-#define PSEG_KERNEL   0x3     /* This is a kernel hard segment, cannot deallocate */
-
-/* for phys_seg_life entries */
-/* The idea is, every call to update_mmu_cache we increment all the life
- * counters.  When we re-allocate or allocate a physical segment for the
- * first time we set the phys_seg_life entry to PSEG_BORN.  Also, when we
- * fill a pte for a segment already loaded we *decrease* the life count
- * by two for that segment.  We'll see how this works.
- */
-#define PSEG_BORN     0x00     /* Just allocated */
+/* Note that the 'non-cacheable' bit is not set in any of these settings,
+ * you may want to turn it on for debugging the flushing of the virtual
+ * cache on the SUN4C MMU.
+ */
+#define _SUN4C_PAGE_CHG_MASK  (0xffff | _SUN4C_PAGE_REF | _SUN4C_PAGE_DIRTY)
+
+#define SUN4C_PAGE_NONE     __pgprot(_SUN4C_PAGE_VALID | _SUN4C_PAGE_PRIV | \
+				     _SUN4C_PAGE_REF)
+#define SUN4C_PAGE_SHARED   __pgprot(_SUN4C_PAGE_VALID | _SUN4C_PAGE_WRITE | \
+				     _SUN4C_PAGE_USER | _SUN4C_PAGE_REF)
+#define SUN4C_PAGE_COPY     __pgprot(_SUN4C_PAGE_VALID | _SUN4C_PAGE_USER | \
+				     _SUN4C_PAGE_REF | _SUN4C_PAGE_COW)
+#define SUN4C_PAGE_READONLY __pgprot(_SUN4C_PAGE_VALID | _SUN4C_PAGE_USER | \
+				     _SUN4C_PAGE_REF)
+#define SUN4C_PAGE_KERNEL   __pgprot(_SUN4C_PAGE_VALID | _SUN4C_PAGE_WRITE | \
+				     _SUN4C_PAGE_PRIV | _SUN4C_PAGE_DIRTY | \
+				     _SUN4C_PAGE_REF)
+#define SUN4C_PAGE_INVALID  __pgprot(0)
+
+struct pseg_list {
+	struct pseg_list *next;
+	struct pseg_list *prev;
+	struct pseg_list *ctx_next;
+	struct pseg_list *ctx_prev;
+	unsigned long vaddr;    /* Where the pseg is mapped. */
+	unsigned char context;  /* The context in which it is mapped. */
+	unsigned char pseg;     /* The pseg itself. */
+        unsigned ref_cnt:21,
+                 hardlock:1;
+};
+
+extern char *sun4c_lockarea(char *vaddr, unsigned long size);
+extern void sun4c_unlockarea(char *vaddr, unsigned long size);
+
+extern __inline__ unsigned long sun4c_get_synchronous_error(void)
+{
+	unsigned long sync_err;
+
+	__asm__ __volatile__("lda [%1] %2, %0\n\t" :
+			     "=r" (sync_err) :
+			     "r" (AC_SYNC_ERR), "i" (ASI_CONTROL));
+	return sync_err;
+}
+
+extern __inline__ unsigned long sun4c_get_synchronous_address(void)
+{
+	unsigned long sync_addr;
+
+	__asm__ __volatile__("lda [%1] %2, %0\n\t" :
+			     "=r" (sync_addr) :
+			     "r" (AC_SYNC_VA), "i" (ASI_CONTROL));
+	return sync_addr;
+}
 
 #endif /* !(_SPARC_PGTSUN4C_H) */
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/processor.h linux/include/asm-sparc/processor.h
--- v1.3.43/linux/include/asm-sparc/processor.h	Tue Jun 27 14:11:46 1995
+++ linux/include/asm-sparc/processor.h	Sat Nov 25 04:32:30 1995
@@ -1,4 +1,5 @@
-/* include/asm-sparc/processor.h
+/* $Id: processor.h,v 1.28 1995/11/25 02:32:30 davem Exp $
+ * include/asm-sparc/processor.h
  *
  * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
  */
@@ -6,9 +7,12 @@
 #ifndef __ASM_SPARC_PROCESSOR_H
 #define __ASM_SPARC_PROCESSOR_H
 
-#include <linux/sched.h>  /* For intr_count */
+#include <linux/string.h>
 
-#include <asm/ptrace.h>   /* For pt_regs declaration */
+#include <asm/psr.h>
+#include <asm/ptrace.h>
+#include <asm/head.h>
+#include <asm/signal.h>
 
 /*
  * Bus types
@@ -19,125 +23,89 @@
 #define MCA_bus__is_a_macro /* for versions in ksyms.c */
 
 /*
- * Write Protection works right in supervisor mode on the Sparc
+ * Write Protection works right in supervisor mode on the Sparc...
+ * And then there came the Swift module, which isn't so swift...
  */
-#if 0  /* Let's try this out ;) */
-#define wp_works_ok 1
-#define wp_works_ok__is_a_macro /* for versions in ksyms.c */
-#else
 extern char wp_works_ok;
-#endif
 
-/*
- * User space process size: 3GB. This is hardcoded into a few places,
- * so don't change it unless you know what you are doing.
- *
- * With the way identity mapping works on the sun4c, this is the best
- * value to use.
- *
- * This has to be looked into for a unified sun4c/sun4m task size.
- */
-#define TASK_SIZE	(0xC000000UL)
+/* Whee, this is STACK_TOP and the lowest kernel address too... */
+#define TASK_SIZE	(KERNBASE)
 
-/*
- * Size of io_bitmap in longwords: 32 is ports 0-0x3ff.
- */
-#define IO_BITMAP_SIZE	32
+/* The Sparc processor specific thread struct. */
+struct thread_struct {
+	unsigned long uwinmask __attribute__ ((aligned (8)));
 
-/* The first four entries here MUST be the first four. This allows me to
- * do %lo(offset) loads and stores in entry.S. See TRAP_WIN_CLEAN to see
- * why.
- */
+	/* For signal handling */
+	unsigned long sig_address __attribute__ ((aligned (8)));
+	unsigned long sig_desc;
+
+	/* Context switch saved kernel state. */
+	unsigned long ksp __attribute__ ((aligned (8)));
+	unsigned long kpc;
+	unsigned long kpsr;
+	unsigned long kwim;
+
+	/* A place to store user windows and stack pointers
+	 * when the stack needs inspection.
+	 */
+#define NSWINS 8
+	struct reg_window reg_window[NSWINS] __attribute__ ((aligned (8)));
+	unsigned long rwbuf_stkptrs[NSWINS] __attribute__ ((aligned (8)));
+	unsigned long w_saved;
 
-struct thread_struct {
-	unsigned long uwindows;       /* how many user windows are in the set */
-	unsigned long wim;            /* user's window invalid mask */
-	unsigned long w_saved;        /* how many windows saved in reg_window[] */
-	unsigned long ksp;            /* kernel stack pointer */
-	unsigned long usp;            /* user's sp, throw reg windows here */
-	unsigned long psr;            /* save for condition codes */
-	unsigned long pc;             /* program counter */
-	unsigned long npc;            /* next program counter */
-	unsigned long yreg;
-	unsigned long align;          /* to get 8-byte alignment  XXX  */
-	unsigned long reg_window[16];
+	/* Where our page table lives. */
 	unsigned long pgd_ptr;
-	int context;                  /* The context allocated to this thread */
 
-/* 8 local registers + 8 in registers * 24 register windows.
- * Most sparcs I know of only have 7 or 8 windows implemented,
- * we determine how many at boot time and store that value
- * in nwindows.
- */
-	unsigned long float_regs[64]; /* V8 and below have 32, V9 has 64 */
+	/* The context currently allocated to this process
+	 * or -1 if no context has been allocated to this
+	 * task yet.
+	 */
+	int context;
+
+	/* Floating point regs */
+	unsigned long   float_regs[64] __attribute__ ((aligned (8)));
+	unsigned long   fsr;
+	unsigned long   fpqdepth;
+	struct fpq {
+		unsigned long *insn_addr;
+		unsigned long insn;
+	} fpqueue[16];
+	struct sigstack sstk_info;
 };
 
-#define INIT_MMAP { &init_task, (PAGE_OFFSET), (0xff000000UL), \
-		    0x0 , VM_READ | VM_WRITE | VM_EXEC }
+#define INIT_MMAP { &init_mm, (0xf0000000UL), (0xffffffffUL), \
+		    __pgprot(0x0) , VM_READ | VM_WRITE | VM_EXEC }
 
 #define INIT_TSS  { \
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
-        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, \
-	(long) &swapper_pg_dir, -1,  \
-        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, \
+/* uwinmask, sig_address, sig_desc, ksp, kpc, kpsr, kwim */ \
+   0,        0,           0,        0,   0,   0,    0, \
+/* reg_window */  \
+{ { { 0, }, { 0, } }, }, \
+/* rwbuf_stkptrs */  \
+{ 0, 0, 0, 0, 0, 0, 0, 0, }, \
+/* w_saved, pgd_ptr,                context */  \
+   0,       (long) &swapper_pg_dir, -1, \
+/* FPU regs */   { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
+                   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
+                   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
+                   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, \
+/* FPU status, FPU qdepth, FPU queue */ \
+   0,          0,  { { 0, 0, }, }, \
+/* sstk_info */ \
+{ 0, 0, }, \
 }
 
-/* The thread_frame is what needs to be set up in certain circumstances
- * upon entry to a trap. It is also loaded sometimes during a window
- * spill if things don't go right (bad user stack pointer). In reality
- * it is not per-process per se, it just sits in the kernel stack while
- * the current process is in a handler then it is basically forgotten
- * about the next time flow control goes back to that process.
- */
-
-/* Sparc stack save area allocated for each save, not very exciting. */
-struct sparc_save_stack {
-  unsigned int locals[8];
-  unsigned int ins[8];
-  unsigned int padd[8];
-};
-
-/*
- * These are the "cli()" and "sti()" for software interrupts
- * They work by increasing/decreasing the "intr_count" value, 
- * and as such can be nested arbitrarily.
- */
-extern inline void start_bh_atomic(void)
+/* Return saved PC of a blocked thread. */
+extern inline unsigned long thread_saved_pc(struct thread_struct *t)
 {
-	__asm__ __volatile__("rd %%psr, %%g2\n\t"
-			     "wr %%g2, 0x20, %%psr\n\t"  /* disable traps */
-			     "ld %0,%%g3\n\t"
-			     "add %%g3,1,%%g3\n\t"
-			     "st %%g3,%0\n\t"
-			     "wr %%g2, 0x0, %%psr\n\t"   /* enable traps */
-			     : "=m" (intr_count)
-			     : : "g2", "g3", "memory");
-}
-
-extern inline void end_bh_atomic(void)
-{
-	__asm__ __volatile__("rd %%psr, %%g2\n\t"
-			     "wr %%g2, 0x20, %%psr\n\t"
-			     "ld %0,%%g3\n\t"
-			     "sub %%g3,1,%%g3\n\t"
-			     "st %%g3,%0\n\t"
-			     "wr %%g2, 0x0, %%psr\n\t"
-			     : "=m" (intr_count)
-			     : : "g2", "g3", "memory");
+	return ((struct pt_regs *)
+		((t->ksp&(~0xfff))+(0x1000-TRACEREG_SZ)))->pc;
 }
 
 /*
  * Do necessary setup to start up a newly executed thread.
  */
-static inline void start_thread(struct pt_regs * regs, unsigned long sp,
-				unsigned long fp)
-{
-  printk("start_thread called, halting..n");
-  halt();
-}
+extern void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp);
 
 #endif /* __ASM_SPARC_PROCESSOR_H */
 
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/psr.h linux/include/asm-sparc/psr.h
--- v1.3.43/linux/include/asm-sparc/psr.h	Tue Jun 27 14:11:46 1995
+++ linux/include/asm-sparc/psr.h	Sat Nov 25 04:32:32 1995
@@ -1,11 +1,12 @@
-/* psr.h: This file holds the macros for masking off various parts of
-          the processor status register on the Sparc. This is valid
-	  for Version 8. On the V9 this is renamed to the PSTATE
-	  register and its members are accessed as fields like
-	  PSTATE.PRIV for the current CPU privilege level.
-
-   Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
-*/
+/* $Id: psr.h,v 1.5 1995/11/25 02:32:31 davem Exp $
+ * psr.h: This file holds the macros for masking off various parts of
+ *        the processor status register on the Sparc. This is valid
+ *        for Version 8. On the V9 this is renamed to the PSTATE
+ *        register and its members are accessed as fields like
+ *        PSTATE.PRIV for the current CPU privilege level.
+ *
+ * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
+ */
 
 #ifndef __LINUX_SPARC_PSR_H
 #define __LINUX_SPARC_PSR_H
@@ -15,21 +16,12 @@
 #ifdef __LINUX_SPARC_V8
 
 /* The Sparc PSR fields are laid out as the following:
-
-    ------------------------------------------------------------------------
-    | impl  | vers  | icc   | resv  | EC | EF | PIL  | S | PS | ET |  CWP  |
-bits| 31-28 | 27-24 | 23-20 | 19-14 | 13 | 12 | 11-8 | 7 | 6  | 5  |  4-0  |
-    ------------------------------------------------------------------------
-
-   The PSR can only be directly be written/read by the privileged instructions
-   'rd' and 'wr'. Certain fields are changed as a side effect due to the 'Ticc',
-   'save', 'restore', and 'rett' instructions. Also the integer condition codes
-   'icc' are modified by various arithmetic instructions.
-
-   For example:  wr  %o2, or'd_bit_pattern, %psr
-                 rd  %psr, %o3
-
-*/
+ *
+ *  ------------------------------------------------------------------------
+ *  | impl  | vers  | icc   | resv  | EC | EF | PIL  | S | PS | ET |  CWP  |
+ *  | 31-28 | 27-24 | 23-20 | 19-14 | 13 | 12 | 11-8 | 7 | 6  | 5  |  4-0  |
+ *  ------------------------------------------------------------------------
+ */
 
 #define PSR_CWP     0x0000001f         /* current window pointer     */
 #define PSR_ET      0x00000020         /* enable traps field         */
@@ -87,18 +79,18 @@
 #ifdef __LINUX_SPARC_V9
 
 /* The information available in the %psr on the V8 is spread amongst
-   a whole bunch of registers on the V9. The main one being PSTATE.
-
-     --------------------------------------------------------
-     |  CLE  | TLE |  MM  | RED | PEF | AM | PRIV | IE | AG |
-bits |   9   |  8  |  7-6 |  5  |  4  |  3 |   2  |  1 |  0 |
-     --------------------------------------------------------
-
-   Writes and reads to PSTATE are done via 'wrpr' and 'rdpr' instructions.
-
-   For example:  wrpr %o2, or'd_bit_pattern, %pstate
-                 rdpr %pstate, %o3
-*/
+ * a whole bunch of registers on the V9. The main one being PSTATE.
+ *
+ *   --------------------------------------------------------
+ *   |  CLE  | TLE |  MM  | RED | PEF | AM | PRIV | IE | AG |
+ *   |   9   |  8  |  7-6 |  5  |  4  |  3 |   2  |  1 |  0 |
+ *   --------------------------------------------------------
+ *
+ * Writes and reads to PSTATE are done via 'wrpr' and 'rdpr' instructions.
+ *
+ * For example:  wrpr %o2, or'd_bit_pattern, %pstate
+ *               rdpr %pstate, %o3
+ */
 
 #define PSTATE_AG    0x001   /* Alternate Globals             */
 #define PSTATE_IE    0x002   /* Interrupt Enable              */
@@ -132,13 +124,13 @@
 }
 
 /* The Version Register holds vendor information for the chip:
-
-    ---------------------------------------------------------------------------
-    | manufacturer | implementation | mask | reserved | maxtl | resv | maxwin |
-bits|  63-48       |   47-32        | 31-24|   23-16  | 15-8  | 7-5  |  4-0   |
-    ---------------------------------------------------------------------------
-
-*/
+ *
+ *  ---------------------------------------------------------------------------
+ *  | manufacturer | implementation | mask | reserved | maxtl | resv | maxwin |
+ *  |  63-48       |   47-32        | 31-24|   23-16  | 15-8  | 7-5  |  4-0   |
+ *  ---------------------------------------------------------------------------
+ *
+ */
 
 #define VERS_MAXWIN  0x000000000000001f     /* 'nwindows' on this chip       */
 #define VERS_MAXTL   0x00000000000ff000     /* Maximum Trap-level supported  */
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/ptrace.h linux/include/asm-sparc/ptrace.h
--- v1.3.43/linux/include/asm-sparc/ptrace.h	Tue Jun 27 14:11:46 1995
+++ linux/include/asm-sparc/ptrace.h	Sat Nov 25 04:32:34 1995
@@ -1,29 +1,170 @@
+/* $Id: ptrace.h,v 1.14 1995/11/25 02:32:33 davem Exp $ */
 #ifndef _SPARC_PTRACE_H
 #define _SPARC_PTRACE_H
 
-/* I have not looked enough into how this should be done. Without playing
- * lots of tricks to optimize I think we need to save the whole register
- * window frame plus the floating-point registers. We'll see...
+#include <asm/psr.h>
+
+/* This struct defines the way the registers are stored on the 
+ * stack during a system call and basically all traps.
  */
 
-/* this struct defines the way the registers are stored on the 
-   stack during a system call. */
+#ifndef __ASSEMBLY__
 
 struct pt_regs {
-	unsigned long psr;   /* for condition codes */
-	unsigned long pc;    /* current and next program counter */
+	unsigned long psr;
+	unsigned long pc;
 	unsigned long npc;
 	unsigned long y;
-	/* not sure yet whether all regs are necessary
-	 * but this is how it is traditionally done on the sparc.
-	 */
 	unsigned long u_regs[16]; /* globals and ins */
 };
 
+#define UREG_G0        0
+#define UREG_G1        1
+#define UREG_G2        2
+#define UREG_G3        3
+#define UREG_G4        4
+#define UREG_G5        5
+#define UREG_G6        6
+#define UREG_G7        7
+#define UREG_I0        8
+#define UREG_I1        9
+#define UREG_I2        10
+#define UREG_I3        11
+#define UREG_I4        12
+#define UREG_I5        13
+#define UREG_I6        14
+#define UREG_I7        15
+#define UREG_WIM       UREG_G0
+#define UREG_FP        UREG_I6
+#define UREG_RETPC     UREG_I7
+
+/* A register window */
+struct reg_window {
+	unsigned long locals[8];
+	unsigned long ins[8];
+};
+
+
+/* A Sparc stack frame */
+struct sparc_stackf {
+	unsigned long locals[8];
+        unsigned long ins[6];
+	struct sparc_stackf *fp;
+	unsigned long callers_pc;
+	char *structptr;
+	unsigned long xargs[6];
+	unsigned long xxargs[1];
+};	
+
+#define TRACEREG_SZ   sizeof(struct pt_regs)
+#define STACKFRAME_SZ sizeof(struct sparc_stackf)
+#define REGWIN_SZ     sizeof(struct reg_window)
+
 #ifdef __KERNEL__
-/* if previous supervisor is 0, came from user */
-#define user_mode(regs) (0x0)
+#define user_mode(regs) (!((regs)->psr & PSR_PS))
+#define instruction_pointer(regs) ((regs)->pc)
 extern void show_regs(struct pt_regs *);
 #endif
 
+#else /* __ASSEMBLY__ */
+/* For assembly code. */
+#define TRACEREG_SZ       0x50
+#define STACKFRAME_SZ     0x60
+#define REGWIN_SZ         0x40
 #endif
+
+/* First generic task_struct offsets. sizeof(task_struct)=1536 */
+#define TASK_STATE        0x000
+#define TASK_PRIORITY     0x008
+#define TASK_SIGNAL       0x00c
+#define TASK_BLOCKED      0x010
+#define TASK_FLAGS        0x014
+#define TASK_SAVED_KSTACK 0x054
+#define TASK_KSTACK_PG    0x058
+
+/* Thread stuff. */
+#define THREAD_UMASK      0x210
+#define THREAD_SADDR      0x218
+#define THREAD_SDESC      0x21c
+#define THREAD_KSP        0x220
+#define THREAD_KPC        0x224
+#define THREAD_KPSR       0x228
+#define THREAD_KWIM       0x22c
+#define THREAD_REG_WINDOW 0x230
+#define THREAD_STACK_PTRS 0x430
+#define THREAD_W_SAVED    0x450
+#define THREAD_PGD_PTR    0x454
+#define THREAD_CONTEXT    0x458
+#define THREAD_FLOAT_REGS 0x460
+#define THREAD_FSR        0x560
+#define THREAD_SIGSTK     0x5e8
+
+/* These are for pt_regs. */
+#define PT_PSR    0x0
+#define PT_PC     0x4
+#define PT_NPC    0x8
+#define PT_Y      0xc
+#define PT_G0     0x10
+#define PT_WIM    PT_G0
+#define PT_G1     0x14
+#define PT_G2     0x18
+#define PT_G3     0x1c
+#define PT_G4     0x20
+#define PT_G5     0x24
+#define PT_G6     0x28
+#define PT_G7     0x2c
+#define PT_I0     0x30
+#define PT_I1     0x34
+#define PT_I2     0x38
+#define PT_I3     0x3c
+#define PT_I4     0x40
+#define PT_I5     0x44
+#define PT_I6     0x48
+#define PT_FP     PT_I6
+#define PT_I7     0x4c
+
+/* Reg_window offsets */
+#define RW_L0     0x00
+#define RW_L1     0x04
+#define RW_L2     0x08
+#define RW_L3     0x0c
+#define RW_L4     0x10
+#define RW_L5     0x14
+#define RW_L6     0x18
+#define RW_L7     0x1c
+#define RW_I0     0x20
+#define RW_I1     0x24
+#define RW_I2     0x28
+#define RW_I3     0x2c
+#define RW_I4     0x30
+#define RW_I5     0x34
+#define RW_I6     0x38
+#define RW_I7     0x3c
+
+/* Stack_frame offsets */
+#define SF_L0     0x00
+#define SF_L1     0x04
+#define SF_L2     0x08
+#define SF_L3     0x0c
+#define SF_L4     0x10
+#define SF_L5     0x14
+#define SF_L6     0x18
+#define SF_L7     0x1c
+#define SF_I0     0x20
+#define SF_I1     0x24
+#define SF_I2     0x28
+#define SF_I3     0x2c
+#define SF_I4     0x30
+#define SF_I5     0x34
+#define SF_FP     0x38
+#define SF_PC     0x3c
+#define SF_RETP   0x40
+#define SF_XARG0  0x44
+#define SF_XARG1  0x48
+#define SF_XARG2  0x4c
+#define SF_XARG3  0x50
+#define SF_XARG4  0x54
+#define SF_XARG5  0x58
+#define SF_XXARG  0x5c
+
+#endif /* !(_SPARC_PTRACE_H) */
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/resource.h linux/include/asm-sparc/resource.h
--- v1.3.43/linux/include/asm-sparc/resource.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-sparc/resource.h	Sat Nov 25 04:32:35 1995
@@ -0,0 +1,38 @@
+/* $Id: resource.h,v 1.5 1995/11/25 02:32:35 davem Exp $
+ * resource.h: Resource definitions.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef _SPARC_RESOURCE_H
+#define _SPARC_RESOURCE_H
+
+/*
+ * Resource limits
+ */
+
+#define RLIMIT_CPU	0		/* CPU time in ms */
+#define RLIMIT_FSIZE	1		/* Maximum filesize */
+#define RLIMIT_DATA	2		/* max data size */
+#define RLIMIT_STACK	3		/* max stack size */
+#define RLIMIT_CORE	4		/* max core file size */
+#define RLIMIT_RSS	5		/* max resident set size */
+#define RLIMIT_NOFILE	6		/* max number of open files */
+#define RLIMIT_NPROC	7		/* max number of processes */
+#define RLIMIT_MEMLOCK  8               /* max locked-in-memory address space */
+#define RLIM_NLIMITS	9
+
+#ifdef __KERNEL__
+
+#define INIT_RLIMITS							\
+{									\
+    {LONG_MAX, LONG_MAX}, {LONG_MAX, LONG_MAX},				\
+    {LONG_MAX, LONG_MAX}, {_STK_LIM, _STK_LIM},				\
+    {       0, LONG_MAX}, {LONG_MAX, LONG_MAX},				\
+    {MAX_TASKS_PER_USER, MAX_TASKS_PER_USER}, {NR_OPEN, NR_OPEN},	\
+    {LONG_MAX, LONG_MAX},                                               \
+}
+
+#endif /* __KERNEL__ */
+
+#endif /* !(_SPARC_RESOURCE_H) */
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/ross.h linux/include/asm-sparc/ross.h
--- v1.3.43/linux/include/asm-sparc/ross.h	Tue Jun 27 14:11:46 1995
+++ linux/include/asm-sparc/ross.h	Sat Nov 25 04:32:38 1995
@@ -1,4 +1,5 @@
-/* ross.h: Ross module specific definitions and defines.
+/* $Id: ross.h,v 1.3 1995/11/25 02:32:37 davem Exp $
+ * ross.h: Ross module specific definitions and defines.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  */
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/sbus.h linux/include/asm-sparc/sbus.h
--- v1.3.43/linux/include/asm-sparc/sbus.h	Tue Jun 27 14:11:46 1995
+++ linux/include/asm-sparc/sbus.h	Sat Nov 25 04:32:39 1995
@@ -1,4 +1,5 @@
-/* sbus.h:  Defines for the Sun SBus.
+/* $Id: sbus.h,v 1.8 1995/11/25 02:32:38 davem Exp $
+ * sbus.h:  Defines for the Sun SBus.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  */
@@ -6,7 +7,7 @@
 #ifndef _SPARC_SBUS_H
 #define _SPARC_SBUS_H
 
-#include <asm/openprom.h>  /* For linux_prom_registers and linux_prom_irqs */
+#include <asm/oplib.h>
 
 /* We scan which devices are on the SBus using the PROM node device
  * tree.  SBus devices are described in two different ways.  You can
@@ -37,21 +38,20 @@
   return (unsigned long) (((dev_addr)-SUN_SBUS_BVADDR)&SBUS_OFF_MASK);
 }
 
-/* Handy macro */
-#define STRUCT_ALIGN(addr) ((addr+7)&(~7))
+struct linux_sbus;
 
-/* Linus SBUS device tables */
+/* Linux SBUS device tables */
 struct linux_sbus_device {
   struct linux_sbus_device *next;      /* next device on this SBus or null */
+  struct linux_sbus_device *child;     /* For ledma and espdma on sun4m */
+  struct linux_sbus *my_bus;           /* Back ptr to sbus */
   int prom_node;                       /* PROM device tree node for this device */
-  char *prom_name;                     /* PROM device name */
-  char *linux_name;                    /* Name used internally by Linux */
+  char prom_name[64];                  /* PROM device name */
+  char linux_name[64];                 /* Name used internally by Linux */
 
-  /* device register addresses */
   struct linux_prom_registers reg_addrs[PROMREG_MAX];
   int num_registers;
 
-  /* List of IRQ's this device uses. */
   struct linux_prom_irqs irqs[PROMINTR_MAX];
   int num_irqs;
 
@@ -59,18 +59,32 @@
   unsigned long sbus_vaddrs[PROMVADDR_MAX];
   unsigned long num_vaddrs;
   unsigned long offset;                /* Offset given by PROM */
-  int slot;                            /* Device slot number */
+  int slot;
 };
 
-/* This struct describes the SBus-es found on this machine. */
+/* This struct describes the SBus(s) found on this machine. */
 struct linux_sbus {
   struct linux_sbus *next;             /* next SBus, if more than one SBus */
   struct linux_sbus_device *devices;   /* Link to devices on this SBus */
   int prom_node;                       /* PROM device tree node for this SBus */
-  char *prom_name;                     /* Usually "sbus" */
-  int clock_freq;                 /* Speed of this SBus */
+  char prom_name[64];                  /* Usually "sbus" */
+  int clock_freq;
 };
 
-extern struct linux_sbus Linux_SBus;
+extern struct linux_sbus *SBus_chain;
+
+extern inline int
+sbus_is_slave(struct linux_sbus_device *dev)
+{
+	/* Have to write this for sun4c's */
+	return 0;
+}
+
+/* Device probing routines could find these handy */
+#define for_each_sbus(bus) \
+        for((bus) = SBus_chain; (bus); (bus)=(bus)->next)
+
+#define for_each_sbusdev(device, bus) \
+        for((device) = (bus)->devices; (device); (device)=(device)->next)
 
 #endif /* !(_SPARC_SBUS_H) */
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/segment.h linux/include/asm-sparc/segment.h
--- v1.3.43/linux/include/asm-sparc/segment.h	Tue Jun 27 14:11:46 1995
+++ linux/include/asm-sparc/segment.h	Sat Nov 25 04:32:41 1995
@@ -1,15 +1,68 @@
+/* $Id: segment.h,v 1.6 1995/11/25 02:32:40 davem Exp $ */
 #ifndef _ASM_SEGMENT_H
 #define _ASM_SEGMENT_H
 
-#define KERNEL_CS   0x0
-#define KERNEL_DS   0x0
-
-#define USER_CS     0x1
-#define USER_DS     0x1
+/* Sparc is not segmented, these are just place holders. */
+#define KERNEL_DS   0
+#define USER_DS     1
 
 #include <linux/string.h>
 #include <asm/vac-ops.h>
 
+#ifndef __ASSEMBLY__
+
+/*
+ * Uh, these should become the main single-value transfer routines..
+ * They automatically use the right size if we just have the right
+ * pointer type..
+ */
+#define put_user(x,ptr) __put_user((unsigned long)(x),(ptr),sizeof(*(ptr)))
+#define get_user(ptr) ((__typeof__(*(ptr)))__get_user((ptr),sizeof(*(ptr))))
+
+/*
+ * This is a silly but good way to make sure that
+ * the __put_user function is indeed always optimized,
+ * and that we use the correct sizes..
+ */
+extern int bad_user_access_length(void);
+
+/* I should make this use unaligned transfers etc.. */
+static inline void __put_user(unsigned long x, void * y, int size)
+{
+	switch (size) {
+		case 1:
+			*(char *) y = x;
+			break;
+		case 2:
+			*(short *) y = x;
+			break;
+		case 4:
+			*(int *) y = x;
+			break;
+		default:
+			bad_user_access_length();
+	}
+}
+
+/* I should make this use unaligned transfers etc.. */
+static inline unsigned long __get_user(const void * y, int size)
+{
+	switch (size) {
+		case 1:
+			return *(unsigned char *) y;
+		case 2:
+			return *(unsigned short *) y;
+		case 4:
+			return *(unsigned int *) y;
+		default:
+			return bad_user_access_length();
+	}
+}
+
+/*
+ * Deprecated routines
+ */
+
 static inline unsigned char get_user_byte(const char * addr)
 {
 	return *addr;
@@ -31,13 +84,6 @@
 
 #define get_fs_long(addr) get_user_long((int *)(addr))
 
-static inline unsigned long get_user_quad(const long *addr)
-{
-	return *addr;
-}
-
-#define get_fs_quad(addr) get_user_quad((long *)(addr))
-
 static inline void put_user_byte(char val,char *addr)
 {
 	*addr = val;
@@ -59,33 +105,27 @@
 
 #define put_fs_long(x,addr) put_user_long((x),(int *)(addr))
 
-static inline void put_user_quad(unsigned long val,long * addr)
-{
-	*addr = val;
-}
-
-#define put_fs_quad(x,addr) put_user_quad((x),(long *)(addr))
-
 #define memcpy_fromfs(to, from, n) memcpy((to),(from),(n))
 
 #define memcpy_tofs(to, from, n) memcpy((to),(from),(n))
 
+extern int current_user_segment;
+
 static inline unsigned long get_fs(void)
 {
-	return 0;
+	return current_user_segment;
 }
 
 static inline unsigned long get_ds(void)
 {
-	return 0;
+	return KERNEL_DS;
 }
 
 static inline void set_fs(unsigned long val)
 {
-  unsigned long foo;
-  foo = val;
-
-  return;
+	current_user_segment = val;
 }
+
+#endif  /* __ASSEMBLY__ */
 
 #endif /* _ASM_SEGMENT_H */
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/shmparam.h linux/include/asm-sparc/shmparam.h
--- v1.3.43/linux/include/asm-sparc/shmparam.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-sparc/shmparam.h	Sat Nov 25 04:32:43 1995
@@ -0,0 +1,45 @@
+/* $Id: shmparam.h,v 1.3 1995/11/25 02:32:42 davem Exp $ */
+#ifndef _ASMSPARC_SHMPARAM_H
+#define _ASMSPARC_SHMPARAM_H
+
+/* address range for shared memory attaches if no address passed to shmat() */
+#define SHM_RANGE_START	0x10000000
+#define SHM_RANGE_END	0x20000000
+
+/*
+ * Format of a swap-entry for shared memory pages currently out in
+ * swap space (see also mm/swap.c).
+ *
+ * SWP_TYPE = SHM_SWP_TYPE
+ * SWP_OFFSET is used as follows:
+ *
+ *  bits 0..6 : id of shared memory segment page belongs to (SHM_ID)
+ *  bits 7..21: index of page within shared memory segment (SHM_IDX)
+ *		(actually fewer bits get used since SHMMAX is so low)
+ */
+
+/*
+ * Keep _SHM_ID_BITS as low as possible since SHMMNI depends on it and
+ * there is a static array of size SHMMNI.
+ */
+#define _SHM_ID_BITS	7
+#define SHM_ID_MASK	((1<<_SHM_ID_BITS)-1)
+
+#define SHM_IDX_SHIFT	(_SHM_ID_BITS)
+#define _SHM_IDX_BITS	15
+#define SHM_IDX_MASK	((1<<_SHM_IDX_BITS)-1)
+
+/*
+ * _SHM_ID_BITS + _SHM_IDX_BITS must be <= 24 on the i386 and
+ * SHMMAX <= (PAGE_SIZE << _SHM_IDX_BITS).
+ */
+
+#define SHMMAX (1024 * 1024)		/* max shared seg size (bytes) */
+#define SHMMIN 1 /* really PAGE_SIZE */	/* min shared seg size (bytes) */
+#define SHMMNI (1<<_SHM_ID_BITS)	/* max num of segs system wide */
+#define SHMALL				/* max shm system wide (pages) */ \
+	(1<<(_SHM_IDX_BITS+_SHM_ID_BITS))
+#define	SHMLBA PAGE_SIZE		/* attach addr a multiple of this */
+#define SHMSEG SHMMNI			/* max shared segs per process */
+
+#endif /* _ASMSPARC_SHMPARAM_H */
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/sigcontext.h linux/include/asm-sparc/sigcontext.h
--- v1.3.43/linux/include/asm-sparc/sigcontext.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-sparc/sigcontext.h	Sat Nov 25 04:32:45 1995
@@ -0,0 +1,37 @@
+/* $Id: sigcontext.h,v 1.7 1995/11/25 02:32:44 davem Exp $ */
+#ifndef _ASMsparc_SIGCONTEXT_H
+#define _ASMsparc_SIGCONTEXT_H
+
+#include <asm/ptrace.h>
+
+/* SunOS system call sigstack() uses this arg. */
+struct sunos_sigstack {
+	unsigned long sig_sp;
+	int onstack_flag;
+};
+
+/* This is what SunOS does, so shall I. */
+#define SUNOS_MAXWIN   31
+struct sigcontext_struct {
+	int sigc_onstack;      /* state to restore */
+	int sigc_mask;         /* sigmask to restore */
+	int sigc_sp;           /* stack pointer */
+	int sigc_pc;           /* program counter */
+	int sigc_npc;          /* next program counter */
+	int sigc_psr;          /* for condition codes etc */
+	int sigc_g1;           /* User uses these two registers */
+	int sigc_o0;           /* within the trampoline code. */
+
+	/* Now comes information regarding the users window set
+	 * at the time of the signal.
+	 */
+	int sigc_oswins;       /* outstanding windows */
+
+	/* stack ptrs for each regwin buf */
+	char *sigc_spbuf[SUNOS_MAXWIN];
+
+	/* Windows to restore after signal */
+	struct reg_window sigc_wbuf[SUNOS_MAXWIN];
+};
+
+#endif /* !(_ASMsparc_SIGCONTEXT_H) */
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/signal.h linux/include/asm-sparc/signal.h
--- v1.3.43/linux/include/asm-sparc/signal.h	Thu Feb  2 08:42:35 1995
+++ linux/include/asm-sparc/signal.h	Sat Nov 25 04:32:47 1995
@@ -1,11 +1,139 @@
+/* $Id: signal.h,v 1.14 1995/11/25 02:32:46 davem Exp $ */
 #ifndef _ASMSPARC_SIGNAL_H
 #define _ASMSPARC_SIGNAL_H
 
-struct sigcontext_struct {
-	/*
-	 * Have to find out what SUNOS and Solaris do. This could
-	 * get real ugly. David S. Miller (davem@caip.rutgers.edu)
-	 */
+/* On the Sparc the signal handlers get passed a 'sub-signal' code
+ * for certain signal types, which we document here.
+ */
+#define _NSIG             32
+#define NSIG		_NSIG
+
+#define SIGHUP		 1
+#define SIGINT		 2
+#define SIGQUIT		 3
+#define SIGILL		 4
+#define    SUBSIG_STACK       0
+#define    SUBSIG_ILLINST     2
+#define    SUBSIG_PRIVINST    3
+#define    SUBSIG_BADTRAP(t)  (0x80 + (n))
+
+#define SIGTRAP		 5
+#define SIGABRT		 6
+#define SIGIOT		 6
+
+#define SIGEMT           7
+#define    SUBSIG_TAG    10
+
+#define SIGFPE		 8
+#define    SUBSIG_FPDISABLED     0x400
+#define    SUBSIG_FPERROR        0x404
+#define    SUBSIG_FPINTOVFL      0x001
+#define    SUBSIG_FPSTSIG        0x002
+#define    SUBSIG_IDIVZERO       0x014
+#define    SUBSIG_FPINEXACT      0x0c4
+#define    SUBSIG_FPDIVZERO      0x0c8
+#define    SUBSIG_FPUNFLOW       0x0cc
+#define    SUBSIG_FPOPERROR      0x0d0
+#define    SUBSIG_FPOVFLOW       0x0d4
+
+#define SIGKILL		 9
+#define SIGBUS          10
+#define    SUBSIG_BUSTIMEOUT    1
+#define    SUBSIG_ALIGNMENT     2
+#define    SUBSIG_MISCERROR     5
+
+#define SIGSEGV		11
+#define    SUBSIG_NOMAPPING     3
+#define    SUBSIG_PROTECTION    4
+#define    SUBSIG_SEGERROR      5
+
+#define SIGSYS          12
+#define SIGPIPE		13
+#define SIGALRM		14
+#define SIGTERM		15
+#define SIGURG          16
+
+/* SunOS values which deviate from the Linux/i386 ones */
+#define SIGSTOP		17
+#define SIGTSTP		18
+#define SIGCONT		19
+#define SIGCHLD		20
+#define SIGTTIN		21
+#define SIGTTOU		22
+#define SIGIO		23
+#define SIGPOLL		SIGIO   /* SysV name for SIGIO */
+#define SIGXCPU		24
+#define SIGXFSZ		25
+#define SIGVTALRM	26
+#define SIGPROF		27
+#define SIGWINCH	28
+#define SIGLOST		29
+#define SIGUSR1		30
+#define SIGUSR2		31
+
+#ifndef __ASSEMBLY__
+
+typedef unsigned long sigset_t;
+
+#ifdef __KERNEL__
+#include <asm/sigcontext.h>
+#endif
+
+/* A SunOS sigstack */
+struct sigstack {
+	char *the_stack;
+	int   cur_status;
 };
 
+/* Sigvec flags */
+#define SV_SSTACK    1     /* This signal handler should use sig-stack */
+#define SV_INTR      2     /* Sig return should not restart system ??? */
+#define SV_RESET     4     /* Set handler to SIG_DFL upon taken signal */
+#define SV_IGNCHILD  8     /* Do not send SIGCHLD */
+
+/*
+ * sa_flags values: SA_STACK is not currently supported, but will allow the
+ * usage of signal stacks by using the (now obsolete) sa_restorer field in
+ * the sigaction structure as a stack pointer. This is now possible due to
+ * the changes in signal handling. LBT 010493.
+ * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the
+ * SA_RESTART flag to get restarting signals (which were the default long ago)
+ */
+#define SA_NOCLDSTOP	SV_IGNCHILD
+#define SA_STACK	SV_SSTACK
+#define SA_RESTART	SV_RESET
+#define SA_INTERRUPT	SV_INTR
+#define SA_NOMASK	0x10
+#define SA_ONESHOT	0x20
+
+#define SIG_BLOCK          0x00	/* for blocking signals */
+#define SIG_UNBLOCK        0x40	/* for unblocking signals */
+#define SIG_SETMASK        0x80	/* for setting the signal mask */
+
+#ifdef __KERNEL__
+/*
+ * These values of sa_flags are used only by the kernel as part of the
+ * irq handling routines.
+ *
+ * SA_INTERRUPT is also used by the irq handling routines.
+ */
+#define SA_PROBE SA_ONESHOT
+#define SA_SAMPLE_RANDOM SA_RESTART
 #endif
+
+/* Type of a signal handler.  */
+typedef void (*__sighandler_t)(int, int, struct sigcontext_struct *, char *);
+
+#define SIG_DFL	((__sighandler_t)0)	/* default signal handling */
+#define SIG_IGN	((__sighandler_t)1)	/* ignore signal */
+#define SIG_ERR	((__sighandler_t)-1)	/* error return from signal */
+
+struct sigaction {
+	__sighandler_t  sa_handler;
+	sigset_t        sa_mask;
+	unsigned long   sa_flags;
+};
+
+#endif /* !(__ASSEMBLY__) */
+
+#endif /* !(_ASMSPARC_SIGNAL_H) */
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/smpprim.h linux/include/asm-sparc/smpprim.h
--- v1.3.43/linux/include/asm-sparc/smpprim.h	Tue Jun 27 14:11:46 1995
+++ linux/include/asm-sparc/smpprim.h	Sat Nov 25 04:32:48 1995
@@ -1,4 +1,5 @@
-/*  smpprim.h:  SMP locking primitives on the Sparc
+/*  $Id: smpprim.h,v 1.4 1995/11/25 02:32:47 davem Exp $
+ *  smpprim.h:  SMP locking primitives on the Sparc
  *
  *  God knows we won't be actually using this code for some time
  *  but I thought I'd write it since I knew how.
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/socket.h linux/include/asm-sparc/socket.h
--- v1.3.43/linux/include/asm-sparc/socket.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-sparc/socket.h	Sat Nov 25 04:32:50 1995
@@ -0,0 +1,37 @@
+/* $Id: socket.h,v 1.4 1995/11/25 02:32:49 davem Exp $ */
+#ifndef _ASM_SOCKET_H
+#define _ASM_SOCKET_H
+
+/* Socket-level I/O control calls. */
+#define FIOSETOWN 	0x8901
+#define SIOCSPGRP	0x8902
+#define FIOGETOWN	0x8903
+#define SIOCGPGRP	0x8904
+#define SIOCATMARK	0x8905
+#define SIOCGSTAMP	0x8906		/* Get stamp */
+
+/* For setsockoptions(2) */
+#define SOL_SOCKET	0xffff
+
+#define SO_DEBUG	0x0001
+#define SO_REUSEADDR	0x0004
+#define SO_KEEPALIVE	0x0008
+#define SO_DONTROUTE	0x0010
+#define SO_BROADCAST	0x0020
+#define SO_LINGER	0x0080
+#define SO_OOBINLINE	0x0100
+/* To add :#define SO_REUSEPORT 0x0200 */
+
+/* wha!??? */
+#define SO_DONTLINGER   (~SO_LINGER)  /* Older SunOS compat. hack */
+
+#define SO_SNDBUF	0x1001
+#define SO_RCVBUF	0x1002
+#define SO_ERROR	0x1007
+#define SO_TYPE		0x1008
+
+/* Linux specific, keep the same. */
+#define SO_NO_CHECK	0x000b
+#define SO_PRIORITY	0x000c
+
+#endif /* _ASM_SOCKET_H */
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/solerrno.h linux/include/asm-sparc/solerrno.h
--- v1.3.43/linux/include/asm-sparc/solerrno.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-sparc/solerrno.h	Sat Nov 25 04:32:52 1995
@@ -0,0 +1,132 @@
+/* $Id: solerrno.h,v 1.3 1995/11/25 02:32:51 davem Exp $
+ * solerrno.h: Solaris error return codes for compatability.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef _SPARC_SOLERRNO_H
+#define _SPARC_SOLERRNO_H
+
+#define SOL_EPERM          1     /* Required superuser access perms  */
+#define SOL_ENOENT         2     /* File or directory does not exist */
+#define SOL_ESRCH          3     /* Process did not exist            */
+#define	SOL_EINTR          4     /* System call was interrupted      */
+#define	SOL_EIO            5     /* An i/o error occurred            */
+#define	SOL_ENXIO          6     /* Device or Address does not exist */
+#define	SOL_E2BIG          7	 /* Too many arguments were given    */
+#define	SOL_ENOEXEC        8     /* Header of executable was munged  */
+#define	SOL_EBADF          9     /* Bogus file number                */
+#define	SOL_ECHILD         10    /* No children of process exist     */
+#define	SOL_EAGAIN         11    /* beep beep, "try again later"     */
+#define	SOL_ENOMEM         12    /* No memory available              */
+#define	SOL_EACCES         13    /* Access not allowed               */
+#define	SOL_EFAULT         14    /* Address passed was invalid       */
+#define	SOL_ENOTBLK        15    /* blkdev op on non-block device    */
+#define	SOL_EBUSY          16    /* Mounted device was busy          */
+#define	SOL_EEXIST         17    /* File specified already exists    */
+#define	SOL_EXDEV          18    /* Link request across diff devices */
+#define	SOL_ENODEV         19    /* Device does not exist on system  */
+#define	SOL_ENOTDIR        20    /* Dir operation on non-directory   */
+#define	SOL_EISDIR         21    /* File was of directory type       */
+#define	SOL_EINVAL         22    /* Argument passed was invalid      */
+#define	SOL_ENFILE         23    /* No more room in file table       */
+#define	SOL_EMFILE         24    /* Proc has too many files open     */
+#define	SOL_ENOTTY         25    /* Ioctl was invalid for req device */
+#define	SOL_ETXTBSY        26    /* Text file in busy state          */
+#define	SOL_EFBIG          27    /* Too big of a file for operation  */
+#define	SOL_ENOSPC         28    /* Disk is full                     */
+#define	SOL_ESPIPE         29    /* Seek attempted on non-seeking dev*/
+#define	SOL_EROFS          30    /* Write attempted on read-only fs  */
+#define	SOL_EMLINK         31    /* Too many links in file search    */
+#define	SOL_EPIPE          32    /* Call a plumber                   */
+#define	SOL_EDOM           33    /* Argument was out of fct domain   */
+#define	SOL_ERANGE         34    /* Could not represent math result  */
+#define	SOL_ENOMSG         35    /* Message of req type doesnt exist */
+#define	SOL_EIDRM          36    /* Identifier has been removed      */
+#define	SOL_ECHRNG         37    /* Req channel number out of range  */
+#define	SOL_EL2NSYNC       38    /* Could not sync at run level 2    */
+#define	SOL_EL3HLT         39    /* Halted at run level 3            */
+#define	SOL_EL3RST         40    /* Reset at run level 3             */
+#define	SOL_ELNRNG         41    /* Out of range link number         */
+#define	SOL_EUNATCH        42    /* Driver for protocol not attached */
+#define	SOL_ENOCSI         43    /* CSI structure not around         */
+#define	SOL_EL2HLT         44    /* Halted at run level 2            */
+#define	SOL_EDEADLK        45    /* Deadlock condition detected      */
+#define	SOL_ENOLCK         46    /* Record locks unavailable         */
+#define	SOL_ECANCELED      47    /* Cancellation of oper. happened   */
+#define	SOL_ENOTSUP        48    /* Attempt of unsupported operation */
+#define	SOL_EDQUOT         49    /* Users disk quota exceeded        */
+#define	SOL_EBADE          50    /* Invalid exchange                 */
+#define	SOL_EBADR          51    /* Request descriptor was invalid   */
+#define	SOL_EXFULL         52    /* Full exchange                    */
+#define	SOL_ENOANO         53    /* ano does not exist               */
+#define	SOL_EBADRQC        54    /* Req code was invalid             */
+#define	SOL_EBADSLT        55    /* Bad slot number                  */
+#define	SOL_EDEADLOCK      56    /* Deadlock in fs error             */
+#define	SOL_EBFONT         57    /* Font file format invalid         */
+/* YOW, I LOVE SYSV STREAMS!!!! */
+#define	SOL_ENOSTR         60    /* Stream-op on non-stream dev      */
+#define	SOL_ENODATA        61    /* No data avail at this time       */
+#define	SOL_ETIME          62    /* Expiration of time occurred      */
+#define	SOL_ENOSR          63    /* Streams resources exhausted      */
+#define	SOL_ENONET         64    /* No network connected             */
+#define	SOL_ENOPKG         65    /* Non-installed package            */
+#define	SOL_EREMOTE        66    /* Object was on remote machine     */
+#define	SOL_ENOLINK        67    /* Cut link                         */
+#define	SOL_EADV           68    /* Error in advertise               */
+#define	SOL_ESRMNT         69    /* Some magic srmount problem       */
+#define	SOL_ECOMM          70    /* During send, comm error occurred */
+#define	SOL_EPROTO         71    /* Protocol botch                   */
+#define	SOL_EMULTIHOP      74    /* Multihop attempted               */
+#define	SOL_EBADMSG        77    /* Message was unreadable           */
+#define	SOL_ENAMETOOLONG   78    /* Too long of a path name          */
+#define	SOL_EOVERFLOW      79    /* Data type too small for datum    */
+#define	SOL_ENOTUNIQ       80    /* Logical name was not unique      */
+#define	SOL_EBADFD         81    /* Op cannot be performed on fd     */
+#define	SOL_EREMCHG        82    /* Remote address is now different  */
+#define	SOL_ELIBACC        83    /* Shared lib could not be accessed */
+#define	SOL_ELIBBAD        84    /* ShLib is corrupted in some way   */
+#define	SOL_ELIBSCN        85    /* A.out ShLib problems             */
+#define	SOL_ELIBMAX        86    /* Exceeded ShLib linkage limit     */
+#define	SOL_ELIBEXEC       87    /* Execution of ShLib attempted     */
+#define	SOL_EILSEQ         88    /* Bad byte sequence found          */
+#define	SOL_ENOSYS         89    /* Invalid filesystem operation     */
+#define	SOL_ELOOP          90    /* Detected loop in symbolic links  */
+#define	SOL_ERESTART       91    /* System call is restartable       */
+#define	SOL_ESTRPIPE       92    /* Do not sleep in head of stream   */
+#define	SOL_ENOTEMPTY      93    /* Rmdir of non-empty directory     */
+#define	SOL_EUSERS         94    /* Over abundance of users for ufs  */
+#define	SOL_ENOTSOCK       95    /* Sock-op on non-sock              */
+#define	SOL_EDESTADDRREQ   96    /* No dest addr given, but needed   */
+#define	SOL_EMSGSIZE       97    /* Msg too big                      */
+#define	SOL_EPROTOTYPE     98    /* Bad socket protocol              */
+#define	SOL_ENOPROTOOPT    99    /* Unavailable protocol             */
+#define	SOL_EPROTONOSUPPORT 120  /* Unsupported protocol             */
+#define	SOL_ESOCKTNOSUPPORT 121  /* Unsupported socket type          */
+#define	SOL_EOPNOTSUPP     122   /* Unsupported sock-op              */
+#define	SOL_EPFNOSUPPORT   123   /* Unsupported protocol family      */
+#define	SOL_EAFNOSUPPORT   124   /* Unsup addr family for protocol   */
+#define	SOL_EADDRINUSE     125   /* Req addr is already in use       */
+#define	SOL_EADDRNOTAVAIL  126   /* Req addr not available right now */
+#define	SOL_ENETDOWN       127   /* Your subnet is on fire           */
+#define	SOL_ENETUNREACH    128   /* Someone playing with gateway and */
+                                 /* did not tell you he was going to */
+#define	SOL_ENETRESET      129   /* Buy less-buggy ethernet cards    */
+#define	SOL_ECONNABORTED   130   /* Aborted connection due to sw     */
+#define	SOL_ECONNRESET     131   /* Your peers reset your connection */
+#define	SOL_ENOBUFS        132   /* No buffer space available        */
+#define	SOL_EISCONN        133   /* Connect on already connected     */
+                                 /* socket attempted                 */
+#define	SOL_ENOTCONN       134   /* Comm on non-connected socket     */
+#define	SOL_ESHUTDOWN      143   /* Op attempted after sock-shutdown */
+#define	SOL_ETOOMANYREFS   144   /* Reference limit exceeded         */
+#define	SOL_ETIMEDOUT      145   /* Timed out connection             */
+#define	SOL_ECONNREFUSED   146   /* Connection refused by remote host*/
+#define	SOL_EHOSTDOWN      147   /* Remote host in up in flames      */
+#define	SOL_EHOSTUNREACH   148   /* Make a left at Easton Ave.....   */
+#define	SOL_EWOULDBLOCK    EAGAIN /* Just an alias */
+#define	SOL_EALREADY       149   /* Operation is already occurring   */
+#define	SOL_EINPROGRESS    150   /* Operation is happening now       */
+#define	SOL_ESTALE         151   /* Fungus growth on NFS file handle */
+
+#endif /* !(_SPARC_SOLERRNO_H) */
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/stat.h linux/include/asm-sparc/stat.h
--- v1.3.43/linux/include/asm-sparc/stat.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-sparc/stat.h	Sat Nov 25 04:32:53 1995
@@ -0,0 +1,41 @@
+/* $Id: stat.h,v 1.6 1995/11/25 02:32:53 davem Exp $ */
+#ifndef _SPARC_STAT_H
+#define _SPARC_STAT_H
+
+#include <linux/types.h>
+
+struct old_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;
+};
+
+struct new_stat {
+	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 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];
+};
+
+#endif
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/statfs.h linux/include/asm-sparc/statfs.h
--- v1.3.43/linux/include/asm-sparc/statfs.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-sparc/statfs.h	Sat Nov 25 04:32:55 1995
@@ -0,0 +1,22 @@
+/* $Id: statfs.h,v 1.3 1995/11/25 02:32:54 davem Exp $ */
+#ifndef _SPARC_STATFS_H
+#define _SPARC_STATFS_H
+
+typedef struct {
+	long    val[2];
+} fsid_t;
+
+struct statfs {
+	long f_type;
+	long f_bsize;
+	long f_blocks;
+	long f_bfree;
+	long f_bavail;
+	long f_files;
+	long f_ffree;
+	fsid_t f_fsid;
+	long f_namelen;  /* SunOS ignores this field. */
+	long f_spare[6];
+};
+
+#endif
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/string.h linux/include/asm-sparc/string.h
--- v1.3.43/linux/include/asm-sparc/string.h	Tue Jun 27 14:11:46 1995
+++ linux/include/asm-sparc/string.h	Sat Nov 25 04:32:57 1995
@@ -1,205 +1,13 @@
-/* string.h: External definitions for optimized assembly string
+/* $Id: string.h,v 1.15 1995/11/25 02:32:56 davem Exp $
+ * string.h: External definitions for optimized assembly string
  *           routines for the Linux Kernel.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  */
 
-#ifndef _SPARC_STRING_H
-#define _SPARC_STRING_H
+#ifndef __SPARC_STRING_H__
+#define __SPARC_STRING_H__
 
-extern __inline__ size_t strlen(const char * str)
-{
-  const char *sc;
+/* Nothing yet... */
 
-  for (sc = str; *sc != '\0'; ++sc)
-    /* nothing */;
-  return sc - str;
-}
-
-extern __inline__ int strcmp(const char* str1, const char* str2)
-{
-  register signed char __res;
-
-  while (1) {
-    if ((__res = *str1 - *str2++) != 0 || !*str1++)
-      break;
-  }
-
-  return __res;
-}
-
-extern __inline__ int strncmp(const char* str1, const char* str2, size_t strlen)
-{
-  register signed char __res = 0;
-
-  while (strlen) {
-    if ((__res = *str1 - *str2++) != 0 || !*str1++)
-      break;
-    strlen--;
-  }
-
-  return __res;
-}
-
-
-extern __inline__ char *strcpy(char* dest, const char* source)
-{
-  char *tmp = dest;
-
-  while ((*dest++ = *source++) != '\0')
-    /* nothing */;
-  return tmp;
-}
-
-extern __inline__ char *strncpy(char *dest, const char *source, size_t cpylen)
-{
-  char *tmp = dest;
-
-  while (cpylen-- && (*dest++ = *source++) != '\0')
-    /* nothing */;
-
-  return tmp;
-}
-
-extern __inline__ char *strcat(char *dest, const char *src)
-{
-  char *tmp = dest;
-
-  while (*dest)
-    dest++;
-  while ((*dest++ = *src++) != '\0')
-    ;
-
-  return tmp;
-}
-
-extern __inline__ char *strncat(char *dest, const char *src, size_t len)
-{
-  char *tmp = dest;
-
-  if (len) {
-    while (*dest)
-      dest++;
-    while ((*dest++ = *src++)) {
-      if (--len == 0)
-	break;
-    }
-  }
-
-  return tmp;
-}
-
-extern __inline__ char *strchr(const char *src, int c)
-{
-  for(; *src != c; ++src)
-    if (*src == '\0')
-      return NULL;
-  return (char *) src;
-}
-
-extern __inline__ char *strpbrk(const char *cs, const char *ct)
-{
-  const char *sc1,*sc2;
-
-  for( sc1 = cs; *sc1 != '\0'; ++sc1) {
-    for( sc2 = ct; *sc2 != '\0'; ++sc2) {
-      if (*sc1 == *sc2)
-	return (char *) sc1;
-    }
-  }
-  return NULL;
-}
-
-      
-extern __inline__ size_t strspn(const char *s, const char *accept)
-{
-  const char *p;
-  const char *a;
-  size_t count = 0;
-
-  for (p = s; *p != '\0'; ++p) {
-    for (a = accept; *a != '\0'; ++a) {
-      if (*p == *a)
-	break;
-    }
-    if (*a == '\0')
-      return count;
-    ++count;
-  }
-
-  return count;
-}
-
-extern __inline__ char *strtok(char *s, const char *ct)
-{
-  char *sbegin, *send;
-
-  sbegin  = s ? s : ___strtok;
-  if (!sbegin) {
-    return NULL;
-  }
-  sbegin += strspn(sbegin,ct);
-  if (*sbegin == '\0') {
-    ___strtok = NULL;
-    return( NULL );
-  }
-  send = strpbrk( sbegin, ct);
-  if (send && *send != '\0')
-    *send++ = '\0';
-  ___strtok = send;
-  return (sbegin);
-}
-	
-
-extern __inline__ void *memset(void *src, int c, size_t count)
-{
-  char *xs = (char *) src;
-
-  while (count--)
-    *xs++ = c;
-
-  return src;
-}
-
-extern __inline__ void *memcpy(void *dest, const void *src, size_t count)
-{
-  char *tmp = (char *) dest, *s = (char *) src;
-
-  while (count--)
-    *tmp++ = *s++;
-
-  return dest;
-}
-
-extern __inline__ void *memmove(void *dest, const void *src, size_t count)
-{
-  char *tmp, *s;
-
-  if (dest <= src) {
-    tmp = (char *) dest;
-    s = (char *) src;
-    while (count--)
-      *tmp++ = *s++;
-  }
-  else {
-    tmp = (char *) dest + count;
-    s = (char *) src + count;
-    while (count--)
-      *--tmp = *--s;
-  }
-
-  return dest;
-}
-
-extern __inline__ int memcmp(const void *cs, const void *ct, size_t count)
-{
-  const unsigned char *su1, *su2;
-  signed char res = 0;
-
-  for( su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
-    if ((res = *su1 - *su2) != 0)
-      break;
-  return res;
-}
-
-#endif /* !(_SPARC_STRING_H) */
+#endif /* !(__SPARC_STRING_H__) */
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/sysen.h linux/include/asm-sparc/sysen.h
--- v1.3.43/linux/include/asm-sparc/sysen.h	Tue Jun 27 14:11:46 1995
+++ linux/include/asm-sparc/sysen.h	Sat Nov 25 04:32:58 1995
@@ -1,4 +1,5 @@
-/* sysen.h:  Bit fields within the "System Enable" register accessed via
+/* $Id: sysen.h,v 1.3 1995/11/25 02:32:58 davem Exp $
+ * sysen.h:  Bit fields within the "System Enable" register accessed via
  *           the ASI_CONTROL address space at address AC_SYSENABLE.
  *
  * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/system.h linux/include/asm-sparc/system.h
--- v1.3.43/linux/include/asm-sparc/system.h	Tue Jun 27 14:11:46 1995
+++ linux/include/asm-sparc/system.h	Sat Nov 25 04:33:00 1995
@@ -1,22 +1,13 @@
+/* $Id: system.h,v 1.19 1995/11/25 02:32:59 davem Exp $ */
 #ifndef __SPARC_SYSTEM_H
 #define __SPARC_SYSTEM_H
 
 #include <asm/segment.h>
 
-/*
- * I wish the boot time image was as beautiful as the Alpha's
- * but no such luck. The icky PROM loads us at 0x0, and jumps
- * to magic address 0x4000 to start things going.
- *
- * Sorry, I can't impress people with cool looking 64-bit values
- * yet. Wait till V9 ;-)
- */
-
 #include <asm/page.h>
 #include <asm/openprom.h>
 #include <asm/psr.h>
 
-#define START_ADDR	(0x00004000)
 #define EMPTY_PGT       (&empty_bad_page)
 #define EMPTY_PGE	(&empty_bad_page_table)
 #define ZERO_PGE	(&empty_zero_page)
@@ -32,7 +23,7 @@
   sun4m       = 0x02,
   sun4d       = 0x03,
   sun4e       = 0x04,
-  sun4u       = 0x05,
+  sun4u       = 0x05, /* V8 ploos ploos */
   sun_unknown = 0x06,
 };
 
@@ -42,98 +33,99 @@
 extern unsigned long empty_bad_page_table;
 extern unsigned long empty_zero_page;
 
-extern void wrent(void *, unsigned long);
-extern void wrkgp(unsigned long);
 extern struct linux_romvec *romvec;
-
-#define halt() do { \
-			 printk("Entering monitor in file %s at line %d\n", __FILE__, __LINE__); \
-romvec->pv_halt(); } while(0)
-
-#define move_to_user_mode() halt()
-
-#ifndef stbar  /* store barrier Sparc insn to synchronize stores in PSO */
-#define stbar() __asm__ __volatile__("stbar": : :"memory")
-#endif
+#define halt() romvec->pv_halt()
 
 /* When a context switch happens we must flush all user windows so that
  * the windows of the current process are flushed onto it's stack. This
- * way the windows are all clean for the next process.
+ * way the windows are all clean for the next process and the stack
+ * frames are up to date.
  */
-
-#define flush_user_windows() \
-do { __asm__ __volatile__( \
-			  "save %sp, -64, %sp\n\t" \
-			  "save %sp, -64, %sp\n\t" \
-			  "save %sp, -64, %sp\n\t" \
-			  "save %sp, -64, %sp\n\t" \
-			  "save %sp, -64, %sp\n\t" \
-			  "save %sp, -64, %sp\n\t" \
-			  "save %sp, -64, %sp\n\t" \
-			  "restore\n\t" \
-			  "restore\n\t" \
-			  "restore\n\t" \
-			  "restore\n\t" \
-			  "restore\n\t" \
-			  "restore\n\t" \
-			  "restore\n\t"); } while(0)
-
+extern void flush_user_windows(void);
 extern void sparc_switch_to(void *new_task);
+#define switch_to(p) do { \
+			  flush_user_windows(); \
+		          switch_to_context(p); \
+                          sparc_switch_to(p); \
+                     } while(0)
 
-#define switch_to(p) sparc_switch_to(p)
+/* Changing the IRQ level on the Sparc. */
+extern inline void setipl(int __new_ipl)
+{
+	__asm__ __volatile__("rd %%psr, %%g1\n\t"
+			     "andn %%g1, %1, %%g1\n\t"
+			     "sll %0, 8, %%g2\n\t"
+			     "and %%g2, %1, %%g2\n\t"
+			     "or %%g1, %%g2, %%g1\n\t"
+			     "wr %%g1, 0x0, %%psr\n\t"
+			     "nop; nop; nop\n\t" : :
+			     "r" (__new_ipl), "i" (PSR_PIL) :
+			     "g1", "g2");
+}
 
-/* Changing the PIL on the sparc is a bit hairy. I'll figure out some
- * more optimized way of doing this soon. This is bletcherous code.
- */
+extern inline int getipl(void)
+{
+	int retval;
+
+	__asm__ __volatile__("rd %%psr, %0\n\t"
+			     "and %0, %1, %0\n\t"
+			     "srl %0, 8, %0\n\t" :
+			     "=r" (retval) :
+			     "i" (PSR_PIL));
+	return retval;
+}
 
-#define swpipl(__new_ipl) \
-({ unsigned long psr, retval; \
-__asm__ __volatile__( \
-        "rd %%psr, %0\n\t" : "=&r" (psr)); \
-retval = psr; \
-psr = (psr & ~(PSR_PIL)); \
-psr |= ((__new_ipl << 8) & PSR_PIL); \
-__asm__ __volatile__( \
-	"wr  %0, 0x0, %%psr\n\t" \
-	: : "r" (psr)); \
-retval = ((retval>>8)&15); \
-retval; })
-
-#define cli()			swpipl(15)  /* 15 = no int's except nmi's */
-#define sti()			swpipl(0)   /* I'm scared */
-#define save_flags(flags)	do { flags = swpipl(15); } while (0)
-#define restore_flags(flags)	swpipl(flags)
+extern inline int swpipl(int __new_ipl)
+{
+	int retval;
 
-#define iret() __asm__ __volatile__ ("jmp %%l1\n\t" \
-				     "rett %%l2\n\t": : :"memory")
+	__asm__ __volatile__("rd %%psr, %%g1\n\t"
+			     "srl %%g1, 8, %0\n\t"
+			     "and %0, 15, %0\n\t"
+			     "andn %%g1, %2, %%g1\n\t"
+			     "and %1, 15, %%g2\n\t"
+			     "sll %%g2, 8, %%g2\n\t"
+			     "or %%g1, %%g2, %%g1\n\t"
+			     "wr %%g1, 0x0, %%psr\n\t"
+			     "nop; nop; nop\n\t" :
+			     "=r" (retval) :
+			     "r" (__new_ipl), "i" (PSR_PIL) :
+			     "g1", "g2");
+	return retval;
+}
 
-/* Must this be atomic? */
+#define cli()			setipl(15)  /* 15 = no int's except nmi's */
+#define sti()			setipl(0)   /* I'm scared */
+#define save_flags(flags)	do { flags = getipl(); } while (0)
+#define restore_flags(flags)	setipl(flags)
+#define nop() __asm__ __volatile__ ("nop");
 
-extern inline void *xchg_u32(int * m, unsigned long val)
+extern inline unsigned long xchg_u32(volatile unsigned long *m, unsigned long val)
 {
-	unsigned long dummy;
+	unsigned long flags, retval;
 
-	__asm__ __volatile__(
-		"ld %1,%2\n\t"
-		"st %0, %1\n\t"
-		"or %%g0, %2, %0"
-		: "=r" (val), "=m" (*m), "=r" (dummy)
-		: "0" (val));
-	return (void *) val;
+	save_flags(flags); cli();
+	retval = *m;
+	*m = val;
+	restore_flags(flags);
+	return retval;
 }
 
+#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
+#define tas(ptr) (xchg((ptr),1))
 
-/* pointers are 32 bits on the sparc (at least the v8, and they'll work
- * on the V9 none the less). I don't need the xchg_u64 routine for now.
- */
+extern void __xchg_called_with_bad_pointer(void);
 
-extern inline void *xchg_ptr(void *m, void *val)
+static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
 {
-	return (void *) xchg_u32((int *) m, (unsigned long) val);
+	switch (size) {
+	case 4:
+		return xchg_u32(ptr, x);
+	};
+	__xchg_called_with_bad_pointer();
+	return x;
 }
 
-
-
 #endif /* __ASSEMBLY__ */
 
-#endif
+#endif /* !(__SPARC_SYSTEM_H) */
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/termios.h linux/include/asm-sparc/termios.h
--- v1.3.43/linux/include/asm-sparc/termios.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-sparc/termios.h	Sat Nov 25 04:33:02 1995
@@ -0,0 +1,384 @@
+/* $Id: termios.h,v 1.10 1995/11/25 02:33:01 davem Exp $ */
+#ifndef _SPARC_TERMIOS_H
+#define _SPARC_TERMIOS_H
+
+#include <linux/types.h>
+
+#include <asm/ioctl.h>
+
+struct sgttyb {
+	char	sg_ispeed;
+	char	sg_ospeed;
+	char	sg_erase;
+	char	sg_kill;
+	short	sg_flags;
+};
+
+struct tchars {
+	char	t_intrc;
+	char	t_quitc;
+	char	t_startc;
+	char	t_stopc;
+	char	t_eofc;
+	char	t_brkc;
+};
+
+struct ltchars {
+	char	t_suspc;
+	char	t_dsuspc;
+	char	t_rprntc;
+	char	t_flushc;
+	char	t_werasc;
+	char	t_lnextc;
+};
+
+struct sunos_ttysize {
+	int st_lines;   /* Lines on the terminal */
+	int st_columns; /* Columns on the terminal */
+};
+
+/* Big T */
+#define TCGETA		_IOR('T', 1, struct termio)
+#define TCSETA		_IOW('T', 2, struct termio)
+#define TCSETAW		_IOW('T', 3, struct termio)
+#define TCSETAF		_IOW('T', 4, struct termio)
+#define TCSBRK		_IO('T', 5)
+#define TCXONC		_IO('T', 6)
+#define TCFLSH		_IO('T', 7)
+#define TCGETS		_IOR('T', 8, struct termios)
+#define TCSETS		_IOW('T', 9, struct termios)
+#define TCSETSW		_IOW('T', 10, struct termios)
+#define TCSETSF		_IOW('T', 11, struct termios)
+
+/* SCARY Rutgers local SunOS kernel hackery, perhaps I will support it
+ * someday.  This is completely bogus, I know...
+ */
+#define TCGETSTAT       _IO('T', 200) /* Rutgers specific */
+#define TCSETSTAT       _IO('T', 201) /* Rutgers specific */
+
+/* Little t */
+#define TIOCGETD	_IOR('t', 0, int)
+#define TIOCSETD	_IOW('t', 1, int)
+#define TIOCHPCL        _IO('t', 2) /* SunOS Specific */
+#define TIOCMODG        _IOR('t', 3, int) /* SunOS Specific */
+#define TIOCMODS        _IOW('t', 4, int) /* SunOS Specific */
+#define TIOCGETP        _IOR('t', 8, struct sgttyb) /* SunOS Specific */
+#define TIOCSETP        _IOW('t', 9, struct sgttyb) /* SunOS Specific */
+#define TIOCSETN        _IOW('t', 10, struct sgttyb) /* SunOS Specific */
+#define TIOCEXCL	_IO('t', 13)
+#define TIOCNXCL	_IO('t', 14)
+#define TIOCFLUSH       _IOW('t', 16, int) /* SunOS Specific */
+#define TIOCSETC        _IOW('t', 17, struct tchars) /* SunOS Specific */
+#define TIOCGETC        _IOR('t', 18, struct tchars) /* SunOS Specific */
+#define TIOCTCNTL       _IOW('t', 32, int) /* SunOS Specific */
+#define TIOCSIGNAL      _IOW('t', 33, int) /* SunOS Specific */
+#define TIOCSETX        _IOW('t', 34, int) /* SunOS Specific */
+#define TIOCGETX        _IOR('t', 35, int) /* SunOS Specific */
+#define TIOCCONS	_IO('t', 36)
+#define TIOCSSIZE       _IOW('t', 37, struct sunos_ttysize) /* SunOS Specific */
+#define TIOCGSIZE       _IOR('t', 38, struct sunos_ttysize) /* SunOS Specific */
+#define TIOCGSOFTCAR	_IOR('t', 100, int)
+#define TIOCSSOFTCAR	_IOW('t', 101, int)
+#define TIOCUCNTL       _IOW('t', 102, int) /* SunOS Specific */
+#define TIOCSWINSZ	_IOW('t', 103, struct winsize)
+#define TIOCGWINSZ	_IOR('t', 104, struct winsize)
+#define TIOCREMOTE      _IOW('t', 105, int) /* SunOS Specific */
+#define TIOCMGET	_IOR('t', 106, int)
+#define TIOCMBIC	_IOW('t', 107, int)
+#define TIOCMBIS	_IOW('t', 108, int)
+#define TIOCMSET	_IOW('t', 109, int)
+#define TIOCSTART       _IO('t', 110) /* SunOS Specific */
+#define TIOCSTOP        _IO('t', 111) /* SunOS Specific */
+#define TIOCPKT		_IOW('t', 112, int)
+#define TIOCNOTTY	_IO('t', 113)
+#define TIOCSTI		_IOW('t', 114, char)
+#define TIOCOUTQ	_IOR('t', 115, int)
+#define TIOCGLTC        _IOR('t', 116, struct ltchars) /* SunOS Specific */
+#define TIOCSLTC        _IOW('t', 117, struct ltchars) /* SunOS Specific */
+/* 118 is the non-posix setpgrp tty ioctl */
+/* 119 is the non-posix getpgrp tty ioctl */
+#define TIOCCDTR        _IO('t', 120) /* SunOS Specific */
+#define TIOCSDTR        _IO('t', 121) /* SunOS Specific */
+#define TIOCCBRK        _IO('t', 122) /* SunOS Specific */
+#define TIOCSBRK        _IO('t', 123) /* SunOS Specific */
+#define TIOCLGET        _IOW('t', 124, int) /* SunOS Specific */
+#define TIOCLSET        _IOW('t', 125, int) /* SunOS Specific */
+#define TIOCLBIC        _IOW('t', 126, int) /* SunOS Specific */
+#define TIOCLBIS        _IOW('t', 127, int) /* SunOS Specific */
+#define TIOCISPACE      _IOR('t', 128, int) /* SunOS Specific */
+#define TIOCISIZE       _IOR('t', 129, int) /* SunOS Specific */
+#define TIOCSPGRP	_IOW('t', 130, int)
+#define TIOCGPGRP	_IOR('t', 131, int)
+#define TIOCSCTTY	_IO('t', 132)
+
+/* Little f */
+#define FIOCLEX		_IO('f', 1)
+#define FIONCLEX	_IO('f', 2)
+#define FIOASYNC	_IOW('f', 125, int)
+#define FIONBIO		_IOW('f', 126, int)
+#define FIONREAD	_IOR('f', 127, int)
+#define TIOCINQ		FIONREAD
+
+/* Linux specific, no SunOS equivalent. */
+#define TIOCLINUX	0x541C
+#define TIOCGSERIAL	0x541E
+#define TIOCSSERIAL	0x541F
+#define TCSBRKP		0x5425
+#define TIOCTTYGSTRUCT	0x5426
+#define TIOCSERCONFIG	0x5453
+#define TIOCSERGWILD	0x5454
+#define TIOCSERSWILD	0x5455
+#define TIOCGLCKTRMIOS	0x5456
+#define TIOCSLCKTRMIOS	0x5457
+#define TIOCSERGSTRUCT	0x5458 /* For debugging only */
+#define TIOCSERGETLSR   0x5459 /* Get line status register */
+#define TIOCSERGETMULTI 0x545A /* Get multiport config  */
+#define TIOCSERSETMULTI 0x545B /* Set multiport config */
+
+/* Used for packet mode */
+#define TIOCPKT_DATA		 0
+#define TIOCPKT_FLUSHREAD	 1
+#define TIOCPKT_FLUSHWRITE	 2
+#define TIOCPKT_STOP		 4
+#define TIOCPKT_START		 8
+#define TIOCPKT_NOSTOP		16
+#define TIOCPKT_DOSTOP		32
+
+struct winsize {
+	unsigned short ws_row;
+	unsigned short ws_col;
+	unsigned short ws_xpixel;
+	unsigned short ws_ypixel;
+};
+
+#define NCC 8
+struct termio {
+	unsigned short c_iflag;		/* input mode flags */
+	unsigned short c_oflag;		/* output mode flags */
+	unsigned short c_cflag;		/* control mode flags */
+	unsigned short c_lflag;		/* local mode flags */
+	unsigned char c_line;		/* line discipline */
+	unsigned char c_cc[NCC];	/* control characters */
+};
+
+#define NCCS 17
+struct termios {
+	tcflag_t c_iflag;		/* input mode flags */
+	tcflag_t c_oflag;		/* output mode flags */
+	tcflag_t c_cflag;		/* control mode flags */
+	tcflag_t c_lflag;		/* local mode flags */
+	cc_t c_line;			/* line discipline */
+	cc_t c_cc[NCCS];		/* control characters */
+};
+
+/* c_cc characters */
+#define VINTR    0
+#define VQUIT    1
+#define VERASE   2
+#define VKILL    3
+#define VEOF     4
+#define VEOL     5
+#define VEOL2    6
+#define VSWTC    7
+#define VSTART   8
+#define VSTOP    9
+#define VSUSP    10
+#define VDSUSP   11  /* SunOS POSIX nicety I do believe... */
+#define VREPRINT 12
+#define VDISCARD 13
+#define VWERASE  14
+#define VLNEXT   15
+#define VMIN     VEOF
+#define VTIME    VEOL
+
+#ifdef __KERNEL__
+/*	intr=^C		quit=^|		erase=del	kill=^U
+	eof=^D		vtime=\0	vmin=\1		sxtc=\0
+	start=^Q	stop=^S		susp=^Z		eol=\0
+	reprint=^R	discard=^U	werase=^W	lnext=^V
+	eol2=\0
+*/
+#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0"
+#endif
+
+/* c_iflag bits */
+#define IGNBRK	0x00000001
+#define BRKINT	0x00000002
+#define IGNPAR	0x00000004
+#define PARMRK	0x00000008
+#define INPCK	0x00000010
+#define ISTRIP	0x00000020
+#define INLCR	0x00000040
+#define IGNCR	0x00000080
+#define ICRNL	0x00000100
+#define IUCLC	0x00000200
+#define IXON	0x00000400
+#define IXANY	0x00000800
+#define IXOFF	0x00001000
+#define IMAXBEL	0x00002000
+
+/* c_oflag bits */
+#define OPOST	0x00000001
+#define OLCUC	0x00000002
+#define ONLCR	0x00000004
+#define OCRNL	0x00000008
+#define ONOCR	0x00000010
+#define ONLRET	0x00000020
+#define OFILL	0x00000040
+#define OFDEL	0x00000080
+#define NLDLY	0x00000100
+#define   NL0	0x00000000
+#define   NL1	0x00000100
+#define CRDLY	0x00000600
+#define   CR0	0x00000000
+#define   CR1	0x00000200
+#define   CR2	0x00000400
+#define   CR3	0x00000600
+#define TABDLY	0x00001800
+#define   TAB0	0x00000000
+#define   TAB1	0x00000800
+#define   TAB2	0x00001000
+#define   TAB3	0x00001800
+#define   XTABS	0x00001800
+#define BSDLY	0x00002000
+#define   BS0	0x00000000
+#define   BS1	0x00002000
+#define VTDLY	0x00004000
+#define   VT0	0x00000000
+#define   VT1	0x00004000
+#define FFDLY	0x00008000
+#define   FF0	0x00000000
+#define   FF1	0x00008000
+#define PAGEOUT 0x00010000  /* SUNOS specific */
+#define WRAP    0x00020000  /* SUNOS specific */
+
+/* c_cflag bit meaning */
+#define CBAUD	0x0000000f
+#define  B0	0x00000000   /* hang up */
+#define  B50	0x00000001
+#define  B75	0x00000002
+#define  B110	0x00000003
+#define  B134	0x00000004
+#define  B150	0x00000005
+#define  B200	0x00000006
+#define  B300	0x00000007
+#define  B600	0x00000008
+#define  B1200	0x00000009
+#define  B1800	0x0000000a
+#define  B2400	0x0000000b
+#define  B4800	0x0000000c
+#define  B9600	0x0000000d
+#define  B19200	0x0000000e
+#define  B38400	0x0000000f
+#define EXTA    B19200
+#define EXTB    B38400
+#define  CSIZE  0x00000030
+#define   CS5	0x00000000
+#define   CS6	0x00000010
+#define   CS7	0x00000020
+#define   CS8	0x00000030
+#define CSTOPB	0x00000040
+#define CREAD	0x00000080
+#define PARENB	0x00000100
+#define PARODD	0x00000200
+#define HUPCL	0x00000400
+#define CLOCAL	0x00000800
+/* We'll never see these speeds with the Zilogs' but for completeness... */
+#define CBAUDEX 0x00010000
+#define  B57600  0x00010001
+#define  B115200 0x00010002
+#define  B230400 0x00010003
+#define CIBAUD	  0x000f0000  /* input baud rate (not used) */
+#define CRTSCTS	  0x80000000  /* flow control */
+
+/* c_lflag bits */
+#define ISIG	0x00000001
+#define ICANON	0x00000002
+#define XCASE	0x00000004
+#define ECHO	0x00000008
+#define ECHOE	0x00000010
+#define ECHOK	0x00000020
+#define ECHONL	0x00000040
+#define NOFLSH	0x00000080
+#define TOSTOP	0x00000100
+#define ECHOCTL	0x00000200
+#define ECHOPRT	0x00000400
+#define ECHOKE	0x00000800
+#define DEFECHO 0x00001000  /* SUNOS thing, what is it? */
+#define FLUSHO	0x00002000
+#define PENDIN	0x00004000
+#define IEXTEN	0x00008000
+
+/* modem lines */
+#define TIOCM_LE	0x001
+#define TIOCM_DTR	0x002
+#define TIOCM_RTS	0x004
+#define TIOCM_ST	0x008
+#define TIOCM_SR	0x010
+#define TIOCM_CTS	0x020
+#define TIOCM_CAR	0x040
+#define TIOCM_RNG	0x080
+#define TIOCM_DSR	0x100
+#define TIOCM_CD	TIOCM_CAR
+#define TIOCM_RI	TIOCM_RNG
+
+/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
+#define TIOCSER_TEMT    0x01	/* Transmitter physically empty */
+
+
+/* tcflow() and TCXONC use these */
+#define	TCOOFF		0
+#define	TCOON		1
+#define	TCIOFF		2
+#define	TCION		3
+
+/* tcflush() and TCFLSH use these */
+#define	TCIFLUSH	0
+#define	TCOFLUSH	1
+#define	TCIOFLUSH	2
+
+/* tcsetattr uses these */
+#define	TCSANOW		0
+#define	TCSADRAIN	1
+#define	TCSAFLUSH	2
+
+/* line disciplines */
+#define N_TTY		0
+#define N_SLIP		1
+#define N_MOUSE		2
+#define N_PPP		3
+
+#ifdef __KERNEL__
+
+/*
+ * Translate a "termio" structure into a "termios". Ugh.
+ */
+extern inline void trans_from_termio(struct termio * termio,
+	struct termios * termios)
+{
+#define SET_LOW_BITS(x,y)	((x) = (0xffff0000 & (x)) | (y))
+	SET_LOW_BITS(termios->c_iflag, termio->c_iflag);
+	SET_LOW_BITS(termios->c_oflag, termio->c_oflag);
+	SET_LOW_BITS(termios->c_cflag, termio->c_cflag);
+	SET_LOW_BITS(termios->c_lflag, termio->c_lflag);
+#undef SET_LOW_BITS
+	memcpy(termios->c_cc, termio->c_cc, NCC);
+}
+
+/*
+ * Translate a "termios" structure into a "termio". Ugh.
+ */
+extern inline void trans_to_termio(struct termios * termios,
+	struct termio * termio)
+{
+	termio->c_iflag = termios->c_iflag;
+	termio->c_oflag = termios->c_oflag;
+	termio->c_cflag = termios->c_cflag;
+	termio->c_lflag = termios->c_lflag;
+	termio->c_line	= termios->c_line;
+	memcpy(termio->c_cc, termios->c_cc, NCC);
+}
+
+#endif	/* __KERNEL__ */
+
+#endif /* _SPARC_TERMIOS_H */
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/timer.h linux/include/asm-sparc/timer.h
--- v1.3.43/linux/include/asm-sparc/timer.h	Tue Jun 27 14:11:46 1995
+++ linux/include/asm-sparc/timer.h	Sat Nov 25 04:33:04 1995
@@ -1,4 +1,5 @@
-/* timer.h:  Definitions for the timer chips on the Sparc.
+/* $Id: timer.h,v 1.10 1995/11/25 02:33:03 davem Exp $
+ * timer.h:  Definitions for the timer chips on the Sparc.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  */
@@ -78,6 +79,7 @@
 };
 
 extern struct sun4m_timer_regs *sun4m_timers;
+extern volatile unsigned int *master_l10_counter;
 extern volatile unsigned int *master_l10_limit;
 
 #endif /* !(_SPARC_TIMER_H) */
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/traps.h linux/include/asm-sparc/traps.h
--- v1.3.43/linux/include/asm-sparc/traps.h	Tue Jun 27 14:11:46 1995
+++ linux/include/asm-sparc/traps.h	Sat Nov 25 04:33:06 1995
@@ -1,4 +1,5 @@
-/* traps.h:  Format of entries for the Sparc trap table.
+/* $Id: traps.h,v 1.5 1995/11/25 02:33:05 davem Exp $
+ * traps.h:  Format of entries for the Sparc trap table.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  */
@@ -38,6 +39,14 @@
 extern struct tt_v9_entry *sparc_v9_ttablel0;
 extern struct tt_v9_entry *sparc_v9_ttablel1;
 
+extern __inline__ unsigned long get_tbr(void)
+{
+	unsigned long tbr;
+
+	__asm__ __volatile__("rd %%tbr, %0\n\t" : "=r" (tbr));
+	return tbr;
+}
+
 /* For patching the trap table at boot time, we need to know how to
  * form various common Sparc instructions.  Thus these macros...
  */
@@ -105,6 +114,16 @@
 #define SP_TRAP_SOLARIS 0x88         /* Solaris System Call */
 #define SP_TRAP_NETBSD  0x89         /* NetBSD System Call */
 #define SP_TRAP_LINUX   0x90         /* Linux System Call */
+
+/* Names used for compatibility with SunOS */
+#define ST_SYSCALL              0x00
+#define ST_BREAKPOINT           0x01
+#define ST_DIV0                 0x02
+#define ST_FLUSH_WINDOWS        0x03
+#define ST_CLEAN_WINDOWS        0x04
+#define ST_RANGE_CHECK          0x05
+#define ST_FIX_ALIGN            0x06
+#define ST_INT_OVERFLOW         0x07
 
 /* Special traps... */
 #define SP_TRAP_KBPT1   0xfe         /* KADB/PROM Breakpoint one */
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/tsunami.h linux/include/asm-sparc/tsunami.h
--- v1.3.43/linux/include/asm-sparc/tsunami.h	Tue Jun 27 14:11:46 1995
+++ linux/include/asm-sparc/tsunami.h	Sat Nov 25 04:33:07 1995
@@ -1,4 +1,5 @@
-/* tsunami.h:  Module specific definitions for Tsunami V8 Sparcs
+/* $Id: tsunami.h,v 1.2 1995/11/25 02:33:06 davem Exp $
+ * tsunami.h:  Module specific definitions for Tsunami V8 Sparcs
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  */
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/types.h linux/include/asm-sparc/types.h
--- v1.3.43/linux/include/asm-sparc/types.h	Thu Feb  2 08:42:35 1995
+++ linux/include/asm-sparc/types.h	Sat Nov 25 04:33:09 1995
@@ -1,3 +1,4 @@
+/* $Id: types.h,v 1.8 1995/11/25 02:33:08 davem Exp $ */
 #ifndef _SPARC_TYPES_H
 #define _SPARC_TYPES_H
 
@@ -6,10 +7,6 @@
  * header files exported to user space   <-- Linus sez this
  */
 
-/* NOTE: I will have to change these when the V9 sparcs come into play,
- *       however this won't be for a while.
- */
-
 #ifndef _SIZE_T
 #define _SIZE_T
 #ifdef __svr4__
@@ -26,9 +23,30 @@
 
 #ifndef _PTRDIFF_T
 #define _PTRDIFF_T
-typedef int ptrdiff_t;
+typedef long int ptrdiff_t;
+#endif
+
+#ifndef _TIME_T
+#define _TIME_T
+typedef long time_t;
 #endif
 
+#ifndef _CLOCK_T
+#define _CLOCK_T
+typedef long clock_t;
+#endif
+
+typedef int pid_t;
+typedef unsigned short uid_t;
+typedef unsigned short gid_t;
+typedef unsigned short dev_t;
+typedef unsigned long ino_t;
+typedef unsigned short mode_t;
+typedef unsigned short umode_t;
+typedef short nlink_t;
+typedef long daddr_t;
+typedef long off_t;
+
 typedef signed char __s8;
 typedef unsigned char __u8;
 
@@ -38,8 +56,6 @@
 typedef signed int __s32;
 typedef unsigned int __u32;
 
-/* Only 32-bit sparcs for now so.... */
-
 typedef signed long long __s64;
 typedef unsigned long long __u64;
 
@@ -54,11 +70,62 @@
 typedef signed int s32;
 typedef unsigned int u32;
 
-/* Again, only have to worry about 32-bits */
-
 typedef signed long long s64;
 typedef unsigned long long u64;
 
 #endif /* __KERNEL__ */
+
+#undef __FD_SET
+static __inline__ void __FD_SET(unsigned long fd, fd_set *fdsetp)
+{
+	unsigned long _tmp = fd / __NFDBITS;
+	unsigned long _rem = fd % __NFDBITS;
+	fdsetp->fds_bits[_tmp] |= (1UL<<_rem);
+}
+
+#undef __FD_CLR
+static __inline__ void __FD_CLR(unsigned long fd, fd_set *fdsetp)
+{
+	unsigned long _tmp = fd / __NFDBITS;
+	unsigned long _rem = fd % __NFDBITS;
+	fdsetp->fds_bits[_tmp] &= ~(1UL<<_rem);
+}
+
+#undef __FD_ISSET
+static __inline__ int __FD_ISSET(unsigned long fd, fd_set *p)
+{ 
+	unsigned long _tmp = fd / __NFDBITS;
+	unsigned long _rem = fd % __NFDBITS;
+	return (p->fds_bits[_tmp] & (1UL<<_rem)) != 0;
+}
+
+/*
+ * This will unroll the loop for the normal constant cases (4 or 8 longs,
+ * for 256 and 512-bit fd_sets respectively)
+ */
+#undef __FD_ZERO
+static __inline__ void __FD_ZERO(fd_set *p)
+{
+	unsigned int *tmp = p->fds_bits;
+	int i;
+
+	if (__builtin_constant_p(__FDSET_INTS)) {
+		switch (__FDSET_INTS) {
+			case 8:
+				tmp[0] = 0; tmp[1] = 0; tmp[2] = 0; tmp[3] = 0;
+				tmp[4] = 0; tmp[5] = 0; tmp[6] = 0; tmp[7] = 0;
+				return;
+			case 4:
+				tmp[0] = 0; tmp[1] = 0; tmp[2] = 0; tmp[3] = 0;
+				return;
+		}
+	}
+	i = __FDSET_INTS;
+	while (i) {
+		i--;
+		*tmp = 0;
+		tmp++;
+	}
+}
 
 #endif /* defined(_SPARC_TYPES_H) */
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/ultra.h linux/include/asm-sparc/ultra.h
--- v1.3.43/linux/include/asm-sparc/ultra.h	Tue Jun 27 14:11:46 1995
+++ linux/include/asm-sparc/ultra.h	Sat Nov 25 04:33:11 1995
@@ -1,4 +1,5 @@
-/* ultra.h: Definitions and defines for the TI V9 UltraSparc.
+/* $Id: ultra.h,v 1.2 1995/11/25 02:33:10 davem Exp $
+ * ultra.h: Definitions and defines for the TI V9 UltraSparc.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  */
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/unistd.h linux/include/asm-sparc/unistd.h
--- v1.3.43/linux/include/asm-sparc/unistd.h	Tue Jun 27 14:11:46 1995
+++ linux/include/asm-sparc/unistd.h	Sat Nov 25 04:33:14 1995
@@ -1,3 +1,4 @@
+/* $Id: unistd.h,v 1.15 1995/11/25 02:33:12 davem Exp $ */
 #ifndef _SPARC_UNISTD_H
 #define _SPARC_UNISTD_H
 
@@ -9,23 +10,271 @@
  * before the trap into the system call with gcc 'asm' statements.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ *
+ * SunOS compatability based upon preliminary work which is:
+ *
+ * Copyright (C) 1995 Adrian M. Rodriguez (adrian@remus.rutgers.edu)
  */
 
-/* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */
+#define __NR_setup                0 /* Used only by init, to get system going.     */
+#define __NR_exit                 1 /* Common                                      */
+#define __NR_fork                 2 /* Common                                      */
+#define __NR_read                 3 /* Common                                      */
+#define __NR_write                4 /* Common                                      */
+#define __NR_open                 5 /* Common                                      */
+#define __NR_close                6 /* Common                                      */
+#define __NR_wait4                7 /* Common                                      */
+#define __NR_creat                8 /* Common                                      */
+#define __NR_link                 9 /* Common                                      */
+#define __NR_unlink              10 /* Common                                      */
+#define __NR_execv               11 /* SunOS Specific                              */
+#define __NR_chdir               12 /* Common                                      */
+/* #define __NR_ni_syscall       13    ENOSYS under SunOS                          */
+#define __NR_mknod               14 /* Common                                      */
+#define __NR_chmod               15 /* Common                                      */
+#define __NR_chown               16 /* Common                                      */
+#define __NR_brk                 17 /* Common                                      */
+/* #define __NR_ni_syscall       18    ENOSYS under SunOS                          */
+#define __NR_lseek               19 /* Common                                      */
+#define __NR_getpid              20 /* Common                                      */
+/* #define __NR_ni_syscall       21    ENOSYS under SunOS                          */
+/* #define __NR_ni_syscall       22    ENOSYS under SunOS                          */
+#define __NR_setuid              23 /* Implemented via setreuid in SunOS           */
+#define __NR_getuid              24 /* Common                                      */
+/* #define __NR_ni_syscall       25    ENOSYS under SunOS                          */
+#define __NR_ptrace              26 /* Common                                      */
+#define __NR_alarm               27 /* Implemented via setitimer in SunOS          */
+/* #define __NR_ni_syscall       28    ENOSYS under SunOS                          */
+#define __NR_pause               29 /* Is sigblock(0)->sigpause() in SunOS         */
+#define __NR_utime               30 /* Implemented via utimes() under SunOS        */
+#define __NR_stty                31 /* Implemented via ioctl() under SunOS         */
+#define __NR_gtty                32 /* Implemented via ioctl() under SunOS         */
+#define __NR_access              33 /* Common                                      */
+#define __NR_nice                34 /* Implemented via get/setpriority() in SunOS  */
+#define __NR_ftime               35 /* Implemented via gettimeofday() in SunOS     */
+#define __NR_sync                36 /* Common                                      */
+#define __NR_kill                37 /* Common                                      */
+#define __NR_stat                38 /* Common                                      */
+/* #define __NR_ni_syscall       39    ENOSYS under SunOS                          */
+#define __NR_lstat               40 /* Common                                      */
+#define __NR_dup                 41 /* Common                                      */
+#define __NR_pipe                42 /* Common                                      */
+#define __NR_times               43 /* Implemented via getrusage() in SunOS        */
+#define __NR_profil              44 /* Common                                      */
+/* #define __NR_ni_syscall       45    ENOSYS under SunOS                          */
+#define __NR_setgid              46 /* Implemented via setregid() in SunOS         */
+#define __NR_getgid              47 /* Common                                      */
+#define __NR_signal              48 /* Implemented via sigvec() in SunOS           */
+#define __NR_geteuid             49 /* SunOS calls getuid()                        */
+#define __NR_getegid             50 /* SunOS calls getgid()                        */
+#define __NR_acct                51 /* Common                                      */
+/* #define __NR_ni_syscall       52    ENOSYS under SunOS                          */
+#define __NR_mctl                53 /* SunOS specific                              */
+#define __NR_ioctl               54 /* Common                                      */
+#define __NR_reboot              55 /* Common                                      */
+/* #define __NR_ni_syscall       56    ENOSYS under SunOS                          */
+#define __NR_symlink             57 /* Common                                      */
+#define __NR_readlink            58 /* Common                                      */
+#define __NR_execve              59 /* Common                                      */
+#define __NR_umask               60 /* Common                                      */
+#define __NR_chroot              61 /* Common                                      */
+#define __NR_fstat               62 /* Common                                      */
+/* #define __NR_ni_syscall       63    ENOSYS under SunOS                          */
+#define __NR_getpagesize         64 /* Common                                      */
+#define __NR_msync               65 /* Common in newer 1.3.x revs...               */
+/* #define __NR_ni_syscall       66    ENOSYS under SunOS                          */
+/* #define __NR_ni_syscall       67    ENOSYS under SunOS                          */
+/* #define __NR_ni_syscall       68    ENOSYS under SunOS                          */
+#define __NR_sbrk                69 /* SunOS Specific                              */
+#define __NR_sstk                70 /* SunOS Specific                              */
+#define __NR_mmap                71 /* Common                                      */
+#define __NR_vadvise             72 /* SunOS Specific                              */
+#define __NR_munmap              73 /* Common                                      */
+#define __NR_mprotect            74 /* Common                                      */
+#define __NR_madvise             75 /* SunOS Specific                              */
+#define __NR_vhangup             76 /* Common                                      */
+/* #define __NR_ni_syscall       77    ENOSYS under SunOS                          */
+#define __NR_mincore             78 /* SunOS Specific                              */
+#define __NR_getgroups           79 /* Common                                      */
+#define __NR_setgroups           80 /* Common                                      */
+#define __NR_getpgrp             81 /* Common                                      */
+#define __NR_setpgrp             82 /* setpgid, same difference...                 */
+#define __NR_setitimer           83 /* Common                                      */
+/* #define __NR_ni_syscall       84    ENOSYS under SunOS                          */
+#define __NR_swapon              85 /* Common                                      */
+#define __NR_getitimer           86 /* Common                                      */
+#define __NR_gethostname         87 /* SunOS Specific                              */
+#define __NR_sethostname         88 /* Common                                      */
+#define __NR_getdtablesize       89 /* SunOS Specific                              */
+#define __NR_dup2                90 /* Common                                      */
+#define __NR_getdopt             91 /* SunOS Specific                              */
+#define __NR_fcntl               92 /* Common                                      */
+#define __NR_select              93 /* Common                                      */
+#define __NR_setdopt             94 /* SunOS Specific                              */
+#define __NR_fsync               95 /* Common                                      */
+#define __NR_setpriority         96 /* Common                                      */
+#define __NR_socket              97 /* SunOS Specific                              */
+#define __NR_connect             98 /* SunOS Specific                              */
+#define __NR_accept              99 /* SunOS Specific                              */
+#define __NR_getpriority        100 /* Common                                      */
+#define __NR_send               101 /* SunOS Specific                              */
+#define __NR_recv               102 /* SunOS Specific                              */
+/* #define __NR_ni_syscall      103    ENOSYS under SunOS                          */
+#define __NR_bind               104 /* SunOS Specific                              */
+#define __NR_setsockopt         105 /* SunOS Specific                              */
+#define __NR_listen             106 /* SunOS Specific                              */
+/* #define __NR_ni_syscall      107    ENOSYS under SunOS                          */
+#define __NR_sigvec             108 /* SunOS Specific                              */
+#define __NR_sigblock           109 /* SunOS Specific                              */
+#define __NR_sigsetmask         110 /* SunOS Specific                              */
+#define __NR_sigpause           111 /* SunOS Specific                              */
+#define __NR_sigstack           112 /* SunOS Specific                              */
+#define __NR_recvmsg            113 /* SunOS Specific                              */
+#define __NR_sendmsg            114 /* SunOS Specific                              */
+#define __NR_vtrace             115 /* SunOS Specific                              */
+#define __NR_gettimeofday       116 /* Common                                      */
+#define __NR_getrusage          117 /* Common                                      */
+#define __NR_getsockopt         118 /* SunOS Specific                              */
+/* #define __NR_ni_syscall      119    ENOSYS under SunOS                          */
+#define __NR_readv              120 /* Common                                      */
+#define __NR_writev             121 /* Common                                      */
+#define __NR_settimeofday       122 /* Common                                      */
+#define __NR_fchown             123 /* Common                                      */
+#define __NR_fchmod             124 /* Common                                      */
+#define __NR_recvfrom           125 /* SunOS Specific                              */
+#define __NR_setreuid           126 /* Common                                      */
+#define __NR_setregid           127 /* Common                                      */
+#define __NR_rename             128 /* Common                                      */
+#define __NR_truncate           129 /* Common                                      */
+#define __NR_ftruncate          130 /* Common                                      */
+#define __NR_flock              131 /* Common                                      */
+/* #define __NR_ni_syscall      132    ENOSYS under SunOS                          */
+#define __NR_sendto             133 /* SunOS Specific                              */
+#define __NR_shutdown           134 /* SunOS Specific                              */
+#define __NR_socketpair         135 /* SunOS Specific                              */
+#define __NR_mkdir              136 /* Common                                      */
+#define __NR_rmdir              137 /* Common                                      */
+#define __NR_utimes             138 /* SunOS Specific                              */
+/* #define __NR_ni_syscall      139    ENOSYS under SunOS                          */
+#define __NR_adjtime            140 /* SunOS Specific                              */
+#define __NR_getpeername        141 /* SunOS Specific                              */
+#define __NR_gethostid          142 /* SunOS Specific                              */
+/* #define __NR_ni_syscall      143    ENOSYS under SunOS                          */
+#define __NR_getrlimit          144 /* Common                                      */
+#define __NR_setrlimit          145 /* Common                                      */
+#define __NR_killpg             146 /* SunOS Specific                              */
+/* #define __NR_ni_syscall      147    ENOSYS under SunOS                          */
+/* #define __NR_ni_syscall      148    ENOSYS under SunOS                          */
+/* #define __NR_ni_syscall      149    ENOSYS under SunOS                          */
+#define __NR_getsockname        150 /* SunOS Specific                              */
+#define __NR_getmsg             151 /* SunOS Specific                              */
+#define __NR_putmsg             152 /* SunOS Specific                              */
+#define __NR_poll               153 /* SunOS Specific                              */
+/* #define __NR_ni_syscall      154    ENOSYS under SunOS                          */
+#define __NR_nfssvc             155 /* SunOS Specific                              */
+#define __NR_getdirentries      156 /* SunOS Specific                              */
+#define __NR_statfs             157 /* Common                                      */
+#define __NR_fstatfs            158 /* Common                                      */
+#define __NR_umount             159 /* Common                                      */
+#define __NR_async_daemon       160 /* SunOS Specific                              */
+#define __NR_getfh              161 /* SunOS Specific                              */
+#define __NR_getdomainname      162 /* SunOS Specific                              */
+#define __NR_setdomainname      163 /* Common                                      */
+/* #define __NR_ni_syscall      164    ENOSYS under SunOS                          */
+#define __NR_quotactl           165 /* Common                                      */
+#define __NR_exportfs           166 /* SunOS Specific                              */
+#define __NR_mount              167 /* Common                                      */
+#define __NR_ustat              168 /* Common                                      */
+#define __NR_semsys             169 /* SunOS Specific                              */
+#define __NR_msgsys             170 /* SunOS Specific                              */
+#define __NR_shmsys             171 /* SunOS Specific                              */
+#define __NR_auditsys           172 /* SunOS Specific                              */
+#define __NR_rfssys             173 /* SunOS Specific                              */
+#define __NR_getdents           174 /* Common                                      */
+#define __NR_setsid             175 /* Common                                      */
+#define __NR_fchdir             176 /* Common                                      */
+#define __NR_fchroot            177 /* SunOS Specific                              */
+#define __NR_vpixsys            178 /* SunOS Specific                              */
+#define __NR_aioread            179 /* SunOS Specific                              */
+#define __NR_aiowrite           180 /* SunOS Specific                              */
+#define __NR_aiowait            181 /* SunOS Specific                              */
+#define __NR_aiocancel          182 /* SunOS Specific                              */
+#define __NR_sigpending         183 /* Common                                      */
+/* #define __NR_ni_syscall      184    ENOSYS under SunOS                          */
+#define __NR_setpgid            185 /* Common                                      */
+#define __NR_pathconf           186 /* SunOS Specific                              */
+#define __NR_fpathconf          187 /* SunOS Specific                              */
+#define __NR_sysconf            188 /* SunOS Specific                              */
+#define __NR_uname              189 /* Linux Specific                              */
+#define __NR_init_module        190 /* Linux Specific                              */
+#define __NR_personality        191 /* Linux Specific                              */
+#define __NR_prof               192 /* Linux Specific                              */
+#define __NR_break              193 /* Linux Specific                              */
+#define __NR_lock               194 /* Linux Specific                              */
+#define __NR_mpx                195 /* Linux Specific                              */
+#define __NR_ulimit             196 /* Linux Specific                              */
+#define __NR_getppid            197 /* Linux Specific                              */
+#define __NR_sigaction          198 /* Linux Specific                              */
+#define __NR_sgetmask           199 /* Linux Specific                              */
+#define __NR_ssetmask           200 /* Linux Specific                              */
+#define __NR_sigsuspend         201 /* Linux Specific                              */
+#define __NR_oldlstat           202 /* Linux Specific                              */
+#define __NR_uselib             203 /* Linux Specific                              */
+#define __NR_readdir            204 /* Linux Specific                              */
+#define __NR_ioperm             205 /* Linux Specific - i386 specific, unused      */
+#define __NR_socketcall         206 /* Linux Specific                              */
+#define __NR_syslog             207 /* Linux Specific                              */
+#define __NR_olduname           208 /* Linux Specific                              */
+#define __NR_iopl               209 /* Linux Specific - i386 specific, unused      */
+#define __NR_idle               210 /* Linux Specific                              */
+#define __NR_vm86               211 /* Linux Specific - i386 specific, unused      */
+#define __NR_waitpid            212 /* Linux Specific                              */
+#define __NR_swapoff            213 /* Linux Specific                              */
+#define __NR_sysinfo            214 /* Linux Specific                              */
+#define __NR_ipc                215 /* Linux Specific                              */
+#define __NR_sigreturn          216 /* Linux Specific                              */
+#define __NR_clone              217 /* Linux Specific                              */
+#define __NR_modify_ldt         218 /* Linux Specific - i386 specific, unused      */
+#define __NR_adjtimex           219 /* Linux Specific                              */
+#define __NR_sigprocmask        220 /* Linux Specific                              */
+#define __NR_create_module      221 /* Linux Specific                              */
+#define __NR_delete_module      222 /* Linux Specific                              */
+#define __NR_get_kernel_syms    223 /* Linux Specific                              */
+#define __NR_getpgid            224 /* Linux Specific                              */
+#define __NR_bdflush            225 /* Linux Specific                              */
+#define __NR_sysfs              226 /* Linux Specific                              */
+#define __NR_afs_syscall        227 /* Linux Specific                              */
+#define __NR_setfsuid           228 /* Linux Specific                              */
+#define __NR_setfsgid           229 /* Linux Specific                              */
+#define __NR__newselect         230 /* Linux Specific                              */
+#define __NR_time               231 /* Linux Specific                              */
+#define __NR_oldstat            232 /* Linux Specific                              */
+#define __NR_stime              233 /* Linux Specific                              */
+#define __NR_oldfstat           234 /* Linux Specific                              */
+#define __NR_phys               235 /* Linux Specific                              */
+#define __NR__llseek            236 /* Linux Specific                              */
+#define __NR_mlock              237
+#define __NR_munlock            238
+#define __NR_mlockall           239
+#define __NR_munlockall         240
+
+/* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar.
+ * XXX These need to be fixed to check the condition codes to see
+ * XXX the return value is an errorno or success.
+ */
 #define _syscall0(type,name) \
 type name(void) \
 { \
 long __res; \
-__asm__ volatile ("or %%g0, %0, %%o0\n\t" \
+__asm__ volatile ("or %%g0, %0, %%g1\n\t" \
 		  "t 0x10\n\t" \
-		  "nop\n\t" \
 		  "or %%g0, %%o0, %0\n\t" \
 		  : "=r" (__res) \
 		  : "0" (__NR_##name) \
-		  : "o0"); \
+		  : "g1"); \
 if (__res >= 0) \
     return (type) __res; \
-errno = -__res; \
+errno = __res; \
 return -1; \
 }
 
@@ -33,17 +282,16 @@
 type name(type1 arg1) \
 { \
 long __res; \
-__asm__ volatile ("or %%g0, %0, %%o0\n\t" \
-		  "or %%g0, %1, %%o1\n\t" \
+__asm__ volatile ("or %%g0, %0, %%g1\n\t" \
+		  "or %%g0, %1, %%o0\n\t" \
 		  "t 0x10\n\t" \
-		  "nop\n\t" \
 		  "or %%g0, %%o0, %0\n\t" \
 		  : "=r" (__res), "=r" ((long)(arg1)) \
 		  : "0" (__NR_##name),"1" ((long)(arg1)) \
-		  : "o0", "o1"); \
+		  : "g1", "o0"); \
 if (__res >= 0) \
 	return (type) __res; \
-errno = -__res; \
+errno = __res; \
 return -1; \
 }
 
@@ -51,18 +299,17 @@
 type name(type1 arg1,type2 arg2) \
 { \
 long __res; \
-__asm__ volatile ("or %%g0, %0, %%o0\n\t" \
-		  "or %%g0, %1, %%o1\n\t" \
-		  "or %%g0, %2, %%o2\n\t" \
+__asm__ volatile ("or %%g0, %0, %%g1\n\t" \
+		  "or %%g0, %1, %%o0\n\t" \
+		  "or %%g0, %2, %%o1\n\t" \
 		  "t 0x10\n\t" \
-		  "nop\n\t" \
 		  "or %%g0, %%o0, %0\n\t" \
-		  : "=r" (__res), "=r" ((long)(arg1)), "=r" ((long)(args)) \
+		  : "=r" (__res), "=r" ((long)(arg1)), "=r" ((long)(arg2)) \
 		  : "0" (__NR_##name),"1" ((long)(arg1)),"2" ((long)(arg2)) \
-		  : "o0", "o1", "o2"); \
+		  : "g1", "o0", "o1"); \
 if (__res >= 0) \
 	return (type) __res; \
-errno = -__res; \
+errno = __res; \
 return -1; \
 }
 
@@ -70,21 +317,20 @@
 type name(type1 arg1,type2 arg2,type3 arg3) \
 { \
 long __res; \
-__asm__ volatile ("or %%g0, %0, %%o0\n\t" \
-		  "or %%g0, %1, %%o1\n\t" \
-		  "or %%g0, %2, %%o2\n\t" \
-		  "or %%g0, %3, %%o3\n\t" \
+__asm__ volatile ("or %%g0, %0, %%g1\n\t" \
+		  "or %%g0, %1, %%o0\n\t" \
+		  "or %%g0, %2, %%o1\n\t" \
+		  "or %%g0, %3, %%o2\n\t" \
 		  "t 0x10\n\t" \
-		  "nop\n\t" \
 		  "or %%g0, %%o0, %0\n\t" \
 		  : "=r" (__res), "=r" ((long)(arg1)), "=r" ((long)(arg2)), \
 		    "=r" ((long)(arg3)) \
 		  : "0" (__NR_##name), "1" ((long)(arg1)), "2" ((long)(arg2)), \
 		    "3" ((long)(arg3)) \
-		  : "o0", "o1", "o2", "o3"); \
+		  : "g1", "o0", "o1", "o2"); \
 if (__res>=0) \
 	return (type) __res; \
-errno=-__res; \
+errno = __res; \
 return -1; \
 }
 
@@ -92,22 +338,21 @@
 type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
 { \
 long __res; \
-__asm__ volatile ("or %%g0, %0, %%o0\n\t" \
-		  "or %%g0, %1, %%o1\n\t" \
-		  "or %%g0, %2, %%o2\n\t" \
-		  "or %%g0, %3, %%o3\n\t" \
-		  "or %%g0, %4, %%o4\n\t" \
+__asm__ volatile ("or %%g0, %0, %%g1\n\t" \
+		  "or %%g0, %1, %%o0\n\t" \
+		  "or %%g0, %2, %%o1\n\t" \
+		  "or %%g0, %3, %%o2\n\t" \
+		  "or %%g0, %4, %%o3\n\t" \
 		  "t 0x10\n\t" \
-		  "nop\n\t" \
 		  "or %%g0, %%o0, %0\n\t" \
 		  : "=r" (__res), "=r" ((long)(arg1)), "=r" ((long)(arg2)), \
 		    "=r" ((long)(arg3)), "=r" ((long)(arg4)) \
 		  : "0" (__NR_##name),"1" ((long)(arg1)),"2" ((long)(arg2)), \
 		    "3" ((long)(arg3)),"4" ((long)(arg4)) \
-		  : "o0", "o1", "o2", "o3", "o4"); \
+		  : "g1", "o0", "o1", "o2", "o3"); \
 if (__res>=0) \
 	return (type) __res; \
-errno=-__res; \
+errno = __res; \
 return -1; \
 } 
 
@@ -116,23 +361,22 @@
 type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
 { \
 long __res; \
-__asm__ volatile ("or %%g0, %0, %%o0\n\t" \
-		  "or %%g0, %1, %%o1\n\t" \
-		  "or %%g0, %2, %%o2\n\t" \
-		  "or %%g0, %3, %%o3\n\t" \
-		  "or %%g0, %4, %%o4\n\t" \
-		  "or %%g0, %5, %%o5\n\t" \
+__asm__ volatile ("or %%g0, %0, %%g1\n\t" \
+		  "or %%g0, %1, %%o0\n\t" \
+		  "or %%g0, %2, %%o1\n\t" \
+		  "or %%g0, %3, %%o2\n\t" \
+		  "or %%g0, %4, %%o3\n\t" \
+		  "or %%g0, %5, %%o4\n\t" \
 		  "t 0x10\n\t" \
-		  "nop\n\t" \
 		  "or %%g0, %%o0, %0\n\t" \
 		  : "=r" (__res), "=r" ((long)(arg1)), "=r" ((long)(arg2)), \
 		    "=r" ((long)(arg3)), "=r" ((long)(arg4)), "=r" ((long)(arg5)) \
 		  : "0" (__NR_##name),"1" ((long)(arg1)),"2" ((long)(arg2)), \
 		    "3" ((long)(arg3)),"4" ((long)(arg4)),"5" ((long)(arg5)) \
-		  : "o0", "o1", "o2", "o3", "o4", "o5"); \
+		  : "g1", "o0", "o1", "o2", "o3", "o4"); \
 if (__res>=0) \
 	return (type) __res; \
-errno=-__res; \
+errno = __res; \
 return -1; \
 }
 
@@ -153,6 +397,7 @@
 #define __NR__exit __NR_exit
 /* static inline _syscall0(int,idle) */
 static inline _syscall0(int,fork)
+static inline _syscall2(int,clone,unsigned long,flags,char *,ksp)
 static inline _syscall0(int,pause)
 /* static inline _syscall0(int,setup) */
 static inline _syscall0(int,sync)
@@ -168,32 +413,57 @@
 extern void sys_idle(void);
 static inline void idle(void)
 {
-	printk("[%d]idle()\n",current->pid);
 	sys_idle();
-	for(;;);
 }
 
 extern int sys_setup(void);
 static inline int setup(void)
 {
-	int retval;
-
-	printk("[%d]setup()\n",current->pid);
-	retval = sys_setup();
-	printk("[%d]setup() returned %d\n",current->pid, retval);
+	return sys_setup();
 }
 
 extern int sys_waitpid(int, int *, int);
 static inline pid_t wait(int * wait_stat)
 {
-	long retval, i;
-	printk("[%d]wait(%p)\n", current->pid, wait_stat);
+	long retval;
 	retval = waitpid(-1,wait_stat,0);
-	printk("[%d]wait(%p) returned %ld\n", current->pid, wait_stat, retval);
-	for (i = 0; i < 1000000000; i++);
 	return retval;
 }
 
-#endif
+/*
+ * This is the mechanism for creating a new kernel thread.
+ *
+ * NOTE! Only a kernel-only process(ie the swapper or direct descendants
+ * who haven't done an "execve()") should use this: it will work within
+ * a system call from a "real" process, but the process memory space will
+ * not be free'd until both the parent and the child have exited.
+ */
+static inline pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
+{
+	long retval;
+
+	__asm__ __volatile("mov %4, %%g2\n\t"    /* Set aside fn ptr... */
+			   "mov %5, %%g3\n\t"    /* and arg. */
+			   "mov %1, %%g1\n\t"
+			   "mov %2, %%o0\n\t"    /* Clone flags. */
+			   "mov 0, %%o1\n\t"     /* usp arg == 0 */
+			   "t 0x10\n\t"          /* Linux/Sparc clone(). */
+			   "cmp %%o1, 0\n\t"
+			   "be 1f\n\t"           /* The parent, just return. */
+			   " nop\n\t"            /* Delay slot. */
+			   "jmpl %%g2, %%o7\n\t" /* Call the function. */
+			   " mov %%g3, %%o0\n\t" /* Get back the arg in delay. */
+			   "mov %3, %%g1\n\t"
+			   "t 0x10\n\t"          /* Linux/Sparc exit(). */
+			   /* Notreached by child. */
+			   "1: mov %%o0, %0\n\t" :
+			   "=r" (retval) :
+			   "i" (__NR_clone), "r" (flags | CLONE_VM),
+			   "i" (__NR_exit),  "r" (fn), "r" (arg) :
+			   "g1", "g2", "g3", "o0", "o1", "memory");
+	return retval;
+}
+
+#endif /* __KERNEL_SYSCALLS__ */
 
 #endif /* _SPARC_UNISTD_H */
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/user.h linux/include/asm-sparc/user.h
--- v1.3.43/linux/include/asm-sparc/user.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-sparc/user.h	Sat Nov 25 04:33:17 1995
@@ -0,0 +1,29 @@
+/* $Id: user.h,v 1.2 1995/11/25 02:33:15 davem Exp $
+ * asm-sparc/user.h: Core file definitions for the Sparc.
+ *
+ * Copyright (C) 1995 (davem@caip.rutgers.edu)
+ */
+#ifndef _SPARC_USER_H
+#define _SPARC_USER_H
+
+struct user {
+	unsigned long regs[24 + 32]; /* locals, ins, globals + fpu regs */
+	size_t        u_tsize;
+	size_t        u_dsize;
+	size_t        u_ssize;
+	unsigned long start_code;
+	unsigned long start_data;
+	unsigned long start_stack;
+	int           signal;
+	unsigned long *u_ar0;
+	unsigned long magic;
+	char          u_comm[32];
+};
+
+#define NBPG                   PAGE_SIZE
+#define UPAGES                 1
+#define HOST_TEXT_START_ADDR   (u.start_code)
+#define HOST_DATA_START_ADDR   (u.start_data)
+#define HOST_STACK_END_ADDR    (u.start_stack + u.u_ssize * NBPG)
+
+#endif /* !(_SPARC_USER_H) */
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/vac-ops.h linux/include/asm-sparc/vac-ops.h
--- v1.3.43/linux/include/asm-sparc/vac-ops.h	Tue Jun 27 14:11:46 1995
+++ linux/include/asm-sparc/vac-ops.h	Sat Nov 25 04:33:19 1995
@@ -1,89 +1,171 @@
+/* $Id: vac-ops.h,v 1.7 1995/11/25 02:33:18 davem Exp $ */
 #ifndef _SPARC_VAC_OPS_H
 #define _SPARC_VAC_OPS_H
 
 /* vac-ops.h: Inline assembly routines to do operations on the Sparc
-              VAC (virtual address cache).
-
-   Copyright (C) 1994, David S. Miller (davem@caip.rutgers.edu)
-*/
-
-extern unsigned long *trapbase;
-extern char end, etext, edata;
-
-extern void flush_vac_context(void);
-extern void flush_vac_segment(unsigned int foo_segment);
-extern void flush_vac_page(unsigned int foo_addr);
-
-extern int vac_do_hw_vac_flushes, vac_size, vac_linesize;
-extern int vac_entries_per_context, vac_entries_per_segment;
-extern int vac_entries_per_page;
-
-/* enable_vac() enables the virtual address cache. It returns 0 on
-   success, 1 on failure.
-*/
-
-extern __inline__ int enable_vac(void)
-{
-  int success=0;
-
-  __asm__ __volatile__("lduba [%1] 2, %0\n\t"
-		       "or    %0, 0x10, %0\n\t"
-		       "stba  %0, [%1] 2\n\t"
-		       "or    %%g0, %%g0, %0" :
-		       "=r" (success) :
-		       "r" ((unsigned int) 0x40000000),
-		       "0" (success));
-  return success;
+ *            VAC (virtual address cache) for the sun4c.
+ *
+ * Copyright (C) 1994, David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#include <asm/sysen.h>
+#include <asm/contregs.h>
+#include <asm/asi.h>
+
+/* The SUN4C models have a virtually addressed write-through
+ * cache.
+ *
+ * The cache tags are directly accessible through an ASI and
+ * each have the form:
+ *
+ * ------------------------------------------------------------
+ * | MBZ | CONTEXT | WRITE | PRIV | VALID | MBZ | TagID | MBZ |
+ * ------------------------------------------------------------
+ *  31 25  24   22     21     20     19    18 16  15   2  1  0
+ *
+ * MBZ: These bits are either unused and/or reserved and should
+ *      be written as zeroes.
+ *
+ * CONTEXT: Records the context to which this cache line belongs.
+ *
+ * WRITE: A copy of the writable bit from the mmu pte access bits.
+ *
+ * PRIV: A copy of the privileged bit from the pte access bits.
+ *
+ * VALID: If set, this line is valid, else invalid.
+ *
+ * TagID: Fourteen bits of tag ID.
+ *
+ * Every virtual address is seen by the cache like this:
+ *
+ * ----------------------------------------
+ * |  RESV  | TagID | LINE | BYTE-in-LINE |
+ * ----------------------------------------
+ *  31    30 29   16 15   4 3            0
+ *
+ * RESV: Unused/reserved.
+ *
+ * TagID: Used to match the Tag-ID in that vac tags.
+ *
+ * LINE: Which line within the cache
+ *
+ * BYTE-in-LINE: Which byte within the cache line.
+ */
+
+/* Sun4c VAC Tags */
+#define S4CVACTAG_CID      0x01c00000
+#define S4CVACTAG_W        0x00200000
+#define S4CVACTAG_P        0x00100000
+#define S4CVACTAG_V        0x00080000
+#define S4CVACTAG_TID      0x0000fffc
+
+/* Sun4c VAC Virtual Address */
+#define S4CVACVA_TID       0x3fff0000
+#define S4CVACVA_LINE      0x0000fff0
+#define S4CVACVA_BIL       0x0000000f
+
+/* The indexing of cache lines creates a problem.  Because the line
+ * field of a virtual address extends past the page offset within
+ * the virtual address it is possible to have what are called
+ * 'bad aliases' which will create inconsistancies.  So we must make
+ * sure that within a context that if a physical page is mapped
+ * more than once, that 'extra' line bits are the same.  If this is
+ * not the case, and thus is a 'bad alias' we must turn off the
+ * cacheable bit in the pte's of all such pages.
+ */
+#define S4CVAC_BADBITS     0x0000f000
+
+/* The following is true if vaddr1 and vaddr2 would cause
+ * a 'bad alias'.
+ */
+#define S4CVAC_BADALIAS(vaddr1, vaddr2) \
+        (((unsigned long) (vaddr1)) ^ ((unsigned long) (vaddr2)) & \
+	 (S4CVAC_BADBITS))
+
+/* The following structure describes the characteristics of a sun4c
+ * VAC as probed from the prom during boot time.
+ */
+struct sun4c_vac_props {
+	unsigned int num_bytes;     /* Size of the cache */
+	unsigned int num_lines;     /* Number of cache lines */
+	unsigned int do_hwflushes;  /* Hardware flushing available? */
+	unsigned int linesize;      /* Size of each line in bytes */
+	unsigned int log2lsize;     /* log2(linesize) */
+	unsigned int on;            /* VAC is enabled */
+};
+
+extern struct sun4c_vac_props sun4c_vacinfo;
+
+extern void sun4c_flush_all(void);
+
+/* sun4c_enable_vac() enables the sun4c virtual address cache. */
+extern __inline__ void sun4c_enable_vac(void)
+{
+  __asm__ __volatile__("lduba [%0] %1, %%g1\n\t"
+		       "or    %%g1, %2, %%g1\n\t"
+		       "stba  %%g1, [%0] %1\n\t" : :
+		       "r" ((unsigned int) AC_SENABLE),
+		       "i" (ASI_CONTROL), "i" (SENABLE_CACHE) :
+		       "g1");
+  sun4c_vacinfo.on = 1;
+}
+
+/* sun4c_disable_vac() disables the virtual address cache. */
+extern __inline__ void sun4c_disable_vac(void)
+{
+  __asm__ __volatile__("lduba [%0] %1, %%g1\n\t"
+		       "andn  %%g1, %2, %%g1\n\t"
+		       "stba  %%g1, [%0] %1\n\t" : :
+		       "r" ((unsigned int) AC_SENABLE),
+		       "i" (ASI_CONTROL), "i" (SENABLE_CACHE) :
+		       "g1");
+  sun4c_vacinfo.on = 0;
+}
+
+extern unsigned long sun4c_ctxflush;
+extern unsigned long sun4c_segflush;
+extern unsigned long sun4c_pgflush;
+
+extern void sun4c_ctxflush_hw64KB16B(void);
+extern void sun4c_ctxflush_hw64KB32B(void);
+extern void sun4c_ctxflush_sw64KB16B(void);
+extern void sun4c_ctxflush_sw64KB32B(void);
+
+extern void sun4c_segflush_hw64KB16B(void);
+extern void sun4c_segflush_hw64KB32B(void);
+extern void sun4c_segflush_sw64KB16B(void);
+extern void sun4c_segflush_sw64KB32B(void);
+
+extern void sun4c_pgflush_hw64KB16B(void);
+extern void sun4c_pgflush_hw64KB32B(void);
+extern void sun4c_pgflush_sw64KB16B(void);
+extern void sun4c_pgflush_sw64KB32B(void);
+
+/* These do indirect calls to the in-line assembly routines
+ * in s4ctlb.S, see that file for more answers.
+ */
+extern inline void sun4c_flush_context(void)
+{
+	__asm__ __volatile__("jmpl %0, %%l4\n\t"
+			     "nop\n\t" : :
+			     "r" (sun4c_ctxflush) :
+			     "l4", "l6", "l7", "memory");
+}
+
+extern inline void sun4c_flush_segment(unsigned long segment)
+{
+	__asm__ __volatile__("jmpl %0, %%l4\n\t"
+			     "or %1, %%g0, %%l2\n\t" : :
+			     "r" (sun4c_segflush), "r" (segment) :
+			     "l2", "l4", "l6", "l7", "memory");
+}
+
+extern inline void sun4c_flush_page(unsigned long page)
+{
+	__asm__ __volatile__("jmpl %0, %%l4\n\t"
+			     "or %1, %%g0, %%l2\n\t" : :
+			     "r" (sun4c_pgflush), "r" (page) :
+			     "l2", "l4", "l6", "l7", "memory");
 }
 
-/* disable_vac() disables the virtual address cache. It returns 0 on
-   success, 1 on failure.
-*/
-
-extern __inline__ int disable_vac(void)
-{
-  int success=0;
-
-  __asm__ __volatile__("lduba [%1] 0x2, %0\n\t"
-			"xor   %0, 0x10, %0\n\t"
-			"stba  %0, [%1] 0x2\n\t"
-			"or    %%g0, %%g0, %0" : 
-		       "=r" (success) : 
-		       "r" (0x40000000),
-		       "0" (success));
-  return success;
-}
-
-/* Various one-shot VAC entry flushes on the Sparc */
-
-extern __inline__ void hw_flush_vac_context_entry(char* addr)
-{
-  __asm__ __volatile__("sta %%g0, [%0] 0x7" : : "r" (addr));
-}
-
-extern __inline__ void sw_flush_vac_context_entry(char* addr)
-{
-  __asm__ __volatile__("sta %%g0, [%0] 0xe" : : "r" (addr));
-}
-
-extern __inline__ void hw_flush_vac_segment_entry(char* addr)
-{
-  __asm__ __volatile__("sta %%g0, [%0] 0x5" : : "r" (addr));
-}
-
-extern __inline__ void sw_flush_vac_segment_entry(char* addr)
-{
-  __asm__ __volatile__("sta %%g0, [%0] 0xc" : : "r" (addr));
-}
-
-extern __inline__ void hw_flush_vac_page_entry(unsigned long* addr)
-{
-  __asm__ __volatile__("sta %%g0, [%0] 0x6" : : "r" (addr));
-}
-
-extern __inline__ void sw_flush_vac_page_entry(unsigned long* addr)
-{
-  __asm__ __volatile__("sta %%g0, [%0] 0xd" : : "r" (addr));
-}
- 
 #endif /* !(_SPARC_VAC_OPS_H) */
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/vaddrs.h linux/include/asm-sparc/vaddrs.h
--- v1.3.43/linux/include/asm-sparc/vaddrs.h	Tue Jun 27 14:11:46 1995
+++ linux/include/asm-sparc/vaddrs.h	Sat Nov 25 04:33:20 1995
@@ -1,3 +1,4 @@
+/* $Id: vaddrs.h,v 1.15 1995/11/25 02:33:20 davem Exp $ */
 #ifndef _SPARC_VADDRS_H
 #define _SPARC_VADDRS_H
 
@@ -23,10 +24,11 @@
 #define  INTREG_VADDR (TIMER_VADDR+0x5000)
 
 #define  IOBASE_VADDR   0xfe000000  /* Base for mapping pages */
-#define  IOBASE_LEN     0x00400000  /* Length of the IO area */
-#define  IOBASE_SUN4C_SEGMAP 100
-#define  DVMA_VADDR     0xfff00000  /* Base area of the DVMA on the 4c */
-#define  DVMA_LEN       0x000c0000  /* Size of the DVMA address space */
+#define  IOBASE_LEN     0x00100000  /* Length of the IO area */
+#define  IOBASE_END     0xfe100000
+#define  DVMA_VADDR     0xfff00000  /* Base area of the DVMA on suns */
+#define  DVMA_LEN       0x00040000  /* Size of the DVMA address space */
+#define  DVMA_END       0xfff40000
 
 /* On sun4m machines we need per-cpu virtual areas */
 #define  PERCPU_VADDR   0xff000000  /* Base for per-cpu virtual mappings */
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/viking.h linux/include/asm-sparc/viking.h
--- v1.3.43/linux/include/asm-sparc/viking.h	Tue Jun 27 14:11:46 1995
+++ linux/include/asm-sparc/viking.h	Sat Nov 25 04:33:23 1995
@@ -1,4 +1,5 @@
-/* viking.h:  Defines specific to the TI Viking MBUS module.
+/* $Id: viking.h,v 1.5 1995/11/25 02:33:21 davem Exp $
+ * viking.h:  Defines specific to the TI Viking MBUS module.
  *            This is SRMMU stuff.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
diff -u --recursive --new-file v1.3.43/linux/include/asm-sparc/winmacro.h linux/include/asm-sparc/winmacro.h
--- v1.3.43/linux/include/asm-sparc/winmacro.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-sparc/winmacro.h	Sat Nov 25 04:33:24 1995
@@ -0,0 +1,120 @@
+/* $Id: winmacro.h,v 1.11 1995/11/25 02:33:23 davem Exp $
+ * winmacro.h: Window loading-unloading macros.
+ *
+ * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef _SPARC_WINMACRO_H
+#define _SPARC_WINMACRO_H
+
+#include <asm/ptrace.h>
+#include <asm/psr.h>
+
+/* These are just handy. */
+#define _SV	save	%sp, -REGWIN_SZ, %sp
+#define _RS     restore 
+
+#define FLUSH_ALL_KERNEL_WINDOWS \
+	_SV; _SV; _SV; _SV; _SV; _SV; _SV; \
+	_RS; _RS; _RS; _RS; _RS; _RS; _RS;
+
+/* Store the register window onto the 8-byte aligned area starting
+ * at %reg.  It might be %sp, it might not, we don't care.
+ */
+#define STORE_WINDOW(reg) \
+	std	%l0, [%reg + RW_L0]; \
+	std	%l2, [%reg + RW_L2]; \
+	std	%l4, [%reg + RW_L4]; \
+	std	%l6, [%reg + RW_L6]; \
+	std	%i0, [%reg + RW_I0]; \
+	std	%i2, [%reg + RW_I2]; \
+	std	%i4, [%reg + RW_I4]; \
+	std	%i6, [%reg + RW_I6];
+
+/* Load a register window from the area beginning at %reg. */
+#define LOAD_WINDOW(reg) \
+	ldd	[%reg + RW_L0], %l0; \
+	ldd	[%reg + RW_L2], %l2; \
+	ldd	[%reg + RW_L4], %l4; \
+	ldd	[%reg + RW_L6], %l6; \
+	ldd	[%reg + RW_I0], %i0; \
+	ldd	[%reg + RW_I2], %i2; \
+	ldd	[%reg + RW_I4], %i4; \
+	ldd	[%reg + RW_I6], %i6;
+
+/* Loading and storing struct pt_reg trap frames. */
+#define LOAD_PT_INS(base_reg) \
+        ldd     [%base_reg + STACKFRAME_SZ + PT_I0], %i0; \
+        ldd     [%base_reg + STACKFRAME_SZ + PT_I2], %i2; \
+        ldd     [%base_reg + STACKFRAME_SZ + PT_I4], %i4; \
+        ldd     [%base_reg + STACKFRAME_SZ + PT_I6], %i6;
+
+#define LOAD_PT_GLOBALS(base_reg) \
+        ld      [%base_reg + STACKFRAME_SZ + PT_G1], %g1; \
+        ldd     [%base_reg + STACKFRAME_SZ + PT_G2], %g2; \
+        ldd     [%base_reg + STACKFRAME_SZ + PT_G4], %g4; \
+        ldd     [%base_reg + STACKFRAME_SZ + PT_G6], %g6;
+
+#define LOAD_PT_YREG(base_reg, scratch) \
+        ld      [%base_reg + STACKFRAME_SZ + PT_Y], %scratch; \
+        wr      %scratch, 0x0, %y;
+
+#define LOAD_PT_PRIV(base_reg, pt_psr, pt_pc, pt_npc) \
+        ld      [%base_reg + STACKFRAME_SZ + PT_PSR], %pt_psr; \
+        ld      [%base_reg + STACKFRAME_SZ + PT_PC], %pt_pc; \
+        ld      [%base_reg + STACKFRAME_SZ + PT_NPC], %pt_npc;
+
+#define LOAD_PT_ALL(base_reg, pt_psr, pt_pc, pt_npc, scratch) \
+        LOAD_PT_YREG(base_reg, scratch) \
+        LOAD_PT_INS(base_reg) \
+        LOAD_PT_GLOBALS(base_reg) \
+        LOAD_PT_PRIV(base_reg, pt_psr, pt_pc, pt_npc)
+
+#define STORE_PT_INS(base_reg) \
+        std     %i0, [%base_reg + STACKFRAME_SZ + PT_I0]; \
+        std     %i2, [%base_reg + STACKFRAME_SZ + PT_I2]; \
+        std     %i4, [%base_reg + STACKFRAME_SZ + PT_I4]; \
+        std     %i6, [%base_reg + STACKFRAME_SZ + PT_I6];
+
+#define STORE_PT_GLOBALS(base_reg) \
+        st      %g1, [%base_reg + STACKFRAME_SZ + PT_G1]; \
+        std     %g2, [%base_reg + STACKFRAME_SZ + PT_G2]; \
+        std     %g4, [%base_reg + STACKFRAME_SZ + PT_G4]; \
+        std     %g6, [%base_reg + STACKFRAME_SZ + PT_G6];
+
+#define STORE_PT_YREG(base_reg, scratch) \
+        rd      %y, %scratch; \
+        st      %scratch, [%base_reg + STACKFRAME_SZ + PT_Y];
+
+#define STORE_PT_PRIV(base_reg, pt_psr, pt_pc, pt_npc, pt_wim) \
+        st      %pt_psr, [%base_reg + STACKFRAME_SZ + PT_PSR]; \
+        st      %pt_pc, [%base_reg + STACKFRAME_SZ + PT_PC]; \
+        st      %pt_npc, [%base_reg + STACKFRAME_SZ + PT_NPC]; \
+        st      %pt_wim, [%base_reg + STACKFRAME_SZ + PT_WIM];
+
+#define STORE_PT_ALL(base_reg, reg_psr, reg_pc, reg_npc, reg_wim, g_scratch) \
+        STORE_PT_PRIV(base_reg, reg_psr, reg_pc, reg_npc, reg_wim) \
+        STORE_PT_GLOBALS(base_reg) \
+        STORE_PT_YREG(base_reg, g_scratch) \
+        STORE_PT_INS(base_reg)
+
+#define SAVE_BOLIXED_USER_STACK(cur_reg, scratch) \
+        ld       [%cur_reg + THREAD_W_SAVED], %scratch; \
+        sll      %scratch, 2, %scratch; \
+        add      %scratch, %cur_reg, %scratch; \
+        st       %sp, [%scratch + THREAD_STACK_PTRS]; \
+        sub      %scratch, %cur_reg, %scratch; \
+        sll      %scratch, 4, %scratch; \
+        add      %scratch, %cur_reg, %scratch; \
+        STORE_WINDOW(scratch + THREAD_REG_WINDOW); \
+        sub      %scratch, %cur_reg, %scratch; \
+        srl      %scratch, 6, %scratch; \
+        add      %scratch, 1, %scratch; \
+        st       %scratch, [%cur_reg + THREAD_W_SAVED];
+
+/* For now on a uniprocessor this is ok. */
+#define LOAD_CURRENT(dest_reg) \
+        sethi    %hi(C_LABEL(current_set)), %dest_reg; \
+        ld       [%dest_reg + %lo(C_LABEL(current_set))], %dest_reg;
+
+#endif /* !(_SPARC_WINMACRO_H) */
diff -u --recursive --new-file v1.3.43/linux/include/linux/aztcd.h linux/include/linux/aztcd.h
--- v1.3.43/linux/include/linux/aztcd.h	Sun Oct 29 11:38:49 1995
+++ linux/include/linux/aztcd.h	Sat Nov 25 17:28:41 1995
@@ -1,4 +1,4 @@
-/* $Id: aztcd.h,v 1.90 1995/10/21 17:52:10 root Exp root $
+/* $Id: aztcd.h,v 2.0 1995/11/10 19:38:49 root Exp root $
  *
  * Definitions for a AztechCD268 CD-ROM interface
  *	Copyright (C) 1994, 1995  Werner Zimmermann
@@ -57,6 +57,7 @@
 
 /*---------------------------------------------------------------------------*/
 /*-----nothing to be configured for normal applications below this line------*/
+
 
 /* Increase this if you get lots of timeouts; if you get kernel panic, replace
    STEN_LOW_WAIT by STEN_LOW in the source code */
diff -u --recursive --new-file v1.3.43/linux/include/linux/igmp.h linux/include/linux/igmp.h
--- v1.3.43/linux/include/linux/igmp.h	Wed Oct  4 14:14:34 1995
+++ linux/include/linux/igmp.h	Fri Nov 24 16:39:54 1995
@@ -23,7 +23,7 @@
 /*
  *	Header in on cable format
  */
- 
+
 struct igmphdr
 {
 	__u8 type;
@@ -36,8 +36,8 @@
 #define IGMP_HOST_MEMBERSHIP_REPORT	0x12	/* Ditto */
 #define IGMP_DVMRP			0x13	/* DVMRP routing */
 #define IGMP_PIM			0x14	/* PIM routing */
-#define IGMP_HOST_NEW_MEMBERSHIP_REPORT	0x16	/* New version of 0x11 */
-#define IGMP_HOST_LEAVE_MESSAGE		0x17	/* An extra BSD seems to send */
+#define IGMP_HOST_NEW_MEMBERSHIP_REPORT 0x16	/* New version of 0x11 */
+#define IGMP_HOST_LEAVE_MESSAGE 	0x17	/* An extra BSD seems to send */
 
 #define IGMP_MTRACE_RESP		0x1e
 #define IGMP_MTRACE			0x1f
@@ -53,12 +53,25 @@
 #define IGMP_SLEEPING_MEMBER		0x04
 #define IGMP_AWAKENING_MEMBER		0x05
 
-#define IGMP_OLD_ROUTER			0x00
-#define IGMP_NEW_ROUTER			0x01
+#define IGMP_OLD_ROUTER 		0x00
+#define IGMP_NEW_ROUTER 		0x01
+
+#define IGMP_MINLEN			8
 
+#define IGMP_MAX_HOST_REPORT_DELAY	10	/* max delay for response to */
+						/* query (in seconds)	*/
 
+#define IGMP_TIMER_SCALE		10	/* denotes that the igmphdr->timer field */
+						/* specifies time in 10th of seconds	 */
+
+#define IGMP_AGE_THRESHOLD		540	/* If this host don't hear any IGMP V1	*/
+						/* message in this period of time, revert */
+						/* to IGMP v2 router */
 
 #define IGMP_ALL_HOSTS		htonl(0xE0000001L)
+#define IGMP_ALL_ROUTER 	htonl(0xE0000002L)
+#define IGMP_LOCAL_GROUP	htonl(0xE0000000L)
+#define IGMP_LOCAL_GROUP_MASK	htonl(0xFFFFFF00L)
 
 /*
  * struct for keeping the multicast list in
@@ -71,7 +84,7 @@
 	struct device *multidev[IP_MAX_MEMBERSHIPS];
 };
 
-struct ip_mc_list 
+struct ip_mc_list
 {
 	struct device *interface;
 	unsigned long multiaddr;
@@ -80,13 +93,21 @@
 	int tm_running;
 	int users;
 };
- 
+
+struct router_info
+{
+	struct device *dev;
+	int    type; /* type of router which is querier on this interface */
+	int    time; /* # of slow timeouts since last old query */
+	struct router_info *next;
+};
+
 extern struct ip_mc_list *ip_mc_head;
 
 
 extern int igmp_rcv(struct sk_buff *, struct device *, struct options *, __u32, unsigned short,
 	__u32, int , struct inet_protocol *);
-extern void ip_mc_drop_device(struct device *dev); 
+extern void ip_mc_drop_device(struct device *dev);
 extern int ip_mc_join_group(struct sock *sk, struct device *dev, unsigned long addr);
 extern int ip_mc_leave_group(struct sock *sk, struct device *dev,unsigned long addr);
 extern void ip_mc_drop_socket(struct sock *sk);
diff -u --recursive --new-file v1.3.43/linux/include/linux/netdevice.h linux/include/linux/netdevice.h
--- v1.3.43/linux/include/linux/netdevice.h	Fri Nov 17 08:42:28 1995
+++ linux/include/linux/netdevice.h	Sat Nov 25 12:09:04 1995
@@ -171,8 +171,7 @@
   int			  (*rebuild_header)(void *eth, struct device *dev,
 				unsigned long raddr, struct sk_buff *skb);
 #define HAVE_MULTICAST			 
-  void			  (*set_multicast_list)(struct device *dev,
-  					 int num_addrs, void *addrs);
+  void			  (*set_multicast_list)(struct device *dev);
 #define HAVE_SET_MAC_ADDR  		 
   int			  (*set_mac_address)(struct device *dev, void *addr);
 #define HAVE_PRIVATE_IOCTL
diff -u --recursive --new-file v1.3.43/linux/include/linux/pci.h linux/include/linux/pci.h
--- v1.3.43/linux/include/linux/pci.h	Fri Nov 17 08:42:28 1995
+++ linux/include/linux/pci.h	Tue Nov 21 16:27:33 1995
@@ -215,6 +215,9 @@
  * Vendor and card ID's: sort these numerically according to vendor
  * (and according to card ID within vendor)
  */
+#define PCI_VENDOR_ID_COMPAQ		0x0e11
+#define PCI_DEVICE_ID_COMPAQ_1280	0x3033
+
 #define PCI_VENDOR_ID_NCR		0x1000
 #define PCI_DEVICE_ID_NCR_53C810	0x0001
 #define PCI_DEVICE_ID_NCR_53C820	0x0002
@@ -298,19 +301,9 @@
 #define PCI_VENDOR_ID_HP		0x103c
 #define PCI_DEVICE_ID_HP_J2585A		0x1030
 
-#if 0
-
-#define PCI_VENDOR_ID_SMC		0x1042	/* Is this really correct?? */
-#define PCI_DEVICE_ID_SMC_37C665	0x1000
-#define PCI_DEVICE_ID_SMC_37C922	0x1001
-
-#else
-
-#define PCI_VENDOR_ID_PCTECH		0x1042	/* Known to be correct */
+#define PCI_VENDOR_ID_PCTECH		0x1042
 #define PCI_DEVICE_ID_PCTECH_RZ1000	0x1000
 
-#endif
-
 #define PCI_VENDOR_ID_DPT               0x1044   
 #define PCI_DEVICE_ID_DPT               0xa400  
 
@@ -323,6 +316,7 @@
 #define PCI_VENDOR_ID_BUSLOGIC		0x104B
 #define PCI_DEVICE_ID_BUSLOGIC_946C_2	0x0140
 #define PCI_DEVICE_ID_BUSLOGIC_946C	0x1040
+#define PCI_DEVICE_ID_BUSLOGIC_930	0x8130
 
 #define PCI_VENDOR_ID_PROMISE		0x105a
 #define PCI_DEVICE_ID_PROMISE_5300	0x5300
@@ -361,6 +355,9 @@
 #define PCI_DEVICE_ID_VISION_QD8500	0x0001
 #define PCI_DEVICE_ID_VISION_QD8580	0x0002
 
+#define PCI_VENDOR_ID_SIERRA		0x10a8
+#define PCI_DEVICE_ID_SIERRA_STB	0x0000
+
 #define PCI_VENDOR_ID_ACC		0x10aa
 
 #define PCI_VENDOR_ID_WINBOND		0x10ad
@@ -379,9 +376,15 @@
 #define PCI_DEVICE_ID_AL_M1461		0x1461
 #define PCI_DEVICE_ID_AL_M4803		0x5215
 
+#define PCI_VENDOR_ID_ASP		0x10cd
+#define PCI_DEVICE_ID_ASP_ABP940	0x1200
+
 #define PCI_VENDOR_ID_IMS		0x10e0
 #define PCI_DEVICE_ID_IMS_8849		0x8849
 
+#define PCI_VENDOR_ID_TEKRAM2		0x10e1
+#define PCI_DEVICE_ID_TEKRAM2_690c	0x690c
+
 #define PCI_VENDOR_ID_REALTEK		0x10ec
 #define PCI_DEVICE_ID_REALTEK_8029	0x8029
 
@@ -394,7 +397,8 @@
 #define PCI_DEVICE_ID_VORTEX_GDT	0x0001
 
 #define PCI_VENDOR_ID_EF		0x111a
-#define PCI_DEVICE_ID_EF_ATM		0x0000
+#define PCI_DEVICE_ID_EF_ATM_FPGA	0x0000
+#define PCI_DEVICE_ID_EF_ATM_ASIC	0x0002
 
 #define PCI_VENDOR_ID_IMAGINGTECH	0x112f
 #define PCI_DEVICE_ID_IMAGINGTECH_ICPCI	0x0000
@@ -408,8 +412,11 @@
 #define PCI_VENDOR_ID_MUTECH		0x1159
 #define PCI_DEVICE_ID_MUTECH_MV1000	0x0001
 
-#define PCI_VENDOR_ID_ZEINET		0x1193
-#define PCI_DEVICE_ID_ZEINET_1221	0x0001
+#define PCI_VENDOR_ID_ZEITNET		0x1193
+#define PCI_DEVICE_ID_ZEITNET_1221	0x0001
+
+#define PCI_VENDOR_ID_HAL		0x11cd
+#define PCI_DEVICE_ID_HAL_RIO		0x8000
 
 #define PCI_VENDOR_ID_CYCLADES		0x120e
 #define PCI_DEVICE_ID_CYCLADES_Y	0x0100
@@ -442,6 +449,7 @@
 #define PCI_DEVICE_ID_INTEL_7116	0x1223
 #define PCI_DEVICE_ID_INTEL_82596	0x1226
 #define PCI_DEVICE_ID_INTEL_82865	0x1227
+#define PCI_DEVICE_ID_INTEL_82557	0x1229
 #define PCI_DEVICE_ID_INTEL_82437	0x122d
 #define PCI_DEVICE_ID_INTEL_82371_0	0x122e
 #define PCI_DEVICE_ID_INTEL_82371_1	0x1230
@@ -452,6 +460,7 @@
 #define PCI_DEVICE_ID_ADAPTEC_7870	0x7078
 #define PCI_DEVICE_ID_ADAPTEC_7871	0x7178
 #define PCI_DEVICE_ID_ADAPTEC_7872	0x7278
+#define PCI_DEVICE_ID_ADAPTEC_7873	0x7378
 #define PCI_DEVICE_ID_ADAPTEC_7880	0x8078
 #define PCI_DEVICE_ID_ADAPTEC_7881	0x8178
 #define PCI_DEVICE_ID_ADAPTEC_7882	0x8278
diff -u --recursive --new-file v1.3.43/linux/include/linux/skbuff.h linux/include/linux/skbuff.h
--- v1.3.43/linux/include/linux/skbuff.h	Wed Nov  8 07:11:42 1995
+++ linux/include/linux/skbuff.h	Sat Nov 25 12:09:04 1995
@@ -54,7 +54,6 @@
 	struct iphdr	*iph;
 	struct udphdr	*uh;
 	unsigned char	*raw;
-	unsigned long	seq;
   } h;
   
   union {						/* As yet incomplete physical layer views 	*/
@@ -64,10 +63,13 @@
   
   struct iphdr			*ip_hdr;		/* For IPPROTO_RAW 				*/
   unsigned long 		len;			/* Length of actual data			*/
-  unsigned long 		saddr;			/* IP source address				*/
-  unsigned long 		daddr;			/* IP target address				*/
-  unsigned long			raddr;			/* IP next hop address				*/
   unsigned long			csum;			/* Checksum 					*/
+  __u32				saddr;			/* IP source address				*/
+  __u32				daddr;			/* IP target address				*/
+  __u32				raddr;			/* IP next hop address				*/
+  __u32				seq;			/* TCP sequence number				*/
+  __u32				end_seq;		/* seq [+ fin] [+ syn] + datalen		*/
+  __u32				ack_seq;		/* TCP ack sequence number			*/
   unsigned char			proto_priv[16];	        /* Protocol private data			*/
   volatile char 		acked,			/* Are we acked ?				*/
 				used,			/* Are we in use ?				*/
@@ -85,6 +87,9 @@
   unsigned short		users;			/* User count - see datagram.c,tcp.c 		*/
   unsigned short		protocol;		/* Packet protocol from driver. 		*/
   unsigned short		truesize;		/* Buffer size 					*/
+
+  int				count;			/* reference count				*/
+  struct sk_buff		*data_skb;		/* Link to the actual data skb			*/
   unsigned char			*head;			/* Head of buffer 				*/
   unsigned char			*data;			/* Data head pointer				*/
   unsigned char			*tail;			/* Tail pointer					*/
diff -u --recursive --new-file v1.3.43/linux/include/net/sock.h linux/include/net/sock.h
--- v1.3.43/linux/include/net/sock.h	Fri Nov 17 08:42:29 1995
+++ linux/include/net/sock.h	Sat Nov 25 12:09:05 1995
@@ -127,7 +127,8 @@
 				no_check,
 				zapped,	/* In ax25 & ipx means not linked */
 				broadcast,
-				nonagle;
+				nonagle,
+				bsdism;
 	unsigned long	        lingertime;
 	int			proc;
 	struct sock		*next;
diff -u --recursive --new-file v1.3.43/linux/kernel/ksyms.c linux/kernel/ksyms.c
--- v1.3.43/linux/kernel/ksyms.c	Fri Nov 17 08:42:29 1995
+++ linux/kernel/ksyms.c	Fri Nov 24 16:39:54 1995
@@ -90,6 +90,10 @@
 #endif
 
 #include <asm/irq.h>
+#ifdef __SMP__
+#include <linux/smp.h>
+#endif
+
 extern char *get_options(char *str, int *ints);
 extern void set_device_ro(int dev,int flag);
 extern struct file_operations * get_blkfops(unsigned int);
diff -u --recursive --new-file v1.3.43/linux/kernel/sys.c linux/kernel/sys.c
--- v1.3.43/linux/kernel/sys.c	Sun Oct 29 11:38:49 1995
+++ linux/kernel/sys.c	Fri Nov 24 16:29:29 1995
@@ -545,6 +545,19 @@
 	return current->pgrp;
 }
 
+asmlinkage int sys_getsid(pid_t pid)
+{
+	struct task_struct * p;
+
+	if (!pid)
+		return current->session;
+	for_each_task(p) {
+		if (p->pid == pid)
+			return p->session;
+	}
+	return -ESRCH;
+}
+
 asmlinkage int sys_setsid(void)
 {
 	if (current->leader)
diff -u --recursive --new-file v1.3.43/linux/net/802/p8022.c linux/net/802/p8022.c
--- v1.3.43/linux/net/802/p8022.c	Mon Jul 31 15:59:03 1995
+++ linux/net/802/p8022.c	Fri Nov 24 16:39:54 1995
@@ -59,7 +59,7 @@
 
 static struct packet_type p8022_packet_type = 
 {
-	0,	/* MUTTER ntohs(ETH_P_IPX),*/
+	0,	/* MUTTER ntohs(ETH_P_8022),*/
 	NULL,		/* All devices */
 	p8022_rcv,
 	NULL,
diff -u --recursive --new-file v1.3.43/linux/net/Changes linux/net/Changes
--- v1.3.43/linux/net/Changes	Fri Nov 17 08:42:29 1995
+++ linux/net/Changes	Fri Nov 24 16:39:54 1995
@@ -232,7 +232,7 @@
 -------->>>>> 1.3.31 <<<<<<-------
 
 o	IP_OPTIONS [A.N.Kuznetsov]			[TESTED]
-o	TCP cache zap more fixes			[TESTED.. STILL NO COOKIE]
+o	TCP cache zap more fixes			[TESTED]
 o	Most of the IP multicast routing cache added	[TESTED - WORK NEEDED]
 o	Kernel/user communication module (not used yet) [TESTED]
 
@@ -252,28 +252,28 @@
 -------->>>>> 1.3.35 <<<<<<--------
 
 o	Appletalk data now in the protinfo union	[TESTED]
-o	BSD style bind to broadcast address supported	[IN]
+o	BSD style bind to broadcast address supported	[TESTED]
 o	Standard loadable firewall chains		[TESTED]
 o	IPFW uses the firewall chains for firewall but
 		not yet acct/masquerade			[TESTED]
 o	Firewall chain hooks in all other protocols	[TESTED]
 o	Sendmsg/recvmsg for IPX. 			[TESTED]
 o	IPX uses sock_alloc_send_skb			[TESTED]
-o	Recvmsg for all IP, sendmsg for TCP		[IN]
+o	Recvmsg for all IP, sendmsg for TCP		[TESTED]
 	(nearly ready to go all *msg())
 
--------->>>>> 1.3.41 <<<<<<--------
+-------->>>>> 1.3.42 <<<<<<--------
 
 o	ip udp/raw nonblock bug fixed			[TESTED]
-o	ICMP lockup fix					[IN]
-o	Fundamental operations now only sendmsg/recvmsg	[IN]
+o	ICMP lockup fix					[TESTED]
+o	Fundamental operations now only sendmsg/recvmsg	[TESTED]
 o	bind() for SOCK_PACKET				[IN]
 o	set_mac_addr fixed up				[IN]
 o	BSD SIOCSIFADDR, AF_UNSPEC behaviour		[IN]
-o	Updated this list				[IN]
+o	Updated this list				[OK]
 o	Massive ARP/cache/routing rewrite [ANK]		[IN]
 o	AX.25 connect return fixed in using sock_error	[IN]
-o	Proper netlink device major(36)			[IN]
+o	Proper netlink device major(36)			[TESTED]
 o	First parts of the SKIP support			[IN, not useful]
 o	TCP ICMP (SOSS should work again)		[IN]
 o	IPFW support for TOS changing (Al Longyear)	[IN]
@@ -281,6 +281,17 @@
 o	NFS root					[IN]
 o	Path MTU discovery [ANK]			[IN]
 
+-------->>>>> 1.3.44 <<<<<<--------
+
+o	NFS root/ FPU clash fixed			[IN]
+o	ARP lock bug fixed				[IN]
+o	SO_BSDCOMPAT option(libbsd/ibcs2 ought to set)	[IN]
+o	Changed to new set_multicast_list()		[IN]
+o	ARP ioctl() call fixes	[Bernd]			[IN]
+o	Fixes to the name set functions (maybe fixes
+	netrom)		[Steve]				[IN]
+o	Packet protocol labelling (not IPX yet)		[IN]
+
 ---------- Things I thought Linus had for a while and not merged ----------------
 
 
@@ -288,61 +299,59 @@
 
 o	Improved IPX support for lwared.
 o	Decnet pre pre pre pre pre Alpha 0.0.
+o	Chase Donald for new drivers, get people to sort out what net
+	drivers should cease to be 'Alpha'.
+o	IPX PPP support
+o	IPalias
 
 ---------- Things pending for me to merge --------------
 
 o	AF_UNIX garbage collect code
 o	Faster closedown option for heavy use sites (me)
 o	Tom May's insw_and_checksum()			
-o	IPX PPP support
 o	SPARC patches [Dave] [partly in]
-o	Path MTU and other goodies [ANK]
 
 --------------- Things That Need Doing Before 1.4 ------------------
 
-o	Finish merging the bridge code
-o	Fast checksum/copy on outgoing TCP
-o	Fast dev_grab_next() transmit reload function
-	and dev_push_failed() ??			[Causes deadlock
-							cases with slow box, heavy networking]
 o	Forwarding queue control (+ fairness algorithms ??)
 o	IP forward flow control.
+o	IPX memory leak ?????
 o	Clean up RAW AX.25 sockets.
-o	Finish 802.2 Class I code to be compliant to the oddities of 802.2
-o	Tidy BPQ support to use a bpqip tunnel device
-o	Strange eth0-eth3 bug 				[Matti fixed ??]
 o	Finish IPIP bug fixes				[Done hopefully]
-o	Why doesnt the PROTO_UNREACH get sent ?		[Should now work]
-o	Kill off old ip_queue_xmit/ip_send stuff.
-o	Remove kernel RARP and replace with user mode daemon.
-o	Throw out existing firewall ioctl()'s and use a single table load.
+o	Multicast routing				[STARTED BITS]
+o	PPP/IPX
+o	IPX for Lwared
+o	SKIP						[Available in user mode]
+o	AX.25/NetROM locking changes
+o	insw_and_csum
+o	IPAlias
+o	AF_UNIX fd passing
 
 0.2
 ---
+o	Fast checksum/copy on outgoing TCP
 o	Better TCP window handling [Pedro Roque]
 o	Add tty support to sonix driver.
 o	PPP for Sonix ISDN.
 o	Screend loadable firewall module
-o	LZ SLIP				[Done, resolving patent issues - sod it use PPP]
-o	AXIP
+o	AXIP						[AVAILABLE IN USER MODE]
+o	Finish merging the bridge code			[LEAVE POST 1.4]
+o	Finish 802.2 Class I code to be compliant to the oddities of 802.2
+o	Tidy BPQ support to use a bpqip tunnel device
+o	Kill off old ip_queue_xmit/ip_send stuff.
+o	Remove kernel RARP and replace with user mode daemon.
+o	Throw out existing firewall ioctl()'s and use a single table load.
+o	SPARC merge
 
 0.3
 ---
 o	Merge the layered protocol support.		[ABANDONED TOO SLOW]
-o	IP firewalling performance - caching and radix trees.
-o	Zebedee
 o	802.2 Class 2 services (eg netbios).
 o	Multidrop KISS					[NOW AVAILABLE IN USER MODE]
-o	Multicast routing				[STARTED BITS]
 
 Possible projects for victim^H^H^H^H^Holunteers
 
 
-1.	Verifying the correctness of implementation against RFC1122 and
-making a list of violations (BSD is sufficiently screwed up you can't
-implement all of RFC1122 and talk to it usefully). [Done - Mike
-Shaver]
-
 2.	Verifying all the error returns match the BSD ones (grotty job I
 wouldn't wish on anyone).
 
@@ -353,17 +362,11 @@
 mathematician with some queue theory you can show this allows you to 
 lose one frame per window full of data without measurable speed loss.
 
-4.	RFC1323 and RFC1191. These are the extensions for very fast nets
-and for 'path MTU discovery' - a way of finding the best packetsize to use.
+4.	RFC1323. These are the extensions for very fast nets.
 RFC1323 will be useful for Linux talking to systems over 100Mb/sec
 ethernet and over ATM as it allows large windows and protects from some
 potential high speed TCP problems.
 
-5.	Fixing the IP fragment handling so that the total space allocated to
-fragments is limited and old fragments are deleted to make room for new ones
-when space is exhausted. Fixing the fragment handling to work at a decent
-speed wouldn't be bad either. [In progress - Arnt Gulbrandsen]
-
 6.	Delayed ack. This is mostly supported but not actually set up and
 used yet. Basically ack frames are held back 1/10th of a second in the hope
 that two acks can be merged into one or for interactive use the ack can
@@ -375,27 +378,17 @@
 is SLIP6) SLIP mode that does packet data compression [maybe use the code
 from term].
 
-8.	Making SLIP/PPP dynamically allocate devices so you never run out
-of channels.	[Done (pending inclusion in the PPP case)]
-
 9.	Implementing streams. Not as a blind slow SYS5.4 style copy but actually
 working out how to do it so it runs like greased lightning. Quite a big
 problem.
 
 10.	Frame Relay/WAN/ISDN drivers [I'm working on the sonix EuroISDN board
 driver but thats for an internal project and its general release is still
-a maybe (so is finishing it ;))][Jim Freeman is working on Frame Relay].
-
+a maybe (so is finishing it ;))][Jim Freeman is working on Frame Relay as is
+Mike McLagan][Friz Elfert is doing the isdn4linux kit].
+ 
 11.	IP over SCSI.
 
-12.	Debugging and making the appletalk alpha test code useful.
-	[Done and in]
-
-13.	Mrouted Multicast routing. Or possibly MOSPF and others
-	as they become available
-	[Started: see/join linux-multicast@www.linux.org.uk
-         if you wish to join in]
-
 14.	Bidirectional PLIP. Also PLIP for the newer style parallel ports.
 
 15.	802.2LLC and thus Netbeui sockets. Becoming less important since the
@@ -406,6 +399,7 @@
 their hands. [Provisionally taken]
 
 17.	PPP multilink. Another nasty job.
+[In progress]
 
 18.	Implement swIPe under Linux.
 [Reportedly in progress]
diff -u --recursive --new-file v1.3.43/linux/net/ax25/af_ax25.c linux/net/ax25/af_ax25.c
--- v1.3.43/linux/net/ax25/af_ax25.c	Fri Nov 17 08:42:29 1995
+++ linux/net/ax25/af_ax25.c	Fri Nov 24 16:39:54 1995
@@ -2162,6 +2162,7 @@
 	}	
 	
 #endif	
+	skb->protocol = htons (ETH_P_AX25);
 
 	if (dev->type == ARPHRD_ETHER) 
 	{
diff -u --recursive --new-file v1.3.43/linux/net/core/dev_mcast.c linux/net/core/dev_mcast.c
--- v1.3.43/linux/net/core/dev_mcast.c	Mon Oct 23 18:02:22 1995
+++ linux/net/core/dev_mcast.c	Fri Nov 24 16:39:54 1995
@@ -12,6 +12,7 @@
  *		Alan Cox	:	Update the device on a real delete
  *					rather than any time but...
  *		Alan Cox	:	IFF_ALLMULTI support.
+ *		Alan Cox	: 	New format set_multicast_list() calls.
  *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License
@@ -60,9 +61,6 @@
  
 void dev_mc_upload(struct device *dev)
 {
-	struct dev_mc_list *dmi;
-	char *data, *tmp;
-
 	/* Don't do anything till we up the interface
 	   [dev_open will call this function so the list will
 	    stay sane] */
@@ -70,7 +68,6 @@
 	if(!(dev->flags&IFF_UP))
 		return;
 		
-		
 	/*
 	 *	Devices with no set multicast don't get set 
 	 */
@@ -78,55 +75,7 @@
 	if(dev->set_multicast_list==NULL)
 		return;
 		
-	/*
-	 *	Promiscuous is promiscuous - so no filter needed 
-	 */
-	 
-	if(dev->flags&IFF_PROMISC)
-	{
-		dev->set_multicast_list(dev, -1, NULL);
-		return;
-	}
-	
-	/*
-	 *	All multicasts. Older cards will interpret this as
-	 * 	promisc mode, which is the next best thing.
-	 */
-	
-	if(dev->flags&IFF_ALLMULTI)
-	{
-		dev->set_multicast_list(dev, -2, NULL);
-		return;
-	}
-	
-	/*
-	 *	No multicasts
-	 */
-	
-	if(dev->mc_count==0)
-	{
-		dev->set_multicast_list(dev,0,NULL);
-		return;
-	}
-	
-	/*
-	 *	The drivers need changing to process the list themselves... this is
-	 *	a mess.
-	 */
-	
-	data=kmalloc(dev->mc_count*dev->addr_len, GFP_KERNEL);
-	if(data==NULL)
-	{
-		printk("Unable to get memory to set multicast list on %s\n",dev->name);
-		return;
-	}
-	for(tmp = data, dmi=dev->mc_list;dmi!=NULL;dmi=dmi->next)
-	{
-		memcpy(tmp,dmi->dmi_addr, dmi->dmi_addrlen);
-		tmp+=dev->addr_len;
-	}
-	dev->set_multicast_list(dev,dev->mc_count,data);
-	kfree(data);
+	dev->set_multicast_list(dev);
 }
   
 /*
diff -u --recursive --new-file v1.3.43/linux/net/core/skbuff.c linux/net/core/skbuff.c
--- v1.3.43/linux/net/core/skbuff.c	Wed Nov  8 07:11:45 1995
+++ linux/net/core/skbuff.c	Thu Nov 23 11:26:03 1995
@@ -461,6 +461,7 @@
 	if (skb->next)
 	 	printk("Warning: kfree_skb passed an skb still on a list (from %p).\n",
 			__builtin_return_address(0));
+
 	if(skb->destructor)
 		skb->destructor(skb);
 	if (skb->sk)
@@ -542,6 +543,9 @@
 	
 	skb=(struct sk_buff *)(bptr+size)-1;
 
+	skb->count = 1;		/* only one reference to this */
+	skb->data_skb = NULL;	/* and we're our own data skb */
+
 	skb->free = 2;	/* Invalid so we pick up forgetful users */
 	skb->lock = 0;
 	skb->pkt_type = PACKET_HOST;	/* Default type */
@@ -579,10 +583,20 @@
 void kfree_skbmem(struct sk_buff *skb)
 {
 	unsigned long flags;
+	void * addr = skb->head;
+
 	save_flags(flags);
 	cli();
-	kfree((void *)skb->head);
-	net_skbcount--;
+	/* don't do anything if somebody still uses us */
+	if (--skb->count <= 0) {
+		/* free the skb that contains the actual data if we've clone()'d */
+		if (skb->data_skb) {
+			addr = skb;
+			kfree_skbmem(skb->data_skb);
+		}
+		kfree(addr);
+		net_skbcount--;
+	}
 	restore_flags(flags);
 }
 
@@ -590,7 +604,38 @@
  *	Duplicate an sk_buff. The new one is not owned by a socket or locked
  *	and will be freed on deletion.
  */
+#if 1
+struct sk_buff *skb_clone(struct sk_buff *skb, int priority)
+{
+	struct sk_buff *n;
+	unsigned long flags;
 
+	IS_SKB(skb);
+	n = kmalloc(sizeof(*n), priority);
+	if (!n)
+		return NULL;
+	memcpy(n, skb, sizeof(*n));
+	n->count = 1;
+	if (skb->data_skb)
+		skb = skb->data_skb;
+	save_flags(flags);
+	cli();
+	skb->count++;
+	net_allocs++;
+	net_skbcount++;
+	restore_flags(flags);
+	n->data_skb = skb;
+	n->next = n->prev = n->link3 = NULL;
+	n->sk = NULL;
+	n->truesize = sizeof(*n);
+	n->free = 1;
+	n->tries = 0;
+	n->lock = 0;
+	n->users = 0;
+	return n;
+}
+#else
+/* this is slower, and copies the whole data area */
 struct sk_buff *skb_clone(struct sk_buff *skb, int priority)
 {
 	struct sk_buff *n;
@@ -628,6 +673,9 @@
 	n->saddr=skb->saddr;
 	n->daddr=skb->daddr;
 	n->raddr=skb->raddr;
+	n->raddr=skb->seq;
+	n->raddr=skb->end_seq;
+	n->raddr=skb->ack_seq;
 	n->acked=skb->acked;
 	memcpy(n->proto_priv, skb->proto_priv, sizeof(skb->proto_priv));
 	n->used=skb->used;
@@ -642,7 +690,7 @@
 	IS_SKB(n);
 	return n;
 }
-
+#endif
 
 /*
  *     Skbuff device locking
diff -u --recursive --new-file v1.3.43/linux/net/core/sock.c linux/net/core/sock.c
--- v1.3.43/linux/net/core/sock.c	Mon Oct 23 18:02:22 1995
+++ linux/net/core/sock.c	Fri Nov 24 16:39:54 1995
@@ -207,7 +207,10 @@
 			}
 			return 0;
 
-
+		case SO_BSDCOMPAT:
+			sk->bsdism = valbool;
+			return 0;
+			
 		default:
 		  	return(-ENOPROTOOPT);
   	}
@@ -285,7 +288,9 @@
 			memcpy_tofs(optval,&ling,sizeof(ling));
 			return 0;
 		
-
+		case SO_BSDCOMPAT:
+			val = sk->bsdism;
+			break;
 
 		default:
 			return(-ENOPROTOOPT);
diff -u --recursive --new-file v1.3.43/linux/net/ethernet/pe2.c linux/net/ethernet/pe2.c
--- v1.3.43/linux/net/ethernet/pe2.c	Mon Jul 31 15:59:04 1995
+++ linux/net/ethernet/pe2.c	Fri Nov 24 16:39:54 1995
@@ -9,7 +9,8 @@
 		struct sk_buff *skb, unsigned char *dest_node)
 {
 	struct device	*dev = skb->dev;
-	
+
+	skb->protocol = htons (ETH_P_IPX);
 	dev->hard_header(skb, dev, ETH_P_IPX, dest_node, NULL, skb->len);
 }
 
diff -u --recursive --new-file v1.3.43/linux/net/ipv4/af_inet.c linux/net/ipv4/af_inet.c
--- v1.3.43/linux/net/ipv4/af_inet.c	Fri Nov 17 08:42:33 1995
+++ linux/net/ipv4/af_inet.c	Fri Nov 24 16:39:54 1995
@@ -1016,10 +1016,11 @@
 	sk1 = (struct sock *) sock->data;
 
 	/*
-	 * We've been passed an extra socket.
-	 * We need to free it up because the tcp module creates
-	 * its own when it accepts one.
+	 *	We've been passed an extra socket.
+	 *	We need to free it up because the tcp module creates
+	 *	its own when it accepts one.
 	 */
+	 
 	if (newsock->data)
 	{
 	  	struct sock *sk=(struct sock *)newsock->data;
@@ -1031,7 +1032,10 @@
 	if (sk1->prot->accept == NULL) 
 		return(-EOPNOTSUPP);
 
-	/* Restore the state if we have been interrupted, and then returned. */
+	/*
+	 *	Restore the state if we have been interrupted, and then returned. 
+	 */
+	 
 	if (sk1->pair != NULL ) 
 	{
 		sk2 = sk1->pair;
diff -u --recursive --new-file v1.3.43/linux/net/ipv4/arp.c linux/net/ipv4/arp.c
--- v1.3.43/linux/net/ipv4/arp.c	Tue Nov 21 13:22:14 1995
+++ linux/net/ipv4/arp.c	Sat Nov 25 10:55:29 1995
@@ -50,6 +50,7 @@
  *					eg intelligent arp probing and generation
  *					of host down events.
  *		Alan Cox	:	Missing unlock in device events.
+ *		Eckes		:	ARP ioctl control errors.
  */
 
 /* RFC1122 Status:
@@ -649,6 +650,7 @@
 	skb->arp = 1;
 	skb->dev = dev;
 	skb->free = 1;
+	skb->protocol = htons (ETH_P_IP);
 
 	/*
 	 *	Fill the device header for the ARP frame
@@ -1057,7 +1059,7 @@
 	{
 		for (entry = arp_tables[HASH(paddr)];
 		     entry != NULL; entry = entry->next)
-			if (entry->ip == paddr && entry->dev == dev)
+			if (entry->ip == paddr && (!dev || entry->dev == dev))
 				break;
 		return entry;
 	}
@@ -1066,13 +1068,14 @@
 	{
 		for (entry = arp_proxy_list;
 		     entry != NULL; entry = entry->next)
-			if (entry->ip == paddr && entry->dev == dev)
+			if (entry->ip == paddr && (!dev || entry->dev == dev))
 				break;
 		return entry;
 	}
 
 	for (entry=arp_proxy_list; entry != NULL; entry = entry->next)
-		if (!((entry->ip^paddr)&entry->mask) && entry->dev == dev)
+		if (!((entry->ip^paddr)&entry->mask) && 
+		                                  (!dev || entry->dev == dev))
 			break;
 	return entry;
 }
@@ -1597,6 +1600,19 @@
 	restore_flags(flags);
 }
 
+/*
+ * Test if a hardware address is all zero
+ */
+static inline int empty(unsigned char * addr, int len)
+{
+	while (len > 0) {
+		if (*addr)
+			return 0;
+		len--;
+		addr++;
+	}
+	return 1;
+}
 
 /*
  *	Set (create) an ARP cache entry.
@@ -1607,7 +1623,8 @@
 	struct arp_table *entry;
 	struct sockaddr_in *si;
 	struct rtable *rt;
-	struct device * dev1;
+	struct device *dev1;
+	unsigned char *ha;
 	u32 ip;
 
 	/*
@@ -1626,12 +1643,19 @@
 	 *	Is it reachable ?
 	 */
 
-	rt = ip_rt_route(ip, 0);
-	if (!rt)
-		return -ENETUNREACH;
-	dev1 = rt->rt_dev;
-	ip_rt_put(rt);
+	if (ip_chk_addr(ip) == IS_MYADDR)
+		dev1 = dev_get("lo");
+	else {
+		rt = ip_rt_route(ip, 0);
+		if (!rt)
+			return -ENETUNREACH;
+		dev1 = rt->rt_dev;
+		ip_rt_put(rt);
+	}
 
+	if (!dev)	/* this is can only be NULL if ATF_PUBL is not set */
+		dev = dev1;
+		
 	if (((r->arp_flags & ATF_PUBL) && dev == dev1) ||
 	    (!(r->arp_flags & ATF_PUBL) && dev != dev1))
 		return -EINVAL;
@@ -1697,11 +1721,10 @@
 	/*
 	 *	We now have a pointer to an ARP entry.  Update it!
 	 */
-	
-	if ((r->arp_flags & ATF_COM) && !r->arp_ha.sa_data[0])
-		memcpy(&entry->ha, dev->dev_addr, dev->addr_len);
-	else
-		memcpy(&entry->ha, &r->arp_ha.sa_data, dev->addr_len);
+	ha = r->arp_ha.sa_data;
+	if ((r->arp_flags & ATF_COM) && empty(ha, dev->addr_len))
+		ha = dev->dev_addr;
+	memcpy(entry->ha, ha, dev->addr_len);
 	entry->last_updated = entry->last_used = jiffies;
 	entry->flags = r->arp_flags | ATF_COM;
 	if ((entry->flags & ATF_PUBL) && (entry->flags & ATF_NETMASK))
@@ -1773,7 +1796,7 @@
 		for (entry = arp_tables[HASH(si->sin_addr.s_addr)];
 		     entry != NULL; entry = entry->next)
 			if (entry->ip == si->sin_addr.s_addr 
-			    && entry->dev == dev)
+			    && (!dev || entry->dev == dev))
 			{
 				arp_destroy(entry);
 				arp_unlock();
@@ -1785,7 +1808,7 @@
 		for (entry = arp_proxy_list;
 		     entry != NULL; entry = entry->next)
 			if (entry->ip == si->sin_addr.s_addr 
-			    && entry->dev == dev) 
+			    && (!dev || entry->dev == dev)) 
 			{
 				arp_destroy(entry);
 				arp_unlock();
@@ -1852,12 +1875,12 @@
 	}
 	else
 	{
-		/*
-		 * Device was not specified. Take the first suitable one.
-		 */
-		if ((dev = dev_getbytype(r.arp_ha.sa_family)) == NULL)
-			return -ENODEV;
-	}
+		if ((r.arp_flags & ATF_PUBL) &&
+		    ((cmd == SIOCSARP) || (cmd == OLD_SIOCSARP))) {
+			if ((dev = dev_getbytype(r.arp_ha.sa_family)) == NULL)
+				return -ENODEV;
+		}
+	}		 
 
 	switch(cmd)
 	{
diff -u --recursive --new-file v1.3.43/linux/net/ipv4/igmp.c linux/net/ipv4/igmp.c
--- v1.3.43/linux/net/ipv4/igmp.c	Fri Nov 17 08:42:33 1995
+++ linux/net/ipv4/igmp.c	Fri Nov 24 16:39:54 1995
@@ -2,12 +2,12 @@
  *	Linux NET3:	Internet Gateway Management Protocol  [IGMP]
  *
  *	This code implements the IGMP protocol as defined in RFC1122. There has
- *	been a further revision of this protocol since, but since it is not 
+ *	been a further revision of this protocol since, but since it is not
  *	cleanly specified in any IETF standards we implement the old one properly
  *	rather than play a game of guess the BSD unofficial extensions.
  *
  *	Authors:
- *		Alan Cox <Alan.Cox@linux.org>	
+ *		Alan Cox <Alan.Cox@linux.org>
  *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License
@@ -15,7 +15,7 @@
  *	2 of the License, or (at your option) any later version.
  *
  *	Fixes:
- *	
+ *
  *		Alan Cox	:	Added lots of __inline__ to optimise
  *					the memory usage of all the tiny little
  *					functions.
@@ -28,9 +28,19 @@
  *					desired by mrouted, fixed the fact it has been
  *					broken since 1.3.6 and cleaned up a few minor
  *					points.
+ *		Chih-Jen Chang	:	Tried to revise IGMP to Version 2
+ *		Tsu-Sheng Tsao		chihjenc@scf.usc.edu and tsusheng@scf.usc.edu
+ *					The enhancements are based on Steve Deering's ipmulti-3.5 code
+ *		Chih-Jen Chang	:	Added the igmp_get_mrouter_info and
+ *		Tsu-Sheng Tsao		igmp_set_mrouter_info to keep track of
+ *					the mrouted version on that device.
+ *		Chih-Jen Chang	:	Added the max_resp_time parameter to
+ *		Tsu-Sheng Tsao		igmp_heard_query(). Using this parameter
+ *					to identify the multicast router verion
+ *					and do what the IGMP version 2 specified.
  */
- 
- 
+
+
 #include <asm/segment.h>
 #include <asm/system.h>
 #include <linux/types.h>
@@ -56,10 +66,75 @@
 
 
 /*
+ *	Multicast router info manager
+ */
+
+struct	router_info	*router_info_head=(struct router_info *)0;
+
+/*
+ *	Get the multicast router info on that device
+ */
+
+static	struct	router_info	*igmp_get_mrouter_info(struct device *dev)
+{
+	register struct router_info *i;
+
+	for(i=router_info_head;i!=NULL;i=i->next)
+	{
+		if (i->dev == dev)
+		{
+			return i;
+		}
+	}
+
+	/*
+	 *  Not found. Create a new entry. The default is IGMP V2 router
+	 */
+	i=(struct router_info *)kmalloc(sizeof(*i), GFP_KERNEL);
+	i->dev = dev;
+	i->type = IGMP_NEW_ROUTER;
+	i->time = IGMP_AGE_THRESHOLD;
+	i->next = router_info_head;
+	router_info_head = i;
+	return i;
+}
+
+/*
+ *	Set the multicast router info on that device
+ */
+
+static	struct	router_info	*igmp_set_mrouter_info(struct device *dev,int type,int time)
+{
+	register struct router_info *i;
+
+	for(i=router_info_head;i!=NULL;i=i->next)
+	{
+		if (i->dev == dev)
+		{
+			i->type = type;
+			i->time = time;
+			return i;
+		}
+	}
+
+	/*
+	 *  Not found. Create a new entry.
+	 */
+	i=(struct router_info *)kmalloc(sizeof(*i), GFP_KERNEL);
+	i->dev = dev;
+	i->type = type;
+	i->time = time;
+	i->next = router_info_head;
+	router_info_head = i;
+	return i;
+}
+
+
+/*
  *	Timer management
  */
- 
- 
+
+
 static void igmp_stop_timer(struct ip_mc_list *im)
 {
 	del_timer(&im->timer);
@@ -77,17 +152,17 @@
  *	Inlined as its only called once.
  */
 
-static void igmp_start_timer(struct ip_mc_list *im)
+static void igmp_start_timer(struct ip_mc_list *im,unsigned char max_resp_time)
 {
 	int tv;
 	if(im->tm_running)
 		return;
-	tv=random()%(10*HZ);		/* Pick a number any number 8) */
+	tv=random()%(max_resp_time*HZ/IGMP_TIMER_SCALE); /* Pick a number any number 8) */
 	im->timer.expires=jiffies+tv;
 	im->tm_running=1;
 	add_timer(&im->timer);
 }
- 
+
 /*
  *	Send an IGMP report.
  */
@@ -99,7 +174,7 @@
 	struct sk_buff *skb=alloc_skb(MAX_IGMP_SIZE, GFP_ATOMIC);
 	int tmp;
 	struct igmphdr *ih;
-	
+
 	if(skb==NULL)
 		return;
 	tmp=ip_build_header(skb, INADDR_ANY, address, &dev, IPPROTO_IGMP, NULL,
@@ -110,7 +185,7 @@
 		return;
 	}
 	ih=(struct igmphdr *)skb_put(skb,sizeof(struct igmphdr));
-	ih->type=IGMP_HOST_MEMBERSHIP_REPORT;
+	ih->type=type;
 	ih->code=0;
 	ih->csum=0;
 	ih->group=address;
@@ -122,8 +197,13 @@
 static void igmp_timer_expire(unsigned long data)
 {
 	struct ip_mc_list *im=(struct ip_mc_list *)data;
+	struct router_info *r;
 	igmp_stop_timer(im);
-	igmp_send_report(im->interface, im->multiaddr, IGMP_HOST_MEMBERSHIP_REPORT);
+	r=igmp_get_mrouter_info(im->interface);
+	if(r->type==IGMP_NEW_ROUTER)
+		igmp_send_report(im->interface, im->multiaddr, IGMP_HOST_NEW_MEMBERSHIP_REPORT);
+	else
+		igmp_send_report(im->interface, im->multiaddr, IGMP_HOST_MEMBERSHIP_REPORT);
 }
 
 static void igmp_init_timer(struct ip_mc_list *im)
@@ -133,7 +213,7 @@
 	im->timer.data=(unsigned long)im;
 	im->timer.function=&igmp_timer_expire;
 }
-	
+
 
 static void igmp_heard_report(struct device *dev, unsigned long address)
 {
@@ -143,20 +223,72 @@
 			igmp_stop_timer(im);
 }
 
-static void igmp_heard_query(struct device *dev)
+static void igmp_heard_query(struct device *dev,unsigned char max_resp_time)
 {
 	struct ip_mc_list *im;
-	for(im=dev->ip_mc_list;im!=NULL;im=im->next)
+	int	mrouter_type;
+
+	/*
+	 *	The max_resp_time is in units of 1/10 second.
+	 */
+	if(max_resp_time>0)
 	{
-		if(!im->tm_running && im->multiaddr!=IGMP_ALL_HOSTS)
-			igmp_start_timer(im);
+		mrouter_type=IGMP_NEW_ROUTER;
+
+		igmp_set_mrouter_info(dev,mrouter_type,0);
+		/*
+		 * - Start the timers in all of our membership records
+		 *   that the query applies to for the interface on
+		 *   which the query arrived excl. those that belong
+		 *   to a "local" group (224.0.0.X)
+		 * - For timers already running check if they need to
+		 *   be reset.
+		 * - Use the igmp->igmp_code field as the maximum
+		 *   delay possible
+		 */
+		for(im=dev->ip_mc_list;im!=NULL;im=im->next)
+		{
+			if(im->tm_running)
+			{
+				if(im->timer.expires>max_resp_time*HZ/IGMP_TIMER_SCALE)
+				{
+					igmp_stop_timer(im);
+					igmp_start_timer(im,max_resp_time);
+				}
+			}
+			else
+			{
+				if((im->multiaddr & IGMP_LOCAL_GROUP_MASK)!=IGMP_LOCAL_GROUP)
+					igmp_start_timer(im,max_resp_time);
+			}
+		}
+	}
+	else
+	{
+		mrouter_type=IGMP_OLD_ROUTER;
+		max_resp_time=IGMP_MAX_HOST_REPORT_DELAY*IGMP_TIMER_SCALE;
+
+		igmp_set_mrouter_info(dev,mrouter_type,IGMP_AGE_THRESHOLD);
+
+		/*
+		 * Start the timers in all of our membership records for
+		 * the interface on which the query arrived, except those
+		 * that are already running and those that belong to a
+		 * "local" group (224.0.0.X).
+		 */
+
+		for(im=dev->ip_mc_list;im!=NULL;im=im->next)
+		{
+			if(!im->tm_running && (im->multiaddr & IGMP_LOCAL_GROUP_MASK)!=IGMP_LOCAL_GROUP)
+				igmp_start_timer(im,max_resp_time);
+		}
 	}
 }
 
 /*
  *	Map a multicast IP onto multicast MAC for type ethernet.
  */
- 
+
 extern __inline__ void ip_mc_map(unsigned long addr, char *buf)
 {
 	addr=ntohl(addr);
@@ -173,26 +305,26 @@
 /*
  *	Add a filter to a device
  */
- 
+
 void ip_mc_filter_add(struct device *dev, unsigned long addr)
 {
 	char buf[6];
 	if(dev->type!=ARPHRD_ETHER)
-		return;	/* Only do ethernet now */
-	ip_mc_map(addr,buf);	
+		return; /* Only do ethernet now */
+	ip_mc_map(addr,buf);
 	dev_mc_add(dev,buf,ETH_ALEN,0);
 }
 
 /*
  *	Remove a filter from a device
  */
- 
+
 void ip_mc_filter_del(struct device *dev, unsigned long addr)
 {
 	char buf[6];
 	if(dev->type!=ARPHRD_ETHER)
-		return;	/* Only do ethernet now */
-	ip_mc_map(addr,buf);	
+		return; /* Only do ethernet now */
+	ip_mc_map(addr,buf);
 	dev_mc_delete(dev,buf,ETH_ALEN,0);
 }
 
@@ -205,9 +337,14 @@
 
 extern __inline__ void igmp_group_added(struct ip_mc_list *im)
 {
+	struct router_info *r;
 	igmp_init_timer(im);
 	ip_mc_filter_add(im->interface, im->multiaddr);
-	igmp_send_report(im->interface, im->multiaddr, IGMP_HOST_MEMBERSHIP_REPORT);
+	r=igmp_get_mrouter_info(im->interface);
+	if(r->type==IGMP_NEW_ROUTER)
+		igmp_send_report(im->interface, im->multiaddr, IGMP_HOST_NEW_MEMBERSHIP_REPORT);
+	else
+		igmp_send_report(im->interface, im->multiaddr, IGMP_HOST_MEMBERSHIP_REPORT);
 }
 
 int igmp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
@@ -216,13 +353,13 @@
 {
 	/* This basically follows the spec line by line -- see RFC1112 */
 	struct igmphdr *ih;
-	
+
 	/*
 	 *	Mrouted needs to able to query local interfaces. So
 	 *	report for the device this was sent at. (Which can
 	 *	be the loopback this time)
 	 */
-	 
+
 	if(dev->flags&IFF_LOOPBACK)
 	{
 		dev=ip_dev_find(saddr);
@@ -230,17 +367,19 @@
 			dev=&loopback_dev;
 	}
 	ih=(struct igmphdr *)skb->h.raw;
-		
+
 	if(skb->len <sizeof(struct igmphdr) || skb->ip_hdr->ttl>1 || ip_compute_csum((void *)skb->h.raw,sizeof(struct igmphdr)))
 	{
 		kfree_skb(skb, FREE_READ);
 		return 0;
 	}
-	
+
 	if(ih->type==IGMP_HOST_MEMBERSHIP_QUERY && daddr==IGMP_ALL_HOSTS)
-		igmp_heard_query(dev);
+		igmp_heard_query(dev,ih->code);
 	if(ih->type==IGMP_HOST_MEMBERSHIP_REPORT && daddr==ih->group)
 		igmp_heard_report(dev,ih->group);
+	if(ih->type==IGMP_HOST_NEW_MEMBERSHIP_REPORT && daddr==ih->group)
+		igmp_heard_report(dev,ih->group);
 	kfree_skb(skb, FREE_READ);
 	return 0;
 }
@@ -248,12 +387,12 @@
 /*
  *	Multicast list managers
  */
- 
- 
+
+
 /*
  *	A socket has joined a multicast group on device dev.
  */
-  
+
 static void ip_mc_inc_group(struct device *dev, unsigned long addr)
 {
 	struct ip_mc_list *i;
@@ -279,7 +418,7 @@
 /*
  *	A socket has left a multicast group on device dev
  */
-	
+
 static void ip_mc_dec_group(struct device *dev, unsigned long addr)
 {
 	struct ip_mc_list **i;
@@ -303,7 +442,7 @@
 /*
  *	Device going down: Clean up.
  */
- 
+
 void ip_mc_drop_device(struct device *dev)
 {
 	struct ip_mc_list *i;
@@ -319,13 +458,24 @@
 /*
  *	Device going up. Make sure it is in all hosts
  */
- 
+
 void ip_mc_allhost(struct device *dev)
 {
 	struct ip_mc_list *i;
+	/*
+	 *	Don't add to non multicast units
+	 */
+	if(!(dev->flags&IFF_MULTICAST))
+		return;
+	/*
+	 *	No duplicates
+	 */
 	for(i=dev->ip_mc_list;i!=NULL;i=i->next)
 		if(i->multiaddr==IGMP_ALL_HOSTS)
 			return;
+	/*
+	 *	Add it
+	 */
 	i=(struct ip_mc_list *)kmalloc(sizeof(*i), GFP_KERNEL);
 	if(!i)
 		return;
@@ -337,12 +487,12 @@
 	dev->ip_mc_list=i;
 	ip_mc_filter_add(i->interface, i->multiaddr);
 
-}	
- 
+}
+
 /*
  *	Join a socket to a group
  */
- 
+
 int ip_mc_join_group(struct sock *sk , struct device *dev, unsigned long addr)
 {
 	int unused= -1;
@@ -364,7 +514,7 @@
 		if(sk->ip_mc_list->multidev[i]==NULL)
 			unused=i;
 	}
-	
+
 	if(unused==-1)
 		return -ENOBUFS;
 	sk->ip_mc_list->multiaddr[unused]=addr;
@@ -376,7 +526,7 @@
 /*
  *	Ask a socket to leave a group.
  */
- 
+
 int ip_mc_leave_group(struct sock *sk, struct device *dev, unsigned long addr)
 {
 	int i;
@@ -386,7 +536,7 @@
 		return -EADDRNOTAVAIL;
 	if(sk->ip_mc_list==NULL)
 		return -EADDRNOTAVAIL;
-		
+
 	for(i=0;i<IP_MAX_MEMBERSHIPS;i++)
 	{
 		if(sk->ip_mc_list->multiaddr[i]==addr && sk->ip_mc_list->multidev[i]==dev)
@@ -402,14 +552,14 @@
 /*
  *	A socket is closing.
  */
- 
+
 void ip_mc_drop_socket(struct sock *sk)
 {
 	int i;
-	
+
 	if(sk->ip_mc_list==NULL)
 		return;
-		
+
 	for(i=0;i<IP_MAX_MEMBERSHIPS;i++)
 	{
 		if(sk->ip_mc_list->multidev[i])
diff -u --recursive --new-file v1.3.43/linux/net/ipv4/ip_forward.c linux/net/ipv4/ip_forward.c
--- v1.3.43/linux/net/ipv4/ip_forward.c	Fri Nov 17 08:42:33 1995
+++ linux/net/ipv4/ip_forward.c	Fri Nov 24 16:39:54 1995
@@ -274,6 +274,7 @@
 			/*
 			 *	Add the physical headers.
 			 */
+			skb2->protocol=htons(ETH_P_IP);
 #ifdef CONFIG_IP_MROUTE
 			if(is_frag&16)
 			{
diff -u --recursive --new-file v1.3.43/linux/net/ipv4/ip_output.c linux/net/ipv4/ip_output.c
--- v1.3.43/linux/net/ipv4/ip_output.c	Fri Nov 17 08:42:34 1995
+++ linux/net/ipv4/ip_output.c	Fri Nov 24 16:39:54 1995
@@ -116,6 +116,7 @@
 
 	skb->dev = dev;
 	skb->arp = 1;
+	skb->protocol = htons(ETH_P_IP);
 	if (dev->hard_header)
 	{
 		/*
@@ -152,6 +153,7 @@
 
 	skb->dev = dev;
 	skb->arp = 1;
+	skb->protocol = ETH_P_IP;
 	if (dev->hard_header)
 	{
 		skb_reserve(skb,MAX_HEADER);
diff -u --recursive --new-file v1.3.43/linux/net/ipv4/ipmr.c linux/net/ipv4/ipmr.c
--- v1.3.43/linux/net/ipv4/ipmr.c	Wed Nov  8 07:11:46 1995
+++ linux/net/ipv4/ipmr.c	Fri Nov 24 16:39:54 1995
@@ -359,6 +359,7 @@
 	 */
 	
 	cli();
+
 	cache=ipmr_cache_find(mfc->mfcc_origin.s_addr,mfc->mfcc_mcastgrp.s_addr);
 	
 	/*
diff -u --recursive --new-file v1.3.43/linux/net/ipv4/raw.c linux/net/ipv4/raw.c
--- v1.3.43/linux/net/ipv4/raw.c	Fri Nov 17 08:42:34 1995
+++ linux/net/ipv4/raw.c	Sat Nov 25 18:23:09 1995
@@ -125,6 +125,16 @@
 	skb->dev = dev;
 	skb->saddr = daddr;
 	skb->daddr = saddr;
+
+#if 0	
+	/*
+	 *	For no adequately explained reasons BSD likes to mess up the header of
+	 *	the received frame. 
+	 */
+	 
+	if(sk->bsdism)
+		skb->ip_hdr->tot_len=ntohs(skb->ip_hdr->tot_len-4*skb->ip_hdr->ihl);
+#endif
 	
 	/* Charge it to the socket. */
 	
diff -u --recursive --new-file v1.3.43/linux/net/ipv4/tcp.c linux/net/ipv4/tcp.c
--- v1.3.43/linux/net/ipv4/tcp.c	Fri Nov 17 08:42:34 1995
+++ linux/net/ipv4/tcp.c	Thu Nov 23 12:21:50 1995
@@ -734,7 +734,7 @@
 			 *	this up by avoiding a full checksum.
 			 */
 		 
-			th->ack_seq = ntohl(sk->acked_seq);
+			th->ack_seq = htonl(sk->acked_seq);
 			th->window = ntohs(tcp_select_window(sk));
 			tcp_send_check(th, sk->saddr, sk->daddr, size, sk);
 		
@@ -1163,9 +1163,9 @@
 	 
 	do 
 	{
-		if (before(counted, skb->h.th->seq)) 	/* Found a hole so stops here */
+		if (before(counted, skb->seq))	 	/* Found a hole so stops here */
 			break;
-		sum = skb->len -(counted - skb->h.th->seq);	/* Length - header but start from where we are up to (avoid overlaps) */
+		sum = skb->len - (counted - skb->seq);	/* Length - header but start from where we are up to (avoid overlaps) */
 		if (skb->h.th->syn)
 			sum++;
 		if (sum > 0) 
@@ -1405,7 +1405,8 @@
 	 */
 	 
 	tcp_statistics.TcpOutSegs++;  
-	skb->h.seq = ntohl(th->seq) + size - 4*th->doff;
+	skb->seq = ntohl(th->seq);
+	skb->end_seq = skb->seq + size - 4*th->doff;
 	
 	/*
 	 *	We must queue if
@@ -1415,7 +1416,7 @@
 	 *	c) We have too many packets 'in flight'
 	 */
 	 
-	if (after(skb->h.seq, sk->window_seq) ||
+	if (after(skb->end_seq, sk->window_seq) ||
 	    (sk->retransmits && sk->ip_xmit_timeout == TIME_WRITE) ||
 	     sk->packets_out >= sk->cong_window) 
 	{
@@ -1436,7 +1437,7 @@
 		 *	grief).
 		 */
 		 
-		if (before(sk->window_seq, sk->write_queue.next->h.seq) &&
+		if (before(sk->window_seq, sk->write_queue.next->end_seq) &&
 		    sk->send_head == NULL && sk->ack_backlog == 0)
 			reset_xmit_timer(sk, TIME_PROBE0, sk->rto);
 	} 
@@ -1446,8 +1447,8 @@
 		 *	This is going straight out
 		 */
 		 
-		th->ack_seq = ntohl(sk->acked_seq);
-		th->window = ntohs(tcp_select_window(sk));
+		th->ack_seq = htonl(sk->acked_seq);
+		th->window = htons(tcp_select_window(sk));
 
 		tcp_send_check(th, sk->saddr, sk->daddr, size, sk);
 
@@ -1645,7 +1646,7 @@
   	 *	Fill in the packet and send it
   	 */
   	 
-  	t1->ack_seq = ntohl(ack);
+  	t1->ack_seq = htonl(ack);
   	t1->doff = sizeof(*t1)/4;
   	tcp_send_check(t1, sk->saddr, daddr, sizeof(*t1), sk);
   	if (sk->debug)
@@ -2117,8 +2118,8 @@
 	sk->ack_backlog = 0;
 	sk->bytes_rcv = 0;
 	sk->window = tcp_select_window(sk);
-	t1->window = ntohs(sk->window);
-	t1->ack_seq = ntohl(sk->acked_seq);
+	t1->window = htons(sk->window);
+	t1->ack_seq = htonl(sk->acked_seq);
 	t1->doff = sizeof(*t1)/4;
 	tcp_send_check(t1, sk->saddr, sk->daddr, sizeof(*t1), sk);
 	sk->prot->queue_xmit(sk, dev, buff, 1);
@@ -2343,9 +2344,9 @@
 		{
 			if (!skb)
 				break;
-			if (before(*seq, skb->h.th->seq))
+			if (before(*seq, skb->seq))
 				break;
-			offset = *seq - skb->h.th->seq;
+			offset = *seq - skb->seq;
 			if (skb->h.th->syn)
 				offset--;
 			if (offset < skb->len)
@@ -2645,12 +2646,13 @@
 	t1 =(struct tcphdr *)skb_put(buff,sizeof(struct tcphdr));
 	buff->dev = dev;
 	memcpy(t1, th, sizeof(*t1));
-	t1->seq = ntohl(sk->write_seq);
+	buff->seq = sk->write_seq;
 	sk->write_seq++;
-	buff->h.seq = sk->write_seq;
+	buff->end_seq = sk->write_seq;
+	t1->seq = htonl(buff->seq);
 	t1->ack = 1;
-	t1->ack_seq = ntohl(sk->acked_seq);
-	t1->window = ntohs(sk->window=tcp_select_window(sk));
+	t1->ack_seq = htonl(sk->acked_seq);
+	t1->window = htons(sk->window=tcp_select_window(sk));
 	t1->fin = 1;
 	t1->rst = 0;
 	t1->doff = sizeof(*t1)/4;
@@ -2802,10 +2804,10 @@
 	{
 	  	t1->ack = 1;
 	  	if(!th->syn)
-  			t1->ack_seq=htonl(th->seq);
-  		else
-  			t1->ack_seq=htonl(th->seq+1);
-  		t1->seq=0;
+			t1->ack_seq = th->seq;
+		else
+			t1->ack_seq = htonl(ntohl(th->seq)+1);
+		t1->seq = 0;
 	}
 
 	t1->syn = 0;
@@ -3021,9 +3023,9 @@
 	newsk->err = 0;
 	newsk->shutdown = 0;
 	newsk->ack_backlog = 0;
-	newsk->acked_seq = skb->h.th->seq+1;
-	newsk->copied_seq = skb->h.th->seq+1;
-	newsk->fin_seq = skb->h.th->seq;
+	newsk->acked_seq = skb->seq+1;
+	newsk->copied_seq = skb->seq+1;
+	newsk->fin_seq = skb->seq;
 	newsk->state = TCP_SYN_RECV;
 	newsk->timeout = 0;
 	newsk->ip_xmit_timeout = 0;
@@ -3061,8 +3063,8 @@
 	newsk->dummy_th.ack = 0;
 	newsk->dummy_th.urg = 0;
 	newsk->dummy_th.res2 = 0;
-	newsk->acked_seq = skb->h.th->seq + 1;
-	newsk->copied_seq = skb->h.th->seq + 1;
+	newsk->acked_seq = skb->seq + 1;
+	newsk->copied_seq = skb->seq + 1;
 	newsk->socket = NULL;
 
 	/*
@@ -3167,13 +3169,14 @@
 	t1 =(struct tcphdr *)skb_put(buff,sizeof(struct tcphdr));
   
 	memcpy(t1, skb->h.th, sizeof(*t1));
-	buff->h.seq = newsk->write_seq;
+	buff->seq = newsk->write_seq++;
+	buff->end_seq = newsk->write_seq;
 	/*
 	 *	Swap the send and the receive. 
 	 */
 	t1->dest = skb->h.th->source;
 	t1->source = newsk->dummy_th.source;
-	t1->seq = ntohl(newsk->write_seq++);
+	t1->seq = ntohl(buff->seq);
 	t1->ack = 1;
 	newsk->window = tcp_select_window(newsk);
 	newsk->sent_seq = newsk->write_seq;
@@ -3184,7 +3187,7 @@
 	t1->urg = 0;
 	t1->psh = 0;
 	t1->syn = 1;
-	t1->ack_seq = ntohl(skb->h.th->seq+1);
+	t1->ack_seq = htonl(newsk->acked_seq);
 	t1->doff = sizeof(*t1)/4+1;
 	ptr = skb_put(buff,4);
 	ptr[0] = 2;
@@ -3305,10 +3308,10 @@
 	 */
 	 
 	while((skb = skb_peek(&sk->write_queue)) != NULL &&
-		before(skb->h.seq, sk->window_seq + 1) &&
+		before(skb->end_seq, sk->window_seq + 1) &&
 		(sk->retransmits == 0 ||
 		 sk->ip_xmit_timeout != TIME_WRITE ||
-		 before(skb->h.seq, sk->rcv_ack_seq + 1))
+		 before(skb->end_seq, sk->rcv_ack_seq + 1))
 		&& sk->packets_out < sk->cong_window) 
 	{
 		IS_SKB(skb);
@@ -3318,7 +3321,7 @@
 		 *	See if we really need to send the packet. 
 		 */
 		 
-		if (before(skb->h.seq, sk->rcv_ack_seq +1)) 
+		if (before(skb->end_seq, sk->rcv_ack_seq +1)) 
 		{
 			/*
 			 *	This is acked data. We can discard it. This 
@@ -3353,12 +3356,12 @@
 			}
 #endif
 			
-			th->ack_seq = ntohl(sk->acked_seq);
-			th->window = ntohs(tcp_select_window(sk));
+			th->ack_seq = htonl(sk->acked_seq);
+			th->window = htons(tcp_select_window(sk));
 
 			tcp_send_check(th, sk->saddr, sk->daddr, size, sk);
 
-			sk->sent_seq = skb->h.seq;
+			sk->sent_seq = skb->end_seq;
 			
 			/*
 			 *	IP manages our queue for some crazy reason
@@ -3494,7 +3497,7 @@
 			skb = skb2;
 			skb2 = skb->link3;
 			skb->link3 = NULL;
-			if (after(skb->h.seq, sk->window_seq)) 
+			if (after(skb->end_seq, sk->window_seq)) 
 			{
 				if (sk->packets_out > 0) 
 					sk->packets_out--;
@@ -3603,7 +3606,7 @@
 		 */
 		 
   		if (skb_peek(&sk->write_queue) != NULL &&   /* should always be non-null */
-		    ! before (sk->window_seq, sk->write_queue.next->h.seq)) 
+		    ! before (sk->window_seq, sk->write_queue.next->end_seq)) 
 		{
 			sk->backoff = 0;
 			
@@ -3629,7 +3632,7 @@
 	{
 		/* Check for a bug. */
 		if (sk->send_head->link3 &&
-		    after(sk->send_head->h.seq, sk->send_head->link3->h.seq)) 
+		    after(sk->send_head->end_seq, sk->send_head->link3->end_seq)) 
 			printk("INET: tcp.c: *** bug send_list out of order.\n");
 			
 		/*
@@ -3637,7 +3640,7 @@
 		 *	discard it as it's confirmed to have arrived the other end.
 		 */
 		 
-		if (before(sk->send_head->h.seq, ack+1)) 
+		if (before(sk->send_head->end_seq, ack+1)) 
 		{
 			struct sk_buff *oskb;	
 			if (sk->retransmits) 
@@ -3761,10 +3764,10 @@
 	 */
 	if (skb_peek(&sk->write_queue) != NULL) 
 	{
-		if (after (sk->window_seq+1, sk->write_queue.next->h.seq) &&
+		if (after (sk->window_seq+1, sk->write_queue.next->end_seq) &&
 			(sk->retransmits == 0 || 
 			 sk->ip_xmit_timeout != TIME_WRITE ||
-			 before(sk->write_queue.next->h.seq, sk->rcv_ack_seq + 1))
+			 before(sk->write_queue.next->end_seq, sk->rcv_ack_seq + 1))
 			&& sk->packets_out < sk->cong_window) 
 		{
 			/*
@@ -3773,7 +3776,7 @@
 			flag |= 1;
 			tcp_write_xmit(sk);
 		}
-		else if (before(sk->window_seq, sk->write_queue.next->h.seq) &&
+		else if (before(sk->window_seq, sk->write_queue.next->end_seq) &&
  			sk->send_head == NULL &&
  			sk->ack_backlog == 0 &&
  			sk->state != TCP_TIME_WAIT) 
@@ -3985,7 +3988,7 @@
  
 static int tcp_fin(struct sk_buff *skb, struct sock *sk, struct tcphdr *th)
 {
-	sk->fin_seq = th->seq + skb->len + th->syn + th->fin;
+	sk->fin_seq = skb->end_seq;
 
 	if (!sk->dead) 
 	{
@@ -4119,7 +4122,7 @@
 		if(skb->len)	/* We don't care if it's just an ack or
 				   a keepalive/window probe */
 		{
-			new_seq= th->seq + skb->len + th->syn;	/* Right edge of _data_ part of frame */
+			new_seq = skb->seq + skb->len + th->syn;	/* Right edge of _data_ part of frame */
 			
 			/* Do this the way 4.4BSD treats it. Not what I'd
 			   regard as the meaning of the spec but it's what BSD
@@ -4132,7 +4135,7 @@
 			 *	b) A fin takes effect when read not when received.
 			 */
 			 
-			shut_seq=sk->acked_seq+1;	/* Last byte */
+			shut_seq = sk->acked_seq+1;	/* Last byte */
 			
 			if(after(new_seq,shut_seq))
 			{
@@ -4181,8 +4184,8 @@
 			if(sk->debug)
 			{
 				printk("skb1=%p :", skb1);
-				printk("skb1->h.th->seq = %d: ", skb1->h.th->seq);
-				printk("skb->h.th->seq = %d\n",skb->h.th->seq);
+				printk("skb1->seq = %d: ", skb1->seq);
+				printk("skb->seq = %d\n",skb->seq);
 				printk("copied_seq = %d acked_seq = %d\n", sk->copied_seq,
 						sk->acked_seq);
 			}
@@ -4195,7 +4198,7 @@
 			 *	the new one in its place.
 			 */
 			 
-			if (th->seq==skb1->h.th->seq && skb->len>= skb1->len)
+			if (skb->seq==skb1->seq && skb->len>=skb1->len)
 			{
 				skb_append(skb1,skb);
 				skb_unlink(skb1);
@@ -4209,7 +4212,7 @@
 			 *	Found where it fits
 			 */
 			 
-			if (after(th->seq+1, skb1->h.th->seq))
+			if (after(skb->seq+1, skb1->seq))
 			{
 				skb_append(skb1,skb);
 				break;
@@ -4230,12 +4233,6 @@
 	 *	Figure out what the ack value for this frame is
 	 */
 	 
- 	th->ack_seq = th->seq + skb->len;
- 	if (th->syn) 
- 		th->ack_seq++;
- 	if (th->fin)
- 		th->ack_seq++;
-
 	if (before(sk->acked_seq, sk->copied_seq)) 
 	{
 		printk("*** tcp.c:tcp_data bug acked < copied\n");
@@ -4248,19 +4245,19 @@
 	 *	queue.
 	 */
 
-	if ((!dup_dumped && (skb1 == NULL || skb1->acked)) || before(th->seq, sk->acked_seq+1)) 
+	if ((!dup_dumped && (skb1 == NULL || skb1->acked)) || before(skb->seq, sk->acked_seq+1)) 
 	{
-		if (before(th->seq, sk->acked_seq+1)) 
+		if (before(skb->seq, sk->acked_seq+1)) 
 		{
 			int newwindow;
 
-			if (after(th->ack_seq, sk->acked_seq)) 
+			if (after(skb->end_seq, sk->acked_seq)) 
 			{
-				newwindow = sk->window-(th->ack_seq - sk->acked_seq);
+				newwindow = sk->window - (skb->end_seq - sk->acked_seq);
 				if (newwindow < 0)
 					newwindow = 0;	
 				sk->window = newwindow;
-				sk->acked_seq = th->ack_seq;
+				sk->acked_seq = skb->end_seq;
 			}
 			skb->acked = 1;
 
@@ -4278,16 +4275,16 @@
 			    skb2 != (struct sk_buff *)&sk->receive_queue;
 			    skb2 = skb2->next) 
 			{
-				if (before(skb2->h.th->seq, sk->acked_seq+1)) 
+				if (before(skb2->seq, sk->acked_seq+1)) 
 				{
-					if (after(skb2->h.th->ack_seq, sk->acked_seq))
+					if (after(skb2->end_seq, sk->acked_seq))
 					{
 						newwindow = sk->window -
-						 (skb2->h.th->ack_seq - sk->acked_seq);
+						 (skb2->end_seq - sk->acked_seq);
 						if (newwindow < 0)
 							newwindow = 0;	
 						sk->window = newwindow;
-						sk->acked_seq = skb2->h.th->ack_seq;
+						sk->acked_seq = skb2->end_seq;
 					}
 					skb2->acked = 1;
 					/*
@@ -4403,7 +4400,7 @@
 
 	if (ptr)
 		ptr--;
-	ptr += th->seq;
+	ptr += ntohl(th->seq);
 
 	/* ignore urgent data that we've already seen and read */
 	if (after(sk->copied_seq, ptr))
@@ -4452,7 +4449,7 @@
 	 *	Is the urgent pointer pointing into this packet? 
 	 */
 	 
-	ptr = sk->urg_seq - th->seq + th->doff*4;
+	ptr = sk->urg_seq - ntohl(th->seq) + th->doff*4;
 	if (ptr >= len)
 		return 0;
 
@@ -4608,9 +4605,10 @@
 	t1 = (struct tcphdr *) skb_put(buff,sizeof(struct tcphdr));
 
 	memcpy(t1,(void *)&(sk->dummy_th), sizeof(*t1));
-	t1->seq = ntohl(sk->write_seq++);
+	buff->seq = sk->write_seq++;
+	t1->seq = htonl(buff->seq);
 	sk->sent_seq = sk->write_seq;
-	buff->h.seq = sk->write_seq;
+	buff->end_seq = sk->write_seq;
 	t1->ack = 0;
 	t1->window = 2;
 	t1->res1=0;
@@ -4712,7 +4710,7 @@
 	/* if we have a zero window, we can't have any data in the packet.. */
 	if (next_seq && !sk->window)
 		goto ignore_it;
-	next_seq += th->seq;
+	next_seq += ntohl(th->seq);
 
 	/*
 	 * This isn't quite right.  sk->acked_seq could be more recent
@@ -4725,7 +4723,7 @@
 	if (!after(next_seq+1, sk->acked_seq))
 		goto ignore_it;
 	/* or does it start beyond the window? */
-	if (!before(th->seq, sk->acked_seq + sk->window + 1))
+	if (!before(ntohl(th->seq), sk->acked_seq + sk->window + 1))
 		goto ignore_it;
 
 	/* ok, at least part of this packet would seem interesting.. */
@@ -4864,7 +4862,10 @@
 			 */
 			return(0);
 		}
-		th->seq = ntohl(th->seq);
+
+		skb->seq = ntohl(th->seq);
+		skb->end_seq = skb->seq + th->syn + th->fin + len - th->doff*4;
+		skb->ack_seq = ntohl(th->ack_seq);
 
 		/* See if we know about the socket. */
 		if (sk == NULL) 
@@ -4977,7 +4978,7 @@
 		}
 	
 		/* retransmitted SYN? */
-		if (sk->state == TCP_SYN_RECV && th->syn && th->seq+1 == sk->acked_seq)
+		if (sk->state == TCP_SYN_RECV && th->syn && skb->seq+1 == sk->acked_seq)
 		{
 			kfree_skb(skb, FREE_READ);
 			release_sock(sk);
@@ -5021,8 +5022,8 @@
 				 *	move to established.
 				 */
 				syn_ok=1;	/* Don't reset this connection for the syn */
-				sk->acked_seq=th->seq+1;
-				sk->fin_seq=th->seq;
+				sk->acked_seq = skb->seq+1;
+				sk->fin_seq = skb->seq;
 				tcp_send_ack(sk->sent_seq,sk->acked_seq,sk,th,sk->daddr);
 				tcp_set_state(sk, TCP_ESTABLISHED);
 				tcp_options(sk,th);
@@ -5080,7 +5081,7 @@
 #define BSD_TIME_WAIT
 #ifdef BSD_TIME_WAIT
 		if (sk->state == TCP_TIME_WAIT && th->syn && sk->dead && 
-			after(th->seq, sk->acked_seq) && !th->rst)
+			after(skb->seq, sk->acked_seq) && !th->rst)
 		{
 			u32 seq = sk->write_seq;
 			if(sk->debug)
@@ -5310,8 +5311,8 @@
 		 */
 		 
 		nth->ack = 1; 
-		nth->ack_seq = ntohl(sk->acked_seq);
-		nth->window = ntohs(tcp_select_window(sk));
+		nth->ack_seq = htonl(sk->acked_seq);
+		nth->window = htons(tcp_select_window(sk));
 		nth->check = 0;
 
 		/*
@@ -5330,8 +5331,8 @@
 		 *	Remember our right edge sequence number.
 		 */
 		 
-	    	buff->h.seq = sk->sent_seq + win_size;
-	    	sk->sent_seq = buff->h.seq;		/* Hack */
+	    	buff->end_seq = sk->sent_seq + win_size;
+	    	sk->sent_seq = buff->end_seq;		/* Hack */
 #if 0
 
 	    	/*
@@ -5411,8 +5412,8 @@
 		t1->psh = 0;
 		t1->fin = 0;	/* We are sending a 'previous' sequence, and 0 bytes of data - thus no FIN bit */
 		t1->syn = 0;
-		t1->ack_seq = ntohl(sk->acked_seq);
-		t1->window = ntohs(tcp_select_window(sk));
+		t1->ack_seq = htonl(sk->acked_seq);
+		t1->window = htons(tcp_select_window(sk));
 		t1->doff = sizeof(*t1)/4;
 		tcp_send_check(t1, sk->saddr, sk->daddr, sizeof(*t1), sk);
 
diff -u --recursive --new-file v1.3.43/linux/net/ipv4/udp.c linux/net/ipv4/udp.c
--- v1.3.43/linux/net/ipv4/udp.c	Fri Nov 17 08:42:34 1995
+++ linux/net/ipv4/udp.c	Fri Nov 24 16:39:54 1995
@@ -196,6 +196,12 @@
 
 	if (code < 13 && icmp_err_convert[code].fatal)
 	{
+		/*
+		 *	4.x BSD compatibility item. Break RFC1122 to
+		 *	get BSD socket semantics.
+		 */
+		if(sk->bsdism && sk->state!=TCP_ESTABLISHED)
+			return;
 		sk->err = icmp_err_convert[code].errno;
 		sk->error_report(sk);
 	}
diff -u --recursive --new-file v1.3.43/linux/net/ipx/af_ipx.c linux/net/ipx/af_ipx.c
--- v1.3.43/linux/net/ipx/af_ipx.c	Fri Nov 17 08:42:34 1995
+++ linux/net/ipx/af_ipx.c	Fri Nov 24 16:39:54 1995
@@ -390,7 +390,19 @@
 	 * that skb1 and skb2 point to it (them) so that it (they) can be 
 	 * demuxed to sock1 and/or sock2.  If we are unable to make enough
 	 * copies, we do as much as is possible.
+	 *
+	 * Firstly stop charging the sender for the space. We will
+	 * charge the recipient or discard. If we are called from ipx_rcv
+	 * this is ok as no socket owns an input buffer.
 	 */
+	 
+	if(skb->sk)
+	{
+		skb->sk->wmem_alloc -= skb->truesize;	/* Adjust */
+		skb->sk=NULL;				/* Disown */
+	}
+
+	 
 	if (copy) {
 		skb1 = skb_clone(skb, GFP_ATOMIC);
 		if (skb1 != NULL) {
@@ -529,14 +541,14 @@
 	/* set up data link and physical headers */
 	skb->dev = dev;
 	dl->datalink_header(dl, skb, dest_node);
-
+#ifdef ALREADY_DONE_GUV
 	if (skb->sk != NULL) {
 		/* This is an outbound packet from this host.  We need to 
 		 * increment the write count.
 		 */
 		skb->sk->wmem_alloc += skb->truesize;
 	}
-
+#endif
 #if 0
 	/* Now log the packet just before transmission */
 	dump_pkt("IPX snd:", (ipx_packet *)skb->h.raw);
diff -u --recursive --new-file v1.3.43/linux/net/netrom/nr_dev.c linux/net/netrom/nr_dev.c
--- v1.3.43/linux/net/netrom/nr_dev.c	Fri Nov 17 08:42:34 1995
+++ linux/net/netrom/nr_dev.c	Fri Nov 24 16:39:55 1995
@@ -14,6 +14,7 @@
  *
  *	History
  *	NET/ROM 001	Jonathan(G4KLX)	Cloned from loopback.c
+ *	NET/ROM 002	Steve Whitehouse(GW7RRM) fixed the set_mac_address
  */
 
 #include <linux/config.h>
@@ -140,7 +141,8 @@
 
 static int nr_set_mac_address(struct device *dev, void *addr)
 {
-	memcpy(dev->dev_addr, addr, dev->addr_len);
+	struct sockaddr *sa=addr;
+	memcpy(dev->dev_addr, sa->sa_data, dev->addr_len);
 
 	return 0;
 }
diff -u --recursive --new-file v1.3.43/linux/net/socket.c linux/net/socket.c
--- v1.3.43/linux/net/socket.c	Fri Nov 17 08:42:34 1995
+++ linux/net/socket.c	Fri Nov 24 16:39:55 1995
@@ -670,21 +670,23 @@
 asmlinkage int sys_listen(int fd, int backlog)
 {
 	struct socket *sock;
-
+	int err=-EOPNOTSUPP;
+	
 	if (fd < 0 || fd >= NR_OPEN || current->files->fd[fd] == NULL)
 		return(-EBADF);
 	if (!(sock = sockfd_lookup(fd, NULL))) 
 		return(-ENOTSOCK);
 
 	if (sock->state != SS_UNCONNECTED) 
-	{
 		return(-EINVAL);
-	}
 
 	if (sock->ops && sock->ops->listen)
-		sock->ops->listen(sock, backlog);
-	sock->flags |= SO_ACCEPTCON;
-	return(0);
+	{
+		err=sock->ops->listen(sock, backlog);
+		if(!err)
+			sock->flags |= SO_ACCEPTCON;
+	}
+	return(err);
 }
 
 
diff -u --recursive --new-file v1.3.43/linux/net/unix/af_unix.c linux/net/unix/af_unix.c
--- v1.3.43/linux/net/unix/af_unix.c	Thu Nov  9 11:23:56 1995
+++ linux/net/unix/af_unix.c	Fri Nov 24 16:39:55 1995
@@ -313,6 +313,7 @@
 	sk->sndbuf=SK_WMEM_MAX;
 	sk->allocation=GFP_KERNEL;
 	sk->inuse=0;
+	sk->bsdism=0;
 	sk->debug=0;
 	sk->prot=NULL;
 	sk->err=0;
