diff -u --recursive --new-file v1.3.49/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v1.3.49/linux/Documentation/Configure.help	Wed Dec 13 09:02:45 1995
+++ linux/Documentation/Configure.help	Fri Dec 22 08:51:07 1995
@@ -56,6 +56,15 @@
   want to compile it as a module, say M here and read
   Documentation/modules.txt.
   
+RAM disk support
+CONFIG_BLK_DEV_RAM
+  Enabling this option will allow you to use a portion of your RAM memory 
+  as a block device, so that you can make filesystems on it, read and
+  write to it and do all the other things that normal block devices can do.
+  It is usually used to load and store a copy of a minimal root file
+  system off of a floppy into RAM during the initial install of Linux.
+  Most normal users won't need this functionality, and can thus say N here.
+
 Normal (MFM/RLL) disk and IDE disk/cdrom support
 CONFIG_ST506   		           
   This is the regular, non-SCSI harddisk support. Pretty much everyone
diff -u --recursive --new-file v1.3.49/linux/Documentation/devices.tex linux/Documentation/devices.tex
--- v1.3.49/linux/Documentation/devices.tex	Mon Dec 11 15:41:59 1995
+++ linux/Documentation/devices.tex	Thu Dec 21 12:05:27 1995
@@ -42,7 +42,7 @@
 %
 \title{{\bf Linux Allocated Devices}}
 \author{Maintained by H. Peter Anvin $<$hpa@storm.net$>$}
-\date{Last revised: December 4, 1995}
+\date{Last revised: December 17, 1995}
 \maketitle
 %
 \noindent
@@ -51,11 +51,9 @@
 registry of allocated major device numbers, as well as the recommended
 {\file /dev} directory nodes for these devices.
 
-This list is now included with the Linux kernel sources in \LaTeX\ and
-ASCII form.  This list is also vailable via FTP from ftp.yggdrasil.com
-in the directory {\file /pub/device-list}; filename is {\file
-devices.{\it format\/}} where {\it format\/} is {\file txt} (ASCII),
-{\file tex} (\LaTeX), {\file dvi} (DVI) or {\file ps} (PostScript).
+The latest version of this list is included with the Linux kernel
+sources in \LaTeX\ and ASCII form.  In case of discrepancy, the
+\LaTeX\ version is authoritative.
 
 This document is included by reference into the Linux Filesystem
 Standard (FSSTND).  The FSSTND is available via FTP from
@@ -67,7 +65,9 @@
 have additional information regarding any of the devices listed below,
 or if I have made a mistake, I would greatly appreciate a note.
 
-Allocations marked (68k) apply to Linux/68k only.
+Allocations marked (68k/Amiga) apply to Linux/68k on the Amiga
+platform only.  Allocations marked (68k/Atari) apply to Linux/68k on
+the Atari platform only.
 
 This document is in the public domain.  The author requests, however,
 that semantically altered versions are not distributed without
@@ -90,7 +90,7 @@
 \major{ 7}{}{char }{Virtual console access devices}
 \major{ 8}{}{block}{SCSI disk devices}
 \major{ 9}{}{char }{SCSI tape devices}
-\major{  }{}{block}{Multiple disk devices}
+\major{  }{}{block}{Metadisk (RAID) devices}
 \major{10}{}{char }{Non-serial mice, misc features}
 \major{11}{}{block}{SCSI CD-ROM devices}
 \major{12}{}{char }{QIC-02 tape}
@@ -101,7 +101,7 @@
 \major{  }{}{block}{BIOS harddrive callback support}
 \major{15}{}{char }{Joystick}
 \major{  }{}{block}{Sony CDU-31A/CDU-33A CD-ROM}
-\major{16}{}{char }{Reserved for scanners}
+\major{16}{}{char }{Non-SCSI scanners}
 \major{  }{}{block}{GoldStar CD-ROM}
 \major{17}{}{char }{Chase serial card}
 \major{  }{}{block}{Optics Storage CD-ROM}
@@ -120,12 +120,14 @@
 \major{  }{}{block}{Sony CDU-535 CD-ROM}
 \major{25}{}{char }{Stallion serial card -- alternate devices}
 \major{  }{}{block}{First Matsushita (Panasonic/SoundBlaster) CD-ROM}
-\major{26}{}{block}{Second Matsushita (Panasonic/SoundBlaster) CD-ROM}
+\major{26}{}{char }{Frame grabbers}
+\major{  }{}{block}{Second Matsushita (Panasonic/SoundBlaster) CD-ROM}
 \major{27}{}{char }{QIC-117 tape}
 \major{  }{}{block}{Third Matsushita (Panasonic/SoundBlaster) CD-ROM}
 \major{28}{}{char }{Stallion serial card -- card programming}
+\major{  }{}{char }{Atari SLM ACSI laser printer (68k/Atari)}
 \major{  }{}{block}{Fourth Matsushita (Panasonic/SoundBlaster) CD-ROM}
-\major{  }{}{block}{ACSI disk (68k)}
+\major{  }{}{block}{ACSI disk (68k/Atari)}
 \major{29}{}{char }{Universal frame buffer}
 \major{  }{}{block}{Aztech/Orchid/Okano/Wearnes CD-ROM}
 \major{30}{}{char }{iBCS-2}
@@ -143,11 +145,17 @@
 \major{36}{}{char }{Netlink support}
 \major{  }{}{block}{MCA ESDI hard disk}
 \major{37}{}{char }{IDE tape}
-\major{38}{--41}{}{Unallocated}
+\major{38}{}{char }{Myricom PCI Myrinet board}
+\major{39}{}{char }{Reserved for ncpfs $<$lendecke@namu01.gwdg.de$>$}
+\major{40}{--41}{}{Unallocated}
 \major{42}{}{}{Demo/sample use}
-\major{43}{--223}{}{Unallocated}
+\major{43}{--59}{}{Unallocated}
+\major{60}{--63}{}{Local/experimental use}
+\major{64}{--119}{}{Unallocated}
+\major{120}{--127}{}{Local/experimental use}
+\major{128}{--223}{}{Unallocated}
 \major{224}{--239}{}{SEE NOTE}
-\major{240}{--254}{}{Local use}
+\major{240}{--254}{}{Local/experimental use}
 \major{255}{}{}{Reserved}
 \end{devicelist}
 
@@ -265,17 +273,17 @@
 \\
 \major{}{}{}{For partitions, add to the whole disk device number}
 	\minor{0}{/dev/hd?}{Whole disk}
-	\minor{1}{/dev/hd?1}{First primary partition}
-	\minor{2}{/dev/hd?2}{Second primary partition}
-	\minor{3}{/dev/hd?3}{Third primary partition}
-	\minor{4}{/dev/hd?4}{Fourth primary partition}
-	\minor{5}{/dev/hd?5}{First logical partition}
-	\minor{6}{/dev/hd?6}{Second logical partition}
-	\minor{7}{/dev/hd?7}{Third logical partition}
+	\minor{1}{/dev/hd?1}{First partition}
+	\minor{2}{/dev/hd?2}{Second partition}
 	\minordots
-	\minor{63}{/dev/hd?63}{59th logical partition}
+	\minor{63}{/dev/hd?63}{63rd partition}
 \end{devicelist}
 
+\noindent
+For Linux/i386, partitions 1-4 are the primary partitions, partitions
+5 and up are logical partitions.  Other versions of Linux use
+partitioning schemes appropriate to their respective architectures.
+
 \begin{devicelist}
 \major{ 4}{}{char }{TTY devices}
 	\minor{0}{/dev/console}{Console device}
@@ -344,8 +352,8 @@
 
 \noindent
 Partitions are handled in the same way as for IDE disks (see major
-number 3) except that the limit on logical partitions is 11 rather
-than 59 per disk.
+number 3) except that the partition limit is 15 rather than 63 per
+disk.
 
 \begin{devicelist}
 \major{ 9}{}{char }{SCSI tape devices}
@@ -356,14 +364,14 @@
 	\minor{129}{/dev/nst1}{Second SCSI tape, no rewind-on-close}
 	\minordots
 \\
-\major{  }{}{block}{Multiple disk devices}
-	\minor{0}{/dev/md0}{First device group}
-	\minor{1}{/dev/md1}{Second device group}
+\major{  }{}{block}{Metadisk (RAID) devices}
+	\minor{0}{/dev/md0}{First metadisk group}
+	\minor{1}{/dev/md1}{Second metadisk group}
 	\minordots
 \end{devicelist}
 
 \noindent
-The multiple device driver is used to span a filesystem across multiple
+The metadisk driver is used to span a filesystem across multiple
 physical disks.
 
 \begin{devicelist}
@@ -373,8 +381,8 @@
 	\minor{2}{/dev/inportbm}{Microsoft Inport bus mouse}
 	\minor{3}{/dev/atibm}{ATI XL bus mouse}
 	\minor{4}{/dev/jbm}{J-mouse}
-	\minor{4}{/dev/amigamouse}{Amiga Mouse (68k)}
-	\minor{5}{/dev/atarimouse}{Atari Mouse (68k)}
+	\minor{4}{/dev/amigamouse}{Amiga Mouse (68k/Amiga)}
+	\minor{5}{/dev/atarimouse}{Atari Mouse}
 	\minor{128}{/dev/beep}{Fancy beep device}
 	\minor{129}{/dev/modreq}{Kernel module load request}
 	\minor{130}{/dev/watchdog}{Watchdog timer port}
@@ -472,7 +480,9 @@
 \end{devicelist}
 
 \begin{devicelist}
-\major{16}{}{char }{Reserved for scanners}
+\major{16}{}{char }{Non-SCSI scanners}
+	\minor{0}{/dev/gs4500}{Genius 4500 handheld scanner}
+\\
 \major{  }{}{block}{GoldStar CD-ROM}
 	\minor{0}{/dev/gscd}{GoldStar CD-ROM}
 \end{devicelist}
@@ -635,13 +645,18 @@
 	\minor{2}{/dev/staliomem2}{Third Stallion I/O card memory}
 	\minor{3}{/dev/staliomem3}{Fourth Stallion I/O card memory}
 \\
+\major{  }{}{char }{Atari SLM ACSI laser printer (68k/Atari)}
+	\minor{0}{/dev/slm0}{First SLM laser printer}
+	\minor{1}{/dev/slm1}{Second SLM laser printer}
+	\minordots
+\\
 \major{  }{}{block}{Fourth Matsushita (Panasonic/SoundBlaster) CD-ROM}
 	\minor{0}{/dev/sbpcd12}{Panasonic CD-ROM controller 3 unit 0}
 	\minor{1}{/dev/sbpcd13}{Panasonic CD-ROM controller 3 unit 1}
 	\minor{2}{/dev/sbpcd14}{Panasonic CD-ROM controller 3 unit 2}
 	\minor{3}{/dev/sbpcd15}{Panasonic CD-ROM controller 3 unit 3}
 \\
-\major{  }{}{block}{ACSI disk (68k)}
+\major{  }{}{block}{ACSI disk/CD-ROM (68k/Atari)}
 	\minor{0}{/dev/ada}{First ACSI disk whole disk}
 	\minor{16}{/dev/adb}{Second ACSI disk whole disk}
 	\minor{32}{/dev/adc}{Third ACSI disk whole disk}
@@ -651,16 +666,16 @@
 
 \noindent
 Partitions are handled in the same way as for IDE disks (see major
-number 3) except that the limit on logical partitions is 11 rather
-than 59 per disk.
+number 3) except that the partition limit is 15 rather than 63 per
+disk (same as SCSI.)
 
 \begin{devicelist}
 \major{29}{}{char }{Universal frame buffer}
 	\minor{0}{/dev/fb0current}{First frame buffer}
 	\minor{1}{/dev/fb0autodetect}{}
 	\minordots
-	\minor{16}{/dev/fb1current}{Second frame buffer}
-	\minor{17}{/dev/fb1autodetect}{}
+	\minor{32}{/dev/fb1current}{Second frame buffer}
+	\minor{33}{/dev/fb1autodetect}{}
 	\minordots
 \end{devicelist}
 
@@ -668,7 +683,7 @@
 The universal frame buffer device is currently supported only on
 Linux/68k.  The {\file current} device accesses the frame buffer at
 current resolution; the {\file autodetect} one at bootup (default)
-resolution.  Minor numbers 2--15 within each frame buffer assignment
+resolution.  Minor numbers 2--31 within each frame buffer assignment
 are used for specific device-dependent resolutions.  There appears to
 be no standard naming for these devices.
 
@@ -761,7 +776,7 @@
 \end{devicelist}
 
 \noindent
-In a previous version these files were named {\file /dev/sc1} for
+In a previous version these devices were named {\file /dev/sc1} for
 {\file /dev/scc0}, {\file /dev/sc2} for {\file /dev/scc1}, and so on.
 
 \begin{devicelist}
@@ -821,7 +836,23 @@
 Currently, only one IDE tape drive is supported.
 
 \begin{devicelist}
-\major{38}{--41}{}{Unallocated}
+\major{38}{}{char }{Myricom PCI Myrinet board}
+	\minor{0}{/dev/mlanai0}{First Myrinet board}
+	\minor{1}{/dev/mlanai1}{Second Myrinet board}
+	\minordots
+\end{devicelist}
+
+\noindent
+This device is used for board control, status query and ``user level
+packet I/O''.  The board is also accessible as a regular {\file eth}
+networking device.
+
+\begin{devicelist}
+\major{39}{}{char }{Reserved for ncpfs $<$lendecke@namu01.gwdg.de$>$}
+\end{devicelist}
+
+\begin{devicelist}
+\major{40}{--41}{}{Unallocated}
 \end{devicelist}
 
 \begin{devicelist}
@@ -837,34 +868,40 @@
 (bugs excepted.)
 
 \begin{devicelist}
-\major{43}{--223}{}{Unallocated}
+\major{43}{--59}{}{Unallocated}
 \end{devicelist}
 
 \begin{devicelist}
-\major{224}{--239}{}{SEE NOTE}
+\major{60}{--63}{}{Local/experimental use}
 \end{devicelist}
 
 \noindent
-This range is currently assigned as part of the local/experimental
-range.  However, because of the Linux way of setting a limit on the
-highest device number in the system, currently set at 63 by default, I
-am considering changing the local/experimental use to 60--63,
-120--127, 240--254.  If you are currently using the range 224--239 and
-such a change would pose a problem for you, please contact
-$<$hpa@storm.net$>$ as soon as possible.
+For devices not assigned official numbers, these ranges should be
+used, in order to avoid conflict with future assignments.
 
 \begin{devicelist}
-\major{240}{--254}{}{Local/experimental use}
+\major{64}{--119}{}{Unallocated}
+\end{devicelist}
+
+\begin{devicelist}
+\major{120}{--127}{}{Local/experimental use}
+\end{devicelist}
+
+\begin{devicelist}
+\major{128}{--223}{}{Unallocated}
+\end{devicelist}
+
+\begin{devicelist}
+\major{224}{--239}{}{SEE NOTE}
 \end{devicelist}
 
 \noindent
-For devices not assigned official numbers, this range should be used,
-in order to avoid conflict with future assignments.  Please note that
-{\file MAX\_CHRDEV} and {\file MAX\_BLKDEV} in {\file
-linux/include/linux/major.h} must be set to a value greater than the
-highest used major number.  For a kernel using local/experimental
-devices, it is probably easiest to set both of these equal to 256.
-The memory cost above using the default value of 64 is 3K.
+This range is no longer a local/experimental range, since the feedback
+I received was all in favour of realignment.
+
+\begin{devicelist}
+\major{240}{--254}{}{Local/experimental use}
+\end{devicelist}
 
 \begin{devicelist}
 \major{255}{}{}{Reserved}
diff -u --recursive --new-file v1.3.49/linux/Documentation/devices.txt linux/Documentation/devices.txt
--- v1.3.49/linux/Documentation/devices.txt	Mon Dec 11 15:41:59 1995
+++ linux/Documentation/devices.txt	Thu Dec 21 12:05:35 1995
@@ -2,18 +2,16 @@
 
 	 Maintained by H. Peter Anvin <Peter.Anvin@linux.org>
 
-		    Last revised: December 4, 1995
+		   Last revised: December 17, 1995
 
 This list is the successor to Rick Miller's Linux Device List, which
 he stopped maintaining when he lost network access in 1993.  It is a
 registry of allocated major device numbers, as well as the recommended
 /dev directory nodes for these devices.
 
-This list is now included with the Linux kernel sources in LaTeX and
-ASCII form.  This list is also available via FTP from
-ftp.yggdrasil.com in the directory /pub/device-list; filename is
-devices.<format> where <format> is txt (ASCII), tex (LaTeX), dvi (DVI)
-or ps (PostScript).
+The lastest version of this list is included with the Linux kernel
+sources in LaTeX and ASCII form.  In case of discrepancy, the LaTeX
+version is authoritative.
 
 This document is included by reference into the Linux Filesystem
 Standard (FSSTND).  The FSSTND is available via FTP from
@@ -24,7 +22,9 @@
 have additional information regarding any of the devices listed below,
 or if I have made a mistake, I would greatly appreciate a note.
 
-Allocations marked (68k) apply to Linux/68k only.
+Allocations marked (68k/Amiga) apply to Linux/68k on the Amiga
+platform only.  Allocations marked (68k/Atari) apply to Linux/68k on
+the Atari platform only.
 
 This document is in the public domain.  The author requests, however,
 that semantically altered versions are not distributed without
@@ -124,16 +124,16 @@
 		
 		For partitions, add to the whole disk device number:
 		  0 = /dev/hd?		Whole disk
-		  1 = /dev/hd?1		First primary partition
-		  2 = /dev/hd?2		Second primary partition
-		  3 = /dev/hd?3		Third primary partition
-		  4 = /dev/hd?4		Fourth primary partition
-		  5 = /dev/hd?5		First logical partition
-		  6 = /dev/hd?6		Second logical partition
-		  7 = /dev/hd?7		Third logical partition
+		  1 = /dev/hd?1		First partition
+		  2 = /dev/hd?2		Second partition
 		    ...
-		 63 = /dev/hd?63	59th logical partition
+		 63 = /dev/hd?63	63rd logical partition
 
+		For Linux/i386, partitions 1-4 are the primary
+		partitions, and 5 and above are logical partitions.
+		Other versions of Linux use partitioning schemes
+		appropriate to their respective architectures.
+		
   4 char	TTY devices
     		  0 = /dev/console	Console device
 
@@ -192,7 +192,7 @@
 
 		Partitions are handled in the same way as for IDE
 		disks (see major number 3) except that the limit on
-		logical partitions is 11.
+		partitions is 15.
 
   9 char	SCSI tape devices
     		  0 = /dev/st0		First SCSI tape
@@ -201,12 +201,12 @@
 		128 = /dev/nst0		First SCSI tape, no rewind-on-close
 		129 = /dev/nst1		Second SCSI tape, no rewind-on-close
 		      ...
-    block	Multiple disk devices
-		  0 = /dev/md0		First device group
-		  1 = /dev/md1		Second device group
+    block	Metadisk (RAID) devices
+		  0 = /dev/md0		First metadisk group
+		  1 = /dev/md1		Second metadisk group
 		      ...
 
-		The multiple devices driver is used to span a
+		The metadisk driver is used to span a
 		filesystem across multiple physical disks.
 
  10 char	Non-serial mice, misc features
@@ -215,8 +215,8 @@
 		  2 = /dev/inportbm	Microsoft Inport bus mouse
 		  3 = /dev/atibm	ATI XL bus mouse
 		  4 = /dev/jbm		J-mouse
-		  4 = /dev/amigamouse	Amiga Mouse (68k)
-		  5 = /dev/atarimouse	Atari Mouse (68k)
+		  4 = /dev/amigamouse	Amiga Mouse (68k/Amiga)
+		  5 = /dev/atarimouse	Atari Mouse
 		128 = /dev/beep		Fancy beep device
 		129 = /dev/modreq	Kernel module load request
 		130 = /dev/watchdog	Watchdog timer port
@@ -293,7 +293,8 @@
     block	Sony CDU-31A/CDU-33A CD-ROM
 		  0 = /dev/sonycd	Sony CDU-31a CD-ROM
 
- 16 char	Reserved for scanners
+ 16 char	Non-SCSI scanners
+		  0 = /dev/gs4500	Genius 4500 handheld scanner
     block	GoldStar CD-ROM
 		  0 = /dev/gscd		GoldStar CD-ROM
 
@@ -415,12 +416,16 @@
 		  1 = /dev/staliomem1	Second Stallion card I/O memory
 		  2 = /dev/staliomem2	Third Stallion card I/O memory
 		  3 = /dev/staliomem3	Fourth Stallion card I/O memory
+    char	Atari SLM ACSI laser printer (68k/Atari)
+		  0 = /dev/slm0		First SLM laser printer
+		  1 = /dev/slm1		Second SLM laser printer
+		      ...
     block	Fourth Matsushita (Panasonic/SoundBlaster) CD-ROM
 		  0 = /dev/sbpcd12	Panasonic CD-ROM controller 3 unit 0
 		  1 = /dev/sbpcd13	Panasonic CD-ROM controller 3 unit 1
 		  2 = /dev/sbpcd14	Panasonic CD-ROM controller 3 unit 2
 		  3 = /dev/sbpcd15	Panasonic CD-ROM controller 3 unit 3
-    block	ACSI disk (68k)
+    block	ACSI disk (68k/Atari)
 		  0 = /dev/ada		First ACSI disk whole disk
 		 16 = /dev/adb		Second ACSI disk whole disk
 		 32 = /dev/adc		Third ACSI disk whole disk
@@ -429,14 +434,14 @@
 
 		Partitions are handled in the same way as for IDE
 		disks (see major number 3) except that the limit on
-		logical partitions is 11.
+		partitions is 15, like SCSI.
 
  29 char	Universal frame buffer
 		  0 = /dev/fb0current	First frame buffer
 		  1 = /dev/fb0autodetect
 		      ...
-		 16 = /dev/fb1current	Second frame buffer
-		 17 = /dev/fb1autodetect
+		 32 = /dev/fb1current	Second frame buffer
+		 33 = /dev/fb1autodetect
 		      ...
     block	Aztech/Orchid/Okano/Wearnes CD-ROM
 		  0 = /dev/aztcd	Aztech CD-ROM
@@ -445,7 +450,7 @@
 		supported on Linux/68k.  The "current" device accesses
 		the fame buffer at current resolution; the
 		"autodetect" one at bootup (default) resolution.
-		Minor numbers 2-15 within each frame buffer assignment
+		Minor numbers 2-31 within each frame buffer assignment
 		are used for specific device-dependent resolutions.
 		There appears to be no standard naming for these devices.
 
@@ -508,11 +513,16 @@
 		interface (see major number 3).
 
  34 char	Z8530 HDLC driver
-		  0 = /dev/sc1		First Z8530, first port
-		  1 = /dev/sc2		First Z8530, second port
-		  2 = /dev/sc3		Second Z8530, first port
-		  3 = /dev/sc4		Second Z8530, second port
+		  0 = /dev/scc0		First Z8530, first port
+		  1 = /dev/scc1		First Z8530, second port
+		  2 = /dev/scc2		Second Z8530, first port
+		  3 = /dev/scc3		Second Z8530, second port
 		      ...
+
+		In a previous version these devices were named
+		/dev/sc1 for /dev/scc0, /dev/sc2 for /dev/scc1, and so
+		on.
+
     block	Fourth IDE hard disk/CD-ROM interface
     		  0 = /dev/hdg		Master: whole disk (or CD-ROM)
 		 64 = /dev/hdh		Slave: whole disk (or CD-ROM)
@@ -556,7 +566,18 @@
 
 		Currently, only one IDE tape drive is supported.
 
- 38-41		UNALLOCATED
+ 38 char	Myricom PCI Myrinet board
+		  0 = /dev/mlanai0	First Myrinet board
+		  1 = /dev/mlanai1	Second Myrinet board
+		      ...
+
+		This device is used for status query, board control
+		and "user level packet I/O."  This board is also
+		accessible as a standard networking "eth" device.
+
+ 39		Reserved for ncpfs <lendecke@namu01.gwdg.de>
+
+ 40-41		UNALLOCATED
 
  42		Demo/sample use
 
@@ -568,29 +589,25 @@
 		removal of a driver with this number should not cause
 		ill effects to the system (bugs excepted.)
 
- 43-223		UNALLOCATED
+ 43-59		UNALLOCATED
+
+ 60-63		LOCAL/EXPERIMENTAL USE
+		Allocated for local/experimental use.  For devices not
+		assigned official numbers, these ranges should be
+		used, in order to avoid conflicting with future assignments.
+
+ 64-119		UNALLOCATED
+
+120-127		LOCAL/EXPERIMENTAL USE
+
+128-223		UNALLOCATED
 
 224-239		SEE NOTE
+		This range is no longer allocated to
+		local/experimental use, since the feedback I received
+		was all in favour of realignment.
 
-		This range is currently assigned as part of the
-		local/experimental range.  However, because of the
-		Linux way of setting a limit on the highest device
-		number in the system, currently set at 63 by default,
-		I am considering changing the local/experimental use
-		to 60-63, 120-127, 240-254.  If you are currently
-		using the range 224-239 and such a change would pose a
-		problem for you, please contact <hpa@storm.net> as
-		soon as possible.
-
-240-254		LOCAL USE
-		Allocated for local/experimental use
-
-		Please note that MAX_CHRDEV and MAX_BLKDEV in
-		linux/include/linux/major.h must be set to a value
-		greater than the highest used major number.  For a
-		kernel using local/experimental devices, it is
-		probably easiest to set both of these equal to 256.  The
-		memory cost above using the default value of 64 is 3K.
+240-254		LOCAL/EXPERIMENTAL USE
 
 255		RESERVED
 
diff -u --recursive --new-file v1.3.49/linux/Makefile linux/Makefile
--- v1.3.49/linux/Makefile	Thu Dec 21 08:53:30 1995
+++ linux/Makefile	Fri Dec 22 08:51:08 1995
@@ -1,6 +1,6 @@
 VERSION = 1
 PATCHLEVEL = 3
-SUBLEVEL = 49
+SUBLEVEL = 50
 
 ARCH = i386
 
@@ -249,7 +249,7 @@
 endif
 
 modules: include/linux/version.h
-	@set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i CFLAGS="$(CFLAGS) $(MODFLAGS)" modules; done
+	@set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i CFLAGS="-dc $(CFLAGS) $(MODFLAGS)" modules; done
 
 modules_install:
 	@( \
@@ -261,10 +261,11 @@
 		echo Installing modules under $$MODLIB/$$2; \
 	}; \
 	\
-	if [ -f NET_MODULES  ]; then inst_mod NET_MODULES  net;  fi; \
-	if [ -f IPV4_MODULES ]; then inst_mod IPV4_MODULES ipv4; fi; \
-	if [ -f SCSI_MODULES ]; then inst_mod SCSI_MODULES scsi; fi; \
-	if [ -f FS_MODULES   ]; then inst_mod FS_MODULES   fs;   fi; \
+	if [ -f BLOCK_MODULES ]; then inst_mod BLOCK_MODULES block; fi; \
+	if [ -f NET_MODULES   ]; then inst_mod NET_MODULES   net;   fi; \
+	if [ -f IPV4_MODULES  ]; then inst_mod IPV4_MODULES  ipv4;  fi; \
+	if [ -f SCSI_MODULES  ]; then inst_mod SCSI_MODULES  scsi;  fi; \
+	if [ -f FS_MODULES    ]; then inst_mod FS_MODULES    fs;    fi; \
 	\
 	ls *.o > .allmods; \
 	echo $$MODULES | tr ' ' '\n' | sort | comm -23 .allmods - > .misc; \
diff -u --recursive --new-file v1.3.49/linux/arch/alpha/Makefile linux/arch/alpha/Makefile
--- v1.3.49/linux/arch/alpha/Makefile	Thu Nov  9 11:23:46 1995
+++ linux/arch/alpha/Makefile	Fri Dec 22 08:22:04 1995
@@ -24,9 +24,11 @@
 
 HEAD := arch/alpha/kernel/head.o
 
-SUBDIRS := $(SUBDIRS) arch/alpha/kernel arch/alpha/mm arch/alpha/lib
+SUBDIRS := $(SUBDIRS) arch/alpha/kernel arch/alpha/mm arch/alpha/lib \
+	arch/alpha/math-emu
 ARCHIVES := arch/alpha/kernel/kernel.o arch/alpha/mm/mm.o $(ARCHIVES)
-LIBS := $(TOPDIR)/arch/alpha/lib/lib.a $(LIBS) $(TOPDIR)/arch/alpha/lib/lib.a
+LIBS := $(TOPDIR)/arch/alpha/math-emu/math-emu.a \
+	$(TOPDIR)/arch/alpha/lib/lib.a $(LIBS) $(TOPDIR)/arch/alpha/lib/lib.a
 
 MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
 
diff -u --recursive --new-file v1.3.49/linux/arch/alpha/config.in linux/arch/alpha/config.in
--- v1.3.49/linux/arch/alpha/config.in	Thu Nov  9 11:23:46 1995
+++ linux/arch/alpha/config.in	Fri Dec 22 08:22:04 1995
@@ -7,6 +7,7 @@
 # clear all implied options (don't want default values for those):
 unset CONFIG_CROSSCOMPILE CONFIG_NATIVE
 unset CONFIG_PCI CONFIG_ALPHA_LCA CONFIG_ALPHA_APECS
+unset CONFIG_ALPHA_NEED_ROUNDING_EMULATION
 
 mainmenu_option next_comment
 comment 'General setup'
@@ -24,7 +25,6 @@
 	 Cabriolet	CONFIG_ALPHA_CABRIOLET		\
 	 EB66		CONFIG_ALPHA_EB66		\
 	 EB66+		CONFIG_ALPHA_EB66P		\
-	 EB64		CONFIG_ALPHA_EB64		\
 	 EB64+		CONFIG_ALPHA_EB64P" Cabriolet
 if [ "$CONFIG_ALPHA_NONAME" = "y" -o "$CONFIG_ALPHA_EB66" = "y" \
 	-o "$CONFIG_ALPHA_EB66P" = "y" ]
@@ -33,13 +33,14 @@
 	define_bool CONFIG_ALPHA_LCA y
 fi
 if [ "$CONFIG_ALPHA_CABRIOLET" = "y" -o "$CONFIG_ALPHA_AVANTI" = "y" \
-	-o "$CONFIG_ALPHA_EB64" = "y" -o "$CONFIG_ALPHA_EB64P" = "y" ]
+	-o "$CONFIG_ALPHA_EB64P" = "y" ]
 then
 	bool 'Using SRM as bootloader' CONFIG_ALPHA_SRM
 	define_bool CONFIG_PCI y
 	define_bool CONFIG_ALPHA_APECS y
 fi
-
+# This needs to be defined for all EV4 and EV45 CPUs:
+define_bool CONFIG_ALPHA_NEED_ROUNDING_EMULATION y
 bool 'Echo console messages on /dev/ttyS1' CONFIG_SERIAL_ECHO
 if [ "$CONFIG_PCI" = "y" ]; then
   bool 'TGA Console Support' CONFIG_TGA_CONSOLE
