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 - 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. where 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 + + 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 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_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 #include +#include +#include #include #include -#include 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 #include #include +#include -#include #include +#include +#include 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(®s, write_mask)) { + return; /* emulation was successful */ + } + } + printk("Arithmetic trap at %016lx: %02lx %016lx\n", + regs.pc, summary, write_mask); die_if_kernel("Arithmetic fault", ®s, 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 + +#include +#include + +#include + +#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 + +#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", ®s, 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 +#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 +#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 /* * 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;irxRingMask;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;itxRingMask;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;iphys_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 #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 #include #include @@ -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= 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= '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 -# endif /* EXPORT_SYMTAB */ -# endif /* MODULE */ -# endif /* MODVERSIONS */ +# if defined(MODVERSIONS) && !defined(MODULE) && defined(EXPORT_SYMTAB) +# define _set_ver(sym,vers) sym +# include +# 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 #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 #include #include +#include #include #include @@ -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; };