diff -u --recursive --new-file v1.3.49/linux/arch/alpha/defconfig linux/arch/alpha/defconfig
--- v1.3.49/linux/arch/alpha/defconfig	Sun Dec 17 11:43:08 1995
+++ linux/arch/alpha/defconfig	Fri Dec 22 08:22:04 1995
@@ -12,7 +12,6 @@
 CONFIG_ALPHA_CABRIOLET=y
 # CONFIG_ALPHA_EB66 is not set
 # CONFIG_ALPHA_EB66P is not set
-# CONFIG_ALPHA_EB64 is not set
 # CONFIG_ALPHA_EB64P is not set
 # CONFIG_ALPHA_SRM is not set
 CONFIG_PCI=y
diff -u --recursive --new-file v1.3.49/linux/arch/alpha/kernel/Makefile linux/arch/alpha/kernel/Makefile
--- v1.3.49/linux/arch/alpha/kernel/Makefile	Wed Sep 27 15:59:56 1995
+++ linux/arch/alpha/kernel/Makefile	Fri Dec 22 08:22:04 1995
@@ -24,7 +24,6 @@
 
 kernel.o: $(OBJS)
 	$(LD) -r -o kernel.o $(OBJS)
-	sync
 
 dep:
 	$(CPP) -M *.c > .depend
diff -u --recursive --new-file v1.3.49/linux/arch/alpha/kernel/bios32.c linux/arch/alpha/kernel/bios32.c
--- v1.3.49/linux/arch/alpha/kernel/bios32.c	Sun Dec 17 11:43:09 1995
+++ linux/arch/alpha/kernel/bios32.c	Fri Dec 22 08:22:04 1995
@@ -581,7 +581,7 @@
 		{ 0,  0,  2,  1,  0}, /* idsel 11 (slot furthest from ISA) KN25_PCI_SLOT0 */
 		{ 1,  1,  0,  2,  1}, /* idsel 12 (middle slot) KN25_PCI_SLOT1 */
 #ifdef CONFIG_ALPHA_AVANTI
-		{ 1,  1, -1, -1, -1}, /* idsel 13 KN25_PCI_SLOT2 ??? */
+		{ 1,  1, -1, -1, -1}, /* idsel 13 KN25_PCI_SLOT2 */
 #endif /* CONFIG_ALPHA_AVANTI */
 	};
 	/*
@@ -595,7 +595,8 @@
 	 * example, sound boards seem to like using IRQ 9.
 	 */
 	const unsigned int route_tab = 0x0b0a090f;
-	unsigned char pin, level_bits;
+	unsigned int level_bits;
+	unsigned char pin;
 	int pirq;
 
 	pcibios_write_config_dword(0, PCI_DEVFN(7, 0), 0x60, route_tab);
@@ -634,8 +635,7 @@
 		dev->irq = (route_tab >> (8 * pirq)) & 0xff;
 
 		/* must set the PCI IRQs to level triggered */
-		/* assume they are all >= 8 */
-		level_bits |= (1 << (dev->irq - 8));
+		level_bits |= (1 << dev->irq);
 
 #if PCI_MODIFY
 		/* tell the device: */
@@ -645,7 +645,7 @@
 	}
 	/* now, set any level-triggered IRQs */
 	if (level_bits)
-		outb(level_bits, 0x4d1);
+		outw(level_bits, 0x4d0);
 
 
 #if PCI_MODIFY
diff -u --recursive --new-file v1.3.49/linux/arch/alpha/kernel/entry.S linux/arch/alpha/kernel/entry.S
--- v1.3.49/linux/arch/alpha/kernel/entry.S	Mon Dec 11 15:41:59 1995
+++ linux/arch/alpha/kernel/entry.S	Fri Dec 22 08:23:04 1995
@@ -277,9 +277,11 @@
 	stt $f25,264($30)
 	stt $f26,272($30)
 	stt $f27,280($30)
+	mf_fpcr $f0		# get fpcr
 	stt $f28,288($30)
 	stt $f29,296($30)
 	stt $f30,304($30)
+	stt $f0,312($30)	# save fpcr in slot of $f31
 	ret $31,($1),1
 .end do_switch_stack
 
@@ -294,10 +296,12 @@
 	ldq $14,40($30)
 	ldq $15,48($30)
 	ldq $26,56($30)
+	ldt $f30,312($30)	# get saved fpcr
 	ldt $f0,64($30)
 	ldt $f1,72($30)
 	ldt $f2,80($30)
 	ldt $f3,88($30)
+	mt_fpcr $f30		# install saved fpcr
 	ldt $f4,96($30)
 	ldt $f5,104($30)
 	ldt $f6,112($30)
@@ -641,12 +645,12 @@
 	.quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
 	.quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
 	.quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
-	.quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
+	.quad do_entSys, do_entSys, do_entSys, do_entSys, sys_getsid
 	.quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
 	.quad do_entSys, do_entSys, do_entSys, do_entSys, osf_proplist_syscall
 	.quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
 /*250*/	.quad do_entSys, osf_usleep_thread, do_entSys, do_entSys, do_entSys
-	.quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
+	.quad do_entSys, osf_getsysinfo, osf_setsysinfo, do_entSys, do_entSys
 	.quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
 	.quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
 	.quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
@@ -657,7 +661,6 @@
 	.quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
 /* linux-specific system calls start at 300 */
 /*300*/	.quad sys_bdflush, sys_sethae, sys_mount, sys_adjtimex, sys_swapoff
-	.quad sys_getdents, sys_create_module, sys_init_module, sys_delete_module, sys_get_kernel_syms
-	.quad sys_syslog, sys_reboot, sys_clone, sys_uselib, do_entSys
-	.quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
-
+	.quad sys_getdents, alpha_create_module, sys_init_module, sys_delete_module, sys_get_kernel_syms
+	.quad sys_syslog, sys_reboot, sys_clone, sys_uselib, sys_mlock
+	.quad sys_munlock, sys_mlockall, sys_munlockall, do_entSys, do_entSys
diff -u --recursive --new-file v1.3.49/linux/arch/alpha/kernel/head.S linux/arch/alpha/kernel/head.S
--- v1.3.49/linux/arch/alpha/kernel/head.S	Mon Nov 13 12:36:42 1995
+++ linux/arch/alpha/kernel/head.S	Fri Dec 22 08:22:04 1995
@@ -33,7 +33,7 @@
 	.ent	wrent
 wrent:
 	.long PAL_wrent
-	ret ($26)
+	ret	($26)
 	.end wrent
 
 	.align 3
@@ -41,7 +41,7 @@
 	.ent	wrkgp
 wrkgp:
 	.long PAL_wrkgp
-	ret ($26)
+	ret	($26)
 	.end wrkgp
 
 	.align 3
@@ -49,7 +49,7 @@
 	.ent	wrusp
 wrusp:
 	.long PAL_wrusp
-	ret ($26)
+	ret	($26)
 	.end wrusp
 
 	.align 3
@@ -57,7 +57,7 @@
 	.ent	rdusp
 rdusp:
 	.long PAL_rdusp
-	ret ($26)
+	ret	($26)
 	.end rdusp
 
 	.align 3
@@ -65,7 +65,7 @@
 	.ent	tbi
 tbi:
 	.long PAL_tbi
-	ret ($26)
+	ret	($26)
 	.end tbi
 
 	.align 3
@@ -73,7 +73,7 @@
 	.ent	imb
 imb:
 	.long PAL_imb
-	ret ($26)
+	ret	($26)
 	.end imb
 
 	.align 3
@@ -81,7 +81,7 @@
 	.ent	rdmces
 rdmces:
 	call_pal PAL_rdmces
-	ret ($26)
+	ret	($26)
 	.end rdmces
 
 	.align 3
@@ -89,5 +89,39 @@
 	.ent	wrmces
 wrmces:
 	call_pal PAL_wrmces
-	ret ($26)
+	ret	($26)
 	.end wrmces
+
+	#
+	# The following two functions don't need trapb/excb instructions
+	# around the mf_fpcr/mt_fpcr instructions because (a) the kernel
+	# never generates arithmetic faults and (b) call_pal instructions
+	# are implied trap barriers.
+	#
+	.align 3
+	.globl	rdfpcr
+	.ent	rdfpcr
+rdfpcr:
+	lda	$30,-0x10($30)
+	stt	$f0,0($30)
+	mf_fpcr	$f0
+	stt	$f0,8($30)
+	ldt	$f0,0($30)
+	ldq	$0,8($30)
+	lda	$30,0x10($30)
+	ret	($26)
+	.end	rdfpcr
+
+	.align 3
+	.globl	wrfpcr
+	.ent	wrfpcr
+wrfpcr:
+	lda	$30,-0x10($30)
+	stt	$f0,0($30)
+	stq	$16,8($30)
+	ldt	$f0,8($30)
+	mt_fpcr	$f0
+	ldt	$f0,0($30)
+	lda	$30,0x10($30)
+	ret	($26)
+	.end	wrfpcr
diff -u --recursive --new-file v1.3.49/linux/arch/alpha/kernel/irq.c linux/arch/alpha/kernel/irq.c
--- v1.3.49/linux/arch/alpha/kernel/irq.c	Fri Nov 17 08:42:24 1995
+++ linux/arch/alpha/kernel/irq.c	Fri Dec 22 08:22:04 1995
@@ -356,6 +356,14 @@
 #	define IACK_SC	APECS_IACK_SC
 #elif defined(CONFIG_ALPHA_LCA)
 #	define IACK_SC	LCA_IACK_SC
+#else
+    	/*
+	 * This is bogus but necessary to get it to compile
+	 * on all platforms.  If you try to use this on any
+	 * other than the intended platforms, you'll notice
+	 * real fast...
+	 */
+#	define IACK_SC	1L
 #endif
 	int j;
 
@@ -568,7 +576,7 @@
 	irqmask |= ((((unsigned long)cache_26)<<16) |
 		    (((unsigned long)cache_27)<<24));
 #endif
-	irqs &= irqmask;
+	irqs &= irqmask & ~1;	/* always mask out irq 0---it's the unused timer */
 	if (!irqs)
 		return 0;
 	i = ffz(~irqs);
diff -u --recursive --new-file v1.3.49/linux/arch/alpha/kernel/lca.c linux/arch/alpha/kernel/lca.c
--- v1.3.49/linux/arch/alpha/kernel/lca.c	Sun Oct 29 11:38:48 1995
+++ linux/arch/alpha/kernel/lca.c	Fri Dec 22 08:22:04 1995
@@ -299,6 +299,13 @@
 	*(vulp)LCA_IOC_W_BASE0 = 1UL<<33 | LCA_DMA_WIN_BASE;
 	*(vulp)LCA_IOC_W_MASK0 = LCA_DMA_WIN_SIZE - 1;
 	*(vulp)LCA_IOC_T_BASE0 = 0;
+
+	/*
+	 * Disable PCI parity for now.  The NCR53c810 chip has
+	 * troubles meeting the PCI spec which results in
+	 * data parity errors.
+	 */
+	*(vulp)LCA_IOC_PAR_DIS = 1UL<<5;
 	return mem_start;
 }
 
@@ -310,10 +317,71 @@
  * could be moved into lca.h but I don't see much reason why anybody
  * else would want to use them.
  */
-#define ESR_EAV	(1UL<< 0)	/* error address valid */
-#define ESR_CEE	(1UL<< 1)	/* correctable error */
-#define ESR_UEE (1UL<< 2)	/* uncorrectable error */
-#define ESR_NXM (1UL<<12)	/* non-existent memory */
+#define ESR_EAV		(1UL<< 0)	/* error address valid */
+#define ESR_CEE		(1UL<< 1)	/* correctable error */
+#define ESR_UEE		(1UL<< 2)	/* uncorrectable error */
+#define ESR_WRE		(1UL<< 3)	/* write-error */
+#define ESR_SOR		(1UL<< 4)	/* error source */
+#define ESR_CTE		(1UL<< 7)	/* cache-tag error */
+#define ESR_MSE		(1UL<< 9)	/* multiple soft errors */
+#define ESR_MHE		(1UL<<10)	/* multiple hard errors */
+#define ESR_NXM		(1UL<<12)	/* non-existent memory */
+
+#define IOC_ERR		(  1<<4)	/* ioc logs an error */
+#define IOC_CMD_SHIFT	0
+#define IOC_CMD		(0xf<<IOC_CMD_SHIFT)
+#define IOC_CODE_SHIFT	8
+#define IOC_CODE	(0xf<<IOC_CODE_SHIFT)
+#define IOC_LOST	(  1<<5)
+#define IOC_P_NBR	((__u32) ~((1<<13) - 1))
+
+
+void mem_error (unsigned long esr, unsigned long ear)
+{
+    printk("    %s %s error to %s occurred at address %x",
+	   (esr & ESR_CEE) ? "Correctable" : ((esr & ESR_UEE) ? "Uncorrectable" : "A"),
+	   (esr & ESR_WRE) ? "write" : "read",
+	   (esr & ESR_SOR) ? "b-cache" : "memory",
+	   (unsigned) (ear & 0x1ffffff8));
+    if (esr & ESR_CTE) {
+	printk("    A b-cache tag parity error was detected.\n");
+    }
+    if (esr & ESR_MSE) {
+	printk("    Several other correctable errors occurred.\n");
+    }
+    if (esr & ESR_MHE) {
+	printk("    Several other uncorrectable errors occurred.\n");
+    }
+    if (esr & ESR_NXM) {
+	printk("    Attempted to access non-existent memory.\n");
+    }
+}
+
+
+void ioc_error (__u32 stat0, __u32 stat1)
+{
+    const char *pci_cmd[] = {
+	"Interrupt Acknowledge", "Special", "I/O Read", "I/O Write",
+	"Rsvd 1", "Rsvd 2", "Memory Read", "Memory Write", "Rsvd3", "Rsvd4",
+	"Configuration Read", "Configuration Write", "Memory Read Multiple",
+	"Dual Address", "Memory Read Line", "Memory Write and Invalidate"
+    };
+    const char *err_name[] = {
+	"exceeded retry limit", "no device", "bad data parity", "target abort",
+	"bad address parity", "page table read error", "invalid page", "data error"
+    };
+    unsigned code = (stat0 & IOC_CODE) >> IOC_CODE_SHIFT;
+    unsigned cmd  = (stat0 & IOC_CMD)  >> IOC_CMD_SHIFT;
+
+    printk("    %s initiated PCI %s cycle to address %x failed due to %s.\n",
+	   code > 3 ? "PCI" : "CPU", pci_cmd[cmd], stat1, err_name[code]);
+    if (code == 5 || code == 6) {
+	printk("    (Error occurred at PCI memory address %x.)\n", (stat0 & ~IOC_P_NBR));
+    }
+    if (stat0 & IOC_LOST) {
+	printk("    Other PCI errors occurred simultaneously.\n");
+    }
+}
 
 
 void lca_machine_check (unsigned long vector, unsigned long la, struct pt_regs *regs)
@@ -322,14 +390,16 @@
 	union el_lca el;
 	char buf[128];
 
-	printk("lca: machine check (la=0x%lx)\n", la);
+	printk("lca: machine check (la=0x%lx,pc=0x%lx)\n", la, regs->pc);
 	el.c = (struct el_common *) la;
 	/*
 	 * The first quadword after the common header always seems to
 	 * be the machine check reason---don't know why this isn't
-	 * part of the common header instead.
+	 * part of the common header instead.  In the case of a long
+	 * logout frame, the upper 32 bits is the machine check
+	 * revision level, which we ignore for now.
 	 */
-	switch (el.s->reason) {
+	switch (el.s->reason & 0xffffffff) {
 	      case MCHK_K_TPERR:	reason = "tag parity error"; break;
 	      case MCHK_K_TCPERR:	reason = "tag something parity error"; break;
 	      case MCHK_K_HERR:		reason = "access to non-existent memory"; break;
@@ -345,7 +415,8 @@
 	      case MCHK_K_DCSR:		reason = "MCHK_K_DCSR"; break;
 	      case MCHK_K_UNKNOWN:
 	      default:
-		sprintf(buf, "reason for machine-check unknown (0x%lx)", el.s->reason);
+		sprintf(buf, "reason for machine-check unknown (0x%lx)",
+			el.s->reason & 0xffffffff);
 		reason = buf;
 		break;
 	}
@@ -354,11 +425,14 @@
 
 	switch (el.c->size) {
 	      case sizeof(struct el_lca_mcheck_short):
-		printk("  Reason: %s (short frame%s):\n",
-		       reason, el.c->retry ? ", retryable" : "");
-		printk("    esr: %lx  ear: %lx\n", el.s->esr, el.s->ear);
-		printk("    dc_stat: %lx  ioc_stat0: %lx  ioc_stat1: %lx\n",
-		       el.s->dc_stat, el.s->ioc_stat0, el.s->ioc_stat1);
+		printk("  Reason: %s (short frame%s, dc_stat=%lx):\n",
+		       reason, el.c->retry ? ", retryable" : "", el.s->dc_stat);
+		if (el.s->esr & ESR_EAV) {
+		    mem_error(el.s->esr, el.s->ear);
+		}
+		if (el.s->ioc_stat0 & IOC_ERR) {
+		    ioc_error(el.s->ioc_stat0, el.s->ioc_stat1);
+		}
 		break;
 
 	      case sizeof(struct el_lca_mcheck_long):
@@ -366,8 +440,13 @@
 		       reason, el.c->retry ? ", retryable" : "");
 		printk("    reason: %lx  exc_addr: %lx  dc_stat: %lx\n", 
 		       el.l->pt[0], el.l->exc_addr, el.l->dc_stat);
-		printk("    esr: %lx  ear: %lx  car: %lx\n", el.l->esr, el.l->ear, el.l->car);
-		printk("    ioc_stat0: %lx  ioc_stat1: %lx\n", el.l->ioc_stat0, el.l->ioc_stat1);
+		printk("    car: %lx\n", el.l->car);
+		if (el.l->esr & ESR_EAV) {
+		    mem_error(el.l->esr, el.l->ear);
+		}
+		if (el.l->ioc_stat0 & IOC_ERR) {
+		    ioc_error(el.l->ioc_stat0, el.l->ioc_stat1);
+		}
 		break;
 
 	      default:
diff -u --recursive --new-file v1.3.49/linux/arch/alpha/kernel/osf_sys.c linux/arch/alpha/kernel/osf_sys.c
--- v1.3.49/linux/arch/alpha/kernel/osf_sys.c	Mon Dec 11 15:41:59 1995
+++ linux/arch/alpha/kernel/osf_sys.c	Fri Dec 22 08:22:05 1995
@@ -28,9 +28,10 @@
 #include <linux/mman.h>
 #include <linux/shm.h>
 
+#include <asm/fpu.h>
+#include <asm/io.h>
 #include <asm/segment.h>
 #include <asm/system.h>
-#include <asm/io.h>
 
 extern int do_mount(kdev_t, const char *, const char *, char *, int, void *);
 extern int do_pipe(int *);
@@ -618,4 +619,92 @@
 	      default:
 		return -EOPNOTSUPP;
 	}
+}
+
+/*
+ * The Linux kernel isn't good at returning values that look
+ * like negative longs (they are mistaken as error values).
+ * Until that is fixed, we need this little workaround for
+ * create_module() because it's one of the few system calls
+ * that return kernel addresses (which are negative).
+ */
+asmlinkage unsigned long
+alpha_create_module (char * module_name, unsigned long size,
+		     int a3, int a4, int a5, int a6,
+		     struct pt_regs regs)
+{
+	asmlinkage unsigned long sys_create_module (char *, unsigned long);
+	long retval;
+
+	retval = sys_create_module(module_name, size);
+	/*
+	 * we get either a module address or an error number,
+	 * and we know the error number is a small negative
+	 * number, while the address is always negative but
+	 * much larger.
+	 */
+	if (retval + 1000 > 0)
+	  return retval;
+
+	/* tell entry.S:syscall_error that this is NOT an error: */
+	regs.r0 = 0;
+	return retval;
+}
+
+
+asmlinkage unsigned long
+osf_getsysinfo (unsigned long op, void * buffer, unsigned long nbytes,
+		int * start, void *arg)
+{
+    extern unsigned long rdfpcr (void);
+    unsigned long fpcw;
+
+    switch (op) {
+      case 45:	/* GSI_IEEE_FP_CONTROL */
+	  /* build and return current fp control word: */
+	  fpcw = current->tss.flags & IEEE_TRAP_ENABLE_MASK;
+	  fpcw |= ((rdfpcr() >> 52) << 17) & IEEE_STATUS_MASK;
+	  put_user(fpcw, (unsigned long *) buffer);
+	  return 0;
+
+      case 46:	/* GSI_IEEE_STATE_AT_SIGNAL */
+	  /*
+	   * Not sure anybody will ever use this weird stuff.  These
+	   * ops can be used (under OSF/1) to set the fpcr that should
+	   * be used when a signal handler starts executing.
+	   */
+	  break;
+
+      default:
+	  break;
+    }
+    return -EOPNOTSUPP;
+}
+
+
+asmlinkage unsigned long
+osf_setsysinfo (unsigned long op, void * buffer, unsigned long nbytes,
+		int * start, void *arg)
+{
+    unsigned long fpcw;
+
+    switch (op) {
+      case 14:	/* SSI_IEEE_FP_CONTROL */
+	  /* update trap enable bits: */
+	  fpcw = get_user((unsigned long *) buffer);
+	  current->tss.flags &= ~IEEE_TRAP_ENABLE_MASK;
+	  current->tss.flags |= (fpcw & IEEE_TRAP_ENABLE_MASK);
+	  return 0;
+
+      case 15:	/* SSI_IEEE_STATE_AT_SIGNAL */
+      case 16:	/* SSI_IEEE_IGNORE_STATE_AT_SIGNAL */
+	  /*
+	   * Not sure anybody will ever use this weird stuff.  These
+	   * ops can be used (under OSF/1) to set the fpcr that should
+	   * be used when a signal handler starts executing.
+	   */
+      default:
+	  break;
+    }
+    return -EOPNOTSUPP;
 }
diff -u --recursive --new-file v1.3.49/linux/arch/alpha/kernel/setup.c linux/arch/alpha/kernel/setup.c
--- v1.3.49/linux/arch/alpha/kernel/setup.c	Sun Dec 17 11:43:09 1995
+++ linux/arch/alpha/kernel/setup.c	Fri Dec 22 08:22:05 1995
@@ -50,6 +50,7 @@
 #define COMMAND_LINE_SIZE	256
 
 static char command_line[COMMAND_LINE_SIZE] = { 0, };
+       char saved_command_line[COMMAND_LINE_SIZE];
 
 /*
  * The format of "screen_info" is strange, and due to early
@@ -68,6 +69,30 @@
 	16			/* orig-video-points */
 };
 
+/*
+ * Initialize Programmable Interval Timers with standard values.  Some
+ * drivers depend on them being initialized (e.g., joystick driver).
+ */
+static void init_pit (void)
+{
+#if 0
+    /*
+     * Leave refresh timer alone---nobody should depend on
+     * a particular value anyway.
+     */
+    outb(0x54, 0x43);	/* counter 1: refresh timer */
+    outb(0x18, 0x41);
+#endif
+
+    outb(0x36, 0x43);	/* counter 0: system timer */
+    outb(0x00, 0x40);
+    outb(0x00, 0x40);
+
+    outb(0xb6, 0x43);	/* counter 2: speaker */
+    outb(0x31, 0x42);
+    outb(0x13, 0x42);
+}
+
 static unsigned long find_end_memory(void)
 {
 	int i;
@@ -94,6 +119,8 @@
 {
 	extern int _end;
 
+	init_pit();
+
 	hwrpb = (struct hwrpb_struct*)(IDENT_ADDR + INIT_HWRPB->phys_addr);
 
 	set_hae(hae.cache);	/* sync HAE register w/hae_cache */
@@ -102,6 +129,7 @@
 	ROOT_DEV = to_kdev_t(0x0802);		/* sda2 */
 	command_line[COMMAND_LINE_SIZE - 1] = '\0';
 	strcpy(command_line, COMMAND_LINE);
+	strcpy(saved_command_line, COMMAND_LINE);
 
 	*cmdline_p = command_line;
 	*memory_start_p = (unsigned long) &_end;
diff -u --recursive --new-file v1.3.49/linux/arch/alpha/kernel/traps.c linux/arch/alpha/kernel/traps.c
--- v1.3.49/linux/arch/alpha/kernel/traps.c	Tue Nov 21 13:22:05 1995
+++ linux/arch/alpha/kernel/traps.c	Fri Dec 22 21:05:52 1995
@@ -11,9 +11,11 @@
 #include <linux/mm.h>
 #include <linux/sched.h>
 #include <linux/tty.h>
+#include <linux/config.h>
 
-#include <asm/unaligned.h>
 #include <asm/gentrap.h>
+#include <asm/segment.h>
+#include <asm/unaligned.h>
 
 void die_if_kernel(char * str, struct pt_regs * regs, long err)
 {
@@ -47,17 +49,30 @@
 }
 
 asmlinkage void do_entArith(unsigned long summary, unsigned long write_mask,
-	unsigned long a2, unsigned long a3, unsigned long a4, unsigned long a5,
-	struct pt_regs regs)
+			    unsigned long a2, unsigned long a3,
+			    unsigned long a4, unsigned long a5,
+			    struct pt_regs regs)
 {
-	printk("Arithmetic trap: %02lx %016lx\n", summary, write_mask);
+	if ((summary & 1)) {
+		extern long alpha_fp_emul_imprecise (struct pt_regs * regs,
+						     unsigned long write_mask);
+		/*
+		 * Software-completion summary bit is set, so try to
+		 * emulate the instruction.
+		 */
+		if (alpha_fp_emul_imprecise(&regs, write_mask)) {
+			return;		/* emulation was successful */
+		}
+	}
+	printk("Arithmetic trap at %016lx: %02lx %016lx\n",
+	       regs.pc, summary, write_mask);
 	die_if_kernel("Arithmetic fault", &regs, 0);
 	send_sig(SIGFPE, current, 1);
 }
 
 asmlinkage void do_entIF(unsigned long type, unsigned long a1, unsigned long a2,
-	unsigned long a3, unsigned long a4, unsigned long a5,
-	struct pt_regs regs)
+			 unsigned long a3, unsigned long a4, unsigned long a5,
+			 struct pt_regs regs)
 {
 	extern int ptrace_cancel_bpt (struct task_struct *who);
 
@@ -110,7 +125,28 @@
 
 	      case 1: /* bugcheck */
 	      case 3: /* FEN fault */
+		send_sig(SIGILL, current, 1);
+		break;
+
 	      case 4: /* opDEC */
+#ifdef CONFIG_ALPHA_NEED_ROUNDING_EMULATION
+		{
+			extern long alpha_fp_emul (unsigned long pc);
+			unsigned int opcode;
+
+			/* get opcode of faulting instruction: */
+			opcode = get_user((__u32*)(regs.pc - 4)) >> 26;
+			if (opcode == 0x16) {
+				/*
+				 * It's a FLTI instruction, emulate it
+				 * (we don't do no stinkin' VAX fp...)
+				 */
+				if (!alpha_fp_emul(regs.pc - 4))
+					send_sig(SIGFPE, current, 1);
+				break;
+			}
+		}
+#endif
 		send_sig(SIGILL, current, 1);
 		break;
 
@@ -197,6 +233,11 @@
  * load/stores are not supported.  The former make no sense with
  * unaligned faults (they are guaranteed to fail) and I don't think
  * the latter will occur in any decent program.
+ *
+ * Sigh. We *do* have to handle some FP operations, because GCC will
+ * uses them as temporary storage for integer memory to memory copies.
+ * However, we need to deal with stt/ldt only as they are the only
+ * fp load/stores that preserve the bit pattern.
  */
 asmlinkage void do_entUnaUser(void * va, unsigned long opcode, unsigned long reg,
 			      unsigned long * frame)
@@ -223,12 +264,12 @@
 	unaligned[1].pc = *pc_addr;
 
 	dir = VERIFY_READ;
-	if (opcode > 0x29) {
-		/* it's a stl or stq */
+	if (opcode & 0x4) {
+		/* it's a stl, stq, or stt */
 		dir = VERIFY_WRITE;
 	}
 	size = 4;
-	if (opcode & 1) {
+	if (opcode & 0x1) {
 		/* it's a quadword op */
 		size = 8;
 	}
@@ -239,41 +280,47 @@
 	}
 
 	reg_addr = frame;
-	if (reg < 9) {
-		reg_addr += 7 + reg;			/* v0-t7 in SAVE_ALL frame */
-	} else if (reg < 16) {
-		reg_addr += (reg - 9);			/* s0-s6 in entUna frame */
-	} else if (reg < 19) {
-		reg_addr += 7 + 20 + 3 + (reg - 16);	/* a0-a2 in PAL frame */
-	} else if (reg < 29) {
-		reg_addr += 7 + 9 + (reg - 19);		/* a3-at in SAVE_ALL frame */
-	} else {
-		switch (reg) {
-			case 29:			/* gp in PAL frame */
+	if (opcode >= 0x28) {
+		/* it's an integer load/store */
+		if (reg < 9) {
+			reg_addr += 7 + reg;			/* v0-t7 in SAVE_ALL frame */
+		} else if (reg < 16) {
+			reg_addr += (reg - 9);			/* s0-s6 in entUna frame */
+		} else if (reg < 19) {
+			reg_addr += 7 + 20 + 3 + (reg - 16);	/* a0-a2 in PAL frame */
+		} else if (reg < 29) {
+			reg_addr += 7 + 9 + (reg - 19);		/* a3-at in SAVE_ALL frame */
+		} else {
+			switch (reg) {
+			      case 29:				/* gp in PAL frame */
 				reg_addr += 7 + 20 + 2;
 				break;
-			case 30:			/* usp in PAL regs */
+			      case 30:				/* usp in PAL regs */
 				usp = rdusp();
 				reg_addr = &usp;
 				break;
-			case 31:			/* zero "register" */
+			      case 31:				/* zero "register" */
 				reg_addr = &zero;
 				break;
+			}
 		}
 	}
 
 	switch (opcode) {
-		case 0x28: *reg_addr = (int) ldl_u(va);	break;	/* ldl */
-		case 0x29: *reg_addr = ldq_u(va);	break;	/* ldq */
-		case 0x2c: stl_u(*reg_addr, va);	break;	/* stl */
-		case 0x2d: stq_u(*reg_addr, va);	break;	/* stq */
-		default:
-			*pc_addr -= 4;	/* make pc point to faulting insn */
-			send_sig(SIGBUS, current, 1);
-			return;
+	      case 0x23: alpha_write_fp_reg(reg, ldq_u(va)); break; /* ldt */
+	      case 0x27: stq_u(alpha_read_fp_reg(reg), va);  break; /* stt */
+
+	      case 0x28: *reg_addr = (int) ldl_u(va);	     break; /* ldl */
+	      case 0x29: *reg_addr = ldq_u(va);		     break; /* ldq */
+	      case 0x2c: stl_u(*reg_addr, va);		     break; /* stl */
+	      case 0x2d: stq_u(*reg_addr, va);		     break; /* stq */
+	      default:
+		*pc_addr -= 4;	/* make pc point to faulting insn */
+		send_sig(SIGBUS, current, 1);
+		return;
 	}
 
-	if (reg == 30 && dir == VERIFY_WRITE) {
+	if (opcode >= 0x28 && reg == 30 && dir == VERIFY_WRITE) {
 		wrusp(usp);
 	} 
 }
diff -u --recursive --new-file v1.3.49/linux/arch/alpha/lib/Makefile linux/arch/alpha/lib/Makefile
--- v1.3.49/linux/arch/alpha/lib/Makefile	Tue Aug 15 20:38:59 1995
+++ linux/arch/alpha/lib/Makefile	Fri Dec 22 08:22:05 1995
@@ -7,7 +7,6 @@
 
 lib.a: $(OBJS)
 	$(AR) rcs lib.a $(OBJS)
-	sync
 
 __divqu.o: divide.S
 	$(CC) -DDIV -c -o __divqu.o divide.S
diff -u --recursive --new-file v1.3.49/linux/arch/alpha/lib/memcpy.c linux/arch/alpha/lib/memcpy.c
--- v1.3.49/linux/arch/alpha/lib/memcpy.c	Wed Nov  8 07:11:29 1995
+++ linux/arch/alpha/lib/memcpy.c	Fri Dec 22 08:22:05 1995
@@ -123,3 +123,9 @@
 	__memcpy(dest, src, n);
 	return dest;
 }
+
+/*
+ * gcc-2.7.1 and newer generate calls to memset and memcpy.  So we
+ * need to define that here:
+ */
+asm (".weakext memcpy, __memcpy");
diff -u --recursive --new-file v1.3.49/linux/arch/alpha/lib/memset.c linux/arch/alpha/lib/memset.c
--- v1.3.49/linux/arch/alpha/lib/memset.c	Fri Jul  7 08:54:44 1995
+++ linux/arch/alpha/lib/memset.c	Fri Dec 22 08:22:05 1995
@@ -38,3 +38,9 @@
 	__constant_c_memset(s,0x0101010101010101UL * (unsigned char) c, count);
 	return s;
 }
+
+/*
+ * gcc-2.7.1 and newer generate calls to memset and memcpy.  So we
+ * need to define that here:
+ */
+asm (".weakext memset, __memset");
diff -u --recursive --new-file v1.3.49/linux/arch/alpha/math-emu/Makefile linux/arch/alpha/math-emu/Makefile
--- v1.3.49/linux/arch/alpha/math-emu/Makefile	Thu Jan  1 02:00:00 1970
+++ linux/arch/alpha/math-emu/Makefile	Fri Dec 22 08:22:05 1995
@@ -0,0 +1,12 @@
+#
+# Makefile for math-emulator files...
+#
+
+OBJS  = fp-emul.o ieee-math.o
+
+math-emu.a: $(OBJS)
+	$(AR) rcs $@ $(OBJS)
+
+dep:
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v1.3.49/linux/arch/alpha/math-emu/fp-emul.c linux/arch/alpha/math-emu/fp-emul.c
--- v1.3.49/linux/arch/alpha/math-emu/fp-emul.c	Thu Jan  1 02:00:00 1970
+++ linux/arch/alpha/math-emu/fp-emul.c	Fri Dec 22 08:22:05 1995
@@ -0,0 +1,388 @@
+#include <sys/types.h>
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+
+#include <asm/segment.h>
+
+#include "ieee-math.h"
+
+#define	OPC_PAL		0x00
+
+#define OPC_INTA	0x10
+#define OPC_INTL	0x11
+#define OPC_INTS	0x12
+#define OPC_INTM	0x13
+#define OPC_FLTV	0x14
+#define OPC_FLTI	0x15
+#define OPC_FLTL	0x16
+
+#define OPC_MISC	0x18
+
+#define	OPC_JSR		0x1a
+
+/*
+ * "Base" function codes for the FLTI-class instructions.  These
+ * instructions all have opcode 0x16.  Note that in most cases these
+ * actually correspond to the "chopped" form of the instruction.  Not
+ * to worry---we extract the qualifier bits separately and deal with
+ * them separately.  Notice that base function code 0x2c is used for
+ * both CVTTS and CVTST.  The other bits in the function code are used
+ * to distinguish the two.
+ */
+#define FLTI_FUNC_ADDS			0x000
+#define FLTI_FUNC_ADDT			0x020
+#define FLTI_FUNC_CMPTEQ		0x0a5
+#define FLTI_FUNC_CMPTLT		0x0a6
+#define FLTI_FUNC_CMPTLE		0x0a7
+#define FLTI_FUNC_CMPTUN		0x0a4
+#define FLTI_FUNC_CVTTS_or_CVTST	0x02c
+#define FLTI_FUNC_CVTTQ			0x02f
+#define FLTI_FUNC_CVTQS			0x03c
+#define FLTI_FUNC_CVTQT			0x03e
+#define FLTI_FUNC_DIVS			0x003
+#define FLTI_FUNC_DIVT			0x023
+#define FLTI_FUNC_MULS			0x002
+#define FLTI_FUNC_MULT			0x022
+#define FLTI_FUNC_SUBS			0x001
+#define FLTI_FUNC_SUBT			0x021
+
+#define FLTI_FUNC_CVTQL			0x030	/* opcode 0x17 */
+
+#define MISC_TRAPB	0x0000
+#define MISC_EXCB	0x0400
+
+
+extern unsigned long	rdfpcr (void);
+extern void		wrfpcr (unsigned long);
+
+
+unsigned long
+alpha_read_fp_reg (unsigned long reg)
+{
+	unsigned long r;
+
+	switch (reg) {
+	      case  0: asm ("stt  $f0,%0" : "m="(r)); break;
+	      case  1: asm ("stt  $f1,%0" : "m="(r)); break;
+	      case  2: asm ("stt  $f2,%0" : "m="(r)); break;
+	      case  3: asm ("stt  $f3,%0" : "m="(r)); break;
+	      case  4: asm ("stt  $f4,%0" : "m="(r)); break;
+	      case  5: asm ("stt  $f5,%0" : "m="(r)); break;
+	      case  6: asm ("stt  $f6,%0" : "m="(r)); break;
+	      case  7: asm ("stt  $f7,%0" : "m="(r)); break;
+	      case  8: asm ("stt  $f8,%0" : "m="(r)); break;
+	      case  9: asm ("stt  $f9,%0" : "m="(r)); break;
+	      case 10: asm ("stt $f10,%0" : "m="(r)); break;
+	      case 11: asm ("stt $f11,%0" : "m="(r)); break;
+	      case 12: asm ("stt $f12,%0" : "m="(r)); break;
+	      case 13: asm ("stt $f13,%0" : "m="(r)); break;
+	      case 14: asm ("stt $f14,%0" : "m="(r)); break;
+	      case 15: asm ("stt $f15,%0" : "m="(r)); break;
+	      case 16: asm ("stt $f16,%0" : "m="(r)); break;
+	      case 17: asm ("stt $f17,%0" : "m="(r)); break;
+	      case 18: asm ("stt $f18,%0" : "m="(r)); break;
+	      case 19: asm ("stt $f19,%0" : "m="(r)); break;
+	      case 20: asm ("stt $f20,%0" : "m="(r)); break;
+	      case 21: asm ("stt $f21,%0" : "m="(r)); break;
+	      case 22: asm ("stt $f22,%0" : "m="(r)); break;
+	      case 23: asm ("stt $f23,%0" : "m="(r)); break;
+	      case 24: asm ("stt $f24,%0" : "m="(r)); break;
+	      case 25: asm ("stt $f25,%0" : "m="(r)); break;
+	      case 26: asm ("stt $f26,%0" : "m="(r)); break;
+	      case 27: asm ("stt $f27,%0" : "m="(r)); break;
+	      case 28: asm ("stt $f28,%0" : "m="(r)); break;
+	      case 29: asm ("stt $f29,%0" : "m="(r)); break;
+	      case 30: asm ("stt $f30,%0" : "m="(r)); break;
+	      case 31: asm ("stt $f31,%0" : "m="(r)); break;
+	      default:
+		break;
+	}
+	return r;
+}
+
+
+#if 0
+/*
+ * This is IMHO the better way of implementing LDT().  But it
+ * has the disadvantage that gcc 2.7.0 refuses to compile it
+ * (invalid operand constraints), so instead, we use the uglier
+ * macro below.
+ */
+# define LDT(reg,val)	\
+  asm volatile ("ldt $f"#reg",%0" :: "m"(val));
+#else
+# define LDT(reg,val)	\
+  asm volatile ("ldt $f"#reg",0(%0)" :: "r"(&val));
+#endif
+
+void
+alpha_write_fp_reg (unsigned long reg, unsigned long val)
+{
+	switch (reg) {
+	      case  0: LDT( 0, val); break;
+	      case  1: LDT( 1, val); break;
+	      case  2: LDT( 2, val); break;
+	      case  3: LDT( 3, val); break;
+	      case  4: LDT( 4, val); break;
+	      case  5: LDT( 5, val); break;
+	      case  6: LDT( 6, val); break;
+	      case  7: LDT( 7, val); break;
+	      case  8: LDT( 8, val); break;
+	      case  9: LDT( 9, val); break;
+	      case 10: LDT(10, val); break;
+	      case 11: LDT(11, val); break;
+	      case 12: LDT(12, val); break;
+	      case 13: LDT(13, val); break;
+	      case 14: LDT(14, val); break;
+	      case 15: LDT(15, val); break;
+	      case 16: LDT(16, val); break;
+	      case 17: LDT(17, val); break;
+	      case 18: LDT(18, val); break;
+	      case 19: LDT(19, val); break;
+	      case 20: LDT(20, val); break;
+	      case 21: LDT(21, val); break;
+	      case 22: LDT(22, val); break;
+	      case 23: LDT(23, val); break;
+	      case 24: LDT(24, val); break;
+	      case 25: LDT(25, val); break;
+	      case 26: LDT(26, val); break;
+	      case 27: LDT(27, val); break;
+	      case 28: LDT(28, val); break;
+	      case 29: LDT(29, val); break;
+	      case 30: LDT(30, val); break;
+	      case 31: LDT(31, val); break;
+	      default:
+		break;
+	}
+}
+
+
+/*
+ * Emulate the floating point instruction at address PC.  Returns 0 if
+ * emulation fails.  Notice that the kernel does not and cannot use FP
+ * regs.  This is good because it means that instead of
+ * saving/restoring all fp regs, we simply stick the result of the
+ * operation into the appropriate register.
+ */
+long
+alpha_fp_emul (unsigned long pc)
+{
+	unsigned long opcode, fa, fb, fc, func, mode;
+	unsigned long fpcw = current->tss.flags;
+	unsigned long va, vb, vc, res, fpcr;
+	__u32 insn;
+
+	insn = get_user((__u32*)pc);
+	fc     = (insn >>  0) &  0x1f;	/* destination register */
+	func   = (insn >>  5) & 0x3ff;
+	fb     = (insn >> 16) &  0x1f;
+	fa     = (insn >> 21) &  0x1f;
+	opcode = insn >> 26;
+	
+	va = alpha_read_fp_reg(fa);
+	vb = alpha_read_fp_reg(fb);
+
+	fpcr = rdfpcr();
+	/*
+	 * Try the operation in software.  First, obtain the rounding
+	 * mode...
+	 */
+	mode = func & 0xc0;
+	if (mode == 0xc0) {
+	    /* dynamic---get rounding mode from fpcr: */
+	    mode = ((fpcr & FPCR_DYN_MASK) >> FPCR_DYN_SHIFT) << ROUND_SHIFT;
+	}
+	mode |= (fpcw & IEEE_TRAP_ENABLE_MASK);
+
+	if ((IEEE_TRAP_ENABLE_MASK & 0xc0)) {
+		extern int something_is_wrong (void);
+		something_is_wrong();
+	}
+
+	/* least 6 bits contain operation code: */
+	switch (func & 0x3f) {
+	      case FLTI_FUNC_CMPTEQ:
+		res = ieee_CMPTEQ(va, vb, &vc);
+		break;
+
+	      case FLTI_FUNC_CMPTLT:
+		res = ieee_CMPTLT(va, vb, &vc);
+		break;
+
+	      case FLTI_FUNC_CMPTLE:
+		res = ieee_CMPTLE(va, vb, &vc);
+		break;
+
+	      case FLTI_FUNC_CMPTUN:
+		res = ieee_CMPTUN(va, vb, &vc);
+		break;
+
+	      case FLTI_FUNC_CVTQL:
+		/*
+		 * Notice: We can get here only due to an integer
+		 * overflow.  Such overflows are reported as invalid
+		 * ops.  We return the result the hw would have
+		 * computed.
+		 */
+		vc = ((vb & 0xc0000000) << 32 |	/* sign and msb */
+		      (vb & 0x3fffffff) << 29);	/* rest of the integer */
+		res = FPCR_INV;
+		break;
+
+	      case FLTI_FUNC_CVTQS:
+		res = ieee_CVTQS(mode, vb, &vc);
+		break;
+
+	      case FLTI_FUNC_CVTQT:
+		res = ieee_CVTQT(mode, vb, &vc);
+		break;
+
+	      case FLTI_FUNC_CVTTS_or_CVTST:
+		if (func == 0x6ac) {
+			/*
+			 * 0x2ac is also CVTST, but if the /S
+			 * qualifier isn't set, we wouldn't be here in
+			 * the first place...
+			 */
+			res = ieee_CVTST(mode, vb, &vc);
+		} else {
+			res = ieee_CVTTS(mode, vb, &vc);
+		}
+		break; 
+
+	      case FLTI_FUNC_DIVS:
+		res = ieee_DIVS(mode, va, vb, &vc);
+		break;
+
+	      case FLTI_FUNC_DIVT:
+		res = ieee_DIVT(mode, va, vb, &vc);
+		break;
+
+	      case FLTI_FUNC_MULS:
+		res = ieee_MULS(mode, va, vb, &vc);
+		break;
+
+	      case FLTI_FUNC_MULT:
+		res = ieee_MULT(mode, va, vb, &vc);
+		break;
+
+	      case FLTI_FUNC_SUBS:
+		res = ieee_SUBS(mode, va, vb, &vc);
+		break;
+
+	      case FLTI_FUNC_SUBT:
+		res = ieee_SUBT(mode, va, vb, &vc);
+		break;
+
+	      case FLTI_FUNC_ADDS:
+		res = ieee_ADDS(mode, va, vb, &vc);
+		break;
+
+	      case FLTI_FUNC_ADDT:
+		res = ieee_ADDT(mode, va, vb, &vc);
+		break;
+
+	      case FLTI_FUNC_CVTTQ:
+		res = ieee_CVTTQ(mode, vb, &vc);
+		break;
+
+	      default:
+		printk("alpha_fp_emul: unexpected function code %#lx at %#lx",
+		       opcode, pc);
+		return 0;
+	}
+	/*
+	 * Take the appropriate action for each possible
+	 * floating-point result:
+	 *
+	 *	- Set the appropriate bits in the FPCR
+	 *	- If the specified exception is enabled in the FPCR,
+	 *	  return.  The caller (mxr_signal_handler) will dispatch
+	 *	  the appropriate signal to the translated program.
+	 */
+	if (res) {
+		fpcr |= FPCR_SUM | res;
+		wrfpcr(fpcr);
+		if (((res & FPCR_INV) && (fpcw & IEEE_TRAP_ENABLE_INV)) ||
+		    ((res & FPCR_DZE) && (fpcw & IEEE_TRAP_ENABLE_DZE)) ||
+		    ((res & FPCR_OVF) && (fpcw & IEEE_TRAP_ENABLE_OVF)) ||
+		    ((res & FPCR_UNF) && (fpcw & IEEE_TRAP_ENABLE_UNF)) ||
+		    ((res & FPCR_INE) && (fpcw & IEEE_TRAP_ENABLE_INE)))
+			return 0;
+	}
+	/*
+	 * Whoo-kay... we got this far, and we're not generating a signal
+	 * to the translated program.  All that remains is to write the
+	 * result:
+	 */
+	alpha_write_fp_reg(fc, vc);
+	return 1;
+}
+
+
+long
+alpha_fp_emul_imprecise (struct pt_regs *regs, unsigned long write_mask)
+{
+	unsigned long trigger_pc = regs->pc - 4;
+	unsigned long insn, opcode, rc;
+	/*
+	 * Turn off the bits corresponding to registers that are the
+	 * target of instructions that set bits in the exception
+	 * summary register.  We have some slack doing this because a
+	 * register that is the target of a trapping instruction can
+	 * be written at most once in the trap shadow.
+	 *
+	 * Branches, jumps, TRAPBs, EXCBs and calls to PALcode all
+	 * bound the trap shadow, so we need not look any further than
+	 * up to the first occurance of such an instruction.
+	 */
+	while (write_mask) {
+		insn = get_user((__u32*)(trigger_pc));
+		opcode = insn >> 26;
+		rc = insn & 0x1f;
+
+		switch (opcode) {
+		      case OPC_PAL:
+		      case OPC_JSR:
+		      case 0x30 ... 0x3f:	/* branches */
+			return 0;
+
+		      case OPC_MISC:
+			switch (insn & 0xffff) {
+			      case MISC_TRAPB:
+			      case MISC_EXCB:
+				return 0;
+
+			      default:
+				break;
+			}
+			break;
+
+		      case OPC_INTA:
+		      case OPC_INTL:
+		      case OPC_INTS:
+		      case OPC_INTM:
+			write_mask &= ~(1UL << rc);
+			break;
+
+		      case OPC_FLTV:
+		      case OPC_FLTI:
+		      case OPC_FLTL:
+			write_mask &= ~(1UL << (rc + 32));
+			break;
+		}
+		if (!write_mask) {
+			if ((opcode == OPC_FLTI || opcode == OPC_FLTL)
+			    && alpha_fp_emul(trigger_pc))
+			{
+			    /* re-execute insns in trap-shadow: */
+			    regs->pc = trigger_pc + 4;
+			    return 1;
+			}
+			break;
+		}
+		trigger_pc -= 4;
+	}
+	return 0;
+}
diff -u --recursive --new-file v1.3.49/linux/arch/alpha/math-emu/fp-emul.h linux/arch/alpha/math-emu/fp-emul.h
--- v1.3.49/linux/arch/alpha/math-emu/fp-emul.h	Thu Jan  1 02:00:00 1970
+++ linux/arch/alpha/math-emu/fp-emul.h	Fri Dec 22 08:22:05 1995
@@ -0,0 +1,10 @@
+/*
+ * These defines correspond to the dynamic rounding mode bits in the
+ * Floating Point Control Register.  They also happen to correspond to
+ * the instruction encodings except that 0x03 signifies dynamic
+ * rounding mode in that case.
+ */
+#define ROUND_CHOP	0x00	/* chopped (aka round twards zero) */
+#define ROUND_NINF	0x01	/* round towards negative infinity */
+#define ROUND_NEAR	0x02	/* round towards nearest number */
+#define ROUND_PINF	0x03	/* round towards positive infinity */
diff -u --recursive --new-file v1.3.49/linux/arch/alpha/math-emu/ieee-math.c linux/arch/alpha/math-emu/ieee-math.c
--- v1.3.49/linux/arch/alpha/math-emu/ieee-math.c	Thu Jan  1 02:00:00 1970
+++ linux/arch/alpha/math-emu/ieee-math.c	Fri Dec 22 08:22:05 1995
@@ -0,0 +1,1343 @@
+/*
+ * ieee-math.c - IEEE floating point emulation code
+ * Copyright (C) 1989,1990,1991,1995 by
+ * Digital Equipment Corporation, Maynard, Massachusetts.
+ *
+ * Heavily modified for Linux/Alpha.  Changes are Copyright (c) 1995
+ * by David Mosberger (davidm@azstarnet.com).
+ *
+ * This file may be redistributed according to the terms of the
+ * GNU General Public License.
+ */
+/*
+ * The orginal code did not have any comments. I have created many
+ * comments as I fix the bugs in the code.  My comments are based on
+ * my observation and interpretation of the code.  If the orginal
+ * author would have spend a few minutes to comment the code, we would
+ * never had a problem of misinterpretation.  -HA
+ *
+ * This code could probably be a lot more optimized (especially the
+ * division routine).  However, my foremost concern was to get the
+ * IEEE behavior right.  Performance is less critical as these
+ * functions are used on exceptional numbers only (well, assuming you
+ * don't turn on the "trap on inexact"...).
+ */
+#include "ieee-math.h"
+
+#define STICKY_S	0x20000000	/* both in longword 0 of fraction */
+#define STICKY_T	1
+
+/*
+ * Careful: order matters here!
+ */
+enum {
+	NaN, QNaN, INFTY, ZERO, DENORM, NORMAL
+};
+
+enum {
+	SINGLE, DOUBLE
+};
+
+typedef unsigned long fpclass_t;
+
+#define IEEE_TMAX	0x7fefffffffffffff
+#define IEEE_SMAX	0x47efffffe0000000
+#define IEEE_SNaN	0xfff00000000f0000
+#define IEEE_QNaN	0xfff8000000000000
+#define IEEE_PINF	0x7ff0000000000000
+#define IEEE_NINF	0xfff0000000000000
+
+
+/*
+ * The memory format of S floating point numbers differs from the
+ * register format.  In the following, the bitnumbers above the
+ * diagram below give the memory format while the numbers below give
+ * the register format.
+ *
+ *	  31 30	     23 22				0
+ *	+-----------------------------------------------+
+ * S	| s |	exp    |       fraction			|
+ *	+-----------------------------------------------+
+ *	  63 62	     52 51			      29
+ *	
+ * For T floating point numbers, the register and memory formats
+ * match:
+ *
+ *	+-------------------------------------------------------------------+
+ * T	| s |	     exp	|	    frac | tion			    |
+ *	+-------------------------------------------------------------------+
+ *	  63 62		      52 51	       32 31			   0
+ */
+typedef struct {
+	unsigned long	f[2];	/* bit 55 in f[0] is the factor of 2^0*/
+	int		s;	/* 1 bit sign (0 for +, 1 for -) */
+	int		e;	/* 16 bit signed exponent */
+} EXTENDED;
+
+
+/*
+ * Return the sign of a Q integer, S or T fp number in the register
+ * format.
+ */
+static inline int
+sign (unsigned long a)
+{
+	if ((long) a < 0)
+		return -1;
+	else
+		return 1;
+}
+
+
+static inline long
+cmp128 (const long a[2], const long b[2])
+{
+	if (a[1] < b[1]) return -1;
+	if (a[1] > b[1]) return  1;
+	return a[0] - b[0];
+}
+
+
+static inline void
+sll128 (unsigned long a[2])
+{
+	a[1] = (a[1] << 1) | (a[0] >> 63);
+	a[0] <<= 1;
+}
+
+
+static inline void
+srl128 (unsigned long a[2])
+{
+	a[0] = (a[0] >> 1) | (a[1] << 63);
+	a[1] >>= 1;
+}
+
+
+static inline void
+add128 (const unsigned long a[2], const unsigned long b[2], unsigned long c[2])
+{
+	unsigned long carry = a[0] > (0xffffffffffffffff - b[0]);
+
+	c[0] = a[0] + b[0];
+	c[1] = a[1] + b[1] + carry;
+}
+
+
+static inline void
+sub128 (const unsigned long a[2], const unsigned long b[2], unsigned long c[2])
+{
+	unsigned long borrow = a[0] < b[0];
+
+	c[0] = a[0] - b[0];
+	c[1] = a[1] - b[1] - borrow;
+}
+
+
+static inline void
+mul64 (const unsigned long a, const unsigned long b, unsigned long c[2])
+{
+	asm ("mulq  %2,%3,%0\n\t"
+	     "umulh %2,%3,%1"
+	     : "r="(c[0]), "r="(c[1]) : "r"(a), "r"(b));
+}
+
+
+static void
+div128 (unsigned long a[2], unsigned long b[2], unsigned long c[2])
+{
+	unsigned long mask[2] = {1, 0};
+
+	/*
+	 * Shift b until either the sign bit is set or until it is at
+	 * least as big as the dividend:
+	 */
+	while (cmp128(b, a) < 0 && sign(b[1]) >= 0) {
+		sll128(b);
+		sll128(mask);
+	}
+	c[0] = c[1] = 0;
+	do {
+		if (cmp128(a, b) >= 0) {
+			sub128(a, b, a);
+			add128(mask, c, c);
+		}
+		srl128(mask);
+		srl128(b);
+	} while (mask[0] || mask[1]);
+}
+
+
+static void
+normalize (EXTENDED *a)
+{
+	if (!a->f[0] && !a->f[1])
+		return;		/* zero fraction, unnormalizable... */
+	/*
+	 * In "extended" format, the "1" in "1.f" is explicit; it is
+	 * in bit 55 of f[0], and the decimal point is understood to
+	 * be between bit 55 and bit 54.  To normalize, shift the
+	 * fraction until we have a "1" in bit 55.
+	 */
+	if ((a->f[0] & 0xff00000000000000) != 0 || a->f[1] != 0) {
+		/*
+		 * Mantissa is greater than 1.0:
+		 */
+		while ((a->f[0] & 0xff80000000000000) != 0x0080000000000000 ||
+		       a->f[1] != 0)
+		{
+			unsigned long sticky;
+
+			++a->e;
+			sticky = a->f[0] & 1;
+			srl128(a->f);
+			a->f[0] |= sticky;
+		}
+		return;
+	}
+
+	if (!(a->f[0] & 0x0080000000000000)) {
+		/*
+		 * Mantissa is less than 1.0:
+		 */
+		while (!(a->f[0] & 0x0080000000000000)) {
+			--a->e;
+			a->f[0] <<= 1;
+		}
+		return;
+	}
+}
+
+
+static inline fpclass_t
+ieee_fpclass (unsigned long a)
+{
+	unsigned long exp, fract;
+
+	exp   = (a >> 52) & 0x7ff;	/* 11 bits of exponent */
+	fract = a & 0x000fffffffffffff;	/* 52 bits of fraction */
+	if (exp == 0) {
+		if (fract == 0)
+			return ZERO;
+		return DENORM;
+	}
+	if (exp == 0x7ff) {
+		if (fract == 0)
+			return INFTY;
+		if (((fract >> 51) & 1) != 0)
+			return QNaN;
+		return NaN;
+	}
+	return NORMAL;
+}
+
+
+/*
+ * Translate S/T fp number in register format into extended format.
+ */
+static fpclass_t
+extend_ieee (unsigned long a, EXTENDED *b, int prec)
+{
+	fpclass_t result_kind;
+
+	b->s = a >> 63;
+	b->e = ((a >> 52) & 0x7ff) - 0x3ff;	/* remove bias */
+	b->f[1] = 0;
+	/*
+	 * We shift f[1] left three bits so that the higher order bits
+	 * of the fraction will reside in bits 55 through 0 of f[0].
+	 */
+	b->f[0] = (a & 0x000fffffffffffff) << 3;
+	result_kind = ieee_fpclass(a);
+	if (result_kind == NORMAL) {
+		/* set implied 1. bit: */
+		b->f[0] |= 1UL << 55;
+	} else if (result_kind == DENORM) {
+		if (prec == SINGLE)
+			b->e = -126;
+		else
+			b->e = -1022;
+	}
+	return result_kind;
+}
+
+
+/*
+ * INPUT PARAMETERS:
+ *       a           a number in EXTENDED format to be converted to
+ *                   s-floating format.
+ *	 f	     rounding mode and exception enable bits.
+ * OUTPUT PARAMETERS:
+ *       b          will contain the s-floating number that "a" was
+ *                  converted to (in register format).
+ */
+static unsigned long
+make_s_ieee (long f, EXTENDED *a, unsigned long *b)
+{
+	unsigned long res, sticky;
+
+	if (!a->f[0] && !a->f[1]) {
+		*b = (unsigned long) a->s << 63;	/* return +/-0 */
+		return 0;
+	}
+
+	normalize(a);
+	res = 0;
+
+	if (a->e < -0x7e) {
+		res = FPCR_INE;
+		if (f & IEEE_TRAP_ENABLE_UNF) {
+			res |= FPCR_UNF;
+			a->e += 0xc0;	/* scale up result by 2^alpha */
+		} else {
+			/* try making denormalized number: */
+			while (a->e < -0x7e) {
+				++a->e;
+				sticky = a->f[0] & 1;
+				srl128(a->f);
+				if (!a->f[0] && !a->f[0]) {
+					/* underflow: replace with exact 0 */
+					res |= FPCR_UNF;
+					break;
+				}
+				a->f[0] |= sticky;
+			}
+			a->e = -0x3ff;
+		}
+	}
+	if (a->e >= 0x80) {
+		res = FPCR_OVF | FPCR_INE;
+		if (f & IEEE_TRAP_ENABLE_OVF) {
+			a->e -= 0xc0;	/* scale down result by 2^alpha */
+		} else {
+			/*
+			 * Overflow without trap enabled, substitute
+			 * result according to rounding mode:
+			 */
+			switch (RM(f)) {
+			      case ROUND_NEAR:
+				*b = IEEE_PINF;
+				break;
+
+			      case ROUND_CHOP:
+				*b = IEEE_SMAX;
+				break;
+
+			      case ROUND_NINF:
+				if (a->s) {
+					*b = IEEE_PINF;
+				} else {
+					*b = IEEE_SMAX;
+				}
+				break;
+
+			      case ROUND_PINF: 
+				if (a->s) {
+					*b = IEEE_SMAX;
+				} else {
+					*b = IEEE_PINF;
+				}
+				break;
+			}
+			*b |= ((unsigned long) a->s << 63);
+			return res;
+		}
+	}
+
+	*b = (((unsigned long) a->s << 63) |
+	      (((unsigned long) a->e + 0x3ff) << 52) |
+	      ((a->f[0] >> 3) & 0x000fffffe0000000));
+	return res;
+}
+
+
+static unsigned long
+make_t_ieee (long f, EXTENDED *a, unsigned long *b)
+{
+	unsigned long res, sticky;
+
+	if (!a->f[0] && !a->f[1]) {
+		*b = (unsigned long) a->s << 63;	/* return +/-0 */
+		return 0;
+	}
+
+	normalize(a);
+	res = 0;
+	if (a->e < -0x3fe) {
+		res = FPCR_INE;
+		if (f & IEEE_TRAP_ENABLE_UNF) {
+			res |= FPCR_UNF;
+			a->e += 0x600;
+		} else {
+			/* try making denormalized number: */
+			while (a->e < -0x3fe) {
+				++a->e;
+				sticky = a->f[0] & 1;
+				srl128(a->f);
+				if (!a->f[0] && !a->f[0]) {
+					/* underflow: replace with exact 0 */
+					res |= FPCR_UNF;
+					break;
+				}
+				a->f[0] |= sticky;
+			}
+			a->e = -0x3ff;
+		}
+	}
+	if (a->e > 0x3ff) {
+		res = FPCR_OVF | FPCR_INE;
+		if (f & IEEE_TRAP_ENABLE_OVF) {
+			a->e -= 0x600;	/* scale down result by 2^alpha */
+		} else {
+			/*
+			 * Overflow without trap enabled, substitute
+			 * result according to rounding mode:
+			 */
+			switch (RM(f)) {
+			      case ROUND_NEAR:
+				*b = IEEE_PINF;
+				break;
+
+			      case ROUND_CHOP:
+				*b = IEEE_TMAX;
+				break;
+
+			      case ROUND_NINF:
+				if (a->s) {
+					*b = IEEE_PINF;
+				} else {
+					*b = IEEE_TMAX;
+				}
+				break;
+
+			      case ROUND_PINF: 
+				if (a->s) {
+					*b = IEEE_TMAX;
+				} else {
+					*b = IEEE_PINF;
+				}
+				break;
+			}
+			*b |= ((unsigned long) a->s << 63);
+			return res;
+		}
+	}
+	*b = (((unsigned long) a->s << 63) |
+	      (((unsigned long) a->e + 0x3ff) << 52) |
+	      ((a->f[0] >> 3) & 0x000fffffffffffff));
+	return res;
+}
+
+
+/*
+ * INPUT PARAMETERS:
+ *       a          EXTENDED format number to be rounded.
+ *       rm	    integer with value ROUND_NEAR, ROUND_CHOP, etc.
+ *                  indicates how "a" should be rounded to produce "b".
+ * OUTPUT PARAMETERS:
+ *       b          s-floating number produced by rounding "a".
+ * RETURN VALUE:
+ *       if no errors occurred, will be zero.  Else will contain flags
+ *       like FPCR_INE_OP, etc.
+ */
+static unsigned long
+round_s_ieee (int f, EXTENDED *a, unsigned long *b)
+{
+	unsigned long diff1, diff2, res = 0;
+	EXTENDED z1, z2;
+
+	if (!(a->f[0] & 0xffffffff)) {
+		return make_s_ieee(f, a, b);	/* no rounding error */
+	}
+
+	/*
+	 * z1 and z2 are the S-floating numbers with the next smaller/greater
+	 * magnitude than a, respectively.
+	 */
+	z1.s = z2.s = a->s;
+	z1.e = z2.e = a->e;
+	z1.f[0] = z2.f[0] = a->f[0] & 0xffffffff00000000;
+	z1.f[1] = z2.f[1] = 0;
+	z2.f[0] += 0x100000000;	/* next bigger S float number */
+
+	switch (RM(f)) {
+	      case ROUND_NEAR:
+		diff1 = a->f[0] - z1.f[0];
+		diff2 = z2.f[0] - a->f[0];
+		if (diff1 > diff2)
+			res = make_s_ieee(f, &z2, b);
+		else if (diff2 > diff1)
+			res = make_s_ieee(f, &z1, b);
+		else
+			/* equal distance: round towards even */
+			if (z1.f[0] & 0x100000000)
+				res = make_s_ieee(f, &z2, b);
+			else
+				res = make_s_ieee(f, &z1, b);
+		break;
+
+	      case ROUND_CHOP:
+		res = make_s_ieee(f, &z1, b);
+		break;
+
+	      case ROUND_PINF:
+		if (a->s) {
+			res = make_s_ieee(f, &z1, b);
+		} else {
+			res = make_s_ieee(f, &z2, b);
+		}
+		break;
+
+	      case ROUND_NINF:
+		if (a->s) {
+			res = make_s_ieee(f, &z2, b);
+		} else {
+			res = make_s_ieee(f, &z1, b);
+		}
+		break;
+	}
+	return FPCR_INE | res;
+}
+
+
+static unsigned long
+round_t_ieee (EXTENDED *a, unsigned long *b, int f)
+{
+	unsigned long diff1, diff2, res;
+	EXTENDED z1, z2;
+
+	if (!(a->f[0] & 0x7)) {
+		/* no rounding error */
+		return make_t_ieee(f, a, b);
+	}
+
+	z1.s = z2.s = a->s;
+	z1.e = z2.e = a->e;
+	z1.f[0] = z2.f[0] = a->f[0] & ~0x7;
+	z1.f[1] = z2.f[1] = 0;
+	z2.f[0] += (1 << 3);
+
+	res = 0;
+	switch (RM(f)) {
+	      case ROUND_NEAR:
+		diff1 = a->f[0] - z1.f[0];
+		diff2 = z2.f[0] - a->f[0];
+		if (diff1 > diff2)
+			res = make_t_ieee(f, &z2, b);
+		else if (diff2 > diff1)
+			res = make_t_ieee(f, &z1, b);
+		else
+			/* equal distance: round towards even */
+			if (z1.f[0] & (1 << 3))
+				res = make_t_ieee(f, &z2, b);
+			else
+				res = make_t_ieee(f, &z1, b);
+		break;
+
+	      case ROUND_CHOP:
+		res = make_t_ieee(f, &z1, b);
+		break;
+
+	      case ROUND_PINF:
+		if (a->s) {
+			res = make_t_ieee(f, &z1, b);
+		} else {
+			res = make_t_ieee(f, &z2, b);
+		}
+		break;
+
+	      case ROUND_NINF:
+		if (a->s) {
+			res = make_t_ieee(f, &z2, b);
+		} else {
+			res = make_t_ieee(f, &z1, b);
+		}
+		break;
+	}
+	return FPCR_INE | res;
+}
+
+
+static fpclass_t
+add_kernel_ieee (EXTENDED *op_a, EXTENDED *op_b, EXTENDED *op_c)
+{
+	unsigned long mask, fa, fb, fc;
+	int diff;
+
+	diff = op_a->e - op_b->e;
+	fa = op_a->f[0];
+	fb = op_b->f[0];
+	if (diff < 0) {
+		diff = -diff;
+		op_c->e = op_b->e;
+		mask = (1UL << diff) - 1;
+		fa >>= diff;
+		if (op_a->f[0] & mask) {
+			fa |= 1;		/* set sticky bit */
+		}
+	} else {
+		op_c->e = op_a->e;
+		mask = (1UL << diff) - 1;
+		fb >>= diff;
+		if (op_b->f[0] & mask) {
+			fb |= 1;		/* set sticky bit */
+		}
+	}
+	if (op_a->s)
+		fa = -fa;
+	if (op_b->s)
+		fb = -fb;
+	fc = fa + fb;
+	op_c->f[1] = 0;
+	op_c->s = fc >> 63;
+	if (op_c->s) {
+		fc = -fc;
+	}
+	op_c->f[0] = fc;
+	normalize(op_c);
+	return 0;
+}
+
+
+/*
+ * converts s-floating "a" to t-floating "b".
+ *
+ * INPUT PARAMETERS:
+ *       a           a s-floating number to be converted
+ *       f           the rounding mode (ROUND_NEAR, etc. )
+ * OUTPUT PARAMETERS:
+ *       b           the t-floating number that "a" is converted to.
+ * RETURN VALUE:
+ *       error flags - i.e., zero if no errors occurred,
+ *       FPCR_INV if invalid operation occurred, etc.
+ */
+unsigned long
+ieee_CVTST (int f, unsigned long a, unsigned long *b)
+{
+	EXTENDED temp;
+	fpclass_t a_type;
+
+	a_type = extend_ieee(a, &temp, SINGLE);
+	if (a_type >= NaN && a_type <= INFTY) {
+		*b = a;
+		if (a_type == NaN) {
+			*b |= (1UL << 51);	/* turn SNaN into QNaN */
+			return FPCR_INV;
+		}
+		return 0;
+	}
+	return round_s_ieee(f, &temp, b);
+}
+
+
+/*
+ * converts t-floating "a" to s-floating "b".
+ *
+ * INPUT PARAMETERS:
+ *       a           a t-floating number to be converted
+ *       f           the rounding mode (ROUND_NEAR, etc. )
+ * OUTPUT PARAMETERS:
+ *       b           the s-floating number that "a" is converted to.
+ * RETURN VALUE:
+ *       error flags - i.e., zero if no errors occurred,
+ *       FPCR_INV if invalid operation occurred, etc.
+ */
+unsigned long
+ieee_CVTTS (int f, unsigned long a, unsigned long *b)
+{
+	EXTENDED temp;
+	fpclass_t a_type;
+
+	a_type = extend_ieee(a, &temp, DOUBLE);
+	if (a_type >= NaN && a_type <= INFTY) {
+		*b = a;
+		if (a_type == NaN) {
+			*b |= (1UL << 51);	/* turn SNaN into QNaN */
+			return FPCR_INV;
+		}
+		return 0;
+	}
+	return round_s_ieee(f, &temp, b);
+}
+
+
+/*
+ * converts q-format (64-bit integer) "a" to s-floating "b".
+ *
+ * INPUT PARAMETERS:
+ *       a           an 64-bit integer to be converted.
+ *       f           the rounding mode (ROUND_NEAR, etc. )
+ * OUTPUT PARAMETERS:
+ *       b           the s-floating number "a" is converted to.
+ * RETURN VALUE:
+ *       error flags - i.e., zero if no errors occurred,
+ *       FPCR_INV if invalid operation occurred, etc.
+ */
+unsigned long
+ieee_CVTQS (int f, unsigned long a, unsigned long *b)
+{
+	EXTENDED op_b;
+
+	op_b.s    = 0;
+	op_b.f[0] = a;
+	op_b.f[1] = 0;
+	if (sign(a) < 0) {
+		op_b.s = 1;
+		op_b.f[0] = -a;
+	}
+	op_b.e = 55;
+	normalize(&op_b);
+	return round_s_ieee(f, &op_b, b);
+}
+
+
+/*
+ * converts 64-bit integer "a" to t-floating "b".
+ *
+ * INPUT PARAMETERS:
+ *       a           a 64-bit integer to be converted.
+ *       f           the rounding mode (ROUND_NEAR, etc.)
+ * OUTPUT PARAMETERS:
+ *       b           the t-floating number "a" is converted to.
+ * RETURN VALUE:
+ *       error flags - i.e., zero if no errors occurred,
+ *       FPCR_INV if invalid operation occurred, etc.
+ */
+unsigned long
+ieee_CVTQT (int f, unsigned long a, unsigned long *b)
+{
+	EXTENDED op_b;
+
+	op_b.s    = 0;
+	op_b.f[0] = a;
+	op_b.f[1] = 0;
+	if (sign(a) < 0) {
+		op_b.s = 1;
+		op_b.f[0] = -a;
+	}
+	op_b.e = 55;
+	normalize(&op_b);
+	return round_t_ieee(&op_b, b, f);
+}
+
+
+/*
+ * converts t-floating "a" to 64-bit integer (q-format) "b".
+ *
+ * INPUT PARAMETERS:
+ *       a           a t-floating number to be converted.
+ *       f           the rounding mode (ROUND_NEAR, etc. )
+ * OUTPUT PARAMETERS:
+ *       b           the 64-bit integer "a" is converted to.
+ * RETURN VALUE:
+ *       error flags - i.e., zero if no errors occurred,
+ *       FPCR_INV if invalid operation occurred, etc.
+ */
+unsigned long
+ieee_CVTTQ (int f, unsigned long a, unsigned long *b)
+{
+	unsigned int midway;
+	unsigned long ov, uv, res = 0;
+	fpclass_t a_type;
+	EXTENDED temp;
+
+	*b = 0;
+	a_type = extend_ieee(a, &temp, DOUBLE);
+	if (a_type == NaN || a_type == INFTY)
+		return FPCR_INV;
+	if (a_type == QNaN)
+		return 0;
+
+	if (temp.e > 0) {
+		ov = 0;
+		while (temp.e > 0) {
+			--temp.e;
+			ov |= temp.f[1] >> 63;
+			sll128(temp.f);
+		}
+		if (ov || (temp.f[1] & 0xffc0000000000000))
+			res |= FPCR_IOV | FPCR_INE;
+	}
+	if (temp.e < 0) {
+		while (temp.e < 0) {
+			++temp.e;
+			uv = temp.f[0] & 1;		/* save sticky bit */
+			srl128(temp.f);
+			temp.f[0] |= uv;
+		}
+	}
+	*b = ((temp.f[1] << 9) | (temp.f[0] >> 55)) & 0x7fffffffffffffff;
+	/*
+	 * Notice: the fraction is only 52 bits long.  Thus, rounding
+	 * cannot possibly result in an integer overflow.
+	 */
+	switch (RM(f)) {
+	      case ROUND_NEAR:
+		if (temp.f[0] & 0x0040000000000000) {
+			midway = (temp.f[0] & 0x003fffffffffffff) == 0;
+			if ((midway && (temp.f[0] & 0x0080000000000000)) ||
+			    !midway)
+				++b;
+		}
+		break;
+
+	      case ROUND_PINF:
+		if ((temp.f[0] & 0x003fffffffffffff) != 0)
+			++b;
+		break;
+
+	      case ROUND_NINF:
+		if ((temp.f[0] & 0x003fffffffffffff) != 0)
+			--b;
+		break;
+
+	      case ROUND_CHOP:
+		/* no action needed */
+		break;
+	}
+	if ((temp.f[0] & 0x003fffffffffffff) != 0)
+		res |= FPCR_INE;
+
+	if (temp.s) {
+		*b = -*b;
+	}
+	return res;
+}
+
+
+unsigned long
+ieee_CMPTEQ (unsigned long a, unsigned long b, unsigned long *c)
+{
+	EXTENDED op_a, op_b;
+	fpclass_t a_type, b_type;
+
+	*c = 0;
+	a_type = extend_ieee(a, &op_a, DOUBLE);
+	b_type = extend_ieee(b, &op_b, DOUBLE);
+	if (a_type == NaN || b_type == NaN)
+		return FPCR_INV;
+	if (a_type == QNaN || b_type == QNaN)
+		return 0;
+
+	if ((op_a.e == op_b.e && op_a.s == op_b.s &&
+	     op_a.f[0] == op_b.f[0] && op_a.f[1] == op_b.f[1]) ||
+	    (a_type == ZERO && b_type == ZERO))
+		*c = 0x4000000000000000;
+	return 0;
+}
+
+
+unsigned long
+ieee_CMPTLT (unsigned long a, unsigned long b, unsigned long *c)
+{
+	fpclass_t a_type, b_type;
+	EXTENDED op_a, op_b;
+
+	*c = 0;
+	a_type = extend_ieee(a, &op_a, DOUBLE);
+	b_type = extend_ieee(b, &op_b, DOUBLE);
+	if (a_type == NaN || b_type == NaN)
+		return FPCR_INV;
+	if (a_type == QNaN || b_type == QNaN)
+		return 0;
+
+	if ((op_a.s == 1 && op_b.s == 0 &&
+	     (a_type != ZERO || b_type != ZERO)) ||
+	    (op_a.s == 1 && op_b.s == 1 &&
+	     (op_a.e > op_b.e || (op_a.e == op_b.e &&
+				  cmp128(op_a.f, op_b.f) > 0))) ||
+	    (op_a.s == 0 && op_b.s == 0 &&
+	     (op_a.e < op_b.e || (op_a.e == op_b.e &&
+				  cmp128(op_a.f,op_b.f) < 0))))
+		*c = 0x4000000000000000;
+	return 0;
+}
+
+
+unsigned long
+ieee_CMPTLE (unsigned long a, unsigned long b, unsigned long *c)
+{
+	fpclass_t a_type, b_type;
+	EXTENDED op_a, op_b;
+
+	*c = 0;
+	a_type = extend_ieee(a, &op_a, DOUBLE);
+	b_type = extend_ieee(b, &op_b, DOUBLE);
+	if (a_type == NaN || b_type == NaN)
+		return FPCR_INV;
+	if (a_type == QNaN || b_type == QNaN)
+		return 0;
+
+	if ((a_type == ZERO && b_type == ZERO) ||
+	    (op_a.s == 1 && op_b.s == 0) ||
+	    (op_a.s == 1 && op_b.s == 1 &&
+	     (op_a.e > op_b.e || (op_a.e == op_b.e &&
+				  cmp128(op_a.f,op_b.f) >= 0))) ||
+	    (op_a.s == 0 && op_b.s == 0 &&
+	     (op_a.e < op_b.e || (op_a.e == op_b.e &&
+				  cmp128(op_a.f,op_b.f) <= 0))))
+		*c = 0x4000000000000000;
+	return 0;
+}
+
+
+unsigned long
+ieee_CMPTUN (unsigned long a, unsigned long b, unsigned long *c)
+{
+	fpclass_t a_type, b_type;
+	EXTENDED op_a, op_b;
+
+	*c = 0x4000000000000000;
+	a_type = extend_ieee(a, &op_a, DOUBLE);
+	b_type = extend_ieee(b, &op_b, DOUBLE);
+	if (a_type == NaN || b_type == NaN)
+		return FPCR_INV;
+	if (a_type == QNaN || b_type == QNaN)
+		return 0;
+	*c = 0;
+	return 0;
+}
+
+
+/*
+ * Add a + b = c, where a, b, and c are ieee s-floating numbers.  "f"
+ * contains the rounding mode etc.
+ */
+unsigned long
+ieee_ADDS (int f, unsigned long a, unsigned long b, unsigned long *c)
+{
+	fpclass_t a_type, b_type;
+	EXTENDED op_a, op_b, op_c;
+
+	a_type = extend_ieee(a, &op_a, SINGLE);
+	b_type = extend_ieee(b, &op_b, SINGLE);
+	if ((a_type >= NaN && a_type <= INFTY) ||
+	    (b_type >= NaN && b_type <= INFTY))
+	{
+		/* propagate NaNs according to arch. ref. handbook: */
+		if (b_type == QNaN)
+			*c = b;
+		else if (b_type == NaN)
+			*c = b | (1UL << 51);
+		else if (a_type == QNaN)
+			*c = a;
+		else if (a_type == NaN)
+			*c = a | (1UL << 51);
+
+		if (a_type == NaN || b_type == NaN)
+			return FPCR_INV;
+		if (a_type == QNaN || b_type == QNaN)
+			return 0;
+
+		if (a_type == INFTY && b_type == INFTY && sign(a) != sign(b)) {
+			*c = IEEE_QNaN;
+			return FPCR_INV;
+		}
+		if (a_type == INFTY)
+			*c = a;
+		else
+			*c = b;
+		return 0;
+	}
+
+	add_kernel_ieee(&op_a, &op_b, &op_c);
+	/* special case for -0 + -0 ==> -0 */
+	if (a_type == ZERO && b_type == ZERO)
+		op_c.s = op_a.s && op_b.s;
+	return round_s_ieee(f, &op_c, c);
+}
+
+
+/*
+ * Add a + b = c, where a, b, and c are ieee t-floating numbers.  "f"
+ * contains the rounding mode etc.
+ */
+unsigned long
+ieee_ADDT (int f, unsigned long a, unsigned long b, unsigned long *c)
+{
+	fpclass_t a_type, b_type;
+	EXTENDED op_a, op_b, op_c;
+
+	a_type = extend_ieee(a, &op_a, DOUBLE);
+	b_type = extend_ieee(b, &op_b, DOUBLE);
+	if ((a_type >= NaN && a_type <= INFTY) ||
+	    (b_type >= NaN && b_type <= INFTY))
+	{
+		/* propagate NaNs according to arch. ref. handbook: */
+		if (b_type == QNaN)
+			*c = b;
+		else if (b_type == NaN)
+			*c = b | (1UL << 51);
+		else if (a_type == QNaN)
+			*c = a;
+		else if (a_type == NaN)
+			*c = a | (1UL << 51);
+
+		if (a_type == NaN || b_type == NaN)
+			return FPCR_INV;
+		if (a_type == QNaN || b_type == QNaN)
+			return 0;
+
+		if (a_type == INFTY && b_type == INFTY && sign(a) != sign(b)) {
+			*c = IEEE_QNaN;
+			return FPCR_INV;
+		}
+		if (a_type == INFTY)
+			*c = a;
+		else
+			*c = b;
+		return 0;
+	}
+	add_kernel_ieee(&op_a, &op_b, &op_c);
+	/* special case for -0 + -0 ==> -0 */
+	if (a_type == ZERO && b_type == ZERO)
+		op_c.s = op_a.s && op_b.s;
+
+	return round_t_ieee(&op_c, c, f);	
+}
+
+
+/*
+ * Subtract a - b = c, where a, b, and c are ieee s-floating numbers.
+ * "f" contains the rounding mode etc.
+ */
+unsigned long
+ieee_SUBS (int f, unsigned long a, unsigned long b, unsigned long *c)
+{
+	fpclass_t a_type, b_type;
+	EXTENDED op_a, op_b, op_c;
+
+	a_type = extend_ieee(a, &op_a, SINGLE);
+	b_type = extend_ieee(b, &op_b, SINGLE);
+	if ((a_type >= NaN && a_type <= INFTY) ||
+	    (b_type >= NaN && b_type <= INFTY))
+	{
+		/* propagate NaNs according to arch. ref. handbook: */
+		if (b_type == QNaN)
+			*c = b;
+		else if (b_type == NaN)
+			*c = b | (1UL << 51);
+		else if (a_type == QNaN)
+			*c = a;
+		else if (a_type == NaN)
+			*c = a | (1UL << 51);
+
+		if (a_type == NaN || b_type == NaN)
+			return FPCR_INV;
+		if (a_type == QNaN || b_type == QNaN)
+			return 0;
+
+		if (a_type == INFTY && b_type == INFTY && sign(a) == sign(b)) {
+			*c = IEEE_QNaN;
+			return FPCR_INV;
+		}
+		if (a_type == INFTY)
+			*c = a;
+		else
+			*c = b ^ (1UL << 63);
+		return 0;
+	}
+	op_b.s = !op_b.s;
+	add_kernel_ieee(&op_a, &op_b, &op_c);
+	/* special case for -0 - +0 ==> -0 */
+	if (a_type == ZERO && b_type == ZERO)
+		op_c.s = op_a.s && op_b.s;
+
+	return round_s_ieee(f, &op_c, c);
+}
+
+
+/*
+ * Subtract a - b = c, where a, b, and c are ieee t-floating numbers.
+ * "f" contains the rounding mode etc.
+ */
+unsigned long
+ieee_SUBT (int f, unsigned long a, unsigned long b, unsigned long *c)
+{
+	fpclass_t a_type, b_type;
+	EXTENDED op_a, op_b, op_c;
+
+	a_type = extend_ieee(a, &op_a, DOUBLE);
+	b_type = extend_ieee(b, &op_b, DOUBLE);
+	if ((a_type >= NaN && a_type <= INFTY) ||
+	    (b_type >= NaN && b_type <= INFTY))
+	{
+		/* propagate NaNs according to arch. ref. handbook: */
+		if (b_type == QNaN)
+			*c = b;
+		else if (b_type == NaN)
+			*c = b | (1UL << 51);
+		else if (a_type == QNaN)
+			*c = a;
+		else if (a_type == NaN)
+			*c = a | (1UL << 51);
+
+		if (a_type == NaN || b_type == NaN)
+			return FPCR_INV;
+		if (a_type == QNaN || b_type == QNaN)
+			return 0;
+
+		if (a_type == INFTY && b_type == INFTY && sign(a) == sign(b)) {
+			*c = IEEE_QNaN;
+			return FPCR_INV;
+		}
+		if (a_type == INFTY)
+			*c = a;
+		else
+			*c = b ^ (1UL << 63);
+		return 0;
+	}
+	op_b.s = !op_b.s;
+	add_kernel_ieee(&op_a, &op_b, &op_c);
+	/* special case for -0 - +0 ==> -0 */
+	if (a_type == ZERO && b_type == ZERO)
+		op_c.s = op_a.s && op_b.s;
+
+	return round_t_ieee(&op_c, c, f);
+}
+
+
+/*
+ * Multiply a x b = c, where a, b, and c are ieee s-floating numbers.
+ * "f" contains the rounding mode.
+ */
+unsigned long
+ieee_MULS (int f, unsigned long a, unsigned long b, unsigned long *c)
+{
+	fpclass_t a_type, b_type;
+	EXTENDED op_a, op_b, op_c;
+
+	a_type = extend_ieee(a, &op_a, SINGLE);
+	b_type = extend_ieee(b, &op_b, SINGLE);
+	if ((a_type >= NaN && a_type <= INFTY) ||
+	    (b_type >= NaN && b_type <= INFTY))
+	{
+		/* propagate NaNs according to arch. ref. handbook: */
+		if (b_type == QNaN)
+			*c = b;
+		else if (b_type == NaN)
+			*c = b | (1UL << 51);
+		else if (a_type == QNaN)
+			*c = a;
+		else if (a_type == NaN)
+			*c = a | (1UL << 51);
+
+		if (a_type == NaN || b_type == NaN)
+			return FPCR_INV;
+		if (a_type == QNaN || b_type == QNaN)
+			return 0;
+
+		if ((a_type == INFTY && b_type == ZERO) ||
+		    (b_type == INFTY && a_type == ZERO))
+		{
+			*c = IEEE_QNaN;		/* return canonical QNaN */
+			return FPCR_INV;
+		}
+		if (a_type == INFTY)
+			*c = a ^ ((b >> 63) << 63);
+		else if (b_type == INFTY)
+			*c = b ^ ((a >> 63) << 63);
+		else
+			/* either of a and b are +/-0 */
+			*c = ((unsigned long) op_a.s ^ op_b.s) << 63;
+		return 0;
+	}
+	op_c.s = op_a.s ^ op_b.s;
+	op_c.e = op_a.e + op_b.e;
+	mul64(op_a.f[0], op_b.f[0], op_c.f);
+
+	normalize(&op_c);
+	op_c.e -= 55;		/* drop the 55 original bits. */
+
+	return round_s_ieee(f, &op_c, c);
+}
+
+
+/*
+ * Multiply a x b = c, where a, b, and c are ieee t-floating numbers.
+ * "f" contains the rounding mode.
+ */
+unsigned long
+ieee_MULT (int f, unsigned long a, unsigned long b, unsigned long *c)
+{
+	fpclass_t a_type, b_type;
+	EXTENDED op_a, op_b, op_c;
+
+	*c = IEEE_QNaN;
+	a_type = extend_ieee(a, &op_a, DOUBLE);
+	b_type = extend_ieee(b, &op_b, DOUBLE);
+	if ((a_type >= NaN && a_type <= ZERO) ||
+	    (b_type >= NaN && b_type <= ZERO))
+	{
+		/* propagate NaNs according to arch. ref. handbook: */
+		if (b_type == QNaN)
+			*c = b;
+		else if (b_type == NaN)
+			*c = b | (1UL << 51);
+		else if (a_type == QNaN)
+			*c = a;
+		else if (a_type == NaN)
+			*c = a | (1UL << 51);
+
+		if (a_type == NaN || b_type == NaN)
+			return FPCR_INV;
+		if (a_type == QNaN || b_type == QNaN)
+			return 0;
+
+		if ((a_type == INFTY && b_type == ZERO) ||
+		    (b_type == INFTY && a_type == ZERO))
+		{
+			*c = IEEE_QNaN;		/* return canonical QNaN */
+			return FPCR_INV;
+		}
+		if (a_type == INFTY)
+			*c = a ^ ((b >> 63) << 63);
+		else if (b_type == INFTY)
+			*c = b ^ ((a >> 63) << 63);
+		else
+			/* either of a and b are +/-0 */
+			*c = ((unsigned long) op_a.s ^ op_b.s) << 63;
+		return 0;
+	}
+	op_c.s = op_a.s ^ op_b.s;
+	op_c.e = op_a.e + op_b.e;
+	mul64(op_a.f[0], op_b.f[0], op_c.f);
+
+	normalize(&op_c);
+	op_c.e -= 55;	/* drop the 55 original bits. */
+
+	return round_t_ieee(&op_c, c, f);
+}
+
+
+/*
+ * Divide a / b = c, where a, b, and c are ieee s-floating numbers.
+ * "f" contains the rounding mode etc.
+ */
+unsigned long
+ieee_DIVS (int f, unsigned long a, unsigned long b, unsigned long *c)
+{
+	fpclass_t a_type, b_type;
+	EXTENDED op_a, op_b, op_c;
+
+	a_type = extend_ieee(a, &op_a, SINGLE);
+	b_type = extend_ieee(b, &op_b, SINGLE);
+	if ((a_type >= NaN && a_type <= ZERO) ||
+	    (b_type >= NaN && b_type <= ZERO))
+	{
+		unsigned long res;
+
+		/* propagate NaNs according to arch. ref. handbook: */
+		if (b_type == QNaN)
+			*c = b;
+		else if (b_type == NaN)
+			*c = b | (1UL << 51);
+		else if (a_type == QNaN)
+			*c = a;
+		else if (a_type == NaN)
+			*c = a | (1UL << 51);
+
+		if (a_type == NaN || b_type == NaN)
+			return FPCR_INV;
+		if (a_type == QNaN || b_type == QNaN)
+			return 0;
+
+		res = 0;
+		*c = IEEE_PINF;
+		if (a_type == INFTY) {
+			if (b_type == INFTY) {
+				*c = IEEE_QNaN;
+				return FPCR_INV;
+			}
+		} else if (b_type == ZERO) {
+			if (a_type == ZERO) {
+				*c = IEEE_QNaN;
+				return FPCR_INV;
+			}
+			res = FPCR_DZE;
+		} else
+			/* a_type == ZERO || b_type == INFTY */
+			*c = 0;
+		*c |= (unsigned long) (op_a.s ^ op_b.s) << 63;
+		return res;
+	}
+	op_c.s = op_a.s ^ op_b.s;
+	op_c.e = op_a.e - op_b.e;
+
+	op_a.f[1] = op_a.f[0];
+	op_a.f[0] = 0;
+	div128(op_a.f, op_b.f, op_c.f);
+	if (a_type != ZERO)
+		/* force a sticky bit because DIVs never hit exact .5: */
+		op_c.f[0] |= STICKY_S;
+	normalize(&op_c);
+	op_c.e -= 9;		/* remove excess exp from original shift */
+	return round_s_ieee(f, &op_c, c);
+}
+
+
+/*
+ * Divide a/b = c, where a, b, and c are ieee t-floating numbers.  "f"
+ * contains the rounding mode etc.
+ */
+unsigned long
+ieee_DIVT (int f, unsigned long a, unsigned long b, unsigned long *c)
+{
+	fpclass_t a_type, b_type;
+	EXTENDED op_a, op_b, op_c;
+
+	*c = IEEE_QNaN;
+	a_type = extend_ieee(a, &op_a, DOUBLE);
+	b_type = extend_ieee(b, &op_b, DOUBLE);
+	if ((a_type >= NaN && a_type <= ZERO) ||
+	    (b_type >= NaN && b_type <= ZERO))
+	{
+		unsigned long res;
+
+		/* propagate NaNs according to arch. ref. handbook: */
+		if (b_type == QNaN)
+			*c = b;
+		else if (b_type == NaN)
+			*c = b | (1UL << 51);
+		else if (a_type == QNaN)
+			*c = a;
+		else if (a_type == NaN)
+			*c = a | (1UL << 51);
+
+		if (a_type == NaN || b_type == NaN)
+			return FPCR_INV;
+		if (a_type == QNaN || b_type == QNaN)
+			return 0;
+
+		res = 0;
+		*c = IEEE_PINF;
+		if (a_type == INFTY) {
+			if (b_type == INFTY) {
+				*c = IEEE_QNaN;
+				return FPCR_INV;
+			}
+		} else if (b_type == ZERO) {
+			if (a_type == ZERO) {
+				*c = IEEE_QNaN;
+				return FPCR_INV;
+			}
+			res = FPCR_DZE;
+		} else
+			/* a_type == ZERO || b_type == INFTY */
+			*c = 0;
+		*c |= (unsigned long) (op_a.s ^ op_b.s) << 63;
+		return res;
+	}
+	op_c.s = op_a.s ^ op_b.s;
+	op_c.e = op_a.e - op_b.e;
+
+	op_a.f[1] = op_a.f[0];
+	op_a.f[0] = 0;
+	div128(op_a.f, op_b.f, op_c.f);
+	if (a_type != ZERO)
+		/* force a sticky bit because DIVs never hit exact .5 */
+		op_c.f[0] |= STICKY_T;
+	normalize(&op_c);
+	op_c.e -= 9;		/* remove excess exp from original shift */
+	return round_t_ieee(&op_c, c, f);
+}
diff -u --recursive --new-file v1.3.49/linux/arch/alpha/math-emu/ieee-math.h linux/arch/alpha/math-emu/ieee-math.h
--- v1.3.49/linux/arch/alpha/math-emu/ieee-math.h	Thu Jan  1 02:00:00 1970
+++ linux/arch/alpha/math-emu/ieee-math.h	Fri Dec 22 08:22:05 1995
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 1992,1995 by
+ * Digital Equipment Corporation, Maynard, Massachusetts.
+ * This file may be redistributed according to the terms of the
+ * GNU General Public License.
+ */
+#ifndef __ieee_math_h__
+#define __ieee_math_h__
+
+#include <asm/fpu.h>
+
+#define ROUND_SHIFT	6		/* make space for trap-enable bits */
+#define RM(f)		(((f) >> ROUND_SHIFT) & 0x3)
+
+#define ROUND_CHOP 	(FPCR_DYN_CHOPPED >> FPCR_DYN_SHIFT)
+#define ROUND_NINF 	(FPCR_DYN_MINUS   >> FPCR_DYN_SHIFT)
+#define ROUND_NEAR 	(FPCR_DYN_NORMAL  >> FPCR_DYN_SHIFT)
+#define ROUND_PINF 	(FPCR_DYN_PLUS    >> FPCR_DYN_SHIFT)
+
+extern unsigned long ieee_CVTST (int rm, unsigned long a, unsigned long *b);
+extern unsigned long ieee_CVTTS (int rm, unsigned long a, unsigned long *b);
+extern unsigned long ieee_CVTQS (int rm, unsigned long a, unsigned long *b);
+extern unsigned long ieee_CVTQT (int rm, unsigned long a, unsigned long *b);
+extern unsigned long ieee_CVTTQ (int rm, unsigned long a, unsigned long *b);
+
+extern unsigned long ieee_CMPTEQ (unsigned long a, unsigned long b,
+				  unsigned long *c);
+extern unsigned long ieee_CMPTLT (unsigned long a, unsigned long b,
+				  unsigned long *c);
+extern unsigned long ieee_CMPTLE (unsigned long a, unsigned long b,
+				  unsigned long *c);
+extern unsigned long ieee_CMPTUN (unsigned long a, unsigned long b,
+				  unsigned long *c);
+
+extern unsigned long ieee_ADDS (int rm, unsigned long a, unsigned long b,
+				unsigned long *c);
+extern unsigned long ieee_ADDT (int rm, unsigned long a, unsigned long b,
+				unsigned long *c);
+extern unsigned long ieee_SUBS (int rm, unsigned long a, unsigned long b,
+				unsigned long *c);
+extern unsigned long ieee_SUBT (int rm, unsigned long a, unsigned long b,
+				unsigned long *c);
+extern unsigned long ieee_MULS (int rm, unsigned long a, unsigned long b,
+				unsigned long *c);
+extern unsigned long ieee_MULT (int rm, unsigned long a, unsigned long b,
+				unsigned long *c);
+extern unsigned long ieee_DIVS (int rm, unsigned long a, unsigned long b,
+				unsigned long *c);
+extern unsigned long ieee_DIVT (int rm, unsigned long a, unsigned long b,
+				unsigned long *c);
+
+#endif /* __ieee_math_h__ */
diff -u --recursive --new-file v1.3.49/linux/arch/alpha/mm/fault.c linux/arch/alpha/mm/fault.c
--- v1.3.49/linux/arch/alpha/mm/fault.c	Sun Dec 17 11:43:09 1995
+++ linux/arch/alpha/mm/fault.c	Fri Dec 22 08:22:05 1995
@@ -87,7 +87,8 @@
  * Oops. The kernel tried to access some bad page. We'll have to
  * terminate things with extreme prejudice.
  */
-	printk(KERN_ALERT "Unable to handle kernel paging request at virtual address %08lx\n",address);
+	printk(KERN_ALERT 
+	       "Unable to handle kernel paging request at virtual address %016lx\n", address);
 	die_if_kernel("Oops", &regs, cause);
 	do_exit(SIGKILL);
 }
diff -u --recursive --new-file v1.3.49/linux/arch/i386/defconfig linux/arch/i386/defconfig
--- v1.3.49/linux/arch/i386/defconfig	Wed Dec 13 09:02:45 1995
+++ linux/arch/i386/defconfig	Fri Dec 22 08:58:48 1995
@@ -24,6 +24,7 @@
 # block devices
 #
 CONFIG_BLK_DEV_FD=y
+# CONFIG_BLK_DEV_RAM is not set
 CONFIG_ST506=y
 
 #
diff -u --recursive --new-file v1.3.49/linux/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c
--- v1.3.49/linux/arch/i386/kernel/setup.c	Thu Dec 21 08:53:30 1995
+++ linux/arch/i386/kernel/setup.c	Fri Dec 22 08:51:07 1995
@@ -62,9 +62,13 @@
 #endif
 
 unsigned char aux_device_present;
+
+#ifdef CONFIG_BLK_DEV_RAM
 extern int rd_doload;		/* 1 = load ramdisk, 0 = don't load */
 extern int rd_prompt;		/* 1 = prompt for ramdisk, 0 = don't prompt */
 extern int rd_image_start;	/* starting block # of image */
+#endif
+
 extern int root_mountflags;
 extern int _etext, _edata, _end;
 
@@ -92,6 +96,7 @@
 #define RAMDISK_LOAD_FLAG		0x4000	
 
 static char command_line[COMMAND_LINE_SIZE] = { 0, };
+       char saved_command_line[COMMAND_LINE_SIZE];
 
 void setup_arch(char **cmdline_p,
 	unsigned long * memory_start_p, unsigned long * memory_end_p)
@@ -116,9 +121,11 @@
 	aux_device_present = AUX_DEVICE_INFO;
 	memory_end = (1<<20) + (EXT_MEM_K<<10);
 	memory_end &= PAGE_MASK;
+#ifdef CONFIG_BLK_DEV_RAM
 	rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK;
 	rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0);
 	rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
+#endif
 #ifdef CONFIG_MAX_16M
 	if (memory_end > 16*1024*1024)
 		memory_end = 16*1024*1024;
@@ -130,6 +137,10 @@
 	init_task.mm->end_code = TASK_SIZE + (unsigned long) &_etext;
 	init_task.mm->end_data = TASK_SIZE + (unsigned long) &_edata;
 	init_task.mm->brk = TASK_SIZE + (unsigned long) &_end;
+
+	/* Save unparsed command line copy for /proc/cmdline */
+	memcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
+	saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
 
 	for (;;) {
 		/*
diff -u --recursive --new-file v1.3.49/linux/arch/mips/kernel/setup.c linux/arch/mips/kernel/setup.c
--- v1.3.49/linux/arch/mips/kernel/setup.c	Sun Dec 17 11:43:11 1995
+++ linux/arch/mips/kernel/setup.c	Thu Dec 21 12:05:17 1995
@@ -216,6 +216,7 @@
 #endif
 
 static char command_line[CL_SIZE] = { 0, };
+       char saved_command_line[CL_SIZE];
 
 #if 0
 /*
@@ -306,6 +307,9 @@
 
 	memory_start = (unsigned long) &_end;
 	memory_start += (ramdisk_size << 10);
+
+	memcpy(saved_command_line, command_line, CL_SIZE);
+	saved_command_line[CL_SIZE-1] = '\0';
 
 	*cmdline_p = command_line;
 	*memory_start_p = memory_start;
diff -u --recursive --new-file v1.3.49/linux/arch/ppc/kernel/setup.c linux/arch/ppc/kernel/setup.c
--- v1.3.49/linux/arch/ppc/kernel/setup.c	Mon Nov 27 12:48:26 1995
+++ linux/arch/ppc/kernel/setup.c	Thu Dec 21 12:05:18 1995
@@ -134,6 +134,9 @@
 
 #define DEFAULT_ROOT_DEVICE 0x0200	/* fd0 */
 
+#define COMMAND_LINE_SIZE 512	/* Should match head.S */
+char saved_command_line[COMMAND_LINE_SIZE];
+
 void setup_arch(char **cmdline_p,
 	unsigned long * memory_start_p, unsigned long * memory_end_p)
 {
@@ -143,6 +146,7 @@
 
 	ROOT_DEV = DEFAULT_ROOT_DEVICE;
 	aux_device_present = 0xaa;
+	strcpy(saved_command_line, cmd_line);
 	*cmdline_p = cmd_line;
 	*memory_start_p = (unsigned long) &_end;
 	*memory_end_p = (unsigned long *)Hash;
diff -u --recursive --new-file v1.3.49/linux/arch/sparc/kernel/setup.c linux/arch/sparc/kernel/setup.c
--- v1.3.49/linux/arch/sparc/kernel/setup.c	Sat Nov 25 19:04:36 1995
+++ linux/arch/sparc/kernel/setup.c	Thu Dec 21 12:05:17 1995
@@ -153,6 +153,7 @@
 
 
 char sparc_command_line[256];  /* Should be enough */
+char saved_command_line[256];
 enum sparc_cpu sparc_cpu_model;
 
 struct tt_entry *sparc_ttable;
@@ -166,6 +167,7 @@
 
 	/* Initialize PROM console and command line. */
 	*cmdline_p = prom_getbootargs();
+	strcpy(saved_command_line, *cmdline_p);
 
 	/* Set sparc_cpu_model */
 	sparc_cpu_model = sun_unknown;
diff -u --recursive --new-file v1.3.49/linux/drivers/block/Config.in linux/drivers/block/Config.in
--- v1.3.49/linux/drivers/block/Config.in	Mon Dec 11 15:42:00 1995
+++ linux/drivers/block/Config.in	Fri Dec 22 08:51:07 1995
@@ -5,6 +5,7 @@
 comment 'block devices'
 
 tristate 'Normal floppy disk support' CONFIG_BLK_DEV_FD
+bool 'RAM disk support' CONFIG_BLK_DEV_RAM
 bool 'Normal (MFM/RLL) disk and IDE disk/cdrom support' CONFIG_ST506
 if [ "$CONFIG_ST506" = "y" ]; then
   comment 'Please see drivers/block/README.ide for help/info on IDE drives'
diff -u --recursive --new-file v1.3.49/linux/drivers/block/Makefile linux/drivers/block/Makefile
--- v1.3.49/linux/drivers/block/Makefile	Sun Dec 17 11:43:11 1995
+++ linux/drivers/block/Makefile	Fri Dec 22 08:51:07 1995
@@ -16,7 +16,7 @@
 
 
 L_TARGET := block.a
-L_OBJS   := ll_rw_blk.o rd.o genhd.o 
+L_OBJS   := ll_rw_blk.o genhd.o 
 M_OBJS   :=
 MOD_LIST_NAME := BLOCK_MODULES
 
@@ -26,6 +26,10 @@
   ifeq ($(CONFIG_BLK_DEV_FD),m)
   M_OBJS += floppy.o
   endif
+endif
+
+ifeq ($(CONFIG_BLK_DEV_RAM),y)
+L_OBJS += rd.o
 endif
 
 ifeq ($(CONFIG_BLK_DEV_HD),y)
diff -u --recursive --new-file v1.3.49/linux/drivers/block/floppy.c linux/drivers/block/floppy.c
--- v1.3.49/linux/drivers/block/floppy.c	Mon Nov 27 12:48:28 1995
+++ linux/drivers/block/floppy.c	Thu Dec 21 12:05:36 1995
@@ -3479,6 +3479,7 @@
 		if (floppy_track_buffer){
 			free_pages((unsigned long)tmp,__get_order(try*1024));
 		}else {
+			buffer_min = buffer_max = -1;
 			floppy_track_buffer = tmp;
 			max_buffer_sectors = try;
 		}
@@ -3955,6 +3956,7 @@
 		tmpaddr = (void *)floppy_track_buffer;
 		floppy_track_buffer = 0;
 		max_buffer_sectors = 0;
+		buffer_min = buffer_max = -1;
 		free_pages((unsigned long)tmpaddr, __get_order(tmpsize));
 	}
 
diff -u --recursive --new-file v1.3.49/linux/drivers/block/genhd.c linux/drivers/block/genhd.c
--- v1.3.49/linux/drivers/block/genhd.c	Sun Dec 17 11:43:12 1995
+++ linux/drivers/block/genhd.c	Fri Dec 22 08:51:07 1995
@@ -25,6 +25,22 @@
 
 #include <asm/system.h>
 
+#ifdef __alpha__
+/*
+ * On the Alpha, we get unaligned access exceptions on
+ *  p->nr_sects and p->start_sect, when the partition table
+ *  is not on a 4-byte boundary, which is frequently the case.
+ * This code uses unaligned load instructions to prevent
+ *  such exceptions.
+ */
+#include <asm/unaligned.h>
+#define NR_SECTS(p)	ldl_u(&p->nr_sects)
+#define START_SECT(p)	ldl_u(&p->start_sect)
+#else /* __alpha__ */
+#define NR_SECTS(p)	p->nr_sects
+#define START_SECT(p)	p->start_sect
+#endif /* __alpha__ */
+
 struct gendisk *gendisk_head = NULL;
 
 static int current_minor = 0;
@@ -130,19 +146,19 @@
 		 * First process the data partition(s)
 		 */
 		for (i=0; i<4; i++, p++) {
-		    if (!p->nr_sects || is_extended_partition(p))
+		    if (!NR_SECTS(p) || is_extended_partition(p))
 		      continue;
 
 		    /* Check the 3rd and 4th entries -
 		       these sometimes contain random garbage */
 		    if (i >= 2
-			&& p->start_sect + p->nr_sects > this_size
-			&& (this_sector + p->start_sect < first_sector ||
-			    this_sector + p->start_sect + p->nr_sects >
+			&& START_SECT(p) + NR_SECTS(p) > this_size
+			&& (this_sector + START_SECT(p) < first_sector ||
+			    this_sector + START_SECT(p) + NR_SECTS(p) >
 			     first_sector + first_size))
 		      continue;
 
-		    add_partition(hd, current_minor, this_sector+p->start_sect, p->nr_sects);
+		    add_partition(hd, current_minor, this_sector+START_SECT(p), NR_SECTS(p));
 		    current_minor++;
 		    if ((current_minor & mask) == 0)
 		      goto done;
@@ -159,14 +175,14 @@
 		 */
 		p -= 4;
 		for (i=0; i<4; i++, p++)
-		  if(p->nr_sects && is_extended_partition(p))
+		  if(NR_SECTS(p) && is_extended_partition(p))
 		    break;
 		if (i == 4)
 		  goto done;	 /* nothing left to do */
 
-		hd->part[current_minor].nr_sects = p->nr_sects;
-		hd->part[current_minor].start_sect = first_sector + p->start_sect;
-		this_sector = first_sector + p->start_sect;
+		hd->part[current_minor].nr_sects = NR_SECTS(p);
+		hd->part[current_minor].start_sect = first_sector + START_SECT(p);
+		this_sector = first_sector + START_SECT(p);
 		dev = MKDEV(hd->major, current_minor);
 		brelse(bh);
 	}
@@ -262,9 +278,9 @@
 
 	current_minor += 4;  /* first "extra" minor (for extended partitions) */
 	for (i=1 ; i<=4 ; minor++,i++,p++) {
-		if (!p->nr_sects)
+		if (!NR_SECTS(p))
 			continue;
-		add_partition(hd, minor, first_sector+p->start_sect, p->nr_sects);
+		add_partition(hd, minor, first_sector+START_SECT(p), NR_SECTS(p));
 		if (is_extended_partition(p)) {
 			printk(" <");
 			/*
@@ -292,9 +308,9 @@
 			p--;
 			if ((current_minor & mask) == 0)
 				break;
-			if (!(p->start_sect && p->nr_sects))
+			if (!(START_SECT(p) && NR_SECTS(p)))
 				continue;
-			add_partition(hd, current_minor, p->start_sect, p->nr_sects);
+			add_partition(hd, current_minor, START_SECT(p), NR_SECTS(p));
 		}
 	}
 	printk("\n");
@@ -558,5 +574,7 @@
 		nr += p->nr_real;
 	}
 
+#ifdef CONFIG_BLK_DEV_RAM
 	rd_load();
+#endif
 }
diff -u --recursive --new-file v1.3.49/linux/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c
--- v1.3.49/linux/drivers/block/ll_rw_blk.c	Sun Dec 17 11:43:12 1995
+++ linux/drivers/block/ll_rw_blk.c	Fri Dec 22 08:51:07 1995
@@ -623,7 +623,9 @@
 		req->next = NULL;
 	}
 	memset(ro_bits,0,sizeof(ro_bits));
+#ifdef CONFIG_BLK_DEV_RAM
 	rd_init();
+#endif
 #ifdef CONFIG_BLK_DEV_IDE
 	ide_init();		/* this MUST preceed hd_init */
 #endif
diff -u --recursive --new-file v1.3.49/linux/drivers/block/rd.c linux/drivers/block/rd.c
--- v1.3.49/linux/drivers/block/rd.c	Sun Dec 17 11:43:13 1995
+++ linux/drivers/block/rd.c	Fri Dec 22 21:21:01 1995
@@ -70,8 +70,6 @@
 int rd_prompt = 1;		/* 1 = prompt for ramdisk, 0 = don't prompt */
 int rd_image_start = 0;		/* starting block # of image */
 
-int rd_loading = 0;
-
 /*
  *  Basically, my strategy here is to set up a buffer-head which can't be
  *  deleted, and make that my Ramdisk.  If the request is outside of the
@@ -253,7 +251,6 @@
 	}
 
 	/* Try ext2 */
-	printk("ext2 magic = %d\n", ext2sb->s_magic);
 	if (ext2sb->s_magic == EXT2_SUPER_MAGIC) {
 		printk(KERN_NOTICE
 		       "RAMDISK: Ext2 filesystem found at block %d\n",
@@ -296,6 +293,8 @@
 	int device, ram_device;
 	int nblocks, i;
 	char *buf;
+	unsigned short rotate = 0;
+	char rotator[4] = { '|' , '/' , '-' , '\\' };
 
 	if (rd_doload == 0)
 		return;
@@ -328,7 +327,6 @@
 
 	fs = get_fs();
 	set_fs(KERNEL_DS);
-	rd_loading = 1;
 	
 	nblocks = identify_ramdisk_image(device, &infile, rd_image_start);
 	if (nblocks < 0)
@@ -360,12 +358,19 @@
 		printk(KERN_ERR "RAMDISK: could not allocate buffer\n");
 		goto done;
 	}
+
+	printk(KERN_NOTICE "RAMDISK: Loading %d blocks into ram disk... ", nblocks);
 	for (i=0; i < nblocks; i++) {
 		infile.f_op->read(infile.f_inode, &infile, buf,
 				  BLOCK_SIZE);
 		outfile.f_op->write(outfile.f_inode, &outfile, buf,
 				    BLOCK_SIZE);
+		if (!(i % 16)) {
+			printk("%c\b", rotator[rotate & 0x3]);
+			rotate++;
+		}
 	}
+	printk("done.\n");
 	kfree(buf);
 
 successful_load:
@@ -376,12 +381,9 @@
 	if (infile.f_op->release)
 		infile.f_op->release(&inode, &infile);
 	set_fs(fs);
-	rd_loading = 0;
 }
 
 #ifdef BUILD_CRAMDISK
-
-#include <string.h>
 
 /*
  * gzip declarations
diff -u --recursive --new-file v1.3.49/linux/drivers/char/console.c linux/drivers/char/console.c
--- v1.3.49/linux/drivers/char/console.c	Mon Dec 11 15:42:02 1995
+++ linux/drivers/char/console.c	Fri Dec 22 08:51:07 1995
@@ -1874,6 +1874,10 @@
 			if (c == 10 || c == 13)
 				continue;
 		}
+		if (c == 8) {		/* backspace */
+			bs(currcons);
+			continue;
+		}
 		scr_writew((attr << 8) + c, (unsigned short *) pos);
 		if (x == video_num_columns - 1) {
 			need_wrap = 1;
diff -u --recursive --new-file v1.3.49/linux/drivers/net/depca.c linux/drivers/net/depca.c
--- v1.3.49/linux/drivers/net/depca.c	Sat Nov 25 19:04:45 1995
+++ linux/drivers/net/depca.c	Fri Dec 22 08:22:05 1995
@@ -696,20 +696,20 @@
       printk("\nDescriptor buffers:\nRX: ");
       for (i=0;i<lp->rxRingMask;i++){
 	if (i < 3) {
-	  printk("0x%8.8x  ", readl(&lp->rx_ring[i].base));
+	  printk("0x%8.8lx  ", readl(&lp->rx_ring[i].base));
 	}
       }
-      printk("...0x%8.8x\n", readl(&lp->rx_ring[i].base));
+      printk("...0x%8.8lx\n", readl(&lp->rx_ring[i].base));
       printk("TX: ");
       for (i=0;i<lp->txRingMask;i++){
 	if (i < 3) {
-	  printk("0x%8.8x  ", readl(&lp->tx_ring[i].base));
+	  printk("0x%8.8lx  ", readl(&lp->tx_ring[i].base));
 	}
       }
-      printk("...0x%8.8x\n", readl(&lp->tx_ring[i].base));
+      printk("...0x%8.8lx\n", readl(&lp->tx_ring[i].base));
       printk("Status:  %d\n", status);
       printk("Initialisation block at 0x%8.8lx\n",lp->sh_mem);
-      printk("\tmode: 0x%4.4x\n",readw(&p->mode));
+      printk("\tmode: 0x%4.4lx\n",readw(&p->mode));
       printk("\tphysical address: ");
       for (i=0;i<ETH_ALEN-1;i++){
 	printk("%2.2x:",(u_char)readb(&p->phys_addr[i]));
@@ -720,8 +720,8 @@
 	printk("%2.2x:",(u_char)readb(&p->mcast_table[i]));
       }
       printk("%2.2x\n",(u_char)readb(&p->mcast_table[i]));
-      printk("\trx_ring at: 0x%8.8x\n",readl(&p->rx_ring));
-      printk("\ttx_ring at: 0x%8.8x\n",readl(&p->tx_ring));
+      printk("\trx_ring at: 0x%8.8lx\n",readl(&p->rx_ring));
+      printk("\ttx_ring at: 0x%8.8lx\n",readl(&p->tx_ring));
       printk("dma_buffs: 0x%8.8lx\n",lp->dma_buffs);
       printk("Ring size:\nRX: %d  Log2(rxRingMask): 0x%8.8x\n", 
                                           (int)lp->rxRingMask + 1, 
diff -u --recursive --new-file v1.3.49/linux/drivers/pci/pci.c linux/drivers/pci/pci.c
--- v1.3.49/linux/drivers/pci/pci.c	Thu Dec 21 08:53:31 1995
+++ linux/drivers/pci/pci.c	Thu Dec 21 12:08:47 1995
@@ -96,8 +96,8 @@
 	DEVICE( OPTI,		OPTI_82C558,	"82C558"),
 	DEVICE( OPTI,		OPTI_82C621,	"82C621"),
 	DEVICE( OPTI,		OPTI_82C822,	"82C822"),
-	DEVICE( BUSLOGIC,	BUSLOGIC_946C_2,"946C"),
-	DEVICE( BUSLOGIC,	BUSLOGIC_946C,	"946C"),
+	DEVICE( BUSLOGIC,	BUSLOGIC_946C_2,"BT-946C"),
+	DEVICE( BUSLOGIC,	BUSLOGIC_946C,	"BT-946C"),
 	DEVICE( BUSLOGIC,	BUSLOGIC_930,	"BT-930"),
 	DEVICE( PROMISE,	PROMISE_5300,	"DC5030"),
 	DEVICE( N9,		N9_I128,	"Imagine 128"),
diff -u --recursive --new-file v1.3.49/linux/drivers/scsi/53c7,8xx.c linux/drivers/scsi/53c7,8xx.c
--- v1.3.49/linux/drivers/scsi/53c7,8xx.c	Thu Dec 21 08:53:32 1995
+++ linux/drivers/scsi/53c7,8xx.c	Fri Dec 22 09:14:59 1995
@@ -1323,6 +1323,11 @@
     /* Initialize single command */
     hostdata->free = (struct NCR53c7x0_cmd *) 
 	(hostdata->script + hostdata->script_count);
+/* 
+ * FIXME: This is wrong.  If we add max_cmd_size to hostdata->free
+ * once it's been rounded up, we end up going past the end of what 
+ * we allocated.
+ */
     hostdata->free = ROUNDUP(hostdata->free, void *);
     hostdata->free->real = (void *) hostdata->free;
     hostdata->free->size = max_cmd_size;
@@ -3369,23 +3374,18 @@
 
     /* Enable active negation */
     NCR53c7x0_write8(STEST3_REG_800, STEST3_800_TE);
-
-    
 }
 
 
 /*
  * Function static struct NCR53c7x0_cmd *allocate_cmd (Scsi_Cmnd *cmd)
  * 
- * Purpose : If we have not already allocated enough NCR53c7x0_cmd
- *	structures to satisfy any allowable number of simultaneous 
- *	commands for this host; do so (using either scsi_malloc()
- *	or kmalloc() depending on configuration), and add them to the 
- *	free list.
- *
- *	Return the first free NCR53c7x0_cmd structure (which are 
+ * Purpose : Return the first free NCR53c7x0_cmd structure (which are 
  * 	reused in a LIFO maner to minimize cache thrashing).
  *
+ * Side effects : If we don't have enough NCR53c7x0_cmd structures,
+ *	allocate more.  Teach programmers not to drink and hack.
+ *
  * Inputs : cmd - SCSI command
  *
  * Returns : NCR53c7x0_cmd structure allocated on behalf of cmd;
@@ -3399,8 +3399,7 @@
 	(struct NCR53c7x0_hostdata *) host->hostdata;
     void *real;			/* Real address */
     int size;			/* Size of *tmp */
-    int i;
-    struct NCR53c7x0_cmd *tmp = NULL;
+    struct NCR53c7x0_cmd *tmp;
     unsigned long flags;
 
     if (hostdata->options & OPTION_DEBUG_ALLOCATION)
@@ -3409,92 +3408,57 @@
 	    host->host_no, hostdata->num_cmds, host->can_queue,
 	    cmd->target, cmd->lun, (hostdata->cmd_allocated[cmd->target] &
 		(1 << cmd->lun)) ? "allready allocated" : "not allocated");
-	    
 
-    if (hostdata->num_cmds < host->can_queue &&
+/* 
+ * Under Linux 1.2.x, kmalloc() and friends are unavailable until after 
+ * device driver initialization has happened.  Calling kmalloc()
+ * during scsi device initialization will print a "cannot get free page"
+ * message.  To avoid too many of these, we'll forget about trying 
+ * to allocate command structures until AFTER initialization.
+ */
 #ifdef LINUX_1_2
-	!in_scan_scsis &&
+    if (!in_scan_scsis)
 #endif
-	(hostdata->extra_allocate ||
-    	    !(hostdata->cmd_allocated[cmd->target] & (1 << cmd->lun)))) {
-	
-    	for (i = !(hostdata->cmd_allocated[cmd->target] & (1 << cmd->lun)) ?
-		(host->hostt->cmd_per_lun - 1) : -1;
-	    (hostdata->extra_allocate || i >= 0) && hostdata->num_cmds 
-		< host->can_queue ;
-	    (hostdata->extra_allocate ? --hostdata->extra_allocate : --i), 
-		++hostdata->num_cmds) {
-
-	    if (hostdata->options & OPTION_SCSI_MALLOC) {
-    /* scsi_malloc must allocate with a 512 byte granularity, but always
-       returns buffers which are aligned on a 512 boundary */
-	    	size = (hostdata->max_cmd_size + 511) / 512 * 512;
-	    	tmp = (struct NCR53c7x0_cmd *) scsi_malloc (size);
-	    	if (!tmp) {
-		    if (hostdata->options & OPTION_DEBUG_ALLOCATION)
-			printk ("scsi%d : scsi_malloc(%d) failed\n",
-			    host->host_no, size);
-		    break;
-		}
-	    	tmp->real = (void *) tmp; 
-		tmp->free = ((void (*)(void *, int)) scsi_free); 
-	    } else {
+    for (; hostdata->extra_allocate > 0 ; --hostdata->extra_allocate, 
+    	++hostdata->num_cmds) {
     /* kmalloc() can allocate any size, but historically has returned 
        unaligned addresses, so we need to allow for alignment */
-		size = hostdata->max_cmd_size + sizeof (void *);
-		real = kmalloc (size, GFP_ATOMIC);
-		if (!real) {
-		    if (hostdata->options & OPTION_DEBUG_ALLOCATION)
-			printk ("scsi%d : kmalloc(%d) failed\n",
-			    host->host_no, size);
-		    break;
-		}
-		tmp = ROUNDUP(real, void *);
-		tmp->real = real;
-		tmp->size = size;			
+	size = hostdata->max_cmd_size + sizeof (void *);
+/* FIXME: for ISA bus '7xx chips, we need to or GFP_DMA in here */
+	real = kmalloc (size, GFP_ATOMIC);
+	if (!real) {
+	    if (hostdata->options & OPTION_DEBUG_ALLOCATION)
+		printk ("scsi%d : kmalloc(%d) failed\n",
+		    host->host_no, size);
+	    break;
+	}
+	tmp = ROUNDUP(real, void *);
+	tmp->real = real;
+	tmp->size = size;			
 #ifdef LINUX_1_2
-		tmp->free = ((void (*)(void *, int)) kfree_s);
+	tmp->free = ((void (*)(void *, int)) kfree_s);
 #else
-		tmp->free = ((void (*)(void *, int)) kfree);
+	tmp->free = ((void (*)(void *, int)) kfree);
 #endif
-	    }
-
-
-	    if (!hostdata->extra_allocate) 
-		hostdata->cmd_allocated[cmd->target] |= 1 << cmd->lun;
-
-    /* Keep the last one out of the free list so we can use it now */
-	    if (i > 0) {
-		save_flags (flags);
-		cli();
-		tmp->next = hostdata->free;
-		hostdata->free = tmp;
-		restore_flags (flags);
-	    }
-	}
-    /* If for some reason, our allocation attempt failed here, we'll
-	try again later */
-	if (i >= 0) 
-	    hostdata->extra_allocate += i + 1;
+	save_flags (flags);
+	cli();
+	tmp->next = hostdata->free;
+	hostdata->free = tmp;
+	restore_flags (flags);
     }
-
-    if (!tmp) {
-    	save_flags(flags);
-    	cli();
-    	tmp = (struct NCR53c7x0_cmd *) hostdata->free;
-	if (tmp) {
-    	    hostdata->free = tmp->next;
-	    restore_flags(flags);
-    	}
-	restore_flags(flags);
+    save_flags(flags);
+    cli();
+    tmp = (struct NCR53c7x0_cmd *) hostdata->free;
+    if (tmp) {
+	hostdata->free = tmp->next;
     }
+    restore_flags(flags);
     if (!tmp)
 	printk ("scsi%d : can't allocate command for target %d lun %d\n",
 	    host->host_no, cmd->target, cmd->lun);
     return tmp;
 }
 
-
 /*
  * Function static struct NCR53c7x0_cmd *create_cmd (Scsi_Cmnd *cmd) 
  *
@@ -4486,6 +4450,25 @@
 #if 0
 			hostdata->options &= ~OPTION_DEBUG_INTR;
 #endif
+
+/*
+ * If we have not yet reserved commands for this I_T_L nexus, and the 
+ * command completed successfully, reserve NCR53c7x0_cmd structures
+ * which will be allocated the next time we run the allocate
+ * routine.
+ */
+			if (!(hostdata->cmd_allocated[tmp->target] &
+			    	(1 << tmp->lun)) && 
+			    status_byte(tmp->result) == GOOD) {
+			    if ((hostdata->extra_allocate + hostdata->num_cmds)
+			    	< host->can_queue) {
+				hostdata->extra_allocate += 
+				    host->cmd_per_lun;
+			    }
+			    hostdata->cmd_allocated[tmp->target] |=
+				(1 << tmp->lun);
+			}
+
 			tmp->scsi_done(tmp);
 			goto restart;
 
diff -u --recursive --new-file v1.3.49/linux/drivers/scsi/53c7,8xx.h linux/drivers/scsi/53c7,8xx.h
--- v1.3.49/linux/drivers/scsi/53c7,8xx.h	Thu Dec 21 08:53:32 1995
+++ linux/drivers/scsi/53c7,8xx.h	Fri Dec 22 09:14:58 1995
@@ -67,7 +67,7 @@
 #endif
 
 #ifdef LINUX_1_2
-#define NCR53c7xx {NULL, NULL, "NCR53c{7,8}xx (rel 13)", NCR53c7xx_detect,\
+#define NCR53c7xx {NULL, NULL, "NCR53c{7,8}xx (rel 14)", NCR53c7xx_detect,\
 	NULL, /* info */ NULL, /* command, deprecated */ NULL, 		\
 	NCR53c7xx_queue_command, NCR53c7xx_abort, NCR53c7xx_reset,	\
 	NULL /* slave attach */, scsicam_bios_param, /* can queue */ 24, \
@@ -75,7 +75,7 @@
 	/* present */ 0, /* unchecked isa dma */ 0, DISABLE_CLUSTERING} 
 #else
 #define NCR53c7xx {NULL, NULL, NULL, NULL, \
-        "NCR53c{7,8}xx (rel 13)", NCR53c7xx_detect,\
+        "NCR53c{7,8}xx (rel 14)", NCR53c7xx_detect,\
         NULL, /* info */ NULL, /* command, deprecated */ NULL,		\
 	NCR53c7xx_queue_command, NCR53c7xx_abort, NCR53c7xx_reset,	\
 	NULL /* slave attach */, scsicam_bios_param, /* can queue */ 24, \
@@ -985,10 +985,6 @@
 #define OPTION_DEBUG_DISCONNECT 0x10000000	
 #define OPTION_ALWAYS_SYNCHRONOUS 0x20000000	/* Negotiate sync. transfers
 						   on power up */
-#define OPTION_SCSI_MALLOC	0x40000000	/* Use scsi_malloc instead of
-						   kmalloc() to allocate NCR
-						   command structures after 
-						   boot */
 #define OPTION_DEBUG_QUEUES	0x80000000	
 #define OPTION_DEBUG_ALLOCATION 0x100000000LL
 #define OPTION_DEBUG_SYNCHRONOUS 0x200000000LL	/* Sanity check SXFER and 
@@ -1207,7 +1203,6 @@
 struct NCR53c7x0_hostdata {
     int size;				/* Size of entire Scsi_Host
 					   structure */
-    struct Scsi_Host *next;		/* next of this type */
     int board;				/* set to board type, useful if 
 					   we have host specific things,
 					   ie, a general purpose I/O 
@@ -1452,6 +1447,9 @@
     volatile u16 initiate_wdtr;
     /* Bit fielded list of targets we've talked to. */
     volatile u16 talked_to;
+    /* Bit fielded list of targets that answered */
+    volatile u16 answered;
+
     /* Array of bit-fielded lun lists that we need to request_sense */
     volatile unsigned char request_sense[16];
 
diff -u --recursive --new-file v1.3.49/linux/drivers/scsi/Makefile linux/drivers/scsi/Makefile
--- v1.3.49/linux/drivers/scsi/Makefile	Sun Dec 17 11:43:18 1995
+++ linux/drivers/scsi/Makefile	Fri Dec 22 08:22:05 1995
@@ -269,7 +269,7 @@
 	$(CC) $(CFLAGS) -g -c 53c7,8xx.c
 
 53c8xx_d.h 53c8xx_u.h : 53c7,8xx.scr script_asm.pl
-	ln 53c7,8xx.scr fake.c
+	ln -sf 53c7,8xx.scr fake.c
 	$(CPP) -traditional -DCHIP=810 fake.c | grep -v '^#' | perl script_asm.pl 
 	mv script.h 53c8xx_d.h
 	mv scriptu.h 53c8xx_u.h
diff -u --recursive --new-file v1.3.49/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c
--- v1.3.49/linux/drivers/scsi/scsi.c	Wed Dec 13 09:02:46 1995
+++ linux/drivers/scsi/scsi.c	Thu Dec 21 12:08:36 1995
@@ -1564,6 +1564,13 @@
 #ifdef DEBUG
 	    printk("Aborting\n");
 #endif
+	    /*
+	      Allow TEST_UNIT_READY and INQUIRY commands to timeout early
+	      without causing resets.  All other commands should be retried.
+	    */
+	    if (SCpnt->cmnd[0] != TEST_UNIT_READY &&
+		SCpnt->cmnd[0] != INQUIRY)
+		    status = MAYREDO;
 	    exit = (DRIVER_TIMEOUT | SUGGEST_ABORT);
 	}
 	else
diff -u --recursive --new-file v1.3.49/linux/drivers/scsi/seagate.c linux/drivers/scsi/seagate.c
--- v1.3.49/linux/drivers/scsi/seagate.c	Tue Nov 21 13:22:11 1995
+++ linux/drivers/scsi/seagate.c	Fri Dec 22 17:19:00 1995
@@ -363,6 +363,8 @@
 				hostno, (int) irq);
 			return 0;
 		}
+		instance->irq = irq;
+		instance->io_port = (unsigned int) base_address;
 #ifdef SLOW_HANDSHAKE
 		borken_init();
 #endif
diff -u --recursive --new-file v1.3.49/linux/drivers/sound/Makefile linux/drivers/sound/Makefile
--- v1.3.49/linux/drivers/sound/Makefile	Mon Nov 27 12:48:31 1995
+++ linux/drivers/sound/Makefile	Fri Dec 22 08:22:05 1995
@@ -115,7 +115,7 @@
 
 sound.o: local.h $(FIXEDOBJS) sound.a
 	-rm -f sound.o
-	$(LD) -r -o sound.o $(FIXEDOBJS) sound.a
+	$(LD) -dc -r -o sound.o $(FIXEDOBJS) sound.a
 
 modules: local.h sound.o
 	ln -fs `pwd`/sound.o $(TOPDIR)/modules/sound.o
diff -u --recursive --new-file v1.3.49/linux/drivers/sound/soundcard.c linux/drivers/sound/soundcard.c
--- v1.3.49/linux/drivers/sound/soundcard.c	Sat Nov 11 17:41:33 1995
+++ linux/drivers/sound/soundcard.c	Fri Dec 22 08:22:05 1995
@@ -29,7 +29,6 @@
 /*
  * Created modular version by Peter Trattler (peter@sbox.tu-graz.ac.at)
  */
-
 #include <linux/module.h>
 
 #include "sound_config.h"
diff -u --recursive --new-file v1.3.49/linux/fs/buffer.c linux/fs/buffer.c
--- v1.3.49/linux/fs/buffer.c	Sun Dec 24 11:47:22 1995
+++ linux/fs/buffer.c	Sun Dec 24 11:49:14 1995
@@ -16,6 +16,8 @@
  * invalidate changed floppy-disk-caches.
  */
  
+/* Some bdflush() changes for the dynamic ramdisk - Paul Gortmaker, 12/94 */
+
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/major.h>
@@ -827,24 +829,18 @@
 }
 
 /*
- * bforget() is like brelse(), except is throws the buffer away
+ * bforget() is like brelse(), except it removes the buffer
+ * from the hash-queues (so that it won't be re-used if it's
+ * shared).
  */
 void __bforget(struct buffer_head * buf)
 {
 	wait_on_buffer(buf);
-	if (buf->b_count != 1) {
-		printk("Aieee... bforget(): count = %d\n", buf->b_count);
-		return;
-	}
-	if (mem_map[MAP_NR(buf->b_data)].count != 1) {
-		printk("Aieee... bforget(): shared buffer\n");
-		return;
-	}
 	mark_buffer_clean(buf);
-	buf->b_count = 0;
-	remove_from_queues(buf);
-	buf->b_dev = B_FREE;
-	put_last_free(buf);
+	buf->b_count--;
+	remove_from_hash_queue(buf);
+	buf->b_dev = NODEV;
+	refile_buffer(buf);
 	wake_up(&buffer_wait);
 }
 
@@ -1035,64 +1031,7 @@
 	}
 }
 
-/*
- * This actually gets enough info to try to align the stuff,
- * but we don't bother yet.. We'll have to check that nobody
- * else uses the buffers etc.
- *
- * "address" points to the new page we can use to move things
- * around..
- */
-static inline unsigned long try_to_align(struct buffer_head ** bh, int nrbuf,
-	unsigned long address)
-{
-	while (nrbuf-- > 0)
-		brelse(bh[nrbuf]);
-	return 0;
-}
-
-static unsigned long check_aligned(struct buffer_head * first, unsigned long address,
-	kdev_t dev, int *b, int size)
-{
-	struct buffer_head * bh[MAX_BUF_PER_PAGE];
-	unsigned long page;
-	unsigned long offset;
-	int block;
-	int nrbuf;
-	int aligned = 1;
-
-	bh[0] = first;
-	nrbuf = 1;
-	page = (unsigned long) first->b_data;
-	if (page & ~PAGE_MASK)
-		aligned = 0;
-	for (offset = size ; offset < PAGE_SIZE ; offset += size) {
-		block = *++b;
-		if (!block)
-			goto no_go;
-		first = get_hash_table(dev, block, size);
-		if (!first)
-			goto no_go;
-		bh[nrbuf++] = first;
-		if (page+offset != (unsigned long) first->b_data)
-			aligned = 0;
-	}
-	if (!aligned)
-		return try_to_align(bh, nrbuf, address);
-	mem_map[MAP_NR(page)].count++;
-	read_buffers(bh,nrbuf);		/* make sure they are actually read correctly */
-	while (nrbuf-- > 0)
-		brelse(bh[nrbuf]);
-	free_page(address);
-	++current->min_flt;
-	return page;
-no_go:
-	while (nrbuf-- > 0)
-		brelse(bh[nrbuf]);
-	return 0;
-}
-
-static unsigned long try_to_load_aligned(unsigned long address,
+static int try_to_load_aligned(unsigned long address,
 	kdev_t dev, int b[], int size)
 {
 	struct buffer_head * bh, * tmp, * arr[MAX_BUF_PER_PAGE];
@@ -1142,7 +1081,7 @@
 	while (block-- > 0)
 		brelse(arr[block]);
 	++current->maj_flt;
-	return address;
+	return 1;
 not_aligned:
 	while ((tmp = bh) != NULL) {
 		bh = bh->b_this_page;
@@ -1154,15 +1093,13 @@
 /*
  * Try-to-share-buffers tries to minimize memory use by trying to keep
  * both code pages and the buffer area in the same page. This is done by
- * (a) checking if the buffers are already aligned correctly in memory and
- * (b) if none of the buffer heads are in memory at all, trying to load
- * them into memory the way we want them.
+ * trying to load them into memory the way we want them.
  *
  * This doesn't guarantee that the memory is shared, but should under most
  * circumstances work very well indeed (ie >90% sharing of code pages on
  * demand-loadable executables).
  */
-static inline unsigned long try_to_share_buffers(unsigned long address,
+static inline int try_to_share_buffers(unsigned long address,
 	kdev_t dev, int *b, int size)
 {
 	struct buffer_head * bh;
@@ -1172,9 +1109,10 @@
 	if (!block)
 		return 0;
 	bh = get_hash_table(dev, block, size);
-	if (bh)
-		return check_aligned(bh, address, dev, b, size);
-	return try_to_load_aligned(address, dev, b, size);
+	if (!bh)
+		return try_to_load_aligned(address, dev, b, size);
+	brelse(bh);
+	return 0;
 }
 
 /*
@@ -1184,17 +1122,14 @@
  * etc. This also allows us to optimize memory usage by sharing code pages
  * and filesystem buffers..
  */
-unsigned long bread_page(unsigned long address, kdev_t dev, int b[], int size, int no_share)
+void bread_page(unsigned long address, kdev_t dev, int b[], int size)
 {
 	struct buffer_head * bh[MAX_BUF_PER_PAGE];
 	unsigned long where;
 	int i, j;
 
-	if (!no_share) {
-		where = try_to_share_buffers(address, dev, b, size);
-		if (where)
-			return where;
-	}
+	if (try_to_share_buffers(address, dev, b, size))
+		return;
 	++current->maj_flt;
  	for (i=0, j=0; j<PAGE_SIZE ; i++, j+= size) {
 		bh[i] = NULL;
@@ -1211,7 +1146,6 @@
 		} else
 			memset((void *) where, 0, size);
 	}
-	return address;
 }
 
 #if 0
@@ -1788,34 +1722,20 @@
 
 /* ====================== bdflush support =================== */
 
-/* This is a simple kernel daemon, whose job it is to provide a dynamically
+/* This is a simple kernel daemon, whose job it is to provide a dynamic
  * response to dirty buffers.  Once this process is activated, we write back
  * a limited number of buffers to the disks and then go back to sleep again.
- * In effect this is a process which never leaves kernel mode, and does not have
- * any user memory associated with it except for the stack.  There is also
- * a kernel stack page, which obviously must be separate from the user stack.
  */
 struct wait_queue * bdflush_wait = NULL;
 struct wait_queue * bdflush_done = NULL;
 
-static int bdflush_running = 0;
-
 static void wakeup_bdflush(int wait)
 {
-	extern int	rd_loading;
-	
-	if (!bdflush_running){
-		if (!rd_loading)
-			printk("Warning - bdflush not running\n");
-		sync_buffers(0,0);
-		return;
-	};
 	wake_up(&bdflush_wait);
 	if(wait) sleep_on(&bdflush_done);
 }
 
 
-
 /* 
  * Here we attempt to write back old buffers.  We also try and flush inodes 
  * and supers as well, since this function is essentially "update", and 
@@ -1894,18 +1814,13 @@
 
 
 /* This is the interface to bdflush.  As we get more sophisticated, we can
- * pass tuning parameters to this "process", to adjust how it behaves.  If you
- * invoke this again after you have done this once, you would simply modify 
- * the tuning parameters.  We would want to verify each parameter, however,
- * to make sure that it is reasonable. */
+ * pass tuning parameters to this "process", to adjust how it behaves. 
+ * We would want to verify each parameter, however, to make sure that it 
+ * is reasonable. */
 
 asmlinkage int sys_bdflush(int func, long data)
 {
 	int i, error;
-	int ndirty;
-	int nlist;
-	int ncount;
-	struct buffer_head * bh, *next;
 
 	if (!suser())
 		return -EPERM;
@@ -1913,7 +1828,7 @@
 	if (func == 1)
 		 return sync_old_buffers();
 
-	/* Basically func 0 means start, 1 means read param 1, 2 means write param 1, etc */
+	/* Basically func 1 means read param 1, 2 means write param 1, etc */
 	if (func >= 2) {
 		i = (func-2) >> 1;
 		if (i < 0 || i >= N_PARAM)
@@ -1930,13 +1845,32 @@
 		bdf_prm.data[i] = data;
 		return 0;
 	};
+
+	/* Having func 0 used to launch the actual bdflush and then never
+	return (unless explicitly killed). We return zero here to 
+	remain semi-compatible with present update(8) programs. */
+
+	return 0;
+}
+
+/* This is the actual bdflush daemon itself. It used to be started from
+ * the syscall above, but now we launch it ourselves internally with
+ * kernel_thread(...)  directly after the first thread in init/main.c */
+
+int bdflush(void * unused) {
 	
-	if (bdflush_running)
-		return -EBUSY; /* Only one copy of this running at one time */
-	bdflush_running++;
-	
-	/* OK, from here on is the daemon */
-	
+	int i;
+	int ndirty;
+	int nlist;
+	int ncount;
+	struct buffer_head * bh, *next;
+
+	/* We have a bare-bones task_struct, and really should fill
+	in a few more things so "top" and /proc/2/{exe,root,cwd}
+	display semi-sane things. Not real crucial though...  */
+
+	sprintf(current->comm, "bdflush - kernel");
+
 	for (;;) {
 #ifdef DEBUG
 		printk("bdflush() activated...");
@@ -1995,11 +1929,7 @@
 		
 		if(nr_buffers_type[BUF_DIRTY] <= (nr_buffers - nr_buffers_type[BUF_SHARED]) * 
 		   bdf_prm.b_un.nfract/100) {
-		   	if (current->signal & (1 << (SIGKILL-1))) {
-				bdflush_running--;
-		   		return 0;
-			}
-		   	current->signal = 0;
+			current->signal = 0;
 			interruptible_sleep_on(&bdflush_wait);
 		}
 	}
diff -u --recursive --new-file v1.3.49/linux/fs/devices.c linux/fs/devices.c
--- v1.3.49/linux/fs/devices.c	Mon Sep 18 14:54:05 1995
+++ linux/fs/devices.c	Fri Dec 22 13:00:19 1995
@@ -211,6 +211,8 @@
 	NULL,			/* rename */
 	NULL,			/* readlink */
 	NULL,			/* follow_link */
+	NULL,			/* readpage */
+	NULL,			/* writepage */
 	NULL,			/* bmap */
 	NULL,			/* truncate */
 	NULL			/* permission */
@@ -262,6 +264,8 @@
 	NULL,			/* rename */
 	NULL,			/* readlink */
 	NULL,			/* follow_link */
+	NULL,			/* readpage */
+	NULL,			/* writepage */
 	NULL,			/* bmap */
 	NULL,			/* truncate */
 	NULL			/* permission */
diff -u --recursive --new-file v1.3.49/linux/fs/exec.c linux/fs/exec.c
--- v1.3.49/linux/fs/exec.c	Mon Dec 11 15:42:03 1995
+++ linux/fs/exec.c	Fri Dec 22 08:22:05 1995
@@ -748,8 +748,13 @@
 		goto restart_interp;
 	}
 #ifdef __alpha__
-/* handle /sbin/loader.. */
-	if (!loader && (((struct exec *) bprm.buf)->fh.f_flags & 0x3000)) {
+	/* handle /sbin/loader.. */
+	{
+	    struct exec * eh = (struct exec *) bprm.buf;
+
+	    if (!loader && eh->fh.f_magic == 0x183 &&
+		(eh->fh.f_flags & 0x3000) == 0x3000)
+	    {
 		char * dynloader[] = { "/sbin/loader" };
 		iput(bprm.inode);
 		loader = 1;
@@ -759,6 +764,7 @@
 		if (retval)
 			goto exec_error1;
 		goto restart_interp;
+	    }
 	}
 #endif
 	if (!sh_bang) {
diff -u --recursive --new-file v1.3.49/linux/fs/ext/dir.c linux/fs/ext/dir.c
--- v1.3.49/linux/fs/ext/dir.c	Mon Sep 18 14:54:05 1995
+++ linux/fs/ext/dir.c	Fri Dec 22 13:00:19 1995
@@ -56,6 +56,8 @@
 	ext_rename,		/* rename */
 	NULL,			/* readlink */
 	NULL,			/* follow_link */
+	NULL,			/* readpage */
+	NULL,			/* writepage */
 	NULL,			/* bmap */
 	ext_truncate,		/* truncate */
 	NULL			/* permission */
diff -u --recursive --new-file v1.3.49/linux/fs/ext/file.c linux/fs/ext/file.c
--- v1.3.49/linux/fs/ext/file.c	Mon Nov 27 12:48:31 1995
+++ linux/fs/ext/file.c	Fri Dec 22 13:00:19 1995
@@ -64,6 +64,8 @@
 	NULL,			/* rename */
 	NULL,			/* readlink */
 	NULL,			/* follow_link */
+	NULL,			/* readpage */
+	NULL,			/* writepage */
 	ext_bmap,		/* bmap */
 	ext_truncate,		/* truncate */
 	NULL			/* permission */
diff -u --recursive --new-file v1.3.49/linux/fs/ext/symlink.c linux/fs/ext/symlink.c
--- v1.3.49/linux/fs/ext/symlink.c	Tue Jun 27 14:11:39 1995
+++ linux/fs/ext/symlink.c	Fri Dec 22 13:00:19 1995
@@ -39,6 +39,8 @@
 	NULL,			/* rename */
 	ext_readlink,		/* readlink */
 	ext_follow_link,	/* follow_link */
+	NULL,			/* readpage */
+	NULL,			/* writepage */
 	NULL,			/* bmap */
 	NULL,			/* truncate */
 	NULL			/* permission */
diff -u --recursive --new-file v1.3.49/linux/fs/ext2/dir.c linux/fs/ext2/dir.c
--- v1.3.49/linux/fs/ext2/dir.c	Mon Nov 27 12:48:31 1995
+++ linux/fs/ext2/dir.c	Fri Dec 22 13:00:19 1995
@@ -63,6 +63,8 @@
 	ext2_rename,		/* rename */
 	NULL,			/* readlink */
 	NULL,			/* follow_link */
+	NULL,			/* readpage */
+	NULL,			/* writepage */
 	NULL,			/* bmap */
 	ext2_truncate,		/* truncate */
 	ext2_permission,	/* permission */
diff -u --recursive --new-file v1.3.49/linux/fs/ext2/file.c linux/fs/ext2/file.c
--- v1.3.49/linux/fs/ext2/file.c	Mon Nov 27 12:48:31 1995
+++ linux/fs/ext2/file.c	Fri Dec 22 13:00:19 1995
@@ -71,6 +71,8 @@
 	NULL,			/* rename */
 	NULL,			/* readlink */
 	NULL,			/* follow_link */
+	NULL,			/* readpage */
+	NULL,			/* writepage */
 	ext2_bmap,		/* bmap */
 	ext2_truncate,		/* truncate */
 	ext2_permission,	/* permission */
diff -u --recursive --new-file v1.3.49/linux/fs/ext2/symlink.c linux/fs/ext2/symlink.c
--- v1.3.49/linux/fs/ext2/symlink.c	Tue Jun 27 14:11:39 1995
+++ linux/fs/ext2/symlink.c	Fri Dec 22 13:00:19 1995
@@ -43,6 +43,8 @@
 	NULL,			/* rename */
 	ext2_readlink,		/* readlink */
 	ext2_follow_link,	/* follow_link */
+	NULL,			/* readpage */
+	NULL,			/* writepage */
 	NULL,			/* bmap */
 	NULL,			/* truncate */
 	NULL,			/* permission */
diff -u --recursive --new-file v1.3.49/linux/fs/fifo.c linux/fs/fifo.c
--- v1.3.49/linux/fs/fifo.c	Mon Jan 23 23:04:10 1995
+++ linux/fs/fifo.c	Fri Dec 22 13:00:19 1995
@@ -144,6 +144,8 @@
 	NULL,			/* rename */
 	NULL,			/* readlink */
 	NULL,			/* follow_link */
+	NULL,			/* readpage */
+	NULL,			/* writepage */
 	NULL,			/* bmap */
 	NULL,			/* truncate */
 	NULL			/* permission */
diff -u --recursive --new-file v1.3.49/linux/fs/hpfs/hpfs_fs.c linux/fs/hpfs/hpfs_fs.c
--- v1.3.49/linux/fs/hpfs/hpfs_fs.c	Sun Dec 17 11:43:20 1995
+++ linux/fs/hpfs/hpfs_fs.c	Fri Dec 22 13:00:19 1995
@@ -175,6 +175,8 @@
 	NULL,				/* rename */
 	NULL,				/* readlink */
 	NULL,				/* follow_link */
+	NULL,				/* readpage */
+	NULL,				/* writepage */
 	(int (*)(struct inode *, int))
 	&hpfs_bmap,			/* bmap */
 	NULL,				/* truncate */
@@ -217,6 +219,8 @@
 	NULL,				/* rename */
 	NULL,				/* readlink */
 	NULL,				/* follow_link */
+	NULL,				/* readpage */
+	NULL,				/* writepage */
 	NULL,				/* bmap */
 	NULL,				/* truncate */
 	NULL,				/* permission */
diff -u --recursive --new-file v1.3.49/linux/fs/inode.c linux/fs/inode.c
--- v1.3.49/linux/fs/inode.c	Sun Dec 17 11:43:20 1995
+++ linux/fs/inode.c	Fri Dec 22 21:05:52 1995
@@ -148,6 +148,7 @@
 {
 	struct wait_queue * wait;
 
+	invalidate_inode_pages(inode, 0);
 	wait_on_inode(inode);
 	if (IS_WRITABLE(inode)) {
 		if (inode->i_sb && inode->i_sb->dq_op)
diff -u --recursive --new-file v1.3.49/linux/fs/isofs/dir.c linux/fs/isofs/dir.c
--- v1.3.49/linux/fs/isofs/dir.c	Thu Nov  9 11:23:51 1995
+++ linux/fs/isofs/dir.c	Fri Dec 22 13:00:19 1995
@@ -53,6 +53,8 @@
 	NULL,			/* rename */
 	NULL,			/* readlink */
 	NULL,			/* follow_link */
+	NULL,			/* readpage */
+	NULL,			/* writepage */
 	isofs_bmap,		/* bmap */
 	NULL,			/* truncate */
 	NULL			/* permission */
diff -u --recursive --new-file v1.3.49/linux/fs/isofs/file.c linux/fs/isofs/file.c
--- v1.3.49/linux/fs/isofs/file.c	Mon Nov 27 12:48:31 1995
+++ linux/fs/isofs/file.c	Fri Dec 22 13:00:19 1995
@@ -59,6 +59,8 @@
 	NULL,			/* rename */
 	NULL,			/* readlink */
 	NULL,			/* follow_link */
+	NULL,			/* readpage */
+	NULL,			/* writepage */
 	isofs_bmap,		/* bmap */
 	NULL,	       		/* truncate */
 	NULL			/* permission */
diff -u --recursive --new-file v1.3.49/linux/fs/isofs/inode.c linux/fs/isofs/inode.c
--- v1.3.49/linux/fs/isofs/inode.c	Mon Dec 11 15:42:04 1995
+++ linux/fs/isofs/inode.c	Fri Dec 22 08:51:08 1995
@@ -60,6 +60,7 @@
   char rock;
   char cruft;
   char unhide;
+  unsigned char check;
   unsigned char conversion;
   unsigned int blocksize;
   mode_t mode;
@@ -75,6 +76,7 @@
 	popt->rock = 'y';
 	popt->cruft = 'n';
 	popt->unhide = 'n';
+	popt->check = 's';		/* default: strict */
 	popt->conversion = 'b';		/* default: no conversion */
 	popt->blocksize = 1024;
 	popt->mode = S_IRUGO;
@@ -103,6 +105,13 @@
 			else if (!strcmp(value,"normal")) popt->map = 'n';
 			else return 0;
 		}
+		else if (!strcmp(this_char,"check") && value) {
+			if (value[0] && !value[1] && strchr("rs",*value))
+				popt->check = *value;
+			else if (!strcmp(value,"relaxed")) popt->check = 'r';
+			else if (!strcmp(value,"strict")) popt->check = 's';
+			else return 0;
+		}
 		else if (!strcmp(this_char,"conv") && value) {
 			if (value[0] && !value[1] && strchr("btma",*value))
 				popt->conversion = *value;
@@ -213,6 +222,7 @@
 #if 0
 	printk("map = %c\n", opt.map);
 	printk("rock = %c\n", opt.rock);
+	printk("check = %c\n", opt.check);
 	printk("cruft = %c\n", opt.cruft);
 	printk("unhide = %c\n", opt.unhide);
 	printk("conversion = %c\n", opt.conversion);
@@ -353,6 +363,7 @@
 	s->s_op = &isofs_sops;
 	s->u.isofs_sb.s_mapping = opt.map;
 	s->u.isofs_sb.s_rock = (opt.rock == 'y' ? 1 : 0);
+	s->u.isofs_sb.s_name_check = opt.check;
 	s->u.isofs_sb.s_conversion = opt.conversion;
 	s->u.isofs_sb.s_cruft = opt.cruft;
 	s->u.isofs_sb.s_unhide = opt.unhide;
diff -u --recursive --new-file v1.3.49/linux/fs/isofs/namei.c linux/fs/isofs/namei.c
--- v1.3.49/linux/fs/isofs/namei.c	Thu Nov  9 11:23:51 1995
+++ linux/fs/isofs/namei.c	Fri Dec 22 08:51:08 1995
@@ -238,14 +238,33 @@
 	if (dcache_lookup(dir, name, len, &ino)) ino_back = dir->i_ino;
 
 	if (!ino) {
-	  if (!(bh = isofs_find_entry(dir,name,len, &ino, &ino_back))) {
-	    iput(dir);
-	    return -ENOENT;
-	  }
-	  if (ino_back == dir->i_ino)
-		dcache_add(dir, name, len, ino);
-	  brelse(bh);
-	};
+		char *lcname;
+
+		/* If mounted with check=relaxed (and most likely norock),
+		   then first convert this name to lower case. */
+		if (dir->i_sb->u.isofs_sb.s_name_check == 'r'
+		    && (lcname = kmalloc(len, GFP_KERNEL)) != NULL) {
+			int i;
+			char c;
+
+			for (i=0; i<len; i++) {
+				c = name[i];
+				if (c >= 'A' && c <= 'Z') c |= 0x20;
+				lcname[i] = c;
+			}
+			bh = isofs_find_entry(dir,lcname,len, &ino, &ino_back);
+			kfree(lcname);
+		} else
+			bh = isofs_find_entry(dir,name,len, &ino, &ino_back);
+
+		if (!bh) {
+			iput(dir);
+	  		return -ENOENT;
+		}
+		if (ino_back == dir->i_ino)
+			dcache_add(dir, name, len, ino);
+		brelse(bh);
+	}
 
 	if (!(*result = iget(dir->i_sb,ino))) {
 		iput(dir);
diff -u --recursive --new-file v1.3.49/linux/fs/isofs/symlink.c linux/fs/isofs/symlink.c
--- v1.3.49/linux/fs/isofs/symlink.c	Thu Nov  9 11:23:51 1995
+++ linux/fs/isofs/symlink.c	Fri Dec 22 13:00:19 1995
@@ -37,6 +37,8 @@
 	NULL,			/* rename */
 	isofs_readlink,		/* readlink */
 	isofs_follow_link,	/* follow_link */
+	NULL,			/* readpage */
+	NULL,			/* writepage */
 	NULL,			/* bmap */
 	NULL,			/* truncate */
 	NULL			/* permission */
diff -u --recursive --new-file v1.3.49/linux/fs/minix/dir.c linux/fs/minix/dir.c
--- v1.3.49/linux/fs/minix/dir.c	Thu Nov  9 11:23:51 1995
+++ linux/fs/minix/dir.c	Fri Dec 22 13:00:19 1995
@@ -50,6 +50,8 @@
 	minix_rename,		/* rename */
 	NULL,			/* readlink */
 	NULL,			/* follow_link */
+	NULL,			/* readpage */
+	NULL,			/* writepage */
 	NULL,			/* bmap */
 	minix_truncate,		/* truncate */
 	NULL			/* permission */
diff -u --recursive --new-file v1.3.49/linux/fs/minix/file.c linux/fs/minix/file.c
--- v1.3.49/linux/fs/minix/file.c	Mon Nov 27 12:48:31 1995
+++ linux/fs/minix/file.c	Fri Dec 22 13:00:19 1995
@@ -58,6 +58,8 @@
 	NULL,			/* rename */
 	NULL,			/* readlink */
 	NULL,			/* follow_link */
+	NULL,			/* readpage */
+	NULL,			/* writepage */
 	minix_bmap,		/* bmap */
 	minix_truncate,		/* truncate */
 	NULL			/* permission */
diff -u --recursive --new-file v1.3.49/linux/fs/minix/symlink.c linux/fs/minix/symlink.c
--- v1.3.49/linux/fs/minix/symlink.c	Thu Nov  9 11:23:51 1995
+++ linux/fs/minix/symlink.c	Fri Dec 22 13:00:19 1995
@@ -33,6 +33,8 @@
 	NULL,			/* rename */
 	minix_readlink,		/* readlink */
 	minix_follow_link,	/* follow_link */
+	NULL,			/* readpage */
+	NULL,			/* writepage */
 	NULL,			/* bmap */
 	NULL,			/* truncate */
 	NULL			/* permission */
diff -u --recursive --new-file v1.3.49/linux/fs/msdos/dir.c linux/fs/msdos/dir.c
--- v1.3.49/linux/fs/msdos/dir.c	Sat Nov 11 17:41:33 1995
+++ linux/fs/msdos/dir.c	Fri Dec 22 13:00:19 1995
@@ -51,6 +51,8 @@
 	msdos_rename,		/* rename */
 	NULL,			/* readlink */
 	NULL,			/* follow_link */
+	NULL,			/* readpage */
+	NULL,			/* writepage */
 	msdos_bmap,		/* bmap */
 	NULL,			/* truncate */
 	NULL			/* permission */
diff -u --recursive --new-file v1.3.49/linux/fs/msdos/file.c linux/fs/msdos/file.c
--- v1.3.49/linux/fs/msdos/file.c	Sun Dec 17 11:43:20 1995
+++ linux/fs/msdos/file.c	Fri Dec 22 13:00:19 1995
@@ -52,6 +52,8 @@
 	NULL,			/* rename */
 	NULL,			/* readlink */
 	NULL,			/* follow_link */
+	NULL,			/* readpage */
+	NULL,			/* writepage */
 	msdos_bmap,		/* bmap */
 	msdos_truncate,		/* truncate */
 	NULL,			/* permission */
@@ -98,6 +100,8 @@
 	NULL,			/* rename */
 	NULL,			/* readlink */
 	NULL,			/* follow_link */
+	NULL,			/* readpage */
+	NULL,			/* writepage */
 	NULL,			/* bmap */
 	msdos_truncate,		/* truncate */
 	NULL,			/* permission */
diff -u --recursive --new-file v1.3.49/linux/fs/nfs/dir.c linux/fs/nfs/dir.c
--- v1.3.49/linux/fs/nfs/dir.c	Thu Nov  9 11:23:51 1995
+++ linux/fs/nfs/dir.c	Fri Dec 22 13:00:19 1995
@@ -64,6 +64,8 @@
 	nfs_rename,		/* rename */
 	NULL,			/* readlink */
 	NULL,			/* follow_link */
+	NULL,			/* readpage */
+	NULL,			/* writepage */
 	NULL,			/* bmap */
 	NULL,			/* truncate */
 	NULL			/* permission */
diff -u --recursive --new-file v1.3.49/linux/fs/nfs/file.c linux/fs/nfs/file.c
--- v1.3.49/linux/fs/nfs/file.c	Thu Nov  9 11:23:51 1995
+++ linux/fs/nfs/file.c	Fri Dec 22 13:00:19 1995
@@ -56,6 +56,8 @@
 	NULL,			/* rename */
 	NULL,			/* readlink */
 	NULL,			/* follow_link */
+	NULL,			/* readpage */
+	NULL,			/* writepage */
 	NULL,			/* bmap */
 	NULL			/* truncate */
 };
diff -u --recursive --new-file v1.3.49/linux/fs/nfs/symlink.c linux/fs/nfs/symlink.c
--- v1.3.49/linux/fs/nfs/symlink.c	Thu Nov  9 11:23:51 1995
+++ linux/fs/nfs/symlink.c	Fri Dec 22 13:00:19 1995
@@ -38,6 +38,8 @@
 	NULL,			/* rename */
 	nfs_readlink,		/* readlink */
 	nfs_follow_link,	/* follow_link */
+	NULL,			/* readpage */
+	NULL,			/* writepage */
 	NULL,			/* bmap */
 	NULL,			/* truncate */
 	NULL			/* permission */
diff -u --recursive --new-file v1.3.49/linux/fs/pipe.c linux/fs/pipe.c
--- v1.3.49/linux/fs/pipe.c	Sat Nov 25 19:04:47 1995
+++ linux/fs/pipe.c	Fri Dec 22 13:00:19 1995
@@ -386,6 +386,8 @@
 	NULL,			/* rename */
 	NULL,			/* readlink */
 	NULL,			/* follow_link */
+	NULL,			/* readpage */
+	NULL,			/* writepage */
 	NULL,			/* bmap */
 	NULL,			/* truncate */
 	NULL			/* permission */
diff -u --recursive --new-file v1.3.49/linux/fs/proc/array.c linux/fs/proc/array.c
--- v1.3.49/linux/fs/proc/array.c	Mon Dec 11 15:42:04 1995
+++ linux/fs/proc/array.c	Fri Dec 22 13:00:19 1995
@@ -291,6 +291,13 @@
 	return strlen(buffer);
 }
 
+static int get_cmdline(char * buffer)
+{
+	extern char saved_command_line[];
+
+	return sprintf(buffer, "%s\n", saved_command_line);
+}
+
 static struct task_struct ** get_task(pid_t pid)
 {
 	struct task_struct ** p;
@@ -827,6 +834,8 @@
 		case PROC_APM:
 			return apm_proc(page);
 #endif
+		case PROC_CMDLINE:
+			return get_cmdline(page);
 	}
 	return -EBADF;
 }
@@ -927,6 +936,8 @@
 	NULL,			/* rename */
 	NULL,			/* readlink */
 	NULL,			/* follow_link */
+	NULL,			/* readpage */
+	NULL,			/* writepage */
 	NULL,			/* bmap */
 	NULL,			/* truncate */
 	NULL			/* permission */
@@ -973,6 +984,8 @@
 	NULL,			/* rename */
 	NULL,			/* readlink */
 	NULL,			/* follow_link */
+	NULL,			/* readpage */
+	NULL,			/* writepage */
 	NULL,			/* bmap */
 	NULL,			/* truncate */
 	NULL			/* permission */
diff -u --recursive --new-file v1.3.49/linux/fs/proc/base.c linux/fs/proc/base.c
--- v1.3.49/linux/fs/proc/base.c	Tue Aug 15 20:39:04 1995
+++ linux/fs/proc/base.c	Fri Dec 22 13:00:19 1995
@@ -42,6 +42,8 @@
 	NULL,			/* rename */
 	NULL,			/* readlink */
 	NULL,			/* follow_link */
+	NULL,			/* readpage */
+	NULL,			/* writepage */
 	NULL,			/* bmap */
 	NULL,			/* truncate */
 	NULL			/* permission */
diff -u --recursive --new-file v1.3.49/linux/fs/proc/fd.c linux/fs/proc/fd.c
--- v1.3.49/linux/fs/proc/fd.c	Sat Nov 25 19:04:48 1995
+++ linux/fs/proc/fd.c	Fri Dec 22 13:00:19 1995
@@ -45,6 +45,8 @@
 	NULL,			/* rename */
 	NULL,			/* readlink */
 	NULL,			/* follow_link */
+	NULL,			/* readpage */
+	NULL,			/* writepage */
 	NULL,			/* bmap */
 	NULL,			/* truncate */
 	NULL			/* permission */
diff -u --recursive --new-file v1.3.49/linux/fs/proc/kmsg.c linux/fs/proc/kmsg.c
--- v1.3.49/linux/fs/proc/kmsg.c	Mon Dec 27 07:37:36 1993
+++ linux/fs/proc/kmsg.c	Fri Dec 22 13:00:19 1995
@@ -70,6 +70,8 @@
 	NULL,			/* rename */
 	NULL,			/* readlink */
 	NULL,			/* follow_link */
+	NULL,			/* readpage */
+	NULL,			/* writepage */
 	NULL,			/* bmap */
 	NULL,			/* truncate */
 	NULL			/* permission */
diff -u --recursive --new-file v1.3.49/linux/fs/proc/link.c linux/fs/proc/link.c
--- v1.3.49/linux/fs/proc/link.c	Fri Oct 13 14:44:44 1995
+++ linux/fs/proc/link.c	Fri Dec 22 13:00:19 1995
@@ -54,6 +54,8 @@
 	NULL,			/* rename */
 	proc_readlink,		/* readlink */
 	proc_follow_link,	/* follow_link */
+	NULL,			/* readpage */
+	NULL,			/* writepage */
 	NULL,			/* bmap */
 	NULL,			/* truncate */
 	NULL			/* permission */
diff -u --recursive --new-file v1.3.49/linux/fs/proc/mem.c linux/fs/proc/mem.c
--- v1.3.49/linux/fs/proc/mem.c	Wed Dec 13 09:02:47 1995
+++ linux/fs/proc/mem.c	Fri Dec 22 13:00:19 1995
@@ -328,6 +328,8 @@
 	NULL,			/* rename */
 	NULL,			/* readlink */
 	NULL,			/* follow_link */
+	NULL,			/* readpage */
+	NULL,			/* writepage */
 	NULL,			/* bmap */
 	NULL,			/* truncate */
 	NULL			/* permission */
diff -u --recursive --new-file v1.3.49/linux/fs/proc/net.c linux/fs/proc/net.c
--- v1.3.49/linux/fs/proc/net.c	Wed Nov  8 07:11:37 1995
+++ linux/fs/proc/net.c	Fri Dec 22 13:00:19 1995
@@ -114,6 +114,8 @@
 	NULL,			/* rename */
 	NULL,			/* readlink */
 	NULL,			/* follow_link */
+	NULL,			/* readpage */
+	NULL,			/* writepage */
 	NULL,			/* bmap */
 	NULL,			/* truncate */
 	NULL			/* permission */
diff -u --recursive --new-file v1.3.49/linux/fs/proc/root.c linux/fs/proc/root.c
--- v1.3.49/linux/fs/proc/root.c	Mon Dec 11 15:42:04 1995
+++ linux/fs/proc/root.c	Fri Dec 22 13:00:19 1995
@@ -62,6 +62,8 @@
 	NULL,			/* rename */
 	NULL,			/* readlink */
 	NULL,			/* follow_link */
+	NULL,			/* readpage */
+	NULL,			/* writepage */
 	NULL,			/* bmap */
 	NULL,			/* truncate */
 	NULL			/* permission */
@@ -101,6 +103,8 @@
 	NULL,			/* rename */
 	NULL,			/* readlink */
 	NULL,			/* follow_link */
+	NULL,			/* readpage */
+	NULL,			/* writepage */
 	NULL,			/* bmap */
 	NULL,			/* truncate */
 	NULL			/* permission */
@@ -202,6 +206,8 @@
 	NULL,			/* rename */
 	proc_self_readlink,	/* readlink */
 	proc_self_followlink,	/* follow_link */
+	NULL,			/* readpage */
+	NULL,			/* writepage */
 	NULL,			/* bmap */
 	NULL,			/* truncate */
 	NULL			/* permission */
@@ -302,6 +308,10 @@
 		S_IFREG | S_IRUGO, 1, 0, 0,
 	});
 #endif
+	proc_register(&proc_root, &(struct proc_dir_entry) {
+		PROC_CMDLINE, 7, "cmdline",
+		S_IFREG | S_IRUGO, 1, 0, 0,
+	});
 		   
 	if (prof_shift) {
 		proc_register(&proc_root, &(struct proc_dir_entry) {
diff -u --recursive --new-file v1.3.49/linux/fs/proc/scsi.c linux/fs/proc/scsi.c
--- v1.3.49/linux/fs/proc/scsi.c	Wed Nov  8 07:11:39 1995
+++ linux/fs/proc/scsi.c	Fri Dec 22 13:00:19 1995
@@ -70,6 +70,8 @@
     NULL,	    /* rename	   */
     NULL,	    /* readlink	   */
     NULL,	    /* follow_link */
+    NULL,	    /* readpage	   */
+    NULL,	    /* writepage   */
     NULL,	    /* bmap	   */
     NULL,	    /* truncate	   */
     NULL	    /* permission  */
diff -u --recursive --new-file v1.3.49/linux/fs/smbfs/dir.c linux/fs/smbfs/dir.c
--- v1.3.49/linux/fs/smbfs/dir.c	Mon Dec 11 15:42:04 1995
+++ linux/fs/smbfs/dir.c	Fri Dec 22 13:00:19 1995
@@ -108,6 +108,8 @@
 	smb_rename,    		/* rename */
 	NULL,			/* readlink */
 	NULL,			/* follow_link */
+	NULL,			/* readpage */
+	NULL,			/* writepage */
 	NULL,			/* bmap */
 	NULL,			/* truncate */
 	NULL,			/* permission */
diff -u --recursive --new-file v1.3.49/linux/fs/smbfs/file.c linux/fs/smbfs/file.c
--- v1.3.49/linux/fs/smbfs/file.c	Sat Nov 11 17:41:34 1995
+++ linux/fs/smbfs/file.c	Fri Dec 22 13:00:19 1995
@@ -248,6 +248,8 @@
 	NULL,			/* rename */
 	NULL,			/* readlink */
 	NULL,			/* follow_link */
+	NULL,			/* readpage */
+	NULL,			/* writepage */
 	NULL,			/* bmap */
 	NULL			/* truncate */
 };
diff -u --recursive --new-file v1.3.49/linux/fs/sysv/dir.c linux/fs/sysv/dir.c
--- v1.3.49/linux/fs/sysv/dir.c	Thu Nov  9 11:23:51 1995
+++ linux/fs/sysv/dir.c	Fri Dec 22 13:00:19 1995
@@ -57,6 +57,8 @@
 	sysv_rename,		/* rename */
 	NULL,			/* readlink */
 	NULL,			/* follow_link */
+	NULL,			/* readpage */
+	NULL,			/* writepage */
 	NULL,			/* bmap */
 	sysv_truncate,		/* truncate */
 	NULL			/* permission */
diff -u --recursive --new-file v1.3.49/linux/fs/sysv/file.c linux/fs/sysv/file.c
--- v1.3.49/linux/fs/sysv/file.c	Mon Nov 27 12:48:32 1995
+++ linux/fs/sysv/file.c	Fri Dec 22 13:00:19 1995
@@ -64,6 +64,8 @@
 	NULL,			/* rename */
 	NULL,			/* readlink */
 	NULL,			/* follow_link */
+	NULL,			/* readpage */
+	NULL,			/* writepage */
 	sysv_bmap,		/* bmap */
 	sysv_truncate,		/* truncate */
 	NULL			/* permission */
diff -u --recursive --new-file v1.3.49/linux/fs/sysv/symlink.c linux/fs/sysv/symlink.c
--- v1.3.49/linux/fs/sysv/symlink.c	Thu Nov  9 11:23:52 1995
+++ linux/fs/sysv/symlink.c	Fri Dec 22 13:00:19 1995
@@ -39,6 +39,8 @@
 	NULL,			/* rename */
 	sysv_readlink,		/* readlink */
 	sysv_follow_link,	/* follow_link */
+	NULL,			/* readpage */
+	NULL,			/* writepage */
 	NULL,			/* bmap */
 	NULL,			/* truncate */
 	NULL			/* permission */
diff -u --recursive --new-file v1.3.49/linux/fs/umsdos/dir.c linux/fs/umsdos/dir.c
--- v1.3.49/linux/fs/umsdos/dir.c	Thu Nov  9 11:23:52 1995
+++ linux/fs/umsdos/dir.c	Fri Dec 22 13:00:19 1995
@@ -812,6 +812,8 @@
 	UMSDOS_rename,		/* rename */
 	NULL,			/* readlink */
 	NULL,			/* follow_link */
+	NULL,			/* readpage */
+	NULL,			/* writepage */
 	NULL,			/* bmap */
 	NULL,			/* truncate */
 	NULL			/* permission */
diff -u --recursive --new-file v1.3.49/linux/fs/umsdos/file.c linux/fs/umsdos/file.c
--- v1.3.49/linux/fs/umsdos/file.c	Thu Nov  9 11:23:52 1995
+++ linux/fs/umsdos/file.c	Fri Dec 22 13:00:19 1995
@@ -87,6 +87,8 @@
 	NULL,			/* rename */
 	NULL,			/* readlink */
 	NULL,			/* follow_link */
+	NULL,			/* readpage */
+	NULL,			/* writepage */
 	msdos_bmap,		/* bmap */
 	UMSDOS_truncate,/* truncate */
 	NULL,			/* permission */
@@ -119,6 +121,8 @@
 	NULL,			/* rename */
 	NULL,			/* readlink */
 	NULL,			/* follow_link */
+	NULL,			/* readpage */
+	NULL,			/* writepage */
 	NULL,			/* bmap */
 	UMSDOS_truncate,/* truncate */
 	NULL,			/* permission */
diff -u --recursive --new-file v1.3.49/linux/fs/umsdos/rdir.c linux/fs/umsdos/rdir.c
--- v1.3.49/linux/fs/umsdos/rdir.c	Thu Nov  9 11:23:52 1995
+++ linux/fs/umsdos/rdir.c	Fri Dec 22 13:00:19 1995
@@ -261,6 +261,8 @@
 	msdos_rename,		/* rename */
 	NULL,				/* readlink */
 	NULL,				/* follow_link */
+	NULL,				/* readpage */
+	NULL,				/* writepage */
 	NULL,				/* bmap */
 	NULL,				/* truncate */
 	NULL				/* permission */
diff -u --recursive --new-file v1.3.49/linux/fs/umsdos/symlink.c linux/fs/umsdos/symlink.c
--- v1.3.49/linux/fs/umsdos/symlink.c	Thu Nov  9 11:23:52 1995
+++ linux/fs/umsdos/symlink.c	Fri Dec 22 13:00:19 1995
@@ -137,6 +137,8 @@
 	NULL,			/* rename */
 	UMSDOS_readlink,	/* readlink */
 	UMSDOS_follow_link,	/* follow_link */
+	NULL,			/* readpage */
+	NULL,			/* writepage */
 	NULL,			/* bmap */
 	NULL,			/* truncate */
 	NULL			/* permission */
diff -u --recursive --new-file v1.3.49/linux/fs/xiafs/dir.c linux/fs/xiafs/dir.c
--- v1.3.49/linux/fs/xiafs/dir.c	Thu Nov  9 11:23:52 1995
+++ linux/fs/xiafs/dir.c	Fri Dec 22 13:00:19 1995
@@ -52,6 +52,8 @@
     xiafs_rename,			/* rename */
     NULL,			/* readlink */
     NULL,			/* follow_link */
+    NULL,			/* readpage */
+    NULL,			/* writepage */
     NULL,			/* bmap */
     xiafs_truncate,		/* truncate */
     NULL			/* permission */
diff -u --recursive --new-file v1.3.49/linux/fs/xiafs/file.c linux/fs/xiafs/file.c
--- v1.3.49/linux/fs/xiafs/file.c	Mon Nov 27 12:48:32 1995
+++ linux/fs/xiafs/file.c	Fri Dec 22 13:00:19 1995
@@ -61,6 +61,8 @@
     NULL,			/* rename */
     NULL,			/* readlink */
     NULL,			/* follow_link */
+    NULL,			/* readpage */
+    NULL,			/* writepage */
     xiafs_bmap,			/* bmap */
     xiafs_truncate,		/* truncate */
     NULL			/* permission */
diff -u --recursive --new-file v1.3.49/linux/fs/xiafs/symlink.c linux/fs/xiafs/symlink.c
--- v1.3.49/linux/fs/xiafs/symlink.c	Thu Nov  9 11:23:52 1995
+++ linux/fs/xiafs/symlink.c	Fri Dec 22 13:00:19 1995
@@ -39,6 +39,8 @@
 	NULL,			/* rename */
 	xiafs_readlink,		/* readlink */
 	xiafs_follow_link,	/* follow_link */
+	NULL,			/* readpage */
+	NULL,			/* writepage */
 	NULL,			/* bmap */
 	NULL,			/* truncate */
 	NULL			/* permission */
diff -u --recursive --new-file v1.3.49/linux/include/asm-alpha/apecs.h linux/include/asm-alpha/apecs.h
--- v1.3.49/linux/include/asm-alpha/apecs.h	Wed Nov  8 07:11:40 1995
+++ linux/include/asm-alpha/apecs.h	Fri Dec 22 08:22:05 1995
@@ -170,6 +170,14 @@
 
 extern inline void * bus_to_virt(unsigned long address)
 {
+	/*
+	 * This check is a sanity check but also ensures that bus
+	 * address 0 maps to virtual address 0 which is useful to
+	 * detect null "pointers" (the NCR driver is much simpler if
+	 * NULL pointers are preserved).
+	 */
+	if (address < APECS_DMA_WIN_BASE)
+		return 0;
 	return phys_to_virt(address - APECS_DMA_WIN_BASE);
 }
 
diff -u --recursive --new-file v1.3.49/linux/include/asm-alpha/byteorder.h linux/include/asm-alpha/byteorder.h
--- v1.3.49/linux/include/asm-alpha/byteorder.h	Tue Aug 15 20:39:04 1995
+++ linux/include/asm-alpha/byteorder.h	Fri Dec 22 08:22:05 1995
@@ -34,10 +34,21 @@
 extern __inline__ unsigned long int
 __ntohl(unsigned long int x)
 {
-	return (((x & 0x000000ffU) << 24) |
-		((x & 0x0000ff00U) <<  8) |
-		((x & 0x00ff0000U) >>  8) |
-		((x & 0xff000000U) >> 24));
+	unsigned long int res, t1, t2;
+
+	__asm__
+	    ("bis	%3,%3,%0	# %0 is result; %0=aabbccdd
+	      extlh	%0,5,%1		# %1 = dd000000
+	      zap	%0,0xfd,%2	# %2 = 0000cc00
+	      sll	%2,5,%2		# %2 = 00198000
+	      s8addl	%2,%1,%1	# %1 = ddcc0000
+	      zap	%0,0xfb,%2	# %2 = 00bb0000
+	      srl	%2,8,%2		# %2 = 0000bb00
+	      extbl	%0,3,%0		# %0 = 000000aa
+	      or	%1,%0,%0	# %0 = ddcc00aa
+	      or	%2,%0,%0	# %0 = ddccbbaa"
+	     : "r="(res), "r="(t1), "r="(t2) : "r"(x));
+	return res;
 }
 
 #define __constant_ntohl(x) \
@@ -49,8 +60,15 @@
 extern __inline__ unsigned short int
 __ntohs(unsigned short int x)
 {
-	return (((x & 0x00ff) << 8) |
-		((x & 0xff00) >> 8));
+	unsigned long int res, t1;
+	
+	__asm__
+	    ("bis	%2,%2,%0	# v0 is result; swap in-place.  v0=aabb
+	      extwh	%0,7,%1		# t1 = bb00
+	      extbl	%0,1,%0		# v0 = 00aa
+	      bis	%0,%1,%0	# v0 = bbaa"
+	     : "r="(res), "r="(t1) : "r"(x));
+	return res;
 }
 
 #define __constant_ntohs(x) \
diff -u --recursive --new-file v1.3.49/linux/include/asm-alpha/fpu.h linux/include/asm-alpha/fpu.h
--- v1.3.49/linux/include/asm-alpha/fpu.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-alpha/fpu.h	Fri Dec 22 08:22:06 1995
@@ -0,0 +1,64 @@
+#ifndef __ASM_ALPHA_FPU_H
+#define __ASM_ALPHA_FPU_H
+
+/*
+ * Alpha floating-point control register defines:
+ */
+#define FPCR_INVD	(1UL<<49)	/* invalid op disable (opt.) */
+#define FPCR_DZED	(1UL<<50)	/* division by zero disable (opt.) */
+#define FPCR_OVFD	(1UL<<51)	/* overflow disable (optional) */
+#define FPCR_INV	(1UL<<52)	/* invalid operation */
+#define FPCR_DZE	(1UL<<53)	/* division by zero */
+#define FPCR_OVF	(1UL<<54)	/* overflow */
+#define FPCR_UNF	(1UL<<55)	/* underflow */
+#define FPCR_INE	(1UL<<56)	/* inexact */
+#define FPCR_IOV	(1UL<<57)	/* integer overflow */
+#define FPCR_UNDZ	(1UL<<60)	/* underflow to zero (opt.) */
+#define FPCR_UNFD	(1UL<<61)	/* underflow disable (opt.) */
+#define FPCR_INED	(1UL<<62)	/* inexact disable (opt.) */
+#define FPCR_SUM	(1UL<<63)	/* summary bit */
+
+#define FPCR_DYN_SHIFT	58		/* first dynamic rounding mode bit */
+#define FPCR_DYN_CHOPPED (0x0UL << FPCR_DYN_SHIFT)	/* towards 0 */
+#define FPCR_DYN_MINUS	 (0x1UL << FPCR_DYN_SHIFT)	/* towards -INF */
+#define FPCR_DYN_NORMAL	 (0x2UL << FPCR_DYN_SHIFT)	/* towards nearest */
+#define FPCR_DYN_PLUS	 (0x3UL << FPCR_DYN_SHIFT)	/* towards +INF */
+#define FPCR_DYN_MASK	 (0x3UL << FPCR_DYN_SHIFT)
+
+#define FPCR_MASK	0xfffe000000000000
+
+/*
+ * IEEE trap enables are implemented in software.  These per-thread
+ * bits are stored in the "flags" field of "struct thread_struct".
+ * Thus, the bits are defined so as not to conflict with the
+ * floating-point enable bit (which is architected).  On top of that,
+ * we want to make these bits compatible with OSF/1 so
+ * ieee_set_fp_control() etc. can be implemented easily and
+ * compatibly.  The corresponding definitions are in
+ * /usr/include/machine/fpu.h under OSF/1.
+ */
+#define IEEE_TRAP_ENABLE_INV	(1<<1)	/* invalid op */
+#define IEEE_TRAP_ENABLE_DZE	(1<<2)	/* division by zero */
+#define IEEE_TRAP_ENABLE_OVF	(1<<3)	/* overflow */
+#define IEEE_TRAP_ENABLE_UNF	(1<<4)	/* underflow */
+#define IEEE_TRAP_ENABLE_INE	(1<<5)	/* inexact */
+#define IEEE_TRAP_ENABLE_MASK	(IEEE_TRAP_ENABLE_INV | IEEE_TRAP_ENABLE_DZE |\
+				 IEEE_TRAP_ENABLE_OVF | IEEE_TRAP_ENABLE_UNF |\
+				 IEEE_TRAP_ENABLE_INE)
+
+/* status bits coming from fpcr: */
+#define IEEE_STATUS_INV		(1<<17)
+#define IEEE_STATUS_DZE		(1<<18)
+#define IEEE_STATUS_OVF		(1<<19)
+#define IEEE_STATUS_UNF		(1<<20)
+#define IEEE_STATUS_INE		(1<<21)
+
+#define IEEE_STATUS_MASK	(IEEE_STATUS_INV | IEEE_STATUS_DZE |	\
+				 IEEE_STATUS_OVF | IEEE_STATUS_UNF |	\
+				 IEEE_STATUS_INE)
+
+#define IEEE_STATUS_TO_EXCSUM_SHIFT	16
+
+#define IEEE_INHERIT    (1UL<<63)	/* inherit on thread create? */
+
+#endif /* __ASM_ALPHA_FPU_H */
diff -u --recursive --new-file v1.3.49/linux/include/asm-alpha/io.h linux/include/asm-alpha/io.h
--- v1.3.49/linux/include/asm-alpha/io.h	Sat Nov 25 19:04:48 1995
+++ linux/include/asm-alpha/io.h	Fri Dec 22 08:22:06 1995
@@ -124,8 +124,20 @@
 #ifndef inb_p
 # define inb_p		inb
 #endif
+#ifndef inw_p
+# define inw_p		inw
+#endif
+#ifndef inl_p
+# define inl_p		inl
+#endif
 #ifndef outb_p
 # define outb_p		outb
+#endif
+#ifndef outw_p
+# define outw_p		outw
+#endif
+#ifndef outl_p
+# define outl_p		outl
 #endif
 
 #ifndef inw_p
diff -u --recursive --new-file v1.3.49/linux/include/asm-alpha/lca.h linux/include/asm-alpha/lca.h
--- v1.3.49/linux/include/asm-alpha/lca.h	Wed Nov  8 07:11:41 1995
+++ linux/include/asm-alpha/lca.h	Fri Dec 22 08:22:06 1995
@@ -143,6 +143,14 @@
 
 extern inline void * bus_to_virt(unsigned long address)
 {
+	/*
+	 * This check is a sanity check but also ensures that bus
+	 * address 0 maps to virtual address 0 which is useful to
+	 * detect null "pointers" (the NCR driver is much simpler if
+	 * NULL pointers are preserved).
+	 */
+	if (address < LCA_DMA_WIN_BASE)
+		return 0;
 	return phys_to_virt(address - LCA_DMA_WIN_BASE);
 }
 
diff -u --recursive --new-file v1.3.49/linux/include/asm-alpha/param.h linux/include/asm-alpha/param.h
--- v1.3.49/linux/include/asm-alpha/param.h	Wed Oct  4 14:14:33 1995
+++ linux/include/asm-alpha/param.h	Fri Dec 22 08:22:06 1995
@@ -5,7 +5,7 @@
 
 #ifndef HZ
 # if defined(CONFIG_ALPHA_EB66) || defined(CONFIG_ALPHA_EB66P) || \
-     defined(CONFIG_ALPHA_EB64) || defined(CONFIG_ALPHA_EB64P)
+     defined(CONFIG_ALPHA_EB64P)
 #  define HZ	 977	/* Evaluation Boards seem to be a little odd */
 # else
 #  define HZ	1024	/* normal value for Alpha systems */
diff -u --recursive --new-file v1.3.49/linux/include/asm-alpha/processor.h linux/include/asm-alpha/processor.h
--- v1.3.49/linux/include/asm-alpha/processor.h	Sun Dec 17 11:43:22 1995
+++ linux/include/asm-alpha/processor.h	Fri Dec 22 08:22:06 1995
@@ -33,6 +33,10 @@
 	unsigned int pcc;
 	unsigned int asn;
 	unsigned long unique;
+	/*
+	 * bit  0.. 0: floating point enable (used by PALcode)
+	 * bit  1.. 5: IEEE_TRAP_ENABLE bits (see fpu.h)
+	 */
 	unsigned long flags;
 	unsigned long res1, res2;
 };
diff -u --recursive --new-file v1.3.49/linux/include/asm-alpha/ptrace.h linux/include/asm-alpha/ptrace.h
--- v1.3.49/linux/include/asm-alpha/ptrace.h	Wed Sep 13 12:45:32 1995
+++ linux/include/asm-alpha/ptrace.h	Fri Dec 22 08:22:06 1995
@@ -59,7 +59,7 @@
 	unsigned long r14;
 	unsigned long r15;
 	unsigned long r26;
-	unsigned long fp[32];
+	unsigned long fp[32];	/* fp[31] is fpcr */
 };
 
 #ifdef __KERNEL__
diff -u --recursive --new-file v1.3.49/linux/include/asm-alpha/unistd.h linux/include/asm-alpha/unistd.h
--- v1.3.49/linux/include/asm-alpha/unistd.h	Mon Dec 11 15:42:05 1995
+++ linux/include/asm-alpha/unistd.h	Fri Dec 22 08:22:06 1995
@@ -114,6 +114,11 @@
 #define __NR_shmdt		211
 #define __NR_shmget		212
 
+#define __NR_getsid		234
+
+#define __NR_getsysinfo		256
+#define __NR_setsysinfo		257
+
 /*
  * Linux-specific system calls begin at 300
  */
@@ -131,6 +136,10 @@
 #define __NR_reboot		311
 #define __NR_clone		312
 #define __NR_uselib		313
+#define __NR_mlock		314
+#define __NR_munlock		315
+#define __NR_mlockall		316
+#define __NR_munlockall		317
 
 #ifdef __LIBRARY__
 
diff -u --recursive --new-file v1.3.49/linux/include/linux/fs.h linux/include/linux/fs.h
--- v1.3.49/linux/include/linux/fs.h	Sun Dec 17 11:43:32 1995
+++ linux/include/linux/fs.h	Fri Dec 22 14:26:26 1995
@@ -250,12 +250,14 @@
 	unsigned long	i_blksize;
 	unsigned long	i_blocks;
 	unsigned long	i_version;
+	unsigned long	i_nrpages;
 	struct semaphore i_sem;
 	struct inode_operations *i_op;
 	struct super_block *i_sb;
 	struct wait_queue *i_wait;
 	struct file_lock *i_flock;
 	struct vm_area_struct *i_mmap;
+	struct page *i_pages;
 	struct dquot *i_dquot[MAXQUOTAS];
 	struct inode *i_next, *i_prev;
 	struct inode *i_hash_next, *i_hash_prev;
@@ -402,6 +404,8 @@
 	int (*rename) (struct inode *,const char *,int,struct inode *,const char *,int);
 	int (*readlink) (struct inode *,char *,int);
 	int (*follow_link) (struct inode *,struct inode *,int,int,struct inode **);
+	int (*readpage) (struct inode *, unsigned long, char *);
+	int (*writepage) (struct inode *, struct page *);
 	int (*bmap) (struct inode *,int);
 	void (*truncate) (struct inode *);
 	int (*permission) (struct inode *, int);
@@ -524,6 +528,7 @@
 
 extern int check_disk_change(kdev_t dev);
 extern void invalidate_inodes(kdev_t dev);
+extern void invalidate_inode_pages(struct inode *, unsigned long);
 extern void invalidate_buffers(kdev_t dev);
 extern int floppy_is_wp(int minor);
 extern void sync_inodes(kdev_t dev);
@@ -569,7 +574,7 @@
 }
 extern void set_blocksize(kdev_t dev, int size);
 extern struct buffer_head * bread(kdev_t dev, int block, int size);
-extern unsigned long bread_page(unsigned long addr,kdev_t dev,int b[],int size,int no_share);
+extern void bread_page(unsigned long addr,kdev_t dev,int b[],int size);
 extern void bwrite_page(unsigned long addr,kdev_t dev,int b[],int size);
 extern struct buffer_head * breada(kdev_t dev,int block, int size, 
 				   unsigned int pos, unsigned int filesize);
diff -u --recursive --new-file v1.3.49/linux/include/linux/iso_fs_sb.h linux/include/linux/iso_fs_sb.h
--- v1.3.49/linux/include/linux/iso_fs_sb.h	Wed Feb 22 08:15:14 1995
+++ linux/include/linux/iso_fs_sb.h	Fri Dec 22 08:51:08 1995
@@ -2,7 +2,7 @@
 #define _ISOFS_FS_SB
 
 /*
- * minix super-block data in memory
+ * iso9660 super-block data in memory
  */
 struct isofs_sb_info {
 			unsigned long s_ninodes;
@@ -15,6 +15,7 @@
 			unsigned char s_mapping;
 			unsigned char s_conversion;
 			unsigned char s_rock;
+			unsigned char s_name_check; /* r = relaxed, s = strict */
 			unsigned char s_cruft; /* Broken disks with high
 						  byte of length containing
 						  junk */
diff -u --recursive --new-file v1.3.49/linux/include/linux/mm.h linux/include/linux/mm.h
--- v1.3.49/linux/include/linux/mm.h	Tue Nov 21 13:22:13 1995
+++ linux/include/linux/mm.h	Fri Dec 22 21:27:54 1995
@@ -106,11 +106,17 @@
 	pte_t (*swapin)(struct vm_area_struct *, unsigned long, unsigned long);
 };
 
-typedef struct {
-	unsigned count:24,
+typedef struct page {
+	unsigned int count;
+	unsigned dirty:16,
 		 age:6,
-		 dirty:1,
+		 unused:9,
 		 reserved:1;
+	unsigned long offset;
+	struct inode *inode;
+	struct page *write_list;
+	struct page *next, *prev;
+	struct page *next_hash, *prev_hash;
 } mem_map_t;
 
 extern mem_map_t * mem_map;
@@ -208,6 +214,10 @@
 extern void exit_mmap(struct mm_struct *);
 extern int do_munmap(unsigned long, size_t);
 extern unsigned long get_unmapped_area(unsigned long, unsigned long);
+
+/* filemap.c */
+extern unsigned long page_unuse(unsigned long);
+extern int shrink_mmap(int, unsigned long);
 
 #define read_swap_page(nr,buf) \
 	rw_swap_page(READ,(nr),(buf))
diff -u --recursive --new-file v1.3.49/linux/include/linux/module.h linux/include/linux/module.h
--- v1.3.49/linux/include/linux/module.h	Sat Nov 11 17:41:34 1995
+++ linux/include/linux/module.h	Fri Dec 22 08:22:06 1995
@@ -12,14 +12,10 @@
 #  undef  MODVERSIONS
 #  define MODVERSIONS
 #else /* ! __GENKSYMS__ */
-# ifdef MODVERSIONS
-#  ifndef MODULE
-#   ifdef EXPORT_SYMTAB
-#    define _set_ver(sym,vers) sym
-#    include <linux/modversions.h>
-#   endif /* EXPORT_SYMTAB */
-#  endif /* MODULE */
-# endif /* MODVERSIONS */
+# if defined(MODVERSIONS) && !defined(MODULE) && defined(EXPORT_SYMTAB)
+#   define _set_ver(sym,vers) sym
+#   include <linux/modversions.h>
+# endif
 #endif /* __GENKSYMS__ */
 
 /* values of module.state */
diff -u --recursive --new-file v1.3.49/linux/include/linux/pagemap.h linux/include/linux/pagemap.h
--- v1.3.49/linux/include/linux/pagemap.h	Thu Jan  1 02:00:00 1970
+++ linux/include/linux/pagemap.h	Fri Dec 22 21:05:52 1995
@@ -0,0 +1,92 @@
+#ifndef _LINUX_PAGEMAP_H
+#define _LINUX_PAGEMAP_H
+
+/*
+ * Page-mapping primitive inline functions
+ *
+ * Copyright 1995 Linus Torvalds
+ */
+
+static inline unsigned long page_address(struct page * page)
+{
+	return PAGE_OFFSET + PAGE_SIZE*(page - mem_map);
+}
+
+#define PAGE_HASH_SIZE 257
+
+extern struct page * page_hash_table[PAGE_HASH_SIZE];
+
+static inline unsigned long _page_hashfn(struct inode * inode, unsigned long offset)
+{
+	offset ^= (unsigned long) inode;
+	return offset % PAGE_HASH_SIZE;
+}
+
+#define page_hash(inode,offset) page_hash_table[_page_hashfn(inode,offset)]
+
+static inline struct page * find_page(struct inode * inode, unsigned long offset)
+{
+	struct page *page;
+
+	for (page = page_hash(inode, offset); page ; page = page->next_hash) {
+		if (page->inode != inode)
+			continue;
+		if (page->offset != offset)
+			continue;
+		break;
+	}
+	return page;
+}
+
+static inline void remove_page_from_hash_queue(struct page * page)
+{
+	struct page **p = &page_hash(page->inode,page->offset);
+
+	if (page->next_hash)
+		page->next_hash->prev_hash = page->prev_hash;
+	if (page->prev_hash)
+		page->prev_hash->next_hash = page->next_hash;
+	if (*p == page)
+		*p = page->next_hash;
+	page->next_hash = page->prev_hash = NULL;
+}
+
+static inline void add_page_to_hash_queue(struct inode * inode, struct page * page)
+{
+	struct page **p = &page_hash(inode,page->offset);
+
+	page->prev_hash = NULL;
+	if ((page->next_hash = *p) != NULL)
+		page->next_hash->prev_hash = page;
+	*p = page;
+}
+
+static inline void remove_page_from_inode_queue(struct page * page)
+{
+	struct inode * inode = page->inode;
+
+	page->inode = NULL;
+	inode->i_nrpages--;
+	if (inode->i_pages == page)
+		inode->i_pages = page->next;
+	if (page->next)
+		page->next->prev = page->prev;
+	if (page->prev)
+		page->prev->next = page->next;
+	page->next = NULL;
+	page->prev = NULL;
+}
+
+static inline void add_page_to_inode_queue(struct inode * inode, struct page * page)
+{
+	struct page **p = &inode->i_pages;
+
+	inode->i_nrpages++;
+	page->inode = inode;
+	page->prev = NULL;
+	if ((page->next = *p) != NULL)
+		page->next->prev = page;
+	*p = page;
+}
+
+#endif
diff -u --recursive --new-file v1.3.49/linux/include/linux/proc_fs.h linux/include/linux/proc_fs.h
--- v1.3.49/linux/include/linux/proc_fs.h	Wed Dec 13 09:02:47 1995
+++ linux/include/linux/proc_fs.h	Fri Dec 22 21:28:03 1995
@@ -35,7 +35,8 @@
 	PROC_DMA,	
 	PROC_IOPORTS,
 	PROC_APM,
-	PROC_PROFILE /* whether enabled or not */
+	PROC_PROFILE, /* whether enabled or not */
+	PROC_CMDLINE
 };
 
 enum pid_directory_inos {
diff -u --recursive --new-file v1.3.49/linux/init/main.c linux/init/main.c
--- v1.3.49/linux/init/main.c	Sun Dec 17 11:43:32 1995
+++ linux/init/main.c	Fri Dec 22 21:21:01 1995
@@ -43,6 +43,7 @@
 extern int console_loglevel;
 
 static int init(void *);
+extern int bdflush(void *);
 
 extern void init_IRQ(void);
 extern void init_modules(void);
@@ -101,9 +102,11 @@
 #ifdef CONFIG_SJCD
 extern void sjcd_setup(char *str, int *ints);
 #endif CONFIG_SJCD
+#ifdef CONFIG_BLK_DEV_RAM
 static void ramdisk_start_setup(char *str, int *ints);
 static void load_ramdisk(char *str, int *ints);
 static void prompt_ramdisk(char *str, int *ints);
+#endif CONFIG_BLK_DEV_RAM
 
 #ifdef CONFIG_SYSVIPC
 extern void ipc_init(void);
@@ -122,9 +125,12 @@
 
 int rows, cols;
 
+#ifdef CONFIG_BLK_DEV_RAM
 extern int rd_doload;		/* 1 = load ramdisk, 0 = don't load */
 extern int rd_prompt;		/* 1 = prompt for ramdisk, 0 = don't prompt */
 extern int rd_image_start;	/* starting block # of image */
+#endif
+
 int root_mountflags = MS_RDONLY;
 char *execute_command = 0;
 
@@ -176,9 +182,11 @@
 } bootsetups[] = {
 	{ "reserve=", reserve_setup },
 	{ "profile=", profile_setup },
+#ifdef CONFIG_BLK_DEV_RAM
 	{ "ramdisk_start=", ramdisk_start_setup },
-	{ "load_ramdisk", load_ramdisk },
-	{ "prompt_ramdisk", prompt_ramdisk },
+	{ "load_ramdisk=", load_ramdisk },
+	{ "prompt_ramdisk=", prompt_ramdisk },
+#endif
 	{ "swap=", swap_setup },
 	{ "buff=", buff_setup },
 #ifdef CONFIG_BUGi386
@@ -273,6 +281,7 @@
 	{ 0, 0 }
 };
 
+#ifdef CONFIG_BLK_DEV_RAM
 static void ramdisk_start_setup(char *str, int *ints)
 {
    if (ints[0] > 0 && ints[1] >= 0)
@@ -281,13 +290,16 @@
 
 static void load_ramdisk(char *str, int *ints)
 {
-	rd_doload = 1;
+   if (ints[0] > 0 && ints[1] >= 0)
+      rd_doload = ints[1] & 1;
 }
 
 static void prompt_ramdisk(char *str, int *ints)
 {
-	rd_prompt = 1;
+   if (ints[0] > 0 && ints[1] >= 0)
+      rd_prompt = ints[1] & 1;
 }
+#endif
 
 static int checksetup(char *line)
 {
@@ -657,6 +669,9 @@
 static int init(void * unused)
 {
 	int pid,i;
+
+	/* Launch bdflush from here, instead of the old syscall way. */
+	kernel_thread(bdflush, NULL, 0);
 
 	setup();
 
diff -u --recursive --new-file v1.3.49/linux/kernel/ksyms.c linux/kernel/ksyms.c
--- v1.3.49/linux/kernel/ksyms.c	Thu Dec 21 08:53:33 1995
+++ linux/kernel/ksyms.c	Fri Dec 22 08:22:06 1995
@@ -398,7 +398,7 @@
 #if	defined(CONFIG_ULTRA)	||	defined(CONFIG_WD80x3)		|| \
 	defined(CONFIG_EL2)	||	defined(CONFIG_NE2000)		|| \
 	defined(CONFIG_E2100)	||	defined(CONFIG_HPLAN_PLUS)	|| \
-	defined(CONFIG_HPLAN)	||	defined(CONFIG_AC3200)		
+	defined(CONFIG_HPLAN)	||	defined(CONFIG_AC3200)
 	/* If 8390 NIC support is built in, we will need these. */
 	X(ei_open),
 	X(ei_close),
@@ -415,6 +415,9 @@
 	X(slhc_compress),
 	X(slhc_uncompress),
 	X(slhc_toss),
+#endif
+#ifdef CONFIG_NET_ALIAS
+#include <linux/net_alias.h>
 #endif
 #endif
 	/* Device callback registration */
diff -u --recursive --new-file v1.3.49/linux/kernel/module.c linux/kernel/module.c
--- v1.3.49/linux/kernel/module.c	Mon Dec 11 15:42:06 1995
+++ linux/kernel/module.c	Fri Dec 22 08:22:06 1995
@@ -258,18 +258,17 @@
 			newtab->n_symbols * sizeof(struct internal_symbol) +
 			newtab->n_refs * sizeof(struct module_ref);
 
-		if ((newtab->n_symbols < 0) || (newtab->n_refs < 0) ||
-			(legal_start > size)) {
-			printk("Illegal symbol table! Rejected!\n");
+		if ((newtab->n_symbols < 0) || (newtab->n_refs < 0) || (legal_start > size)) {
+			printk("Rejecting illegal symbol table (n_symbols=%d,n_refs=%d)\n",
+			       newtab->n_symbols, newtab->n_refs);
 			kfree_s(newtab, size);
 			return -EINVAL;
 		}
 
 		/* relocate name pointers, index referred from start of table */
-		for (sym = &(newtab->symbol[0]), i = 0;
-			i < newtab->n_symbols; ++sym, ++i) {
+		for (sym = &(newtab->symbol[0]), i = 0; i < newtab->n_symbols; ++sym, ++i) {
 			if ((unsigned long)sym->name < legal_start || size <= (unsigned long)sym->name) {
-				printk("Illegal symbol table! Rejected!\n");
+				printk("Rejecting illegal symbol table\n");
 				kfree_s(newtab, size);
 				return -EINVAL;
 			}
diff -u --recursive --new-file v1.3.49/linux/mm/filemap.c linux/mm/filemap.c
--- v1.3.49/linux/mm/filemap.c	Sun Dec 17 11:43:33 1995
+++ linux/mm/filemap.c	Sun Dec 24 11:47:39 1995
@@ -20,6 +20,7 @@
 #include <linux/malloc.h>
 #include <linux/fs.h>
 #include <linux/locks.h>
+#include <linux/pagemap.h>
 
 #include <asm/segment.h>
 #include <asm/system.h>
@@ -32,20 +33,111 @@
  * Shared mappings now work. 15.8.1995  Bruno.
  */
 
+struct page * page_hash_table[PAGE_HASH_SIZE];
+
 /*
  * Simple routines for both non-shared and shared mappings.
  */
 
-static inline void multi_bmap(struct inode * inode, unsigned long block, unsigned int * nr, int shift)
+void invalidate_inode_pages(struct inode * inode, unsigned long start)
+{
+	struct page ** p = &inode->i_pages;
+	struct page * page;
+
+	while ((page = *p) != NULL) {
+		unsigned long offset = page->offset;
+
+		/* page wholly truncated - free it */
+		if (offset >= start) {
+			inode->i_nrpages--;
+			if ((*p = page->next) != NULL)
+				(*p)->prev = page->prev;
+			page->dirty = 0;
+			page->next = NULL;
+			page->prev = NULL;
+			remove_page_from_hash_queue(page);
+			page->inode = NULL;
+			free_page(page_address(page));
+			continue;
+		}
+		p = &page->next;
+		offset = start - offset;
+		/* partial truncate, clear end of page */
+		if (offset < PAGE_SIZE)
+			memset((void *) (offset + page_address(page)), 0, PAGE_SIZE - offset);
+	}
+}
+
+int shrink_mmap(int priority, unsigned long limit)
+{
+	static int clock = 0;
+	struct page * page;
+
+	if (limit > high_memory)
+		limit = high_memory;
+	limit = MAP_NR(limit);
+	if (clock >= limit)
+		clock = 0;
+	priority = limit >> (2*priority);
+	page = mem_map + clock;
+	while (priority-- > 0) {
+		if (page->inode && page->count == 1) {
+			remove_page_from_hash_queue(page);
+			remove_page_from_inode_queue(page);
+			free_page(page_address(page));
+			return 1;
+		}
+		page++;
+		clock++;
+		if (clock >= limit) {
+			clock = 0;
+			page = mem_map;
+		}
+	}
+	return 0;
+}
+
+/*
+ * This is called from try_to_swap_out() when we try to egt rid of some
+ * pages..  If we're unmapping the last occurrence of this page, we also
+ * free it from the page hash-queues etc, as we don't want to keep it
+ * in-core unnecessarily.
+ */
+unsigned long page_unuse(unsigned long page)
+{
+	struct page * p = mem_map + MAP_NR(page);
+	int count = p->count;
+
+	if (count != 2)
+		return count;
+	if (!p->inode)
+		return count;
+	remove_page_from_hash_queue(p);
+	remove_page_from_inode_queue(p);
+	free_page(page);
+	return 1;
+}
+
+/*
+ * This should be a low-level fs-specific function (ie
+ * inode->i_op->readpage).
+ */
+static int readpage(struct inode * inode, unsigned long offset, char * page)
 {
-	int i = PAGE_SIZE >> shift;
-	block >>= shift;
+	int *p, nr[PAGE_SIZE/512];
+	int i;
+
+	i = PAGE_SIZE >> inode->i_sb->s_blocksize_bits;
+	offset >>= inode->i_sb->s_blocksize_bits;
+	p = nr;
 	do {
-		*nr = bmap(inode, block);
+		*p = inode->i_op->bmap(inode, offset);
 		i--;
-		block++;
-		nr++;
+		offset++;
+		p++;
 	} while (i > 0);
+	bread_page((unsigned long) page, inode->i_dev, nr, inode->i_sb->s_blocksize);
+	return 0;
 }
 
 /*
@@ -57,15 +149,51 @@
 	unsigned long page, int no_share)
 {
 	struct inode * inode = area->vm_inode;
-	int nr[PAGE_SIZE/512];
+	unsigned long new_page, old_page;
+	struct page *p;
 
 	address = (address & PAGE_MASK) - area->vm_start + area->vm_offset;
 	if (address >= inode->i_size && (area->vm_flags & VM_SHARED) && area->vm_mm == current->mm)
 		send_sig(SIGBUS, current, 1);
-	multi_bmap(inode, address, nr, inode->i_sb->s_blocksize_bits);
-	return bread_page(page, inode->i_dev, nr, inode->i_sb->s_blocksize, no_share);
+	p = find_page(inode, address);
+	if (p)
+		goto old_page_exists;
+	new_page = 0;
+	if (no_share) {
+		new_page = __get_free_page(GFP_USER);
+		if (!new_page) {
+			oom(current);
+			return page;
+		}
+	}
+	/* inode->i_op-> */ readpage(inode, address, (char *) page);
+	p = find_page(inode, address);
+	if (p)
+		goto old_and_new_page_exists;
+	p = mem_map + MAP_NR(page);
+	p->offset = address;
+	add_page_to_inode_queue(inode, p);
+	add_page_to_hash_queue(inode, p);
+	if (new_page) {
+		memcpy((void *) new_page, (void *) page, PAGE_SIZE);
+		return new_page;
+	}
+	p->count++;
+	return page;
+
+old_and_new_page_exists:
+	if (new_page)
+		free_page(new_page);
+old_page_exists:
+	old_page = page_address(p);
+	if (no_share) {
+		memcpy((void *) page, (void *) old_page, PAGE_SIZE);
+		return page;
+	}
+	p->count++;
+	free_page(page);
+	return old_page;
 }
-
 
 /*
  * Tries to write a shared mapped page to its backing store. May return -EIO
diff -u --recursive --new-file v1.3.49/linux/mm/memory.c linux/mm/memory.c
--- v1.3.49/linux/mm/memory.c	Thu Dec 21 08:53:33 1995
+++ linux/mm/memory.c	Sun Dec 24 11:47:40 1995
@@ -916,62 +916,39 @@
 }
 
 /*
- * This function tries to find a page that is shared with the buffer cache,
- * and if so it moves the buffer cache to a new location.
- *
- * It returns non-zero if we used up the "new_page" page.
+ * This function zeroes out partial mmap'ed pages at truncation time..
  */
-static int unshare(struct vm_area_struct *vma, unsigned long address, unsigned long new_page)
+static void partial_clear(struct vm_area_struct *vma, unsigned long address)
 {
 	pgd_t *page_dir;
 	pmd_t *page_middle;
 	pte_t *page_table, pte;
-	unsigned long old_page;
-	struct buffer_head * bh, * tmp;
 
 	page_dir = pgd_offset(vma->vm_mm, address);
 	if (pgd_none(*page_dir))
-		return 0;
+		return;
 	if (pgd_bad(*page_dir)) {
 		printk("bad page table directory entry %p:[%lx]\n", page_dir, pgd_val(*page_dir));
 		pgd_clear(page_dir);
-		return 0;
+		return;
 	}
 	page_middle = pmd_offset(page_dir, address);
 	if (pmd_none(*page_middle))
-		return 0;
+		return;
 	if (pmd_bad(*page_middle)) {
 		printk("bad page table directory entry %p:[%lx]\n", page_dir, pgd_val(*page_dir));
 		pmd_clear(page_middle);
-		return 0;
+		return;
 	}
 	page_table = pte_offset(page_middle, address);
 	pte = *page_table;
 	if (!pte_present(pte))
-		return 0;
-	old_page = pte_page(pte);
-	if (MAP_NR(old_page) > MAP_NR(high_memory))
-		return 0;
+		return;
 	address &= ~PAGE_MASK;
-	memset((void *) (old_page + address), 0, PAGE_SIZE - address);
-	bh = buffer_pages[MAP_NR(old_page)];
-	if (!bh)
-		return 0;
-	if (!new_page) {
-		printk("Aieee... unshare(): no page available\n");
-		return 0;
-	}
-	buffer_pages[MAP_NR(old_page)] = NULL;
-	copy_page(old_page, new_page);
-	free_page(old_page);
-	old_page -= new_page;
-	buffer_pages[MAP_NR(new_page)] = bh;
-	tmp = bh;
-	do {
-		tmp->b_data -= old_page;
-		tmp = tmp->b_this_page;
-	} while (tmp != bh);
-	return 1;
+	address += pte_page(pte);
+	if (address >= high_memory)
+		return;
+	memset((void *) address, 0, PAGE_SIZE - (address & ~PAGE_MASK));
 }
 
 /*
@@ -984,17 +961,12 @@
  */
 void vmtruncate(struct inode * inode, unsigned long offset)
 {
-	unsigned long page;
 	struct vm_area_struct * mpnt;
 
+	invalidate_inode_pages(inode, offset);
 	if (!inode->i_mmap)
 		return;
-	page = __get_free_page(GFP_KERNEL);
 	mpnt = inode->i_mmap;
-	if (!mpnt) {
-		free_page(page);
-		return;
-	}
 	do {
 		unsigned long start = mpnt->vm_start;
 		unsigned long len = mpnt->vm_end - start;
@@ -1012,15 +984,12 @@
 		/* Ok, partially affected.. */
 		start += diff;
 		len = (len - diff) & PAGE_MASK;
-		/* Ugh, here comes the _really_ ugly part.. */
 		if (start & ~PAGE_MASK) {
-			if (unshare(mpnt, start, page))
-				page = 0;
+			partial_clear(mpnt, start);
 			start = (start + ~PAGE_MASK) & PAGE_MASK;
 		}
 		zap_page_range(mpnt->vm_mm, start, len);
 	} while ((mpnt = mpnt->vm_next_share) != inode->i_mmap);
-	free_page(page);
 }
 
 /*
diff -u --recursive --new-file v1.3.49/linux/mm/swap.c linux/mm/swap.c
--- v1.3.49/linux/mm/swap.c	Sun Dec 17 11:43:33 1995
+++ linux/mm/swap.c	Fri Dec 22 14:08:18 1995
@@ -479,7 +479,7 @@
 	vma->vm_mm->rss--;
 	pte_clear(page_table);
 	invalidate_page(vma, address);
-	entry = mem_map[MAP_NR(page)].count;
+	entry = page_unuse(page);
 	free_page(page);
 	return entry;
 }
@@ -687,6 +687,10 @@
 			if (shm_swap(i, limit))
 				return 1;
 			state = 2;
+		case 2:
+			if (shrink_mmap(i, limit))
+				return 1;
+			state = 3;
 		default:
 			if (swap_out(i, limit))
 				return 1;
@@ -1324,6 +1328,11 @@
 		p->count = 0;
 		p->dirty = 0;
 		p->reserved = 1;
+		p->inode = NULL;
+		p->offset = 0;
+		p->write_list = NULL;
+		p->next = p->prev = NULL;
+		p->next_hash = p->next_hash = NULL;
 	}
 
 	for (i = 0 ; i < NR_MEM_LISTS ; i++) {
diff -u --recursive --new-file v1.3.49/linux/scripts/tkgen.c linux/scripts/tkgen.c
--- v1.3.49/linux/scripts/tkgen.c	Thu Nov  9 11:23:57 1995
+++ linux/scripts/tkgen.c	Fri Dec 22 08:22:06 1995
@@ -499,10 +499,10 @@
       case tok_dep_tristate:
       case tok_int:
       case tok_choose:
-      case tok_choice:
       case tok_sound:
 	tot++;
 	break;
+      case tok_choice:
       default:
 	break;
       }
@@ -561,7 +561,6 @@
 	case tok_dep_tristate:
 	case tok_int:
 	case tok_choose:
-	case tok_choice:
 	case tok_sound:
 	  /*
 	   * If we have overfilled the menu, then go to the next one.
@@ -578,6 +577,7 @@
 	  break;
 	case tok_define:
 	  cfg->menu_number = -1;
+	case tok_choice:
 	default:
 	  break;
 	};
