diff -u --recursive --new-file v1.3.21/linux/CREDITS linux/CREDITS
--- v1.3.21/linux/CREDITS	Mon Aug 28 14:52:17 1995
+++ linux/CREDITS	Thu Aug 31 08:09:08 1995
@@ -522,8 +522,9 @@
 
 N: Mark Lord
 E: mlord@bnr.ca
-E: mlord@achilles.net
-D: IDE drive support in hd.c
+D: Author of IDE driver (ide.c), hd.c support
+D: Triton Bus Master IDE driver
+D: Hard Disk Parameter (hdparm) utility
 S: 33 Ridgefield Cr
 S: Nepean, Ontario
 S: Canada K2H 6S3
diff -u --recursive --new-file v1.3.21/linux/Documentation/devices.tex linux/Documentation/devices.tex
--- v1.3.21/linux/Documentation/devices.tex	Thu Jan  1 02:00:00 1970
+++ linux/Documentation/devices.tex	Tue Aug 29 09:52:50 1995
@@ -0,0 +1,818 @@
+\documentstyle{article}
+%
+% Adopt somewhat reasonable margins, so it doesn't take a million
+% pages to print... :-)  If you're actually putting this in print, you
+% may wish to change these.
+%
+\oddsidemargin=0in
+\textwidth=6.5in
+\topmargin=0in
+\headheight=0.5in
+\headsep=0.25in
+\textheight=7.5in
+\footskip=0.75in
+\footheight=0.5in
+%
+\begin{document}
+\newcommand{\file}{\tt}			% Style to use for a filename
+\newcommand{\hex}{\tt}			% Style to use for a hex number
+\newcommand{\ud}{(Under development)}	% Abbreviation
+\newcommand{\1}{\({}^1\)}
+\newcommand{\2}{\({}^2\)}
+\newcommand{\3}{\({}^3\)}
+\newcommand{\4}{\({}^4\)}
+\newlength{\dig}
+\settowidth{\dig}{0}			% Get width of digits
+\newcommand{\num}[2]{\makebox[#1\dig][r]{#2}}
+\newcommand{\major}[4]{\num{3}{#1}#2 \> #3 \> #4 \\}
+\newcommand{\minor}[3]{\> \> \num{3}{#1} \> {\file #2} \> #3 \\}
+\newcommand{\minordots}{\> \> \> \dots \\}
+\newenvironment{devicelist}%
+ {\begin{tabbing}%
+000--000 \= blockxxx \= 000 \= {\file /dev/crambamboli} \= foo \kill}%
+ {\end{tabbing}}
+\newcommand{\link}[4]{{\file #1} \> {\file #2} \> #3 \> #4 \\}
+\newcommand{\vlink}[4]{{\file #1} \> {\em #2 \/} \> #3 \> #4 \\}
+\newcommand{\node}[3]{{\file #1} \> #2 \> #3 \\}
+\newenvironment{nodelist}%
+ {\begin{tabbing}%
+{\file /dev/crambamboli} \= {\file /proc/self/fd/99} \= symbolicxxx \=
+foo \kill}%
+ {\end{tabbing}}
+%
+\title{{\bf Linux Allocated Devices}}
+\author{Maintained by H. Peter Anvin $<$Peter.Anvin@linux.org$>$}
+\date{Last revised: August 28, 1995}
+\maketitle
+%
+\noindent
+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
+{\file /dev} directory nodes for these devices.
+
+This list is available 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).  In cases of
+discrepancy, the \LaTeX\ version has priority.
+
+This document is included by reference into the Linux Filesystem
+Standard (FSSTND).  The FSSTND is available via FTP from
+tsx-11.mit.edu in the directory {\file
+/pub/linux/docs/linux-standards/fsstnd}.
+
+To have a major number allocated, or a minor number in situations
+where that applies (e.g.\ busmice), please contact me.  Also, if you
+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.
+
+\section{Major numbers}
+
+\begin{devicelist}
+\major{ 0}{}{     }{Unnamed devices (NFS mounts, loopback devices)}
+\major{ 1}{}{char }{Memory devices}
+\major{  }{}{block}{RAM disk}
+\major{ 2}{}{char }{Reserved for PTY's $<$tytso@athena.mit.edu$>$}
+\major{  }{}{block}{Floppy disks}
+\major{ 3}{}{char }{Reserved for PTY's $<$tytso@athena.mit.edu$>$}
+\major{  }{}{block}{First MFM, RLL and IDE hard disk/CD-ROM interface}
+\major{ 4}{}{char }{TTY devices}
+\major{ 5}{}{char }{Alternate TTY devices}
+\major{ 6}{}{char }{Parallel printer devices}
+\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{10}{}{char }{Non-serial mice, misc features}
+\major{11}{}{block}{SCSI CD-ROM devices}
+\major{12}{}{char }{QIC-02 tape}
+\major{  }{}{block}{MSCDEX CD-ROM callback support}
+\major{13}{}{char }{PC speaker}
+\major{  }{}{block}{8-bit MFM/RLL/IDE controller}
+\major{14}{}{char }{Sound card}
+\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{  }{}{block}{GoldStar CD-ROM}
+\major{17}{}{char }{Chase serial card}
+\major{  }{}{block}{Optics Storage CD-ROM}
+\major{18}{}{char }{Chase serial card -- alternate devices}
+\major{  }{}{block}{Sanyo CD-ROM}
+\major{19}{}{char }{Cyclades serial card}
+\major{  }{}{block}{Double compressed disk}
+\major{20}{}{char }{Cyclades serial card -- alternate devices}
+\major{  }{}{block}{Hitachi CD-ROM}
+\major{21}{}{char }{Generic SCSI access}
+\major{22}{}{char }{Digiboard serial card}
+\major{  }{}{block}{Second IDE hard disk/CD-ROM interface}
+\major{23}{}{char }{Digiboard serial card -- alternate devices}
+\major{  }{}{block}{Mitsumi proprietary CD-ROM}
+\major{24}{}{char }{Stallion serial card}
+\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{27}{}{char }{QIC-117 tape}
+\major{  }{}{block}{Third Matsushita (Panasonic/SoundBlaster) CD-ROM}
+\major{28}{}{char }{Stallion serial card -- card programming}
+\major{  }{}{block}{Fourth Matsushita (Panasonic/SoundBlaster) CD-ROM}
+\major{  }{}{block}{ACSI disk (68k)}
+\major{29}{}{char }{Universal frame buffer}
+\major{  }{}{block}{Aztech/Orchid/Okano/Wearnes CD-ROM}
+\major{30}{}{char }{iBCS-2}
+\major{  }{}{block}{Philips LMS-205 CD-ROM}
+\major{31}{}{char }{MPU-401 MIDI}
+\major{  }{}{block}{ROM/flash memory card}
+\major{32}{}{char }{Specialix serial card}
+\major{  }{}{block}{Philips LMS-206 CD-ROM}
+\major{33}{}{char }{Specialix serial card -- alternate devices}
+\major{  }{}{block}{Modular RAM disk}
+\major{34}{}{block}{Third IDE hard disk/CD-ROM interface}
+\major{35}{}{block}{Fourth IDE hard disk/CD-ROM interface}
+\major{36--223}{}{}{Unallocated}
+\major{224--254}{}{}{Local use}
+\major{255}{}{}{Reserved}
+\end{devicelist}
+
+\section{Minor numbers}
+
+
+\begin{devicelist}
+\major{0}{}{}{Unnamed devices (NFS mounts, loopback devices)}
+	\minor{0}{}{reserved as null device number}
+\end{devicelist}
+
+\begin{devicelist}
+\major{1}{}{char}{Memory devices}
+	\minor{1}{/dev/mem}{Physical memory access}
+	\minor{2}{/dev/kmem}{Kernel virtual memory access}
+	\minor{3}{/dev/null}{Null device}
+	\minor{4}{/dev/port}{I/O port access}
+	\minor{5}{/dev/zero}{Null byte source}
+	\minor{6}{/dev/core}{OBSOLETE -- should be a link to {\file /proc/kcore}}
+	\minor{7}{/dev/full}{Returns ENOSPC on write}
+	\minor{8}{/dev/random}{Nondeterministic random number generator}
+	\minor{9}{/dev/urandom}{Less secure, but faster random number generator}
+\\
+\major{}{}{block}{RAM disk}
+	\minor{1}{/dev/ramdisk}{RAM disk}
+\end{devicelist}
+
+\begin{devicelist}
+\major{2}{}{char}{Reserved for PTY's $<$tytso@athena.mit.edu$>$}
+\major{}{}{block}{Floppy disks}
+	\minor{0}{/dev/fd0}{Controller 1, drive 1 autodetect}
+	\minor{1}{/dev/fd1}{Controller 1, drive 2 autodetect}
+	\minor{2}{/dev/fd2}{Controller 1, drive 3 autodetect}
+	\minor{3}{/dev/fd3}{Controller 1, drive 4 autodetect}
+	\minor{128}{/dev/fd4}{Controller 2, drive 1 autodetect}
+	\minor{129}{/dev/fd5}{Controller 2, drive 2 autodetect}
+	\minor{130}{/dev/fd6}{Controller 2, drive 3 autodetect}
+	\minor{131}{/dev/fd7}{Controller 2, drive 4 autodetect}
+\\
+\major{}{}{}{To specify format, add to the autodetect device number}
+	\minor{  0}{/dev/fd?}{Autodetect format}
+	\minor{  4}{/dev/fd?d360}{5.25" \num{4}{360}K in a \num{4}{360}K drive\1}
+	\minor{ 20}{/dev/fd?h360}{5.25" \num{4}{360}K in a 1200K drive\1}
+	\minor{ 48}{/dev/fd?h410}{5.25" \num{4}{410}K in a 1200K drive}
+	\minor{ 64}{/dev/fd?h420}{5.25" \num{4}{420}K in a 1200K drive}
+	\minor{ 24}{/dev/fd?h720}{5.25" \num{4}{720}K in a 1200K drive}
+	\minor{ 80}{/dev/fd?h880}{5.25" \num{4}{880}K in a 1200K drive\1}
+	\minor{  8}{/dev/fd?h1200}{5.25" 1200K in a 1200K drive\1}
+	\minor{ 40}{/dev/fd?h1440}{5.25" 1440K in a 1200K drive\1}
+	\minor{ 56}{/dev/fd?h1476}{5.25" 1476K in a 1200K drive}
+	\minor{ 72}{/dev/fd?h1494}{5.25" 1494K in a 1200K drive}
+	\minor{ 92}{/dev/fd?h1600}{5.25" 1600K in a 1200K drive\1}
+	\minor{}{}{}
+	\minor{ 12}{/dev/fd?u360}{3.5" \num{4}{360}K Double Density}
+	\minor{ 16}{/dev/fd?u720}{3.5" \num{4}{720}K Double Density\1}
+	\minor{120}{/dev/fd?u800}{3.5" \num{4}{800}K Double Density\2}
+	\minor{ 52}{/dev/fd?u820}{3.5" \num{4}{820}K Double Density}
+	\minor{ 68}{/dev/fd?u830}{3.5" \num{4}{830}K Double Density}
+	\minor{ 84}{/dev/fd?u1040}{3.5" 1040K Double Density\1}
+	\minor{ 88}{/dev/fd?u1120}{3.5" 1120K Double Density\1}
+	\minor{ 28}{/dev/fd?u1440}{3.5" 1440K High Density\1}
+	\minor{124}{/dev/fd?u1600}{3.5" 1600K High Density\1}
+	\minor{ 44}{/dev/fd?u1680}{3.5" 1680K High Density\3}
+	\minor{ 60}{/dev/fd?u1722}{3.5" 1722K High Density}
+	\minor{ 76}{/dev/fd?u1743}{3.5" 1743K High Density}
+	\minor{ 96}{/dev/fd?u1760}{3.5" 1760K High Density}
+	\minor{116}{/dev/fd?u1840}{3.5" 1840K High Density\3}
+	\minor{100}{/dev/fd?u1920}{3.5" 1920K High Density\1}
+	\minor{ 32}{/dev/fd?u2880}{3.5" 2880K Extra Density\1}
+	\minor{104}{/dev/fd?u3200}{3.5" 3200K Extra Density}
+	\minor{108}{/dev/fd?u3520}{3.5" 3520K Extra Density}
+	\minor{112}{/dev/fd?u3840}{3.5" 3840K Extra Density\1}
+	\minor{}{}{}
+	\minor{36}{/dev/fd?CompaQ}{Compaq 2880K drive; probably obsolete}
+\\
+\major{}{}{}{\1 Autodetectable format}
+\major{}{}{}{\2 Autodetectable format in a Double Density (720K) drive only}
+\major{}{}{}{\3 Autodetectable format in a High Density (1440K) drive only}
+\end{devicelist}
+
+NOTE: The letter in the device name ({\file d}, {\file q}, {\file h}
+or {\file u}) signifies the type of drive supported: 5.25" Double
+Density ({\file d}), 5.25" Quad Density ({\file q}), 5.25" High
+Density ({\file h}) or 3.5" (any type, {\file u}).  The capital
+letters {\file D}, {\file H}, or {\file E} for the 3.5" models have
+been deprecated, since the drive type is insignificant for these devices.
+
+\begin{devicelist}
+\major{3}{}{char}{Reserved for PTY's $<$tytso@athena.mit.edu$>$}
+\major{}{}{block}{First MFM, RLL and IDE hard disk/CD-ROM interface}
+	\minor{0}{/dev/hda}{Master: whole disk (or CD-ROM)}
+	\minor{64}{/dev/hdb}{Slave: whole disk (or CD-ROM)}
+\\
+\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}
+	\minordots
+	\minor{63}{/dev/hd?63}{59th logical partition}
+\end{devicelist}
+
+\begin{devicelist}
+\major{ 4}{}{char }{TTY devices}
+	\minor{0}{/dev/console}{Console device}
+	\minor{1}{/dev/tty1}{First virtual console}
+	\minordots
+	\minor{63}{/dev/tty63}{63rd virtual console}
+	\minor{64}{/dev/ttyS0}{First serial port}
+	\minordots
+	\minor{127}{/dev/ttyS63}{64th serial port}
+	\minor{128}{/dev/ptyp0}{First pseudo-tty master}
+	\minordots
+	\minor{191}{/dev/ptysf}{64th pseudo-tty master}
+	\minor{192}{/dev/ttyp0}{First pseudo-tty slave}
+	\minordots
+	\minor{255}{/dev/ttysf}{64th pseudo-tty slave}
+\end{devicelist}
+
+\noindent
+Pseudo-tty's are named as follows:
+\begin{itemize}
+\item Masters are {\file pty}, slaves are {\file tty};
+\item the fourth letter is one of {\file pqrs} indicating
+the 1st, 2nd, 3rd, 4th series of 16 pseudo-ttys each, and
+\item the fifth letter is one of {\file 0123456789abcdef} indicating
+the position within the series.
+\end{itemize}
+
+\begin{devicelist}
+\major{ 5}{}{char }{Alternate TTY devices}
+	\minor{0}{/dev/tty}{Current TTY device}
+	\minor{64}{/dev/cua0}{Callout device corresponding to {\file ttyS0}}
+	\minordots
+	\minor{127}{/dev/cua63}{Callout device corresponding to {\file ttyS63}}
+\end{devicelist}
+
+\begin{devicelist}
+\major{ 6}{}{char }{Parallel printer devices}
+	\minor{0}{/dev/lp0}{First parallel printer ({\hex 0x3bc})}
+	\minor{1}{/dev/lp1}{Second parallel printer ({\hex 0x378})}
+	\minor{2}{/dev/lp2}{Third parallel printer ({\hex 0x278})}
+\end{devicelist}
+
+\noindent
+Not all computers have the {\hex 0x3bc} parallel port, hence the
+"first" printer may be either {\file /dev/lp0} or {\file /dev/lp1}.
+
+\begin{devicelist}
+\major{ 7}{}{char }{Virtual console access devices}
+	\minor{0}{/dev/vcs}{Current vc text access}
+	\minor{1}{/dev/vcs1}{tty1 text access}
+	\minordots
+	\minor{63}{/dev/vcs63}{tty63 text access}
+	\minor{128}{/dev/vcsa}{Current vc text/attribute access}
+	\minor{129}{/dev/vcsa1}{tty1 text/attribute access}
+	\minordots
+	\minor{191}{/dev/vcsa63}{tty63 text/attribute access}
+\end{devicelist}
+
+\noindent
+NOTE: These devices permit both read and write access.
+
+\begin{devicelist}
+\major{ 8}{}{block}{SCSI disk devices}
+	\minor{0}{/dev/sda}{First SCSI disk whole disk}
+	\minor{16}{/dev/sdb}{Second SCSI disk whole disk}
+	\minor{32}{/dev/sdc}{Third SCSI disk whole disk}
+	\minordots
+	\minor{240}{/dev/sdp}{Sixteenth SCSI disk whole disk}
+\end{devicelist}
+
+\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.
+
+\begin{devicelist}
+\major{ 9}{}{char }{SCSI tape devices}
+	\minor{0}{/dev/st0}{First SCSI tape}
+	\minor{1}{/dev/st1}{Second SCSI tape}
+	\minordots
+	\minor{128}{/dev/nst0}{First SCSI tape, no rewind-on-close}
+	\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}
+	\minordots
+\end{devicelist}
+
+\noindent
+The multiple device driver is used to span a filesystem across multiple
+physical disks.
+
+\begin{devicelist}
+\major{10}{}{char }{Non-serial mice, misc features}
+	\minor{0}{/dev/logibm}{Logitech bus mouse}
+	\minor{1}{/dev/psaux}{PS/2-style mouse port}
+	\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{128}{/dev/beep}{Fancy beep device}
+	\minor{129}{/dev/modreq}{Kernel module load request}
+\end{devicelist}
+
+\begin{devicelist}
+\major{11}{}{block}{SCSI CD-ROM devices}
+	\minor{0}{/dev/sr0}{First SCSI CD-ROM}
+	\minor{1}{/dev/sr1}{Second SCSI CD-ROM}
+	\minordots
+\end{devicelist}
+
+\noindent
+The prefix {\file /dev/scd} instead of {\file /dev/sr} has been used
+as well, and might make more sense.
+
+\begin{devicelist}
+\major{12}{}{char }{QIC-02 tape}
+	\minor{2}{/dev/ntpqic11}{QIC-11, no rewind-on-close}
+	\minor{3}{/dev/tpqic11}{QIC-11, rewind-on-close}
+	\minor{4}{/dev/ntpqic24}{QIC-24, no rewind-on-close}
+	\minor{5}{/dev/tpqic24}{QIC-24, rewind-on-close}
+	\minor{6}{/dev/ntpqic120}{QIC-120, no rewind-on-close}
+	\minor{7}{/dev/tpqic120}{QIC-120, rewind-on-close}
+	\minor{8}{/dev/ntpqic150}{QIC-150, no rewind-on-close}
+	\minor{9}{/dev/tpqic150}{QIC-150, rewind-on-close}
+\end{devicelist}
+
+\noindent
+The device names specified are proposed -- if there are ``standard''
+names for these devices, please let me know.
+
+\begin{devicelist}
+\major{  }{}{block}{MSCDEX CD-ROM callback support}
+	\minor{0}{/dev/dos\_cd0}{First MSCDEX CD-ROM}
+	\minor{1}{/dev/dos\_cd1}{Second MSCDEX CD-ROM}
+	\minordots
+\end{devicelist}
+
+\begin{devicelist}
+\major{13}{}{char }{PC speaker}
+	\minor{0}{/dev/pcmixer}{Emulates {\file /dev/mixer}}
+	\minor{3}{/dev/pcsp}{Emulates {\file /dev/dsp} (8-bit)}
+	\minor{4}{/dev/pcaudio}{Emulates {\file /dev/audio}}
+	\minor{5}{/dev/pcsp16}{Emulates {\file /dev/dsp} (16-bit)}
+\\
+\major{  }{}{block}{8-bit MFM/RLL/IDE controller}
+	\minor{0}{/dev/xda}{First XT disk whole disk}
+	\minor{64}{/dev/xdb}{Second XT disk whole disk}
+\end{devicelist}
+
+\noindent
+Partitions are handled in the same way as IDE disks
+(see major number 3).
+
+\begin{devicelist}
+\major{14}{}{char }{Sound card}
+	\minor{0}{/dev/mixer}{Mixer control}
+	\minor{1}{/dev/sequencer}{Audio sequencer}
+	\minor{2}{/dev/midi00}{First MIDI port}
+	\minor{3}{/dev/dsp}{Digital audio}
+	\minor{4}{/dev/audio}{Sun-compatible digital audio}
+	\minor{6}{/dev/sndstat}{Sound card status information}
+	\minor{8}{/dev/sequencer2}{Sequencer -- alternate device}
+	\minor{16}{/dev/mixer1}{Second soundcard mixer control}
+	\minor{17}{/dev/patmgr0}{Sequencer patch manager}
+	\minor{18}{/dev/midi01}{Second MIDI port}
+	\minor{19}{/dev/dsp1}{Second soundcard digital audio}
+	\minor{20}{/dev/audio1}{Second soundcard Sun digital audio}
+	\minor{33}{/dev/patmgr1}{Sequencer patch manager}
+	\minor{34}{/dev/midi02}{Third MIDI port}
+	\minor{50}{/dev/midi03}{Fourth MIDI port}
+\\
+\major{  }{}{block}{BIOS harddrive callback support}
+	\minor{0}{/dev/dos\_hda}{First BIOS harddrive whole disk}
+	\minor{64}{/dev/dos\_hdb}{Second BIOS harddrive whole disk}
+	\minor{128}{/dev/dos\_hdc}{Third BIOS harddrive whole disk}
+	\minor{192}{/dev/dos\_hdd}{Fourth BIOS harddrive whole disk}
+\end{devicelist}
+
+\noindent
+Partitions are handled in the same way as IDE disks
+(see major number 3).
+
+\begin{devicelist}
+\major{15}{}{char }{Joystick}
+	\minor{0}{/dev/js0}{First joystick}
+	\minor{1}{/dev/js1}{Second joystick}
+\\
+\major{  }{}{block}{Sony CDU-31A/CDU-33A CD-ROM}
+	\minor{0}{/dev/sonycd}{Sony CDU-31A CD-ROM}
+\end{devicelist}
+
+\begin{devicelist}
+\major{16}{}{char }{Reserved for scanners}
+\major{  }{}{block}{GoldStar CD-ROM}
+	\minor{0}{/dev/gscd}{GoldStar CD-ROM}
+\end{devicelist}
+
+\begin{devicelist}
+\major{17}{}{char }{Chase serial card}
+	\minor{0}{/dev/ttyH0}{First Chase port}
+	\minor{1}{/dev/ttyH1}{Second Chase port}
+	\minordots
+\\
+\major{  }{}{block}{Optics Storage CD-ROM}
+	\minor{0}{/dev/optcd}{Optics Storage CD-ROM}
+\end{devicelist}
+
+\begin{devicelist}
+\major{18}{}{char }{Chase serial card -- alternate devices}
+	\minor{0}{/dev/cuh0}{Callout device corresponding to {\file ttyH0}}
+	\minor{1}{/dev/cuh1}{Callout device corresponding to {\file ttyH1}}
+	\minordots
+\\
+\major{  }{}{block}{Sanyo CD-ROM}
+	\minor{0}{/dev/sjcd}{Sanyo CD-ROM}
+\end{devicelist}
+
+\begin{devicelist}
+\major{19}{}{char }{Cyclades serial card}
+	\minor{32}{/dev/ttyC0}{First Cyclades port}
+	\minordots
+	\minor{63}{/dev/ttyC31}{32nd Cyclades port}
+\end{devicelist}
+\noindent
+It would make more sense for these to start at 0...
+\begin{devicelist}
+\major{  }{}{block}{``Double'' compressed disk}
+	\minor{0}{/dev/double0}{First compressed disk}
+	\minordots
+	\minor{7}{/dev/double7}{Eighth compressed disk}
+	\minor{128}{/dev/cdouble0}{Mirror of first compressed disk}
+	\minordots
+	\minor{135}{/dev/cdouble7}{Mirror of eighth compressed disk}
+\end{devicelist}
+
+\noindent
+See the Double documentation for an explanation of the ``mirror'' devices.
+
+\begin{devicelist}
+\major{20}{}{char }{Cyclades serial card -- alternate devices}
+	\minor{32}{/dev/cub0}{Callout device corresponding to {\file ttyC0}}
+	\minordots
+	\minor{63}{/dev/cub31}{Callout device corresponding to {\file ttyC31}}
+\\
+\major{  }{}{block}{Hitachi CD-ROM}
+	\minor{0}{/dev/hitcd}{Hitachi CD-ROM}
+\end{devicelist}
+
+\begin{devicelist}
+\major{21}{}{char }{Generic SCSI access}
+	\minor{0}{/dev/sg0}{First generic SCSI device}
+	\minor{1}{/dev/sg1}{Second generic SCSI device}
+	\minordots
+\end{devicelist}
+
+\begin{devicelist}
+\major{22}{}{char }{Digiboard serial card}
+	\minor{0}{/dev/ttyD0}{First Digiboard port}
+	\minor{1}{/dev/ttyD1}{Second Digiboard port}
+	\minordots
+\major{  }{}{block}{Second IDE hard disk/CD-ROM interface}
+	\minor{0}{/dev/hdc}{Master: whole disk (or CD-ROM)}
+	\minor{64}{/dev/hdd}{Slave: whole disk (or CD-ROM)}
+\end{devicelist}
+
+\noindent
+Partitions are handled the same way as for the first
+interface (see major number 3).
+
+\begin{devicelist}
+\major{23}{}{char }{Digiboard serial card -- alternate devices}
+	\minor{0}{/dev/cud0}{Callout device corresponding to {\file ttyD0}}
+	\minor{1}{/dev/cud1}{Callout device corresponding to {\file ttyD1}}
+	\minordots
+\major{  }{}{block}{Mitsumi proprietary CD-ROM}
+	\minor{0}{/dev/mcd}{Mitsumi CD-ROM}
+\end{devicelist}
+
+\begin{devicelist}\
+\major{24}{}{char }{Stallion serial card}
+	\minor{0}{/dev/ttyE0}{Stallion port 0 board 0}
+	\minor{1}{/dev/ttyE1}{Stallion port 1 board 0}
+	\minordots
+	\minor{64}{/dev/ttyE64}{Stallion port 0 board 1}
+	\minor{65}{/dev/ttyE65}{Stallion port 1 board 1}
+	\minordots
+	\minor{128}{/dev/ttyE128}{Stallion port 0 board 2}
+	\minor{129}{/dev/ttyE129}{Stallion port 1 board 2}
+	\minordots
+	\minor{192}{/dev/ttyE192}{Stallion port 0 board 3}
+	\minor{193}{/dev/ttyE193}{Stallion port 1 board 3}
+	\minordots
+\\
+\major{  }{}{block}{Sony CDU-535 CD-ROM}
+	\minor{0}{/dev/cdu535}{Sony CDU-535 CD-ROM}
+\end{devicelist}
+
+\begin{devicelist}
+\major{25}{}{char }{Stallion serial card -- alternate devices}
+	\minor{0}{/dev/cue0}{Callout device corresponding to {\file ttyE0}}
+	\minor{1}{/dev/cue1}{Callout device corresponding to {\file ttyE1}}
+	\minordots
+	\minor{64}{/dev/cue64}{Callout device corresponding to {\file ttyE64}}
+	\minor{65}{/dev/cue65}{Callout device corresponding to {\file ttyE65}}
+	\minordots
+	\minor{128}{/dev/cue128}{Callout device corresponding to {\file ttyE128}}
+	\minor{129}{/dev/cue129}{Callout device corresponding to {\file ttyE129}}
+	\minordots
+	\minor{192}{/dev/cue192}{Callout device corresponding to {\file ttyE192}}
+	\minor{193}{/dev/cue193}{Callout device corresponding to {\file ttyE193}}
+	\minordots
+\\
+\major{  }{}{block}{First Matsushita (Panasonic/SoundBlaster) CD-ROM}
+	\minor{0}{/dev/sbpcd0}{Panasonic CD-ROM controller 0 unit 0}
+	\minor{1}{/dev/sbpcd1}{Panasonic CD-ROM controller 0 unit 1}
+	\minor{2}{/dev/sbpcd2}{Panasonic CD-ROM controller 0 unit 2}
+	\minor{3}{/dev/sbpcd3}{Panasonic CD-ROM controller 0 unit 3}
+\end{devicelist}
+
+\begin{devicelist}
+\major{26}{}{char }{Frame grabbers}
+	\minor{0}{/dev/wvisfgrab}{Quanta WinVision frame grabber}
+\\
+\major{  }{}{block}{Second Matsushita (Panasonic/SoundBlaster) CD-ROM}
+	\minor{0}{/dev/sbpcd4}{Panasonic CD-ROM controller 1 unit 0}
+	\minor{1}{/dev/sbpcd5}{Panasonic CD-ROM controller 1 unit 1}
+	\minor{2}{/dev/sbpcd6}{Panasonic CD-ROM controller 1 unit 2}
+	\minor{3}{/dev/sbpcd7}{Panasonic CD-ROM controller 1 unit 3}
+\end{devicelist}
+
+\begin{devicelist}
+\major{27}{}{char }{QIC-117 tape}
+	\minor{0}{/dev/rft0}{Unit 0, rewind-on-close}
+	\minor{1}{/dev/rft1}{Unit 1, rewind-on-close}
+	\minor{2}{/dev/rft2}{Unit 2, rewind-on-close}
+	\minor{3}{/dev/rft3}{Unit 3, rewind-on-close}
+	\minor{4}{/dev/nrft0}{Unit 0, no rewind-on-close}
+	\minor{5}{/dev/nrft1}{Unit 1, no rewind-on-close}
+	\minor{6}{/dev/nrft2}{Unit 2, no rewind-on-close}
+	\minor{7}{/dev/nrft3}{Unit 3, no rewind-on-close}
+\\
+\major{  }{}{block}{Third Matsushita (Panasonic/SoundBlaster) CD-ROM}
+	\minor{0}{/dev/sbpcd8}{Panasonic CD-ROM controller 2 unit 0}
+	\minor{1}{/dev/sbpcd9}{Panasonic CD-ROM controller 2 unit 1}
+	\minor{2}{/dev/sbpcd10}{Panasonic CD-ROM controller 2 unit 2}
+	\minor{3}{/dev/sbpcd11}{Panasonic CD-ROM controller 2 unit 3}
+\end{devicelist}
+
+\begin{devicelist}
+\major{28}{}{char }{Stallion serial card -- card programming}
+	\minor{0}{/dev/staliomem0}{First Stallion I/O card memory}
+	\minor{1}{/dev/staliomem1}{Second Stallion I/O card memory}
+	\minor{2}{/dev/staliomem2}{Third Stallion I/O card memory}
+	\minor{3}{/dev/staliomem3}{Fourth Stallion I/O card memory}
+\\
+\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)}
+	\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}
+	\minordots
+	\minor{240}{/dev/adp}{Sixteenth ACSI disk whole disk}
+\end{devicelist}
+
+\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.
+
+\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}{}
+	\minordots
+\end{devicelist}
+
+\noindent
+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
+are used for specific device-dependent resolutions.  There appears to
+be no standard naming for these devices.
+
+\begin{devicelist}
+\major{  }{}{block}{Aztech/Orchid/Okano/Wearnes CD-ROM}
+	\minor{0}{/dev/aztcd}{Aztech CD-ROM}
+\end{devicelist}
+
+\begin{devicelist}
+\major{30}{}{char }{iBCS-2 compatibility devices}
+	\minor{0}{/dev/socksys}{Socket access}
+	\minor{1}{/dev/spx}{SVR3 local X interface}
+	\minor{2}{/dev/inet/arp}{Network access}
+	\minor{2}{/dev/inet/icmp}{Network access}
+	\minor{2}{/dev/inet/ip}{Network access}
+	\minor{2}{/dev/inet/udp}{Network access}
+	\minor{2}{/dev/inet/tcp}{Network access}
+\end{devicelist}
+
+\noindent
+iBCS-2 requires {\file /dev/nfsd} to be a link to {\file /dev/socksys}
+and {\file /dev/X0R} to be a link to {\file /dev/null}.
+
+\begin{devicelist}
+\major{  }{}{block}{Philips LMS CM-205 CD-ROM}
+	\minor{0}{/dev/cm205cd}{Philips LMS CM-205 CD-ROM}
+\end{devicelist}
+
+\noindent
+{\file /dev/lmscd} is an older name for this drive.  This driver does
+not work with the CM-205MS CD-ROM.
+
+\begin{devicelist}
+\major{31}{}{char }{MPU-401 MIDI}
+	\minor{0}{/dev/mpu401data}{MPU-401 data port}
+	\minor{1}{/dev/mpu401stat}{MPU-401 status port}
+\\
+\major{  }{}{block}{ROM/flash memory card}
+	\minor{0}{/dev/rom0}{First ROM card (rw)}
+	\minordots
+	\minor{7}{/dev/rom7}{Eighth ROM card (rw)}
+	\minor{8}{/dev/rrom0}{First ROM card (ro)}
+	\minordots
+	\minor{15}{/dev/rrom0}{Eighth ROM card (ro)}
+	\minor{16}{/dev/flash0}{First flash memory card (rw)}
+	\minordots
+	\minor{23}{/dev/flash7}{Eighth flash memory card (rw)}
+	\minor{24}{/dev/rflash0}{First flash memory card (ro)}
+	\minordots
+	\minor{31}{/dev/rflash7}{Eighth flash memory card (ro)}
+\end{devicelist}
+
+\noindent
+The read-write (rw) devices support back-caching written data in RAM,
+as well as writing to flash RAM devices.  The read-only devices (ro)
+support reading only.
+
+\begin{devicelist}
+\major{32}{}{char }{Specialix serial card}
+	\minor{0}{/dev/ttyX0}{First Specialix port}
+	\minor{1}{/dev/ttyX1}{Second Specialix port}
+	\minordots
+\major{  }{}{block}{Philips LMS CM-206 CD-ROM}
+	\minor{0}{/dev/cm206cd}{Philips LMS CM-206 CD-ROM}
+\end{devicelist}
+
+\begin{devicelist}
+\major{33}{}{char }{Specialix serial card -- alternate devices}
+	\minor{0}{/dev/cux0}{Callout device corresponding to {\file ttyX0}}
+	\minor{1}{/dev/cux1}{Callout device corresponding to {\file ttyX1}}
+	\minordots
+\major{  }{}{block}{Modular RAM disk}
+	\minor{0}{/dev/ram0}{First modular RAM disk}
+	\minor{1}{/dev/ram1}{Second modular RAM disk}
+	\minordots
+	\minor{255}{/dev/ram255}{256th modular RAM disk}
+\end{devicelist}
+
+\begin{devicelist}
+\major{33}{}{block}{Third IDE hard disk/CD-ROM interface}
+	\minor{0}{/dev/hde}{Master: whole disk (or CD-ROM)}
+	\minor{64}{/dev/hdf}{Slave: whole disk (or CD-ROM)}
+\end{devicelist}
+
+\begin{devicelist}
+\major{34}{}{block}{Fourth IDE hard disk/CD-ROM interface}
+	\minor{0}{/dev/hdg}{Master: whole disk (or CD-ROM)}
+	\minor{64}{/dev/hdh}{Slave: whole disk (or CD-ROM)}
+\end{devicelist}
+
+\noindent
+For both IDE interfaces: partitions are handled the same way as for
+the first interface (see major number 3).
+
+\begin{devicelist}
+\major{35}{--223}{}{Unallocated}
+\end{devicelist}
+
+\begin{devicelist}
+\major{224}{--254}{}{Local/experimental use}
+\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.
+
+\begin{devicelist}
+\major{255}{}{}{Reserved}
+\end{devicelist}
+
+\section{Additional /dev directory entries}
+
+This section details additional entries that should or may exist in the
+{\file /dev} directory.  It is preferred that symbolic links use the
+same form (absolute or relative) as is indicated here.  Links are
+classified as {\em hard\/} or {\em symbolic\/} depending on the
+preferred type of link; if possible, the indicated type of link should
+be used.
+
+\subsection{Compulsory links}
+
+These links should exist on all systems:
+
+\begin{nodelist}
+\link{/dev/fd}{/proc/self/fd}{symbolic}{File descriptors}
+\link{/dev/stdin}{fd/0}{symbolic}{Standard input file descriptor}
+\link{/dev/stdout}{fd/1}{symbolic}{Standard output file descriptor}
+\link{/dev/stderr}{fd/2}{symbolic}{Standard error file descriptor}
+\end{nodelist}
+
+\subsection{Recommended links}
+
+It is recommended that these links exist on all systems:
+
+\begin{nodelist}
+\link{/dev/X0R}{null}{symbolic}{Used by iBCS-2}
+\link{/dev/nfsd}{socksys}{symbolic}{Used by iBCS-2}
+\link{/dev/core}{/proc/kcore}{symbolic}{Backward compatibility}
+\link{/dev/scd?}{sr?}{hard}{Alternate name for CD-ROMs}
+%\link{/dev/fd?H*}{fd?D*}{hard}{Compatible floppy formats}
+%\link{/dev/fd?E*}{fd?D*}{hard}{Compatible floppy formats}
+%\link{/dev/fd?E*}{fd?H*}{hard}{Compatible floppy formats}
+\end{nodelist}
+
+\subsection{Locally defined links}
+
+The following links may be established locally to conform to the
+configuration of the system.  This is merely a tabulation of existing
+practice, and does not constitute a recommendation.  However, if they
+exist, they should have the following uses.
+
+\begin{nodelist}
+\vlink{/dev/mouse}{mouse port}{symbolic}{Current mouse device}
+\vlink{/dev/tape}{tape device}{symbolic}{Current tape device}
+\vlink{/dev/cdrom}{CD-ROM device}{symbolic}{Current CD-ROM device}
+\vlink{/dev/modem}{modem port}{symbolic}{Current dialout device}
+\vlink{/dev/root}{root device}{symbolic}{Current root filesystem}
+\vlink{/dev/swap}{swap device}{symbolic}{Current swap device}
+\end{nodelist}
+
+\noindent
+{\file /dev/modem} should not be used for a modem which supports
+dialin as well as dialout, as it tends to cause lock file problems.
+If it exists, {\file /dev/modem} should point to the appropriate
+dialout (alternate) device.
+
+\subsection{Sockets and pipes}
+
+Non-transient sockets or named pipes may exist in {\file /dev}.
+Common entries are:
+
+\begin{nodelist}
+\node{/dev/printer}{socket}{{\file lpd} local socket}
+\node{/dev/log}{socket}{{\file syslog} local socket}
+\end{nodelist}
+
+\end{document}
diff -u --recursive --new-file v1.3.21/linux/Documentation/devices.txt linux/Documentation/devices.txt
--- v1.3.21/linux/Documentation/devices.txt	Thu Jan  1 02:00:00 1970
+++ linux/Documentation/devices.txt	Tue Aug 29 09:52:50 1995
@@ -0,0 +1,569 @@
+		       LINUX ALLOCATED DEVICES
+
+	 Maintained by H. Peter Anvin <Peter.Anvin@linux.org>
+
+		    Last revised: August 28, 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 available via FTP from ftp.yggdrasil.com in the directory
+/pub/device-list; filename is devices.<format> where <format> is txt
+(ASCII), tex (LaTeX), dvi (DVI) or ps (PostScript).  In cases of
+discrepancy, the LaTeX version has priority.
+
+This document is included by reference into the Linux Filesystem
+Standard (FSSTND).  The FSSTND is available via FTP from
+tsx-11.mit.edu in the directory /pub/linux/docs/linux-standards/fsstnd.
+
+To have a major number allocated, or a minor number in situations
+where that applies (e.g. busmice), please contact me.  Also, if you
+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.
+
+  0 		Unnamed devices (NFS mounts, loopback devices)
+		  0 = reserved as null device number
+
+  1 char	Memory devices
+    		  1 = /dev/mem		Physical memory access
+		  2 = /dev/kmem		Kernel virtual memory access
+		  3 = /dev/null		Null device
+		  4 = /dev/port		I/O port access
+		  5 = /dev/zero		Null byte source
+		  6 = /dev/core		OBSOLETE - replaced by /proc/kcore
+		  7 = /dev/full		Returns ENOSPC on write
+		  8 = /dev/random	Nondeterministic random number gen.
+		  9 = /dev/urandom	Faster, less secure random number gen.
+    block	RAM disk
+		  1 = /dev/ramdisk	RAM disk
+
+  2 char	Reserved for PTY's <tytso@athena.mit.edu>
+    block	Floppy disks
+		  0 = /dev/fd0		First floppy disk autodetect
+		  1 = /dev/fd1		Second floppy disk autodetect
+		  2 = /dev/fd2		Third floppy disk autodetect
+		  3 = /dev/fd3		Fourth floppy disk autodetect
+
+		To specify format, add to the autodetect device number:
+		  0 = /dev/fd?		Autodetect format
+		  4 = /dev/fd?d360	5.25"  360K in a 360K  drive(1)
+		 20 = /dev/fd?h360	5.25"  360K in a 1200K drive(1)
+		 48 = /dev/fd?h410	5.25"  410K in a 1200K drive
+		 64 = /dev/fd?h420	5.25"  420K in a 1200K drive
+		 24 = /dev/fd?h720	5.25"  720K in a 1200K drive
+		 80 = /dev/fd?h880	5.25"  880K in a 1200K drive(1)
+		  8 = /dev/fd?h1200	5.25" 1200K in a 1200K drive(1)
+		 40 = /dev/fd?h1440	5.25" 1440K in a 1200K drive(1)
+		 56 = /dev/fd?h1476	5.25" 1476K in a 1200K drive
+	  	 72 = /dev/fd?h1494	5.25" 1494K in a 1200K drive
+		 92 = /dev/fd?h1600	5.25" 1600K in a 1200K drive(1)
+
+		 12 = /dev/fd?u360	3.5"   360K Double Density
+		120 = /dev/fd?u800	3.5"   800K Double Density(1)
+		 52 = /dev/fd?u820	3.5"   820K Double Density(2)
+		 68 = /dev/fd?u830	3.5"   830K Double Density
+		 84 = /dev/fd?u1040	3.5"  1040K Double Density(1)
+		 88 = /dev/fd?u1120	3.5"  1120K Double Density(1)
+		 28 = /dev/fd?u1440	3.5"  1440K High Density(1)
+		124 = /dev/fd?u1600	3.5"  1600K High Density(1)
+		 44 = /dev/fd?u1680	3.5"  1680K High Density(3)
+		 60 = /dev/fd?u1722	3.5"  1722K High Density
+		 76 = /dev/fd?u1743	3.5"  1743K High Density
+		 96 = /dev/fd?u1760	3.5"  1760K High Density
+		116 = /dev/fd?u1840	3.5"  1840K High Density(3)
+		100 = /dev/fd?u1920	3.5"  1920K High Density(1)
+		 32 = /dev/fd?u2880	3.5"  2880K Extra Density(1)
+		104 = /dev/fd?u3200	3.5"  3200K Extra Density
+		108 = /dev/fd?u3520	3.5"  3520K Extra Density
+		112 = /dev/fd?u3840	3.5"  3840K Extra Density(1)
+
+		 36 = /dev/fd?CompaQ	Compaq 2880K drive; obsolete?
+
+		(1) Autodetectable format
+		(2) Autodetectable format in a Double Density (720K) drive only
+		(3) Autodetectable format in a High Density (1440K) drive only
+
+		NOTE: THe letter in the device name (d, q, h or u)
+		signifies the type of drive: 5.25" Double Density (d),
+		5.25" Quad Density (q), 5.25" High Density (h) or 3.5"
+		(any model, u).  The use of the capital letters D, H
+		and E for the 3.5" models have been deprecated, since
+		the drive type is insignificant for these devices.
+
+  3 char	Reserved for pty's <tytso@athena.mit.edu>
+    block	First MFM, RLL and IDE hard disk/CD-ROM interface
+    		  0 = /dev/hda		Master: whole disk (or CD-ROM)
+		 64 = /dev/hdb		Slave: whole disk (or CD-ROM)
+		
+		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
+		    ...
+		 63 = /dev/hd?63	59th logical partition
+
+  4 char	TTY devices
+    		  0 = /dev/console	Console device
+
+		  1 = /dev/tty1		First virtual console
+		      ...
+		 63 = /dev/tty63	63rd virtual console
+		 64 = /dev/ttyS0	First serial port
+		      ...
+		127 = /dev/ttyS63	64th serial port
+		128 = /dev/ptyp0	First pseudo-tty master
+		      ...
+		191 = /dev/ptysf	64th pseudo-tty master
+		192 = /dev/ttyp0	First pseudo-tty slave
+		      ...
+		255 = /dev/ttysf	64th pseudo-tty slave
+
+		Pseudo-tty's are named as follows:
+		* Masters are "pty", slaves are "tty";
+		* the fourth letter is one of p, q, r, s indicating
+		  the 1st, 2nd, 3rd, 4th series of 16 pseudo-ttys each, and
+		* the fifth letter is one of 0123456789abcdef indicating
+		  the position within the series.
+
+  5 char	Alternate TTY devices
+    		  0 = /dev/tty		Current TTY device
+		 64 = /dev/cua0		Callout device corresponding to ttyS0
+		      ...
+		127 = /dev/cua63	Callout device corresponding to ttyS63
+
+  6 char	Parallel printer devices
+    		  0 = /dev/lp0		First parallel printer (0x3bc)
+		  1 = /dev/lp1		Second parallel printer (0x378)
+		  2 = /dev/lp2		Third parallel printer (0x278)
+
+		Not all computers have the 0x3bc parallel port; hence
+		the "first" printer may be either /dev/lp0 or
+		/dev/lp1.
+
+  7 char	Virtual console capture devices
+    		  0 = /dev/vcs		Current vc text contents
+		  1 = /dev/vcs1		tty1 text contents
+		      ...
+		 63 = /dev/vcs63	tty63 text contents
+		128 = /dev/vcsa		Current vc text/attribute contents
+		129 = /dev/vcsa1	tty1 text/attribute contents
+		      ...
+		191 = /dev/vcsa63	tty63 text/attribute contents
+	
+		NOTE: These devices permit both read and write access.
+
+  8 block	SCSI disk devices
+    		  0 = /dev/sda		First SCSI disk whole disk
+		 16 = /dev/sdb		Second SCSI disk whole disk
+		 32 = /dev/sdc		Third SCSI disk whole disk
+  		      ...
+		240 = /dev/sdp		Sixteenth SCSI disk whole disk
+
+		Partitions are handled in the same way as for IDE
+		disks (see major number 3) except that the limit on
+		logical partitions is 11.
+
+  9 char	SCSI tape devices
+    		  0 = /dev/st0		First SCSI tape
+		  1 = /dev/st1		Second SCSI tape
+		      ...
+		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
+		      ...
+
+		The multiple devices driver is used to span a
+		filesystem across multiple physical disks.
+
+ 10 char	Non-serial mice, misc features
+		  0 = /dev/logibm	Logitech bus mouse
+		  1 = /dev/psaux	PS/2-style mouse port
+		  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)
+		128 = /dev/beep		Fancy beep device
+		129 = /dev/modreq	Kernel module load request
+
+		The use of the suffix -mouse instead of -bm or -aux
+		has also been used.
+
+ 11 block	SCSI CD-ROM devices
+    		  0 = /dev/sr0		First SCSI CD-ROM
+		  1 = /dev/sr1		Second SCSI CD-ROM
+		      ...
+
+		The prefix /dev/scd instead of /dev/sr has been used
+		as well, and might make more sense.
+
+ 12 char	QIC-02 tape
+		  2 = /dev/ntpqic11	QIC-11, no rewind-on-close
+		  3 = /dev/tpqic11	QIC-11, rewind-on-close
+		  4 = /dev/ntpqic24	QIC-24, no rewind-on-close
+		  5 = /dev/tpqic24	QIC-24, rewind-on-close
+		  6 = /dev/ntpqic120	QIC-120, no rewind-on-close
+		  7 = /dev/tpqic120	QIC-120, rewind-on-close
+		  8 = /dev/ntpqic150	QIC-150, no rewind-on-close
+		  9 = /dev/tpqic150	QIC-150, rewind-on-close
+
+		The device names specified are proposed -- if there
+		are "standard" names for these devices, please let me know.
+
+    block	MSCDEX CD-ROM callback support
+		  0 = /dev/dos_cd0	First MSCDEX CD-ROM
+		  1 = /dev/dos_cd1	Second MSCDEX CD-ROM
+		      ...
+
+ 13 char	PC speaker
+		  0 = /dev/pcmixer	Emulates /dev/mixer
+		  1 = /dev/pcsp		Emulates /dev/dsp (8-bit)
+		  4 = /dev/pcaudio	Emulates /dev/audio
+		  5 = /dev/pcsp16	Emulates /dev/dsp (16-bit)
+    block	8-bit MFM/RLL/IDE controller
+		  0 = /dev/xda		First XT disk whole disk
+		 64 = /dev/xdb		Second XT disk whole disk
+
+		Partitions are handled in the same way as IDE disks
+		(see major number 3).
+
+ 14 char	Sound card
+		  0 = /dev/mixer	Mixer control
+		  1 = /dev/sequencer	Audio sequencer
+		  2 = /dev/midi00	First MIDI port
+		  3 = /dev/dsp		Digital audio
+		  4 = /dev/audio	Sun-compatible digital audio
+		  6 = /dev/sndstat	Sound card status information
+		  8 = /dev/sequencer2	Sequencer -- alternate device
+		 16 = /dev/mixer1	Second soundcard mixer control
+		 17 = /dev/patmgr0	Sequencer patch manager
+		 18 = /dev/midi01	Second MIDI port
+		 19 = /dev/dsp1		Second soundcard digital audio
+		 20 = /dev/audio1	Second soundcard Sun digital audio
+		 33 = /dev/patmgr1	Sequencer patch manager
+		 34 = /dev/midi02	Third MIDI port
+		 50 = /dev/midi03	Fourth MIDI port
+    block	BIOS harddrive callback support
+		  0 = /dev/dos_hda	First BIOS harddrive whole disk
+		 64 = /dev/dos_hdb	Second BIOS harddrive whole disk
+		128 = /dev/dos_hdc	Third BIOS harddrive whole disk
+		192 = /dev/dos_hdd	Fourth BIOS harddrive whole disk
+
+		Partitions are handled in the same way as IDE disks
+		(see major number 3).
+
+ 15 char	Joystick
+		  0 = /dev/js0		First joystick
+		  1 = /dev/js1		Second joystick
+    block	Sony CDU-31A/CDU-33A CD-ROM
+		  0 = /dev/sonycd	Sony CDU-31a CD-ROM
+
+ 16 char	Reserved for scanners
+    block	GoldStar CD-ROM
+		  0 = /dev/gscd		GoldStar CD-ROM
+
+ 17 char	Chase serial card
+		  0 = /dev/ttyH0	First Chase port
+		  1 = /dev/ttyH1	Second Chase port
+		      ...
+    block	Optics Storage CD-ROM
+		  0 = /dev/optcd	Optics Storage CD-ROM
+
+ 18 char	Chase serial card - alternate devices
+		  0 = /dev/cuh0		Callout device corresponding to ttyH0
+		  1 = /dev/cuh1		Callout device corresponding to ttyH1
+		      ...
+    block	Sanyo CD-ROM
+		  0 = /dev/sjcd		Sanyo CD-ROM
+
+ 19 char	Cyclades serial card
+		 32 = /dev/ttyC0	First Cyclades port
+		      ...
+		 63 = /dev/ttyC31	32nd Cyclades port
+		
+		It would make more sense for these to start at 0...
+
+    block	"Double" compressed disk
+		  0 = /dev/double0	First compressed disk
+		      ...
+		  7 = /dev/double7	Eighth compressed disk
+		128 = /dev/cdouble0	Mirror of first compressed disk
+		      ...
+		135 = /dev/cdouble7	Mirror of eighth compressed disk
+
+		See the Double documentation for the meaning of the
+		mirror devices.
+
+ 20 char	Cyclades serial card - alternate devices
+		 32 = /dev/cub0		Callout device corresponding to ttyC0
+		      ...
+		 63 = /dev/cub31	Callout device corresponding to ttyC31
+    block	Hitachi CD-ROM (under development)
+		  0 = /dev/hitcd	Hitachi CD-ROM
+
+ 21 char	Generic SCSI access
+		  0 = /dev/sg0		First generic SCSI device
+		  1 = /dev/sg1		Second generic SCSI device
+		      ...
+
+ 22 char	Digiboard serial card
+		  0 = /dev/ttyD0	First Digiboard port
+		  1 = /dev/ttyD1	Second Digiboard port
+		      ...
+    block	Second IDE hard disk/CD-ROM interface
+    		  0 = /dev/hdc		Master: whole disk (or CD-ROM)
+		 64 = /dev/hdd		Slave: whole disk (or CD-ROM)
+		
+		Partitions are handled the same way as for the first
+		interface (see major number 3).
+
+ 23 char	Digiboard serial card - alternate devices
+		  0 = /dev/cud0		Callout device corresponding to ttyD0
+		  1 = /dev/cud1		Callout device corresponding to ttyD1
+		      ...
+    block	Mitsumi proprietary CD-ROM
+		  0 = /dev/mcd		Mitsumi CD-ROM
+
+ 24 char	Stallion serial card
+		  0 = /dev/ttyE0	Stallion port 0 card 0
+		  1 = /dev/ttyE1	Stallion port 1 card 0
+		      ...
+		 64 = /dev/ttyE64	Stallion port 0 card 1
+		 65 = /dev/ttyE65	Stallion port 1 card 1
+		      ...
+		128 = /dev/ttyE128	Stallion port 0 card 2
+		129 = /dev/ttyE129	Stallion port 1 card 2
+		      ...
+		192 = /dev/ttyE192	Stallion port 0 card 3
+		193 = /dev/ttyE193	Stallion port 1 card 3
+		      ...
+    block	Sony CDU-535 CD-ROM
+		  0 = /dev/cdu535	Sony CDU-535 CD-ROM
+
+ 25 char	Stallion serial card - alternate devices
+		  0 = /dev/cue0		Callout device corresponding to ttyE0
+		  1 = /dev/cue1		Callout device corresponding to ttyE1
+		      ...
+		 64 = /dev/cue64	Callout device corresponding to ttyE64
+		 65 = /dev/cue65	Callout device corresponding to ttyE65
+		      ...
+		128 = /dev/cue128	Callout device corresponding to ttyE128
+		129 = /dev/cue129	Callout device corresponding to ttyE129
+		      ...
+		192 = /dev/cue192	Callout device corresponding to ttyE192
+		193 = /dev/cue193	Callout device corresponding to ttyE193
+		      ...
+    block	First Matsushita (Panasonic/SoundBlaster) CD-ROM
+		  0 = /dev/sbpcd0	Panasonic CD-ROM controller 0 unit 0
+		  1 = /dev/sbpcd1	Panasonic CD-ROM controller 0 unit 1
+		  2 = /dev/sbpcd2	Panasonic CD-ROM controller 0 unit 2
+		  3 = /dev/sbpcd3	Panasonic CD-ROM controller 0 unit 3
+
+ 26 char	Frame grabbers
+		  0 = /dev/wvisfgrab	Quanta WinVision frame grabber
+    block	Second Matsushita (Panasonic/SoundBlaster) CD-ROM
+		  0 = /dev/sbpcd4	Panasonic CD-ROM controller 1 unit 0
+		  1 = /dev/sbpcd5	Panasonic CD-ROM controller 1 unit 1
+		  2 = /dev/sbpcd6	Panasonic CD-ROM controller 1 unit 2
+		  3 = /dev/sbpcd7	Panasonic CD-ROM controller 1 unit 3
+
+ 27 char	QIC-117 tape
+		  0 = /dev/ftape	QIC-117 tape
+    block	Third Matsushita (Panasonic/SoundBlaster) CD-ROM
+		  0 = /dev/sbpcd8	Panasonic CD-ROM controller 2 unit 0
+		  1 = /dev/sbpcd9	Panasonic CD-ROM controller 2 unit 1
+		  2 = /dev/sbpcd10	Panasonic CD-ROM controller 2 unit 2
+		  3 = /dev/sbpcd11	Panasonic CD-ROM controller 2 unit 3
+
+ 28 char	Stallion serial card - card programming
+		  0 = /dev/staliomem0	First Stallion card I/O memory
+		  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
+    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)
+		  0 = /dev/ada		First ACSI disk whole disk
+		 16 = /dev/adb		Second ACSI disk whole disk
+		 32 = /dev/adc		Third ACSI disk whole disk
+		      ...
+		240 = /dev/adp		16th ACSI disk whole disk
+
+		Partitions are handled in the same way as for IDE
+		disks (see major number 3) except that the limit on
+		logical partitions is 11.
+
+ 29 char	Universal frame buffer
+		  0 = /dev/fb0current	First frame buffer
+		  1 = /dev/fb0autodetect
+		      ...
+		 16 = /dev/fb1current	Second frame buffer
+		 17 = /dev/fb1autodetect
+		      ...
+    block	Aztech/Orchid/Okano/Wearnes CD-ROM
+		  0 = /dev/aztcd	Aztech CD-ROM
+
+		The universal frame buffer device is currenly only
+		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
+		are used for specific device-dependent resolutions.
+		There appears to be no standard naming for these devices.
+
+ 30 char	iBCS-2 compatibility devices
+		  0 = /dev/socksys	Socket access
+		  1 = /dev/spx		SVR3 local X interface
+		  2 = /dev/inet/arp	Network access
+		  2 = /dev/inet/icmp	Network access
+		  2 = /dev/inet/ip	Network access
+		  2 = /dev/inet/udp	Network access
+		  2 = /dev/inet/tcp	Network access
+
+		iBCS-2 requires /dev/nfsd to be a link to
+		/dev/socksys, and /dev/X0R to be a link to /dev/null.
+
+    block	Philips LMS CM-205 CD-ROM
+		  0 = /dev/cm205cd	Philips LMS CM-205 CD-ROM
+
+		/dev/lmscd is an older name for this device.  This
+		driver does not work with the CM-205MS CD-ROM.
+
+ 31 char	MPU-401 MIDI
+		  0 = /dev/mpu401data	MPU-401 data port
+		  1 = /dev/mpu401stat	MPU-401 status port
+    block	ROM/flash memory card
+		  0 = /dev/rom0		First ROM card (rw)
+		      ...
+		  7 = /dev/rom7		Eighth ROM card (rw)
+		  8 = /dev/rrom0	First ROM card (ro)
+		      ...
+		 15 = /dev/rrom7	Eighth ROM card (ro)
+		 16 = /dev/flash0	First flash memory card (rw)
+		      ...
+		 23 = /dev/flash7	Eighth flash memory card (rw)
+		 24 = /dev/rflash0	First flash memory card (ro)
+		      ...
+		 31 = /dev/rflash7	Eighth flash memory card (ro)
+
+		The read-write (rw) devices support back-caching
+		written data in RAM, as well as writing to flash RAM
+		devices.  The read-only devices (ro) support reading
+		only.
+
+ 32 char	Specialix serial card
+		  0 = /dev/ttyX0	First Specialix port
+		  1 = /dev/ttyX1	Second Specialix port
+		      ...
+    block	Philips LMS CM-206 CD-ROM
+		  0 = /dev/cm206cd	Philips LMS CM-206 CD-ROM
+
+ 33 char	Specialix serial card - alternate devices
+		  0 = /dev/cux0		Callout device corresponding to ttyX0
+		  1 = /dev/cux1		Callout device corresponding to ttyX1
+		      ...
+    block	Modular RAM disk device
+		  0 = /dev/ram0		First modular RAM disk
+		  1 = /dev/ram1		Second modular RAM disk
+		      ...
+		255 = /dev/ram255	256th modular RAM disk
+
+ 33 block	Third IDE hard disk/CD-ROM interface
+    		  0 = /dev/hde		Master: whole disk (or CD-ROM)
+		 64 = /dev/hdf		Slave: whole disk (or CD-ROM)
+
+ 34 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)
+		
+		For both IDE interfaces: partitions are handled the
+		same way as for the first interface (see major number
+		3).
+
+ 35-223		UNALLOCATED
+
+224-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.
+
+255		RESERVED
+
+
+
+
+	ADDITIONAL /dev DIRECTORY ENTRIES
+
+This section details additional entries that should or may exist in
+the /dev directory.  It is preferred that symbolic links use the same
+form (absolute or relative) as is indicated here.  Links are
+classified as "hard" or "symbolic" depending on the preferred type of
+link; if possible, the indicated type of link should be used.
+
+
+	Compulsory links
+
+These links should exist on all systems:
+
+/dev/fd		/proc/self/fd	symbolic	File descriptors
+/dev/stdin	fd/0		symbolic	stdin file descriptor
+/dev/stdout	fd/1		symbolic	stdout file descriptor
+/dev/stderr	fd/2		symbolic	stderr file descriptor
+
+
+	Recommended links
+
+It is recommended that these links exist on all systems:
+
+/dev/X0R	null		symbolic	Used by iBCS-2
+/dev/nfsd	socksys		symbolic	Used by iBCS-2
+/dev/core	/proc/kcore	symbolic	Backward compatibility
+/dev/scd?	/dev/sr?	hard		Alternate SCSI CD-ROM name
+
+
+	Locally defined links
+
+The following links may be established locally to conform to the
+configuration of the system.  This is merely a tabulation of existing
+practice, and does not constitute a recommendation.  However, if they
+exist, they should have the following uses.
+
+/dev/mouse	mouse port	symbolic	Current mouse device
+/dev/tape	tape device	symbolic	Current tape device
+/dev/cdrom	CD-ROM device	symbolic	Current CD-ROM device
+/dev/modem	modem port	symbolic	Current dialout device
+/dev/root	root device	symbolic	Current root filesystem
+/dev/swap	swap device	symbolic	Current swap device
+
+/dev/modem should not be used for a modem which supports dialin as
+well as dialout, as it tends to cause lock file problems.  If it
+exists, /dev/modem shold point to the appropriate dialout (alternate)
+device.
+
+
+	Sockets and pipes
+
+Non-transient sockets and named pipes may exist in /dev.  Common entries are:
+
+/dev/printer	socket		lpd local socket
+/dev/log	socket		syslog local socket
diff -u --recursive --new-file v1.3.21/linux/Documentation/filesystems/hpfs.txt linux/Documentation/filesystems/hpfs.txt
--- v1.3.21/linux/Documentation/filesystems/hpfs.txt	Thu Jan  1 02:00:00 1970
+++ linux/Documentation/filesystems/hpfs.txt	Wed Feb 23 09:45:39 1994
@@ -0,0 +1,25 @@
+Linux can read, but not write, OS/2 HPFS partitions.
+
+Mount options are the same as for msdos partitions.
+
+  uid=nnn	All files in the partition will be owned by user id nnn.
+  gid=nnn	All files in the partition will be in group nnn.
+  umask=nnn	The permission mask (see umask(1)) for the partition.
+  conv=binary   Data is returned exactly as is, with CRLF's.  [default]
+  conv=text     (Carriage return, line feed) is replaced with newline.
+  conv=auto     Chooses, file by file, conv=binary or conv=text (by guessing)
+
+There is one mount option unique to HPFS.
+
+  case=lower	Convert file names to lower case.  [default]
+  case=asis     Return file names as is, in mixed case.
+
+Case is not significant in filename matching, like real HPFS.
+
+
+Command line example
+    mkdir -p /os2/c
+    mount -t hpfs -o uid=100,gid=100 /dev/sda6 /os2/c
+
+/etc/fstab example
+    /dev/sdb5	/d/f    hpfs    ro,uid=402,gid=402,umask=002
diff -u --recursive --new-file v1.3.21/linux/Documentation/filesystems/smbfs.txt linux/Documentation/filesystems/smbfs.txt
--- v1.3.21/linux/Documentation/filesystems/smbfs.txt	Thu Jan  1 02:00:00 1970
+++ linux/Documentation/filesystems/smbfs.txt	Mon Aug 28 09:48:36 1995
@@ -0,0 +1,12 @@
+smbfs is a filesystem which understands the SMB protocol. This is the
+protocol Windows for Workgroups, Windows NT or Lan Manager use to talk
+to each other. smbfs was inspired by samba, the program written by
+Andrew Tridgell that turns any unix host into a file server for DOS or
+Windows clients.  See ftp://nimbus.anu.edu.au/pub/tridge/samba/ for
+this interesting program suite and lots of more information on SMB and
+NetBIOS over TCP/IP. There you also find explanation for conceps like
+netbios name or share.
+
+To use smbfs, you need a special mount program, which can be found in
+the ksmbfs package, found on sunsite.unc.edu:/pub/Linux/ALPHA/smbfs.
+
diff -u --recursive --new-file v1.3.21/linux/Documentation/filesystems/sysv-fs.txt linux/Documentation/filesystems/sysv-fs.txt
--- v1.3.21/linux/Documentation/filesystems/sysv-fs.txt	Thu Jan  1 02:00:00 1970
+++ linux/Documentation/filesystems/sysv-fs.txt	Sat Nov  5 13:32:13 1994
@@ -0,0 +1,37 @@
+This is the implementation of the SystemV/Coherent filesystem for Linux.
+It implements all of
+  - Xenix FS,
+  - SystemV/386 FS,
+  - Coherent FS.
+
+This is version beta 4.
+
+To install:
+* Answer the 'System V and Coherent filesystem support' question with 'y'
+  when configuring the kernel.
+* To mount a disk or a partition, use
+    mount [-r] -t sysv device mountpoint
+  The file system type names
+               -t sysv
+               -t xenix
+               -t coherent
+  may be used interchangeably, but the last two will eventually disappear.
+
+Bugs in the present implementation:
+- Coherent FS:
+  - The "free list interleave" n:m is currently ignored.
+  - Only file systems with no filesystem name and no pack name are recognized.
+  (See Coherent "man mkfs" for a description of these features.)
+- SystemV Release 2 FS:
+  The superblock is only searched in the blocks 9, 15, 18, which corresponds to the
+  beginning of track 1 on floppy disks. No support for this FS on hard disk yet.
+
+
+Please report any bugs and suggestions to
+  Bruno Haible <haible@ma2s2.mathematik.uni-karlsruhde.de> or
+  Pascal Haible <haible@izfm.uni-stuttgart.de> .
+
+
+Bruno Haible
+<haible@ma2s2.mathematik.uni-karlsruhe.de>
+
diff -u --recursive --new-file v1.3.21/linux/Documentation/filesystems/umsdos.txt linux/Documentation/filesystems/umsdos.txt
--- v1.3.21/linux/Documentation/filesystems/umsdos.txt	Thu Jan  1 02:00:00 1970
+++ linux/Documentation/filesystems/umsdos.txt	Tue Jan 31 09:39:02 1995
@@ -0,0 +1,96 @@
+Very short explanation for the impatient!!!
+
+Umsdos is a file system driver that run on top the MSDOS fs driver.
+It is written by Jacques Gelinas (jacques@solucorp.qc.ca)
+
+Umsdos is not a file system per se, but a twist to make a boring
+one into a useful one.
+
+It gives you:
+
+	long file name
+	Permissions and owner
+	Links
+	Special files (devices, pipe...)
+	All is need to be a linux root fs.
+
+There is plenty of documentation on it in the source. A formated document
+made from those comments is available from
+sunsite.unc.edu:/pub/Linux/system/Filesystems/umsdos.
+
+Mostly...
+
+You mount a DOS partition like this
+
+mount -t umsdos /dev/hda3 /mnt
+         ^
+---------|
+
+All option are passed to the msdos drivers. Option like uid,gid etc are
+given to msdos.
+
+The default behavior of Umsdos is to do the same thing as the msdos driver
+mostly passing commands to it without much processing. Again, this is
+the default. After doing the mount on a DOS partition, nothing special
+happen. This is why all mount options are passed to the Msdos fs driver.
+
+Umsdos use a special DOS file --linux-.--- to store the information
+which can't be handle by the normal MsDOS file system. This is the trick.
+
+--linux-.--- is optional. There is one per directory.
+
+**** If --linux-.--- is missing, then Umsdos process the directory the
+     same way the msdos driver do. Short file name, no goodies, default
+     owner and permissions. So each directory may have or not this
+     --linux-.---
+
+Now, how to get those --linux-.---.
+
+\begin joke_section
+
+	Well send me a directory content
+	and I will send you one customised for you.
+	$5 per directory. Add any applicable taxes.
+\end joke_section
+
+A utility umssync creates those. The kernel maintain them. It is available
+from the same directory above (sunsite) in the file umsdos_progs-0.7.tar.gz.
+A compiled version is available in umsdos_progs-0.7.bin.tar.gz.
+
+So in our example, after mounting mnt, we do
+
+umssync .
+
+This will promote this directory (a recursive option is available) to full
+umsdos capabilities (long name ...). A ls -l before and after won't show
+much difference however. The file which were there are still there. But now
+you can do all this:
+
+	chmod 644 *
+	chown you.your_groupe *
+	ls >THIS_IS.A.VERY.LONG.NAME
+	ln -s toto tata
+	ls -l
+
+Once a directory is promoted, all subdirectory created will inherit that
+promotion.
+
+What happen if you boot DOS and create files in those promoted directories ?
+Umsdos won't notice new files, but will signal removed file (it won't crash).
+Using umssync in /etc/rc will make sure the DOS directory is in sync with
+the --linux-.---.
+
+It is a good idea to put the following command in your RC file just
+after the "mount -a":
+
+	mount -a
+	/sbin/umssync -i+ -c+ -r99 /umsdos_mount_point
+
+	(You put one for each umsdos mount point in the fstab)
+
+This will insure nice operation. A umsdos.fsck is in the making,
+so you will be allowed to managed umsdos partition in the same way
+other filesystem are, using the generic fsck front end.
+
+Hope this helps!
+
diff -u --recursive --new-file v1.3.21/linux/Documentation/modules.txt linux/Documentation/modules.txt
--- v1.3.21/linux/Documentation/modules.txt	Thu Jan  1 02:00:00 1970
+++ linux/Documentation/modules.txt	Fri Sep  1 09:11:18 1995
@@ -0,0 +1,107 @@
+This file describes the strategy for dynamically loadable modules
+in the Linux kernel. This is not a technical description on
+the internals of module, but mostly a sample of how to compile
+and use modules.
+
+In this kernel you also have a possibility to create modules that are
+less dependent on the kernel version.  This option can be selected
+during "make config", by enabling CONFIG_MODVERSIONS.
+Note: If you enable CONFIG_MODVERSIONS, you will need some utilities
+      from the latest module support package: "modules-1.1.8*.tar.gz"!
+
+Anyway, your first step is to compile the kernel, as explained in the
+file README.  It generally goes like:
+
+	make config
+	make dep
+	make clean
+	make zImage or make zlilo
+
+In "make config", you select what you want to include in the kernel.
+You will generally select the minimal set that is needed to boot:
+
+	The filesystem of your root partition
+	A scsi driver, but see below for a list of SCSI modules!
+	Normal hard drive support
+	Net support (CONFIG_NET)
+	TCP/IP support (CONFIG_INET), but no drivers!
+
+	plus those things that you just can't live without...
+
+What has been left out is generally loadable as a modules.
+The set of modules is rapidly increasing, but so far these are known:
+
+	Most filesystems: minix, xiafs, msdos, umsdos, sysv, isofs, hpfs,
+			  smbfs, nfs
+
+	Some SCSI drivers: aha1542, in2000
+
+	Some ethernet drivers:
+		plip, slip, dummy,
+		de600, de620
+		3c501, 3c509
+		eexpress, depca,
+		ewrk3, apricot
+
+	Most CDROM drivers:
+		aztcd:     Aztech,Orchid,Okano,Wearnes
+		cm206:     Philips/LMS CM206
+		gscd:      Goldstar GCDR-420
+		mcd, mcdx: Mitsumi LU005, FX001
+		optcd:     Optics Storage Dolphin 8000AT
+		sbpcd:     Matsushita/Panasonic CR52x, CR56x, CD200,
+		           Longshine LCS-7260, TEAC CD-55A
+		sonycd535: Sony CDU-531/535, CDU-510/515
+
+	Some misc modules:
+		lp: line printer
+		binfmt_elf: elf loader
+
+When you have made the kernel, you create the modules by doing:
+
+	make modules
+
+This will compile all modules and update the modules directory.
+In this directory you will then find a bunch of symbolic links,
+pointing to the various object files in the kernel tree.
+
+As soon as you have rebooted the newly made kernel, you can install
+and remove modules at will with the utilities: "insmod" and "rmmod".
+
+
+Now, after you have made all modules, you can also do:
+
+	make modules_install
+
+This will copy all newly made modules into subdirectories under
+"/lib/modules/kernel_release/", where "kernel_release" is something
+like 1.1.83, or whatever the current kernel version is...
+
+
+Nifty features:
+
+If you have installed the utilities from "modules-1.1.8*.tar.gz",
+you will have access to two new utilities: "modprobe" and "depmod"
+
+Using the modprobe utility, you can load any module like this:
+
+	/sbin/modprobe module
+
+without paying much attention to which kernel you are running.
+To use modprobe successfully, you generally place the following
+command in your /etc/rc.d/rc.S script.
+
+	/sbin/depmod -a
+
+This computes the dependencies between the different modules.
+Then if you do, for example
+
+	/sbin/modprobe umsdos
+
+you will automatically load _both_ the msdos and umsdos modules,
+since umsdos runs piggyback on msdos.
+
+
+Written by:
+	Jacques Gelinas <jacques@solucorp.qc.ca>
+	Bjorn Ekwall <bj0rn@blox.se>
diff -u --recursive --new-file v1.3.21/linux/Documentation/networking/arcnet-jumpers.txt linux/Documentation/networking/arcnet-jumpers.txt
--- v1.3.21/linux/Documentation/networking/arcnet-jumpers.txt	Thu Jan  1 02:00:00 1970
+++ linux/Documentation/networking/arcnet-jumpers.txt	Wed Jul 12 07:53:14 1995
@@ -0,0 +1,1911 @@
+
+-----------------------------------------------------------------------------
+This file is a supplement to README.arcnet.  Please read that for general
+driver configuration help.
+-----------------------------------------------------------------------------
+
+Because so many people (myself included) seem to have obtained ARCnet cards
+without manuals, this will be a quick listing of all jumper settings I can
+find.  Please e-mail apenwarr@foxnet.net with any settings for
+your particular card.
+
+Even if your ARCnet model isn't listed, but has the same jumpers, please
+e-mail me to say so.
+
+If your model isn't listed, and has different settings, PLEASE PLEASE tell
+me.  I had to figure mine out without the manual, and it WASN'T FUN!
+
+Cards Listed in this file (in this order, mostly):
+
+	Manufacturer	Model #		Bits
+	------------	-------		----
+	SMC		PC100		8
+	SMC		PC110		8
+	SMC		PC120		8
+	SMC		PC130		8
+	SMC		PC270E		8
+	SMC		PC500		16
+	SMC		PC500Longboard	16
+	SMC		PC550Longboard	16
+	SMC		PC600		16
+	SMC?		LCS-8830-T	16?
+	Puredata	PDI507		16
+	CNet Tech	CN120-Series	8
+	CNet Tech	CN160-Series	16
+	No Name		--		8/16
+	No Name		Taiwan R.O.C(?)	8
+	Tiara		Tiara Lancard(?)
+	
+
+** SMC = Standard Microsystems Corp.
+** CNet Tech = CNet Technology, Inc.
+
+The model # is listed right above specifics for that card.  Don't forget to
+read "quick briefing" first, since it applies to all ARCnets.
+
+
+Unclassified Stuff
+------------------
+  - Please send any other information you can find.
+  
+  - And some unknowns (other info is welcome!):
+     From: root@ultraworld.xs4all.nl (Timo Hilbrink)
+     To: apenwarr@foxnet.net (Avery Pennarun)
+     Date: Wed, 26 Oct 1994 02:10:32 +0000 (GMT)
+     Reply-To: timoh@xs4all.nl
+
+     [...parts deleted...]
+
+     About the jumpers: On my PC130 there is one more jumper, located near the
+     cable-connector and it's for changing to star or bus topology; 
+     closed: star - open: bus
+     On the PC500 are some more jumper-pins, one block labled with RX,PDN,TXI
+     and another with ALE,LA17,LA18,LA19 these are undocumented..
+
+     [...more parts deleted...]
+
+     --- CUT ---
+
+
+Quick Briefing:
+---------------
+
+All ARCnet cards should have a total of four different settings:
+
+  - the I/O address:  this is the "port" your ARCnet card is on.  Probed
+    values, as of v0.14, are only from 0x200 through 0x3F0. (If your card
+    has additional ones, which is possible, please tell me.) This should not
+    be the same as any other device on your system.  According to a doc I
+    got from Novell, MS Windows prefers values of 0x300 or more, eating
+    netconnections on my system otherwise.
+	- Avery's favourite: 0x300.
+
+  - the IRQ:  on 8-bit cards, it might be 2 (9), 3, 4, 5, or 7.
+             on 16-bit cards, it might be 2 (9), 3, 4, 5, 7, or 10-15.  Make
+    sure this is different from any other card on your system.  Note that
+    IRQ2 is the same as IRQ9, as far as Linux is concerned.
+	- Avery's favourite: IRQ2.
+
+  - the memory address:  Unlike most cards, ARCnets use "shared memory" for
+    copying buffers around.  Make SURE it doesn't conflict with any other
+    used memory in your system!
+	A0000		- VGA graphics memory (ok if you don't have VGA)
+        B0000		- Monochrome text mode
+        C0000		\  One of these is your VGA BIOS - usually C0000.
+        E0000		/
+        F0000		- System BIOS
+
+    Anything less than 0xA0000 is, well, a BAD idea since it isn't above
+    640k.
+	- Avery's favourite: 0xD0000
+
+  - the station address:  Every ARCnet card has its own "unique" network
+    address from 0 to 255.  Unlike ethernet, you can set this address
+    yourself.  Since it's only 8 bits, you can only have 254 ARCnet cards on
+    a network.  DON'T use 0 or 255, since these are reserved. (although neat
+    stuff will probably happen if you DO use them).  By the way, if you
+    haven't already guessed, don't set this the same as any other ARCnet on
+    your network!
+	- Avery's favourite:  3 and 4.  Not that it matters.
+
+
+** Standard Microsystems Corp (SMC) **
+PC100, PC110, PC120, PC130 (8-bit cards)
+PC500, PC600 (16-bit cards)
+---------------------------------
+  - mainly from Avery Pennarun <apenwarr@foxnet.net>.  Values depicted are
+    from Avery's setup.
+  - special thanks to Timo Hilbrink <timoh@xs4all.nl> for noting that PC120,
+    130, 500, and 600 all have the same switches as Avery's PC100. 
+    PC500/600 have several extra, undocumented pins though. (?)
+  - PC110 settings were verified by Stephen A. Wood <saw@cebaf.gov>
+  - On the other hand, John Edward Bauer <jbauer@badlands.NoDak.edu> said
+    the PC110 settings are all wrong.  In his case, you need to switch all
+    the 1's with 0's.  If you're having problems, try that.
+  - Also, the JP- and S-numbers probably don't match your card exactly.  Try
+    to find jumpers/switches with the same number of settings - it's
+    probably more reliable.
+  
+
+     JP5		       [|]    :    :    :    :
+(IRQ Setting)		      IRQ2  IRQ3 IRQ4 IRQ5 IRQ7
+		Put exactly one jumper on exactly one set of pins.
+
+                          1  2   3  4  5  6   7  8  9 10
+     S1                /----------------------------------\
+(I/O and Memory        |  1  1 * 0  0  0  0 * 1  1  0  1  |
+ addresses)            \----------------------------------/
+                          |--|   |--------|   |--------|
+                          (a)       (b)           (m)
+
+		a: The first digit of the I/O address.
+			Setting		Value
+			-------		-----
+			00		0
+			01		1
+			10		2
+			11		3
+
+		b: The second digit of the I/O address.
+			Setting		Value
+			-------		-----
+			0000		0
+			0001		1
+			0010		2
+			...		...
+			1110		E
+			1111		F
+
+		The I/O address is in the form ab0.  For example, if
+		a is 0x2 and b is 0xE, the address will be 0x2E0.
+
+		DO NOT SET THIS LESS THAN 0x200!!!!!
+
+
+		m: The first digit of the memory address.
+			Setting		Value
+			-------		-----
+			0000		0
+			0001		1
+			0010		2
+			...		...
+			1110		E
+			1111		F
+
+		The memory address is in the form m0000.  For example, if
+		m is D, the address will be 0xD0000.
+
+		DO NOT SET THIS TO C0000, F0000, OR LESS THAN A0000!
+
+                          1  2  3  4  5  6  7  8
+     S2                /--------------------------\
+(Station Address)      |  1  1  0  0  0  0  0  0  |
+                       \--------------------------/
+
+			Setting		Value
+			-------		-----
+			00000000	00
+			10000000	01
+			01000000	02
+			...
+			01111111	FE
+			11111111	FF
+
+		Note that this is binary with the digits reversed!
+
+		DO NOT SET THIS TO 0 OR 255 (0xFF)!
+
+
+*****************************************************************************
+
+** Standard Microsystems Corp (SMC) **
+PC130E/PC270E (8-bit cards)
+---------------------------
+  - from Juergen Seifert <seifert@htwm.de>
+
+
+STANDARD MICROSYSTEMS CORPORATION (SMC) ARCNET(R)-PC130E/PC270E
+===============================================================
+
+This description has been written by Juergen Seifert <seifert@htwm.de>
+using information from the following Original SMC Manual 
+
+             "Configuration Guide for
+             ARCNET(R)-PC130E/PC270
+            Network Controller Boards
+                Pub. # 900.044A
+                   June, 1989"
+
+ARCNET is a registered trademark of the Datapoint Corporation
+SMC is a registered trademark of the Standard Microsystems Corporation  
+
+The PC130E is an enhanced version of the PC130 board, is equipped with a 
+standard BNC female connector for connection to RG-62/U coax cable.
+Since this board is designed both for point-to-point connection in star
+networks and for connection to bus networks, it is downwardly compatible 
+with all the other standard boards designed for coax networks (that is,
+the PC120, PC110 and PC100 star topology boards and the PC220, PC210 and 
+PC200 bus topology boards).
+
+The PC270E is an enhanced version of the PC260 board, is equipped with two 
+modular RJ11-type jacks for connection to twisted pair wiring.
+It can be used in a star or a daisy-chained network.
+
+
+         8 7 6 5 4 3 2 1
+    ________________________________________________________________
+   |   |       S1        |                                          |
+   |   |_________________|                                          |
+   |    Offs|Base |I/O Addr                                         |
+   |     RAM Addr |                                              ___|
+   |         ___  ___                                       CR3 |___|
+   |        |   \/   |                                      CR4 |___|
+   |        |  PROM  |                                           ___|
+   |        |        |                                        N |   | 8
+   |        | SOCKET |                                        o |   | 7
+   |        |________|                                        d |   | 6
+   |                   ___________________                    e |   | 5
+   |                  |                   |                   A | S | 4
+   |       |oo| EXT2  |                   |                   d | 2 | 3
+   |       |oo| EXT1  |       SMC         |                   d |   | 2
+   |       |oo| ROM   |      90C63        |                   r |___| 1
+   |       |oo| IRQ7  |                   |               |o|  _____|
+   |       |oo| IRQ5  |                   |               |o| | J1  |
+   |       |oo| IRQ4  |                   |              STAR |_____|
+   |       |oo| IRQ3  |                   |                   | J2  |
+   |       |oo| IRQ2  |___________________|                   |_____|
+   |___                                               ______________|
+       |                                             |
+       |_____________________________________________|
+
+Legend:
+
+SMC 90C63	ARCNET Controller / Transceiver /Logic
+S1	1-3:	I/O Base Address Select
+	4-6:	Memory Base Address Select
+	7-8:	RAM Offset Select
+S2	1-8:	Node ID Select
+EXT		Extended Timeout Select
+ROM		ROM Enable Select
+STAR		Selected - Star Topology	(PC130E only)
+		Deselected - Bus Topology	(PC130E only)
+CR3/CR4		Diagnostic LEDs
+J1		BNC RG62/U Connector		(PC130E only)
+J1		6-position Telephone Jack	(PC270E only)
+J2		6-position Telephone Jack	(PC270E only)
+
+Setting one of the switches to Off/Open means "1", On/Closed means "0".
+
+
+Setting the Node ID
+-------------------
+
+The eight switches in group S2 are used to set the node ID.
+Each node attached to the network must have an unique node ID which
+must be diffrent from 0.
+Switch 1 serves as the least significant bit (LSB).
+
+The node ID is the sum of the values of all switches set to "1"  
+These values are:
+    Switch | Value
+    -------|-------
+      1    |   1
+      2    |   2
+      3    |   4
+      4    |   8
+      5    |  16
+      6    |  32
+      7    |  64
+      8    | 128
+
+Some Examples:
+
+    Switch         | Hex     | Decimal 
+   8 7 6 5 4 3 2 1 | Node ID | Node ID
+   ----------------|---------|---------
+   0 0 0 0 0 0 0 0 |    not allowed
+   0 0 0 0 0 0 0 1 |    1    |    1 
+   0 0 0 0 0 0 1 0 |    2    |    2
+   0 0 0 0 0 0 1 1 |    3    |    3
+       . . .       |         |
+   0 1 0 1 0 1 0 1 |   55    |   85
+       . . .       |         |
+   1 0 1 0 1 0 1 0 |   AA    |  170
+       . . .       |         |  
+   1 1 1 1 1 1 0 1 |   FD    |  253
+   1 1 1 1 1 1 1 0 |   FE    |  254
+   1 1 1 1 1 1 1 1 |   FF    |  255
+
+
+Setting the I/O Base Address
+----------------------------
+
+The first three switches in switch group S1 are used to select one
+of eight possible I/O Base addresses using the followig table
+
+
+   Switch | Hex I/O
+   1 2 3  | Address
+   -------|--------
+   0 0 0  |  260
+   0 0 1  |  290
+   0 1 0  |  2E0  (Manufactor's default)
+   0 1 1  |  2F0
+   1 0 0  |  300
+   1 0 1  |  350
+   1 1 0  |  380
+   1 1 1  |  3E0
+
+
+Setting the Base Memory (RAM) buffer Address
+--------------------------------------------
+
+The memory buffer requires 2K of a 16K block of RAM. The base of this
+16K block can be located in any of eight positions.
+Switches 4-6 of switch group S1 select the Base of the 16K block.
+Within that 16K address space, the buffer may be assigned any one of four 
+positions, determined by the offset, switches 7 and 8 of group S1.
+
+   Switch     | Hex RAM | Hex ROM
+   4 5 6  7 8 | Address | Address *)
+   -----------|---------|-----------
+   0 0 0  0 0 |  C0000  |  C2000
+   0 0 0  0 1 |  C0800  |  C2000
+   0 0 0  1 0 |  C1000  |  C2000
+   0 0 0  1 1 |  C1800  |  C2000
+              |         |
+   0 0 1  0 0 |  C4000  |  C6000
+   0 0 1  0 1 |  C4800  |  C6000
+   0 0 1  1 0 |  C5000  |  C6000
+   0 0 1  1 1 |  C5800  |  C6000
+              |         |
+   0 1 0  0 0 |  CC000  |  CE000
+   0 1 0  0 1 |  CC800  |  CE000
+   0 1 0  1 0 |  CD000  |  CE000
+   0 1 0  1 1 |  CD800  |  CE000
+              |         |
+   0 1 1  0 0 |  D0000  |  D2000  (Manufactor's default)
+   0 1 1  0 1 |  D0800  |  D2000
+   0 1 1  1 0 |  D1000  |  D2000
+   0 1 1  1 1 |  D1800  |  D2000
+              |         |
+   1 0 0  0 0 |  D4000  |  D6000
+   1 0 0  0 1 |  D4800  |  D6000
+   1 0 0  1 0 |  D5000  |  D6000
+   1 0 0  1 1 |  D5800  |  D6000
+              |         |
+   1 0 1  0 0 |  D8000  |  DA000
+   1 0 1  0 1 |  D8800  |  DA000
+   1 0 1  1 0 |  D9000  |  DA000
+   1 0 1  1 1 |  D9800  |  DA000
+              |         |
+   1 1 0  0 0 |  DC000  |  DE000
+   1 1 0  0 1 |  DC800  |  DE000
+   1 1 0  1 0 |  DD000  |  DE000
+   1 1 0  1 1 |  DD800  |  DE000
+              |         |
+   1 1 1  0 0 |  E0000  |  E2000
+   1 1 1  0 1 |  E0800  |  E2000
+   1 1 1  1 0 |  E1000  |  E2000
+   1 1 1  1 1 |  E1800  |  E2000
+  
+*) To enable the 8K Boot PROM install the jumper ROM.
+   The default is jumper ROM not installed.
+
+
+Setting the Timeouts and Interrupt
+----------------------------------
+
+The jumpers labeled EXT1 and EXT2 are used to determine the timeout 
+parameters. These two jumpers are normally left open.
+Refer to the COM9026 Data Sheet for alternate configurations.
+
+To select a hardware interrupt level set one (only one!) of the jumpers
+IRQ2, IRQ3, IRQ4, IRQ5, IRQ7. The Manufactor's default is IRQ2.
+ 
+
+Configuring the PC130E for Star or Bus Topology
+-----------------------------------------------
+
+The single jumper labeled STAR is used to configure the PC130E board for 
+star or bus topology.
+When the jumper is installed, the board may be used in a star network, when 
+it is removed, the board can be used in a bus topology.
+
+
+Diagnostic LEDs
+---------------
+
+Two diagnostic LEDs are visible on the rear bracket of the board.
+The green LED monitors the network activity: the red one shows the
+board activity:
+
+ Green  | Status               Red      | Status
+ -------|-------------------   ---------|-------------------
+  on    | normal activity      flash/on | data transfer
+  blink | reconfiguration      off      | no data transfer;
+  off   | defectiv board or             | incorect memory or
+        | node ID is zero               | I/O address
+
+
+*****************************************************************************
+
+** Standard Microsystems Corp (SMC) **
+PC500/PC550 Long Board (16-bit cards)
+-------------------------------------
+  - from Juergen Seifert <seifert@htwm.de>
+
+
+STANDARD MICROSYSTEMS CORPORATION (SMC) ARCNET-PC500/PC550 Long Board
+=====================================================================
+
+Note: There is another Version of the PC500 called Short Version, which 
+      is different in hard- and software! The most important differences
+      are:
+      - The long board has no Shared memory
+      - On the long board the selection of the interrupt is done by binary
+        coded switch, on the short board directly by jumper.
+
+
+This description has been written by Juergen Seifert <seifert@htwm.de>
+using information from the following Original SMC Manual 
+
+             "Configuration Guide for
+             SMC ARCNET-PC500/PC550
+         Series Network Controller Boards
+             Pub. # 900.033 Rev. A
+                November, 1989"
+
+ARCNET is a registered trademark of the Datapoint Corporation
+SMC is a registered trademark of the Standard Microsystems Corporation  
+
+The PC500 is equipped with a standard BNC female connector for connection
+to RG-62/U coax cable.
+The board is designed both for point-to-point connection in star networks
+and for connection to bus networks.
+
+The PC550 is equipped with two modular RJ11-type jacks for connection
+to twisted pair wiring.
+It can be used in a star or a daisy-chained network.
+
+       1 
+       0 9 8 7 6 5 4 3 2 1     6 5 4 3 2 1
+    ____________________________________________________________________
+   < |         SW1         | |     SW2     |                            |
+   > |_____________________| |_____________|                            |
+   <   IRQ    |I/O Addr                                                 |
+   >                                                                 ___|
+   <                                                            CR4 |___|
+   >                                                            CR3 |___|
+   <                                                                 ___|
+   >                                                              N |   | 8
+   <                                                              o |   | 7
+   >                                                              d | S | 6
+   <                                                              e | W | 5
+   >                                                              A | 3 | 4
+   <                                                              d |   | 3
+   >                                                              d |   | 2
+   <                                                              r |___| 1
+   >                                                        |o|    _____|
+   <                                                        |o|   | J1  |
+   >  3 1                                                   JP6   |_____|
+   < |o|o| JP2                                                    | J2  |
+   > |o|o|                                                        |_____|
+   <  4 2__                                               ______________|
+   >    |  |                                             |
+   <____|  |_____________________________________________|
+
+Legend:
+
+SW1	1-6:	I/O Base Address Select
+	7-10:	Interrupt Select
+SW2	1-6:	Reserved for Future Use
+SW3	1-8:	Node ID Select
+JP2	1-4:	Extended Timeout Select
+JP6		Selected - Star Topology	(PC500 only)
+		Deselected - Bus Topology	(PC500 only)
+CR3	Green	Monitors Network Activity
+CR4	Red	Monitors Board Activity
+J1		BNC RG62/U Connector		(PC500 only)
+J1		6-position Telephone Jack	(PC550 only)
+J2		6-position Telephone Jack	(PC550 only)
+
+Setting one of the switches to Off/Open means "1", On/Closed means "0".
+
+
+Setting the Node ID
+-------------------
+
+The eight switches in group SW3 are used to set the node ID. Each node
+attached to the network must have an unique node ID which must be 
+diffrent from 0.
+Switch 1 serves as the least significant bit (LSB).
+
+The node ID is the sum of the values of all switches set to "1"  
+These values are:
+
+    Switch | Value
+    -------|-------
+      1    |   1
+      2    |   2
+      3    |   4
+      4    |   8
+      5    |  16
+      6    |  32
+      7    |  64
+      8    | 128
+
+Some Examples:
+
+    Switch         | Hex     | Decimal 
+   8 7 6 5 4 3 2 1 | Node ID | Node ID
+   ----------------|---------|---------
+   0 0 0 0 0 0 0 0 |    not allowed
+   0 0 0 0 0 0 0 1 |    1    |    1 
+   0 0 0 0 0 0 1 0 |    2    |    2
+   0 0 0 0 0 0 1 1 |    3    |    3
+       . . .       |         |
+   0 1 0 1 0 1 0 1 |   55    |   85
+       . . .       |         |
+   1 0 1 0 1 0 1 0 |   AA    |  170
+       . . .       |         |  
+   1 1 1 1 1 1 0 1 |   FD    |  253
+   1 1 1 1 1 1 1 0 |   FE    |  254
+   1 1 1 1 1 1 1 1 |   FF    |  255 
+
+
+Setting the I/O Base Address
+----------------------------
+
+The first six switches in switch group SW1 are used to select one
+of 32 possible I/O Base addresses using the followig table
+
+   Switch       | Hex I/O
+   6 5  4 3 2 1 | Address
+   -------------|--------
+   0 1  0 0 0 0 |  200
+   0 1  0 0 0 1 |  210
+   0 1  0 0 1 0 |  220
+   0 1  0 0 1 1 |  230
+   0 1  0 1 0 0 |  240
+   0 1  0 1 0 1 |  250
+   0 1  0 1 1 0 |  260
+   0 1  0 1 1 1 |  270
+   0 1  1 0 0 0 |  280
+   0 1  1 0 0 1 |  290
+   0 1  1 0 1 0 |  2A0
+   0 1  1 0 1 1 |  2B0
+   0 1  1 1 0 0 |  2C0
+   0 1  1 1 0 1 |  2D0
+   0 1  1 1 1 0 |  2E0 (Manufactor's default)
+   0 1  1 1 1 1 |  2F0
+   1 1  0 0 0 0 |  300
+   1 1  0 0 0 1 |  310
+   1 1  0 0 1 0 |  320
+   1 1  0 0 1 1 |  330
+   1 1  0 1 0 0 |  340
+   1 1  0 1 0 1 |  350
+   1 1  0 1 1 0 |  360
+   1 1  0 1 1 1 |  370
+   1 1  1 0 0 0 |  380
+   1 1  1 0 0 1 |  390
+   1 1  1 0 1 0 |  3A0
+   1 1  1 0 1 1 |  3B0
+   1 1  1 1 0 0 |  3C0
+   1 1  1 1 0 1 |  3D0
+   1 1  1 1 1 0 |  3E0
+   1 1  1 1 1 1 |  3F0
+
+
+Setting the Interrupt
+---------------------
+
+Switches seven through ten of switch group SW1 are used to select the 
+interrupt level. The interrupt level is binary coded, so selections 
+from 0 to 15 would be possible, but only the following eight values will
+be supported: 3, 4, 5, 7, 9, 10, 11, 12.
+
+   Switch   | IRQ
+   10 9 8 7 | 
+   ---------|-------- 
+    0 0 1 1 |  3
+    0 1 0 0 |  4
+    0 1 0 1 |  5
+    0 1 1 1 |  7
+    1 0 0 1 |  9 (=2) (default)
+    1 0 1 0 | 10
+    1 0 1 1 | 11
+    1 1 0 0 | 12
+
+
+Setting the Timeouts 
+--------------------
+
+The two jumpers JP2 (1-4) are used to determine the timeout parameters. 
+These two jumpers are normally left open.
+Refer to the COM9026 Data Sheet for alternate configurations.
+
+
+Configuring the PC500 for Star or Bus Topology
+----------------------------------------------
+
+The single jumper labeled JP6 is used to configure the PC500 board for 
+star or bus topology.
+When the jumper is installed, the board may be used in a star network, when 
+it is removed, the board can be used in a bus topology.
+
+
+Diagnostic LEDs
+---------------
+
+Two diagnostic LEDs are visible on the rear bracket of the board.
+The green LED monitors the network activity: the red one shows the
+board activity:
+
+ Green  | Status               Red      | Status
+ -------|-------------------   ---------|-------------------
+  on    | normal activity      flash/on | data transfer
+  blink | reconfiguration      off      | no data transfer;
+  off   | defectiv board or             | incorect memory or
+        | node ID is zero               | I/O address
+
+
+*****************************************************************************
+
+** Possibly SMC **
+LCS-8830-T (16-bit card)
+------------------------
+	- from Mathias Katzer <mkatzer@HRZ.Uni-Bielefeld.DE>
+	
+This is a LCS-8830-T made by SMC, I think ('SMC' only appears on one PLCC,
+nowhere else, not even on the few xeroxed sheets from the manual).
+
+SMC Arcnet Board Type LCS-8830-T
+
+   ------------------------------------
+  |                                    |
+  |              JP3 88  8 JP2         |
+  |       #####      | \               |
+  |       #####    ET1 ET2          ###|
+  |                              8  ###|
+  |  U3   SW 1                  JP0 ###|  Phone Jacks
+  |  --                             ###|
+  | |  |                               |
+  | |  |   SW2                         |
+  | |  |                               |
+  | |  |  #####                        |
+  |  --   #####                       ####  BNC Connector 
+  |                                   ####
+  |   888888 JP1                       |
+  |   234567                           |
+   --                           -------
+     |||||||||||||||||||||||||||
+      --------------------------
+
+
+SW1: DIP-Switches for Station Address
+SW2: DIP-Switches for Memory Base and I/O Base addresses
+
+JP0: If closed, internal termination on (default open)
+JP1: IRQ Jumpers
+JP2: Boot-ROM enabled if closed
+JP3: Jumpers for respsonse timeout
+ 
+U3: Boot-ROM Socket          
+
+
+ET1 ET2     Response Time     Idle Time    Reconfiguration Time
+
+               78                86               840
+ X            285               316              1680
+     X        563               624              1680
+ X   X       1130              1237              1680
+
+(X means closed jumper)
+
+(DIP-Switch downwards means "0")
+
+The station address is binary-coded with SW1.
+
+The I/O base address is coded with DIP-Switches 6,7 and 8 of SW2:
+
+Switches        Base
+678             Address
+000		260-26f
+100		290-29f
+010		2e0-2ef
+110		2f0-2ff
+001		300-30f
+101		350-35f
+011		380-38f
+111 		3e0-3ef
+
+
+DIP Switches 1-5 of SW2 encode the RAM and ROM Adress Range:
+
+Switches        Ram           Rom
+12345           Adress Range  Address Range
+00000		C:0000-C:07ff	C:2000-C:3fff
+10000		C:0800-C:0fff
+01000		C:1000-C:17ff
+11000		C:1800-C:1fff
+00100		C:4000-C:47ff	C:6000-C:7fff
+10100		C:4800-C:4fff
+01100		C:5000-C:57ff 
+11100		C:5800-C:5fff
+00010		C:C000-C:C7ff	C:E000-C:ffff
+10010		C:C800-C:Cfff
+01010		C:D000-C:D7ff
+11010		C:D800-C:Dfff
+00110		D:0000-D:07ff	D:2000-D:3fff
+10110		D:0800-D:0fff
+01110		D:1000-D:17ff
+11110		D:1800-D:1fff
+00001		D:4000-D:47ff	D:6000-D:7fff
+10001		D:4800-D:4fff
+01001		D:5000-D:57ff
+11001		D:5800-D:5fff
+00101		D:8000-D:87ff	D:A000-D:bfff
+10101		D:8800-D:8fff
+01101		D:9000-D:97ff
+11101		D:9800-D:9fff 
+00011		D:C000-D:c7ff	D:E000-D:ffff
+10011		D:C800-D:cfff
+01011		D:D000-D:d7ff
+11011		D:D800-D:dfff
+00111		E:0000-E:07ff	E:2000-E:3fff
+10111		E:0800-E:0fff
+01111		E:1000-E:17ff
+11111		E:1800-E:1fff
+
+
+*****************************************************************************
+
+** PureData Corp **
+PDI507 (16-bit card)
+--------------------
+	- from Mark Rejhon <mdrejhon@magi.com> (slight modifications by
+	  Avery)
+	- Send questions/suggestions/etc about this text to Mark.
+
+Jumpers:
+
+	There is a jumper array at the bottom of the card, near the edge
+        connector.  This array is labelled J1.  They control the IRQs and
+        something else.  Put only one jumper on the IRQ pins.
+
+	IRQ2    - Use IRQ 2 (same as IRQ 9 as far as software is concerned)
+	IRQ3	- Use IRQ 3 (used by COM2 or COM4 serial port if either exists)
+	IRQ4	- Use IRQ 4 (used by COM1 or COM3 serial port if either exists)
+	IRQ5	- Use IRQ 5 (used by LPT2 parallel port if one exists)
+	IRQ6	- Use IRQ 6 (used by Floppy Disk Controller if one exists)
+	IRQ7	- Use IRQ 7 (used by LPT1 parallel port if one exists)
+
+[Avery's note:  This "unknown" set of two jumpers appears to be on all
+ARCnet cards by SMC as well.  Putting jumpers on them seems to affect the
+status register, but only for the two "reserved" bits, ETS1 and ETS2.  Any
+further information is welcome.]
+
+	ET1	- What is this?  (Not tested, no jumper put on it)
+	ET2	- What is this?  (Not tested, no jumper put on it)
+
+	There is a J2 jumper on two pins.  A jumper should be put on them,
+        since it was already there when I got the card.  I don't know what
+        this jumper is for though.
+
+	There is a two-jumper array for J3.  I don't know what it is for,
+        but there were already two jumpers on it when I got the card.  It's
+        a six pin grid in a two-by-three fashion.  The jumpers were
+        configured as follows:
+
+	   .-------.
+	 o | o   o |
+	   :-------:    ------> Accessible end of card with connectors
+	 o | o   o |             in this direction ------->
+	   `-------'
+
+	There is also a J4 jumper on two pins.  A jumper should be put on
+        them, since it was already there when I got the card.  I don't know
+        what this jumper is for though.
+
+
+DIP Switches:
+
+	The dipswitches accessible on the accessible end of the card while
+        it is installed, is used to set the arcnet address.  There are 8
+        switches.  Use an address from 1 to 254.
+
+	Switch No.
+	12345678	Arcnet address
+	-----------------------------------------
+	00000000	FF  	(Don't use this!)
+	00000001	FE
+	00000010	FD
+	....
+	11111101	2	
+	11111110	1
+	11111111	0	(Don't use this!)
+
+	There is another dipswitch array of 8 switches at the top of the
+        card.  There are five labelled MS0-MS4 which seem to control the
+        memory address, and another three labelled IO0-IO2 which seem to
+        control the base I/O address of the card.
+
+	This was difficult to test by trial and error, and the I/O addresses
+        are in a weird order.  This was tested by setting the DIP switches,
+        rebooting the computer, and attempting to load ARCETHER at various
+        addresses (mostly between 0x200 and 0x400).  The address that caused
+        the red transmit LED to blink, is the one that I thought works.
+
+	Also, the address 0x3D0 seem to have a special meaning, since the
+        ARCETHER packet driver loaded fine, but without the red LED
+        blinking.  I don't know what 0x3D0 is for though.  I recommend using
+        an address of 0x300 since Windows may not like addresses below
+        0x300.
+
+	IO Switch No.
+	210             I/O address
+	-------------------------------
+	111             0x260
+	110             0x290
+	101             0x2E0
+	100             0x2F0
+	011             0x300
+	010             0x350
+	001             0x380
+	000             0x3E0
+
+	The memory switches set a reserved address space of 0x1000 bytes
+        (0x100 segment units, or 4k).  For example if I set an address of
+        0xD000, it will use up addresses 0xD000 to 0xD100.
+
+	The memory switches were tested by booting using QEMM386 stealth,
+        and using LOADHI to see what address automatically became excluded
+        from the upper memory regions, and then attempting to load ARCETHER
+        using these addresses.
+
+	I recommend using an arcnet memory address of 0xD000, and putting
+        the EMS page frame at 0xC000 while using QEMM stealth mode.  That
+        way, you get contiguous high memory from 0xD100 almost all the way
+        the end of the megabyte.
+
+	Memory Switch 0 (MS0) didn't seem to work properly when set to OFF
+        on my card.  It could be malfunctioning on my card.  Experiment with
+        it ON first, and if it doesn't work, set it to OFF.  (It may be a
+        modifier for the 0x200 bit?)
+
+	MS Switch No.
+	43210           Memory address
+	--------------------------------
+	00001           0xE100  (guessed - was not detected by QEMM)
+	00011           0xE000  (guessed - was not detected by QEMM)
+	00101           0xDD00
+	00111           0xDC00
+	01001           0xD900
+	01011           0xD800
+	01101           0xD500
+	01111           0xD400
+	10001           0xD100
+	10011           0xD000
+	10101           0xCD00
+	10111           0xCC00
+	11001           0xC900 (guessed - crashes tested system)
+	11011           0xC800 (guessed - crashes tested system)
+	11101           0xC500 (guessed - crashes tested system)
+	11111           0xC400 (guessed - crashes tested system)
+	
+	
+*****************************************************************************
+
+** CNet Technology Inc. **
+120 Series (8-bit cards)
+------------------------
+  - from Juergen Seifert <seifert@htwm.de>
+
+
+CNET TECHNOLOGY INC. (CNet) ARCNET 120A SERIES
+==============================================
+
+This description has been written by Juergen Seifert <seifert@htwm.de>
+using information from the following Original CNet Manual 
+
+              "ARCNET
+            USER'S MANUAL 
+                for
+               CN120A
+               CN120AB
+               CN120TP
+               CN120ST
+               CN120SBT
+             P/N:12-01-0007
+             Revision 3.00"
+
+ARCNET is a registered trademark of the Datapoint Corporation
+
+P/N 120A   ARCNET 8 bit XT/AT Star
+P/N 120AB  ARCNET 8 bit XT/AT Bus
+P/N 120TP  ARCNET 8 bit XT/AT Twisted Pair
+P/N 120ST  ARCNET 8 bit XT/AT Star, Twisted Pair
+P/N 120SBT ARCNET 8 bit XT/AT Star, Bus, Twisted Pair
+
+    __________________________________________________________________
+   |                                                                  |
+   |                                                               ___|
+   |                                                          LED |___|
+   |                                                               ___|
+   |                                                            N |   | ID7
+   |                                                            o |   | ID6
+   |                                                            d | S | ID5
+   |                                                            e | W | ID4
+   |                     ___________________                    A | 2 | ID3
+   |                    |                   |                   d |   | ID2
+   |                    |                   |  1 2 3 4 5 6 7 8  d |   | ID1
+   |                    |                   | _________________ r |___| ID0
+   |                    |      90C65        ||       SW1       |  ____|
+   |  JP 8 7            |                   ||_________________| |    |
+   |    |o|o|  JP1      |                   |                    | J2 |
+   |    |o|o|  |oo|     |                   |         JP 1 1 1   |    |
+   |   ______________   |                   |            0 1 2   |____|
+   |  |  PROM        |  |___________________|           |o|o|o|  _____|
+   |  >  SOCKET      |  JP 6 5 4 3 2                    |o|o|o| | J1  |
+   |  |______________|    |o|o|o|o|o|                   |o|o|o| |_____|
+   |_____                 |o|o|o|o|o|                   ______________|
+         |                                             |
+         |_____________________________________________|
+
+Legend:
+
+90C65       ARCNET Probe
+S1  1-5:    Base Memory Address Select
+    6-8:    Base I/O Address Select
+S2  1-8:    Node ID Select (ID0-ID7)
+JP1     ROM Enable Select
+JP2     IRQ2
+JP3     IRQ3
+JP4     IRQ4
+JP5     IRQ5
+JP6     IRQ7
+JP7/JP8     ET1, ET2 Timeout Parameters
+JP10/JP11   Coax / Twisted Pair Select  (CN120ST/SBT only)
+JP12        Terminator Select       (CN120AB/ST/SBT only)
+J1      BNC RG62/U Connector        (all except CN120TP)
+J2      Two 6-position Telephone Jack   (CN120TP/ST/SBT only)
+
+Setting one of the switches to Off means "1", On means "0".
+
+
+Setting the Node ID
+-------------------
+
+The eight switches in SW2 are used to set the node ID. Each node attached
+to the network must have an unique node ID which must be diffrent from 0.
+Switch 1 (ID0) serves as the least significant bit (LSB).
+
+The node ID is the sum of the values of all switches set to "1"  
+These values are:
+
+   Switch | Label | Value
+   -------|-------|-------
+     1    | ID0   |   1
+     2    | ID1   |   2
+     3    | ID2   |   4
+     4    | ID3   |   8
+     5    | ID4   |  16
+     6    | ID5   |  32
+     7    | ID6   |  64
+     8    | ID7   | 128
+
+Some Examples:
+
+    Switch         | Hex     | Decimal 
+   8 7 6 5 4 3 2 1 | Node ID | Node ID
+   ----------------|---------|---------
+   0 0 0 0 0 0 0 0 |    not allowed
+   0 0 0 0 0 0 0 1 |    1    |    1 
+   0 0 0 0 0 0 1 0 |    2    |    2
+   0 0 0 0 0 0 1 1 |    3    |    3
+       . . .       |         |
+   0 1 0 1 0 1 0 1 |   55    |   85
+       . . .       |         |
+   1 0 1 0 1 0 1 0 |   AA    |  170
+       . . .       |         |  
+   1 1 1 1 1 1 0 1 |   FD    |  253
+   1 1 1 1 1 1 1 0 |   FE    |  254
+   1 1 1 1 1 1 1 1 |   FF    |  255
+
+
+Setting the I/O Base Address
+----------------------------
+
+The last three switches in switch block SW1 are used to select one
+of eight possible I/O Base addresses using the followig table
+
+
+   Switch      | Hex I/O
+    6   7   8  | Address
+   ------------|--------
+   ON  ON  ON  |  260
+   OFF ON  ON  |  290
+   ON  OFF ON  |  2E0  (Manufactor's default)
+   OFF OFF ON  |  2F0
+   ON  ON  OFF |  300
+   OFF ON  OFF |  350
+   ON  OFF OFF |  380
+   OFF OFF OFF |  3E0
+
+
+Setting the Base Memory (RAM) buffer Address
+--------------------------------------------
+
+The memory buffer (RAM) requires 2K. The base of this buffer can be 
+located in any of eight positions. The address of the Boot Prom is
+memory base + 8K or memory base + 0x2000.
+Switches 1-5 of switch block SW1 select the Memory Base address.
+
+   Switch              | Hex RAM | Hex ROM
+    1   2   3   4   5  | Address | Address *)
+   --------------------|---------|-----------
+   ON  ON  ON  ON  ON  |  C0000  |  C2000
+   ON  ON  OFF ON  ON  |  C4000  |  C6000
+   ON  ON  ON  OFF ON  |  CC000  |  CE000
+   ON  ON  OFF OFF ON  |  D0000  |  D2000  (Manufactor's default)
+   ON  ON  ON  ON  OFF |  D4000  |  D6000
+   ON  ON  OFF ON  OFF |  D8000  |  DA000
+   ON  ON  ON  OFF OFF |  DC000  |  DE000
+   ON  ON  OFF OFF OFF |  E0000  |  E2000
+  
+*) To enable the Boot ROM install the jumper JP1
+
+Note: Since the switches 1 and 2 are always set to ON it may be possible
+      that they can be used to add an offset of 2K, 4K or 6K to the base
+      address, but this feature is not documented in the manual and I
+      haven't testet it yet.
+
+
+Setting the Interrupt Line
+--------------------------
+
+To select a hardware interrupt level install one (only one!) of the jumpers
+JP2, JP3, JP4, JP5, JP6. JP2 is the default.
+
+   Jumper | IRQ     
+   -------|-----
+     2    |  2
+     3    |  3
+     4    |  4
+     5    |  5
+     6    |  7
+
+
+Setting the Internal Terminator on CN120AB/TP/SBT
+--------------------------------------------------
+
+The jumper JP12 is used to enable the internal terminator. 
+
+                         -----
+       0                |  0  |     
+     -----   ON         |     |  ON
+    |  0  |             |  0  |
+    |     |  OFF         -----   OFF
+    |  0  |                0
+     -----
+   Terminator          Terminator 
+    disabled            enabled
+  
+
+Selecting the Connector Type on CN120ST/SBT
+-------------------------------------------
+
+     JP10    JP11        JP10    JP11
+                         -----   -----
+       0       0        |  0  | |  0  |       
+     -----   -----      |     | |     |
+    |  0  | |  0  |     |  0  | |  0  |
+    |     | |     |      -----   -----
+    |  0  | |  0  |        0       0 
+     -----   -----
+     Coaxial Cable       Twisted Pair Cable 
+       (Default)
+
+
+Setting the Timeout Parameters
+------------------------------
+
+The jumpers labeled EXT1 and EXT2 are used to determine the timeout 
+parameters. These two jumpers are normally left open.
+
+
+
+*****************************************************************************
+
+** CNet Technology Inc. **
+160 Series (16-bit cards)
+-------------------------
+  - from Juergen Seifert <seifert@htwm.de>
+
+CNET TECHNOLOGY INC. (CNet) ARCNET 160A SERIES
+==============================================
+
+This description has been written by Juergen Seifert <seifert@htwm.de>
+using information from the following Original CNet Manual 
+
+              "ARCNET
+            USER'S MANUAL 
+                for
+               CN160A
+               CN160AB
+               CN160TP
+             P/N:12-01-0006
+             Revision 3.00"
+
+ARCNET is a registered trademark of the Datapoint Corporation
+
+P/N 160A   ARCNET 16 bit XT/AT Star
+P/N 160AB  ARCNET 16 bit XT/AT Bus
+P/N 160TP  ARCNET 16 bit XT/AT Twisted Pair
+
+   ___________________________________________________________________
+  <                             _________________________          ___|
+  >               |oo| JP2     |                         |    LED |___|
+  <               |oo| JP1     |        9026             |    LED |___|
+  >                            |_________________________|         ___|
+  <                                                             N |   | ID7
+  >                                                      1      o |   | ID6
+  <                                    1 2 3 4 5 6 7 8 9 0      d | S | ID5
+  >         _______________           _____________________     e | W | ID4
+  <        |     PROM      |         |         SW1         |    A | 2 | ID3
+  >        >    SOCKET     |         |_____________________|    d |   | ID2
+  <        |_______________|          | IO-Base   | MEM   |     d |   | ID1
+  >                                                             r |___| ID0
+  <                                                               ____|
+  >                                                              |    |
+  <                                                              | J1 |
+  >                                                              |    |
+  <                                                              |____|
+  >                            1 1 1 1                                |
+  <  3 4 5 6 7      JP     8 9 0 1 2 3                                |
+  > |o|o|o|o|o|           |o|o|o|o|o|o|                               |
+  < |o|o|o|o|o| __        |o|o|o|o|o|o|                    ___________|
+  >            |  |                                       |
+  <____________|  |_______________________________________|
+
+Legend:
+
+9026            ARCNET Probe
+SW1 1-6:    Base I/O Address Select
+    7-10:   Base Memory Address Select
+SW2 1-8:    Node ID Select (ID0-ID7)
+JP1/JP2     ET1, ET2 Timeout Parameters
+JP3-JP13    Interrupt Select
+J1      BNC RG62/U Connector        (CN160A/AB only)
+J1      Two 6-position Telephone Jack   (CN160TP only)
+LED
+
+Setting one of the switches to Off means "1", On means "0".
+
+
+Setting the Node ID
+-------------------
+
+The eight switches in SW2 are used to set the node ID. Each node attached
+to the network must have an unique node ID which must be diffrent from 0.
+Switch 1 (ID0) serves as the least significant bit (LSB).
+
+The node ID is the sum of the values of all switches set to "1"  
+These values are:
+
+   Switch | Label | Value
+   -------|-------|-------
+     1    | ID0   |   1
+     2    | ID1   |   2
+     3    | ID2   |   4
+     4    | ID3   |   8
+     5    | ID4   |  16
+     6    | ID5   |  32
+     7    | ID6   |  64
+     8    | ID7   | 128
+
+Some Examples:
+
+    Switch         | Hex     | Decimal 
+   8 7 6 5 4 3 2 1 | Node ID | Node ID
+   ----------------|---------|---------
+   0 0 0 0 0 0 0 0 |    not allowed
+   0 0 0 0 0 0 0 1 |    1    |    1 
+   0 0 0 0 0 0 1 0 |    2    |    2
+   0 0 0 0 0 0 1 1 |    3    |    3
+       . . .       |         |
+   0 1 0 1 0 1 0 1 |   55    |   85
+       . . .       |         |
+   1 0 1 0 1 0 1 0 |   AA    |  170
+       . . .       |         |  
+   1 1 1 1 1 1 0 1 |   FD    |  253
+   1 1 1 1 1 1 1 0 |   FE    |  254
+   1 1 1 1 1 1 1 1 |   FF    |  255
+
+
+Setting the I/O Base Address
+----------------------------
+
+The first six switches in switch block SW1 are used to select the I/O Base
+address using the followig table:
+
+             Switch        | Hex I/O
+    1   2   3   4   5   6  | Address
+   ------------------------|--------
+   OFF ON  ON  OFF OFF ON  |  260
+   OFF ON  OFF ON  ON  OFF |  290
+   OFF ON  OFF OFF OFF ON  |  2E0  (Manufactor's default)
+   OFF ON  OFF OFF OFF OFF |  2F0
+   OFF OFF ON  ON  ON  ON  |  300
+   OFF OFF ON  OFF ON  OFF |  350
+   OFF OFF OFF ON  ON  ON  |  380
+   OFF OFF OFF OFF OFF ON  |  3E0
+
+Note: Other IO-Base addresses seem to be selectable, but only the above
+      combinations are documented.
+
+
+Setting the Base Memory (RAM) buffer Address
+--------------------------------------------
+
+The switches 7-10 of switch block SW1 are used to select the Memory
+Base address of the RAM (2K) and the PROM.
+
+   Switch          | Hex RAM | Hex ROM
+    7   8   9  10  | Address | Address
+   ----------------|---------|-----------
+   OFF OFF ON  ON  |  C0000  |  C8000
+   OFF OFF ON  OFF |  D0000  |  D8000 (Default)
+   OFF OFF OFF ON  |  E0000  |  E8000
+
+Note: Other MEM-Base addresses seem to be selectable, but only the above
+      combinations are documented.
+
+
+Setting the Interrupt Line
+--------------------------
+
+To select a hardware interrupt level install one (only one!) of the jumpers
+JP3 through JP13 using the following table:
+
+   Jumper | IRQ     
+   -------|-----------------
+     3    |  14
+     4    |  15
+     5    |  12
+     6    |  11
+     7    |  10
+     8    |   3
+     9    |   4
+    10    |   5
+    11    |   6
+    12    |   7
+    13    |   2 (=9) Default!
+
+Note:  - Do not use JP11=IRQ6, it may conflict with your Floppy Disk
+         Controler
+       - Use JP3=IRQ14 only, if you don't have an IDE-, MFM-, or RLL-
+         Hard Disk, it may conflict with their controlers
+
+
+Setting the Timeout Parameters
+------------------------------
+
+The jumpers labeled JP1 and JP2 are used to determine the timeout
+parameters. These two jumpers are normally left open.
+
+
+*****************************************************************************
+
+** No Name **
+8-bit cards, 16-bit cards
+-------------------------
+  - from Juergen Seifert <seifert@htwm.de>
+  
+NONAME 8-BIT ARCNET
+===================
+
+I have named this ARCnet card "NONAME", since there is no name of any
+manufactor on the Installation manual nor on the shipping box. The only
+hint to the existence of a manufactor at all is written into cupper,
+it is "Made in Taiwan"
+
+This description has been written by Juergen Seifert <seifert@htwm.de>
+using information from the Original
+                    "ARCnet Installation Manual"
+
+
+    ________________________________________________________________
+   | |STAR| BUS| T/P|                                               |
+   | |____|____|____|                                               |
+   |                            _____________________               |
+   |                           |                     |              |
+   |                           |                     |              |
+   |                           |                     |              |
+   |                           |        SMC          |              |
+   |                           |                     |              |
+   |                           |       COM90C65      |              |
+   |                           |                     |              |
+   |                           |                     |              |
+   |                           |__________-__________|              |
+   |                                                           _____|
+   |      _______________                                     |  CN |
+   |     | PROM          |                                    |_____|
+   |     > SOCKET        |                                          |
+   |     |_______________|         1 2 3 4 5 6 7 8  1 2 3 4 5 6 7 8 |
+   |                               _______________  _______________ |
+   |           |o|o|o|o|o|o|o|o|  |      SW1      ||      SW2      ||
+   |           |o|o|o|o|o|o|o|o|  |_______________||_______________||
+   |___         2 3 4 5 7 E E R        Node ID       IOB__|__MEM____|
+       |        \ IRQ   / T T O                      |
+       |__________________1_2_M______________________|
+
+Legend:
+
+COM90C65:       Arcnet Probe
+S1  1-8:    Node ID Select
+S2  1-3:    I/O Base Address Select
+    4-6:    Memory Base Address Select
+    7-8:    RAM Offset Select
+ET1, ET2    Extended Timeout Select
+ROM     ROM Enable Select
+CN              RG62 Coax Connector
+STAR| BUS | T/P Three fields for placing a sign (colored circle)
+                indicating the topologie of the card
+
+Setting one of the switches to Off means "1", On means "0".
+
+
+Setting the Node ID
+-------------------
+
+The eight switches in group SW1 are used to set the node ID.
+Each node attached to the network must have an unique node ID which
+must be diffrent from 0.
+Switch 8 serves as the least significant bit (LSB).
+
+The node ID is the sum of the values of all switches set to "1"  
+These values are:
+
+    Switch | Value
+    -------|-------
+      8    |   1
+      7    |   2
+      6    |   4
+      5    |   8
+      4    |  16
+      3    |  32
+      2    |  64
+      1    | 128
+
+Some Examples:
+
+    Switch         | Hex     | Decimal 
+   1 2 3 4 5 6 7 8 | Node ID | Node ID
+   ----------------|---------|---------
+   0 0 0 0 0 0 0 0 |    not allowed
+   0 0 0 0 0 0 0 1 |    1    |    1 
+   0 0 0 0 0 0 1 0 |    2    |    2
+   0 0 0 0 0 0 1 1 |    3    |    3
+       . . .       |         |
+   0 1 0 1 0 1 0 1 |   55    |   85
+       . . .       |         |
+   1 0 1 0 1 0 1 0 |   AA    |  170
+       . . .       |         |  
+   1 1 1 1 1 1 0 1 |   FD    |  253
+   1 1 1 1 1 1 1 0 |   FE    |  254
+   1 1 1 1 1 1 1 1 |   FF    |  255
+
+
+Setting the I/O Base Address
+----------------------------
+
+The first three switches in switch group SW2 are used to select one
+of eight possible I/O Base addresses using the followig table
+
+   Switch      | Hex I/O
+    1   2   3  | Address
+   ------------|--------
+   ON  ON  ON  |  260
+   ON  ON  OFF |  290
+   ON  OFF ON  |  2E0  (Manufactor's default)
+   ON  OFF OFF |  2F0
+   OFF ON  ON  |  300
+   OFF ON  OFF |  350
+   OFF OFF ON  |  380
+   OFF OFF OFF |  3E0
+
+
+Setting the Base Memory (RAM) buffer Address
+--------------------------------------------
+
+The memory buffer requires 2K of a 16K block of RAM. The base of this
+16K block can be located in any of eight positions.
+Switches 4-6 of switch group SW2 select the Base of the 16K block.
+Within that 16K address space, the buffer may be assigned any one of four
+positions, determined by the offset, switches 7 and 8 of group SW2.
+
+   Switch     | Hex RAM | Hex ROM
+   4 5 6  7 8 | Address | Address *)
+   -----------|---------|-----------
+   0 0 0  0 0 |  C0000  |  C2000
+   0 0 0  0 1 |  C0800  |  C2000
+   0 0 0  1 0 |  C1000  |  C2000
+   0 0 0  1 1 |  C1800  |  C2000
+              |         |
+   0 0 1  0 0 |  C4000  |  C6000
+   0 0 1  0 1 |  C4800  |  C6000
+   0 0 1  1 0 |  C5000  |  C6000
+   0 0 1  1 1 |  C5800  |  C6000
+              |         |
+   0 1 0  0 0 |  CC000  |  CE000
+   0 1 0  0 1 |  CC800  |  CE000
+   0 1 0  1 0 |  CD000  |  CE000
+   0 1 0  1 1 |  CD800  |  CE000
+              |         |
+   0 1 1  0 0 |  D0000  |  D2000  (Manufactor's default)
+   0 1 1  0 1 |  D0800  |  D2000
+   0 1 1  1 0 |  D1000  |  D2000
+   0 1 1  1 1 |  D1800  |  D2000
+              |         |
+   1 0 0  0 0 |  D4000  |  D6000
+   1 0 0  0 1 |  D4800  |  D6000
+   1 0 0  1 0 |  D5000  |  D6000
+   1 0 0  1 1 |  D5800  |  D6000
+              |         |
+   1 0 1  0 0 |  D8000  |  DA000
+   1 0 1  0 1 |  D8800  |  DA000
+   1 0 1  1 0 |  D9000  |  DA000
+   1 0 1  1 1 |  D9800  |  DA000
+              |         |
+   1 1 0  0 0 |  DC000  |  DE000
+   1 1 0  0 1 |  DC800  |  DE000
+   1 1 0  1 0 |  DD000  |  DE000
+   1 1 0  1 1 |  DD800  |  DE000
+              |         |
+   1 1 1  0 0 |  E0000  |  E2000
+   1 1 1  0 1 |  E0800  |  E2000
+   1 1 1  1 0 |  E1000  |  E2000
+   1 1 1  1 1 |  E1800  |  E2000
+  
+*) To enable the 8K Boot PROM install the jumper ROM.
+   The default is jumper ROM not installed.
+
+
+Setting Interrupt Request Lines (IRQ)
+-------------------------------------
+
+To select a hardware interrupt level set one (only one!) of the jumpers
+IRQ2, IRQ3, IRQ4, IRQ5 or IRQ7. The Manufactor's default is IRQ2.
+ 
+
+Setting the Timeouts
+--------------------
+
+The two jumpers labeled ET1 and ET2 are used to determine the timeout
+parameters (respons and reconfiguration time). Every node in a network
+must be set to the same timeout values.
+
+   ET1 ET2 | Response Time (us) | Reconfiguration Time (ms)
+   --------|--------------------|--------------------------
+   Off Off |        78          |          840   (Default)
+   Off On  |       285          |         1680
+   On  Off |       563          |         1680
+   On  On  |      1130          |         1680
+
+On means jumper installed, Off means jumper not installed
+
+
+NONAME 16-BIT ARCNET
+====================
+
+The manual of my 8-Bit NONAME ARCnet Card contains another description
+of a 16-Bit Coax / Twisted Pair Card. This description is incomplete,
+because there are missing two pages in the manual booklet. (The table
+of contents reports pages ... 2-9, 2-11, 2-12, 3-1, ... but inside
+the booklet there is a diffrent way of counting ... 2-9, 2-10, A-1,
+(empty page), 3-1, ..., 3-18, A-1 (again), A-2)
+Also the picture of the board layout is not as good as the picture of
+8-Bit card, because there isn't any letter like "SW1" written to the
+picture.
+Should somebody have such a board, please feel free to complete this
+description or to send a mail to me!
+
+This description has been written by Juergen Seifert <seifert@htwm.de>
+using information from the Original
+                    "ARCnet Installation Manual"
+
+
+   ___________________________________________________________________
+  <                    _________________  _________________           |
+  >                   |       SW?       ||      SW?        |          |
+  <                   |_________________||_________________|          |
+  >                       ____________________                        |
+  <                      |                    |                       |
+  >                      |                    |                       |
+  <                      |                    |                       |
+  >                      |                    |                       |
+  <                      |                    |                       |
+  >                      |                    |                       |
+  <                      |                    |                       |
+  >                      |____________________|                       |
+  <                                                               ____|
+  >                       ____________________                   |    |
+  <                      |                    |                  | J1 |
+  >                      |                    <                  |    |
+  <                      |____________________|  ? ? ? ? ? ?     |____|
+  >                                             |o|o|o|o|o|o|         |
+  <                                             |o|o|o|o|o|o|         |
+  >                                                                   |
+  <             __                                         ___________|
+  >            |  |                                       |
+  <____________|  |_______________________________________|
+
+
+Setting one of the switches to Off means "1", On means "0".
+
+
+Setting the Node ID
+-------------------
+
+The eight switches in group SW2 are used to set the node ID.
+Each node attached to the network must have an unique node ID which
+must be diffrent from 0.
+Switch 8 serves as the least significant bit (LSB).
+
+The node ID is the sum of the values of all switches set to "1"  
+These values are:
+
+    Switch | Value
+    -------|-------
+      8    |   1
+      7    |   2
+      6    |   4
+      5    |   8
+      4    |  16
+      3    |  32
+      2    |  64
+      1    | 128
+
+Some Examples:
+
+    Switch         | Hex     | Decimal 
+   1 2 3 4 5 6 7 8 | Node ID | Node ID
+   ----------------|---------|---------
+   0 0 0 0 0 0 0 0 |    not allowed
+   0 0 0 0 0 0 0 1 |    1    |    1 
+   0 0 0 0 0 0 1 0 |    2    |    2
+   0 0 0 0 0 0 1 1 |    3    |    3
+       . . .       |         |
+   0 1 0 1 0 1 0 1 |   55    |   85
+       . . .       |         |
+   1 0 1 0 1 0 1 0 |   AA    |  170
+       . . .       |         |  
+   1 1 1 1 1 1 0 1 |   FD    |  253
+   1 1 1 1 1 1 1 0 |   FE    |  254
+   1 1 1 1 1 1 1 1 |   FF    |  255
+
+
+Setting the I/O Base Address
+----------------------------
+
+The first three switches in switch group SW1 are used to select one
+of eight possible I/O Base addresses using the followig table
+
+   Switch      | Hex I/O
+    3   2   1  | Address
+   ------------|--------
+   ON  ON  ON  |  260
+   ON  ON  OFF |  290
+   ON  OFF ON  |  2E0  (Manufactor's default)
+   ON  OFF OFF |  2F0
+   OFF ON  ON  |  300
+   OFF ON  OFF |  350
+   OFF OFF ON  |  380
+   OFF OFF OFF |  3E0
+
+
+Setting the Base Memory (RAM) buffer Address
+--------------------------------------------
+
+The memory buffer requires 2K of a 16K block of RAM. The base of this
+16K block can be located in any of eight positions.
+Switches 6-8 of switch group SW1 select the Base of the 16K block.
+Within that 16K address space, the buffer may be assigned any one of four
+positions, determined by the offset, switches 4 and 5 of group SW1.
+
+   Switch     | Hex RAM | Hex ROM
+   8 7 6  5 4 | Address | Address
+   -----------|---------|-----------
+   0 0 0  0 0 |  C0000  |  C2000
+   0 0 0  0 1 |  C0800  |  C2000
+   0 0 0  1 0 |  C1000  |  C2000
+   0 0 0  1 1 |  C1800  |  C2000
+              |         |
+   0 0 1  0 0 |  C4000  |  C6000
+   0 0 1  0 1 |  C4800  |  C6000
+   0 0 1  1 0 |  C5000  |  C6000
+   0 0 1  1 1 |  C5800  |  C6000
+              |         |
+   0 1 0  0 0 |  CC000  |  CE000
+   0 1 0  0 1 |  CC800  |  CE000
+   0 1 0  1 0 |  CD000  |  CE000
+   0 1 0  1 1 |  CD800  |  CE000
+              |         |
+   0 1 1  0 0 |  D0000  |  D2000  (Manufactor's default)
+   0 1 1  0 1 |  D0800  |  D2000
+   0 1 1  1 0 |  D1000  |  D2000
+   0 1 1  1 1 |  D1800  |  D2000
+              |         |
+   1 0 0  0 0 |  D4000  |  D6000
+   1 0 0  0 1 |  D4800  |  D6000
+   1 0 0  1 0 |  D5000  |  D6000
+   1 0 0  1 1 |  D5800  |  D6000
+              |         |
+   1 0 1  0 0 |  D8000  |  DA000
+   1 0 1  0 1 |  D8800  |  DA000
+   1 0 1  1 0 |  D9000  |  DA000
+   1 0 1  1 1 |  D9800  |  DA000
+              |         |
+   1 1 0  0 0 |  DC000  |  DE000
+   1 1 0  0 1 |  DC800  |  DE000
+   1 1 0  1 0 |  DD000  |  DE000
+   1 1 0  1 1 |  DD800  |  DE000
+              |         |
+   1 1 1  0 0 |  E0000  |  E2000
+   1 1 1  0 1 |  E0800  |  E2000
+   1 1 1  1 0 |  E1000  |  E2000
+   1 1 1  1 1 |  E1800  |  E2000
+  
+
+Setting Interrupt Request Lines (IRQ)
+-------------------------------------
+
+??????????????????????????????????????
+
+
+Setting the Timeouts
+--------------------
+
+??????????????????????????????????????
+
+
+*****************************************************************************
+
+** No Name **
+8-bit cards ("Made in Taiwan R.O.C.")
+-----------
+ - from Vojtech Pavlik <vpav4328@diana.troja.mff.cuni.cz>
+
+I have named this ARCnet card "NONAME", since I got only the card with
+no manual at all and the only text identifying the manufacturer is 
+"MADE IN TAIWAN R.O.C" printed on the card.
+
+This description was written by Vojtech Pavlik 
+(vpav4328@diana.troja.mff.cuni.cz) using parts of the ARCNET-jumpers 
+README file from Linux kernel 1.2.2. 
+
+          ____________________________________________________________
+         |                 1 2 3 4 5 6 7 8                            |
+         | |o|o| JP1       o|o|o|o|o|o|o|o| ON                        |
+         |  +              o|o|o|o|o|o|o|o|                        ___|
+         |  _____________  o|o|o|o|o|o|o|o| OFF         _____     |   | ID7
+         | |             | SW1                         |     |    |   | ID6
+         | > RAM (2k)    |        ____________________ |  H  |    | S | ID5
+         | |_____________|       |                    ||  y  |    | W | ID4
+         |                       |                    ||  b  |    | 2 | ID3
+         |                       |                    ||  r  |    |   | ID2
+         |                       |                    ||  i  |    |   | ID1
+         |                       |       90C65        ||  d  |    |___| ID0
+         |      SW3              |                    ||     |        |      
+         | |o|o|o|o|o|o|o|o| ON  |                    ||  I  |        |
+         | |o|o|o|o|o|o|o|o|     |                    ||  C  |        |
+         | |o|o|o|o|o|o|o|o| OFF |____________________||     |   _____|
+         |  1 2 3 4 5 6 7 8                            |     |  |     |___
+         |  ______________                             |     |  | BNC |___|
+         | |              |                            |_____|  |_____|
+         | > EPROM SOCKET |                                           |
+         | |______________|                                           |
+         |                                              ______________|
+         |                                             |
+         |_____________________________________________|
+
+Legend:
+
+90C65       ARCNET Chip 
+SW1 1-5:    Base Memory Address Select
+    6-8:    Base I/O Address Select
+SW2 1-8:    Node ID Select (ID0-ID7)
+SW3 1-5:    IRQ Select   
+    6-7:    Extra Timeout
+    8  :    Rom Enable   
+JP1         Led connector
+BNC         Coax connector
+
+Although the jumpers SW1 and SW3 are marked SW, not JP, they are jumpers, not 
+switches.
+
+Setting the jumpers to ON means connecting the upper two pins, off the bottom 
+two - or - in case of IRQ setting, connecting none of them at all.
+
+Setting the Node ID
+-------------------
+
+The eight switches in SW2 are used to set the node ID. Each node attached
+to the network must have an unique node ID which must be diffrent from 0.
+Switch 1 (ID0) serves as the least significant bit (LSB).
+
+Setting one of the switches to Off means "1", On means "0".
+
+The node ID is the sum of the values of all switches set to "1"  
+These values are:
+
+   Switch | Label | Value
+   -------|-------|-------
+     1    | ID0   |   1
+     2    | ID1   |   2
+     3    | ID2   |   4
+     4    | ID3   |   8
+     5    | ID4   |  16
+     6    | ID5   |  32
+     7    | ID6   |  64
+     8    | ID7   | 128
+
+Some Examples:
+
+    Switch         | Hex     | Decimal 
+   8 7 6 5 4 3 2 1 | Node ID | Node ID
+   ----------------|---------|---------
+   0 0 0 0 0 0 0 0 |    not allowed
+   0 0 0 0 0 0 0 1 |    1    |    1 
+   0 0 0 0 0 0 1 0 |    2    |    2
+   0 0 0 0 0 0 1 1 |    3    |    3
+       . . .       |         |
+   0 1 0 1 0 1 0 1 |   55    |   85
+       . . .       |         |
+   1 0 1 0 1 0 1 0 |   AA    |  170
+       . . .       |         |  
+   1 1 1 1 1 1 0 1 |   FD    |  253
+   1 1 1 1 1 1 1 0 |   FE    |  254
+   1 1 1 1 1 1 1 1 |   FF    |  255
+
+
+Setting the I/O Base Address
+----------------------------
+
+The last three switches in switch block SW1 are used to select one
+of eight possible I/O Base addresses using the followig table
+
+
+   Switch      | Hex I/O
+    6   7   8  | Address
+   ------------|--------
+   ON  ON  ON  |  260
+   OFF ON  ON  |  290
+   ON  OFF ON  |  2E0  (Manufactor's default)
+   OFF OFF ON  |  2F0
+   ON  ON  OFF |  300
+   OFF ON  OFF |  350
+   ON  OFF OFF |  380
+   OFF OFF OFF |  3E0
+
+
+Setting the Base Memory (RAM) buffer Address
+--------------------------------------------
+
+The memory buffer (RAM) requires 2K. The base of this buffer can be 
+located in any of eight positions. The address of the Boot Prom is
+memory base + 0x2000.
+Jumpers 3-5 of jumper block SW1 select the Memory Base address.
+
+   Switch              | Hex RAM | Hex ROM
+    1   2   3   4   5  | Address | Address *)
+   --------------------|---------|-----------
+   ON  ON  ON  ON  ON  |  C0000  |  C2000
+   ON  ON  OFF ON  ON  |  C4000  |  C6000
+   ON  ON  ON  OFF ON  |  CC000  |  CE000
+   ON  ON  OFF OFF ON  |  D0000  |  D2000  (Manufactor's default)
+   ON  ON  ON  ON  OFF |  D4000  |  D6000
+   ON  ON  OFF ON  OFF |  D8000  |  DA000
+   ON  ON  ON  OFF OFF |  DC000  |  DE000
+   ON  ON  OFF OFF OFF |  E0000  |  E2000
+  
+*) To enable the Boot ROM set the jumper 8 of jumper block SW3 to position ON.
+
+The jumpers 1 and 2 probably add 0x0800, 0x1000 and 0x1800 to RAM addres.
+
+Setting the Interrupt Line
+--------------------------
+
+Jumpers 1-5 of the jumper block SW3 controll the IRQ level.
+
+    Jumper              |  IRQ
+    1   2   3   4   5   |
+   ----------------------------
+    ON  OFF OFF OFF OFF |  2
+    OFF ON  OFF OFF OFF |  3
+    OFF OFF ON  OFF OFF |  4
+    OFF OFF OFF ON  OFF |  5
+    OFF OFF OFF OFF ON  |  7
+
+
+Setting the Timeout Parameters
+------------------------------
+
+The jumpers 6-7 of the jumper block SW3 are used to determine the timeout 
+parameters. These two jumpers are normally left in the OFF position.
+
+
+*****************************************************************************
+** Tiara **
+(model unknown)
+-------------------------
+  - from Christoph Lameter <clameter@netcom.com>
+  
+
+Here is information about my card as far as I could figure it out:
+----------------------------------------------- tiara
+Tiara LanCard of Tiara Computer Systems.
+
++----------------------------------------------+
+!           ! Transmitter Unit !               !
+!           +------------------+             -------
+!          MEM                              Coax Connector
+!  ROM    7654321 <- I/O                     -------
+!  :  :   +--------+                           !
+!  :  :   ! 90C66LJ!                         +++
+!  :  :   !        !                         !D  Switch to set
+!  :  :   !        !                         !I  the Nodenumber
+!  :  :   +--------+                         !P
+!                                            !++
+!         234567 <- IRQ                      !
++------------!!!!!!!!!!!!!!!!!!!!!!!!--------+
+             !!!!!!!!!!!!!!!!!!!!!!!!
+
+0 = Jumper Installed
+1 = Open
+
+Top Jumper line Bit 7 = Rom Enable 654=Memory location 321=I/O
+
+Settings for Memory Location (Top Jumper Line)
+456     Address selected
+000	C0000
+001     C4000
+010     CC000
+011     D0000
+100     D4000
+101     D8000
+110     DC000     
+111     E0000
+
+Settings for I/O Address (Top Jumper Line)
+123     Port
+000	260
+001	290
+010	2E0
+011	2F0
+100	300
+101	350
+110	380
+111	3E0
+
+Settings for IRQ Selection (Lower Jumper Line)
+234567
+011111 IRQ 2
+101111 IRQ 3
+110111 IRQ 4
+111011 IRQ 5
+111110 IRQ 7
+
+*****************************************************************************
+
+
+Other Cards
+-----------
+
+I have no information on other models of ARCnet cards at the moment.  Please
+send any and all info to:
+	apenwarr@foxnet.net
+
+Thanks.
diff -u --recursive --new-file v1.3.21/linux/Documentation/networking/arcnet.txt linux/Documentation/networking/arcnet.txt
--- v1.3.21/linux/Documentation/networking/arcnet.txt	Thu Jan  1 02:00:00 1970
+++ linux/Documentation/networking/arcnet.txt	Fri Aug 11 09:26:58 1995
@@ -0,0 +1,235 @@
+
+----------------------------------------------------------------------------
+NOTE:  See also README.arcnet-jumpers in this directory for jumper-setting
+information if you're like many of us and didn't happen to get a manual with
+your ARCnet card.
+----------------------------------------------------------------------------
+
+Since no one seems to listen to me otherwise, perhaps a poem will get your
+attention:
+			This is alpha software
+			If it works I DO CARE.
+			
+Hmm, I think I'm allowed to call that a poem, even though it's only two
+lines.  Hey, I'm in Computer Science, not English.  Give me a break.
+
+The point is:  I REALLY REALLY REALLY REALLY REALLY want to hear from you if
+you test this and get it working.  Or if you don't.  Or anything.
+
+ARCnet 0.32 ALPHA first made it into the Linux kernel 1.1.80 - this was
+nice, but after that even FEWER people started writing to me because they
+didn't even have to install the patch.  <sigh>
+
+Come on, be a sport!  Send me a success report!
+
+(hey, that was even better than my original poem... this is getting bad!)
+
+Anyway, enough complaining.  Let's get started:
+
+---------------------------------------------------------------------------
+			
+These are the ARCnet drivers for Linux.
+
+We're now back to more ALPHA releases after the 1.01 release which made it
+into Linux 1.2.2, so please be careful, and send all possible
+success/failure reports to me.  If I don't know when/if/how it works, I
+won't be able to answer people's questions.  Do we want that?  Of course
+not.
+
+Once again:  DO send me success reports!  I want to know if this is working!
+(You know, it might be argued that I'm pushing this point a little too much. 
+If you think so, why not flame me in a quick little e-mail?  Please also
+include the type of card(s) you're using, software, size of network, and
+whether it's working or not.)
+
+My e-mail address is:
+	apenwarr@foxnet.net
+
+
+Where do I discuss these drivers?
+---------------------------------
+
+There is a mailing list specifically for discussion of the ARCnet drivers
+for Linux, and anything you might want to interface them with (ie. DOS). 
+I'll also post new versions of the Linux-ARCnet distribution to the list in
+tar-gzip-uuencode format.
+
+To subscribe to the list, send a message to listserv@807-city.on.ca
+with the following line in the BODY (not the SUBJECT) of your message:
+	subscribe linux-arcnet YOUR REAL NAME
+Remember to remove your signature, or you'll get an error back.
+
+Send all bug (or success) reports to me or to the list.
+
+The people on linux-net@vger.rutgers.edu have also been known to be very
+helpful! :)
+
+
+Other Drivers and Info
+----------------------
+
+Also, SMC (one of the companies that makes ARCnet cards) has a WorldWideWeb
+site you might be interested in, which includes several drivers for various
+cards including ARCnet.  Try:
+	http://www.smc.com/
+	
+Performance Technologies makes various network software that supports
+ARCnet.
+	http://www.perftech.com/ or ftp to ftp.perftech.com.
+	
+Novell makes a networking stack for DOS which includes ARCnet drivers.  Try
+ftp'ing to ftp.novell.com.
+
+You can get the Crynwr packet driver collection (including arcether.com, the
+one you'll want for arcnet cards) from oak.oakland.edu:/simtel/msdos/pktdrvr.
+It won't work perfectly on a 386+ without patches, though, and also doesn't
+like several cards.  Mail me if you want a fixed version.  (Ahem:  I may or
+may not have a 100% fixed version by the time I get your mail!)
+
+
+Loadable Module Support
+-----------------------
+
+This is a available starting with 0.42 ALPHA.
+
+Configure and rebuild Linux.  When asked, say NO to "arcnet support" if you
+want loadable module support.
+
+	make config
+	make dep
+	make clean	
+	make zImage
+	make modules
+	
+	
+Booting into your "ARCnet" Kernel
+---------------------------------
+
+If you're using a loadable module, you need to use insmod to load the
+module, and you need to specify various characteristics of your card on the
+command line.  For example:
+	cd /usr/src/linux/modules
+	insmod arcnet.o io=0x300 irqnum=2 shmem=0xd0000
+You can also add a num=1, num=2 etc for additional arcnet cards that will
+use arc1, arc2 etc for their device names (instead of the default, arc0).
+	
+Otherwise the driver will load and probe for your card automatically.
+	
+Now go read the NET-2-HOWTO and ETHERNET-HOWTO for Linux; they should be
+available where you picked up this driver.  Think of your ARCnet as a
+souped-up (or down, as the case may be) ethernet card.
+
+By the way, be sure to change all references from "eth0" to "arc0" in the
+HOWTOs.  Remember that ARCnet isn't a "true" ethernet, and the device name
+is DIFFERENT.
+
+
+How do I get it to work with...?
+--------------------------------
+
+NFS: Should be fine linux->linux, just pretend you're using ethernet cards. 
+        oak.oakland.edu:/simtel/msdos/nfs has some nice DOS clients.  There
+        is also a DOS-based NFS server called SOSS.  It doesn't multitask
+        quite the way Linux does (actually, it doesn't multitask AT ALL) but
+        you never know what you might need.
+
+DOS: If you're using the freeware arcether.com, you might want to install
+        the source code patch.  It helps with PC/TCP, and also can get
+        arcether to load if it timed out too quickly during initialization. 
+        Mail me if you need a precompiled version of arcether.com. (ie. you
+        if don't have a DOS assembler)
+	
+Windows:  See DOS :)  Trumpet Winsock works fine with either the Novell or
+	Arcether client, assuming you remember to load winpkt of course.
+
+LAN Manager and Windows for Workgroups: These programs use protocols that
+        are incompatible with the internet standard.  They try to pretend
+        the cards are ethernet, and confuse everyone else on the network. 
+        However, v1.93 ALPHA and later of the Linux ARCnet driver support
+        this protocol via the 'arc0e' device.  After setting up arc0 as
+        usual, ifconfig and set up routes to your ethernet-encap hosts
+        through arc0e.  There may be non-Microsoft products that support
+        this protocol as well, so it was changed in 1.93 ALPHA from arc0w
+        to arc0e.
+        
+	Using the freeware Samba server and clients for Linux, you can now
+	interface quite nicely with TCP/IP-based WfWg or Lan Manager
+	networks.  In addition, the Linux host can be used as a router
+	between the standard and WfWg protocols, so hosts that could
+	previously never talk to each other should now be able to.
+
+        This feature is still in early testing, so please e-mail with any
+	comments/questions you might have.
+	
+OS2: Has not been tested.  The "correct" solution would be to buy either of
+	IBM's "TCP/IP for OS/2" or "Warp Connect" packages.  However,
+	ftp.microsoft.com also has a freeware Lan Manager for OS/2 client
+	which should use the same protocol as WfWg does.  This has not been
+	tested, however.  Please mail me with any results.
+        
+NetBSD/AmiTCP: These use an old version of the Internet standard ARCnet
+	protocol which is incompatible with the Linux driver at present. 
+	Work to support these is underway and should be available in a
+	standard release soon.
+
+
+It works: what now?
+-------------------
+
+Send mail describing your setup, preferably including driver version, kernel
+version, ARCnet card model, CPU type, number of systems on your network, and
+list of software in use to me at the following address:
+	apenwarr@foxnet.net
+
+I do send (sometimes automated) replies to all messages I receive.  My email
+can be weird (and also usually gets forwarded all over the place along the
+way to me), so if you don't get a reply within a reasonable time, please
+resend.
+
+
+It doesn't work: what now?
+--------------------------
+
+Do the same as above, but also include the output of the ifconfig and route
+commands, as well as any pertinent log entries (ie: anything that starts
+with "arcnet:" and has shown up since the last reboot) in your mail.
+
+If you want to try fixing it yourself (I highly recommend that you mail me
+about the problem first, since it might already have been solved) you may
+want to try some of the debug levels available.  For heavy testing on
+D_DURING or more, it would be a REALLY good idea to kill your klogd
+daemon first!  D_DURING displays 4-5 lines for each packet sent or
+received.  D_TX and RX actually DISPLAY each packet as it is sent or
+received, which is obviously quite big.
+
+You can run the arcdump shell script (available from me or in the full
+ARCnet package if you got it) as root to list the contents of the arcnet
+buffers at any time.  To make any sense at all out of this, you should grab
+the pertinent RFC's. (some are listed near the top of arcnet.c).  arcdump
+assumes your card is at 0xD0000.  If it isn't, edit the script.
+
+Buffers #0 and 1 are used for receiving, and Buffers #2 and 3 are for
+sending.  Ping-pong buffers are implemented both ways.
+
+If your debug level includes D_DURING, the buffers are cleared to a constant
+value of 0x42 every time the card is reset (which should only happen when
+you do an ifconfig up, or when Linux decides that the driver is broken). 
+This is to make it easier to figure out which bytes are being used by a
+packet.
+
+You can change the debug level without recompiling the kernel by typing:
+	ifconfig arc0 down metric 1xxx
+	/etc/rc.d/rc.inet1
+where "xxx" is the debug level you want.  For example, "metric 1015" would put
+you at debug level 15.  Debug level 7 is currently the default.
+
+Note that the debug level is (as of v1.90 ALPHA) a binary combination of
+different debug flags; so debug level 7 is really 1+2+4 or
+D_NORMAL+D_INIT+D_EXTRA.  To reach D_DURING, you would add 8 to this,
+resulting in debug level 15.
+
+
+I want to send money: what now?
+-------------------------------
+
+Go take a nap or something.  You'll feel better in the morning.
diff -u --recursive --new-file v1.3.21/linux/Documentation/networking/ax25.txt linux/Documentation/networking/ax25.txt
--- v1.3.21/linux/Documentation/networking/ax25.txt	Thu Jan  1 02:00:00 1970
+++ linux/Documentation/networking/ax25.txt	Wed Jul  5 13:06:27 1995
@@ -0,0 +1,50 @@
+This is version 029 of the new AX.25 and NET/ROM code for Linux. It
+incorporates many enhancements since the last release, notably the rewriting
+of the connected mode IP code and the IP over NET/ROM code. The opportunity
+has been taken to add the G8BPQ NET/ROM extensions and to add BPQ Ethernet
+support. The latter has been much eased by the use of the new variable
+length header code by Alan Cox.
+
+To use the BPQ Ethernet option, first up the ethernet interface in the usual
+manner, the IP address of the interface is not that important but it will
+be required for the ARP table. Next create an ARP entry in the ARP table of
+type ax25 for the interface binding it to an AX.25 callsign, this callsign
+will be the callsign of that interface. By default BPQ Ethernet uses a
+multi-cast address, this implementation does not, instead the standard
+ethernet broadcast address is used. Therefore the NET.CFG file for the
+ODI driver should look similar to this:
+
+------------------------------ cut here ------------------------------------
+
+LINK SUPPORT
+
+	MAX STACKS 1
+	MAX BOARDS 1
+
+LINK DRIVER E2000			; or other MLID to suit your card
+
+	INT 10				;
+	PORT 300			; to suit your card
+
+	FRAME ETHERNET_II
+
+	PROTOCOL BPQ 8FF ETHERNET_II	; required for BPQ - can change PID
+
+BPQPARMS				; optional - only needed if you want
+					; to override the default target addr
+
+	ETH_ADDR  FF:FF:FF:FF:FF:FF	; Target address
+
+----------------------------- cut here -------------------------------------
+
+The above configuration assumes that only BPQ Ethernet is being used.
+
+It is not possible to run IP over AX.25 on the BPQ Ethernet port. To simply
+route IP frames to (say) eth0 would create standard ethernet IP frames and
+completely bypass the AX.25 code. However it is possible to use IP over
+NET/ROM across a BPQ Ethernet link, the performance of such a system is
+very acceptable indeed.
+
+Jonathan Naylor G4KLX
+
+g4klx@amsat.org
diff -u --recursive --new-file v1.3.21/linux/Documentation/networking/net-modules.txt linux/Documentation/networking/net-modules.txt
--- v1.3.21/linux/Documentation/networking/net-modules.txt	Thu Jan  1 02:00:00 1970
+++ linux/Documentation/networking/net-modules.txt	Fri Aug 11 09:26:59 1995
@@ -0,0 +1,251 @@
+Wed 2-Aug-95  <matti.aarnio@utu.fi>
+
+		Linux network driver modules
+
+	Do not mistake this to "README.modules" at the top-level
+	directory!  That document tells about modules in general, while
+	this one tells only about network device driver modules.
+
+	This is a potpourri of INSMOD-time(*) configuration options
+	(if such exists) and their default values of various modules
+	on Linux network drivers collection.
+
+	Some modules have also hidden (= non-documented) tunable values.
+	Choice of not documenting them is based on general belief, that
+	the less user needs to know, the better.  (There are things that
+	driver developer can use, others should not confuse themselves.)
+
+	In many cases it is highly preferred that insmod:ing is done
+	ONLY with defining an explicite address for the card, AND BY
+	NOT USING AUTO-PROBING!
+
+	Now most cards have some explicitely defined base address, they
+	are compiled with (to avoid auto-probing, among other things).
+	If that compiled value does not match your actual configuration,
+	do use  "io=0xXXX" -parameter for the  insmod, and give there
+	a value matching your environment.
+
+	If you are adventureous, you can ask the driver to autoprobe
+	by using "io=0" parameter, however it is potentially dangerous
+	thing to do in a live system.  (If you don't know where the
+	card is located, you can try autoprobing, and after possible
+	crash recovery, insmod with proper IO-address..)
+
+	--------------------------
+	(*)	"INSMOD-time" means when you load module with
+		/sbin/insmod  you can feed it optional parameters.
+		See "man insmod".
+	--------------------------
+
+
+3c501.c:
+	io  = 0x280	IO base address
+	irq = 5		IRQ
+	(Probes ports:	0x280, 0x300)
+
+3c503.c:
+	io = 0x300
+	irq = 0
+	(Probes ports: 0x300, 0x310, 0x330, 0x350, 0x250, 0x280, 0x2A0, 0x2E0)
+
+3c505.c:
+	io = 0x300
+	irq = 0
+	(Probes ports: 0x300, 0x280, 0x310)
+
+3c507.c:
+	io = 0x300
+	irq = 0
+	(Probes ports: 0x300, 0x320, 0x340, 0x280)
+
+3c509.c:
+	io = 0
+	irq = 0
+	( Module load-time probing Works reliably only on EISA, ISA ID-PROBE
+	  IS NOT RELIABLE!  Compile this driver statically into kernel for
+	  now, if you need it auto-probing on an ISA-bus machine. )
+
+8390.c:
+	(No public options, several other modules need this one)
+
+ac3200.c:
+	io = 0
+	irq = 0
+	(EISA probing..)
+
+apricot.c:
+	io = 0x300  (Can't be altered!)
+	irq = 10
+
+arcnet.c:
+	io = 0
+	irqnum = 0
+	shmem = 0
+	num = 0
+	DO SET THESE MANUALLY AT INSMOD!
+	(When probing, looks at the following possible addresses:
+	 Suggested ones:
+		0x300, 0x2E0, 0x2F0, 0x2D0
+	 Other ones:
+		0x200, 0x210, 0x220, 0x230, 0x240, 0x250, 0x260, 0x270,
+		0x280, 0x290, 0x2A0, 0x2B0, 0x2C0,
+		       0x310, 0x320, 0x330, 0x340, 0x350, 0x360, 0x370,
+		0x380, 0x390, 0x3A0,			  0x3E0, 0x3F0  )
+
+at1700.c:
+	io = 0x260
+	irq = 0
+	(Probes ports: 0x260, 0x280, 0x2A0, 0x240, 0x340, 0x320, 0x380, 0x300)
+
+atp.c: *Not modularized*
+	(Probes ports: 0x378, 0x278, 0x3BC;
+	 fixed IRQs: 5 and 7			)
+
+
+auto_irq.c: *Static kernel component*
+
+
+de4x5.c:
+	io = 0x000b
+	irq = 10
+	is_not_dec = 0  -- For SMC card using DEC 21140 set this to 1
+	(EISA, and PCI probing)
+
+de600.c:
+	de600_debug = 0
+	(On port 0x378, irq 7 -- lpt1;  compile time configurable)
+
+de620.c:
+	bnc = 0, utp = 0  <-- Force media by setting either.
+	io = 0x378	(also compile-time configurable)
+	irq = 7
+
+depca.c:
+	io = 0x200
+	irq = 7
+	(Probes ports:	ISA:  0x300, 0x200;
+			EISA: 0x0c00		)
+
+dummy.c:
+	No options
+
+e2100.c:
+	io = 0x300
+	irq = 0
+	(Probes ports: 0x300, 0x280, 0x380, 0x220)
+
+eepro.c:
+	io = 0x200
+	irq = 0
+	(Probes ports: 0x200, 0x240, 0x280, 0x2C0, 0x300, 0x320, 0x340, 0x360)
+
+eexpress.c:
+	io = 0x300
+	irq = 0
+	(Probes ports: 0x300, 0x270, 0x320, 0x340)
+
+eql.c:
+	(No parameters)
+
+ewrk3.c:
+	io = 0x300
+	irq = 5
+	(With module no autoprobing!
+	 On EISA-bus does EISA probing.
+	 Static linkage probes ports on ISA bus:
+		0x100, 0x120, 0x140, 0x160, 0x180, 0x1A0, 0x1C0,
+		0x200, 0x220, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x2E0,
+		0x300,        0x340, 0x360, 0x380, 0x3A0, 0x3C0)
+
+hp-plus.c:
+	io = 0x200
+	irq = 0
+	(Probes ports: 0x200, 0x240, 0x280, 0x2C0, 0x300, 0x320, 0x340)
+
+hp.c:
+	io = 0x300
+	irq = 0
+	(Probes ports: 0x300, 0x320, 0x340, 0x280, 0x2C0, 0x200, 0x240)
+
+hp100.c:
+	hp100_port = 0 (IO-base address)
+	(Does EISA-probing, if on EISA-slot;
+	 On ISA-bus probes all ports from 0x100 thru to 0x3E0
+	 in increments of 0x020)
+
+ibmtr.c:
+	io = 0xA20
+	(Probes ports: 0xA20, 0xA24 -- Ok, 0x220, 0x224, but IBM style..)
+
+lance.c: *Not modularized*
+	(PCI, and ISA probing; "CONFIG_PCI" needed for PCI support)
+	(Probes ISA ports: 0x300, 0x320, 0x340, 0x360)
+
+loopback.c: *Static kernel component*
+
+ne.c:
+	io = 0x300
+	irq = 0
+	(Probes ports: 0x300, 0x280, 0x320, 0x340, 0x360)
+
+net_init.c: *Static kernel component*
+
+ni52.c: *Not modularized*
+	(Probes ports:	0x300, 0x280, 0x360, 0x320, 0x340
+		mems:	0xD0000, 0xD2000, 0xC8000, 0xCA000,
+			0xD4000, 0xD6000, 0xD8000 )
+
+ni65.c: *Not modularized*  **16MB MEMORY BARRIER BUG**
+	(Probes ports:	0x300, 0x320, 0x340, 0x360)
+
+pi2.c:	*Not modularized* (well, NON-STANDARD modularization!)
+	Only one card supported at this time.
+	(Probes ports: 0x380, 0x300, 0x320, 0x340, 0x360, 0x3A0)
+
+plip.c:
+	No options; goes to IO=0x278, IRQ=2
+
+ppp.c:
+	No options (ppp-2.2+ has some, this is based on non-dynamic
+	version from ppp-2.1.2d)
+
+seeq8005.c: *Not modularized*
+	(Probes ports: 0x300, 0x320, 0x340, 0x360)
+
+sk_g16.c: *Not modularized*
+	(Probes ports: 0x100, 0x180, 0x208, 0x220m 0x288, 0x320, 0x328, 0x390)
+
+skeleton.c: *Skeleton*
+
+slhc.c:
+	No configuration parameters
+
+slip.c:
+	slip_maxdev = 256 (default value from SL_NRUNIT on slip.h)
+
+
+smc-ultra.c:
+	io = 0x200
+	irq = 0
+	(Probes ports:	0x200, 0x220, 0x240, 0x280, 0x300, 0x340, 0x380)
+
+tulip.c: *Partial modularization*
+	(init-time memory allocation makes problems..)
+
+tunnel.c:
+	No insmod parameters
+
+wavelan.c:
+	io = 0x390	(Settable, but change not recommended)
+	irq = 0		(Not honoured, if changed..)
+
+wd.c:
+	io = 0x300
+	irq = 0
+	mem = 0		(Force shared-memory on address 0xC8000, or whatever..)
+	(Probes ports:	0x300, 0x280, 0x380, 0x240,
+	 uses AUTOIRQ)
+
+znet.c: *Not modularized*
+	(Only one device on  Zenith Z-Note (notebook?) systems,
+	 configuration information from (EE)PROM)
diff -u --recursive --new-file v1.3.21/linux/Documentation/networking/tcp.txt linux/Documentation/networking/tcp.txt
--- v1.3.21/linux/Documentation/networking/tcp.txt	Thu Jan  1 02:00:00 1970
+++ linux/Documentation/networking/tcp.txt	Tue Jun  6 11:22:26 1995
@@ -0,0 +1,39 @@
+How the new TCP output machine [nyi] works.
+
+
+Data is kept on a single queue. The skb->users flag tells us if the frame is
+one that has been queued already. To add a frame we throw it on the end. Ack
+walks down the list from the start.
+
+We keep a set of control flags
+
+
+	sk->tcp_pend_event
+
+		TCP_PEND_ACK			Ack needed
+		TCP_ACK_NOW			Needed now
+		TCP_WINDOW			Window update check
+		TCP_WINZERO			Zero probing
+
+
+	sk->transmit_queue		The transmission frame begin
+	sk->transmit_new		First new frame pointer
+	sk->transmit_end		Where to add frames
+
+	sk->tcp_last_tx_ack		Last ack seen
+	sk->tcp_dup_ack			Dup ack count for fast retransmit
+
+
+Frames are queued for output by tcp_write. We do our best to send the frames
+off immediately if possible, but otherwise queue and compute the body
+checksum in the copy. 
+
+When a write is done we try to clear any pending events and piggy back them.
+If the window is full we queue full sized frames. On the firs timeout in
+zero window we split this.
+
+On a timer we walk the retransmit list to send any retransmits, update the
+backoff timers etc. A change of route table stamp causes a change of header
+and recompute. We add any new tcp level headers and refinish the checksum
+before sending. 
+
diff -u --recursive --new-file v1.3.21/linux/Documentation/unicode.txt linux/Documentation/unicode.txt
--- v1.3.21/linux/Documentation/unicode.txt	Thu Jan  1 02:00:00 1970
+++ linux/Documentation/unicode.txt	Tue Jun 13 10:47:47 1995
@@ -0,0 +1,49 @@
+The Linux kernel code has been rewritten to use Unicode to map
+characters to fonts.  By downloading a single Unicode-to-font table,
+both the eight-bit character sets and UTF-8 mode are changed to use
+the font as indicated.
+
+This changes the semantics of the eight-bit character tables subtly.
+The four character tables are now:
+
+Map symbol	Map name			Escape code (G0)
+
+LAT1_MAP	Latin-1 (ISO 8859-1)		ESC ( B
+GRAF_MAP	DEC VT100 pseudographics	ESC ( 0
+IBMPC_MAP	IBM code page 437		ESC ( U
+USER_MAP	User defined			ESC ( K
+
+In particular, ESC ( U is no longer "straight to font", since the font
+might be completely different than the IBM character set.  This
+permits for example the use of block graphics even with a Latin-1 font
+loaded.
+
+In accordance with the Unicode standard/ISO 10646 the range U+F000 to
+U+F8FF has been reserved for OS-wide allocation (the Unicode Standard
+refers to this as a "Corporate Zone").  U+F000 was picked as the
+starting point since it lets the direct-mapping area start on a large
+power of two (in case 1024- or 2048-character fonts ever become
+necessary).  This leaves U+E000 to U+EFFF as End User Zone.
+
+The Unicodes in the range U+F000 to U+F1FF have been hard-coded to map
+directly to the loaded font, bypassing the translation table.  The
+user-defined map now defaults to U+F000 to U+F1FF, emulating the
+previous behaviour.
+
+In addition, the following characters not present in Unicode 1.1.4 (at
+least, I have not found them!) have been defined; these are used by
+the DEC VT graphics map:
+
+U+F800 DEC VT GRAPHICS HORIZONTAL LINE SCAN 1
+U+F801 DEC VT GRAPHICS HORIZONTAL LINE SCAN 3
+U+F803 DEC VT GRAPHICS HORIZONTAL LINE SCAN 7
+U+F804 DEC VT GRAPHICS HORIZONTAL LINE SCAN 9
+
+The DEC VT220 uses a 6x10 character matrix, and these characters form
+a smooth progression in the DEC VT graphics character set.  I have
+omitted the scan 5 line, since it is also used as a block-graphics
+character, and hence has been coded as U+2500 FORMS LIGHT HORIZONTAL.
+However, I left U+F802 blank should the need arise.  
+
+	H. Peter Anvin <Peter.Anvin@linux.org>
+	Yggdrasil Computing, Inc.
diff -u --recursive --new-file v1.3.21/linux/Makefile linux/Makefile
--- v1.3.21/linux/Makefile	Mon Aug 28 14:52:17 1995
+++ linux/Makefile	Tue Aug 29 07:01:59 1995
@@ -1,6 +1,6 @@
 VERSION = 1
 PATCHLEVEL = 3
-SUBLEVEL = 21
+SUBLEVEL = 22
 
 ARCH = i386
 
diff -u --recursive --new-file v1.3.21/linux/README linux/README
--- v1.3.21/linux/README	Tue Jun 13 15:40:16 1995
+++ linux/README	Tue Aug 29 09:51:10 1995
@@ -42,6 +42,10 @@
    Project) books.  This README is not meant to be documentation on the
    system: there are much better sources available.
 
+ - There are various readme's in the kernel doc/ subdirectory: these are
+   mainly used for kernel developers and some very kernel-specific
+   installation notes for some drivers for example.
+
 INSTALLING the kernel:
 
  - If you install the full sources, do a
diff -u --recursive --new-file v1.3.21/linux/README.modules linux/README.modules
--- v1.3.21/linux/README.modules	Fri Jul  7 08:54:43 1995
+++ linux/README.modules	Thu Jan  1 02:00:00 1970
@@ -1,106 +0,0 @@
-This file describes the strategy for dynamically loadable modules
-in the Linux kernel. This is not a technical description on
-the internals of module, but mostly a sample of how to compile
-and use modules.
-
-In this kernel you also have a possibility to create modules that are
-less dependent on the kernel version.  This option can be selected
-during "make config", by enabling CONFIG_MODVERSIONS.
-Note: If you enable CONFIG_MODVERSIONS, you will need some utilities
-      from the latest module support package: "modules-1.1.8*.tar.gz"!
-
-Anyway, your first step is to compile the kernel, as explained in the
-file README.  It generally goes like:
-
-	make config
-	make dep
-	make clean
-	make zImage or make zlilo
-
-In "make config", you select what you want to include in the kernel.
-You will generally select the minimal set that is needed to boot:
-
-	The filesystem of your root partition
-	A scsi driver, but see below for a list of SCSI modules!
-	Normal hard drive support
-	Net support (CONFIG_NET)
-	TCP/IP support (CONFIG_INET), but no drivers!
-
-	plus those things that you just can't live without...
-
-What has been left out is generally loadable as a modules.
-The set of modules is rapidly increasing, but so far these are known:
-
-	Most filesystems: minix, xiafs, msdos, umsdos, sysv, isofs
-
-	Some SCSI drivers: aha1542, in2000
-
-	Some ethernet drivers:
-		plip, slip, dummy,
-		de600, de620
-		3c501, 3c509
-		eexpress, depca,
-		ewrk3, apricot
-
-	Most CDROM drivers:
-		aztcd:     Aztech,Orchid,Okano,Wearnes
-		cm206:     Philips/LMS CM206
-		gscd:      Goldstar GCDR-420
-		mcd, mcdx: Mitsumi LU005, FX001
-		optcd:     Optics Storage Dolphin 8000AT
-		sbpcd:     Matsushita/Panasonic CR52x, CR56x, CD200,
-		           Longshine LCS-7260, TEAC CD-55A
-		sonycd535: Sony CDU-531/535, CDU-510/515
-
-	Some misc modules:
-		lp: line printer
-		binfmt_elf: elf loader
-
-When you have made the kernel, you create the modules by doing:
-
-	make modules
-
-This will compile all modules and update the modules directory.
-In this directory you will then find a bunch of symbolic links,
-pointing to the various object files in the kernel tree.
-
-As soon as you have rebooted the newly made kernel, you can install
-and remove modules at will with the utilities: "insmod" and "rmmod".
-
-
-Now, after you have made all modules, you can also do:
-
-	make modules_install
-
-This will copy all newly made modules into subdirectories under
-"/lib/modules/kernel_release/", where "kernel_release" is something
-like 1.1.83, or whatever the current kernel version is...
-
-
-Nifty features:
-
-If you have installed the utilities from "modules-1.1.8*.tar.gz",
-you will have access to two new utilities: "modprobe" and "depmod"
-
-Using the modprobe utility, you can load any module like this:
-
-	/sbin/modprobe module
-
-without paying much attention to which kernel you are running.
-To use modprobe successfully, you generally place the following
-command in your /etc/rc.d/rc.S script.
-
-	/sbin/depmod -a
-
-This computes the dependencies between the different modules.
-Then if you do, for example
-
-	/sbin/modprobe umsdos
-
-you will automatically load _both_ the msdos and umsdos modules,
-since umsdos runs piggyback on msdos.
-
-
-Written by:
-	Jacques Gelinas <jacques@solucorp.qc.ca>
-	Bjorn Ekwall <bj0rn@blox.se>
diff -u --recursive --new-file v1.3.21/linux/arch/alpha/Makefile linux/arch/alpha/Makefile
--- v1.3.21/linux/arch/alpha/Makefile	Mon Jan 16 07:17:34 1995
+++ linux/arch/alpha/Makefile	Tue Aug 29 10:15:48 1995
@@ -10,7 +10,11 @@
 
 NM := nm -B
 
+# enable this for linking under OSF/1:
 LINKFLAGS = -non_shared -T 0xfffffc0000310000 -N
+# enable this for linking under Linux:
+#LINKFLAGS = -static -T arch/alpha/vmlinux.lds -N
+
 CFLAGS := $(CFLAGS) -mno-fp-regs
 
 HEAD := arch/alpha/kernel/head.o
diff -u --recursive --new-file v1.3.21/linux/arch/alpha/boot/Makefile linux/arch/alpha/boot/Makefile
--- v1.3.21/linux/arch/alpha/boot/Makefile	Tue Aug 15 20:38:59 1995
+++ linux/arch/alpha/boot/Makefile	Tue Aug 29 10:15:48 1995
@@ -8,22 +8,32 @@
 # Copyright (C) 1994 by Linus Torvalds
 #
 
+# enable this for linking under OSF/1:
+LINKFLAGS = -non_shared -T 0x20000000 -N
+# enable this for linking under Linux:
+#LINKFLAGS = -static -T bootloader.lds -N 
+
 .S.s:
 	$(CC) -D__ASSEMBLY__ -traditional -E -o $*.o $<
 .S.o:
 	$(CC) -D__ASSEMBLY__ -traditional -c -o $*.o $<
 
 OBJECTS = head.o main.o
+TARGETS = tools/lxboot tools/bootlx vmlinux vmlinux.gz
 
-all:	tools/lxboot tools/bootlx vmlinux
-	@echo run mkfloppy on machine with floppy drive
+all:	$(TARGETS)
+	@echo Ready to install kernel in $(shell pwd)/vmlinux.gz
 
 msb:	tools/lxboot tools/bootlx vmlinux
 	( cat tools/lxboot tools/bootlx vmlinux ) > /dev/rz0a
 	disklabel -rw rz0 'linux' tools/lxboot tools/bootlx
 
+vmlinux.gz: vmlinux
+	gzip -fv vmlinux
+
 vmlinux: tools/build $(TOPDIR)/vmlinux
-	tools/build -v $(TOPDIR)/vmlinux > vmlinux
+	cp $(TOPDIR)/vmlinux vmlinux
+	quickstrip vmlinux
 
 tools/lxboot: tools/build
 	tools/build > tools/lxboot
@@ -35,13 +45,13 @@
 	$(HOSTCC) tools/build.c -o tools/build
 
 bootloader: $(OBJECTS)
-	$(LD) -non_shared -T 0x20000000 -N \
+	$(LD) $(LINKFLAGS) \
 		$(OBJECTS) \
 		$(LIBS) \
 		-o bootloader || \
 		(rm -f bootloader && exit 1)
 
 clean:
-	rm -f vmlinux bootloader tools/build tools/bootlx tools/lxboot
+	rm -f $(TARGETS) bootloader tools/build
 
 dep:
diff -u --recursive --new-file v1.3.21/linux/arch/alpha/boot/bootloader.lds linux/arch/alpha/boot/bootloader.lds
--- v1.3.21/linux/arch/alpha/boot/bootloader.lds	Thu Jul 13 16:20:19 1995
+++ linux/arch/alpha/boot/bootloader.lds	Tue Aug 29 10:15:48 1995
@@ -40,6 +40,7 @@
   .sbss : {
     *(.sbss)
     *(.scommon)
+    . = ALIGN(16);
   }
   .bss : {
     *(.bss)
diff -u --recursive --new-file v1.3.21/linux/arch/alpha/config.in linux/arch/alpha/config.in
--- v1.3.21/linux/arch/alpha/config.in	Tue Aug  8 12:31:32 1995
+++ linux/arch/alpha/config.in	Tue Aug 29 10:26:18 1995
@@ -2,7 +2,6 @@
 # For a description of the syntax of this configuration file,
 # see the Configure script.
 #
-
 comment 'General setup'
 
 bool 'Normal floppy disk support' CONFIG_BLK_DEV_FD y
@@ -22,9 +21,27 @@
 
 bool 'XT harddisk support' CONFIG_BLK_DEV_XD n
 bool 'Networking support' CONFIG_NET y
-bool 'PCI alpha motherboard' CONFIG_PCI n
+choice 'Alpha system type' \
+	"Jensen		CONFIG_ALPHA_JENSEN		\
+	 Noname		CONFIG_ALPHA_NONAME		\
+	 Cabriolet	CONFIG_ALPHA_CABRIOLET		\
+	 EB66		CONFIG_ALPHA_EB66		\
+	 EB66+		CONFIG_ALPHA_EB66P		\
+	 EB64		CONFIG_ALPHA_EB64		\
+	 EB64+		CONFIG_ALPHA_EB64P" Jensen
+if [ "$CONFIG_ALPHA_NONAME" = "y" ]; then
+	define_bool CONFIG_PCI y
+	define_bool CONFIG_ALPHA_LCA y
+fi
+if [ "$CONFIG_ALPHA_CABRIOLET" = "y" -o "$CONFIG_ALPHA_EB66" = "y" \
+	-o "$CONFIG_ALPHA_EB64" = "y" -o "$CONFIG_ALPHA_EB64P" = "y" ]
+then
+	define_bool CONFIG_PCI y
+	define_bool CONFIG_ALPHA_APECS y
+fi
+
 if [ "$CONFIG_PCI" = "y" ]; then
- bool '   PCI bridge optimisation (experimental)' CONFIG_PCI_OPTIMIZE n
+ bool 'PCI bridge optimisation (experimental)' CONFIG_PCI_OPTIMIZE n
 fi
 bool 'System V IPC' CONFIG_SYSVIPC y
 bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF n
diff -u --recursive --new-file v1.3.21/linux/arch/alpha/kernel/Makefile linux/arch/alpha/kernel/Makefile
--- v1.3.21/linux/arch/alpha/kernel/Makefile	Tue Aug 15 20:38:59 1995
+++ linux/arch/alpha/kernel/Makefile	Tue Aug 29 10:15:48 1995
@@ -13,7 +13,7 @@
 	$(CC) -D__ASSEMBLY__ -traditional -c $< -o $*.o
 
 OBJS  = entry.o traps.o process.o osf_sys.o irq.o signal.o setup.o \
-	lca.o bios32.o ptrace.o
+	bios32.o ptrace.o apecs.o lca.o
 
 all: kernel.o head.o
 
diff -u --recursive --new-file v1.3.21/linux/arch/alpha/kernel/apecs.c linux/arch/alpha/kernel/apecs.c
--- v1.3.21/linux/arch/alpha/kernel/apecs.c	Thu Jan  1 02:00:00 1970
+++ linux/arch/alpha/kernel/apecs.c	Tue Aug 29 10:15:48 1995
@@ -0,0 +1,467 @@
+/*
+ * Code common to all APECS chips.
+ *
+ * Rewritten for Apecs from the lca.c from:
+ *
+ * Written by David Mosberger (davidm@cs.arizona.edu) with some code
+ * taken from Dave Rusling's (david.rusling@reo.mts.dec.com) 32-bit
+ * bios code.
+ */
+#include <linux/kernel.h>
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/bios32.h>
+#include <linux/pci.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/hwrpb.h>
+#include <asm/ptrace.h>
+
+extern struct hwrpb_struct *hwrpb;
+extern asmlinkage void wrmces(unsigned long mces);
+extern int alpha_sys_type;
+/*
+ * BIOS32-style PCI interface:
+ */
+
+#ifdef CONFIG_ALPHA_APECS
+
+#ifdef DEBUG
+# define DBG(args)	printk(args)
+#else
+# define DBG(args)
+#endif
+
+#define vulp	volatile unsigned long *
+#define vuip	volatile unsigned int  *
+
+static volatile unsigned int apecs_mcheck_expected = 0;
+static volatile unsigned int apecs_mcheck_taken = 0;
+static unsigned long apecs_jd, apecs_jd1, apecs_jd2;
+
+
+/*
+ * Given a bus, device, and function number, compute resulting
+ * configuration space address and setup the APECS_HAXR2 register
+ * accordingly.  It is therefore not safe to have concurrent
+ * invocations to configuration space access routines, but there
+ * really shouldn't be any need for this.
+ *
+ * Type 0:
+ *
+ *  3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 
+ *  3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | | | | | | | | | | | | | | | | | | | | | | | |F|F|F|R|R|R|R|R|R|0|0|
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ *	31:11	Device select bit.
+ * 	10:8	Function number
+ * 	 7:2	Register number
+ *
+ * Type 1:
+ *
+ *  3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1 
+ *  3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | | | | | | | | | | |B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|1|
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ *	31:24	reserved
+ *	23:16	bus number (8 bits = 128 possible buses)
+ *	15:11	Device number (5 bits)
+ *	10:8	function number
+ *	 7:2	register number
+ *  
+ * Notes:
+ *	The function number selects which function of a multi-function device 
+ *	(e.g., scsi and ethernet).
+ * 
+ *	The register selects a DWORD (32 bit) register offset.  Hence it
+ *	doesn't get shifted by 2 bits as we want to "drop" the bottom two
+ *	bits.
+ */
+static int mk_conf_addr(unsigned char bus, unsigned char device_fn,
+			unsigned char where, unsigned long *pci_addr,
+			unsigned char *type1)
+{
+	unsigned long addr;
+
+	DBG(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x, pci_addr=0x%p, type1=0x%p)\n",
+	     bus, device_fn, where, pci_addr, type1));
+
+	if (bus == 0) {
+		int device = device_fn >> 3;
+
+		/* type 0 configuration cycle: */
+
+		if (device > 20) {
+			DBG(("mk_conf_addr: device (%d) > 20, returning -1\n", device));
+			return -1;
+		}
+
+		*type1 = 0;
+		addr = (device_fn << 8) | (where);
+	} else {
+		/* type 1 configuration cycle: */
+		*type1 = 1;
+		addr = (bus << 16) | (device_fn << 8) | (where);
+	}
+	*pci_addr = addr;
+	DBG(("mk_conf_addr: returning pci_addr 0x%lx\n", addr));
+	return 0;
+}
+
+
+static unsigned int conf_read(unsigned long addr, unsigned char type1)
+{
+	unsigned long flags;
+	unsigned int stat0, value;
+	unsigned int haxr2 = 0; /* to keep gcc quiet */
+
+	save_flags(flags);	/* avoid getting hit by machine check */
+	cli();
+
+	DBG(("conf_read(addr=0x%lx, type1=%d)\n", addr, type1));
+
+	/* reset status register to avoid losing errors: */
+	stat0 = *((volatile unsigned int *)APECS_IOC_DCSR);
+	*((volatile unsigned int *)APECS_IOC_DCSR) = stat0;
+	mb();
+	DBG(("conf_read: APECS DCSR was 0x%x\n", stat0));
+	/* if Type1 access, must set HAE #2 */
+	if (type1) {
+		haxr2 = *((unsigned int *)APECS_IOC_HAXR2);
+		mb();
+		*((unsigned int *)APECS_IOC_HAXR2) = haxr2 | 1;
+		DBG(("conf_read: TYPE1 access\n"));
+	}
+
+	draina();
+	apecs_mcheck_expected = 1;
+	apecs_mcheck_taken = 0;
+	mb();
+	/* access configuration space: */
+	value = *((volatile unsigned int *)addr);
+	mb();
+	mb();
+	if (apecs_mcheck_taken) {
+		apecs_mcheck_taken = 0;
+		value = 0xffffffffU;
+		mb();
+	}
+	apecs_mcheck_expected = 0;
+	mb();
+	/*
+	 * david.rusling@reo.mts.dec.com.  This code is needed for the
+	 * EB64+ as it does not generate a machine check (why I don't
+	 * know).  When we build kernels for one particular platform
+	 * then we can make this conditional on the type.
+	 */
+#if 1
+	draina();
+
+	/* now look for any errors */
+	stat0 = *((unsigned int *)APECS_IOC_DCSR);
+	DBG(("conf_read: APECS DCSR after read 0x%x\n", stat0));
+	if (stat0 & 0xffe0U) { /* is any error bit set? */
+		/* if not NDEV, print status */
+		if (!(stat0 & 0x0800)) {
+			printk("apecs.c:conf_read: got stat0=%x\n", stat0);
+		}
+
+		/* reset error status: */
+		*((volatile unsigned long *)APECS_IOC_DCSR) = stat0;
+		mb();
+		wrmces(0x7);			/* reset machine check */
+		value = 0xffffffff;
+	}
+#endif
+
+	/* if Type1 access, must reset HAE #2 so normal IO space ops work */
+	if (type1) {
+		*((unsigned int *)APECS_IOC_HAXR2) = haxr2 & ~1;
+		mb();
+	}
+	restore_flags(flags);
+	return value;
+}
+
+
+static void conf_write(unsigned long addr, unsigned int value, unsigned char type1)
+{
+	unsigned long flags;
+	unsigned int stat0;
+	unsigned int haxr2 = 0; /* to keep gcc quiet */
+
+	save_flags(flags);	/* avoid getting hit by machine check */
+	cli();
+
+	/* reset status register to avoid losing errors: */
+	stat0 = *((volatile unsigned int *)APECS_IOC_DCSR);
+	*((volatile unsigned int *)APECS_IOC_DCSR) = stat0;
+	mb();
+
+	/* if Type1 access, must set HAE #2 */
+	if (type1) {
+		haxr2 = *((unsigned int *)APECS_IOC_HAXR2);
+		mb();
+		*((unsigned int *)APECS_IOC_HAXR2) = haxr2 | 1;
+	}
+
+	draina();
+	apecs_mcheck_expected = 1;
+	mb();
+	/* access configuration space: */
+	*((volatile unsigned int *)addr) = value;
+	mb();
+	mb();
+	apecs_mcheck_expected = 0;
+	mb();
+	/*
+	 * david.rusling@reo.mts.dec.com.  This code is needed for the
+	 * EB64+ as it does not generate a machine check (why I don't
+	 * know).  When we build kernels for one particular platform
+	 * then we can make this conditional on the type.
+	 */
+#if 1
+	draina();
+
+	/* now look for any errors */
+	stat0 = *((unsigned int *)APECS_IOC_DCSR);
+	if (stat0 & 0xffe0U) { /* is any error bit set? */
+		/* if not NDEV, print status */
+		if (!(stat0 & 0x0800)) {
+			printk("apecs.c:conf_write: got stat0=%x\n", stat0);
+		}
+
+		/* reset error status: */
+		*((volatile unsigned long *)APECS_IOC_DCSR) = stat0;
+		mb();
+		wrmces(0x7);			/* reset machine check */
+	}
+#endif
+
+	/* if Type1 access, must reset HAE #2 so normal IO space ops work */
+	if (type1) {
+		*((unsigned int *)APECS_IOC_HAXR2) = haxr2 & ~1;
+		mb();
+	}
+	restore_flags(flags);
+}
+
+
+int pcibios_read_config_byte (unsigned char bus, unsigned char device_fn,
+			      unsigned char where, unsigned char *value)
+{
+	unsigned long addr = APECS_CONF;
+	unsigned long pci_addr;
+	unsigned char type1;
+
+	*value = 0xff;
+
+	if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1) < 0) {
+		return PCIBIOS_SUCCESSFUL;
+	}
+
+	addr |= (pci_addr << 5) + 0x00;
+
+	*value = conf_read(addr, type1) >> ((where & 3) * 8);
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+
+int pcibios_read_config_word (unsigned char bus, unsigned char device_fn,
+			      unsigned char where, unsigned short *value)
+{
+	unsigned long addr = APECS_CONF;
+	unsigned long pci_addr;
+	unsigned char type1;
+
+	*value = 0xffff;
+
+	if (where & 0x1) {
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+	}
+
+	if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) {
+		return PCIBIOS_SUCCESSFUL;
+	}
+
+	addr |= (pci_addr << 5) + 0x08;
+
+	*value = conf_read(addr, type1) >> ((where & 3) * 8);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+
+int pcibios_read_config_dword (unsigned char bus, unsigned char device_fn,
+			       unsigned char where, unsigned int *value)
+{
+	unsigned long addr = APECS_CONF;
+	unsigned long pci_addr;
+	unsigned char type1;
+
+	*value = 0xffffffff;
+	if (where & 0x3) {
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+	}
+
+	if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) {
+		return PCIBIOS_SUCCESSFUL;
+	}
+	addr |= (pci_addr << 5) + 0x18;
+	*value = conf_read(addr, type1);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+
+int pcibios_write_config_byte (unsigned char bus, unsigned char device_fn,
+			       unsigned char where, unsigned char value)
+{
+	unsigned long addr = APECS_CONF;
+	unsigned long pci_addr;
+	unsigned char type1;
+
+	if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1) < 0) {
+		return PCIBIOS_SUCCESSFUL;
+	}
+	addr |= (pci_addr << 5) + 0x00;
+	conf_write(addr, value << ((where & 3) * 8), type1);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+
+int pcibios_write_config_word (unsigned char bus, unsigned char device_fn,
+			       unsigned char where, unsigned short value)
+{
+	unsigned long addr = APECS_CONF;
+	unsigned long pci_addr;
+	unsigned char type1;
+
+	if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1) < 0) {
+		return PCIBIOS_SUCCESSFUL;
+	}
+	addr |= (pci_addr << 5) + 0x08;
+	conf_write(addr, value << ((where & 3) * 8), type1);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+
+int pcibios_write_config_dword (unsigned char bus, unsigned char device_fn,
+				unsigned char where, unsigned int value)
+{
+	unsigned long addr = APECS_CONF;
+	unsigned long pci_addr;
+	unsigned char type1;
+
+	if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1) < 0) {
+		return PCIBIOS_SUCCESSFUL;
+	}
+	addr |= (pci_addr << 5) + 0x18;
+	conf_write(addr, value << ((where & 3) * 8), type1);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+
+unsigned long apecs_init(unsigned long mem_start, unsigned long mem_end)
+{
+	/*
+	 * Set up the PCI->physical memory translation windows.
+	 * For now, window 1 is disabled.  In the future, we may
+	 * want to use it to do scatter/gather DMA.  Window 0
+	 * goes at 1 GB and is 1 GB large.
+	 */
+	*(vuip)APECS_IOC_PB2R  = 0U; /* disable window 2 */
+
+	*(vuip)APECS_IOC_PB1R  = 1U<<19 | (APECS_DMA_WIN_BASE & 0xfff00000U);
+	*(vuip)APECS_IOC_PM1R  = (APECS_DMA_WIN_SIZE - 1) & 0xfff00000U;
+	*(vuip)APECS_IOC_TB1R  = 0;
+
+#ifdef CONFIG_ALPHA_CABRIOLET
+	/*
+	 * JAE: HACK!!! for now, hardwire if configured...
+	 * davidm: miniloader doesn't seem to get clockfrequency
+	 * right, so fix for now.
+	 */
+	if (hwrpb->sys_type == ST_DEC_EB64P) {
+		hwrpb->sys_type = ST_DEC_EBPC64;
+	}
+	if (hwrpb->cycle_freq == 0) {
+	    hwrpb->cycle_freq = 275000000;
+	}
+
+	/* update checksum: */
+	{
+	    unsigned long *l, sum;
+
+	    sum = 0;
+	    for (l = (unsigned long *) hwrpb; l < (unsigned long *) &hwrpb->chksum; ++l)
+	      sum += *l;
+	    hwrpb->chksum = sum;
+	}
+#endif /* CONFIG_ALPHA_CABRIOLET */
+	return mem_start;
+}
+
+int apecs_pci_clr_err(void)
+{
+	apecs_jd = *((unsigned long *)APECS_IOC_DCSR);
+	if (apecs_jd & 0xffe0L) {
+		apecs_jd1 = *((unsigned long *)APECS_IOC_SEAR);
+		*((unsigned long *)APECS_IOC_DCSR) = apecs_jd | 0xffe1L;
+		apecs_jd = *((unsigned long *)APECS_IOC_DCSR);
+		mb();
+	}
+	*((unsigned long *)APECS_IOC_TBIA) = APECS_IOC_TBIA;
+	apecs_jd2 = *((unsigned long *)APECS_IOC_TBIA);
+	mb();
+	return 0;
+}
+
+void apecs_machine_check(unsigned long vector, unsigned long la_ptr,
+			 struct pt_regs * regs)
+{
+	struct el_common_logout_header *mchk_header;
+	struct el_apecs_sysdata_mcheck *mchk_sysdata;
+
+	mchk_header = (struct el_common_logout_header *)la_ptr;
+
+	mchk_sysdata = 
+	  (struct el_apecs_sysdata_mcheck *)(la_ptr + mchk_header->elfl_sysoffset);
+
+	DBG(("apecs_machine_check: vector=0x%lx la_ptr=0x%lx\n", vector, la_ptr));
+	DBG(("                     pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n",
+	     regs->pc, mchk_header->elfl_size, mchk_header->elfl_procoffset,
+	     mchk_header->elfl_sysoffset));
+	DBG(("apecs_machine_check: expected %d DCSR 0x%lx PEAR 0x%lx\n",
+	     apecs_mcheck_expected, mchk_sysdata->epic_dcsr, mchk_sysdata->epic_pear));
+#ifdef DEBUG
+	unsigned long *ptr;
+	int i;
+
+	ptr = (unsigned long *)la_ptr;
+	for (i = 0; i < mchk_header->elfl_size / sizeof(long); i += 2) {
+		printk(" +%x %lx %lx\n", i*sizeof(long), ptr[i], ptr[i+1]);
+	}
+#endif /* DEBUG */
+
+	/*
+	 * Check if machine check is due to a badaddr() and if so,
+	 * ignore the machine check.
+	 */
+	if (apecs_mcheck_expected && (mchk_sysdata->epic_dcsr && 0x0c00UL)) {
+		apecs_mcheck_expected = 0;
+		apecs_mcheck_taken = 1;
+		mb();
+		mb();
+		apecs_pci_clr_err();
+		wrmces(0x7);
+		mb();
+		draina();
+	}
+}
+
+#endif /* CONFIG_ALPHA_APECS */
diff -u --recursive --new-file v1.3.21/linux/arch/alpha/kernel/bios32.c linux/arch/alpha/kernel/bios32.c
--- v1.3.21/linux/arch/alpha/kernel/bios32.c	Fri Jun 16 22:02:54 1995
+++ linux/arch/alpha/kernel/bios32.c	Tue Aug 29 10:15:48 1995
@@ -49,7 +49,7 @@
 #define GB		(1024*MB)
 
 #define MAJOR_REV	0
-#define MINOR_REV	2
+#define MINOR_REV	3
 
 /*
  * Align VAL to ALIGN, which must be a power of two.
@@ -209,6 +209,19 @@
 		}
         }
 	/* enable device: */
+	if (dev->class >> 8 == PCI_CLASS_NOT_DEFINED ||
+	    dev->class >> 8 == PCI_CLASS_NOT_DEFINED_VGA ||
+	    dev->class >> 8 == PCI_CLASS_DISPLAY_VGA ||
+	    dev->class >> 8 == PCI_CLASS_DISPLAY_XGA)
+	{
+		/*
+		 * All of these (may) have I/O scattered all around
+		 * and may not use i/o-base address registers at all.
+		 * So we just have to always enable I/O to these
+		 * devices.
+		 */
+		cmd |= PCI_COMMAND_IO;
+	}
 	pcibios_write_config_word(bus->number, dev->devfn, PCI_COMMAND,
 				  cmd | PCI_COMMAND_MASTER);
 }
@@ -355,27 +368,202 @@
 	return mem_start;
 }
 
+/*
+ * The SRM console *disables* the IDE interface, this code ensures its
+ * enabled.
+ *
+ * This code bangs on a control register of the 87312 Super I/O chip
+ * that implements parallel port/serial ports/IDE/FDI.  Depending on
+ * the motherboard, the Super I/O chip can be configured through a
+ * pair of registers that are located either at I/O ports 0x26e/0x26f
+ * or 0x398/0x399.  Unfortunately, autodetecting which base address is
+ * in use works only once (right after a reset).  The Super I/O chip
+ * has the additional quirk that configuration register data must be
+ * written twice (I believe this is a saftey feature to prevent
+ * accidental modification---fun, isn't it?).
+ */
+static inline void enable_ide(long ide_base)
+{
+	int data;
+
+	outb(0, ide_base);		/* set the index register for reg #0 */
+	data = inb(ide_base+1);		/* read the current contents */
+	outb(0, ide_base);		/* set the index register for reg #0 */
+	outb(data | 0x40, ide_base+1);	/* turn on IDE */
+	outb(data | 0x40, ide_base+1);	/* turn on IDE, really! */
+}
 
 /*
- * Fixup configuration for Noname boards (AXPpci33).
+ * Most evaluation boards share most of the fixup code, which is isolated here.
+ * This function is declared "inline" as only one platform will ever be selected
+ * in any given kernel.  If that platform doesn't need this code, we don't want
+ * it around as dead code.
  */
-static void noname_fixup(void)
+static inline void common_fixup(long min_idsel, long max_idsel, long irqs_per_slot,
+				char irq_tab[max_idsel - min_idsel + 1][irqs_per_slot],
+			 long ide_base)
 {
 	struct pci_dev *dev;
+	unsigned char pin;
+	/*
+	 * Go through all devices, fixing up irqs as we see fit:
+	 */
+	for (dev = pci_devices; dev; dev = dev->next) {
+		dev->irq = 0;
+		/*
+		 * Ignore things not on the primary bus - I'll figure
+		 * this out one day - Dave Rusling
+		 */
+		if (dev->bus->number != 0)
+			continue;
+
+		/* read the pin */
+		pcibios_read_config_byte(dev->bus->number, dev->devfn,
+					 PCI_INTERRUPT_PIN, &pin);
+		if (irq_tab[PCI_SLOT(dev->devfn) - min_idsel][pin] != -1)
+			dev->irq = irq_tab[PCI_SLOT(dev->devfn) - min_idsel][pin];
+#if PCI_MODIFY
+		/* tell the device: */
+		pcibios_write_config_byte(dev->bus->number, dev->devfn,
+					  PCI_INTERRUPT_LINE, dev->irq);
+#endif
+	}
+	if (ide_base) {
+		enable_ide(ide_base);
+	}
+}
+
+/*
+ * The EB66+ is very similar to the EB66 except that it does not have
+ * the on-board NCR and Tulip chips.  In the code below, I have used
+ * slot number to refer to the id select line and *not* the slot
+ * number used in the EB66+ documentation.  However, in the table,
+ * I've given the slot number, the id select line and the Jxx number
+ * that's printed on the board.  The interrupt pins from the PCI slots
+ * are wired into 3 interrupt summary registers at 0x804, 0x805 and
+ * 0x806 ISA.
+ *
+ * In the table, -1 means don't assign an IRQ number.  This is usually
+ * because it is the Saturn IO (SIO) PCI/ISA Bridge Chip.
+ */
+static inline void eb66p_fixup(void)
+{
+	char irq_tab[5][5] = {
+		{16+0, 16+0, 16+5,  16+9, 16+13},	/* IdSel 6,  slot 0, J25 */
+		{16+1, 16+1, 16+6, 16+10, 16+14},	/* IdSel 7,  slot 1, J26 */
+		{  -1,   -1,   -1,    -1,    -1},	/* IdSel 8,  SIO         */
+		{16+2, 16+2, 16+7, 16+11, 16+15},	/* IdSel 9,  slot 2, J27 */
+		{16+3, 16+3, 16+8, 16+12,  16+6}	/* IdSel 10, slot 3, J28 */
+	};
+	common_fixup(6, 10, 5, irq_tab, 0x398);
+}
+
+
+/*
+ * The AlphaPC64 is very similar to the EB66+ except that its slots
+ * are numbered differently.  In the code below, I have used slot
+ * number to refer to the id select line and *not* the slot number
+ * used in the AlphaPC64 documentation.  However, in the table, I've
+ * given the slot number, the id select line and the Jxx number that's
+ * printed on the board.  The interrupt pins from the PCI slots are
+ * wired into 3 interrupt summary registers at 0x804, 0x805 and 0x806
+ * ISA.
+ *
+ * In the table, -1 means don't assign an IRQ number.  This is usually
+ * because it is the Saturn IO (SIO) PCI/ISA Bridge Chip.
+ */
+static inline void cabriolet_fixup(void)
+{
+	char irq_tab[5][5] = {
+		{ 16+2, 16+2, 16+7, 16+11, 16+15},      /* IdSel 5,  slot 2, J21 */
+		{ 16+0, 16+0, 16+5,  16+9, 16+13},      /* IdSel 6,  slot 0, J19 */
+		{ 16+1, 16+1, 16+6, 16+10, 16+14},      /* IdSel 7,  slot 1, J20 */
+		{   -1,   -1,   -1,    -1,    -1},	/* IdSel 8,  SIO         */
+		{ 16+3, 16+3, 16+8, 16+12, 16+16}       /* IdSel 9,  slot 3, J22 */
+	};
+	common_fixup(5, 9, 5, irq_tab, 0x398);
+}
+
+
+/*
+ * Fixup configuration for EB66/EB64+ boards.
+ *
+ * Both these boards use the same interrupt summary scheme.  There are
+ * two 8 bit external summary registers as follows:
+ *
+ * Summary @ 0x26:
+ * Bit      Meaning
+ * 0        Interrupt Line A from slot 0
+ * 1        Interrupt Line A from slot 1
+ * 2        Interrupt Line B from slot 0
+ * 3        Interrupt Line B from slot 1
+ * 4        Interrupt Line C from slot 0
+ * 5        Interrupt line from the two ISA PICs
+ * 6        Tulip (slot 
+ * 7        NCR SCSI
+ *
+ * Summary @ 0x27
+ * Bit      Meaning
+ * 0        Interrupt Line C from slot 1
+ * 1        Interrupt Line D from slot 0
+ * 2        Interrupt Line D from slot 1
+ * 3        RAZ
+ * 4        RAZ
+ * 5        RAZ
+ * 6        RAZ
+ * 7        RAZ
+ *
+ * The device to slot mapping looks like:
+ *
+ * Slot     Device
+ *  5       NCR SCSI controller
+ *  6       PCI on board slot 0
+ *  7       PCI on board slot 1
+ *  8       Intel SIO PCI-ISA bridge chip
+ *  9       Tulip - DECchip 21040 ethernet controller
+ *   
+ *
+ * This two layered interrupt approach means that we allocate IRQ 16 and 
+ * above for PCI interrupts.  The IRQ relates to which bit the interrupt
+ * comes in on.  This makes interrupt processing much easier.
+ */
+static inline void eb66_and_eb64p_fixup(void)
+{
+	char irq_tab[5][5] = {
+		{16+7, 16+7, 16+7, 16+7,  16+7},	/* IdSel 5,  slot ?, ?? */
+		{16+0, 16+0, 16+2, 16+4,  16+9},	/* IdSel 6,  slot ?, ?? */
+		{16+1, 16+1, 16+3, 16+8, 16+10},	/* IdSel 7,  slot ?, ?? */
+		{  -1,   -1,   -1,   -1,    -1},	/* IdSel 8,  SIO */
+		{16+6, 16+6, 16+6, 16+6,  16+6},	/* IdSel 9,  TULIP */
+	};
+	common_fixup(5, 9, 5, irq_tab, 0);
+}
+
 
+/*
+ * Fixup configuration for Noname boards (AXPpci33).
+ */
+static inline void noname_fixup(void)
+{
+	struct pci_dev *dev;
 	/*
 	 * The Noname board has 5 PCI slots with each of the 4
 	 * interrupt pins routed to different pins on the PCI/ISA
 	 * bridge (PIRQ0-PIRQ3).  I don't have any information yet as
 	 * to how INTB, INTC, and INTD get routed (4/12/95,
-	 * davidm@cs.arizona.edu).
+	 * davidm@cs.arizona.edu).  pirq_tab[0] is a fake entry to
+	 * deal with old PCI boards that have the interrupt pin number
+	 * hardwired to 0 (meaning that they use the default INTA
+	 * line, if they are interrupt driven at all).
 	 */
-	static const char pirq_tab[5][4] = {
-		{ 3, -1, -1, -1}, /* slot  6 (53c810) */ 
-		{-1, -1, -1, -1}, /* slot  7 (PCI/ISA bridge) */
-		{ 2, -1, -1, -1}, /* slot  8 (slot closest to ISA) */
-		{ 1, -1, -1, -1}, /* slot  9 (middle slot) */
-		{ 0, -1, -1, -1}, /* slot 10 (slot furthest from ISA) */
+	static const char pirq_tab[7][5] = {
+		{ 3,  3, -1, -1, -1}, /* idsel  6 (53c810) */ 
+		{-1, -1, -1, -1, -1}, /* idsel  7 (PCI/ISA bridge) */
+		{ 2,  2, -1, -1, -1}, /* idsel  8 (slot closest to ISA) */
+		{-1, -1, -1, -1, -1}, /* idsel  9 (unused) */
+		{-1, -1, -1, -1, -1}, /* idsel 10 (unused) */
+		{ 0,  0, -1, -1, -1}, /* idsel 11 (slot furthest from ISA) */
+		{ 1,  1, -1, -1, -1}, /* idsel 12 (middle slot) */
 	};
 	/*
 	 * route_tab selects irq routing in PCI/ISA bridge so that:
@@ -399,7 +587,7 @@
 	for (dev = pci_devices; dev; dev = dev->next) {
 		dev->irq = 0;
 		if (dev->bus->number != 0 ||
-		    PCI_SLOT(dev->devfn) < 6 || PCI_SLOT(dev->devfn) > 10)
+		    PCI_SLOT(dev->devfn) < 6 || PCI_SLOT(dev->devfn) > 12)
 		{
 			printk("noname_set_irq: no dev on bus %d, slot %d!!\n",
 			       dev->bus->number, PCI_SLOT(dev->devfn));
@@ -408,17 +596,7 @@
 
 		pcibios_read_config_byte(dev->bus->number, dev->devfn,
 					 PCI_INTERRUPT_PIN, &pin);
-		if (!pin) {
-			if (dev->vendor == PCI_VENDOR_ID_S3 &&
-			    (dev->device == PCI_DEVICE_ID_S3_864_1 ||
-			     dev->device == PCI_DEVICE_ID_S3_864_2))
-			{
-				pin = 1;
-			} else {
-				continue;	/* no interrupt line */
-			}
-		}
-		pirq = pirq_tab[PCI_SLOT(dev->devfn) - 6][pin - 1];
+		pirq = pirq_tab[PCI_SLOT(dev->devfn) - 6][pin];
 		if (pirq < 0) {
 			continue;
 		}
@@ -450,47 +628,7 @@
 	}
 #endif /* !PCI_MODIFY */
 
-	/*
-	 * The SRM console *disables* the IDE interface, this code *
-	 * enables it.	With the miniloader, this may not be necessary
-	 * but it shouldn't hurt either.
-	 *
-	 * This code bangs on a control register of the 87312 Super
-	 * I/O chip that implements parallel port/serial
-	 * ports/IDE/FDI.  Depending on the motherboard, the Super I/O
-	 * chip can be configured through a pair of registers that are
-	 * located either at I/O ports 0x26e/0x26f or 0x398/0x399.
-	 * Unfortunately, autodetecting which base address is in use
-	 * works only once (right after a reset).  On the other hand,
-	 * the Noname board hardwires the I/O ports to 0x26e/0x26f so
-	 * we just use those.  The Super I/O chip has the additional
-	 * quirk that configuration register data must be written
-	 * twice (I believe this is a saftey feature to prevent
-	 * accidental modification---happy PC world...).
-	 */
-	{
-		long flags;
-		int data;
-
-		/* update needs to be atomic: */
-
-		save_flags(flags);
-		cli();
-
-		outb(0, 0x26e); /* set the index register for reg #0 */
-		data = inb(0x26f); /* read the current contents */
-#ifdef DEBUG
-		printk("base @ 0x26e: reg#0 0x%x\n", data);
-#endif
-		outb(0, 0x26e); /* set the index register for reg #0 */
-		outb(data | 0x40, 0x26f); /* turn on IDE */
-		outb(data | 0x40, 0x26f); /* yes, we really mean it... */
-#ifdef DEBUG
-		outb(0, 0x26e); data = inb(0x26f);
-		printk("base @ 0x26e: reg#0 0x%x\n", data);
-#endif
-		restore_flags(flags);
-	}
+	enable_ide(0x26e);
 }
 
 
@@ -506,19 +644,22 @@
 	/*
 	 * Now is the time to do all those dirty little deeds...
 	 */
-	switch (hwrpb->sys_type) {
-	      case ST_DEC_AXPPCI_33:	noname_fixup();	break;
-
-	      default:
-		printk("pcibios_fixup: don't know how to fixup sys type %ld\n",
-		       hwrpb->sys_type);
-		break;
-	}
+#if defined(CONFIG_ALPHA_NONAME)
+	noname_fixup();
+#elif defined(CONFIG_ALPHA_CABRIOLET)
+	cabriolet_fixup();
+#elif defined(CONFIG_ALPHA_EB66)
+	eb66_and_eb64p_fixup();
+#elif defined(CONFIG_ALPHA_EB64P)
+	eb66_and_eb64p_fixup();
+#else
+#	error You must tell me what kind of platform you want.
+#endif
 	return mem_start;
 }
 
 
-char *pcibios_strerror (int error)
+const char *pcibios_strerror (int error)
 {
         static char buf[80];
 
diff -u --recursive --new-file v1.3.21/linux/arch/alpha/kernel/entry.S linux/arch/alpha/kernel/entry.S
--- v1.3.21/linux/arch/alpha/kernel/entry.S	Tue Jul 25 18:21:20 1995
+++ linux/arch/alpha/kernel/entry.S	Tue Aug 29 10:15:48 1995
@@ -36,6 +36,11 @@
 #define TASK_FLAGS	40
 
 /*
+ * task flags (must match include/linux/sched.h):
+ */
+#define	PF_PTRACED	0x00000010
+
+/*
  * This defines the normal kernel pt-regs layout.
  *
  * regs 9-15 preserved by C code
@@ -373,9 +378,27 @@
 	ldq $0,0($30)			/* restore original $0 */
 	lda $30,256($30)		/* pop entUna's stack frame */
 	SAVE_ALL			/* setup normal kernel stack */
+	lda $30,-56($30)
+	stq $9,0($30)
+	stq $10,8($30)
+	stq $11,16($30)
+	stq $12,24($30)
+	stq $13,32($30)
+	stq $14,40($30)
+	stq $15,48($30)
 	lda $27,do_entUnaUser
-	lda $26,ret_from_sys_call
-	jsr $31,($27),do_entUnaUser
+	bis $31,$30,$19
+	jsr $26,($27),do_entUnaUser
+	ldq $9,0($30)
+	ldq $10,8($30)
+	ldq $11,16($30)
+	ldq $12,24($30)
+	ldq $13,32($30)
+	ldq $14,40($30)
+	ldq $15,48($30)
+	lda $30,56($30)
+	br $31,ret_from_sys_call
+
 .end	entUnaUser
 
 .align 3
@@ -424,27 +447,14 @@
 	beq	$1,1f
 	ldq	$27,0($2)
 1:	jsr	$26,($27),do_entSys
-	ldq	$1,0($30)	/* We have to handle ptrace specially */
-	subq	$1,26,$1	/* since it returns a pointer value it will*/
-	bne	$1,3f		/* set up a3 and v0 in the return frame */
-	ldq	$1,72($30)
-	stq	$1,0($30)
-	stq	$0,72($30)
-	bis	$31,$31,$1
-	br	$31,ret_from_sys_call
-3:	bis	$31,$31,$1
-	bge	$0,2f		/* the call succeeded */
-	bis	$31,$31,$26	/* tell "ret_from_sys_call" that we can restart */
-	ldq	$19,0($30)	/* .. with this syscall nr */
-	ldq	$20,72($30)	/* .. and this a3 */
-	addq	$31,1,$1	/* set a3 for errno return */
-	subq	$31,$0,$0	/* with error in v0 */
-2:	stq	$0,0($30)
-	stq	$1,72($30)	/* a3 for return */
+	blt	$0,syscall_error	/* the call failed */
+	stq	$0,0($30)
+ret_success:
+	stq	$31,72($30)		/* a3=0 => no error */
 .align 3
 ret_from_sys_call:
 	ldq	$0,SP_OFF($30)
-	cmovne	$26,0,$19
+	cmovne	$26,0,$19		/* $19 = 0 => non-restartable */
 	and	$0,8,$0
 	beq	$0,restore_all
 ret_from_reschedule:
@@ -463,6 +473,27 @@
 restore_all:
 	RESTORE_ALL
 	rti
+
+	.align 3
+syscall_error:
+	/*
+	 * Some system calls (e.g., ptrace) can return arbitrary
+	 * values which might normally be mistaken as error numbers.
+	 * Those functions must setup $0 (v0) directly in the stack frame
+	 * and return with value -255.
+	 */
+	addq	$0,255,$1
+	beq	$1,ret_success
+
+	bis	$31,$31,$26	/* tell "ret_from_sys_call" that we can restart */
+	ldq	$19,0($30)	/* .. with this syscall nr */
+	ldq	$20,72($30)	/* .. and this a3 */
+	subq	$31,$0,$0	/* with error in v0 */
+	addq	$31,1,$1	/* set a3 for errno return */
+	stq	$0,0($30)
+	stq	$1,72($30)	/* a3 for return */
+	br	$31,ret_from_sys_call
+
 .align 3
 signal_return:
 	bis	$30,$30,$17
@@ -478,8 +509,8 @@
 .ent reschedule
 reschedule:
 	subq	$30,16,$30
-	stq	$19,0($30)
-	stq	$20,8($30)
+	stq	$19,0($30)	/* save syscall nr */
+	stq	$20,8($30)	/* and error indication (a3) */
 	lda	$27,schedule
 	jsr	$26,($27),schedule
 	ldq	$19,0($30)
@@ -510,7 +541,7 @@
 	jsr	$26,($27),do_sigsuspend
 	lda	$30,SWITCH_STACK_SIZE($30)
 	br	$31,ret_from_sys_call
-.end sys_sigreturn
+.end sys_sigsuspend
 
 	.align 3
 	.globl sys_call_table
@@ -525,7 +556,7 @@
 	.quad do_entSys, sys_sync, sys_kill, do_entSys, sys_setpgid
 	.quad do_entSys, sys_dup, sys_pipe, do_entSys, do_entSys
 	.quad sys_open, do_entSys, sys_getxgid, osf_sigprocmask, do_entSys
-/*50*/	.quad do_entSys, do_entSys, do_entSys, do_entSys, sys_ioctl
+/*50*/	.quad do_entSys, sys_acct, do_entSys, do_entSys, sys_ioctl
 	.quad do_entSys, do_entSys, sys_symlink, sys_readlink, sys_execve
 	.quad sys_umask, do_entSys, do_entSys, sys_getpgrp, sys_getpagesize
 	.quad do_entSys, osf_vfork, sys_newstat, sys_newlstat, do_entSys
@@ -579,6 +610,6 @@
 /* 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, do_entSys, do_entSys, do_entSys, do_entSys
+	.quad sys_syslog, sys_reboot, do_entSys, do_entSys, do_entSys
 	.quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
 
diff -u --recursive --new-file v1.3.21/linux/arch/alpha/kernel/irq.c linux/arch/alpha/kernel/irq.c
--- v1.3.21/linux/arch/alpha/kernel/irq.c	Fri Jun 16 22:02:54 1995
+++ linux/arch/alpha/kernel/irq.c	Tue Aug 29 10:15:48 1995
@@ -27,23 +27,53 @@
 static unsigned char cache_21 = 0xff;
 static unsigned char cache_A1 = 0xff;
 
+#if defined(CONFIG_ALPHA_CABRIOLET) || defined(CONFIG_ALPHA_EB66P)
+  static unsigned char cache_804 = 0xef;
+  static unsigned char cache_805 = 0xff;
+  static unsigned char cache_806 = 0xff;
+# define NUM_IRQS	33
+#elif defined(CONFIG_ALPHA_EB66) || defined(CONFIG_ALPHA_EB64P)
+  static unsigned char cache_26 = 0xdf;
+  static unsigned char cache_27 = 0xff;
+# define NUM_IRQS	32
+#else
+# define NUM_IRQS	16
+#endif
+
 void disable_irq(unsigned int irq_nr)
 {
 	unsigned long flags;
 	unsigned char mask;
 
-	mask = 1 << (irq_nr & 7);
 	save_flags(flags);
+	cli();
+	mask = 1 << (irq_nr & 7);
+
 	if (irq_nr < 8) {
-		cli();
 		cache_21 |= mask;
 		outb(cache_21,0x21);
-		restore_flags(flags);
-		return;
+	} else if (irq_nr < 16) {
+		cache_A1 |= mask;
+		outb(cache_A1,0xA1);
+#if defined(CONFIG_ALPHA_CABRIOLET) || defined(CONFIG_ALPHA_EB66P)
+	} else if (irq_nr < 24) {
+		cache_804 |= mask;
+		outb(cache_804, 0x804);
+	} else if (irq_nr < 32) {
+		cache_805 |= mask;
+		outb(cache_805, 0x805);
+	} else {
+		cache_806 |= mask;
+		outb(cache_806, 0x806);
+#elif defined(CONFIG_ALPHA_EB66) || defined(CONFIG_ALPHA_EB64P) 
+	} else if (irq_nr < 24) {
+		cache_26 |= mask;
+		outb(cache_26, 0x26);
+	} else {
+		cache_27 |= mask;
+		outb(cache_27, 0x27);
+#endif
 	}
-	cli();
-	cache_A1 |= mask;
-	outb(cache_A1,0xA1);
 	restore_flags(flags);
 }
 
@@ -54,16 +84,33 @@
 
 	mask = ~(1 << (irq_nr & 7));
 	save_flags(flags);
+	cli();
+
 	if (irq_nr < 8) {
-		cli();
 		cache_21 &= mask;
 		outb(cache_21,0x21);
-		restore_flags(flags);
-		return;
+	} else if (irq_nr < 16) {
+		cache_A1 &= mask;
+		outb(cache_A1,0xA1);
+#if defined(CONFIG_ALPHA_CABRIOLET) || defined(CONFIG_ALPHA_EB66P)
+	} else if (irq_nr < 24) {
+		cache_804 &= mask;
+		outb(cache_804, 0x804);
+	} else if (irq_nr < 32) {
+		cache_805 &= mask;
+		outb(cache_805, 0x805);
+	} else {
+		cache_806 &= mask;
+		outb(cache_806, 0x806);
+#elif defined(CONFIG_ALPHA_EB66) || defined(CONFIG_ALPHA_EB64P)
+	} else if if (irq_nr < 24) {
+		cache_26 &= mask;
+		outb(cache_26, 0x26);
+	} else {
+		cache_27 &= mask;
+		outb(cache_27, 0x27);
+#endif
 	}
-	cli();
-	cache_A1 &= mask;
-	outb(cache_A1,0xA1);
 	restore_flags(flags);
 }
 
@@ -77,23 +124,14 @@
 	const char *name;
 };
 
-static struct irqaction irq_action[16] = {
-	{ NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
-	{ NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
-	{ NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
-	{ NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
-	{ NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
-	{ NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
-	{ NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
-	{ NULL, 0, 0, NULL }, { NULL, 0, 0, NULL }
-};
+static struct irqaction irq_action[NUM_IRQS];
 
 int get_irq_list(char *buf)
 {
 	int i, len = 0;
 	struct irqaction * action = irq_action;
 
-	for (i = 0 ; i < 16 ; i++, action++) {
+	for (i = 0 ; i < NUM_IRQS ; i++, action++) {
 		if (!action->handler)
 			continue;
 		len += sprintf(buf+len, "%2d: %8d %c %s\n",
@@ -106,35 +144,78 @@
 
 static inline void ack_irq(int irq)
 {
-	/* ACK the interrupt making it the lowest priority */
-	/*  First the slave .. */
-	if (irq > 7) {
-		outb(0xE0 | (irq - 8), 0xa0);
-		irq = 2;
+	if (irq < 16) {
+		/* ACK the interrupt making it the lowest priority */
+		/*  First the slave .. */
+		if (irq > 7) {
+			outb(0xE0 | (irq - 8), 0xa0);
+			irq = 2;
+		}
+		/* .. then the master */
+		outb(0xE0 | irq, 0x20);
 	}
-	/* .. then the master */
-	outb(0xE0 | irq, 0x20);
 }
 
 static inline void mask_irq(int irq)
 {
+	unsigned char mask;
+
+	mask = 1 << (irq & 7);
 	if (irq < 8) {
-		cache_21 |= 1 << irq;
+		cache_21 |= mask;
 		outb(cache_21, 0x21);
-	} else {
-		cache_A1 |= 1 << (irq - 8);
+	} else if (irq < 16) {
+		cache_A1 |= mask;
 		outb(cache_A1, 0xA1);
+#if defined(CONFIG_ALPHA_CABRIOLET) || defined(CONFIG_ALPHA_EB66P)
+	} else if (irq < 24) {
+		cache_804 |= mask;
+		outb(cache_804, 0x804);
+	} else if (irq < 32) {
+	        cache_805 |= mask;
+		outb(cache_805, 0x805);
+	} else {
+		cache_806 |= mask;
+		outb(cache_806, 0x806);
+#elif defined(CONFIG_ALPHA_EB66) || defined(CONFIG_ALPHA_EB66P)
+	} else if (irq < 24) {
+		cache_26 |= mask;
+		outb(cache_26, 0x26);
+	} else {
+		cache_27 |= mask;
+		outb(cache_27, 0x27);
+#endif
 	}
 }
 
 static inline void unmask_irq(unsigned long irq)
 {
+	unsigned char mask = ~(1 << (irq & 7));
+
 	if (irq < 8) {
-		cache_21 &= ~(1 << irq);
+		cache_21 &= mask;
 		outb(cache_21, 0x21);
-	} else {
-		cache_A1 &= ~(1 << (irq - 8));
+	} else if (irq < 16) {
+		cache_A1 &= mask;
 		outb(cache_A1, 0xA1);
+#if defined(CONFIG_ALPHA_CABRIOLET) || defined(CONFIG_ALPHA_EB66P)
+	} else if (irq < 24) {
+		cache_804 &= mask;
+		outb(cache_804, 0x804);
+	} else if (irq < 32) {
+	        cache_805 &= mask;
+		outb(cache_805, 0x805);
+	} else {
+		cache_806 &= mask;
+		outb(cache_806, 0x806);
+#elif defined(CONFIG_ALPHA_EB66) || defined(CONFIG_ALPHA_EB66P)
+	} else if (irq < 24) {
+		cache_26 &= mask;
+		outb(cache_26, 0x26);
+	} else {
+		cache_27 &= mask;
+		outb(cache_27, 0x27);
+#endif
 	}
 }
 
@@ -144,7 +225,7 @@
 	struct irqaction * action;
 	unsigned long flags;
 
-	if (irq > 15)
+	if (irq >= NUM_IRQS)
 		return -EINVAL;
 	action = irq + irq_action;
 	if (action->handler)
@@ -157,16 +238,9 @@
 	action->flags = irqflags;
 	action->mask = 0;
 	action->name = devname;
-	if (irq < 8) {
-		if (irq) {
-			cache_21 &= ~(1<<irq);
-			outb(cache_21,0x21);
-		}
-	} else {
-		cache_21 &= ~(1<<2);
-		cache_A1 &= ~(1<<(irq-8));
-		outb(cache_21,0x21);
-		outb(cache_A1,0xA1);
+	enable_irq(irq);
+	if (irq >= 8 && irq < 16) {
+		enable_irq(2);	/* ensure cascade is enabled too */
 	}
 	restore_flags(flags);
 	return 0;
@@ -177,7 +251,7 @@
 	struct irqaction * action = irq + irq_action;
 	unsigned long flags;
 
-	if (irq > 15) {
+	if (irq >= NUM_IRQS) {
 		printk("Trying to free IRQ%d\n", irq);
 		return;
 	}
@@ -195,7 +269,7 @@
 	restore_flags(flags);
 }
 
-static void handle_nmi(struct pt_regs * regs)
+static inline void handle_nmi(struct pt_regs * regs)
 {
 	printk("Whee.. NMI received. Probable hardware error\n");
 	printk("61=%02x, 461=%02x\n", inb(0x61), inb(0x461));
@@ -232,40 +306,126 @@
 	action->handler(irq, regs);
 }
 
-#ifndef CONFIG_PCI
+static inline void device_interrupt(int irq, int ack, struct pt_regs * regs)
+{
+	struct irqaction * action;
+
+	if ((unsigned) irq > NUM_IRQS) {
+		printk("device_interrupt: unexpected interrupt %d\n", irq);
+		return;
+	}
+
+	kstat.interrupts[irq]++;
+	action = irq_action + irq;
+	/* quick interrupts get executed with no extra overhead */
+	if (action->flags & SA_INTERRUPT) {
+		action->handler(irq, regs);
+		ack_irq(ack);
+		return;
+	}
+	/*
+	 * For normal interrupts, we mask it out, and then ACK it.
+	 * This way another (more timing-critical) interrupt can
+	 * come through while we're doing this one.
+	 *
+	 * Note! A irq without a handler gets masked and acked, but
+	 * never unmasked. The autoirq stuff depends on this (it looks
+	 * at the masks before and after doing the probing).
+	 */
+	mask_irq(ack);
+	ack_irq(ack);
+	if (!action->handler)
+		return;
+	action->handler(irq, regs);
+	unmask_irq(ack);
+}
+
+/*
+ * Handle ISA interrupt via the PICs.
+ */
+static inline void isa_device_interrupt(unsigned long vector,
+					struct pt_regs * regs)
+{
+	unsigned long pic;
+	int j;
+	/* 
+	 *  The first read of gives you *all* interrupting lines.
+	 *  Therefore, read the mask register and and out those lines
+	 *  not enabled.  Note that some documentation has 21 and a1 
+	 *  write only.  This is not true.
+	 */
+	pic = inb(0x20) | (inb(0xA0) << 8);	/* read isr */
+	pic &= ~((cache_A1 << 8) | cache_21);	/* apply mask */
+	pic &= 0xFFFB;				/* mask out cascade */
+
+	while (pic) {
+		j = ffz(~pic);
+		pic &= pic - 1;
+		device_interrupt(j, j, regs);
+	}
+}
 
-static void local_device_interrupt(unsigned long vector, struct pt_regs * regs)
+static inline void cabriolet_and_eb66p_device_interrupt(unsigned long vector,
+							struct pt_regs * regs)
 {
-	switch (vector) {
-		/* com1: map to irq 4 */
-		case 0x900:
-			handle_irq(4, regs);
-			return;
+	unsigned long pld;
+	unsigned int i;
+	unsigned long flags;
 
-		/* com2: map to irq 3 */
-		case 0x920:
-			handle_irq(3, regs);
-			return;
+	save_flags(flags);
+	cli();
 
-		/* keyboard: map to irq 1 */
-		case 0x980:
-			handle_irq(1, regs);
-			return;
+	/* read the interrupt summary registers */
+	pld = inb(0x804) | (inb(0x805) << 8) | (inb(0x806) << 16);
 
-		/* mouse: map to irq 9 */
-		case 0x990:
-			handle_irq(9, regs);
-			return;
-		default:
-			printk("Unknown local interrupt %lx\n", vector);
+	/*
+	 * Now for every possible bit set, work through them and call
+	 * the appropriate interrupt handler.
+	 */
+	while (pld) {
+		i = ffz(~pld);
+		pld &= pld - 1;	/* clear least bit set */
+		if (i == 4) {
+			isa_device_interrupt(vector, regs);
+		} else {
+			device_interrupt(16 + i, 16 + i, regs);
+		}
 	}
+	restore_flags(flags);
 }
 
-#endif /* !CONFIG_PCI */
+static inline void eb66_and_eb64p_device_interrupt(unsigned long vector,
+						   struct pt_regs * regs)
+{
+	unsigned long pld;
+	unsigned int i;
+	unsigned long flags;
+
+	save_flags(flags);
+	cli();
+
+	/* read the interrupt summary registers */
+	pld = inb(0x26) | (inb(0x27) << 8);
+	/*
+	 * Now, for every possible bit set, work through
+	 * them and call the appropriate interrupt handler.
+	 */
+	while (pld) {
+		i = ffz(~pld);
+		pld &= pld - 1;	/* clear least bit set */
+
+		if (i == 5) {
+			isa_device_interrupt(vector, regs);
+		} else {
+			device_interrupt(16 + i, 16 + i, regs);
+		}
+	}
+	restore_flags(flags);
+}
 
 /*
- * The vector is 0x8X0 for EISA interrupt X, and 0x9X0 for the local
- * motherboard interrupts.. This is for the Jensen.
+ * Jensen is special: the vector is 0x8X0 for EISA interrupt X, and
+ * 0x9X0 for the local motherboard interrupts..
  *
  *	0x660 - NMI
  *
@@ -279,66 +439,55 @@
  *	0x980 - keyboard
  *	0x990 - mouse
  *
- * The PCI version is more sane: it doesn't have the local interrupts at
- * all, and has only normal PCI interrupts from devices. Happily it's easy
- * enough to do a sane mapping from the Jensen.. Note that this means
- * that we may have to do a hardware "ack" to a different interrupt than
- * we report to the rest of the world..
+ * PCI-based systems are more sane: they don't have the local
+ * interrupts at all, and have only normal PCI interrupts from
+ * devices.  Happily it's easy enough to do a sane mapping from the
+ * Jensen..  Note that this means that we may have to do a hardware
+ * "ack" to a different interrupt than we report to the rest of the
+ * world.
  */
-static void device_interrupt(unsigned long vector, struct pt_regs * regs)
+static inline void srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
 {
 	int irq, ack;
 	struct irqaction * action;
 
-	if (vector == 0x660) {
-		handle_nmi(regs);
-		return;
-	}
-
 	ack = irq = (vector - 0x800) >> 4;
-#ifndef CONFIG_PCI
-	if (vector >= 0x900) {
-		local_device_interrupt(vector, regs);
-		return;
+
+#ifdef CONFIG_ALPHA_JENSEN
+	switch (vector) {
+	      case 0x660: handle_nmi(regs); return;
+		/* local device interrupts: */
+	      case 0x900: handle_irq(4, regs); return;	/* com1 -> irq 4 */
+	      case 0x920: handle_irq(3, regs); return;	/* com2 -> irq 3 */
+	      case 0x980: handle_irq(1, regs); return;	/* kbd -> irq 1 */
+	      case 0x990: handle_irq(9, regs); return;	/* mouse -> irq 9 */
+	      default:
+		if (vector > 0x900) {
+			printk("Unknown local interrupt %lx\n", vector);
+		}
 	}
-	/* irq1 is supposed to be the keyboard, silly Jensen */
+	/* irq1 is supposed to be the keyboard, silly Jensen (is this really needed??) */
 	if (irq == 1)
 		irq = 7;
-#endif
-	kstat.interrupts[irq]++;
-	action = irq_action + irq;
-	/* quick interrupts get executed with no extra overhead */
-	if (action->flags & SA_INTERRUPT) {
-		action->handler(irq, regs);
-		ack_irq(ack);
-		return;
-	}
-	/*
-	 * For normal interrupts, we mask it out, and then ACK it.
-	 * This way another (more timing-critical) interrupt can
-	 * come through while we're doing this one.
-	 *
-	 * Note! A irq without a handler gets masked and acked, but
-	 * never unmasked. The autoirq stuff depends on this (it looks
-	 * at the masks before and after doing the probing).
-	 */
-	mask_irq(ack);
-	ack_irq(ack);
-	if (!action->handler)
-		return;
-	action->handler(irq, regs);
-	unmask_irq(ack);
+#endif /* CONFIG_ALPHA_JENSEN */
+
+	device_interrupt(irq, ack, regs);
 }
 
+#if NUM_IRQS > 64
+#  error Number of irqs limited to 64 due to interrupt-probing.
+#endif
+
 /*
  * Start listening for interrupts..
  */
-unsigned int probe_irq_on(void)
+unsigned long probe_irq_on(void)
 {
-	unsigned int i, irqs = 0, irqmask;
+	unsigned long irqs = 0, irqmask;
 	unsigned long delay;
+	unsigned int i;
 
-	for (i = 15; i > 0; i--) {
+	for (i = NUM_IRQS - 1; i > 0; i--) {
 		if (!irq_action[i].handler) {
 			enable_irq(i);
 			irqs |= (1 << i);
@@ -350,7 +499,15 @@
 		/* about 100 ms delay */;
 	
 	/* now filter out any obviously spurious interrupts */
-	irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int) cache_21;
+	irqmask = (((unsigned long)cache_A1)<<8) | (unsigned long) cache_21;
+#if defined(CONFIG_ALPHA_CABRIOLET) || defined(CONFIG_ALPHA_EB66P)
+	irqmask |= ((((unsigned long)cache_804)<<16) |
+		    (((unsigned long)cache_805)<<24) |
+		    (((unsigned long)cache_806)<<24));
+#elif defined(CONFIG_ALPHA_EB66) || defined(CONFIG_ALPHA_EB64P)
+	irqmask |= ((((unsigned long)cache_26)<<16) |
+		    (((unsigned long)cache_27)<<24);
+#endif
 	irqs &= ~irqmask;
 	return irqs;
 }
@@ -360,27 +517,41 @@
  * we have several candidates (but we return the lowest-numbered
  * one).
  */
-int probe_irq_off(unsigned int irqs)
+int probe_irq_off(unsigned long irqs)
 {
-	unsigned int i, irqmask;
+	unsigned long irqmask;
+	int i;
 	
 	irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int)cache_21;
+#if defined(CONFIG_ALPHA_CABRIOLET) || defined(CONFIG_ALPHA_EB66P)
+	irqmask |= ((((unsigned long)cache_804)<<16) |
+		    (((unsigned long)cache_805)<<24) |
+		    (((unsigned long)cache_806)<<24));
+#elif defined(CONFIG_ALPHA_EB66) || defined(CONFIG_ALPHA_EB64P)
+	irqmask |= ((((unsigned long)cache_26)<<16) |
+		    (((unsigned long)cache_27)<<24);
+#endif
 	irqs &= irqmask;
 	if (!irqs)
 		return 0;
 	i = ffz(~irqs);
-	if (irqs != (1 << i))
+	if (irqs != (1UL << i))
 		i = -i;
 	return i;
 }
 
-static void machine_check(unsigned long vector, unsigned long la_ptr, struct pt_regs * regs)
+static void machine_check(unsigned long vector, unsigned long la, struct pt_regs * regs)
 {
+#if defined(CONFIG_ALPHA_LCA)
+	extern void lca_machine_check (unsigned long vector, unsigned long la,
+				       struct pt_regs *regs);
+	lca_machine_check(vector, la, regs);
+#elif defined(CONFIG_ALPHA_APECS)
+	extern void apecs_machine_check(unsigned long vector, unsigned long la,
+					struct pt_regs * regs);
+	apecs_machine_check(vector, la, regs);
+#else
 	printk("Machine check\n");
-#ifdef LCA_MEM_ESR
-	printk("esr=%lx, ear=%lx, ioc_stat0=%lx, ioc_stat1=%lx\n",
-	       *(unsigned long*)LCA_MEM_ESR, *(unsigned long*)LCA_MEM_EAR,
-	       *(unsigned long*)LCA_IOC_STAT0, *(unsigned long*)LCA_IOC_STAT1);
 #endif
 }
 
@@ -400,7 +571,13 @@
 			machine_check(vector, la_ptr, &regs);
 			break;
 		case 3:
-			device_interrupt(vector, &regs);
+#if defined(CONFIG_ALPHA_JENSEN) || defined(CONFIG_ALPHA_NONAME)
+			srm_device_interrupt(vector, &regs);
+#elif defined(CONFIG_ALPHA_CABRIOLET) || defined(CONFIG_ALPHA_EB66P)
+			cabriolet_and_eb66p_device_interrupt(vector, &regs);
+#elif defined(CONFIG_ALPHA_EB66) || defined(CONFIG_ALPHA_EB64P)
+			eb66_and_eb64p_device_interrupt(vector, &regs);
+#endif
 			return;
 		case 4:
 			printk("Performance counter interrupt\n");
@@ -420,4 +597,12 @@
 	dma_outb(0, DMA2_RESET_REG);
 	dma_outb(0, DMA1_CLR_MASK_REG);
 	dma_outb(0, DMA2_CLR_MASK_REG);
+#if defined(CONFIG_ALPHA_CABRIOLET) || defined(CONFIG_ALPHA_EB66P)
+	outb(cache_804, 0x804);
+	outb(cache_805, 0x805);
+	outb(cache_806, 0x806);
+#elif defined(CONFIG_ALPHA_EB66) || defined(CONFIG_ALPHA_EB64P)
+	outb(cache_26, 0x26);
+	outb(cache_27, 0x27);
+#endif
 }
diff -u --recursive --new-file v1.3.21/linux/arch/alpha/kernel/lca.c linux/arch/alpha/kernel/lca.c
--- v1.3.21/linux/arch/alpha/kernel/lca.c	Thu Jun  1 13:22:05 1995
+++ linux/arch/alpha/kernel/lca.c	Tue Aug 29 10:15:48 1995
@@ -11,6 +11,7 @@
 #include <linux/bios32.h>
 #include <linux/pci.h>
 
+#include <asm/ptrace.h>
 #include <asm/system.h>
 #include <asm/io.h>
 
@@ -18,7 +19,7 @@
  * BIOS32-style PCI interface:
  */
 
-#ifdef CONFIG_PCI
+#ifdef CONFIG_ALPHA_LCA
 
 #define vulp	volatile unsigned long *
 
@@ -76,7 +77,7 @@
 
 		if (device > 12) {
 			return -1;
-		} /* if */
+		}
 
 		*((volatile unsigned long*) LCA_IOC_CONF) = 0;
 		addr = (1 << (11 + device)) | (func << 8) | where;
@@ -84,19 +85,19 @@
 		/* type 1 configuration cycle: */
 		*((volatile unsigned long*) LCA_IOC_CONF) = 1;
 		addr = (bus << 16) | (device_fn << 8) | where;
-	} /* if */
+	}
 	*pci_addr = addr;
-
 	return 0;
 }
 
 
 static unsigned int conf_read(unsigned long addr)
 {
-	unsigned long old_ipl, code, stat0;
+	unsigned long flags, code, stat0;
 	unsigned int value;
 
-	old_ipl = swpipl(7);	/* avoid getting hit by machine check */
+	save_flags(flags);
+	cli();
 
 	/* reset status register to avoid loosing errors: */
 	stat0 = *((volatile unsigned long*)LCA_IOC_STAT0);
@@ -123,17 +124,17 @@
 
 		value = 0xffffffff;
 	}
-	swpipl(old_ipl);
-
+	restore_flags(flags);
 	return value;
 }
 
 
 static void conf_write(unsigned long addr, unsigned int value)
 {
-	unsigned long old_ipl, code, stat0;
+	unsigned long flags, code, stat0;
 
-	old_ipl = swpipl(7);	/* avoid getting hit by machine check */
+	save_flags(flags);	/* avoid getting hit by machine check */
+	cli();
 
 	/* reset status register to avoid loosing errors: */
 	stat0 = *((volatile unsigned long*)LCA_IOC_STAT0);
@@ -158,7 +159,7 @@
 		mb();
 		wrmces(0x7);			/* reset machine check */
 	}
-	swpipl(old_ipl);
+	restore_flags(flags);
 }
 
 
@@ -172,12 +173,9 @@
 
 	if (mk_conf_addr(bus, device_fn, where, &pci_addr) < 0) {
 		return PCIBIOS_SUCCESSFUL;
-	} /* if */
-
+	}
 	addr |= (pci_addr << 5) + 0x00;
-
 	*value = conf_read(addr) >> ((where & 3) * 8);
-
 	return PCIBIOS_SUCCESSFUL;
 }
 
@@ -192,14 +190,11 @@
 
 	if (where & 0x1) {
 		return PCIBIOS_BAD_REGISTER_NUMBER;
-	} /* if */
-
+	}
 	if (mk_conf_addr(bus, device_fn, where, &pci_addr)) {
 		return PCIBIOS_SUCCESSFUL;
-	} /* if */
-
+	}
 	addr |= (pci_addr << 5) + 0x08;
-
 	*value = conf_read(addr) >> ((where & 3) * 8);
 	return PCIBIOS_SUCCESSFUL;
 }
@@ -212,19 +207,14 @@
 	unsigned long pci_addr;
 
 	*value = 0xffffffff;
-
 	if (where & 0x3) {
 		return PCIBIOS_BAD_REGISTER_NUMBER;
-	} /* if */
-
+	}
 	if (mk_conf_addr(bus, device_fn, where, &pci_addr)) {
 		return PCIBIOS_SUCCESSFUL;
-	} /* if */
-
+	}
 	addr |= (pci_addr << 5) + 0x18;
-
 	*value = conf_read(addr);
-
 	return PCIBIOS_SUCCESSFUL;
 }
 
@@ -237,12 +227,9 @@
 
 	if (mk_conf_addr(bus, device_fn, where, &pci_addr) < 0) {
 		return PCIBIOS_SUCCESSFUL;
-	} /* if */
-
+	}
 	addr |= (pci_addr << 5) + 0x00;
-
 	conf_write(addr, value << ((where & 3) * 8));
-
 	return PCIBIOS_SUCCESSFUL;
 }
 
@@ -255,12 +242,9 @@
 
 	if (mk_conf_addr(bus, device_fn, where, &pci_addr) < 0) {
 		return PCIBIOS_SUCCESSFUL;
-	} /* if */
-
+	}
 	addr |= (pci_addr << 5) + 0x08;
-
 	conf_write(addr, value << ((where & 3) * 8));
-
 	return PCIBIOS_SUCCESSFUL;
 }
 
@@ -273,12 +257,9 @@
 
 	if (mk_conf_addr(bus, device_fn, where, &pci_addr) < 0) {
 		return PCIBIOS_SUCCESSFUL;
-	} /* if */
-
+	}
 	addr |= (pci_addr << 5) + 0x18;
-
 	conf_write(addr, value << ((where & 3) * 8));
-
 	return PCIBIOS_SUCCESSFUL;
 }
 
@@ -295,10 +276,20 @@
 	*(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;
-
 	return mem_start;
 }
 
-#endif /* CONFIG_PCI */
 
-			/*** end of lca.c ***/
+void lca_machine_check (unsigned long vector, unsigned long la, struct pt_regs *regs)
+{
+	unsigned long mces;
+
+	mces = rdmces();
+	wrmces(mces);		/* reset machine check asap */
+	printk("Machine check (la=0x%lx,mces=0x%lx)\n", la, mces);
+	printk("esr=%lx, ear=%lx, ioc_stat0=%lx, ioc_stat1=%lx\n",
+	       *(unsigned long*)LCA_MEM_ESR, *(unsigned long*)LCA_MEM_EAR,
+	       *(unsigned long*)LCA_IOC_STAT0, *(unsigned long*)LCA_IOC_STAT1);
+}
+
+#endif /* CONFIG_ALPHA_LCA */
diff -u --recursive --new-file v1.3.21/linux/arch/alpha/kernel/process.c linux/arch/alpha/kernel/process.c
--- v1.3.21/linux/arch/alpha/kernel/process.c	Thu Jul 13 16:20:19 1995
+++ linux/arch/alpha/kernel/process.c	Thu Aug 31 11:44:45 1995
@@ -91,9 +91,7 @@
  */
 int alpha_fork(struct switch_stack * swstack)
 {
-	return do_fork(COPYVM | SIGCHLD,
-		rdusp(),
-		(struct pt_regs *) (swstack+1));
+	return do_fork(SIGCHLD, rdusp(), (struct pt_regs *) (swstack+1));
 }
 
 extern void ret_from_sys_call(void);
@@ -169,17 +167,11 @@
  * This doesn't actually work correctly like this: we need to do the
  * same stack setups that fork() does first.
  */
-asmlinkage int sys_clone(unsigned long a0, unsigned long a1, unsigned long a2,
+asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, unsigned long a2,
 	unsigned long a3, unsigned long a4, unsigned long a5,
 	struct pt_regs regs)
 {
-	unsigned long clone_flags = a0;
-	unsigned long newsp;
-
-	newsp = rdusp();
-	if (newsp == a1 || !a1)
-		clone_flags |= COPYVM;
-	else
-		newsp = a1;	
+	if (!newsp)
+		newsp = rdusp();
 	return do_fork(clone_flags, newsp, &regs);
 }
diff -u --recursive --new-file v1.3.21/linux/arch/alpha/kernel/ptrace.c linux/arch/alpha/kernel/ptrace.c
--- v1.3.21/linux/arch/alpha/kernel/ptrace.c	Sun Aug 13 14:45:27 1995
+++ linux/arch/alpha/kernel/ptrace.c	Tue Aug 29 10:15:48 1995
@@ -2,6 +2,7 @@
 /* By Ross Biro 1/23/92 */
 /* edited by Linus Torvalds */
 /* mangled further by Bob Manson (manson@santafe.edu) */
+/* more mutilation by David Mosberger (davidm@azstarnet.com) */
 
 #include <linux/head.h>
 #include <linux/kernel.h>
@@ -21,8 +22,9 @@
 #ifdef DEBUG
 
   enum {
-      DBG_MEM = (1<<0),
-      DBG_BPT = (1<<1)
+      DBG_MEM		= (1<<0),
+      DBG_BPT		= (1<<1),
+      DBG_MEM_ALL	= (1<<2)
   };
 
   int debug_mask = DBG_BPT;
@@ -35,49 +37,74 @@
 
 #define BREAKINST	0x00000080	/* call_pal bpt */
 
-/* This was determined via brute force. */
-#define MAGICNUM 496
-
 /*
  * does not yet catch signals sent when the child dies.
  * in exit.c or in signal.c.
  */
 
-/* A mapping between register number and its offset on the kernel stack.
- * You also need to add MAGICNUM to get past the kernel stack frame
- * to the actual saved user info.
- * The first portion is the switch_stack, then comes the pt_regs.
- * 320 is the size of the switch_stack area.
+/*
+ * Processes always block with the following stack-layout:
+ *
+ *  +================================+ --------------------------
+ *  | PALcode saved frame (ps, pc,   | ^		      ^
+ *  | gp, a0, a1, a2)		     | |		      |
+ *  +================================+ | struct pt_regs	      |
+ *  |	        		     | |		      |
+ *  | frame generated by SAVE_ALL    | |		      |
+ *  |	        		     | v		      | P
+ *  +================================+			      |	A
+ *  |	        		     | ^		      |	G
+ *  | frame saved by do_switch_stack | | struct switch_stack  |	E
+ *  |	        		     | v		      |	_
+ *  +================================+			      |	S
+ *  |	        		     |			      |	I
+ *  |	        		     |			      |	Z
+ *  /	        		     /			      |	E
+ *  /	                             /			      |
+ *  |				     |			      |
+ *  |				     |			      |
+ *  |				     |			      v
+ *  +================================+ <-------------------------
+ *					task->kernel_stack_page
+ */
+#define PT_REG(reg)	(PAGE_SIZE - sizeof(struct pt_regs)	\
+			 + (long)&((struct pt_regs *)0)->reg)
+#define SW_REG(reg)	(PAGE_SIZE - sizeof(struct pt_regs)	\
+			 - sizeof(struct switch_stack)		\
+			 + (long)&((struct switch_stack *)0)->reg)
+/* 
+ * The following table maps a register index into the stack offset at
+ * which the register is saved.  Register indices are 0-31 for integer
+ * regs, 32-63 for fp regs, and 64 for the pc.  Notice that sp and
+ * zero have no stack-slot and need to be treated specially (see
+ * get_reg/put_reg below).
  */
-
 enum {
-	REG_R0 =  0,
-	REG_F0 = 32,
-	REG_PC = 64
+	REG_R0 = 0, REG_F0 = 32, REG_PC = 64
 };
 
-static int map_reg_to_offset[] = {
-   320+0,320+8,320+16,320+24,320+32,320+40,320+48,320+56,320+64, /* 0-8 */
-   0,8,16,24,32,40,48, /* 9-15 */
-   320+184,320+192,320+200, /* 16-18 */
-   320+72,320+80,320+88,320+96,320+104,320+112,320+120, /* 19-25 */
-   320+128,320+136,320+144,320+176,320+160,-1, /* 26-31*/
-
-   /* fp registers below */
-   64,72,80,88,96,104,112,120,128,136,144,152,160,168,176,184,192,
-   200,208,216,224,232,240,248,256,264,272,280,288,296,304,312,
-
-   /* 64 = pc */
-   320+168
+static unsigned short regoff[] = {
+	PT_REG(	   r0), PT_REG(	   r1), PT_REG(	   r2), PT_REG(	  r3),
+	PT_REG(	   r4), PT_REG(	   r5), PT_REG(	   r6), PT_REG(	  r7),
+	PT_REG(	   r8), SW_REG(	   r9), SW_REG(	  r10), SW_REG(	 r11),
+	SW_REG(	  r12), SW_REG(	  r13), SW_REG(	  r14), SW_REG(	 r15),
+	PT_REG(	  r16), PT_REG(	  r17), PT_REG(	  r18), PT_REG(	 r19),
+	PT_REG(	  r20), PT_REG(	  r21), PT_REG(	  r22), PT_REG(	 r23),
+	PT_REG(	  r24), PT_REG(	  r25), PT_REG(	  r26), PT_REG(	 r27),
+	PT_REG(	  r28), PT_REG(	   gp),		   -1,		   -1,
+	SW_REG(fp[ 0]), SW_REG(fp[ 1]), SW_REG(fp[ 2]), SW_REG(fp[ 3]),
+	SW_REG(fp[ 4]), SW_REG(fp[ 5]), SW_REG(fp[ 6]), SW_REG(fp[ 7]),
+	SW_REG(fp[ 8]), SW_REG(fp[ 9]), SW_REG(fp[10]), SW_REG(fp[11]),
+	SW_REG(fp[12]), SW_REG(fp[13]), SW_REG(fp[14]), SW_REG(fp[15]),
+	SW_REG(fp[16]), SW_REG(fp[17]), SW_REG(fp[18]), SW_REG(fp[19]),
+	SW_REG(fp[20]), SW_REG(fp[21]), SW_REG(fp[22]), SW_REG(fp[23]),
+	SW_REG(fp[24]), SW_REG(fp[25]), SW_REG(fp[26]), SW_REG(fp[27]),
+	SW_REG(fp[28]), SW_REG(fp[29]), SW_REG(fp[30]), SW_REG(fp[31]),
+	PT_REG(	   pc)
 };
 
-static int offset_of_register(int reg_num)
-{
-	if (reg_num < 0 || reg_num > 64) {
-		return -1;
-	}
-	return map_reg_to_offset[reg_num];
-}
+static long zero;
+
 
 /* change a pid into a task struct. */
 static inline struct task_struct * get_task(int pid)
@@ -92,36 +119,38 @@
 }
 
 /*
- * this routine will get a word off of the processes privileged stack. 
- * the offset is how far from the base addr as stored in the TSS.  
- * this routine assumes that all the privileged stacks are in our
- * data space.
- * MAGICNUM is the amount to skip to get to the actual user regs. It
- * was determined by brute force & asking BufElves.
- */   
-static inline long get_stack_long(struct task_struct *task, unsigned long offset)
+ * Get contents of register REGNO in task TASK.
+ */
+static inline long get_reg(struct task_struct * task, long regno)
 {
-	unsigned char *stack;
+	long *addr;
 
-	stack = (unsigned char *)task->tss.ksp;
-	stack += offset+MAGICNUM;
-	return (*((long *)stack));
+	if (regno == 30) {
+		addr = &task->tss.usp;
+	} else if (regno == 31) {
+		zero = 0;
+		addr = &zero;
+	} else {
+		addr = (long *) (task->kernel_stack_page + regoff[regno]);
+	}
+	return *addr;
 }
 
 /*
- * this routine will put a word on the processes privileged stack. 
- * the offset is how far from the base addr as stored in the TSS.  
- * this routine assumes that all the privileged stacks are in our
- * data space.
+ * Write contents of register REGNO in task TASK.
  */
-static inline int put_stack_long(struct task_struct *task, unsigned long offset,
-	unsigned long data)
+static inline int put_reg(struct task_struct *task, long regno, long data)
 {
-	unsigned char * stack;
+	long *addr, zero;
 
-	stack = (unsigned char *) task->tss.ksp;
-	stack += offset+MAGICNUM;
-	*(unsigned long *) stack = data;
+	if (regno == 30) {
+		addr = &task->tss.usp;
+	} else if (regno == 31) {
+		addr = &zero;
+	} else {
+		addr = (long *) (task->kernel_stack_page + regoff[regno]);
+	}
+	*addr = data;
 	return 0;
 }
 
@@ -138,7 +167,7 @@
 	pte_t * pgtable;
 	unsigned long page;
 
-	DBG(DBG_MEM, ("Getting long at 0x%lx\n", addr));
+	DBG(DBG_MEM_ALL, ("getting long at 0x%lx\n", addr));
 repeat:
 	pgdir = pgd_offset(vma->vm_task, addr);
 	if (pgd_none(*pgdir)) {
@@ -226,11 +255,12 @@
 		*(unsigned long *) (page + (addr & ~PAGE_MASK)) = data;
 /* we're bypassing pagetables, so we have to set the dirty bit ourselves */
 /* this should also re-instate whatever read-only mode there was before */
-	*pgtable = pte_mkdirty(mk_pte(page, vma->vm_page_prot));
+	set_pte(pgtable, pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
 	invalidate();
 }
 
-static struct vm_area_struct * find_extend_vma(struct task_struct * tsk, unsigned long addr)
+static struct vm_area_struct * find_extend_vma(struct task_struct * tsk,
+					       unsigned long addr)
 {
 	struct vm_area_struct * vma;
 
@@ -258,57 +288,35 @@
 {
 	struct vm_area_struct * vma = find_extend_vma(tsk, addr);
 
-	DBG(DBG_MEM, ("in read_long\n"));
+	DBG(DBG_MEM_ALL, ("in read_long\n"));
 	if (!vma) {
 	        printk("Unable to find vma for addr 0x%lx\n",addr);
 		return -EIO;
 	}
-	if ((addr & ~PAGE_MASK) > (PAGE_SIZE-sizeof(long))) {
-		unsigned long low,high;
+	if ((addr & ~PAGE_MASK) > (PAGE_SIZE - sizeof(long))) {
 		struct vm_area_struct * vma_high = vma;
+		unsigned long low, align;
 
 		if (addr + sizeof(long) >= vma->vm_end) {
 			vma_high = vma->vm_next;
 			if (!vma_high || vma_high->vm_start != vma->vm_end)
 				return -EIO;
 		}
-		low = get_long(vma, addr & ~(sizeof(long)-1));
-		high = get_long(vma_high, (addr+sizeof(long)) & ~(sizeof(long)-1));
-		switch (addr & (sizeof(long)-1)) {
-			case 1:
-				low >>= 8;
-				low |= high << 56;
-				break;
-			case 2:
-				low >>= 16;
-				low |= high << 48;
-				break;
-			case 3:
-				low >>= 24;
-				low |= high << 40;
-				break;
-			case 4:
-				low >>= 32;
-				low |= high << 32;
-				break;
-			case 5:
-				low >>= 40;
-				low |= high << 24;
-				break;
-			case 6:
-				low >>= 48;
-				low |= high << 16;
-				break;
-			case 7:
-				low >>= 56;
-				low |= high << 8;
-				break;
+		align = addr & (sizeof(long) - 1);
+		addr -= align;
+		low = get_long(vma, addr);
+		if (align) {
+		    unsigned long high;
+
+		    high = get_long(vma_high, addr + sizeof(long));
+		    low >>= align * 8;
+		    low  |= high << (64 - align * 8);
 		}
 		*result = low;
 	} else {
-	        long l =get_long(vma, addr);
+	        long l = get_long(vma, addr);
 
-		DBG(DBG_MEM, ("value is 0x%lx\n",l));
+		DBG(DBG_MEM_ALL, ("value is 0x%lx\n", l));
 		*result = l;
 	}
 	return 0;
@@ -326,7 +334,7 @@
 	if (!vma)
 		return -EIO;
 	if ((addr & ~PAGE_MASK) > PAGE_SIZE-sizeof(long)) {
-		unsigned long low,high;
+		unsigned long low, high, align;
 		struct vm_area_struct * vma_high = vma;
 
 		if (addr + sizeof(long) >= vma->vm_end) {
@@ -334,58 +342,16 @@
 			if (!vma_high || vma_high->vm_start != vma->vm_end)
 				return -EIO;
 		}
-		low = get_long(vma, addr & ~(sizeof(long)-1));
-		high = get_long(vma_high, (addr+sizeof(long)) & ~(sizeof(long)-1));
-		switch (addr & (sizeof(long)-1)) {
-			case 0: /* shouldn't happen, but safety first */
-				low = data;
-				break;
-			case 1:
-				low &= 0x00000000000000ffL;
-				low |= data << 8;
-				high &= ~0x000000000000ffL;
-				high |= data >> 56;
-				break;
-			case 2:
-				low &= 0x000000000000ffffL;
-				low |= data << 16;
-				high &= ~0x0000000000ffffL;
-				high |= data >> 48;
-				break;
-			case 3:
-				low &= 0x0000000000ffffffL;
-				low |= data << 24;
-				high &= ~0x00000000ffffffL;
-				high |= data >> 40;
-				break;
-		        case 4:
-				low &= 0x00000000ffffffffL;
-				low |= data << 32;
-				high &= ~0x000000ffffffffL;
-				high |= data >> 32;
-				break;
-
-			case 5:
-				low &= 0x000000ffffffffffL;
-				low |= data << 40;
-				high &= ~0x0000ffffffffffL;
-				high |= data >> 24;
-				break;
-			case 6:
-				low &= 0x0000ffffffffffffL;
-				low |= data << 48;
-				high &= ~0x00ffffffffffffL;
-				high |= data >> 16;
-				break;
-			case 7:
-				low &= 0x00ffffffffffffffL;
-				low |= data << 56;
-				high &= ~0xffffffffffffffL;
-				high |= data >> 8;
-				break;
-		}
-		put_long(vma, addr & ~(sizeof(long)-1),low);
-		put_long(vma_high, (addr+sizeof(long)) & ~(sizeof(long)-1),high);
+		align = addr & (sizeof(long) - 1);
+		addr -= align;
+		low  = get_long(vma, addr);
+		high = get_long(vma_high, addr + sizeof(long));
+		low  &= ~0UL >> (64 - align * 8);
+		high &= ~0UL << (align * 8);
+		low  |= data << (align * 8);
+		high |= data >> (64 - align * 8);
+		put_long(vma, addr, low);
+		put_long(vma_high, addr + sizeof(long), high);
 	} else
 		put_long(vma, addr, data);
 	return 0;
@@ -394,7 +360,8 @@
 /*
  * Read a 32bit int from address space TSK.
  */
-static int read_int(struct task_struct * tsk, unsigned long addr, unsigned int *data)
+static int read_int(struct task_struct * tsk, unsigned long addr,
+		    unsigned int *data)
 {
 	unsigned long l, align;
 	int res;
@@ -420,7 +387,8 @@
  * For simplicity, do a read-modify-write of the 64bit word that
  * contains the 32bit word that we are about to write.
  */
-static int write_int(struct task_struct * tsk, unsigned long addr, unsigned int data)
+static int write_int(struct task_struct * tsk, unsigned long addr,
+		     unsigned int data)
 {
 	unsigned long l, align;
 	int res;
@@ -441,36 +409,15 @@
 }
 
 /*
- * Uh, this does ugly stuff. It stores the specified value in the a3
- * register. entry.S will swap a3 and the returned value from
- * sys_ptrace() before returning to the user.
- */
-
-static inline void set_success(struct pt_regs *regs,long resval)
-{
-	regs->r19 = resval;
-}
-
-/*
- * This doesn't do diddly, actually--if the value returned from 
- * sys_ptrace() is != 0, it sets things up properly.
- */
-
-static inline void set_failure(struct pt_regs *regs, long errcode)
-{
-	regs->r19 = 0;
-}
-
-/*
  * Set breakpoint.
  */
-static int set_bpt(struct task_struct *child)
+int ptrace_set_bpt(struct task_struct * child)
 {
-	int displ, i, res, reg_b, off, nsaved = 0;
+	int displ, i, res, reg_b, nsaved = 0;
 	u32 insn, op_code;
 	unsigned long pc;
 
-	pc  = get_stack_long(child, map_reg_to_offset[REG_PC]);
+	pc  = get_reg(child, REG_PC);
 	res = read_int(child, pc, &insn);
 	if (res < 0)
 	  return res;
@@ -487,22 +434,12 @@
 		 */
 		displ = ((s32)(insn << 11)) >> 9;
 		child->debugreg[nsaved++] = pc + 4;
-		if (displ)			/* guard against unoptimized code */
+		if (displ)		/* guard against unoptimized code */
 		  child->debugreg[nsaved++] = pc + 4 + displ;
 		DBG(DBG_BPT, ("execing branch\n"));
 	} else if (op_code == 0x1a) {
 		reg_b = (insn >> 16) & 0x1f;
-		off = offset_of_register(reg_b);
-		if (off >= 0) {
-			child->debugreg[nsaved++] = get_stack_long(child, off);
-		} else {
-			/* $31 (aka zero) doesn't have a stack-slot */
-			if (reg_b == 31) {
-				child->debugreg[nsaved++] = 0;
-			} else {
-				return -EIO;
-			}
-		}
+		child->debugreg[nsaved++] = get_reg(child, reg_b);
 		DBG(DBG_BPT, ("execing jump\n"));
 	} else {
 		child->debugreg[nsaved++] = pc + 4;
@@ -524,7 +461,11 @@
 	return 0;
 }
 
-int ptrace_cancel_bpt(struct task_struct *child)
+/*
+ * Ensure no single-step breakpoint is pending.  Returns non-zero
+ * value if child was being single-stepped.
+ */
+int ptrace_cancel_bpt(struct task_struct * child)
 {
 	int i, nsaved = child->debugreg[4];
 
@@ -538,56 +479,43 @@
 	for (i = 0; i < nsaved; ++i) {
 		write_int(child, child->debugreg[i], child->debugreg[i + 2]);
 	}
-	return nsaved;
+	return (nsaved != 0);
 }
 
-asmlinkage long sys_ptrace(long request, long pid, long addr, long data, int a4, int a5,
-			   struct pt_regs regs)
+asmlinkage long sys_ptrace(long request, long pid, long addr, long data,
+			   int a4, int a5, struct pt_regs regs)
 {
 	struct task_struct *child;
 	struct user * dummy;
-	int res;
 
 	dummy = NULL;
 
-	DBG(DBG_MEM, ("request=%ld pid=%ld addr=0x%lx data=0x%lx\n",request,pid,addr,data));
-	set_success(&regs,0);
+	DBG(DBG_MEM, ("request=%ld pid=%ld addr=0x%lx data=0x%lx\n",
+		      request, pid, addr, data));
 	if (request == PTRACE_TRACEME) {
 		/* are we already being traced? */
-		if (current->flags & PF_PTRACED) {
-			set_failure(&regs,-EPERM);
+		if (current->flags & PF_PTRACED)
 			return -EPERM;
-		}
 		/* set the ptrace bit in the process flags. */
 		current->flags |= PF_PTRACED;
 		return 0;
 	}
-	if (pid == 1) {		/* you may not mess with init */
-		set_failure(&regs,-EPERM);
+	if (pid == 1)		/* you may not mess with init */
 		return -EPERM;
-	}
-	if (!(child = get_task(pid))) {
-		set_failure(&regs,-ESRCH);
+	if (!(child = get_task(pid)))
 		return -ESRCH;
-	}
 	if (request == PTRACE_ATTACH) {
-		if (child == current) {
-			set_failure(&regs,-EPERM);
+		if (child == current)
 			return -EPERM;
-		}
 		if ((!child->dumpable ||
 		     (current->uid != child->euid) ||
 		     (current->uid != child->uid) ||
 		     (current->gid != child->egid) ||
-		     (current->gid != child->gid)) && !suser()) {
-			set_failure(&regs,-EPERM);
+		     (current->gid != child->gid)) && !suser())
 			return -EPERM;
-		}
 		/* the same process cannot be attached many times */
-		if (child->flags & PF_PTRACED) {
-			set_failure(&regs,-EPERM);
+		if (child->flags & PF_PTRACED)
 			return -EPERM;
-		}
 		child->flags |= PF_PTRACED;
 		if (child->p_pptr != current) {
 			REMOVE_LINKS(child);
@@ -599,97 +527,54 @@
 	}
 	if (!(child->flags & PF_PTRACED)) {
 		DBG(DBG_MEM, ("child not traced\n"));
-		set_failure(&regs,-ESRCH);
 		return -ESRCH;
 	}
 	if (child->state != TASK_STOPPED) {
 		DBG(DBG_MEM, ("child process not stopped\n"));
-		if (request != PTRACE_KILL) {
-			set_failure(&regs,-ESRCH);
+		if (request != PTRACE_KILL)
 			return -ESRCH;
-		}
 	}
 	if (child->p_pptr != current) {
 		DBG(DBG_MEM, ("child not parent of this process\n"));
-		set_failure(&regs,-ESRCH);
 		return -ESRCH;
 	}
 
 	switch (request) {
 	/* when I and D space are separate, these will need to be fixed. */
-		case PTRACE_PEEKTEXT: /* read word at location addr. */ 
+		case PTRACE_PEEKTEXT: /* read word at location addr. */
 		case PTRACE_PEEKDATA: {
 			unsigned long tmp;
 			int res;
 
-			DBG(DBG_MEM, ("doing request at addr 0x%lx\n",addr));
 			res = read_long(child, addr, &tmp);
-			if (res < 0) {
-				set_failure(&regs,res);
+			DBG(DBG_MEM, ("peek %#lx->%#lx\n", addr, tmp));
+			if (res < 0)
 				return res;
-			} else {
-				set_success(&regs,tmp);
-				return 0;
-			}
+			regs.r0 = tmp;	/* special return */
+			return -255;
 		}
 
-	/* read the word at location addr in the USER area. */
-		case PTRACE_PEEKUSR: {
-		        /* We only allow access to registers. */
-			unsigned long tmp;
+	/* read register number ADDR. */
+		case PTRACE_PEEKUSR:
+			regs.r0 = get_reg(child, addr);
+			DBG(DBG_MEM, ("peek $%ld=%#lx\n", addr, regs.r0));
+			return -255;		/* special return */
 
-			tmp = 0;  /* Default return condition */
-			if (addr == 30) {
-				/* stack pointer */
-				tmp=child->tss.usp;
-			} else {
-#ifdef DEBUG
-				int reg = addr;
-#endif
-				addr = offset_of_register(addr);
-				if (addr < 0) {
-					set_failure(&regs, -EIO);
-					return -EIO;
-				}
-				tmp = get_stack_long(child, addr);
-				DBG(DBG_MEM, ("%d = reg 0x%lx=tmp\n",reg,tmp));
-			}
-			set_success(&regs,tmp);
-			return 0;
-		}
-
-      /* when I and D space are separate, this will have to be fixed. */
+	/* when I and D space are separate, this will have to be fixed. */
 		case PTRACE_POKETEXT: /* write the word at location addr. */
-		case PTRACE_POKEDATA: {
-			long res = write_long(child,addr,data);
-			if (res) {
-				set_failure(&regs,res);
-			}
-			return res;
-		}
+		case PTRACE_POKEDATA:
+			DBG(DBG_MEM, ("poke %#lx<-%#lx\n", addr, data));
+			return write_long(child, addr, data);
 
 		case PTRACE_POKEUSR: /* write the specified register */
-		  {
-			  long res;
-			  addr = offset_of_register(addr);
-			  if(addr < 0) {
-				  set_failure(&regs,-EIO);
-				  return -EIO;
-			  }
-			  res = put_stack_long(child, addr, data);
-			  if (res) {
-				  set_failure(&regs,res);
-			  }
-			  return res;
-		  }
+			DBG(DBG_MEM, ("poke $%ld<-%#lx\n", addr, data));
+			return put_reg(child, addr, data);
 
-		case PTRACE_SYSCALL: /* continue and stop at next 
+		case PTRACE_SYSCALL: /* continue and stop at next
 					(return from) syscall */
 		case PTRACE_CONT: { /* restart after signal. */
-			if ((unsigned long) data > NSIG) {
-				set_failure(&regs,-EIO);
+			if ((unsigned long) data > NSIG)
 				return -EIO;
-			}
 			if (request == PTRACE_SYSCALL)
 				child->flags |= PF_TRACESYS;
 			else
@@ -698,32 +583,28 @@
 			wake_up_process(child);
         /* make sure single-step breakpoint is gone. */
 			ptrace_cancel_bpt(child);
-			set_success(&regs,data);
-			return 0;
+			return data;
 		}
 
 /*
- * make the child exit.  Best I can do is send it a sigkill. 
- * perhaps it should be put in the status that it wants to 
+ * make the child exit.  Best I can do is send it a sigkill.
+ * perhaps it should be put in the status that it wants to
  * exit.
  */
 		case PTRACE_KILL: {
-			wake_up_process(child);
-			child->exit_code = SIGKILL;
+			if (child->state != TASK_ZOMBIE) {
+				wake_up_process(child);
+				child->exit_code = SIGKILL;
+			}
         /* make sure single-step breakpoint is gone. */
 			ptrace_cancel_bpt(child);
 			return 0;
 		}
 
-		case PTRACE_SINGLESTEP: {  /* execute signle instruction. */
-			if ((unsigned long) data > NSIG) {
-				set_failure(&regs,-EIO);
+		case PTRACE_SINGLESTEP: {  /* execute single instruction. */
+			if ((unsigned long) data > NSIG)
 				return -EIO;
-			}
-			res = set_bpt(child);
-			if (res < 0) {
-				return res;
-			}
+			child->debugreg[4] = -1;	/* mark single-stepping */
 			child->flags &= ~PF_TRACESYS;
 			wake_up_process(child);
 			child->exit_code = data;
@@ -732,10 +613,8 @@
 		}
 
 		case PTRACE_DETACH: { /* detach a process that was attached. */
-			if ((unsigned long) data > NSIG) {
-				set_failure(&regs,-EIO);
+			if ((unsigned long) data > NSIG)
 				return -EIO;
-			}
 			child->flags &= ~(PF_PTRACED|PF_TRACESYS);
 			wake_up_process(child);
 			child->exit_code = data;
@@ -748,7 +627,6 @@
 		}
 
 		default:
-		  set_failure(&regs,-EIO);
 		  return -EIO;
 	  }
 }
diff -u --recursive --new-file v1.3.21/linux/arch/alpha/kernel/setup.c linux/arch/alpha/kernel/setup.c
--- v1.3.21/linux/arch/alpha/kernel/setup.c	Tue Jul 25 18:21:20 1995
+++ linux/arch/alpha/kernel/setup.c	Tue Aug 29 10:15:48 1995
@@ -73,7 +73,8 @@
 	struct memclust_struct * cluster;
 	struct memdesc_struct * memdesc;
 
-	memdesc = (struct memdesc_struct *) (INIT_HWRPB->mddt_offset + (unsigned long) INIT_HWRPB);
+	memdesc = (struct memdesc_struct *)
+	  (INIT_HWRPB->mddt_offset + (unsigned long) INIT_HWRPB);
 	cluster = memdesc->cluster;
 	for (i = memdesc->numclusters ; i > 0; i--, cluster++) {
 		unsigned long tmp;
@@ -93,7 +94,8 @@
 
 	hwrpb = (struct hwrpb_struct*)(IDENT_ADDR + INIT_HWRPB->phys_addr);
 
-	set_hae(hae.cache);		/* sync HAE register w/hae_cache */
+	set_hae(hae.cache);	/* sync HAE register w/hae_cache */
+	wrmces(0x7);		/* reset enable correctable error reports */
 
 	ROOT_DEV = 0x0802;		/* sda2 */
 	command_line[COMMAND_LINE_SIZE - 1] = '\0';
@@ -103,8 +105,10 @@
 	*memory_start_p = (unsigned long) &_end;
 	*memory_end_p = find_end_memory();
 
-#ifdef CONFIG_PCI
+#if defined(CONFIG_ALPHA_LCA)
 	*memory_start_p = lca_init(*memory_start_p, *memory_end_p);
+#elif defined(CONFIG_ALPHA_APECS)
+	*memory_start_p = apecs_init(*memory_start_p, *memory_end_p);
 #endif
 }
 
@@ -122,22 +126,27 @@
 	const char *cpu_name[] = {
 		"EV3", "EV4", "Unknown 1", "LCA4", "EV5", "EV45"
 	};
+#	define SYSTYPE_NAME_BIAS	20
 	const char *systype_name[] = {
-		"ADU", "Cobra", "Ruby", "Flamingo", "Unknown 1", "Jensen",
-		"Pelican", "Unknown 2", "Sable", "AXPvme", "Noname",
-		"Turbolaser", "Avanti", "Mustang", "Alcor", "Unknown 3",
-		"Mikasa", "Unknown3", "EB66", "EB64+"
+		"Cabriolet", "EB66P", "-18", "-17", "-16", "-15",
+		"-14", "-13", "-12", "-11", "-10", "-9", "-8",
+		"-7", "-6", "-5", "-4", "-3", "-2", "-1", "0",
+		"ADU", "Cobra", "Ruby", "Flamingo", "5", "Jensen",
+		"Pelican", "8", "Sable", "AXPvme", "Noname",
+		"Turbolaser", "Avanti", "Mustang", "Alcor", "16",
+		"Mikasa", "18", "EB66", "EB64+"
 	};
 	struct percpu_struct *cpu;
-	unsigned int cpu_index, system_index;
+	unsigned int cpu_index;
+	long sysname_index;
 	extern struct unaligned_stat {
 		unsigned long count, va, pc;
-	} unaligned;
+	} unaligned[2];
 #	define N(a)	(sizeof(a)/sizeof(a[0]))
 
 	cpu = (struct percpu_struct*)((char*)hwrpb + hwrpb->processor_offset);
 	cpu_index = (unsigned) (cpu->type - 1);
-	system_index = (unsigned) (hwrpb->sys_type - 1);
+	sysname_index = hwrpb->sys_type + SYSTYPE_NAME_BIAS;
 
 	return sprintf(buffer,
 		       "cpu\t\t\t: Alpha\n"
@@ -155,11 +164,14 @@
 		       "phys. address bits\t: %ld\n"
 		       "max. addr. space #\t: %ld\n"
 		       "BogoMIPS\t\t: %lu.%02lu\n"
-		       "unaligned accesses\t: %ld (pc=%lx,va=%lx)\n",
+		       "kernel unaligned acc\t: %ld (pc=%lx,va=%lx)\n"
+		       "user unaligned acc\t: %ld (pc=%lx,va=%lx)\n",
 
-		       (cpu_index < N(cpu_name) ? cpu_name[cpu_index] : "Unknown"),
+		       (cpu_index < N(cpu_name)
+			? cpu_name[cpu_index] : "Unknown"),
 		       cpu->variation, cpu->revision, (char*)cpu->serial_no,
-		       (system_index < N(systype_name) ? systype_name[system_index] : "Unknown"),
+		       (sysname_index < N(systype_name)
+			? systype_name[sysname_index] : "Unknown"),
 		       hwrpb->sys_variation, hwrpb->sys_revision,
 		       (char*)hwrpb->ssn,
 		       hwrpb->cycle_freq,
@@ -169,6 +181,7 @@
 		       hwrpb->pa_bits,
 		       hwrpb->max_asn,
 		       loops_per_sec / 500000, (loops_per_sec / 5000) % 100,
-		       unaligned.count, unaligned.pc, unaligned.va);
+		       unaligned[0].count, unaligned[0].pc, unaligned[0].va,
+		       unaligned[1].count, unaligned[1].pc, unaligned[1].va);
 #       undef N
 }
diff -u --recursive --new-file v1.3.21/linux/arch/alpha/kernel/signal.c linux/arch/alpha/kernel/signal.c
--- v1.3.21/linux/arch/alpha/kernel/signal.c	Tue Jul 25 18:21:20 1995
+++ linux/arch/alpha/kernel/signal.c	Tue Aug 29 10:15:48 1995
@@ -25,6 +25,9 @@
 	unsigned long, unsigned long);
 asmlinkage void imb(void);
 
+extern int ptrace_set_bpt (struct task_struct *child);
+extern int ptrace_cancel_bpt (struct task_struct *child);
+
 /*
  * The OSF/1 sigprocmask calling sequence is different from the
  * C sigprocmask() sequence..
@@ -119,13 +122,19 @@
 	regs->gp  = get_fs_quad(sc->sc_regs+29);
 	for (i = 0; i < 31; i++)
 		sw->fp[i] = get_fs_quad(sc->sc_fpregs+i);
+
+	/* send SIGTRAP if we're single-stepping: */
+	if (ptrace_cancel_bpt (current))
+		send_sig(SIGTRAP, current, 1);
 }
 
 /*
  * Set up a signal frame...
  */
-static void setup_frame(struct sigaction * sa, struct sigcontext_struct ** fp, unsigned long pc,
-	struct pt_regs * regs, struct switch_stack * sw, int signr, unsigned long oldmask)
+static void setup_frame(struct sigaction * sa, struct sigcontext_struct ** fp,
+			unsigned long pc, struct pt_regs * regs,
+			struct switch_stack * sw, int signr,
+			unsigned long oldmask)
 {
 	int i;
 	struct sigcontext_struct * sc;
@@ -212,11 +221,10 @@
 	unsigned long handler_signal = 0;
 	struct sigcontext_struct *frame = NULL;
 	unsigned long pc = 0;
-	unsigned long signr;
+	unsigned long signr, single_stepping;
 	struct sigaction * sa;
-	extern ptrace_cancel_bpt (struct task_struct *child);
 
-	ptrace_cancel_bpt(current);	/* make sure single-step bpt is gone */
+	single_stepping = ptrace_cancel_bpt(current);
 
 	while ((signr = current->signal & mask) != 0) {
 		signr = ffz(~signr);
@@ -228,6 +236,7 @@
 			current->state = TASK_STOPPED;
 			notify_parent(current);
 			schedule();
+			single_stepping |= ptrace_cancel_bpt(current);
 			if (!(signr = current->exit_code))
 				continue;
 			current->exit_code = 0;
@@ -263,6 +272,7 @@
 						SA_NOCLDSTOP))
 					notify_parent(current);
 				schedule();
+				single_stepping |= ptrace_cancel_bpt(current);
 				continue;
 
 			case SIGQUIT: case SIGILL: case SIGTRAP:
@@ -292,12 +302,16 @@
 	    (regs->r0 == ERESTARTNOHAND ||
 	     regs->r0 == ERESTARTSYS ||
 	     regs->r0 == ERESTARTNOINTR)) {
-		regs->r0 = r0;
+		regs->r0 = r0;	/* reset v0 and a3 and replay syscall */
 		regs->r19 = r19;
 		regs->pc -= 4;
 	}
-	if (!handler_signal)		/* no handler will be called - return 0 */
+	if (!handler_signal) {	/* no handler will be called - return 0 */
+		if (single_stepping) {
+			ptrace_set_bpt(current);	/* re-set breakpoint */
+		}
 		return 0;
+	}
 	pc = regs->pc;
 	frame = (struct sigcontext_struct *) rdusp();
 	signr = 1;
@@ -318,5 +332,8 @@
 	imb();
 	wrusp((unsigned long) frame);
 	regs->pc = pc;			/* "return" to the first handler */
+	if (single_stepping) {
+		ptrace_set_bpt(current);	/* re-set breakpoint */
+	}
 	return 1;
 }
diff -u --recursive --new-file v1.3.21/linux/arch/alpha/kernel/traps.c linux/arch/alpha/kernel/traps.c
--- v1.3.21/linux/arch/alpha/kernel/traps.c	Thu Jul 27 10:13:16 1995
+++ linux/arch/alpha/kernel/traps.c	Tue Aug 29 10:15:48 1995
@@ -8,6 +8,7 @@
  * This file initializes the trap entry points
  */
 
+#include <linux/mm.h>
 #include <linux/sched.h>
 #include <linux/tty.h>
 
@@ -102,21 +103,27 @@
 
 struct unaligned_stat {
 	unsigned long count, va, pc;
-} unaligned;
+} unaligned[2];
 
 asmlinkage void do_entUna(void * va, unsigned long opcode, unsigned long reg,
 	unsigned long a3, unsigned long a4, unsigned long a5,
 	struct allregs regs)
 {
 	static int cnt = 0;
+	static long last_time = 0;
 
-	if (++cnt < 5)
-		printk("Unaligned trap at %016lx: %p %lx %ld\n",
-			regs.pc, va, opcode, reg);
-
-	++unaligned.count;
-	unaligned.va = (unsigned long) va - 4;
-	unaligned.pc = regs.pc;
+	if (cnt >= 5 && jiffies - last_time > 5*HZ) {
+		cnt = 0;
+	}
+	if (++cnt < 5) {
+		printk("kernel: unaligned trap at %016lx: %p %lx %ld\n",
+		       regs.pc - 4, va, opcode, reg);
+	}
+	last_time = jiffies;
+
+	++unaligned[0].count;
+	unaligned[0].va = (unsigned long) va - 4;
+	unaligned[0].pc = regs.pc;
 
 	/* $16-$18 are PAL-saved, and are offset by 19 entries */
 	if (reg >= 16 && reg <= 18)
@@ -141,19 +148,98 @@
 }
 
 /*
- * Handle user-level unaligned fault.  For now, simply send a
- * SIGBUS---there should be little reason for users not wanting to
- * fix their code instead.  Notice that we have the regular kernel
- * stack layout here, so finding the appropriate registers is a little
- * more difficult than in the kernel case.  Also, we'd need to do
- * a "verify_area()" before accessing memory on behalf of the user.
+ * Handle user-level unaligned fault.  Handling user-level unaligned
+ * faults is *extremely* slow and produces nasty messages.  A user
+ * program *should* fix unaligned faults ASAP.
+ *
+ * Notice that we have (almost) the regular kernel stack layout here,
+ * so finding the appropriate registers is a little more difficult
+ * than in the kernel case.
+ *
+ * Finally, we handle regular integer load/stores only.  In
+ * particular, load-linked/store-conditionally and floating point
+ * 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.
  */
-asmlinkage void do_entUnaUser(void *va, unsigned long opcode, unsigned long reg,
-			      unsigned long a3, unsigned long a4, unsigned long a5,
-			      struct pt_regs regs)
+asmlinkage void do_entUnaUser(void * va, unsigned long opcode, unsigned long reg,
+			      unsigned long * frame)
 {
-	regs.pc -= 4;	/* make pc point to faulting insn */
-	send_sig(SIGBUS, current, 1);
+	long dir, size;
+	unsigned long *reg_addr, *pc_addr, usp, zero = 0;
+	static int cnt = 0;
+	static long last_time = 0;
+
+	pc_addr = frame + 7 + 20 + 1;			/* pc in PAL frame */
+
+	if (cnt >= 5 && jiffies - last_time > 5*HZ) {
+		cnt = 0;
+	}
+	if (++cnt < 5) {
+		printk("%s(%d): unaligned trap at %016lx: %p %lx %ld\n",
+		       current->comm, current->pid,
+		       *pc_addr - 4, va, opcode, reg);
+	}
+	last_time = jiffies;
+
+	++unaligned[1].count;
+	unaligned[1].va = (unsigned long) va - 4;
+	unaligned[1].pc = *pc_addr;
+
+	dir = VERIFY_READ;
+	if (opcode > 0x29) {
+		/* it's a stl or stq */
+		dir = VERIFY_WRITE;
+	}
+	size = 4;
+	if (opcode & 1) {
+		/* it's a quadword op */
+		size = 8;
+	}
+	if (verify_area(dir, va, size)) {
+		*pc_addr -= 4;	/* make pc point to faulting insn */
+		send_sig(SIGSEGV, current, 1);
+		return;
+	}
+
+	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 */
+				reg_addr += 7 + 20 + 2;
+				break;
+			case 30:			/* usp in PAL regs */
+				usp = rdusp();
+				reg_addr = &usp;
+				break;
+			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;
+	}
+
+	if (reg == 30 && dir == VERIFY_WRITE) {
+		wrusp(usp);
+	} 
 }
 
 /*
diff -u --recursive --new-file v1.3.21/linux/arch/i386/config.in linux/arch/i386/config.in
--- v1.3.21/linux/arch/i386/config.in	Mon Aug 28 14:52:18 1995
+++ linux/arch/i386/config.in	Fri Sep  1 14:31:56 1995
@@ -57,13 +57,16 @@
   bool 'IP: firewall packet logging' CONFIG_IP_FIREWALL_VERBOSE y
   bool 'IP: masquerading (ALPHA)' CONFIG_IP_MASQUERADE n
 fi
+if [ "$CONFIG_IP_FORWARD" = "y" -a "$CONFIG_IP_MULTICAST" = "y" -a "$CONFIG_NET_IPIP" = "y" ]; then
+  bool 'IP: multicast routing(in progress)' CONFIG_IP_MROUTE n
+fi
 comment '(it is safe to leave these untouched)'
 bool 'IP: PC/TCP compatibility mode' CONFIG_INET_PCTCP n
 bool 'IP: Reverse ARP' CONFIG_INET_RARP n
 bool 'IP: Assume subnets are local' CONFIG_INET_SNARL y
 bool 'IP: Disable NAGLE algorithm (normally enabled)' CONFIG_TCP_NAGLE_OFF n
 bool 'IP: Drop source routed frames' CONFIG_IP_NOSR y
-bool 'IP: Allow large windows (not recommend if <16Mb of memory)' CONFIG_SKB_LARGE y
+bool 'IP: Allow large windows (not recommended if <16Mb of memory)' CONFIG_SKB_LARGE y
 fi
 bool 'The IPX protocol' CONFIG_IPX n
 bool 'Appletalk DDP' CONFIG_ATALK n
@@ -142,6 +145,8 @@
 fi
 if [ "$CONFIG_AX25" = "y" ]; then
 	bool 'Z8530 SCC kiss emulation driver for AX.25' CONFIG_SCC y
+else
+	bool 'Z8530 SCC kiss emulation driver for AX.25' CONFIG_SCC n
 fi
 bool 'PLIP (parallel port) support' CONFIG_PLIP n
 bool 'EQL (serial line load balancing) support' CONFIG_EQUALIZER n
@@ -218,7 +223,7 @@
 
 bool 'Sony CDU31A/CDU33A CDROM support' CONFIG_CDU31A n
 bool 'Standard Mitsumi [no XA/Multisession] CDROM support' CONFIG_MCD n
-bool 'Experimental Mitsumi [XA/MultiSession, no Audio] support' CONFIG_MCDX n
+bool 'Experimental Mitsumi [XA/MultiSession] support' CONFIG_MCDX n
 bool 'Matsushita/Panasonic CDROM support' CONFIG_SBPCD n
 if [ "$CONFIG_SBPCD" = "y" ]; then
   bool 'Matsushita/Panasonic second CDROM controller support' CONFIG_SBPCD2 n
diff -u --recursive --new-file v1.3.21/linux/arch/i386/kernel/irq.c linux/arch/i386/kernel/irq.c
--- v1.3.21/linux/arch/i386/kernel/irq.c	Thu Mar  2 08:39:22 1995
+++ linux/arch/i386/kernel/irq.c	Tue Aug 29 10:37:43 1995
@@ -295,7 +295,7 @@
 
 static void no_action(int cpl, struct pt_regs * regs) { }
 
-unsigned int probe_irq_on (void)
+unsigned long probe_irq_on (void)
 {
 	unsigned int i, irqs = 0, irqmask;
 	unsigned long delay;
@@ -325,7 +325,7 @@
 	return irqs;
 }
 
-int probe_irq_off (unsigned int irqs)
+int probe_irq_off (unsigned long irqs)
 {
 	unsigned int i, irqmask;
 
diff -u --recursive --new-file v1.3.21/linux/arch/i386/kernel/process.c linux/arch/i386/kernel/process.c
--- v1.3.21/linux/arch/i386/kernel/process.c	Thu Jun 29 19:02:39 1995
+++ linux/arch/i386/kernel/process.c	Fri Sep  1 08:15:46 1995
@@ -232,12 +232,17 @@
 	dump->u_tsize = ((unsigned long) current->mm->end_code) >> 12;
 	dump->u_dsize = ((unsigned long) (current->mm->brk + (PAGE_SIZE-1))) >> 12;
 	dump->u_dsize -= dump->u_tsize;
+	if (verify_area(VERIFY_READ, (void *) dump->u_tsize, dump->u_dsize) < 0)
+		dump->u_dsize = 0;
 	dump->u_ssize = 0;
 	for (i = 0; i < 8; i++)
 		dump->u_debugreg[i] = current->debugreg[i];  
 
-	if (dump->start_stack < TASK_SIZE)
+	if (dump->start_stack < TASK_SIZE) {
 		dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> 12;
+		if (verify_area(VERIFY_READ, (void *) dump->start_stack, dump->u_ssize) < 0)
+			dump->u_ssize = 0;
+	}
 
 	dump->regs = *regs;
 
@@ -246,12 +251,11 @@
 
 asmlinkage int sys_fork(struct pt_regs regs)
 {
-	return do_fork(COPYVM | SIGCHLD, regs.esp, &regs);
+	return do_fork(SIGCHLD, regs.esp, &regs);
 }
 
 asmlinkage int sys_clone(struct pt_regs regs)
 {
-#ifdef CLONE_ACTUALLY_WORKS_OK
 	unsigned long clone_flags;
 	unsigned long newsp;
 
@@ -259,12 +263,7 @@
 	clone_flags = regs.ecx;
 	if (!newsp)
 		newsp = regs.esp;
-	if (newsp == regs.esp)
-		clone_flags |= COPYVM;
 	return do_fork(clone_flags, newsp, &regs);
-#else
-	return -ENOSYS;
-#endif
 }
 
 /*
diff -u --recursive --new-file v1.3.21/linux/arch/i386/kernel/ptrace.c linux/arch/i386/kernel/ptrace.c
--- v1.3.21/linux/arch/i386/kernel/ptrace.c	Sun Aug 13 14:45:27 1995
+++ linux/arch/i386/kernel/ptrace.c	Tue Aug 29 09:42:56 1995
@@ -177,7 +177,7 @@
 		*(unsigned long *) (page + (addr & ~PAGE_MASK)) = data;
 /* we're bypassing pagetables, so we have to set the dirty bit ourselves */
 /* this should also re-instate whatever read-only mode there was before */
-	*pgtable = pte_mkdirty(mk_pte(page, vma->vm_page_prot));
+	set_pte(pgtable, pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
 	invalidate();
 }
 
diff -u --recursive --new-file v1.3.21/linux/arch/i386/kernel/vm86.c linux/arch/i386/kernel/vm86.c
--- v1.3.21/linux/arch/i386/kernel/vm86.c	Fri Jun 16 22:02:54 1995
+++ linux/arch/i386/kernel/vm86.c	Tue Aug 29 09:42:56 1995
@@ -93,7 +93,7 @@
 	pte = pte_offset(pmd, 0xA0000);
 	for (i = 0; i < 32; i++) {
 		if (pte_present(*pte))
-			*pte = pte_wrprotect(*pte);
+			set_pte(pte, pte_wrprotect(*pte));
 		pte++;
 	}
 	invalidate();
diff -u --recursive --new-file v1.3.21/linux/arch/i386/mm/init.c linux/arch/i386/mm/init.c
--- v1.3.21/linux/arch/i386/mm/init.c	Tue Aug  8 12:31:33 1995
+++ linux/arch/i386/mm/init.c	Tue Aug 29 09:42:56 1995
@@ -157,7 +157,7 @@
 		pg_dir++;
 		for (tmp = 0 ; tmp < PTRS_PER_PTE ; tmp++,pg_table++) {
 			if (address < end_mem)
-				*pg_table = mk_pte(address, PAGE_SHARED);
+				set_pte(pg_table, mk_pte(address, PAGE_SHARED));
 			else
 				pte_clear(pg_table);
 			address += PAGE_SIZE;
diff -u --recursive --new-file v1.3.21/linux/arch/mips/kernel/process.c linux/arch/mips/kernel/process.c
--- v1.3.21/linux/arch/mips/kernel/process.c	Wed Jan 25 08:54:22 1995
+++ linux/arch/mips/kernel/process.c	Thu Aug 31 11:44:45 1995
@@ -87,7 +87,7 @@
 
 #define IS_CLONE (regs->orig_reg2 == __NR_clone)
 
-unsigned long copy_thread(int nr, unsigned long clone_flags, struct task_struct * p, struct pt_regs * regs)
+void copy_thread(int nr, unsigned long clone_flags, struct task_struct * p, struct pt_regs * regs)
 {
 	struct pt_regs * childregs;
 
@@ -109,16 +109,6 @@
 	p->tss.cp0_status = regs->cp0_status &
 	                    ~(ST0_CU1|ST0_CU0|ST0_KSU|ST0_ERL|ST0_EXL);
 	childregs->cp0_status &= ~(ST0_CU1|ST0_CU0);
-
-	if (IS_CLONE) {
-		if (regs->reg4)
-			childregs->reg29 = regs->reg4;
-		clone_flags = regs->reg5;
-		if (childregs->reg29 == regs->reg29)
-			clone_flags |= COPYVM;
-	}
-
-	return clone_flags;
 }
 
 /*
diff -u --recursive --new-file v1.3.21/linux/arch/mips/kernel/ptrace.c linux/arch/mips/kernel/ptrace.c
--- v1.3.21/linux/arch/mips/kernel/ptrace.c	Tue Jul 18 16:28:56 1995
+++ linux/arch/mips/kernel/ptrace.c	Tue Aug 29 09:42:57 1995
@@ -156,7 +156,7 @@
 	}
 /* we're bypassing pagetables, so we have to set the dirty bit ourselves */
 /* this should also re-instate whatever read-only mode there was before */
-	*pgtable = pte_mkdirty(mk_pte(page, vma->vm_page_prot));
+	set_pte(pgtable, pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
 	invalidate();
 }
 
diff -u --recursive --new-file v1.3.21/linux/arch/mips/mm/init.c linux/arch/mips/mm/init.c
--- v1.3.21/linux/arch/mips/mm/init.c	Wed Jan 25 08:54:22 1995
+++ linux/arch/mips/mm/init.c	Tue Aug 29 09:42:57 1995
@@ -163,7 +163,7 @@
 		pg_dir++;
 		for (tmp = 0 ; tmp < PTRS_PER_PAGE ; tmp++,pg_table++) {
 			if (address < end_mem)
-				*pg_table = mk_pte(address, PAGE_SHARED);
+				set_pte(pg_table, mk_pte(address, PAGE_SHARED));
 			else
 				pte_clear(pg_table);
 			address += PAGE_SIZE;
diff -u --recursive --new-file v1.3.21/linux/arch/sparc/kernel/process.c linux/arch/sparc/kernel/process.c
--- v1.3.21/linux/arch/sparc/kernel/process.c	Tue Jun 27 14:11:32 1995
+++ linux/arch/sparc/kernel/process.c	Thu Aug 31 11:44:45 1995
@@ -139,7 +139,7 @@
 
 asmlinkage int sys_fork(struct pt_regs *regs)
 {
-  return do_fork(COPYVM | SIGCHLD, regs->u_regs[14], regs);
+  return do_fork(SIGCHLD, regs->u_regs[14], regs);
 }
 
 /*
diff -u --recursive --new-file v1.3.21/linux/arch/sparc/mm/loadmmu.c linux/arch/sparc/mm/loadmmu.c
--- v1.3.21/linux/arch/sparc/mm/loadmmu.c	Tue Jun 27 14:11:32 1995
+++ linux/arch/sparc/mm/loadmmu.c	Tue Aug 29 09:42:57 1995
@@ -10,6 +10,7 @@
 #include <asm/pgtable.h>
 
 void (*invalidate)(void);
+void (*set_pte)(pte_t *ptep, pte_t entry);
 
 unsigned int pmd_shift, pmd_size, pmd_mask;
 unsigned int (*pmd_align)(unsigned int);
diff -u --recursive --new-file v1.3.21/linux/arch/sparc/mm/srmmu.c linux/arch/sparc/mm/srmmu.c
--- v1.3.21/linux/arch/sparc/mm/srmmu.c	Tue Jun 27 14:11:32 1995
+++ linux/arch/sparc/mm/srmmu.c	Tue Aug 29 09:42:57 1995
@@ -427,6 +427,13 @@
 	return;
 }
 
+void
+srmmu_set_pte(pte_t *ptep, pte_t entry)
+{
+	/* for now... */
+	*ptep = entry;
+}
+
 /* XXX Needs to be written */
 void
 srmmu_switch_to_context(int context)
@@ -840,6 +847,7 @@
 	
 	/* Functions */
 	invalidate = srmmu_invalidate;
+	set_pte = srmmu_set_pte;
 	switch_to_context = srmmu_switch_to_context;
 	pmd_align = srmmu_pmd_align;
 	pgdir_align = srmmu_pgdir_align;
diff -u --recursive --new-file v1.3.21/linux/arch/sparc/mm/sun4c.c linux/arch/sparc/mm/sun4c.c
--- v1.3.21/linux/arch/sparc/mm/sun4c.c	Tue Jun 27 14:11:32 1995
+++ linux/arch/sparc/mm/sun4c.c	Tue Aug 29 09:42:57 1995
@@ -364,6 +364,13 @@
 }
 
 void
+sun4c_set_pte(pte_t *ptep, pte_t entry)
+{
+	/* for now... */
+	*ptep = entry;
+}
+
+void
 sun4c_switch_to_context(int context)
 {
 	__asm__ __volatile__("stba %0, [%1] %2" : :
@@ -630,6 +637,7 @@
 	
 	/* Functions */
 	invalidate = sun4c_invalidate;
+	set_pte = sun4c_set_pte;
 	switch_to_context = sun4c_switch_to_context;
 	pmd_align = sun4c_pmd_align;
 	pgdir_align = sun4c_pgdir_align;
diff -u --recursive --new-file v1.3.21/linux/drivers/block/README.aztcd linux/drivers/block/README.aztcd
--- v1.3.21/linux/drivers/block/README.aztcd	Sun Aug 13 14:45:28 1995
+++ linux/drivers/block/README.aztcd	Fri Sep  1 08:45:29 1995
@@ -1,8 +1,8 @@
-$Id: README.aztcd,v 1.60 1995/08/09 12:37:46 root Exp root $
+$Id: README.aztcd,v 1.70 1995/08/19 16:21:05 root Exp root $
                        Readme-File README.aztcd
    for Aztech CD-ROM CDA268-01A, ORCHID CD-3110, OKANO/WEARNES CDD110 
                           CD-ROM  Driver 
-                       Version 1.6 and newer
+                       Version 1.7 and newer
                    (for other drives see 6.-8.)
 
 NOTE: THIS DRIVER WILL WORK WITH THE CD-ROM DRIVES LISTED, WHICH HAVE
@@ -20,12 +20,12 @@
                          2.  INSTALLATION
                          3.  CONFIGURING YOUR KERNEL
                          4.  RECOMPILING YOUR KERNEL
-                         4.1 AZTCD AS A RUN-TIME LOADABLE MODULE
-                         4.2 CDROM CONNECTED TO A SOUNDCARD
+                         4.1   AZTCD AS A RUN-TIME LOADABLE MODULE
+                         4.2   CDROM CONNECTED TO A SOUNDCARD
                          5.  KNOWN PROBLEMS, FUTURE DEVELOPMENTS
-			 5.1 MULTISESSION SUPPORT
-			 5.2 STATUS RECOGNITION
-			 5.3 DOSEMU's CDROM SUPPORT
+			 5.1   MULTISESSION SUPPORT
+			 5.2   STATUS RECOGNITION
+			 5.3   DOSEMU's CDROM SUPPORT
                          6.  BUG REPORTS
                          7.  OTHER DRIVES
                          8.  IF YOU DON'T SUCCEED ... DEBUGGING  
@@ -181,11 +181,22 @@
 
 5. KNOWN PROBLEMS, FUTURE DEVELOPMENTS
 5.1 MULTISESSION SUPPORT
-I have now (July 1995) started support of multisession CDs. Unfortunately I
-do only have one multisession CD and no appropriate applications, so I can
-program, but testing is a little too less :-(. If you'd like to help me, 
-please contact me. As of version 1.4 you can enable the multisession support 
-in aztcd.h by setting AZT_MULTISESSION to 1. 
+Multisession support for CD's still is a myth. I implemented and tested a basic
+support for multisession and XA CDs, but I still have not enough CDs and appli-
+cations to test it rigourously. So if you'd like to help me, please contact me
+(Email address see below). As of version 1.4 and newer you can enable the 
+multisession support in aztcd.h by setting AZT_MULTISESSION to 1. Doing so 
+will cause the ISO9660-filesystem to deal with multisession CDs, ie. redirect 
+requests to the Table of Contents (TOC) information from the last session, 
+which contains the info of all previous sessions etc.. If you do set 
+AZT_MULTISESSION to 0, you can use multisession CDs anyway. In that case the 
+drive's firmware will do automatic redirection. For the ISO9660-filesystem any 
+multisession CD  will then look like a 'normal' single session CD. But never-
+theless the data of all sessions is viewable and accessible. So with practical-
+ly all real world applications you won't notice the difference. But as future
+applications may make use of advanced multisession features, I've started to
+implement the interface for the ISO9660 multisession interface via ioctl
+CDROMMULTISESSION.
 
 5.2 STATUS RECOGNITION
 The drive status recognition does not work correctly in all cases. Changing
diff -u --recursive --new-file v1.3.21/linux/drivers/block/README.ide linux/drivers/block/README.ide
--- v1.3.21/linux/drivers/block/README.ide	Mon Aug 28 14:52:18 1995
+++ linux/drivers/block/README.ide	Thu Aug 31 08:09:07 1995
@@ -27,28 +27,31 @@
 	- support for interrupt unmasking during I/O (better than hd.c)
 	- improved handshaking and error detection/recovery
 	- can co-exist with hd.c controlling the first interface
-	- support for reliable operation of buggy CMD-640 interfaces
-NEW!		- use kernel command line option:   ide1=serialize
-	- experimental support for DTC-2278D interfaces
-NEW!		- use kernel command line option:   ide1=dtc2278
 	- run-time selectable 32bit interface support (using hdparm-2.3)
-
+NEW!	- support for reliable operation of buggy RZ1000 interfaces
+NEW!		- PCI support is automatic
+NEW!	- support for reliable operation of buggy CMD-640 interfaces
+NEW!		- PCI support is automatic
+NEW!		- for VLB, use kernel command line option:   ide0=cmd640_vlb
+NEW!		- this support also enables the secondary i/f on most cards
+NEW!	- support for secondary interface on the FGI/Holtek HT-6560B VLB i/f
+NEW!		- use kernel command line option:   ide1=ht6560
+NEW!	- experimental support for DTC-2278D interfaces
+NEW!		- use kernel command line option:   ide1=dtc2278
 NEW!	- support for drives with a stuck WRERR_STAT bit
 NEW!	- support for removeable devices, including door lock/unlock
-
 NEW!	- transparent support for DiskManager 6.0x and "Dynamic Disk Overlay"
+NEW!		- works with Linux fdisk, LILO, loadlin, bootln, etc..
 NEW!		- should work for for EZ-Drive disks as well (not verified)
-		- works with Linux fdisk, LILO, loadlin, bootln, etc..
 NEW!	- ide-cd.c now compiles separate from ide.c
 NEW!	- Bus-Master DMA support for Intel PCI Triton chipset IDE interfaces
-		- for details, see comments at top of triton.c
+NEW!		- for details, see comments at top of triton.c
 
 For work in progress, see the comments in ide.c, ide-cd.c, and triton.c.
 
-***
-***  IMPORTANT NOTICES:
-***  ==================
-***
+
+***  IMPORTANT NOTICES (for kernel versions prior to 1.3.22)
+***  =================
 ***  "CMD" EIDE Interfaces will not (by default) work *reliably* when drives
 ***  are attached to the second interface.  This is due to a flaw in the
 ***  hardware.  To "fix" this, supply the special kernel "command line"
@@ -63,7 +66,21 @@
 ***  and is only a problem when "hdparm -u1" is used after booting.
 ***
 ***  Failure to abide by these restrictions can cause severe data corruption!
+
+
+***  IMPORTANT NOTICES (for kernel versions after 1.3.21)
+***  =================
+***  PCI versions of the CMD640 and RZ1000 interfaces are now detected
+***  automatically at startup when PCI BIOS support is configured.
+***  Linux disables the "pre-fetch" or "read-ahead" modes of these interfaces
+***  to prevent data corruption possible due to hardware design flaws.
+***  Use of the "serialize" option is no longer necessary.
 ***
+***  The CMD640 is also used on some Vesa Local Bus (VLB) cards, and is *NOT*
+***  automatically detected by Linux.  For safe, reliable operation with such
+***  interfaces, one *MUST* use the "ide0=cmd640_vlb" kernel option.
+***  Use of the "serialize" option is no longer necessary.
+
 
 To access devices on the 2nd/3rd/4th interfaces, device entries must first be
 created in /dev for them.  To create such entries, simply run the included
@@ -184,6 +201,9 @@
 
   "idex=dtc2278"	: look for and try to initialize a dtc2278
   "idex=serialize"	: do not overlap operations on ide0 and ide1.
+  "idex=ht6560b"        : enables use of HT6560B secondary i/f
+  "idex=cmd640_vlb"     : required for VLB cards with the CMD640 chip
+                           (not for PCI versions)
 
 Everything else is rejected with a "BAD OPTION" message.
 
@@ -374,3 +394,32 @@
 
    Vladimir Myslik
 
+comp.sys.intel #41571 (1 + 2 more)              --(1)--(1)+-(1)--(1)
+From: triblet@almaden.ibm.com (Chuck Tribolet)            \-(1)--(1)--(1)--(1)
+Newsgroups: comp.sys.intel,comp.os.os2.bugs
+[1] Re: RZ1000 errorIntel motherboards and RZ1000
+Date: Tue Aug 29 11:00:12 EDT 1995
+Organization: IBM Almaden Research Center
+Lines: 20
+X-Newsreader: IBM NewsReader/2 v1.02
+
+In <41ip85$gf9@park.uvsc.edu>, Terry Lambert <terry@cs.weber.edu> writes:
+>Try running a real OS.  BIOS drivers so not initiate bus mastering
+>DMA, and DOS does not interleave I/O.
+
+1: The RZ1000 can't do DMA.
+2: I was running OS/2 (2.11 back then).
+
+I agreed that you might be able to concoct a benchmark that was affected,
+but it has had no real world effect for me or a lot of other people.  Disabling
+IDE prefetch has the effect of a small increase in PCI bus busy at a time
+when the CPU is giving all it's CPU cycles to the IDE driver (because the
+RZ1000 can't run DMA and the driver has to be in a PIO loop) and therefore
+the CPU can't do much of anything else anyway.
+
+
+Chuck Tribolet
+Triblet@Almaden.IBM.Com
+San Jose, CA
+ 
+Silicon Valley - best day job in the world
diff -u --recursive --new-file v1.3.21/linux/drivers/block/README.mcd linux/drivers/block/README.mcd
--- v1.3.21/linux/drivers/block/README.mcd	Fri Jul  7 08:54:44 1995
+++ linux/drivers/block/README.mcd	Tue Aug 29 07:01:32 1995
@@ -1,6 +1,4 @@
 This driver does not support XA or MultiSession CDs (PhotoCDs). Use the
 experimental driver mcdx.c for that.
 
-You can use mcd for one interface, and mcdx for another; this way, you
-can use the audio functions with the "old" driver, and read XA CDs with
-the "new" driver (if you have at least two drives).
+You can use mcd for one interface, and mcdx for another.
diff -u --recursive --new-file v1.3.21/linux/drivers/block/README.mcdx linux/drivers/block/README.mcdx
--- v1.3.21/linux/drivers/block/README.mcdx	Fri Jul  7 08:54:44 1995
+++ linux/drivers/block/README.mcdx	Tue Aug 29 07:01:32 1995
@@ -5,13 +5,17 @@
 To allow this "coexistence" as long as mcdx.c is not a superset of mcd.c,
 this driver has to use its own device files. We use MAJOR 20 for it. So,
 you have to do
+
  # mknod /dev/mcdx0 b 20 0
  # mknod /dev/mcdx1 b 20 1
+
 and so on, one entry for each drive to support, once.
 
 If you are using the driver as a module, you can specify your ports and IRQs
 like
+
  # insmod mcdx.o mcdx=0x300,11,0x304,5
+
 and so on ("address,IRQ" pairs).
 This will override the configuration in mcdx.h.
 
@@ -23,10 +27,10 @@
 		IRQs, i/o ports and slots);
 	o	uses much less kernel memory than the standard mcd driver
 		(no extra driver internal buffers!).
+    o   plays audio (like the `old' driver, I hope)
 
 This version doesn't support yet:
 
-	o	audio functions;
 	o	shared IRQs (but it seems to be possible - I've successfully
                 connected two drives to the same irq.  So it's `only' a 
                 problem of the driver.)
@@ -35,3 +39,6 @@
 
 	o	Read digital audio (i.e. copy directly), due to missing
 		hardware features. 
+
+
+heiko@lotte.sax.de
diff -u --recursive --new-file v1.3.21/linux/drivers/block/aztcd.c linux/drivers/block/aztcd.c
--- v1.3.21/linux/drivers/block/aztcd.c	Sun Aug 13 14:45:28 1995
+++ linux/drivers/block/aztcd.c	Fri Sep  1 08:45:30 1995
@@ -1,5 +1,5 @@
-#define AZT_VERSION "1.60"
-/*      $Id: aztcd.c,v 1.60 1995/08/09 12:37:38 root Exp root $
+#define AZT_VERSION "1.70"
+/*      $Id: aztcd.c,v 1.70 1995/08/19 16:16:39 root Exp root $
 	linux/drivers/block/aztcd.c - AztechCD268 CDROM driver
 
 	Copyright (C) 1994,1995 Werner Zimmermann (zimmerma@rz.fht-esslingen.de)
@@ -117,8 +117,7 @@
 	V1.30   Auto-eject feature. Inspired by Franc Racis (racis@psu.edu)
 	        Werner Zimmermann, July 4, 95
 	V1.40   Started multisession support. Implementation copied from mcdx.c
-	        by Heiko Schlittermann. Not tested, as I do not have a multi-
-	        session CD. If you can test it, please contact me.
+	        by Heiko Schlittermann. Not tested yet.
 	        Werner Zimmermann, July 15, 95
         V1.50   Implementation of ioctl CDROMRESET, continued multisession, began
                 XA, but still untested. Heavy modifications to drive status de-
@@ -127,6 +126,10 @@
         V1.60   XA support now should work. Speeded up drive recognition in cases, 
                 where no drive is installed.
                 Werner Zimmermann, August 8, 1995
+        V1.70   Multisession support now is completed, but there is still not 
+                enough testing done. If you can test it, please contact me. For
+                details please read README.aztcd.
+                Werner Zimmermann, August 19, 1995
 	NOTE: 
 	Points marked with ??? are questionable !
 */
@@ -188,6 +191,7 @@
 #define AZT_TEST4 /* QUICK_LOOP-counter */
 #define AZT_TEST5 /* port(1) state */
 #define AZT_DEBUG
+#define AZT_DEBUG_MULTISESSION
 #endif
 
 #define CURRENT_VALID \
@@ -256,6 +260,7 @@
 static void azt_transfer(void);
 static void azt_poll(void);
 static void azt_invalidate_buffers(void);
+static void do_aztcd_request(void);
 static void azt_hsg2msf(long hsg, struct msf *msf);
 static void azt_bin2bcd(unsigned char *p);
 static int  azt_bcd2bin(unsigned char bcd);
@@ -266,7 +271,10 @@
 static int  aztGetQChannelInfo(struct azt_Toc *qp);
 static int  aztUpdateToc(void);
 static int  aztGetDiskInfo(void);
-static int  aztGetToc(void);
+#if AZT_MULTISESSION 
+  static int  aztGetMultiDiskInfo(void);
+#endif
+static int  aztGetToc(int multi);
 static int  aztGetValue(unsigned char *result);
 static void aztStatTimer(void);
 static void aztCloseDoor(void);
@@ -338,7 +346,7 @@
 #define STEN_LOW_WAIT   statusAzt()
 void statusAzt(void)
 { AztTimeout = AZT_STATUS_DELAY;
-  SET_TIMER(aztStatTimer, 1); 
+  SET_TIMER(aztStatTimer, HZ/100); 
   sleep_on(&azt_waitq);
   if (AztTimeout <= 0) printk("aztcd: Error Wait STEN_LOW_WAIT command:%x\n",aztCmd);
   return;
@@ -355,7 +363,7 @@
        printk("aztcd: Error aztStatTimer: Timeout\n");
        return;
      }
-  SET_TIMER(aztStatTimer, 1);
+  SET_TIMER(aztStatTimer, HZ/100);
 }
 
 void aztcd_setup(char *str, int *ints)
@@ -469,6 +477,39 @@
    RETURNM("sendAztCmd",-1);
 }
 
+/*
+ * Send a seek command to the drive, return -1 on error, else 0
+*/
+static int aztSeek(struct azt_Play_msf *params)
+{  unsigned char data;
+   int retry;
+
+#ifdef AZT_DEBUG
+   printk("aztcd: aztSeek %02x:%02x:%02x\n", \
+	   params->start.min, params->start.sec, params->start.frame);
+#endif   
+   for (retry=0;retry<AZT_RETRY_ATTEMPTS;retry++)
+     { aztSendCmd(ACMD_SEEK);
+       outb(params -> start.min,CMD_PORT);
+       outb(params -> start.sec,CMD_PORT);
+       outb(params -> start.frame,CMD_PORT);
+       STEN_LOW;
+       data=inb(DATA_PORT);
+       if (data==AFL_PA_OK)
+	 { return 0;}           /*PA_OK ?*/
+       if (data==AFL_PA_ERR)
+	 { STEN_LOW;
+	   data=inb(DATA_PORT);
+	   printk("### Error 1 aztcd: aztSeek\n");
+	 }
+     }
+   if (retry>=AZT_RETRY_ATTEMPTS)
+     { printk("### Error 2 aztcd: aztSeek\n ");
+       azt_error=0xA5;
+     }
+   RETURNM("aztSeek",-1);
+}
+
 /* Send a Set Disk Type command
    does not seem to work with Aztech drives, behavior is completely indepen-
    dent on which mode is set ???
@@ -633,7 +674,6 @@
 		}
 		aztAudioStatus = CDROM_AUDIO_PLAY;
 		break;
-#if AZT_MULTISESSION
 	case CDROMMULTISESSION: /*multisession support -- experimental*/
 	        { struct cdrom_multisession ms;
 #ifdef AZT_DEBUG
@@ -643,12 +683,12 @@
 		  if (st) return st;
 		  memcpy_fromfs(&ms, (void*) arg, sizeof(struct cdrom_multisession));
 		  if (ms.addr_format == CDROM_MSF) 
-		     { ms.addr.msf.minute = azt_bcd2bin(DiskInfo.lastTrack.min);
-		       ms.addr.msf.second = azt_bcd2bin(DiskInfo.lastTrack.sec);
-		       ms.addr.msf.frame  = azt_bcd2bin(DiskInfo.lastTrack.frame);
+		     { ms.addr.msf.minute = azt_bcd2bin(DiskInfo.lastSession.min);
+		       ms.addr.msf.second = azt_bcd2bin(DiskInfo.lastSession.sec);
+		       ms.addr.msf.frame  = azt_bcd2bin(DiskInfo.lastSession.frame);
 		     } 
 		  else if (ms.addr_format == CDROM_LBA)
-		       ms.addr.lba = azt_msf2hsg(&DiskInfo.lastTrack);
+		       ms.addr.lba = azt_msf2hsg(&DiskInfo.lastSession);
 		  else
 		       return -EINVAL;
 		  ms.xa_flag = DiskInfo.xa;
@@ -659,16 +699,15 @@
  		  if (ms.addr_format == CDROM_MSF) 
                       printk("aztcd multisession xa:%d, msf:%02x:%02x.%02x [%02x:%02x.%02x])\n",
 			      ms.xa_flag, ms.addr.msf.minute, ms.addr.msf.second, 
-			      ms.addr.msf.frame, DiskInfo.lastTrack.min,
-			      DiskInfo.lastTrack.sec, DiskInfo.lastTrack.frame);
+			      ms.addr.msf.frame, DiskInfo.lastSession.min,
+			      DiskInfo.lastSession.sec, DiskInfo.lastSession.frame);
 		  else
 		      printk("atzcd multisession %d, lba:0x%08x [%02x:%02x.%02x])\n",
-			      ms.xa_flag, ms.addr.lba, DiskInfo.lastTrack.min,
-			      DiskInfo.lastTrack.sec, DiskInfo.lastTrack.frame);
+			      ms.xa_flag, ms.addr.lba, DiskInfo.lastSession.min,
+			      DiskInfo.lastSession.sec, DiskInfo.lastSession.frame);
 #endif
    		  return 0;
 		}
-#endif
 	case CDROMPLAYTRKIND:     /* Play a track.  This currently ignores index. */
 		st = verify_area(VERIFY_READ, (void *) arg, sizeof ti);
 		if (st) return st;
@@ -890,6 +929,19 @@
 		  }
 		 } 
                 break;
+	case CDROMSEEK:    /*seek msf address*/
+		st = verify_area(VERIFY_READ,  (void *) arg, sizeof msf);
+		if (st) return st;
+		memcpy_fromfs(&msf, (void *) arg, sizeof msf);
+		/* convert to bcd */
+		azt_bin2bcd(&msf.cdmsf_min0);
+		azt_bin2bcd(&msf.cdmsf_sec0);
+		azt_bin2bcd(&msf.cdmsf_frame0);
+		azt_Play.start.min = msf.cdmsf_min0;
+		azt_Play.start.sec = msf.cdmsf_sec0;
+		azt_Play.start.frame = msf.cdmsf_frame0;
+		if (aztSeek(&azt_Play)) return -1;
+                break;
 #endif /*end of incompatible code*/       
 	case CDROMREADMODE1: /*set read data in mode 1*/
                 return aztSetDiskType(AZT_MODE_1);
@@ -976,7 +1028,7 @@
 	}
 	azt_state = AZT_S_START;
 	AztTries = 5;
-	SET_TIMER(azt_poll, 1);
+	SET_TIMER(azt_poll, HZ/100);
       }
       break;
     }
@@ -1372,7 +1424,7 @@
       STEN_LOW_WAIT;     
     };
 
-  SET_TIMER(azt_poll, 1);
+  SET_TIMER(azt_poll, HZ/100);
 }
 
 static void azt_invalidate_buffers(void)
@@ -1413,24 +1465,10 @@
 
 	    if ((st & AST_NOT_READY) || (st & AST_DSK_CHG)) /*no disk in drive or changed*/
 	       { printk("aztcd: Disk Changed or No Disk in Drive?\n");
-/*	         return -EIO;
-*/	       }
-
-	    if (aztUpdateToc() < 0)	return -EIO;
-
-            /* XA detection was already done in aztGetToc */
-            if (DiskInfo.xa) 
-               { printk("aztcd: XA support experimental - mail results to zimmerma@rz.fht-esslingen.de\n");
+                 aztTocUpToDate=0;
                }
-
-            /* audio detection was already done in aztGetToc */
-	    if (DiskInfo.audio) 
-	       { printk(("aztcd: Audio-CD found\n"));
-	       } 
-	    else 
-	       { printk("aztcd: %sCD-ROM found\n",
-	  	         DiskInfo.xa ? "XA " : "");
-	       }
+            if (aztUpdateToc())	return -EIO;
+	       
 	  }
 	++azt_open_count;
         MOD_INC_USE_COUNT;
@@ -1503,8 +1541,7 @@
           return -EIO;
 #endif	  
 	}
-	printk("aztcd: Aztech, Orchid, Okano, Wearnes CD-ROM Driver\n");
-	printk("aztcd: (C) 1994,1995 Werner Zimmermann\n");
+	printk("aztcd: Aztech, Orchid, Okano, Wearnes CD-ROM Driver (C) 1994,1995 W.Zimmermann\n");
 	printk("aztcd: DriverVersion=%s  BaseAddress=0x%x \n",AZT_VERSION,azt_port);
 
 	if (check_region(azt_port, 4)) {
@@ -1566,9 +1603,10 @@
 	            { inb(STATUS_PORT);    /*removing all data from earlier tries*/
 	              inb(DATA_PORT);
 	            }
-	          outb(POLLED,MODE_PORT);              /*???*/
+	          outb(POLLED,MODE_PORT);           /*???*/
 	          inb(CMD_PORT);
 	          inb(CMD_PORT);
+		  getAztStatus(); 		    /*trap errors*/
 	          outb(ACMD_SOFT_RESET,CMD_PORT);   /*send reset*/
 	          STEN_LOW;
 	          if (inb(DATA_PORT)!=AFL_OP_OK)    /*OP_OK?*/
@@ -1579,7 +1617,10 @@
                        return -EIO;
 #endif	     
 	             } 
-	          for (count = 0; count < AZT_TIMEOUT; count++);  /* delay a bit */
+	          for (count = 0; count < AZT_TIMEOUT; count++); 
+	             { count=count*2;          /* delay a bit */
+	               count=count/2;
+	             }                        
 	          if ((st=getAztStatus())==-1)
 	             { printk("aztcd: Drive Status Error Status=%x\n",st);
 #ifndef MODULE
@@ -1765,7 +1806,8 @@
  * Read the table of contents (TOC) and TOC header if necessary
  */
 static int aztUpdateToc()
-{
+{       int st;
+
 #ifdef AZT_DEBUG
 	printk("aztcd: starting aztUpdateToc  Time:%li\n",jiffies);
 #endif  
@@ -1775,9 +1817,57 @@
 	if (aztGetDiskInfo() < 0)
 		return -EIO;
 
-	if (aztGetToc() < 0)
+	if (aztGetToc(0) < 0)
 		return -EIO;
 
+        /*audio disk detection
+          with my Aztech drive there is no audio status bit, so I use the copy
+          protection bit of the first track. If this track is copy protected 
+          (copy bit = 0), I assume, it's an audio  disk. Strange, but works ??? */
+        if (!(Toc[DiskInfo.first].ctrl_addr & 0x40)) 
+           DiskInfo.audio=1;
+        else 
+           DiskInfo.audio=0;
+
+        /* XA detection */
+	if (! DiskInfo.audio) 
+	   { azt_Play.start.min   = 0;  /*XA detection only seems to work*/
+             azt_Play.start.sec   = 2;  /*when we play a track*/
+	     azt_Play.start.frame = 0;
+	     azt_Play.end.min     = 0;
+	     azt_Play.end.sec     = 0;
+	     azt_Play.end.frame   = 1;
+	     if (sendAztCmd(ACMD_PLAY_READ, &azt_Play)) return -1;
+	     DTEN_LOW;
+	     for (st=0;st<CD_FRAMESIZE;st++) inb(DATA_PORT);
+           } 
+        DiskInfo.xa = getAztStatus() & AST_MODE;
+        if (DiskInfo.xa) 
+           { printk("aztcd: XA support experimental - mail results to zimmerma@rz.fht-esslingen.de\n");
+           }
+        
+        /*multisession detection
+          support for multisession CDs is done automatically with Aztech drives,
+          we don't have to take care about TOC redirection; if we want the isofs
+          to take care about redirection, we have to set AZT_MULTISESSION to 1*/
+        DiskInfo.multi=0;
+#if AZT_MULTISESSION
+  	if (DiskInfo.xa) 
+  	   { aztGetMultiDiskInfo(); /*here Disk.Info.multi is set*/
+  	   }
+#endif
+        if (DiskInfo.multi)
+           { DiskInfo.lastSession.min  = Toc[DiskInfo.next].diskTime.min;
+	     DiskInfo.lastSession.sec  = Toc[DiskInfo.next].diskTime.sec;
+             DiskInfo.lastSession.frame= Toc[DiskInfo.next].diskTime.frame;
+             printk("aztcd: Multisession support experimental\n");
+           }
+        else
+           { DiskInfo.lastSession.min  = Toc[DiskInfo.first].diskTime.min;
+	     DiskInfo.lastSession.sec  = Toc[DiskInfo.first].diskTime.sec;
+             DiskInfo.lastSession.frame= Toc[DiskInfo.first].diskTime.frame;
+           }
+
 	aztTocUpToDate = 1;
 #ifdef AZT_DEBUG
 	printk("aztcd: exiting aztUpdateToc  Time:%li\n",jiffies);
@@ -1786,8 +1876,8 @@
 }
 
 
-/*
- * Read the table of contents header
+/* Read the table of contents header, i.e. no. of tracks and start of first 
+ * track
  */
 static int aztGetDiskInfo()
 { int limit;
@@ -1814,7 +1904,7 @@
 	}
       if (qInfo.pointIndex==0xA2)   /*DiskLength*/
 	{ DiskInfo.diskLength.min=qInfo.diskTime.min;
-	  DiskInfo.diskLength.sec=qInfo.diskTime.sec-2;
+	  DiskInfo.diskLength.sec=qInfo.diskTime.sec;
 	  DiskInfo.diskLength.frame=qInfo.diskTime.frame;
 	  test=test|0x04;
 	}
@@ -1827,114 +1917,189 @@
       if (test==0x0F) break;
    }
 #ifdef AZT_DEBUG
-printk ("aztcd: exiting aztGetDiskInfo  Time:%li\n",jiffies);
-printk("Disk Info: first %d last %d length %02x:%02x.%02x first %02x:%02x.%02x\n",
-	DiskInfo.first,
-	DiskInfo.last,
-	DiskInfo.diskLength.min,
-	DiskInfo.diskLength.sec,
-	DiskInfo.diskLength.frame,
-	DiskInfo.firstTrack.min,
-	DiskInfo.firstTrack.sec,
-	DiskInfo.firstTrack.frame);
+  printk ("aztcd: exiting aztGetDiskInfo  Time:%li\n",jiffies);
+  printk("Disk Info: first %d last %d length %02X:%02X.%02X dez  first %02X:%02X.%02X dez\n",
+  	  DiskInfo.first,
+	  DiskInfo.last,
+	  DiskInfo.diskLength.min,
+	  DiskInfo.diskLength.sec,
+	  DiskInfo.diskLength.frame,
+	  DiskInfo.firstTrack.min,
+	  DiskInfo.firstTrack.sec,
+	  DiskInfo.firstTrack.frame);
 #endif
   if (test!=0x0F) return -1;
   return 0;
 }
 
+#if AZT_MULTISESSION
 /*
- * Read the table of contents (TOC)
+ * Get Multisession Disk Info
  */
-static int aztGetToc()
-{       int i, px;
-	int limit;
-	struct azt_Toc qInfo;
+static int aztGetMultiDiskInfo(void)
+{ int limit, k=5;
+  unsigned char test;
+  struct azt_Toc qInfo;
+
+#ifdef AZT_DEBUG
+  printk("aztcd: starting aztGetMultiDiskInfo\n");
+#endif
+
+  do { azt_Play.start.min   = Toc[DiskInfo.last+1].diskTime.min;
+       azt_Play.start.sec   = Toc[DiskInfo.last+1].diskTime.sec;
+       azt_Play.start.frame = Toc[DiskInfo.last+1].diskTime.frame;
+       test=0;
+
+       for (limit=30;limit>0;limit--)   /*Seek for LeadIn of next session*/
+           { if (aztSeek(&azt_Play)) RETURNM("aztGetMultiDiskInfo 1",-1);
+             if (aztGetQChannelInfo(&qInfo)<0) RETURNM("aztGetMultiDiskInfo 2",-1);
+             if ((qInfo.track==0)&&(qInfo.pointIndex)) break;  /*LeadIn found*/
+             if ((azt_Play.start.sec+=10) > 59)
+                { azt_Play.start.sec=0;
+                  azt_Play.start.min++;
+                }
+           }
+       if (!limit) break;  /*Check, if a leadin track was found, if not we're
+                             at the end of the disk*/
+#ifdef AZT_DEBUG_MULTISESSION
+       printk("leadin found track %d  pointIndex %x  limit %d\n",qInfo.track,qInfo.pointIndex,limit);
+#endif
+       for (limit=300;limit>0;limit--)
+           { if (++azt_Play.start.frame>74)
+                { azt_Play.start.frame=0;
+                  if (azt_Play.start.sec > 59)
+                     { azt_Play.start.sec=0;
+                       azt_Play.start.min++;
+                     }
+                }     
+             if (aztSeek(&azt_Play)) RETURNM("aztGetMultiDiskInfo 3",-1);
+             if (aztGetQChannelInfo(&qInfo)<0) RETURNM("aztGetMultiDiskInfo 4",-1);
+             if (qInfo.pointIndex==0xA0)   /*Number of NextTrack*/
+	        { DiskInfo.next = qInfo.diskTime.min;
+	          DiskInfo.next = azt_bcd2bin(DiskInfo.next);
+	          test=test|0x01;
+	        }
+             if (qInfo.pointIndex==0xA1)   /*Number of LastTrack*/
+	 	{ DiskInfo.last  = qInfo.diskTime.min;
+	   	  DiskInfo.last  = azt_bcd2bin(DiskInfo.last);
+	   	  test=test|0x02;
+	 	}
+      	     if (qInfo.pointIndex==0xA2)   /*DiskLength*/
+	 	{ DiskInfo.diskLength.min  =qInfo.diskTime.min;
+	   	  DiskInfo.diskLength.sec  =qInfo.diskTime.sec;
+	   	  DiskInfo.diskLength.frame=qInfo.diskTime.frame;
+	  	  test=test|0x04;
+	 	}
+      	     if ((qInfo.pointIndex==DiskInfo.next)&&(test&0x01))   /*StartTime of Next Track*/
+		{ DiskInfo.nextSession.min=qInfo.diskTime.min;
+	  	  DiskInfo.nextSession.sec=qInfo.diskTime.sec;
+	  	  DiskInfo.nextSession.frame=qInfo.diskTime.frame;
+	  	  test=test|0x08;
+		}
+      	     if (test==0x0F) break;
+   	   }
+#ifdef AZT_DEBUG_MULTISESSION
+       printk ("MultiDisk Info: first %d next %d last %d length %02x:%02x.%02x dez  first %02x:%02x.%02x dez  next %02x:%02x.%02x dez\n",
+     		DiskInfo.first,
+		DiskInfo.next,
+		DiskInfo.last,
+		DiskInfo.diskLength.min,
+		DiskInfo.diskLength.sec,
+		DiskInfo.diskLength.frame,
+		DiskInfo.firstTrack.min,
+		DiskInfo.firstTrack.sec,
+		DiskInfo.firstTrack.frame,
+		DiskInfo.nextSession.min,
+		DiskInfo.nextSession.sec,
+		DiskInfo.nextSession.frame);
+#endif
+       if (test!=0x0F) 
+           break;
+       else 
+           DiskInfo.multi=1;   /*found TOC of more than one session*/
+       aztGetToc(1);
+     } while(--k);
 
 #ifdef AZT_DEBUG
-	printk("aztcd: starting aztGetToc  Time:%li\n",jiffies);
+  printk ("aztcd: exiting aztGetMultiDiskInfo  Time:%li\n",jiffies);
+#endif
+  return 0;
+}
 #endif
-	for (i = 0; i < MAX_TRACKS; i++)
-		Toc[i].pointIndex = 0;
 
-	i = DiskInfo.last + 3;
+/*
+ * Read the table of contents (TOC)
+ */
+static int aztGetToc(int multi)
+{ int i, px;
+  int limit;
+  struct azt_Toc qInfo;
+
+#ifdef AZT_DEBUG
+  printk("aztcd: starting aztGetToc  Time:%li\n",jiffies);
+#endif
+  if (!multi)
+     { for (i = 0; i < MAX_TRACKS; i++)
+ 	    Toc[i].pointIndex = 0;
+       i = DiskInfo.last + 3;
+     }
+  else
+     { for (i = DiskInfo.next; i < MAX_TRACKS; i++)
+     	    Toc[i].pointIndex = 0; 
+       i = DiskInfo.last + 4 - DiskInfo.next;
+     }
 
-/* Is there a good reason to stop motor before TOC read?
-	if (aztSendCmd(ACMD_STOP)) RETURNM("aztGetToc 1",-1);
-	STEN_LOW_WAIT;
+/*Is there a good reason to stop motor before TOC read?
+  if (aztSendCmd(ACMD_STOP)) RETURNM("aztGetToc 1",-1);
+      STEN_LOW_WAIT;
 */
 
-	azt_mode = 0x05;
-	if (aztSendCmd(ACMD_SEEK_TO_LEADIN)) RETURNM("aztGetToc 2",-1); /*???*/
-	STEN_LOW_WAIT;
+  if (!multi)
+     { azt_mode = 0x05;
+       if (aztSendCmd(ACMD_SEEK_TO_LEADIN)) RETURNM("aztGetToc 2",-1); /*???*/
+       STEN_LOW_WAIT;
+     }
+  for (limit = 300; limit > 0; limit--)
+      { if (multi)
+           { if (++azt_Play.start.sec > 59)
+                { azt_Play.start.sec=0;
+                  azt_Play.start.min++;
+                }
+             if (aztSeek(&azt_Play)) RETURNM("aztGetToc 3",-1);
+           }
+	if (aztGetQChannelInfo(&qInfo) < 0)
+	    break;
 
-	for (limit = 300; limit > 0; limit--)
-	{
-		if (aztGetQChannelInfo(&qInfo) < 0)
-			break;
+	px = azt_bcd2bin(qInfo.pointIndex);
 
-		px = azt_bcd2bin(qInfo.pointIndex);
-		if (px > 0 && px < MAX_TRACKS && qInfo.track == 0)
-			if (Toc[px].pointIndex == 0)
-			{
-				Toc[px] = qInfo;
-				i--;
-			}
+	if (px > 0 && px < MAX_TRACKS && qInfo.track == 0)
+  	    if (Toc[px].pointIndex == 0)
+	       { Toc[px] = qInfo;
+		 i--;
+	       }
 
-		if (i <= 0)
-			break;
-	}
+	if (i <= 0)
+	    break;
+      }
 
-	Toc[DiskInfo.last + 1].diskTime = DiskInfo.diskLength;
+  Toc[DiskInfo.last + 1].diskTime = DiskInfo.diskLength;
 
-        /*support for multisession CDs is done automatically with Aztech drives,
-          we don't have to take care about TOC redirection */
-        DiskInfo.multi = 0;    
-        DiskInfo.lastTrack.min  = Toc[DiskInfo.last].diskTime.min;
-	DiskInfo.lastTrack.sec  = Toc[DiskInfo.last].diskTime.sec;
-        DiskInfo.lastTrack.frame= Toc[DiskInfo.last].diskTime.frame;
-
-        /*try to detect XA disks*/
-        i = getAztStatus();
-  	DiskInfo.xa    = i & AST_MODE; /* XA info sometimes unreliable ??? */
-
-        /*try to detect audio disks; with my Aztech drive there is no audio
-          status bit, so I use the copy protection bit of the first track. If
-          this track is copy protected (copy bit = 0), I assume, it's an audio 
-          disk. ???*/
-        if (!(Toc[DiskInfo.first].ctrl_addr & 0x40)) 
-           DiskInfo.audio=1;
-        else 
-           DiskInfo.audio=0;
 
-#ifdef AZT_DEBUG
-printk("aztcd: exiting aztGetToc  Time:%li\n",jiffies);
-for (i = 1; i <= DiskInfo.last+1; i++)
-printk("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X    %02X:%02X.%02X\n",
-i, Toc[i].ctrl_addr, Toc[i].track, Toc[i].pointIndex,
-Toc[i].trackTime.min, Toc[i].trackTime.sec, Toc[i].trackTime.frame,
-Toc[i].diskTime.min, Toc[i].diskTime.sec, Toc[i].diskTime.frame);
-for (i = 100; i < 103; i++)
-printk("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X    %02X:%02X.%02X\n",
-i, Toc[i].ctrl_addr, Toc[i].track, Toc[i].pointIndex,
-Toc[i].trackTime.min, Toc[i].trackTime.sec, Toc[i].trackTime.frame,
-Toc[i].diskTime.min, Toc[i].diskTime.sec, Toc[i].diskTime.frame);
-printk("\nDisk Info: first %d last %d length %02x:%02x.%02x first %02x:%02x.%02x last %02x:%02x.%02x type %02x %02x\n",
-	DiskInfo.first,
-	DiskInfo.last,
-	DiskInfo.diskLength.min,
-	DiskInfo.diskLength.sec,
-	DiskInfo.diskLength.frame,
-	DiskInfo.firstTrack.min,
-	DiskInfo.firstTrack.sec,
-	DiskInfo.firstTrack.frame,
-	DiskInfo.lastTrack.min,
-	DiskInfo.lastTrack.sec,
-	DiskInfo.lastTrack.frame,
-        DiskInfo.xa,
-        DiskInfo.audio);
+#ifdef AZT_DEBUG_MULTISESSION 
+  printk("aztcd: exiting aztGetToc\n");
+  for (i = 1; i <= DiskInfo.last+1; i++)
+       printk("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X dez  %02X:%02X.%02X dez\n",
+               i, Toc[i].ctrl_addr, Toc[i].track, Toc[i].pointIndex,
+               Toc[i].trackTime.min, Toc[i].trackTime.sec, Toc[i].trackTime.frame,
+               Toc[i].diskTime.min, Toc[i].diskTime.sec, Toc[i].diskTime.frame);
+  for (i = 100; i < 103; i++)
+       printk("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X dez  %02X:%02X.%02X dez\n",
+               i, Toc[i].ctrl_addr, Toc[i].track, Toc[i].pointIndex,
+               Toc[i].trackTime.min, Toc[i].trackTime.sec, Toc[i].trackTime.frame,
+               Toc[i].diskTime.min, Toc[i].diskTime.sec, Toc[i].diskTime.frame);
 #endif
 
-	return limit > 0 ? 0 : -1;
+  return limit > 0 ? 0 : -1;
 }
 
 #ifdef MODULE
diff -u --recursive --new-file v1.3.21/linux/drivers/block/blk.h linux/drivers/block/blk.h
--- v1.3.21/linux/drivers/block/blk.h	Mon Aug 28 14:52:18 1995
+++ linux/drivers/block/blk.h	Fri Sep  1 14:59:43 1995
@@ -128,7 +128,7 @@
 #define DEVICE_NAME "harddisk"
 #define DEVICE_INTR do_hd
 #define DEVICE_TIMEOUT HD_TIMER
-#define TIMEOUT_VALUE 600
+#define TIMEOUT_VALUE (6*HZ)
 #define DEVICE_REQUEST do_hd_request
 #define DEVICE_NR(device) (MINOR(device)>>6)
 #define DEVICE_ON(device)
@@ -138,7 +138,7 @@
 
 #define DEVICE_NAME "scsidisk"
 #define DEVICE_INTR do_sd  
-#define TIMEOUT_VALUE 200
+#define TIMEOUT_VALUE (2*HZ)
 #define DEVICE_REQUEST do_sd_request
 #define DEVICE_NR(device) (MINOR(device) >> 4)
 #define DEVICE_ON(device)
diff -u --recursive --new-file v1.3.21/linux/drivers/block/cdu31a.c linux/drivers/block/cdu31a.c
--- v1.3.21/linux/drivers/block/cdu31a.c	Wed Aug  2 13:20:59 1995
+++ linux/drivers/block/cdu31a.c	Thu Aug 31 08:09:05 1995
@@ -625,7 +625,7 @@
    }
 
    current->state = TASK_INTERRUPTIBLE;
-   current->timeout = jiffies + 200;
+   current->timeout = jiffies + 2*HZ;
    schedule();
 
    do_sony_cd_cmd(SONY_READ_TOC_CMD, NULL, 0, res_reg, &res_size);
@@ -834,6 +834,7 @@
             result_buffer[0] = 0x20;
             result_buffer[1] = SONY_SIGNAL_OP_ERR;
             *result_size = 2;
+            restore_flags(flags);
             return;
          }
       }
@@ -887,7 +888,7 @@
    {
       num_retries++;
       current->state = TASK_INTERRUPTIBLE;
-      current->timeout = jiffies + 10; /* Wait .1 seconds on retries */
+      current->timeout = jiffies + HZ/10; /* Wait .1 seconds on retries */
       schedule();
       goto retry_cd_operation;
    }
@@ -2137,6 +2138,7 @@
       interruptible_sleep_on(&sony_wait);
       if (current->signal & ~current->blocked)
       {
+         restore_flags(flags);
          return -EAGAIN;
       }
    }
diff -u --recursive --new-file v1.3.21/linux/drivers/block/cm206.c linux/drivers/block/cm206.c
--- v1.3.21/linux/drivers/block/cm206.c	Wed Aug  2 13:20:59 1995
+++ linux/drivers/block/cm206.c	Tue Aug 29 10:15:49 1995
@@ -126,9 +126,9 @@
 #define POLLOOP 10000
 #define READ_AHEAD 1		/* defines private buffer, waste! */
 #define BACK_AHEAD 1		/* defines adapter-read ahead */
-#define DATA_TIMEOUT 300	/* measured in jiffies (10 ms) */
-#define UART_TIMEOUT 5
-#define DSB_TIMEOUT 700		/* time for the slowest command to finish */
+#define DATA_TIMEOUT (3*HZ)	/* measured in jiffies (10 ms) */
+#define UART_TIMEOUT (5*HZ/100)
+#define DSB_TIMEOUT (7*HZ)	/* time for the slowest command to finish */
 
 #define RAW_SECTOR_SIZE 2352	/* ok, is also defined in cdrom.h */
 #define ISO_SECTOR_SIZE 2048
diff -u --recursive --new-file v1.3.21/linux/drivers/block/floppy.c linux/drivers/block/floppy.c
--- v1.3.21/linux/drivers/block/floppy.c	Wed Aug  2 13:20:59 1995
+++ linux/drivers/block/floppy.c	Tue Aug 29 10:15:49 1995
@@ -908,7 +908,7 @@
 	} else {		
 		del_timer(&fd_timer);
 		fd_timer.function = (timeout_fn) fd_watchdog;
-		fd_timer.expires = jiffies + 10;
+		fd_timer.expires = jiffies + HZ / 10;
 		add_timer(&fd_timer);
 	}
 }
@@ -1031,7 +1031,7 @@
 static int output_byte(char byte)
 {
 	int counter;
-	unsigned char status;
+	unsigned char status = 0;	/* keep gcc quiet */
 	unsigned char rstatus;
 
 	if (FDCS->reset)
@@ -1065,7 +1065,7 @@
 /* gets the response from the fdc */
 static int result(void)
 {
-	int i = 0, counter, status;
+	int i = 0, counter, status = 0;
 
 	if (FDCS->reset)
 		return -1;
diff -u --recursive --new-file v1.3.21/linux/drivers/block/genhd.c linux/drivers/block/genhd.c
--- v1.3.21/linux/drivers/block/genhd.c	Tue Aug 15 20:39:01 1995
+++ linux/drivers/block/genhd.c	Fri Sep  1 09:09:58 1995
@@ -15,6 +15,8 @@
  *  with information provided by OnTrack.  This now works for linux fdisk
  *  and LILO, as well as loadlin and bootln.  Note that disks other than
  *  /dev/hda *must* have a "DOS" type 0x51 partition in the first slot (hda1).
+ * 
+ *  Added support for "missing/deleted" extended partitions - mlord@bnr.ca
  */
 
 #include <linux/config.h>
@@ -98,17 +100,19 @@
 		bh->b_dirt = 0;
 		bh->b_uptodate = 0;
 		bh->b_req = 0;
-		if (*(unsigned short *) (bh->b_data+510) == 0xAA55) {
-			p = (struct partition *) (0x1BE + bh->b_data);
+		if (*(unsigned short *) (bh->b_data+510) != 0xAA55)
+			goto done;
+		p = (struct partition *) (0x1BE + bh->b_data);
 		/*
 		 * Process the first entry, which should be the real
 		 * data partition.
 		 */
-			if (p->sys_ind == EXTENDED_PARTITION || !p->nr_sects)
-				goto done;  /* shouldn't happen */
+		if (p->sys_ind == EXTENDED_PARTITION)
+			goto done;	/* shouldn't happen */
+		if (p->sys_ind && p->nr_sects)
 			add_partition(hd, current_minor, this_sector+p->start_sect, p->nr_sects);
-			current_minor++;
-			p++;
+		current_minor++;
+		p++;
 		/*
 		 * Process the second entry, which should be a link
 		 * to the next logical partition.  Create a minor
@@ -116,15 +120,13 @@
 		 * table.  The minor will be reused for the real
 		 * data partition.
 		 */
-			if (p->sys_ind != EXTENDED_PARTITION ||
-			    !(hd->part[current_minor].nr_sects = p->nr_sects))
-				goto done;  /* no more logicals in this partition */
-			hd->part[current_minor].start_sect = first_sector + p->start_sect;
-			this_sector = first_sector + p->start_sect;
-			dev = ((hd->major) << 8) | current_minor;
-			brelse(bh);
-		} else
-			goto done;
+		if (p->sys_ind != EXTENDED_PARTITION ||
+		    !(hd->part[current_minor].nr_sects = p->nr_sects))
+			goto done;  /* no more logicals in this partition */
+		hd->part[current_minor].start_sect = first_sector + p->start_sect;
+		this_sector = first_sector + p->start_sect;
+		dev = ((hd->major) << 8) | current_minor;
+		brelse(bh);
 	}
 done:
 	brelse(bh);
diff -u --recursive --new-file v1.3.21/linux/drivers/block/ide.c linux/drivers/block/ide.c
--- v1.3.21/linux/drivers/block/ide.c	Mon Aug 28 14:52:19 1995
+++ linux/drivers/block/ide.c	Thu Aug 31 08:09:07 1995
@@ -1,5 +1,5 @@
 /*
- *  linux/drivers/block/ide.c	Version 5.10  Aug 26, 1995
+ *  linux/drivers/block/ide.c	Version 5.11  Aug 29, 1995
  *
  *  Copyright (C) 1994, 1995  Linus Torvalds & authors (see below)
  */
@@ -124,12 +124,18 @@
  *			added ATAPI reset sequence for cdroms
  *  Version 5.10	added Bus-Mastered DMA support for Triton Chipset
  *			some (mostly) cosmetic changes
+ *  Version 5.11	added ht6560b support by malafoss@snakemail.hut.fi
+ *			reworked PCI scanning code
+ *			added automatic RZ1000 detection/support
+ *			added automatic PCI CMD640 detection/support
+ *			added option for VLB CMD640 support
+ *			tweaked probe to find cdrom on hdb with disks on hda,hdc
  *
  *  Driver compile-time options are in ide.h
  *
  *  To do, in likely order of completion:
- *	- add in several updates from my email collection (soon folks!)
- *	- improved CMD support:  handing this off to someone else
+ *	- improved CMD support:  probably handing this off to someone else
+ *	- modify kernel to obtain BIOS geometry for drives on 2nd/3rd/4th i/f
  *	- find someone to work on IDE *tape drive* support
  */
 
@@ -149,24 +155,23 @@
 #include <linux/genhd.h>
 #include <asm/byteorder.h>
 #include <asm/irq.h>
+#include <asm/segment.h>
 
 #ifdef CONFIG_PCI
 #include <linux/bios32.h>
+#include <linux/pci.h>
 #endif /* CONFIG_PCI */
 
 #include "ide.h"
 
-static ide_hwif_t	ide_hwifs[MAX_HWIFS];		/* hwif info */
+       ide_hwif_t	ide_hwifs[MAX_HWIFS];		/* hwif info */
 static ide_hwgroup_t	*irq_to_hwgroup [16];
 static const byte	ide_hwif_to_major[MAX_HWIFS]   = {IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR};
 
 static const unsigned short default_io_base[MAX_HWIFS] = {0x1f0, 0x170, 0x1e8, 0x168};
 static const byte	default_irqs[MAX_HWIFS]     = {14, 15, 11, 10};
 static int		single_threaded = 0;	/* "serialize" option */
-
-#if SUPPORT_DTC2278
-static unsigned int	probe_dtc2278 = 0;
-#endif
+static int		disallow_unmask = 0;	/* for buggy hardware */
 
 #if (DISK_RECOVERY_TIME > 0)
 /*
@@ -284,7 +289,7 @@
 #endif	/* __i386__ */
 
 /*
- * This is used for all data transfers *from* the IDE interface
+ * This is used for most PIO data transfers *from* the IDE interface
  */
 void ide_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount)
 {
@@ -304,7 +309,7 @@
 }
 
 /*
- * This is used for all data transfers *to* the IDE interface
+ * This is used for most PIO data transfers *to* the IDE interface
  */
 void ide_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount)
 {
@@ -323,6 +328,37 @@
 		outsw(IDE_DATA_REG, buffer, wcount<<1);
 }
 
+#if SUPPORT_HT6560B
+/*
+ * This routine handles interface switching for the peculiar hardware design
+ * on the F.G.I./Holtek HT-6560B VLB IDE interface.
+ * The HT-6560B can only enable one IDE port at a time, and requires a
+ * silly sequence (below) whenever we switch between primary and secondary.
+ *
+ * Apparently, systems with multiple CMD640 chips may need something similar..
+ *
+ * This algorithm courtesy of malafoss@snakemail.hut.fi
+ */
+
+void ide_hwif_select (ide_hwif_t *hwif)
+{
+	static ide_hwif_t *current_hwif = NULL;
+
+	if (hwif != current_hwif) {
+		unsigned long flags;
+		save_flags (flags);
+		cli();
+		(void) inb(0x3e6);
+		(void) inb(0x3e6);
+		(void) inb(0x3e6);
+		(void) inb(0x3e6);
+		outb(0x1c,hwif->select);
+		current_hwif = hwif;
+		restore_flags (flags);
+	}
+}
+#endif /* SUPPORT_HT6560B */
+
 /*
  * This should get invoked any time we exit the driver to
  * wait for an interrupt response from a drive.  handler() points
@@ -837,12 +873,14 @@
 	if (GET_STAT() & (BUSY_STAT|DRQ_STAT))
 		rq->errors |= ERROR_RESET;	/* Mmmm.. timing problem */
 
+#ifdef CONFIG_BLK_DEV_TRITON
 	if (rq->errors > 3 && drive->using_dma) {	/* DMA troubles? */
 		drive->using_dma = 0;
 		printk("%s: DMA disabled\n", drive->name);
 		--rq->errors;
 		return 0;
 	}
+#endif /* CONFIG_BLK_DEV_TRITON */
 	if (rq->errors >= ERROR_MAX)
 		ide_end_request(0, HWGROUP(drive));
 	else {
@@ -1196,15 +1234,19 @@
 #endif
 	}
 	if (rq->cmd == READ) {
+#ifdef CONFIG_BLK_DEV_TRITON
 		if (drive->using_dma && !(HWIF(drive)->dmaproc(ide_dma_read, drive)))
 			return;
+#endif /* CONFIG_BLK_DEV_TRITON */
 		ide_set_handler(drive, &read_intr);
 		OUT_BYTE(drive->mult_count ? WIN_MULTREAD : WIN_READ, IDE_COMMAND_REG);
 		return;
 	}
 	if (rq->cmd == WRITE) {
+#ifdef CONFIG_BLK_DEV_TRITON
 		if (drive->using_dma && !(HWIF(drive)->dmaproc(ide_dma_write, drive)))
 			return;
+#endif /* CONFIG_BLK_DEV_TRITON */
 		OUT_BYTE(drive->mult_count ? WIN_MULTWRITE : WIN_WRITE, IDE_COMMAND_REG);
 		if (ide_wait_stat(drive, DATA_READY, drive->bad_wstat, WAIT_DRQ)) {
 			printk("%s: no DRQ after issuing %s\n", drive->name,
@@ -1287,6 +1329,10 @@
 #if (DISK_RECOVERY_TIME > 0)
 	while ((read_timer() - hwif->last_time) < DISK_RECOVERY_TIME);
 #endif
+#if SUPPORT_HT6560B
+	if (hwif->select)
+		ide_hwif_select (hwif);
+#endif
 	OUT_BYTE(drive->select.all,IDE_SELECT_REG);
 	if (ide_wait_stat(drive, drive->ready_stat, BUSY_STAT|DRQ_STAT, WAIT_READY)) {
 		printk("%s: drive not ready for command\n", drive->name);
@@ -1473,6 +1519,10 @@
 	 */
 	do {
 		if (hwif->irq == irq) {
+#if SUPPORT_HT6560B
+			if (hwif->select)
+				ide_hwif_select (hwif);
+#endif
 			for (unit = 0; unit < MAX_DRIVES; ++unit) {
 				ide_drive_t *drive = &hwif->drives[unit];
 				if (!drive->present)
@@ -1788,6 +1838,10 @@
 					drive->keep_settings = arg;
 					break;
 				case HDIO_SET_UNMASKINTR:
+					if (arg && disallow_unmask) {
+						restore_flags(flags);
+						return -EPERM;
+					}
 					drive->unmask = arg;
 					break;
 				case HDIO_SET_NOWERR:
@@ -2120,10 +2174,9 @@
 static int do_probe (ide_drive_t *drive, byte cmd)
 {
 	int rc;
-
 #ifdef CONFIG_BLK_DEV_IDECD
 	if (drive->present) {	/* avoid waiting for inappropriate probes */
-		if ((drive->media == disk) ^ (cmd == WIN_IDENTIFY))
+		if ((drive->media == cdrom) && (cmd == WIN_IDENTIFY))
 			return 4;
 	}
 #endif	/* CONFIG_BLK_DEV_IDECD */
@@ -2132,6 +2185,10 @@
 		drive->name, drive->present, drive->media ? "cdrom":"disk",
 		(cmd == WIN_IDENTIFY) ? "ATA" : "ATAPI");
 #endif
+#if SUPPORT_HT6560B
+	if (HWIF(drive)->select)
+		ide_hwif_select (HWIF(drive));
+#endif
 	OUT_BYTE(drive->select.all,IDE_SELECT_REG);	/* select target drive */
 	delay_10ms();				/* wait for BUSY_STAT */
 	if (IN_BYTE(IDE_SELECT_REG) != drive->select.all && !drive->present) {
@@ -2251,6 +2308,116 @@
 	}
 }
 
+#if SUPPORT_DTC2278
+/*
+ * From: andy@cercle.cts.com (Dyan Wile)
+ *
+ * Below is a patch for DTC-2278 - alike software-programmable controllers
+ * The code enables the secondary IDE controller and the PIO4 (3?) timings on
+ * the primary (EIDE). You may probably have to enable the 32-bit support to
+ * get the full speed. You better get the disk interrupts disabled ( hdparm -u0
+ * /dev/hd.. ) for the drives connected to the EIDE interface. (I get my 
+ * filesystem  corrupted with -u1, but under heavy disk load only :-)  
+ *
+ * From: mlord@bnr.ca -- this chipset is now forced to use the "serialize" feature,
+ * which hopefully will make it more reliable to use.. maybe it has the same bugs
+ * as the CMD640B and RZ1000 ??
+ */
+
+#if SET_DTC2278_MODE4
+static void sub22 (char b, char c)
+{
+	int i;
+
+	for(i = 0; i < 3; ++i) {
+		inb(0x3f6);
+		outb_p(b,0xb0);
+		inb(0x3f6);
+		outb_p(c,0xb4);
+		inb(0x3f6);
+		if(inb(0xb4) == c) {
+			outb_p(7,0xb0);
+			inb(0x3f6);
+			return;	/* success */
+		}
+	}
+}
+#endif /* SET_DTC2278_MODE4 */
+
+static void init_dtc2278 (void)
+{
+	cli();
+#if SET_DTC2278_MODE4
+	/*
+	 * This enables PIO mode4 (3?) on the first interface
+	 */
+	sub22(1,0xc3);
+	sub22(0,0xa0);
+#endif /* SET_DTC2278_MODE4 */
+	/*
+	 * This enables the second interface
+	 */
+	outb_p(4,0xb0);
+	inb(0x3f6);
+	outb_p(0x20,0xb4);
+	inb(0x3f6);
+
+	sti();
+}
+#endif /* SUPPORT_DTC2278 */
+
+#if SUPPORT_CMD640
+/*
+ * ??? fixme: 
+ */
+byte read_cmd640_vlb (byte port, byte reg)
+{
+	byte val;
+
+	unsigned long flags;
+	save_flags(flags);
+	cli();
+	outw(reg, port);
+	val = inb(port+4);
+	restore_flags(flags);
+	return val;
+}
+
+void write_cmd640_vlb (byte port, byte reg, byte val)
+{
+	unsigned long flags;
+	save_flags(flags);
+	cli();
+	outw(reg, port);
+	outw(val, port+4);
+	restore_flags(flags);
+}
+
+void init_cmd640_vlb (void)
+{
+	byte reg;
+	unsigned short port = 0x178;
+
+ 	printk("ide: buggy CMD640 interface: ");
+	reg = read_cmd640_vlb(port, 0x50);
+	if (reg == 0xff || (reg & 0x90) != 0x90) {
+#if TRY_CMD640_VLB_AT_0x78
+		port = 0x78;
+		if (reg == 0xff || (reg & 0x90) != 0x90)
+#endif
+		{
+			single_threaded = 1;
+			disallow_unmask = 1;
+			printk("(probe failed) serialized, disabled unmasking\n");
+			return;
+		}
+	}
+	write_cmd640_vlb(port, 0x51, read_cmd640_vlb(port, 0x51)|0xc8);
+	printk("disabled read-ahead, enabled secondary\n");
+
+}
+#endif /* SUPPORT_CMD640 */
+
 /*
  * stridx() returns the offset of c within s,
  * or -1 if c is '\0' or not found within s.
@@ -2333,42 +2500,52 @@
  * "idex=base,ctl"	: specify both base and ctl
  * "idex=base,ctl,irq"	: specify base, ctl, and irq number
  *
- * The following two are valid ONLY on ide0 or ide1:
+ * The following two are valid ONLY on ide0 or ide1,
+ * and the defaults for the base,ctl ports must not be altered.
  *
- * "idex=dtc2278"	: look for and try to initialize a dtc2278
  * "idex=serialize"	: do not overlap operations on ide0 and ide1.
+ * "idex=dtc2278"	: enables use of DTC2278 secondary i/f
+ * "idex=ht6560b"	: enables use of HT6560B secondary i/f
+ * "idex=cmd640_vlb"	: required for VLB cards with the CMD640 chip
+ *			  (PCI version will be automatically detected)
  */
 void ide_setup (char *s)
 {
 	int vals[3];
+	ide_hwif_t *hwif;
 	ide_drive_t *drive;
-	unsigned int unit, hwif;
+	unsigned int hw, unit;
 	const char max_drive = 'a' + ((MAX_HWIFS * MAX_DRIVES) - 1);
 	const char max_hwif  = '0' + (MAX_HWIFS - 1);
 
 	printk("ide_setup: %s", s);
 	init_ide_data ();
+
+	/*
+	 * Look for drive options:  "hdx="
+	 */
 	if (s[0] == 'h' && s[1] == 'd' && s[2] >= 'a' && s[2] <= max_drive) {
 		const char *hd_words[] = {"noprobe", "nowerr", "cdrom", "serialize", NULL};
 		unit = s[2] - 'a';
-		hwif = unit / MAX_DRIVES;
+		hw   = unit / MAX_DRIVES;
 		unit = unit % MAX_DRIVES;
-		drive = &ide_hwifs[hwif].drives[unit];
+		hwif = &ide_hwifs[hw];
+		drive = &hwif->drives[unit];
 		switch (match_parm(&s[3], hd_words, vals, 3)) {
 			case -1: /* "noprobe" */
 				drive->noprobe = 1;
 				goto done;
 			case -2: /* "nowerr" */
 				drive->bad_wstat = BAD_R_STAT;
-				ide_hwifs[hwif].noprobe = 0;
+				hwif->noprobe = 0;
 				goto done;
 			case -3: /* "cdrom" */
 				drive->present = 1;
 				drive->media = cdrom;
-				ide_hwifs[hwif].noprobe = 0;
+				hwif->noprobe = 0;
 				goto done;
 			case -4: /* "serialize" */
-				printk(" -- USE ""ide%c=serialize"" INSTEAD", '0'+hwif);
+				printk(" -- USE ""ide%c=serialize"" INSTEAD", '0'+hw);
 				goto do_serialize;
 			case 3: /* cyl,head,sect */
 				drive->media	= disk;
@@ -2376,41 +2553,58 @@
 				drive->head	= drive->bios_head = vals[1];
 				drive->sect	= drive->bios_sect = vals[2];
 				drive->present	= 1;
-				ide_hwifs[hwif].noprobe = 0;
+				hwif->noprobe = 0;
 				goto done;
 			default:
 				goto bad_option;
 		}
 	}
+	/*
+	 * Look for interface options:  "idex="
+	 */
 	if (s[0] == 'i' && s[1] == 'd' && s[2] == 'e' && s[3] >= '0' && s[3] <= max_hwif) {
-		const char *ide_words[] = {"dtc2278", "serialize", "noprobe", NULL};
-		hwif = s[3] - '0';
+		const char *ide_words[] = {"noprobe", "serialize", "dtc2278", "ht6560b", "cmd640_vlb", NULL};
+		hw = s[3] - '0';
+		hwif = &ide_hwifs[hw];
+
 		switch (match_parm(&s[4], ide_words, vals, 3)) {
+#if SUPPORT_CMD640
+			case -5: /* "cmd640_vlb" */
+				if (hw > 1) goto bad_hwif;
+				init_cmd640_vlb();
+				goto do_serialize; /* not necessary once we implement the above */
+				break;
+#endif /* SUPPORT_CMD640 */
+#if SUPPORT_HT6560B
+			case -4: /* "ht6560b" */
+				if (hw > 1) goto bad_hwif;
+				ide_hwifs[0].select = 0x1c;
+				ide_hwifs[1].select = 0x1d;
+				goto do_serialize;
+#endif /* SUPPORT_HT6560B */
 #if SUPPORT_DTC2278
-			case -1: /* "dtc2278" */
-				if (hwif > 1) goto bad_hwif;
-				probe_dtc2278 = 1;
-				ide_hwifs[hwif].noprobe = 0;
-				goto done;
+			case -3: /* "dtc2278" */
+				if (hw > 1) goto bad_hwif;
+				init_dtc2278();
+				goto do_serialize;
 #endif /* SUPPORT_DTC2278 */
 			case -2: /* "serialize" */
 			do_serialize:
-				if (hwif > 1) goto bad_hwif;
+				if (hw > 1) goto bad_hwif;
 				single_threaded = 1;
-				ide_hwifs[hwif].noprobe = 0;
 				goto done;
-			case -3: /* "noprobe" */
-				ide_hwifs[hwif].noprobe = 1;
+			case -1: /* "noprobe" */
+				hwif->noprobe = 1;
 				goto done;
 			case 1:	/* base */
 				vals[1] = vals[0] + 0x206; /* default ctl */
 			case 2: /* base,ctl */
 				vals[2] = 0;	/* default irq = probe for it */
 			case 3: /* base,ctl,irq */
-				ide_hwifs[hwif].io_base  = vals[0];
-				ide_hwifs[hwif].ctl_port = vals[1];
-				ide_hwifs[hwif].irq      = vals[2];
-				ide_hwifs[hwif].noprobe = 0;
+				hwif->io_base  = vals[0];
+				hwif->ctl_port = vals[1];
+				hwif->irq      = vals[2];
+				hwif->noprobe = 0;
 				goto done;
 		}
 	}
@@ -2418,7 +2612,7 @@
 	printk(" -- BAD OPTION\n");
 	return;
 bad_hwif:
-	printk("-- NOT SUPPORTED ON ide%d", hwif);
+	printk("-- NOT SUPPORTED ON ide%d", hw);
 done:
 	printk("\n");
 }
@@ -2471,6 +2665,16 @@
  * nibble.  This will be either a 4 bit drive type or 0xf indicating use byte
  * 0x19 for an 8 bit type, drive 1, 0x1a for drive 2 in CMOS.  A non-zero value 
  * means we have an AT controller hard disk for that drive.
+ *
+ * Of course, there is no guarantee that either drive is actually on the
+ * "primary" IDE interface, but we don't bother trying to sort that out here.
+ * If a drive is not actually on the primary interface, then these parameters
+ * will be ignored.  This results in the user having to supply the logical
+ * drive geometry as a boot parameter for each drive not on the primary i/f.
+ *
+ * The only "perfect" way to handle this would be to modify the setup.[cS] code
+ * to do BIOS calls Int13h/Fn08h and Int13h/Fn48h to get all of the drive info
+ * for us during initialization.  I have the necessary docs -- any takers?  -ml
  */
 
 static void probe_cmos_for_drives (ide_hwif_t *hwif)
@@ -2490,7 +2694,6 @@
 			drive->head  = drive->bios_head = *(BIOS+2);
 			drive->sect  = drive->bios_sect = *(BIOS+14);
 			drive->ctl   = *(BIOS+8);
-			drive->media = disk;
 			drive->present = 1;
 		}
 		BIOS += 16;
@@ -2577,54 +2780,100 @@
 	revalidate_disk		/* revalidate */
 };
 
+#ifdef CONFIG_PCI
 
-#if SUPPORT_DTC2278
-/*
- * From: andy@cercle.cts.com (Dyan Wile)
- *
- * Below is a patch for DTC-2278 - alike software-programmable controllers
- * The code enables the secondary IDE controller and the PIO4 (3?) timings on
- * the primary (EIDE). You may probably have to enable the 32-bit support to
- * get the full speed. You better get the disk interrupts disabled ( hdparm -u0 
- * /dev/hd.. ) for the drives connected to the EIDE interface. (I get my 
- * filesystem  corrupted with -u 1, but under heavy disk load only :-)  
- */
+void ide_pci_access_error (int rc)
+{
+	printk("ide: pcibios access failed - %s\n", pcibios_strerror(rc));
+}
 
-static void sub22 (char b, char c)
+#if SUPPORT_RZ1000 || SUPPORT_CMD640
+void buggy_interface_fallback (int rc)
 {
-	int i;
+	ide_pci_access_error (rc);
+	single_threaded = 1;
+	disallow_unmask = 1;
+	printk("serialized, disabled unmasking\n");
+}
+#endif /* SUPPORT_RZ1000 || SUPPORT_CMD640 */
 
-	for(i = 0; i < 3; ++i) {
-		inb(0x3f6);
-		outb_p(b,0xb0);
-		inb(0x3f6);
-		outb_p(c,0xb4);
-		inb(0x3f6);
-		if(inb(0xb4) == c) {
-			outb_p(7,0xb0);
-			inb(0x3f6);
-			return;	/* success */
-		}
-	}
+#if SUPPORT_RZ1000
+void init_rz1000 (byte bus, byte fn)
+{
+	int rc;
+	unsigned short reg;
+
+	printk("ide: buggy RZ1000 interface: ");
+	if ((rc = pcibios_read_config_word(bus, fn, 0x40, &reg))
+	 || (rc =  pcibios_write_config_word(bus, fn, 0x40, reg & 0xdfff)))
+		buggy_interface_fallback (rc);
+	else
+		printk("disabled read-ahead\n");
 }
+#endif /* SUPPORT_RZ1000 */
 
-static void try_to_init_dtc2278 (void)
+#if SUPPORT_CMD640
+void init_cmd640 (byte bus, byte fn)
 {
-/* This (presumably) enables PIO mode4 (3?) on the first interface */
-	cli();
-	sub22(1,0xc3);
-	sub22(0,0xa0);
-	sti();
+	int rc;
+	unsigned char reg;
 
-/* This enables the second interface */
+	printk("ide: buggy CMD640 interface: ");
+	if ((rc = pcibios_read_config_byte(bus, fn, 0x51, &reg))
+	 || (rc =  pcibios_write_config_byte(bus, fn, 0x51, reg | 0xc8)))
+		buggy_interface_fallback (rc);
+	else
+		printk("disabled read-ahead, enabled secondary\n");
+}
+#endif /* SUPPORT_CMD640 */
 
-	outb_p(4,0xb0);
-	inb(0x3f6);
-	outb_p(0x20,0xb4);
-	inb(0x3f6);
+typedef void (ide_pci_init_proc_t)(byte, byte);
+
+/*
+ * ide_probe_pci() scans PCI for a specific vendor/device function,
+ * and invokes the supplied init routine for each instance detected.
+ */
+static void ide_probe_pci (unsigned short vendor, unsigned short device, ide_pci_init_proc_t *init)
+{
+	unsigned long flags;
+	unsigned index = 0;
+	byte fn, bus;
+	int rc;
+
+	if (!pcibios_present())
+		return;
+	save_flags(flags);
+	cli();
+	for (index = 0; !pcibios_find_device (vendor, device, index, &bus, &fn); ++index) {
+		unsigned short command;
+		if ((rc = pcibios_read_config_word (bus, fn, PCI_COMMAND, &command))) {
+			ide_pci_access_error (rc);
+		} else if (command & 1) {	/* is device enabled? */
+			init (bus, fn);
+		}
+	}
+	restore_flags(flags);
 }
-#endif /* SUPPORT_DTC2278 */
 
+/*
+ * ide_init_pci() finds/initializes "known" PCI IDE interfaces
+ * 
+ * This routine should ideally be using pcibios_find_class() to find
+ * all IDE interfaces, but that function causes some systems to "go weird".
+ */
+static void ide_init_pci (void)
+{
+#if SUPPORT_RZ1000
+	ide_probe_pci (PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1000, &init_rz1000);
+#endif
+#if SUPPORT_CMD640
+	ide_probe_pci (PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_640, &init_cmd640);
+#endif
+#ifdef CONFIG_BLK_DEV_TRITON
+	ide_probe_pci (PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371, &ide_init_triton);
+#endif
+}
+#endif /* CONFIG_PCI */
 
 /*
  * This is gets invoked once during initialization, to set *everything* up
@@ -2638,19 +2887,12 @@
 	/*
 	 * First, we determine what hardware is present
 	 */
-#if SUPPORT_DTC2278
-	if (probe_dtc2278)
-		try_to_init_dtc2278();
-#endif /* SUPPORT_DTC2278 */
+
 #ifdef CONFIG_PCI
 	/*
-	 * Look for pci disk interfaces.
+	 * Find/initialize PCI IDE interfaces
 	 */
-	if (pcibios_present()) {
-#ifdef CONFIG_BLK_DEV_TRITON
-		ide_init_triton (ide_hwifs);
-#endif /* CONFIG_BLK_DEV_TRITON */
-	}
+	ide_init_pci ();
 #endif /* CONFIG_PCI */
 
 	/*
diff -u --recursive --new-file v1.3.21/linux/drivers/block/ide.h linux/drivers/block/ide.h
--- v1.3.21/linux/drivers/block/ide.h	Mon Aug 28 14:52:19 1995
+++ linux/drivers/block/ide.h	Fri Sep  1 15:00:11 1995
@@ -30,8 +30,20 @@
 #ifndef OK_TO_RESET_CONTROLLER		/* 1 needed for good error recovery */
 #define OK_TO_RESET_CONTROLLER	1	/* 0 for use with AH2372A/B interface */
 #endif
+#ifndef SUPPORT_RZ1000			/* 1 to support RZ1000 chipset */
+#define SUPPORT_RZ1000		1	/* 0 to reduce kernel size */
+#endif
+#ifndef SUPPORT_CMD640			/* 1 to support CMD640 chipset */
+#define SUPPORT_CMD640		1	/* 0 to reduce kernel size */
+#endif
+#ifndef SUPPORT_HT6560B			/* 1 to support HT6560B chipset */
+#define SUPPORT_HT6560B		1	/* 0 to reduce kernel size */
+#endif
 #ifndef SUPPORT_DTC2278			/* 1 to support DTC2278 chipset */
 #define SUPPORT_DTC2278		1	/* 0 to reduce kernel size */
+#ifndef SET_DTC2278_MODE4
+#define SET_DTC2278_MODE4	0	/* 1 to init primary i/f for PIO mode4 */
+#endif
 #endif
 #ifndef FANCY_STATUS_DUMPS		/* 1 for human-readable drive errors */
 #define FANCY_STATUS_DUMPS	1	/* 0 to reduce kernel size */
@@ -287,7 +299,7 @@
 	unsigned short	dma_base;	/* base addr for dma ports (triton) */
 	byte		irq;		/* our irq number */
 	byte		major;		/* our major number */
-	byte		drivecount;	/* how many drives attached */
+	byte		select;		/* pri/sec hwif select for ht6560b */
 	char 		name[5];	/* name of interface, eg. "ide0" */
 	unsigned	noprobe : 1;	/* don't probe for this interface */
 	unsigned	present : 1;	/* this interface exists */
@@ -415,6 +427,6 @@
 #endif /* CONFIG_BLK_DEV_IDECD */
 
 #ifdef CONFIG_BLK_DEV_TRITON
-void ide_init_triton (ide_hwif_t *);
+void ide_init_triton (byte, byte);
 #endif /* CONFIG_BLK_DEV_TRITON */
 
diff -u --recursive --new-file v1.3.21/linux/drivers/block/mcd.c linux/drivers/block/mcd.c
--- v1.3.21/linux/drivers/block/mcd.c	Sun Aug 13 14:45:28 1995
+++ linux/drivers/block/mcd.c	Tue Aug 29 07:01:32 1995
@@ -1662,6 +1662,7 @@
        return;    
      }
   release_region(mcd_port,4);
+  free_irq(mcd_irq);
   printk("mcd module released.\n");
 }
 #endif MODULE
diff -u --recursive --new-file v1.3.21/linux/drivers/block/mcdx.c linux/drivers/block/mcdx.c
--- v1.3.21/linux/drivers/block/mcdx.c	Tue Jul 11 10:02:49 1995
+++ linux/drivers/block/mcdx.c	Tue Aug 29 10:20:21 1995
@@ -1,7 +1,7 @@
 /*
  * The Mitsumi CDROM interface
  * Copyright (C) 1995 Heiko Schlittermann
- * VERSION: @VERSION@
+ * VERSION: 1.0a
  * 
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -34,7 +34,7 @@
 
 #if RCS
 static const char *mcdx_c_version
-		= "$Id: mcdx.c,v 1.2 1995/06/18 18:00:53 heiko Exp $";
+		= "mcdx.c,v 1.7 1995/08/27 01:46:41 heiko Exp";
 #endif
 
 #include <linux/config.h>
@@ -42,7 +42,7 @@
 #include <linux/module.h>
 #include <linux/version.h>
 #ifndef CONFIG_MODVERSIONS
-char kernel_version[]=UTS_RELEASE;
+char kernel_version[] = UTS_RELEASE;
 #endif
 #else
 #define MOD_INC_USE_COUNT
@@ -64,9 +64,22 @@
 #include <asm/io.h>
 #include <asm/segment.h>
 
+
+#include <linux/major.h>
+
+#ifndef MITSUMI_X_CDROM_MAJOR               /* old kernel (doesn't know about MCDX) */
+#define MITSUMI_X_CDROM_MAJOR 20
+#define DEVICE_NAME "Mitsumi CD-ROM"
+/* #define DEVICE_INTR do_mcdx */
+#define DEVICE_REQUEST do_mcdx_request
+#define DEVICE_NR(device) (MINOR(device))
+#define DEVICE_ON(device)
+#define DEVICE_OFF(device)
+#endif
+
 #define MAJOR_NR MITSUMI_X_CDROM_MAJOR
 #include "blk.h"
-#define	mcdx_drive_map mcdx /* for compatible parameter passing with "insmod" */
+#define	mcdx_drive_map mcdx     /* for compatible parameter passing with "insmod" */
 #include <linux/mcdx.h>
 
 /* CONSTANTS *******************************************************/
@@ -82,6 +95,7 @@
 const int DOUBLE = 0x02;
 const int DOOR   = 0x04;
 const int MULTI  = 0x08;
+const int READY  = 0x70;
 
 const unsigned char READSSPEED = 0xc0;
 const unsigned char READDSPEED = 0xc1;
@@ -137,7 +151,7 @@
 	struct s_multi multi;
 	struct s_subqcode* toc;	/* first enty of the toc array */
 	struct s_subqcode start;
-	struct s_subqcode stop;
+    struct s_subqcode stop;
 	int xa;					/* 1 if xa disk */
 	int audio;				/* 1 if audio disk */
 	int audiostatus;			
@@ -160,13 +174,16 @@
     int minor;			/* minor number of this drive */
     int present;	    /* drive present and its capabilities */
     char readcmd;		/* read cmd depends on single/double speed */
+    char playcmd;       /* play should always be single speed */
     unsigned long changed;	/* last jiff the media was changed */
+    unsigned long xxx;      /* last jiff it was asked for media change */
     int users;				/* keeps track of open/close */
     int lastsector;			/* last block accessible */
     int errno;				/* last operation's error */
 
 };
 
+
 /* Prototypes ******************************************************/ 
 
 /*	The following prototypes are already declared elsewhere.  They are
@@ -202,9 +219,7 @@
 #if MCDX_DEBUG
 static void TRACE((int level, const char* fmt, ...));
 #endif
-#ifndef NOWARN
-static void WARN((const char* fmt, ...));
-#endif
+static void warn(const char* fmt, ...);
 static char *port(int*);
 static int irq(int*);
 static void mcdx_delay(struct s_drive_stuff*, long jifs);
@@ -214,10 +229,8 @@
 static int mcdx_closedoor(struct s_drive_stuff*, int);
 static int mcdx_requestversion(struct s_drive_stuff*, struct s_version*, int);
 static int mcdx_lockdoor(struct s_drive_stuff*, int, int);
-#if 0
-static int mcdx_getstatus(struct s_drive_stuff*, int);
-#endif
 static int mcdx_stop(struct s_drive_stuff*, int);
+static int mcdx_hold(struct s_drive_stuff*, int);
 static int mcdx_reset(struct s_drive_stuff*, enum resetmodes, int);
 static int mcdx_eject(struct s_drive_stuff*, int);
 static int mcdx_setdrivemode(struct s_drive_stuff*, enum drivemodes, int);
@@ -225,11 +238,15 @@
 static int mcdx_requestsubqcode(struct s_drive_stuff*, struct s_subqcode*, int);
 static int mcdx_requestmultidiskinfo(struct s_drive_stuff*, struct s_multi*, int);
 static int mcdx_requesttocdata(struct s_drive_stuff*, struct s_diskinfo*, int);
+static int mcdx_getstatus(struct s_drive_stuff*, int);
+static int mcdx_getval(struct s_drive_stuff*, int to, int delay, char*);
 
 static int mcdx_talk(struct s_drive_stuff*, 
 		const unsigned char* cmd, size_t, void *buffer,
 		size_t size, unsigned int timeout, int);
 static int mcdx_readtoc(struct s_drive_stuff*);
+static int mcdx_playtrk(struct s_drive_stuff*, const struct cdrom_ti*);
+static int mcdx_playmsf(struct s_drive_stuff*, const struct cdrom_msf*);
 
 /* static variables ************************************************/
 
@@ -258,6 +275,12 @@
 
 /* KERNEL INTERFACE FUNCTIONS **************************************/ 
 
+#ifdef MODULE
+#define     free(x, y)      kfree((x))
+#else
+#define     free(x, y)      (mem_start -= y)
+#endif
+
 static int 
 mcdx_ioctl(
 	struct inode* ip, struct file* fp, 
@@ -273,19 +296,21 @@
 			TRACE((IOCTL, "ioctl() START\n"));
 			return 0;
 		}
+
 		case CDROMSTOP: {
 			TRACE((IOCTL, "ioctl() STOP\n"));
+            stuffp->audiostatus = CDROM_AUDIO_INVALID;
 			if (-1 == mcdx_stop(stuffp, 1))
 				return -EIO;
 			return 0;
 		}
+
 		case CDROMPLAYTRKIND: {
-			return -EINVAL;
-			/*
 			int ans;
 			struct cdrom_ti ti;
+
 			TRACE((IOCTL, "ioctl() PLAYTRKIND\n"));
-			if (ans = verify_area(VERIFY_READ, (void*) arg, sizeof(ti));
+			if ((ans = verify_area(VERIFY_READ, (void*) arg, sizeof(ti))))
 				return ans;
 			memcpy_fromfs(&ti, (void*) arg, sizeof(ti));
 			if ((ti.cdti_trk0 < stuffp->di.n_first)
@@ -293,8 +318,41 @@
 					|| (ti.cdti_trk1 < stuffp->di.n_first))
 				return -EINVAL;
 			if (ti.cdti_trk1 > stuffp->di.n_last) ti.cdti_trk1 = stuffp->di.n_last;
-			*/
-		}
+            TRACE((IOCTL, "ioctl() track %d to %d\n", ti.cdti_trk0, ti.cdti_trk1));
+
+            return mcdx_playtrk(stuffp, &ti);
+        }
+
+        case CDROMPLAYMSF: {
+            int ans;
+            struct cdrom_msf msf;
+
+            TRACE((IOCTL, "ioctl() PLAYMSF\n"));
+
+            if ((stuffp->audiostatus == CDROM_AUDIO_PLAY)
+                && (-1 == mcdx_hold(stuffp, 1))) return -EIO;
+
+            if ((ans = verify_area(
+                    VERIFY_READ, (void*) arg, sizeof(struct cdrom_msf)))) 
+                return ans;
+
+            memcpy_fromfs(&msf, (void*) arg, sizeof msf);
+
+            msf.cdmsf_min0 = uint2bcd(msf.cdmsf_min0);
+            msf.cdmsf_sec0 = uint2bcd(msf.cdmsf_sec0);
+            msf.cdmsf_frame0 = uint2bcd(msf.cdmsf_frame0);
+
+            msf.cdmsf_min1 = uint2bcd(msf.cdmsf_min1);
+            msf.cdmsf_sec1 = uint2bcd(msf.cdmsf_sec1);
+            msf.cdmsf_frame1 = uint2bcd(msf.cdmsf_frame1);
+
+            return mcdx_playmsf(stuffp, &msf);
+        }
+
+        case CDROMRESUME: {
+            TRACE((IOCTL, "ioctl() RESUME\n"));
+            return mcdx_playtrk(stuffp, NULL);
+        }
 
 		case CDROMREADTOCENTRY: {
 			struct cdrom_tocentry entry;
@@ -303,7 +361,7 @@
 
 			TRACE((IOCTL, "ioctl() READTOCENTRY\n"));
 
-			if ((stuffp->toc == NULL) && (0 != (ans = mcdx_readtoc(stuffp)))) return ans;
+            if (-1 == mcdx_readtoc(stuffp)) return -1;
 
 			if ((ans = verify_area(VERIFY_READ, (void *) arg, sizeof(entry)))) return ans;
 			memcpy_fromfs(&entry, (void *) arg, sizeof(entry));
@@ -337,12 +395,15 @@
 			int ans;
 			struct cdrom_subchnl sub;
 			struct s_subqcode q;
+
 			TRACE((IOCTL, "ioctl() SUBCHNL\n"));
 
-			if ((ans = verify_area(VERIFY_READ, (void*) arg, sizeof(sub)))) return ans;
+			if ((ans = verify_area(VERIFY_READ, 
+                    (void*) arg, sizeof(sub)))) return ans;
+
 			memcpy_fromfs(&sub, (void*) arg, sizeof(sub));
 
-			if (-1 == mcdx_requestsubqcode(stuffp, &q, 1)) return -EIO;
+			if (-1 == mcdx_requestsubqcode(stuffp, &q, 2)) return -EIO;
 
             TRACE((IOCTL, "audiostatus: %x\n", stuffp->audiostatus));
 			sub.cdsc_audiostatus = stuffp->audiostatus;
@@ -351,9 +412,15 @@
 			sub.cdsc_trk = bcd2uint(q.tno);
 			sub.cdsc_ind = bcd2uint(q.index);
 
+            TRACE((IOCTL, "trk %d, ind %d\n", 
+                    sub.cdsc_trk, sub.cdsc_ind));
+
 			if (sub.cdsc_format == CDROM_LBA) {
 				sub.cdsc_absaddr.lba = msf2log(&q.dt);
 				sub.cdsc_reladdr.lba = msf2log(&q.tt);
+                TRACE((IOCTL, "lba: abs %d, rel %d\n",
+                    sub.cdsc_absaddr.lba,
+                    sub.cdsc_reladdr.lba));
 			} else if (sub.cdsc_format == CDROM_MSF) {
 				sub.cdsc_absaddr.msf.minute = bcd2uint(q.dt.minute);
 				sub.cdsc_absaddr.msf.second = bcd2uint(q.dt.second);
@@ -361,6 +428,14 @@
 				sub.cdsc_reladdr.msf.minute = bcd2uint(q.tt.minute);
 				sub.cdsc_reladdr.msf.second = bcd2uint(q.tt.second);
 				sub.cdsc_reladdr.msf.frame = bcd2uint(q.tt.frame);
+                TRACE((IOCTL,
+                        "msf: abs %02d:%02d:%02d, rel %02d:%02d:%02d\n",
+                        sub.cdsc_absaddr.msf.minute,
+                        sub.cdsc_absaddr.msf.second,
+                        sub.cdsc_absaddr.msf.frame,
+                        sub.cdsc_reladdr.msf.minute,
+                        sub.cdsc_reladdr.msf.second,
+                        sub.cdsc_reladdr.msf.frame));
 			} else return -EINVAL;
 
 			if ((ans = verify_area(VERIFY_WRITE, (void*) arg, sizeof(sub))))
@@ -373,6 +448,7 @@
 		case CDROMREADTOCHDR: {
 			struct cdrom_tochdr toc;
 			int ans;
+
 			TRACE((IOCTL, "ioctl() READTOCHDR\n"));
 			if ((ans = verify_area(VERIFY_WRITE, (void*) arg, sizeof toc)))
 				return ans;
@@ -390,8 +466,11 @@
 			if (-1 == mcdx_stop(stuffp, 1)) return -EIO;
 			if (-1 == mcdx_requestsubqcode(stuffp, &stuffp->start, 1))
 				return -EIO;
+            
+            stuffp->audiostatus = CDROM_AUDIO_PAUSED;
 			return 0;
 		}
+
 		case CDROMMULTISESSION: {
 			int ans;
 			struct cdrom_multisession ms;
@@ -447,6 +526,11 @@
 			return 0;
 		}
 
+        case CDROMVOLCTRL: {
+            TRACE((IOCTL, "ioctl() volctrl\n"));
+            return 0;
+        }
+
 		default:
 			WARN(("ioctl(): unknown request 0x%04x\n", cmd));
 	    	return -EINVAL;
@@ -474,7 +558,7 @@
     dev = MINOR(CURRENT->dev);
 
 	if ((dev < 0) || (dev >= MCDX_NDRIVES) || (!stuffp->present)) {
-		printk(MCD "do_request(): bad device: 0x%04x\n", CURRENT->dev);
+		WARN(("do_request(): bad device: 0x%04x\n", CURRENT->dev));
 		end_request(0);
 		goto again;
     }
@@ -487,7 +571,7 @@
 
     switch (CURRENT->cmd) {
       case WRITE:
-	  printk(MCD ": do_request(): attempt to write to cd!!\n");
+	  WARN(("do_request(): attempt to write to cd!!\n"));
 	  end_request(0);
 	  break;
 
@@ -501,7 +585,7 @@
 				      CURRENT->buffer,
 				      CURRENT->sector,
 				      CURRENT->nr_sectors))) {
-		  printk(MCD " read error\n");
+          WARN(("do_request() read error\n"));
 		  if (stuffp->errno == MCDX_EOM) {
 		      CURRENT->sector += CURRENT->nr_sectors;
 		      CURRENT->nr_sectors = 0;
@@ -519,7 +603,7 @@
 	  break;
 
       default:
-	  panic(MCD "do_request: unknown command.\n");
+	  panic(MCDX "do_request: unknown command.\n");
 	  break;
     }
 
@@ -530,19 +614,20 @@
 mcdx_open(struct inode *ip, struct file *fp)
 {
     struct s_drive_stuff *stuffp;
-	static unsigned long changed = 0;
 
 	TRACE((OPENCLOSE, "open()\n"));
     stuffp = mcdx_stuffp[MINOR(ip->i_rdev)];
     if (!stuffp->present) return -ENXIO;
 
+    if (-1 == mcdx_getstatus(stuffp, 1)) return -EIO;
+
 	/* close the door, if necessary (get the door information
     from the hardware status register) */
 	if (inb((unsigned int) stuffp->rreg_status) & MCDX_RBIT_DOOR)  
 		mcdx_closedoor(stuffp, 1);
 
 	/* if the media changed we will have to little more */
-	if (changed < stuffp->changed) {
+	if (stuffp->xxx < stuffp->changed) {
 
 		TRACE((OPENCLOSE, "open() media changed\n"));
         /* but wait - the time of media change will be set at the 
@@ -550,6 +635,13 @@
         talk() will detect a media change ... (I think, config()
         is the reason. */
 
+        /*
+        TRACE((OPENCLOSE, "open() hardware reset\n"));
+		if (-1 == mcdx_reset(stuffp, HARD, 1)) return -EIO;
+        */
+
+        stuffp->audiostatus = CDROM_AUDIO_INVALID;
+
 		/* get the multisession information */
 		{
 			TRACE((OPENCLOSE, "open() Request multisession info\n"));
@@ -570,11 +662,11 @@
 					stuffp->multi.msf_last.frame));
 		} /* got multisession information */
 
-
 		/* request the disks table of contents (aka diskinfo) */
 		if (-1 == mcdx_requesttocdata(stuffp, &stuffp->di, 1)) return -EIO;
 
-		stuffp->lastsector = (CD_FRAMESIZE / 512) * msf2log(&stuffp->di.msf_leadout) - 1;
+		stuffp->lastsector = (CD_FRAMESIZE / 512) 
+                * msf2log(&stuffp->di.msf_leadout) - 1;
 
 		TRACE((OPENCLOSE, "open() start %d (%02x:%02x.%02x) %d\n",
 				stuffp->di.n_first,
@@ -633,17 +725,19 @@
 			return -EIO;
 
 		if (stuffp->audio) {
-			WARN(("open() audio disk found\n"));
+			INFO(("open() audio disk found\n"));
 		} else {
-			WARN(("open() %s%s disk found\n",
+			INFO(("open() %s%s disk found\n",
 					stuffp->xa ? "XA / " : "",
 					stuffp->multi.multi ? "Multi Session" : "Single Session"));
 		}
 
-        changed = stuffp->changed;
+        stuffp->xxx = jiffies;
 	}
 
-	if (-1 == mcdx_lockdoor(stuffp, 1, 1)) return -EIO;
+    /* lock the door if not already done */
+    if (0 == stuffp->users && (-1 == mcdx_lockdoor(stuffp, 1, 1))) 
+        return -EIO;
 
     stuffp->users++;
     MOD_INC_USE_COUNT;
@@ -666,7 +760,7 @@
 		invalidate_buffers(ip->i_rdev);
 
 		if (-1 == mcdx_lockdoor(stuffp, 0, 1))
-				printk(MCD ": Cannot unlock the door\n");
+				printk(MCDX ": Cannot unlock the door\n");
     }
     MOD_DEC_USE_COUNT;
 
@@ -680,14 +774,14 @@
 	Setting flag to 0 resets the changed state. */
 
 {
-    printk(MCD ":: check_mcdx_media_change(0x%x) called\n", full_dev);
+    INFO(("check_mcdx_media_change(0x%x) called\n"));
     return 0;
 }
 
 void mcdx_setup(char *str, int *pi)
 {
 #if MCDX_DEBUG
-    printk(MCD ":: setup(%s, %d) called\n",
+    printk(MCDX ":: setup(%s, %d) called\n",
 	    str, pi[0]);
 #endif
 }
@@ -698,29 +792,32 @@
 /*	This routine is used for sleeping while initialisation - it seems that
  	there are no other means available. May be we could use a simple count
  	loop w/ jumps to itself, but I wanna make this independend of cpu
- 	speed.  */
+ 	speed. [1 jiffie is 1/HZ sec */
 {
     unsigned long tout = jiffies + jifs;
 
+    TRACE((INIT, "mcdx_delay %d\n", jifs));
     if (jifs < 0) return;
 
-#ifdef MODULE
-	/*	timer are available */
-    current->timeout = tout;
-    while (current->timeout)
-		interruptible_sleep_on(&stuff->sleepq);
+#if 1
+    while (jiffies < tout) {
+        current->timeout = jiffies;
+        schedule();
+    }
 #else
-	/* timer are _not_ available at initialisation time */
-    if (stuff->present) {
-		current->state = TASK_INTERRUPTIBLE;
-		current->timeout = tout;
-		interruptible_sleep_on(&stuff->sleepq);
-    } else
+    if (current->pid == 0) {        /* no sleep allowed */
 		while (jiffies < tout) {
-	    current->timeout = jiffies;
-	    schedule();
-	}
-#endif MODULE
+            current->timeout = jiffies;
+            schedule();
+        }
+    } else {                        /* sleeping is allowed */
+        current->timeout = tout;
+        current->state = TASK_INTERRUPTIBLE;
+        while (current->timeout) {
+            interruptible_sleep_on(&stuff->sleepq);
+        }
+    }
+#endif
 }
 
 static void 
@@ -732,7 +829,7 @@
     stuffp = mcdx_irq_map[irq];
 
     if (!stuffp->busy) {
-		WARN(("intr() unexpected interrupt @ irq %d\n", irq));
+		INFO(("intr() unexpected interrupt @ irq %d\n", irq));
 		return;
     }
 
@@ -761,7 +858,6 @@
  * returns -1 on timeout, drive status otherwise
  */
 {
-    const DELAY = 1;				/* minimum delay */
 	char c;
 	int st;
 
@@ -770,79 +866,77 @@
     while (stuffp->lock)
 		interruptible_sleep_on(&stuffp->lockq);
 
+    if (current->signal && ~current->blocked) {
+        WARN(("talk() got signal %d\n", current->signal));
+        return -1;
+    }
+
     stuffp->lock = 1;
     stuffp->valid = 0;	
 
 #if MCDX_DEBUG & TALK
 	{ 
 		unsigned char i;
-		TRACE((TALK, "talk() res.size %d, command 0x%02x", 
-				size, (unsigned char) cmd[0]));
+		TRACE((TALK, "talk() %d / %d tries, res.size %d, command 0x%02x", 
+				tries, timeout, size, (unsigned char) cmd[0]));
 		for (i = 1; i < cmdlen; i++) printk(" 0x%02x", cmd[i]);
 		printk("\n");
 	}
 #endif
 
+    /*  give up if all tries are done (bad) or if the status
+     *  st != -1 (good) */
 	for (st = -1; st == -1 && tries; tries--) {
 
-		int sz = size;
-		unsigned char* bp = buffer;
+        size_t sz = size;
+        char* bp = buffer;
 
 		outsb((unsigned int) stuffp->wreg_data, cmd, cmdlen);
+        TRACE((TALK, "talk() command sent\n"));
 
-		while (sz--) {
-			int to = 0;
-
-			/* wait for the status bit */
-			{
-				unsigned long limit = jiffies + timeout;
-				while ((inb((unsigned int) stuffp->rreg_status)) & MCDX_RBIT_STEN) {
-					if ((to = (jiffies > limit))) break;
-					mcdx_delay(stuffp, DELAY);
-				}
-			}
-
-			if (!to) {
-
-				/* status read? */
-				if (st == -1) {
-
-					/* read the status byte */
-					*bp++ = st = (unsigned char) inb((unsigned int) stuffp->rreg_data);
-
-					TRACE((TALK, "talk() got status 0x%02x\n", st));
-
-					/* audio status is handled here */
-					stuffp->audiostatus = e_audiobusy(st) ? 
-							CDROM_AUDIO_PLAY : CDROM_AUDIO_NO_STATUS;
-
-					/* media change is handled here ... */
-					if (e_changed(st)) {
-						WARN(("talk() media changed\n"));
-						stuffp->changed = jiffies;
-					}
-
-					/* command error is handled here ... */
-					if (e_cmderr(st)) {
-						WARN(("command error\n"));
-						st = -1;
-						break;
-					}
-				} else {
-					/* read the answer */
-					 *bp++ = (unsigned char) inb((unsigned int) stuffp->rreg_data); 
-				}
-			} else {
-				WARN(("talk() timed out, %1d %s left\n", 
-					tries - 1, (tries -1 ) > 1 ? "tries" : "try"));
-				st = -1;
-				break;
-			}
-		}
-	}
-
-	if (tries) WARN(("talk() giving up\n"));
+        /* get the status byte */
+        if (-1 == mcdx_getval(stuffp, timeout, 0, bp)) {
+            WARN(("talk() %02x timed out (status), %d tr%s left\n", 
+                    cmd[0], tries - 1, tries == 2 ? "y" : "ies"));
+                continue; 
+        }
+        st = *bp++;
+        sz--;
+
+        TRACE((TALK, "talk() got status 0x%02x\n", st));
+
+        /* command error? */
+        if (e_cmderr(st)) {
+            WARN(("command error %02x (%d)\n", cmd[0], cmdlen));
+            st = -1;
+            continue;
+        }
+
+        /* audio status? */
+        if (stuffp->audiostatus == CDROM_AUDIO_INVALID)
+            stuffp->audiostatus = 
+                    e_audiobusy(st) ? CDROM_AUDIO_PLAY : CDROM_AUDIO_NO_STATUS;
+
+        /* media change? */
+        if (e_changed(st)) {
+            INFO(("talk() media changed\n"));
+            stuffp->changed = jiffies;
+        }
+
+        /* now actually get the data */
+        while (sz--) {
+            if (-1 == mcdx_getval(stuffp, timeout, -1, bp++)) {
+                WARN(("talk() %02x timed out (data), %d tr%s left\n", 
+                        cmd[0], tries - 1, tries == 2 ? "y" : "ies"));
+                st = -1; break;
+            }
+            TRACE((TALK, "talk() got 0x%02x\n", *(bp - 1)));
+        }
+    }
 
+#if QUIET == 0
+    if (!tries && st == -1) INFO(("talk() giving up\n"));
+#endif
 
     stuffp->lock = 0;
     wake_up_interruptible(&stuffp->lockq);
@@ -868,10 +962,8 @@
 		}
 	}
 
-    if (!drives) {
-		WARN(("init_module() cannot init any drive\n"));
+    if (!drives) 
 		return -EIO;
-    }
 
     return 0;
 }
@@ -897,10 +989,9 @@
 		kfree(stuffp);
     }
 
-    if (unregister_blkdev(MAJOR_NR, MCD) != 0) 
-		printk(MCD ": cleanup_module failed.\n");
-    else 
-		printk(MCD ": cleanup_module succeeded.\n");
+    if (unregister_blkdev(MAJOR_NR, DEVICE_NAME) != 0) 
+        WARN(("cleanup() unregister_blkdev() failed\n"));
+    else INFO(("cleanup() succeeded\n"));
 }
 
 #endif MODULE
@@ -915,33 +1006,30 @@
 	if (level < 1) return;
 	va_start(args, fmt);
 	if (sizeof(s) < vsprintf(s, fmt, args))
-		printk(MCD ":: dprintf exeeds limit!!\n");
-	else printk(MCD ":: %s", s);
+		printk(MCDX ":: dprintf exeeds limit!!\n");
+	else printk(MCDX ":: %s", s);
 	va_end(args);
 }
 #endif
 
-#ifndef NOWARN
 void warn(const char* fmt, ...)
 {
 	char s[255];
 	va_list args;
 	va_start(args, fmt);
 	if (sizeof(s) < vsprintf(s, fmt, args))
-		printk(MCD ":: dprintf exeeds limit!!\n");
-	else printk(MCD ": %s", s);
+		printk(MCDX ":: dprintf exeeds limit!!\n");
+	else printk(MCDX ": %s", s);
 	va_end(args);
 }
-#endif
 
 
 unsigned long mcdx_init(unsigned long mem_start, unsigned long mem_end)
 {
 	int drive;
 
-	printk(MCD 
-			": Version @VERSION@ "
-			"$Id: mcdx.c,v 1.2 1995/06/18 18:00:53 heiko Exp $ \n");
+	INFO((": Version 1.0a "
+			"mcdx.c,v 1.7 1995/08/27 01:46:41 heiko Exp\n"));
 
 	/* zero the pointer array */
 	for (drive = 0; drive < MCDX_NDRIVES; drive++)
@@ -951,14 +1039,23 @@
 	for (drive = 0; drive < MCDX_NDRIVES; drive++) { 
 		struct s_version version;
 		struct s_drive_stuff* stuffp;
+        int size;
+
+        size = sizeof(*stuffp);
 		
 		TRACE((INIT, "init() try drive %d\n", drive));
-		TRACE((MALLOC, "init() malloc %d bytes\n", sizeof(*stuffp)));
 
-		if (!(stuffp = kmalloc(sizeof(*stuffp), GFP_KERNEL))) {
+#ifdef MODULE
+		TRACE((MALLOC, "init() malloc %d bytes\n", size));
+		if (!(stuffp = kmalloc(size, GFP_KERNEL))) {
 			WARN(("init() malloc failed\n"));
 			break; 
 		}
+#else
+        TRACE((INIT, "adjust mem_start\n"));
+        stuffp = mem_start;
+        mem_start += size;
+#endif
 
 		TRACE((INIT, "init() got %d bytes for drive stuff @ %p\n", sizeof(*stuffp), stuffp));
 
@@ -978,11 +1075,14 @@
 
 		/* check if i/o addresses are available */
 		if (0 != check_region((unsigned int) stuffp->wreg_data, MCDX_IO_SIZE)) {
-			WARN(("init() i/o ports at 0x%3p .. 0x%3p not available\n",
-					stuffp->wreg_data, stuffp->wreg_data + MCDX_IO_SIZE - 1));
-					stuffp->wreg_data = 0;
+            WARN(("%s=0x%3p,%d: "
+                    "Init failed. I/O ports (0x%3p..0x3p) already in use.\n"
+                    MCDX, 
+                    stuffp->wreg_data, stuffp->irq,
+                    stuffp->wreg_data, 
+                    stuffp->wreg_data + MCDX_IO_SIZE - 1));
 			TRACE((MALLOC, "init() free stuffp @ %p\n", stuffp));
-			kfree(stuffp);
+            free(stuffp, size);
 			TRACE((INIT, "init() continue at next drive\n"));
 			continue; /* next drive */
 		}
@@ -993,13 +1093,17 @@
 		mcdx_reset(stuffp, HARD, 1);
 
 		TRACE((INIT, "init() get version\n"));
-		if (-1 == mcdx_requestversion(stuffp, &version, 2)) {
+		if (-1 == mcdx_requestversion(stuffp, &version, 4)) {
 			/* failed, next drive */
+            WARN(("%s=0x%3p,%d: Init failed. Can't get version.\n",
+                    MCDX,
+                    stuffp->wreg_data, stuffp->irq));
 			TRACE((MALLOC, "init() free stuffp @ %p\n", stuffp));
-			kfree(stuffp);
+            free(stuffp, size);
 			TRACE((INIT, "init() continue at next drive\n"));
 			continue;
 		}
+
 		switch (version.code) {
 		case 'D': 
                 stuffp->readcmd = READDSPEED; 
@@ -1017,18 +1121,22 @@
                 stuffp->present = 0; break;
 		}
 
+        stuffp->playcmd = READSSPEED;
+
 
 		if (!stuffp->present) {
-			printk(MCD ": no drive found. continue at next drive\n");
-			kfree(stuffp);
+            WARN(("%s=0x%3p,%d: Init failed. No Mitsumi CD-ROM?.\n",
+                    MCDX, stuffp->wreg_data, stuffp->irq));
+			free(stuffp, size);
 			continue; /* next drive */
 		}
 
 		TRACE((INIT, "init() register blkdev\n"));
-		if (register_blkdev(MAJOR_NR, MCD, &mcdx_fops) != 0) {
-			printk(MCD ": unable to get major %d for " DEVICE_NAME "\n",
-					MAJOR_NR);
-			kfree(stuffp);
+		if (register_blkdev(MAJOR_NR, DEVICE_NAME, &mcdx_fops) != 0) {
+            WARN(("%s=0x%3p,%d: Init failed. Can't get major %d.\n",
+                    MCDX,
+                    stuffp->wreg_data, stuffp->irq, MAJOR_NR));
+			free(stuffp, size);
 			continue; /* next drive */
 		}
 
@@ -1041,19 +1149,22 @@
 
 		TRACE((INIT, "init() subscribe irq and i/o\n"));
 		mcdx_irq_map[stuffp->irq] = stuffp;
-		if (request_irq(stuffp->irq, mcdx_intr, SA_INTERRUPT, MCD)) {
-			printk(MCD ": init() unable to get IRQ %d for "
-					DEVICE_NAME "\n", stuffp->irq);
+		if (request_irq(stuffp->irq, mcdx_intr, SA_INTERRUPT, DEVICE_NAME)) {
+            WARN(("%s=0x%3p,%d: Init failed. Can't get irq (%d).\n",
+                    MCDX,
+                    stuffp->wreg_data, stuffp->irq, stuffp->irq));
 			stuffp->irq = 0;
-			kfree(stuffp);
+			free(stuffp, size);
 			continue;
 		}
-		request_region((unsigned long) (unsigned int) stuffp->wreg_data, MCDX_IO_SIZE, MCD); 
+		request_region((unsigned int) stuffp->wreg_data, 
+                MCDX_IO_SIZE, 
+                DEVICE_NAME); 
 
 		TRACE((INIT, "init() get garbage\n"));
 		{
 			int i;
-			mcdx_delay(stuffp, 50);
+			mcdx_delay(stuffp, HZ/2);
 			for (i = 100; i; i--) (void) inb((unsigned int) stuffp->rreg_status);
 		}
 
@@ -1067,9 +1178,10 @@
 
 		stuffp->minor = drive;
 
-		printk(MCD ": " DEVICE_NAME " installed at 0x%3p, irq %d.\n"
-			   MCD ": Firmware version %c %x\n",
-			   stuffp->wreg_data, stuffp->irq, version.code, version.ver);
+		WARN((DEVICE_NAME " installed at 0x%3p, irq %d."
+			   " (Firmware version %c %x)\n",
+			   stuffp->wreg_data, stuffp->irq, version.code,
+               version.ver));
 		mcdx_stuffp[drive] = stuffp;
 		TRACE((INIT, "init() mcdx_stuffp[%d] = %p\n", drive, stuffp));
 	}
@@ -1091,12 +1203,15 @@
 			nr_sectors, sector));
 
 	if (stuffp->audio) {
-		printk(MCD ": attempt to read from audio disk\n");
+		WARN(("attempt to read from audio cd\n"));
 		return -1;
 	}
 
     while (stuffp->lock)
 		interruptible_sleep_on(&stuffp->lockq);
+    if (current->signal && ~current->blocked) {
+        WARN(("talk() got signal %d\n", current->signal));
+    }
 
     if (stuffp->valid
 			&& (sector >= stuffp->pending)
@@ -1113,7 +1228,7 @@
 	    int to = 0;
 
 		/* wait for the drive become idle */
-	    current->timeout = jiffies + 500;
+	    current->timeout = jiffies + 5*HZ;
 	    while (stuffp->busy) {
 			interruptible_sleep_on(&stuffp->busyq);
 			if ((sig = (current->signal && ~current->blocked))
@@ -1129,11 +1244,11 @@
 				|| sig
 				|| to) {
 			if ((stuffp->busy == 0) && !stuffp->introk)
-				printk(MCD ": failure in data request\n");
+                WARN(("mcdx_transfer() failure in data request\n"));
 			else if (to)
-				printk(MCD ": timeout\n");
+                WARN(("mcdx_transfer(): timeout\n"));
 			else if (sig)
-				printk(MCD ": got signal 0x%lx\n", current->signal);
+                WARN(("mcdx_transfer(): got signal 0x%lx\n", current->signal));
 
 			stuffp->lock = 0;
 			stuffp->busy = 0;
@@ -1195,8 +1310,8 @@
 		/* do some sanity checks */
 		TRACE((TRANSFER, "transfer() request sector %d\n", stuffp->pending));
 		if (stuffp->pending > stuffp->lastsector) {
-			printk(MCD ": transfer() sector %d from nirvana requested.\n",
-				stuffp->pending);
+			WARN(("transfer() sector %d from nirvana requested.\n",
+				stuffp->pending));
 			stuffp->errno = MCDX_EOM;
 			TRACE((TRANSFER, "transfer() done (-1)\n"));
 			return -1;
@@ -1266,17 +1381,19 @@
 }
 	
 int mcdx_readtoc(struct s_drive_stuff* stuffp)
+/*  Read the toc entries from the CD,
+ *  Return: -1 on failure, else 0 */
 {
 
-	TRACE((IOCTL, "ioctl() readtoc for %d tracks\n",
-			stuffp->di.n_last - stuffp->di.n_first + 1));
-
-#if MCDX_DEBUG && IOCTL
 	if (stuffp->toc) {
 		TRACE((IOCTL, "ioctl() toc already read\n"));
 		return 0;
 	}
-#endif
+
+	TRACE((IOCTL, "ioctl() readtoc for %d tracks\n",
+			stuffp->di.n_last - stuffp->di.n_first + 1));
+
+    if (-1 == mcdx_hold(stuffp, 1)) return -1;
 
 	TRACE((IOCTL, "ioctl() tocmode\n"));
 	if (-1 == mcdx_setdrivemode(stuffp, TOC, 1)) return -EIO;
@@ -1321,6 +1438,7 @@
 					&& (q.tno == 0)
 					&& (stuffp->toc[idx - stuffp->di.n_first].index == 0)) {
 				stuffp->toc[idx - stuffp->di.n_first] = q;
+				TRACE((IOCTL, "ioctl() toc idx %d (trk %d)\n", idx, trk));
 				trk--;
 			}
 			if (trk == 0) break;
@@ -1350,40 +1468,109 @@
 	}
 #endif
 
-
 	return 0;
 }
 
+static int
+mcdx_playmsf(struct s_drive_stuff* stuffp, const struct cdrom_msf* msf)
+{
+    unsigned char cmd[7] = {
+        0, 0, 0, 0, 0, 0, 0
+    };
+
+    cmd[0] = stuffp->playcmd;
+    
+    cmd[1] = msf->cdmsf_min0;
+    cmd[2] = msf->cdmsf_sec0;
+    cmd[3] = msf->cdmsf_frame0;
+    cmd[4] = msf->cdmsf_min1;
+    cmd[5] = msf->cdmsf_sec1;
+    cmd[6] = msf->cdmsf_frame1;
+
+    TRACE((IOCTL, "ioctl(): play %x "
+            "%02x:%02x:%02x -- %02x:%02x:%02x\n",
+            cmd[0], cmd[1], cmd[2], cmd[3],
+            cmd[4], cmd[5], cmd[6])); 
+
+    outsb((unsigned int) stuffp->wreg_data, cmd, sizeof cmd);
+
+    if (-1 == mcdx_getval(stuffp, 1*HZ, 0, NULL)) {
+        WARN(("playmsf() timeout\n")); 
+        return -1;
+    }
+
+    stuffp->audiostatus = CDROM_AUDIO_PLAY;
+    return 0;
+}
+
+static int 
+mcdx_playtrk(struct s_drive_stuff* stuffp, const struct cdrom_ti* ti)
+{
+    struct s_subqcode* p;
+    struct cdrom_msf msf;
+
+    if (-1 == mcdx_readtoc(stuffp)) return -1;
+
+    if (ti) p = &stuffp->toc[ti->cdti_trk0 - stuffp->di.n_first];
+    else p = &stuffp->start;
+
+    msf.cdmsf_min0 = p->dt.minute;
+    msf.cdmsf_sec0 = p->dt.second;
+    msf.cdmsf_frame0 = p->dt.frame;
+
+    if (ti) {
+        p = &stuffp->toc[ti->cdti_trk1 - stuffp->di.n_first + 1];
+        stuffp->stop = *p;
+    } else p = &stuffp->stop;
+
+    msf.cdmsf_min1 = p->dt.minute;
+    msf.cdmsf_sec1 = p->dt.second;
+    msf.cdmsf_frame1 = p->dt.frame;
+
+    return mcdx_playmsf(stuffp, &msf);
+}
+
+
 /* Drive functions ************************************************/
 
 static int 
 mcdx_closedoor(struct s_drive_stuff *stuffp, int tries)
 {
 	if (stuffp->present & DOOR)
-		return mcdx_talk(stuffp, "\xf8", 1, NULL, 0, 500, tries);
+		return mcdx_talk(stuffp, "\xf8", 1, NULL, 0, 5*HZ, tries);
 	else
 		return 0;
 }
 
 static int 
 mcdx_stop(struct s_drive_stuff *stuffp, int tries)
-{ return mcdx_talk(stuffp, "\xf0", 1, NULL, 0, 200, tries); }
+{ return mcdx_talk(stuffp, "\xf0", 1, NULL, 0, 2*HZ, tries); }
+
+static int
+mcdx_hold(struct s_drive_stuff *stuffp, int tries)
+{ return mcdx_talk(stuffp, "\x70", 1, NULL, 0, 2*HZ, tries); }
 
 static int
 mcdx_eject(struct s_drive_stuff *stuffp, int tries)
 {
 	if (stuffp->present & DOOR)
-		return mcdx_talk(stuffp, "\xf6", 1, NULL, 0, 500, tries);
+		return mcdx_talk(stuffp, "\xf6", 1, NULL, 0, 5*HZ, tries);
 	else
 		return 0;
 }
 
 static int
-mcdx_requestsubqcode(struct s_drive_stuff *stuffp, struct s_subqcode *sub, int tries)
+mcdx_requestsubqcode(struct s_drive_stuff *stuffp, 
+        struct s_subqcode *sub, 
+        int tries)
 {
 	char buf[11];
 	int ans;
-	ans = mcdx_talk(stuffp, "\x20", 1, buf, sizeof(buf), 200, tries);
+
+	if (-1 == (ans = mcdx_talk(
+            stuffp, "\x20", 1, buf, sizeof(buf),
+            2*HZ, tries))) 
+        return -1;
 	sub->control = buf[1];
 	sub->tno = buf[2];
 	sub->index = buf[3];
@@ -1393,6 +1580,7 @@
 	sub->dt.minute = buf[8];
 	sub->dt.second = buf[9];
 	sub->dt.frame = buf[10];
+
 	return ans;
 }
 
@@ -1403,7 +1591,7 @@
 	int ans;
 
     if (stuffp->present & MULTI) {
-        ans = mcdx_talk(stuffp, "\x11", 1, buf, sizeof(buf), 200, tries);
+        ans = mcdx_talk(stuffp, "\x11", 1, buf, sizeof(buf), 2*HZ, tries);
         multi->multi = buf[1];
         multi->msf_last.minute = buf[2];
         multi->msf_last.second = buf[3];
@@ -1420,7 +1608,7 @@
 {
 	char buf[9];
 	int ans;
-	ans = mcdx_talk(stuffp, "\x10", 1, buf, sizeof(buf), 200, tries);
+	ans = mcdx_talk(stuffp, "\x10", 1, buf, sizeof(buf), 2*HZ, tries);
 	info->n_first = bcd2uint(buf[1]);
 	info->n_last = bcd2uint(buf[2]);
 	info->msf_leadout.minute = buf[3];
@@ -1440,8 +1628,8 @@
 
 	TRACE((HW, "setdrivemode() %d\n", mode));
 
-	if (-1 == (ans = mcdx_talk(stuffp, "\xc2", 1, cmd, sizeof(cmd), 500, tries)))
-		return ans;
+	if (-1 == (ans = mcdx_talk(stuffp, "\xc2", 1, cmd, sizeof(cmd), 5*HZ, tries)))
+		return -1;
 
 	switch (mode) {
 	  case TOC: cmd[1] |= 0x04; break;
@@ -1451,7 +1639,7 @@
 	  default: break;
 	}
 	cmd[0] = 0x50;
-	return mcdx_talk(stuffp, cmd, 2, NULL, 0, 500, tries);
+	return mcdx_talk(stuffp, cmd, 2, NULL, 0, 5*HZ, tries);
 }
 
 
@@ -1466,7 +1654,7 @@
 	  case MODE2: cmd[1] = 0x02; break;
 	  default: return -EINVAL;
 	}
-	return mcdx_talk(stuffp, cmd, 2, NULL, 0, 500, tries);
+	return mcdx_talk(stuffp, cmd, 2, NULL, 0, 5*HZ, tries);
 }
 
 static int
@@ -1481,13 +1669,13 @@
 	cmd[1] = 0x10;		/* irq enable */
 	cmd[2] = 0x05;		/* pre, err irq enable */
 
-	if (-1 == mcdx_talk(stuffp, cmd, 3, NULL, 0, 100, tries))
+	if (-1 == mcdx_talk(stuffp, cmd, 3, NULL, 0, 1*HZ, tries))
 		return -1;
 
 	cmd[1] = 0x02;		/* dma select */
 	cmd[2] = 0x00;		/* no dma */
 
-	return mcdx_talk(stuffp, cmd, 3, NULL, 0, 100, tries);
+	return mcdx_talk(stuffp, cmd, 3, NULL, 0, 1*HZ, tries);
 }
 
 static int
@@ -1496,7 +1684,7 @@
 	char buf[3];
 	int ans;
 
-	if (-1 == (ans = mcdx_talk(stuffp, "\xdc", 1, buf, sizeof(buf), 200, tries)))
+	if (-1 == (ans = mcdx_talk(stuffp, "\xdc", 1, buf, sizeof(buf), 2*HZ, tries)))
 		return ans;
 
 	ver->code = buf[1];
@@ -1512,7 +1700,7 @@
 		outb(0, (unsigned int) stuffp->wreg_chn);		/* no dma, no irq -> hardware */
 		outb(0, (unsigned int) stuffp->wreg_reset);		/* hw reset */
 		return 0;
-	} else return mcdx_talk(stuffp, "\x60", 1, NULL, 0, 500, tries);
+	} else return mcdx_talk(stuffp, "\x60", 1, NULL, 0, 5*HZ, tries);
 }
 
 static int
@@ -1521,13 +1709,29 @@
 	char cmd[2] = { 0xfe };
     if (stuffp->present & DOOR) {
         cmd[1] = lock ? 0x01 : 0x00;
-        return mcdx_talk(stuffp, cmd, sizeof(cmd), NULL, 0, 500, tries);
+        return mcdx_talk(stuffp, cmd, sizeof(cmd), NULL, 0, 5*HZ, tries);
     } else 
         return 0;
 }
 
-#if 0
 static int
 mcdx_getstatus(struct s_drive_stuff *stuffp, int tries)
-{ return mcdx_talk(stuffp, "\x40", 1, NULL, 0, 500, tries); }
-#endif
+{ return mcdx_talk(stuffp, "\x40", 1, NULL, 0, 5*HZ, tries); }
+
+static int
+mcdx_getval(struct s_drive_stuff *stuffp, int to, int delay, char* buf)
+{
+    unsigned long timeout = to + jiffies;
+    char c;
+
+    if (!buf) buf = &c;
+
+    while (inb((unsigned int) stuffp->rreg_status) & MCDX_RBIT_STEN) {
+        if (jiffies > timeout) return -1;
+        mcdx_delay(stuffp, delay);
+    }
+
+    *buf = (unsigned char) inb((unsigned int) stuffp->rreg_data) & 0xff;
+
+    return 0;
+}
diff -u --recursive --new-file v1.3.21/linux/drivers/block/optcd.c linux/drivers/block/optcd.c
--- v1.3.21/linux/drivers/block/optcd.c	Mon Aug 28 14:52:19 1995
+++ linux/drivers/block/optcd.c	Tue Aug 29 11:39:40 1995
@@ -46,6 +46,7 @@
 				copied from sjcd.c, with a few changes.
 				Updated README.optcd. Submitted for
 				inclusion in 1.3.21
+	29-9-95		v0.4a	Fixed bug that prevented compilation as module
 */
 
 #include <linux/major.h>
@@ -1442,7 +1443,7 @@
 
     if ( isp16_config( optcd_port, ISP16_SONY, 0, 0 ) < 0 ) {
       printk( "ISP16 cdrom interface has not been properly configured.\n" );
-      return(mem_start);
+      RETURN_EIO;
     }
   }
 	}
diff -u --recursive --new-file v1.3.21/linux/drivers/block/sbpcd.c linux/drivers/block/sbpcd.c
--- v1.3.21/linux/drivers/block/sbpcd.c	Fri Aug 18 08:44:57 1995
+++ linux/drivers/block/sbpcd.c	Tue Aug 29 10:15:50 1995
@@ -901,14 +901,14 @@
 	int i;
 	
 #ifdef MODULE
-	sbp_sleep(150);
+	sbp_sleep(15*HZ/10);
 	for (i=maxtim_data;i!=0;i--) inb(CDi_status);
 #else
 	if (current == task[0])
 		for (i=maxtim02;i!=0;i--) inb(CDi_status);
 	else 
 	{
-		sbp_sleep(150);
+		sbp_sleep(15*HZ/10);
 		for (i=maxtim_data;i!=0;i--) inb(CDi_status);
 	}
 #endif MODULE
@@ -919,7 +919,7 @@
 	int i,j;
 	
 #ifdef MODULE
-	for(timeout = jiffies + 1000, i=maxtim_data; timeout > jiffies; )
+	for(timeout = jiffies + 10*HZ, i=maxtim_data; timeout > jiffies; )
 	{
 		for ( ;i!=0;i--)
 		{
@@ -928,7 +928,7 @@
 			if (!(j&s_not_result_ready)) return (j);
 			if (fam0L_drive) if (j&s_attention) return (j);
 		}
-		sbp_sleep(1);
+		sbp_sleep(HZ/100);
 		i = 1;
 	}
 #else
@@ -941,7 +941,7 @@
 			if (fam0L_drive) if (j&s_attention) return (j);
 		}
 	else
-		for(timeout = jiffies + 1000, i=maxtim_data; timeout > jiffies; )
+		for(timeout = jiffies + 10*HZ, i=maxtim_data; timeout > jiffies; )
 		{
 			for ( ;i!=0;i--)
 			{
@@ -950,7 +950,7 @@
 				if (!(j&s_not_result_ready)) return (j);
 				if (fam0L_drive) if (j&s_attention) return (j);
 			}
-			sbp_sleep(1);
+			sbp_sleep(HZ/100);
 			i = 1;
 		}
 #endif MODULE
@@ -1015,7 +1015,7 @@
 		}
 	else 
 	{
-		for (i=0,timeout=jiffies+100;i<response_count;i++) 
+		for (i=0,timeout=jiffies+HZ;i<response_count;i++) 
 		{
 			for (j=maxtim_data; ; )
 			{
@@ -1025,7 +1025,7 @@
 					if (!(st&s_not_result_ready)) break;
 				}
 				if ((j!=0)||(timeout<=jiffies)) break;
-				sbp_sleep(1);
+				sbp_sleep(HZ/100);
 				j = 1;
 			}
 			if (timeout<=jiffies) break;
@@ -1170,8 +1170,8 @@
 	else
 	{
 		if (flags_cmd_out & f_respo3) timeout = jiffies;
-		else if (flags_cmd_out & f_respo2) timeout = jiffies + 1600;
-		else timeout = jiffies + 400;
+		else if (flags_cmd_out & f_respo2) timeout = jiffies + 16*HZ;
+		else timeout = jiffies + 4*HZ;
 		j=maxtim_8;
 		do
 		{
@@ -1181,7 +1181,7 @@
 				if (!(i&s_not_result_ready)) break;
 			}
 			if ((j!=0)||(timeout<jiffies)) break;
-			sbp_sleep(1);
+			sbp_sleep(HZ/100);
 			j = 1;
 		}
 		while (1);
@@ -1298,7 +1298,7 @@
 	sti();
 	for (ntries=CMDT_TRIES;ntries>0;ntries--)
 	{
-		if (drvcmd[0]==CMDT_READ_VER) sbp_sleep(100);
+		if (drvcmd[0]==CMDT_READ_VER) sbp_sleep(HZ);
 #if 1
 		OUT(CDo_sel_i_d,0);
 #endif
@@ -1358,7 +1358,7 @@
 				drvcmd[0]=CMDT_READ_ERR;
 				j=cmd_out_T(); /* !!! recursive here !!! */
 				--recursion;
-				sbp_sleep(1);
+				sbp_sleep(HZ/100);
 			}
 			while (j<0);
 			D_S[d].error_state=infobuf[2];
@@ -1373,7 +1373,7 @@
 			return (-D_S[d].error_state-400);
 		}
 		if (drvcmd[0]==CMDT_READ) return (0); /* handled elsewhere */
-		sbp_sleep(10);
+		sbp_sleep(HZ/10);
 		if (ntries>(CMDT_TRIES-50)) continue;
 		msg(DBG_TEA,"cmd_out_T: next CMDT_TRIES (%02X): %d.\n", drvcmd[0], ntries-1);
 	}
@@ -1874,13 +1874,13 @@
 		OUT(CDo_command,CMDT_RESET);
 		for (i=1;i<10;i++) OUT(CDo_command,0);
 	}
-	if (fam0L_drive) sbp_sleep(500); /* wait 5 seconds */
-	else sbp_sleep(100); /* wait a second */
+	if (fam0L_drive) sbp_sleep(5*HZ); /* wait 5 seconds */
+	else sbp_sleep(1*HZ); /* wait a second */
 #if 1
 	if (famT_drive)
 	{
 		msg(DBG_TEA, "================CMDT_RESET given=================.\n");
-		sbp_sleep(300);
+		sbp_sleep(3*HZ);
 	}
 #endif 1
 	flush_status();
@@ -1917,7 +1917,7 @@
 		i=GetStatus();
 		if ((i<0)&&(i!=-615)) return (-2); /* i!=-615 is from sta2err */
 		if (!st_caddy_in) break;
-		sbp_sleep(1);
+		sbp_sleep(HZ/100);
 	}
 	while (!st_diskok);
 #if 000
@@ -2075,7 +2075,7 @@
 	{
 		i=cc_LockDoor(0);
 		--j;
-		sbp_sleep(1);
+		sbp_sleep(HZ/100);
 	}
 	while ((i<0)&&(j));
 	if (i<0)
@@ -2095,7 +2095,7 @@
 	{
 		i=cc_LockDoor(1);
 		--j;
-		sbp_sleep(1);
+		sbp_sleep(HZ/100);
 	}
 	while ((i<0)&&(j));
 	if (j==0)
@@ -2106,7 +2106,7 @@
 		{
 			i=cc_LockDoor(1);
 			--j;
-			sbp_sleep(1);
+			sbp_sleep(HZ/100);
 		}
 		while ((i<0)&&(j));
 	}
@@ -2944,10 +2944,10 @@
 #if 1
 	del_timer(&delay_timer);
 #endif
-	delay_timer.expires=jiffies+110;
+	delay_timer.expires=jiffies+11*HZ/10;
 	timed_out_delay=0;
 	add_timer(&delay_timer);
-	msg(DBG_TIM,"delay timer started (110).\n");
+	msg(DBG_TIM,"delay timer started (11*HZ/10).\n");
 	do
 	{
 		i=inb(CDi_status);
@@ -3109,7 +3109,7 @@
 		if (sbpro_type==1) OUT(CDo_sel_i_d,0);
 #if 0
 		OUT(CDo_reset,0);
-		sbp_sleep(600);
+		sbp_sleep(6*HZ);
 		OUT(CDo_enable,D_S[d].drv_sel);
 #endif 0
 		drvcmd[0]=CMD2_READ_VER;
@@ -3165,7 +3165,7 @@
 					OUT(CDo_command,CMDT_RESET);
 					for (i=0;i<9;i++) OUT(CDo_command,0);
 				}
-				sbp_sleep(50);
+				sbp_sleep(5*HZ/10);
 				OUT(CDo_enable,D_S[d].drv_sel);
 				OUT(CDo_sel_i_d,0);
 				i=inb(CDi_status);
@@ -4142,7 +4142,7 @@
 		msg(DBG_AUD,"read_audio: lba: %d, msf: %06X\n",
 		    block, blk2msf(block));
 		msg(DBG_AUD,"read_audio: before cc_ReadStatus.\n");
-		while (busy_data) sbp_sleep(10); /* wait a bit */
+		while (busy_data) sbp_sleep(HZ/10); /* wait a bit */
 		busy_audio=1;
 		error_flag=0;
 		for (data_tries=5; data_tries>0; data_tries--)
@@ -4156,7 +4156,7 @@
 				flags_cmd_out |= f_respo3;
 				cc_ReadStatus();
 				if (sbp_status() != 0) break;
-				sbp_sleep(1);    /* wait a bit, try again */
+				sbp_sleep(HZ/100);    /* wait a bit, try again */
 			}
 			if (status_tries == 0)
 			{
@@ -4199,7 +4199,7 @@
 			for (frame=1;frame<2 && !error_flag; frame++)
 			{
 				try=maxtim_data;
-				for (timeout=jiffies+900; ; )
+				for (timeout=jiffies+9*HZ; ; )
 				{
 					for ( ; try!=0;try--)
 					{
@@ -4211,7 +4211,7 @@
 					if (try != 0 || timeout <= jiffies) break;
 					if (data_retrying == 0) data_waits++;
 					data_retrying = 1;
-					sbp_sleep(1);
+					sbp_sleep(HZ/100);
 					try = 1;
 				}
 				if (try==0)
@@ -4249,7 +4249,7 @@
 			if (fam0L_drive)
 			{
 				i=maxtim_data;
-				for (timeout=jiffies+900; timeout > jiffies; timeout--)
+				for (timeout=jiffies+9*HZ; timeout > jiffies; timeout--)
 				{
 					for ( ;i!=0;i--)
 					{
@@ -4383,7 +4383,7 @@
 		msg(DBG_INF, "do_request: bad device: %04X\n", CURRENT->dev);
 		goto err_done;
 	}
-	while (busy_audio) sbp_sleep(100); /* wait a bit */
+	while (busy_audio) sbp_sleep(HZ); /* wait a bit */
 	busy_data=1;
 	
 	if (D_S[i].audio_state==audio_playing) goto err_done;
@@ -4566,10 +4566,10 @@
 	error_flag=0;
 	success=0;
 #if LONG_TIMING
-	max_latency=900;
+	max_latency=9*HZ;
 #else
-	if (D_S[d].f_multisession) max_latency=900;
-	else max_latency=300;
+	if (D_S[d].f_multisession) max_latency=9*HZ;
+	else max_latency=3*HZ;
 #endif
 	msg(DBG_TE2,"beginning to READ\n");
 	duration=jiffies;
@@ -4747,7 +4747,7 @@
 	{
 		SBPCD_CLI;
 		i=maxtim_data;
-		for (timeout=jiffies+100; timeout > jiffies; timeout--)
+		for (timeout=jiffies+HZ; timeout > jiffies; timeout--)
 		{
 			for ( ;i!=0;i--)
 			{
@@ -5146,7 +5146,7 @@
 	if (!famL_drive)
 	{
 		OUT(CDo_reset,0);
-		sbp_sleep(100);
+		sbp_sleep(HZ);
 	}
 #endif 0
 
@@ -5190,7 +5190,7 @@
 		    D_S[d].error_byte);
 		if (D_S[d].error_byte==aud_12)
 		{
-			timeout=jiffies+200;
+			timeout=jiffies+2*HZ;
 			do
 			{
 				i=GetStatus();
diff -u --recursive --new-file v1.3.21/linux/drivers/block/sjcd.c linux/drivers/block/sjcd.c
--- v1.3.21/linux/drivers/block/sjcd.c	Mon Jul 31 15:59:01 1995
+++ linux/drivers/block/sjcd.c	Tue Aug 29 10:15:50 1995
@@ -380,13 +380,13 @@
   } else if( --sjcd_status_timeout <= 0 ){
     wake_up( &sjcd_waitq );
   } else {
-    SJCD_SET_TIMER( sjcd_status_timer, 1 );
+    SJCD_SET_TIMER( sjcd_status_timer, HZ/100 );
   }
 }
 
 static int sjcd_wait_for_status( void ){
   sjcd_status_timeout = SJCD_WAIT_FOR_STATUS_TIMEOUT;
-  SJCD_SET_TIMER( sjcd_status_timer, 1 ); 
+  SJCD_SET_TIMER( sjcd_status_timer, HZ/100 );
   sleep_on( &sjcd_waitq );    
   if( sjcd_status_timeout <= 0 )
     printk( "sjcd: Error Wait For Status.\n" );
@@ -1223,7 +1223,7 @@
   /*
    * Get back in some time.
    */
-  SJCD_SET_TIMER( sjcd_poll, 1 );
+  SJCD_SET_TIMER( sjcd_poll, HZ/100 );
 }
 
 static void do_sjcd_request( void ){
@@ -1252,7 +1252,7 @@
 	  }
 	}
 	sjcd_transfer_state = SJCD_S_START;
-	SJCD_SET_TIMER( sjcd_poll, 1 );
+	SJCD_SET_TIMER( sjcd_poll, HZ/100 );
       }
       break;
     }
diff -u --recursive --new-file v1.3.21/linux/drivers/block/triton.c linux/drivers/block/triton.c
--- v1.3.21/linux/drivers/block/triton.c	Mon Aug 28 14:52:19 1995
+++ linux/drivers/block/triton.c	Thu Aug 31 08:09:07 1995
@@ -1,5 +1,5 @@
 /*
- *  linux/drivers/block/triton.c	Version 1.00  Aug 26, 1995
+ *  linux/drivers/block/triton.c	Version 1.01  Aug 28, 1995
  *
  *  Copyright (c) 1995  Mark Lord
  *  May be copied or modified under the terms of the GNU General Public License
@@ -25,8 +25,8 @@
  * for drives which support multi-word DMA mode2 (mword2), or which are
  * recognized as "good" (see table below).  Drives with only mode0 or mode1
  * (single or multi) DMA should also work with this chipset/driver (eg. MC2112A)
- * but are not enabled by default.  Use "hdparm -i" to view supported modes
- * for a given drive.
+ * but are not enabled by default.  Use "hdparm -i" to view modes supported
+ * by a given drive.
  *
  * The hdparm-2.4 (or later) utility can be used for manually enabling/disabling
  * DMA support, but must be (re-)compiled against this kernel version or later.
@@ -45,11 +45,11 @@
  *
  *   Quantum Fireball 1080A (1Gig w/83kB buffer), DMA mode2, PIO mode4.
  *	- DMA mode2 works fine (7.4MB/sec), despite the tiny on-drive buffer.
- *	- This drive also does PIO mode4, slightly slower than DMA mode2.
+ *	- This drive also does PIO mode4, at about the same speed as DMA mode2.
  *
- *   Micropolis MC2112A (1Gig w/512kB buffer), drive pre-dates EIDE, ATA2.
+ *   Micropolis MC2112A (1Gig w/508kB buffer), drive pre-dates EIDE and ATA2.
  *	- DMA works fine (2.2MB/sec), probably due to the large on-drive buffer.
- *	- This older drive can also be tweaked for fastPIO (3,7MB/sec) by using
+ *	- This older drive can also be tweaked for fastPIO (3.7MB/sec) by using
  *	  maximum clock settings (5,4) and setting all flags except prefetch.
  *
  *   Western Digital AC31000H (1Gig w/128kB buffer), DMA mode1, PIO mode3.
@@ -61,8 +61,8 @@
  * Drives like the AC31000H could likely be made to work if all DMA were done
  * one sector at a time, but that would likely negate any advantage over PIO.
  *
- * If you have any drive models add, email your results to:  mlord@bnr.ca
- * Keep an eye on your /var/adm/messages for "DMA disabled" messages.
+ * If you have any drive models to add, email your results to:  mlord@bnr.ca
+ * Keep an eye on /var/adm/messages for "DMA disabled" messages.
  */
 #define _TRITON_C
 #include <linux/config.h>
@@ -114,9 +114,9 @@
 	struct request *rq = HWGROUP(drive)->rq;
 	unsigned short dma_base = HWIF(drive)->dma_base;
 
-	dma_stat = inb(dma_base+2);	/* get DMA status */
+	dma_stat = inb(dma_base+2);		/* get DMA status */
 	outb(inb(dma_base)&~1, dma_base);	/* stop DMA operation */
-	stat = GET_STAT();
+	stat = GET_STAT();			/* get drive status */
 	if (OK_STAT(stat,DRIVE_READY,drive->bad_wstat|DRQ_STAT)) {
 		if ((dma_stat & 7) == 4) {	/* verify good DMA status */
 			rq = HWGROUP(drive)->rq;
@@ -267,21 +267,18 @@
 }
 
 /*
- * ide_init_triton() uses the PCI BIOS to scan for a Triton i82371FB chip,
- * and prepares the IDE driver for DMA operation if one is found.
- * This routine is called from ide.c during driver initialization.
+ * ide_init_triton() prepares the IDE driver for DMA operation.
+ * This routine is called once, from ide.c during driver initialization,
+ * for each triton chipset which is found (unlikely to be more than one).
  */
-void ide_init_triton (ide_hwif_t  hwifs[])
+void ide_init_triton (byte bus, byte fn)
 {
 	int rc = 0, h;
 	unsigned short bmiba, pcicmd;
 	unsigned int timings;
-	unsigned char bus, fn;
-
-	if (pcibios_find_device (PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371, 0, &bus, &fn))
-		goto quit;
-	++fn;	/* IDE is second function on this chip */
+	extern ide_hwif_t ide_hwifs[];
 
+	++fn;	/* IDE interface is 2nd function on this device */
 	/*
 	 * See if IDE and BM-DMA features are enabled:
 	 */
@@ -319,7 +316,7 @@
 	 * Save the dma_base port addr for each interface
 	 */
 	for (h = 0; h < MAX_HWIFS; ++h) {
-		ide_hwif_t *hwif = &hwifs[h];
+		ide_hwif_t *hwif = &ide_hwifs[h];
 		unsigned short base, time;
 		if (hwif->io_base == 0x1f0 && (timings & 0x8000)) {
 			time = timings & 0xffff;
diff -u --recursive --new-file v1.3.21/linux/drivers/char/README.scc linux/drivers/char/README.scc
--- v1.3.21/linux/drivers/char/README.scc	Tue Jun  6 11:22:05 1995
+++ linux/drivers/char/README.scc	Tue Aug 29 07:12:05 1995
@@ -1,36 +1,48 @@
+// 950824: note -- I will upload the new version 1.9 to ftp.ucsd.edu
+//         as soon as possible... 
+//
+// ****** The driver has it's own MAJOR number (22) now! ******
+//
+// please remake /dev/sc*:
+//
+// mknod /dev/sc1 c 22 0
+// mknod /dev/sc2 c 22 1
+// mknod /dev/sc3 c 22 2
+// mknod /dev/sc4 c 22 3
+//
+// (and so on...)
+//
+// -dl1bke-
+
 This is a subset of the documentation. To use this driver you MUST have the
 full package from:
 
 Internet:
 =========
 
-ftp.ucsd.edu:/hamradio/packet/tcpip/incoming/z8530drv-1.8.dl1bke.tar.gz
+ftp.ucsd.edu:/hamradio/packet/tcpip/incoming/z8530drv-1.9.dl1bke.tar.gz
+
+[
+  if you can't find it there, try:
+  .../tcpip/linux/z8530drv-1.9.dl1bke.tar.gz
+
+]
 
 and various mirrors (i.e. nic.switch.ch)
 
 AX.25 BBS
 =========
 
-UNIX @ DB0ACH.#NRW.DEU.EU, subject: Z8530D18.Pxx/Pyy
+UNIX @ DB0ACH.#NRW.DEU.EU, subject: Z8530D19.Pxx/Pyy
 
 (AX.25 call: DB0ACH-8)
 
 and various BBS that received the file through AUTO7P or 7PSERV
-with the filename Z8530D18.TGZ
+with the filename Z8530D19.TGZ
 
 
 ---------------------------------------------------------------------------
 
-!! Version 1.8
-!!
-!! Deutscher Text siehe scc_ger.doc
-!! 
-!! perhaps somebody could correct the English documentation (grammar,
-!! spelling)?
-!!
-!! BTW: REAL programmers don't document...
-!!
-
 
 	 SCC.C - Linux driver for Z8530 based HDLC cards for AX.25      
 
@@ -763,6 +775,7 @@
 And always remember: 
 The 1.1.* kernel series is for alpha tests -- use at your own risk ;-)
 The 1.2.* series should run reliable. This driver perhaps NOT!
+The 1.3.* kernel series is for alpha tests again... you get the idea!
 
 ------------
 
@@ -927,7 +940,12 @@
 the on-board baudrate generator is not supported.
 
 *****************
-
-
 (mni tnx to Mike Bilow)
+
  
+...an many thanks to Linus Torvalds and Alan Cox for including the driver
+   in the LinuX standard distribution...
+
+Joerg Reuter	ampr-net: dl1bke@db0pra.ampr.org
+		AX-25   : DL1BKE @ DB0ACH.#NRW.DEU.EU
+		Internet: jreuter@lykos.tng.oche.de
diff -u --recursive --new-file v1.3.21/linux/drivers/char/README.unicode linux/drivers/char/README.unicode
--- v1.3.21/linux/drivers/char/README.unicode	Tue Jun 13 15:40:16 1995
+++ linux/drivers/char/README.unicode	Thu Jan  1 02:00:00 1970
@@ -1,49 +0,0 @@
-The Linux kernel code has been rewritten to use Unicode to map
-characters to fonts.  By downloading a single Unicode-to-font table,
-both the eight-bit character sets and UTF-8 mode are changed to use
-the font as indicated.
-
-This changes the semantics of the eight-bit character tables subtly.
-The four character tables are now:
-
-Map symbol	Map name			Escape code (G0)
-
-LAT1_MAP	Latin-1 (ISO 8859-1)		ESC ( B
-GRAF_MAP	DEC VT100 pseudographics	ESC ( 0
-IBMPC_MAP	IBM code page 437		ESC ( U
-USER_MAP	User defined			ESC ( K
-
-In particular, ESC ( U is no longer "straight to font", since the font
-might be completely different than the IBM character set.  This
-permits for example the use of block graphics even with a Latin-1 font
-loaded.
-
-In accordance with the Unicode standard/ISO 10646 the range U+F000 to
-U+F8FF has been reserved for OS-wide allocation (the Unicode Standard
-refers to this as a "Corporate Zone").  U+F000 was picked as the
-starting point since it lets the direct-mapping area start on a large
-power of two (in case 1024- or 2048-character fonts ever become
-necessary).  This leaves U+E000 to U+EFFF as End User Zone.
-
-The Unicodes in the range U+F000 to U+F1FF have been hard-coded to map
-directly to the loaded font, bypassing the translation table.  The
-user-defined map now defaults to U+F000 to U+F1FF, emulating the
-previous behaviour.
-
-In addition, the following characters not present in Unicode 1.1.4 (at
-least, I have not found them!) have been defined; these are used by
-the DEC VT graphics map:
-
-U+F800 DEC VT GRAPHICS HORIZONTAL LINE SCAN 1
-U+F801 DEC VT GRAPHICS HORIZONTAL LINE SCAN 3
-U+F803 DEC VT GRAPHICS HORIZONTAL LINE SCAN 7
-U+F804 DEC VT GRAPHICS HORIZONTAL LINE SCAN 9
-
-The DEC VT220 uses a 6x10 character matrix, and these characters form
-a smooth progression in the DEC VT graphics character set.  I have
-omitted the scan 5 line, since it is also used as a block-graphics
-character, and hence has been coded as U+2500 FORMS LIGHT HORIZONTAL.
-However, I left U+F802 blank should the need arise.  
-
-	H. Peter Anvin <Peter.Anvin@linux.org>
-	Yggdrasil Computing, Inc.
diff -u --recursive --new-file v1.3.21/linux/drivers/char/console.c linux/drivers/char/console.c
--- v1.3.21/linux/drivers/char/console.c	Tue Aug  8 12:31:34 1995
+++ linux/drivers/char/console.c	Fri Sep  1 08:26:08 1995
@@ -2030,7 +2030,7 @@
 	timer_table[BLANK_TIMER].fn = blank_screen;
 	timer_table[BLANK_TIMER].expires = 0;
 	if (blankinterval) {
-		timer_table[BLANK_TIMER].expires = jiffies+blankinterval;
+		timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
 		timer_active |= 1<<BLANK_TIMER;
 	}
 
@@ -2051,7 +2051,8 @@
 			video_type = VIDEO_TYPE_MDA;
 			video_mem_term = 0xb2000;
 			display_desc = "*MDA";
-			request_region(0x3b0,16,"mda");
+			request_region(0x3b0,12,"mda");
+			request_region(0x3bf, 1,"mda");
 		}
 	}
 	else				/* If not, it is color. */
diff -u --recursive --new-file v1.3.21/linux/drivers/char/cyclades.c linux/drivers/char/cyclades.c
--- v1.3.21/linux/drivers/char/cyclades.c	Wed Aug  2 13:21:00 1995
+++ linux/drivers/char/cyclades.c	Tue Aug 29 10:15:51 1995
@@ -1025,13 +1025,13 @@
 	 * Delay for 0.1 seconds -- we use a busy loop since this may 
 	 * occur during the bootup sequence
 	 */
-	timeout = jiffies+10;
+	timeout = jiffies+HZ/10;
 	while (timeout >= jiffies)
 	    ;
 	
 	cy_triggered = 0;	/* Reset after letting things settle */
 
-	timeout = jiffies+10;
+	timeout = jiffies+HZ/10;
 	while (timeout >= jiffies)
 		;
 	
@@ -1072,7 +1072,7 @@
 	base_addr[CySRER] |= CyTxMpty;
     sti();
     
-    timeout = jiffies+2;
+    timeout = jiffies+2*HZ/100;
     while (timeout >= jiffies) {
 	if (cy_irq_triggered)
 	    break;
@@ -2302,7 +2302,7 @@
     if (info->flags & ASYNC_CALLOUT_ACTIVE)
 	info->callout_termios = *tty->termios;
     if (info->flags & ASYNC_INITIALIZED)
-	tty_wait_until_sent(tty, 3000); /* 30 seconds timeout */
+	tty_wait_until_sent(tty, 30*HZ); /* 30 seconds timeout */
     shutdown(info);
     if (tty->driver.flush_buffer)
 	tty->driver.flush_buffer(tty);
diff -u --recursive --new-file v1.3.21/linux/drivers/char/lp.c linux/drivers/char/lp.c
--- v1.3.21/linux/drivers/char/lp.c	Mon Aug 28 14:52:19 1995
+++ linux/drivers/char/lp.c	Tue Aug 29 10:15:51 1995
@@ -409,7 +409,7 @@
 		return -ENODEV;
 	switch ( cmd ) {
 		case LPTIME:
-			LP_TIME(minor) = arg;
+			LP_TIME(minor) = arg * HZ/100;
 			break;
 		case LPCHAR:
 			LP_CHAR(minor) = arg;
diff -u --recursive --new-file v1.3.21/linux/drivers/char/mem.c linux/drivers/char/mem.c
--- v1.3.21/linux/drivers/char/mem.c	Wed Aug  2 13:21:00 1995
+++ linux/drivers/char/mem.c	Tue Aug 29 10:15:51 1995
@@ -42,7 +42,7 @@
 
 	if (count < 0)
 		return -EINVAL;
-	if (p >= high_memory)
+	if (MAP_NR(p) >= MAP_NR(high_memory))
 		return 0;
 	if (count > high_memory - p)
 		count = high_memory - p;
@@ -67,7 +67,7 @@
 
 	if (count < 0)
 		return -EINVAL;
-	if (p >= high_memory)
+	if (MAP_NR(p) >= MAP_NR(high_memory))
 		return 0;
 	if (count > high_memory - p)
 		count = high_memory - p;
diff -u --recursive --new-file v1.3.21/linux/drivers/char/psaux.c linux/drivers/char/psaux.c
--- v1.3.21/linux/drivers/char/psaux.c	Wed Aug  2 13:21:00 1995
+++ linux/drivers/char/psaux.c	Tue Aug 29 10:15:51 1995
@@ -72,7 +72,11 @@
 #define AUX_RESET	0xff		/* reset aux device */
 
 #define MAX_RETRIES	60		/* some aux operations take long time*/
-#define AUX_IRQ		12
+#if defined(__alpha__) && !defined(CONFIG_PCI)
+# define AUX_IRQ	9		/* Jensen is odd indeed */
+#else
+# define AUX_IRQ	12
+#endif
 #define AUX_BUF_SIZE	2048
 
 /* 82C710 definitions */
@@ -200,6 +204,9 @@
 	int head = queue->head;
 	int maxhead = (queue->tail-1) & (AUX_BUF_SIZE-1);
 
+	if ((inb(AUX_STATUS) & AUX_OBUF_FULL) != AUX_OBUF_FULL)
+		return;
+
 	queue->buf[head] = inb(AUX_INPUT_PORT);
 	if (head != maxhead) {
 		head++;
@@ -502,6 +509,7 @@
 	}
 	queue = (struct aux_queue *) kmem_start;
 	kmem_start += sizeof (struct aux_queue);
+	memset(queue, 0, sizeof(*queue));
 	queue->head = queue->tail = 0;
 	queue->proc_list = NULL;
 	if (!qp_found) {
diff -u --recursive --new-file v1.3.21/linux/drivers/char/scc.c linux/drivers/char/scc.c
--- v1.3.21/linux/drivers/char/scc.c	Tue Aug  8 12:31:34 1995
+++ linux/drivers/char/scc.c	Thu Aug 31 08:09:05 1995
@@ -1,54 +1,107 @@
 #include <linux/autoconf.h>	/* fastest method */
 #ifdef CONFIG_SCC
 
+#define RCS_ID "$Id: scc.c,v 1.25 1995/08/24 21:05:00 jreuter Exp jreuter $"
 
-#define BANNER "Z8530 SCC driver v1.8.17test.17.7.95 PE1AYX (c)\n"
+#define BANNER "Z8530 SCC driver v1.9.dl1bke (beta) by dl1bke\n"
 
-/* ******************************************************************** */
-/* *   SCC.C - Linux driver for Z8530 based HDLC cards for AX.25      *	*/ 
-/* ******************************************************************** */
+/*
 
-/* ********************************************************************
+   ********************************************************************
+   *   SCC.C - Linux driver for Z8530 based HDLC cards for AX.25      *
+   ********************************************************************
 
-	(c) Hans Alblas PE1AYX 1993,1994,1995
-	          Released for GNU
-	portions (c) 1995 by Joerg Reuter DL1BKE
-	         (c) 1993 Guido ten Dolle PE1NNZ
 
+   ********************************************************************
 
-   ********************************************************************	*/   
+	(c) 1993 - 1995 by Joerg Reuter DL1BKE
 
-/*
+	portions (c) 1994 Hans Alblas PE1AYX 
+	and      (c) 1993 Guido ten Dolle PE1NNZ
+
+   ********************************************************************
+   
+   The driver and the programs in this archive are UNDER CONSTRUCTION.
+   The code is likely to fail, and so your kernel could --- even 
+   a whole network. 
+
+   This driver is intended for Amateur Radio use. If you are running it
+   for commercial purposes, please drop me a note. I am nosy...
+
+   ...BUT:
+ 
+   ! You  m u s t  recognize the appropriate legislations of your country !
+   ! before you connect a radio to the SCC board and start to transmit or !
+   ! receive. The GPL allows you to use the  d r i v e r,  NOT the RADIO! !
+
+   For non-Amateur-Radio use please note that you might need a special
+   allowance/licence from the designer of the SCC Board and/or the
+   MODEM. 
+
+   This program is free software; you can redistribute it and/or modify 
+   it under the terms of the (modified) GNU General Public License 
+   delivered with the LinuX kernel source.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should find a copy of the GNU General Public License in 
+   /usr/src/linux/COPYING; 
+   
+   ******************************************************************** 
 
 
-   931100	- started with the projekt pe1ayx
-   9406??	- KISS-parameter setting and BayCom USCC support dl1bke
-   940613	- fixed memory leak ,main memory fragmentation problem,
-                  speeded up the interupt routines ,has now its own
-                  memory buffer pool and source cleanup. pe1ayx
-   940620	- bug fixed in line disipline change ,local ringbuf
-   		  reorganisation ,and some little bugfixes.
-   940715	- first release to the public (scc15b.tgz) pe1ayx		                
+   ...If you find any portions of the code that are copyrighted to you,
+   and you don't want to see in here, please send me a private (!) 
+   message to my internet site. I will change it as soon as possible. 
+   Please don't flame to the tcp-group or anywhere else. Thanks!
+
+   Joerg Reuter	ampr-net: dl1bke@db0pra.ampr.org
+		AX-25   : DL1BKE @ DB0ACH.#NRW.DEU.EU
+		Internet: jreuter@lykos.tng.oche.de
+		
+		
+   History of z8530drv:
+   --------------------
+
+   940913	- started to write the driver, rescued most of my own
+		  code (and Hans Alblas' memory buffer pool concept) from 
+		  an earlier project "sccdrv" which was initiated by 
+		  Guido ten Dolle. Not much of the old driver survived, 
+		  though. The first version I put my hands on was sccdrv1.3
+		  from August 1993. The memory buffer pool concept
+		  appeared in an unauthorized sccdrv version (1.5) from
+		  August 1994.
+
+   950131	- changed copyright notice to GPL without limitations.
+   
    950228	- (hopefully) fixed the reason for kernel panics in
-                  chk_rcv_queue() [stupid error] dl1bke
-   950229       - buffer timeout for vergotten buffer :-( pe1ayx                
-   950304       - fixed underrun/zcount handling dl1bke
-   950305	- the driver registers port addresses now dl1bke
-   950314	- fixed underrun interrupt handling again dl1bke
-   950514	- fixed slip tty wakeup (it wil now work again with kernel ax25)pe1ayx
-   950703	- rewrote the 8530 init/reset routines pe1ayx
-   950712	- rewrote the RXirq + buffering routines pe1ayx
-   950716	- It can now handle ax25 rx frame info > 256
-   O		- rewrite TX + buffering (there is a little mem leak ,but
-                  wil not be dangerous since my buffer timeout routine
-                  wil put back vergotten buffers in the queue pe1ayx
-   O		- change the tty i/o so that the tty wakeup is handled properly
-           	  pe1ayx
+                  chk_rcv_queue() [stupid error]
+                  
+   950304       - fixed underrun/zcount handling
+   
+   950305	- the driver registers port addresses now
+   
+   950314	- fixed underrun interrupt handling again
    
+   950512	- (hope to have) fixed hidden re-entrance problem
+   		  in scc_timer()
+   		  
+   950824	- received frames will be sent to the application
+   		  faster, clean-up of z8530_init()
+
    Thanks to:
-   DL1BKE Joerg - for some good ideas
+   ----------
+   
    PE1CHL Rob	- for a lot of good ideas from his SCC driver for DOS
    PE1NNZ Guido - for his port of the original driver to Linux
+   KA9Q   Phil  - from whom we stole the mbuf-structure
+   PA3AYX Hans  - who rewrote parts of the memory management and some 
+   		  minor, but nevertheless useful changes
+   DL8MBT Flori - for support
+   DG0FT  Rene  - for the BayCom USCC support
    PA3AOU Harry - for ESCC testing, information supply and support
    
    PE1KOX Rob, DG1RTF Thomas, ON5QK Roland, 
@@ -56,10 +109,18 @@
    and all who sent me bug reports and ideas... 
    
    
-      
+   NB -- if you find errors, change something, please let me know
+      	 first before you distribute it... And please don't touch
+   	 the version number. Just replace my callsign in
+   	 "v1.9.dl1bke" with your own. Just to avoid confusion...
+   	 
+   If you want to add your modification to the linux distribution
+   please (!) contact me first.
+   	  
+   Jörg Reuter DL1BKE
+  
 */
 
-
 #include <linux/errno.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
@@ -87,8 +148,17 @@
 #include <asm/segment.h>
 #include <asm/bitops.h>
 
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <time.h>
 #include <linux/kernel.h>
 
+#ifndef Z8530_MAJOR
+#define Z8530_MAJOR 22
+#endif
+
+long scc_init(long kmem_start);
 
 int scc_open(struct tty_struct *tty, struct file *filp);
 static void scc_close(struct tty_struct *tty, struct file *filp);
@@ -108,6 +178,8 @@
 static void z8530_init(void);
 
 static void scc_change_speed(struct scc_channel *scc);
+static void kiss_encode(struct scc_channel *scc);
+
 static void init_channel(struct scc_channel *scc);
 static void scc_key_trx (struct scc_channel *scc, char tx);
 static void scc_txint(register struct scc_channel *scc);
@@ -117,23 +189,16 @@
 static void scc_isr(int irq, struct pt_regs *regs);
 static void scc_timer(void);
 static void scc_init_timer(struct scc_channel *scc);
+static void scc_rx_timer(void);
 
 /* from serial.c */
 
-#ifndef MIN
-#define MIN(a,b)	((a) < (b) ? (a) : (b))
-#endif
-
-static unsigned char *tmp_buf = 0;
-static struct semaphore tmp_buf_sem = MUTEX;
-static unsigned int start_controle;
-
 static int baud_table[] = {
 	0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
 	9600, 19200, 38400, 57600, 115200, 0 };
 
 
-struct tty_driver scc_driver;		    /* new in 1.1.xx */
+struct tty_driver scc_driver;
 static int scc_refcount;
 static struct tty_struct *scc_table[2*MAXSCC];
 static struct termios scc_termios[2 * MAXSCC];
@@ -146,8 +211,7 @@
 static struct sccbuf *sccfreelist[MAX_IBUFS] = {0};
 static int allocated_ibufs = 0;
 
-#define SERIAL_TYPE_NORMAL	1
-
+static struct rx_timer_CB rx_timer_cb;
 
 /* ******************************************************************** */
 /* *			Port Access Functions			      * */
@@ -203,6 +267,10 @@
 /* * 			Memory Buffer Management			*/
 /* ******************************************************************** */
 
+/* mbuf concept lent from KA9Q. Tnx PE1AYX for the buffer pool concept	*/
+/* (sorry, do you have any better ideas?) */
+
+
 /* allocate memory for the interrupt buffer pool */
 
 void scc_alloc_buffer_pool(void)
@@ -211,8 +279,6 @@
 	struct sccbuf *sccb;
 	struct mbuf   *bp;
 	
-	start_controle = 0;
-	
    	for (i = 0 ; i < MAX_IBUFS ; i++)
    	{
    		sccb = (struct sccbuf *)kmalloc(sizeof(struct sccbuf), GFP_ATOMIC);
@@ -290,7 +356,6 @@
 			sccfreelist[i]->bp->refcnt = 1;
 			sccfreelist[i]->bp->cnt = 0;
 			sccfreelist[i]->bp->in_use = 0;
-			sccfreelist[i]->bp->time_out = CURRENT_TIME + 300;
 		
 			restore_flags(flags);
 			return sccfreelist[i]->bp;
@@ -319,33 +384,7 @@
 		
 	save_flags(flags); cli();
 	bpnext = bp->next;
-/*=========================================================================*/	
-/*==      THIS IS A LITTLE ROUTINE TO FIX THE TX MEM LEAK                ==*/
-/*==             UNTIL I HAVE REWRITE THE TX ROUTINES                    ==*/
-/*==                 PE1AYX@PI8HRL.AMPR.ORG                              ==*/
-/*=========================================================================*/
-
-	 start_controle++;
-	 if(start_controle > 100){
-	  if(bp->type == BT_TRANSMIT){
-	    start_controle = 0;
-	    for(i = 0 ; i < allocated_ibufs ; i++)
-	    {
-	       if(sccfreelist[i]->inuse == 1)
-	        if(sccfreelist[i]->bp->type == BT_TRANSMIT)
-	         if(sccfreelist[i]->bp->time_out < CURRENT_TIME)
-		    {
-			sccfreelist[i]->bp->cnt = 0;
-			sccfreelist[i]->bp->refcnt = 0;
-			sccfreelist[i]->inuse = 0;
-		    }
- 	     }
-           } 
-	 }
-/*=========================================================================*/
-/*==                END OF THAT SILLY STUPID ROUTINE                     ==*/
-/*=========================================================================*/	 
-
+	
 	if (bp->dup)
 	{
 		for(i = 0 ; i < allocated_ibufs ; i++)
@@ -412,7 +451,7 @@
 	abp = bp->anext;
 	while (bp) bp = scc_return_buffer(bp, type);
 		
-	restore_flags(flags); cli();
+	restore_flags(flags);
 	return abp;
 }
 
@@ -512,13 +551,13 @@
 	
 	if (Vector_Latch)
 	{
-	    	while(1)
+	    	while(1)			   /* forever...? */
     		{ 
 			Outb(Vector_Latch, 0);      /* Generate INTACK */
         
 			/* Read the vector */
-			if((vector=Inb(Vector_Latch)) >= 16 * Nchips)
-				break; 
+			if((vector=Inb(Vector_Latch)) >= 16 * Nchips) break; 
+						/* ...not forever! */
           
 			/* Extract channel number and status from vector. */
 			/* Isolate channel nummer */
@@ -650,20 +689,39 @@
 /* Throw away received mbuf(s) when an error occurred */
 
 static inline void
+scc_toss_buffer(register struct scc_channel *scc)
+{
+	register struct mbuf *bp;
+	
+	if((bp = scc->rbp) != NULLBUF)
+	{
+		scc_free_chain(bp->next, BT_RECEIVE);
+		bp->next = NULLBUF;
+		scc->rbp1 = bp;         /* Don't throw this one away */
+		bp->cnt = 0;            /* Simply rewind it */
+		bp->in_use = 0;
+	}
+}
+
+static inline void
 flush_FIFO(register struct scc_channel *scc)
 {
 	register int k;
 	
 	for (k=0; k<3; k++)
 		Inb(scc->data);
-
-	if(scc->rxbufcnt > 0)
+		
+	if(scc->rbp != NULLBUF)	/* did we receive something? */
 	{
-		scc->stat.rxerrs++;
-		scc->rxbufcnt = 0;         /* throw away frame */
+		if(scc->rbp->next != NULLBUF || scc->rbp->cnt > 0)
+			scc->stat.rxerrs++;  /* then count it as an error */
+			
+		scc_toss_buffer(scc);         /* throw away buffer */
 	}
 }
 
+
+
 /* External/Status interrupt handler */
 static void
 scc_exint(register struct scc_channel *scc)
@@ -741,7 +799,7 @@
 static void
 scc_rxint(register struct scc_channel *scc)
 {
-	unsigned char ch;
+	register struct mbuf *bp;
 
 	scc->stat.rxints++;
 
@@ -752,120 +810,98 @@
 		return;
 	}
 
-	if (scc->rxbufcnt > 2044)		/* no buffer available? */
-	{
-		Inb(scc->data);		/* discard character */
-		or(scc,R3,ENT_HM);      /* enter hunt mode */
-		scc->rxbufcnt = 0;	/* throw away frame */
-		scc->stat.nospace++;    /* and count this error */
-		return;
+	if ((bp = scc->rbp1) == NULLBUF || bp->cnt >= bp->size)	
+	{ 				/* no buffer available or buffer full */
+		if (scc->rbp == NULLBUF)
+		{
+			if ((bp = scc_get_buffer(BT_RECEIVE)) != NULLBUF)
+				scc->rbp = scc->rbp1 = bp;
+				
+		}
+		else if ((bp = scc_get_buffer(BT_RECEIVE)))
+		{
+			scc_append_to_chain(&scc->rbp, bp);
+			scc->rbp1 = bp;
+		}
+		
+		if (bp == NULLBUF)		/* no buffer available? */
+		{
+			Inb(scc->data);		/* discard character */
+			or(scc,R3,ENT_HM);      /* enter hunt mode */
+			scc_toss_buffer(scc);	/* throw away buffers */
+			scc->stat.nospace++;    /* and count this error */
+			return;
+		}
 	}
 
-	if(scc->rxbufcnt == 0) /* make begin of kissframe */
-	{
-		scc->rxbuf[scc->rxbufcnt++] = FEND;
-		if (scc->kiss.not_slip)
-			scc->rxbuf[scc->rxbufcnt++] = 0;
-	}
+	/* now, we have a buffer. read character and store it */
+	bp->data[bp->cnt++] = Inb(scc->data);
+}
+
+/* kick rx_timer (try to send received frame or part of it ASAP) */
+/* !experimental! */
+
+static inline void
+kick_rx_timer(register struct scc_channel *scc)
+{
+	register unsigned long expires;
 
-	switch( ch = Inb(scc->data) )
+	if (!rx_timer_cb.lock)
 	{
-		case FEND:
-			scc->rxbuf[scc->rxbufcnt++] = FESC;
-			scc->rxbuf[scc->rxbufcnt++] = TFEND;
-			break;
-		case FESC:
-			scc->rxbuf[scc->rxbufcnt++] = FESC;
-			scc->rxbuf[scc->rxbufcnt++] = TFESC;
-			break;
-		default:
-			scc->rxbuf[scc->rxbufcnt++] = ch;
-	}
+		expires = timer_table[SCC_TIMER].expires - jiffies;
 
+		rx_timer_cb.expires = (expires > 1)? expires:1;
+		rx_timer_cb.scc = scc;
+		rx_timer_cb.lock = 1;
+	
+		timer_table[SCC_TIMER].fn = scc_rx_timer;
+		timer_table[SCC_TIMER].expires = jiffies + 1;
+		timer_active |= 1 << SCC_TIMER;
+	}
 }
 
-
 /* Receive Special Condition interrupt handler */
 static void
 scc_spint(register struct scc_channel *scc)
 {
 	register unsigned char status;
-	int i;
-	unsigned char	*cp;
-	char		*fp;
-	int		count;
-
+	register struct mbuf *bp;
 
 	scc->stat.spints++;
 
-	status = InReg(scc->ctrl,R1);		/* read Special Receive Condition status */
+	status = InReg(scc->ctrl,R1);		/* read receiver status */
 	
-	Inb(scc->data);				/* read byte */
+	Inb(scc->data);				/* throw away Rx byte */
 
-	if(status & Rx_OVR)			/* RX_OVerRrun? */
+	if(status & Rx_OVR)			/* receiver overrun */
 	{
-		scc->stat.rx_over++;
-		or(scc,R3,ENT_HM);              /* enter hunt mode */
-		scc->rxbufcnt = 0;              /* rewind the buffer */
+		scc->stat.rx_over++;                /* count them */
+		or(scc,R3,ENT_HM);              /* enter hunt mode for next flag */
+		scc_toss_buffer(scc);                 /* rewind the buffer and toss */
 	}
 	
-	if(status & END_FR && scc->rxbufcnt != 0)	/* END of FRame */
+	if(status & END_FR && scc->rbp != NULLBUF)	/* end of frame */
 	{
-		if (!(status & CRC_ERR) && (status & 0xe) == RES8 && scc->rxbufcnt > 0)
+		/* CRC okay, frame ends on 8 bit boundary and received something ? */
+		
+		if (!(status & CRC_ERR) && (status & 0xe) == RES8 && scc->rbp->cnt)
 		{
-		   scc->rxbufcnt--;	/*strip the CRC */
-  		   scc->rxbuf[scc->rxbufcnt++] = FEND;
-
-		   for(i = 0 ; i < scc->rxbufcnt ; i++)
-			{
-			if((scc->tty->flip.count + 1) < TTY_FLIPBUF_SIZE)
-				tty_insert_flip_char(scc->tty, scc->rxbuf[i], 0);
-			else    {
-				if (scc->tty->flip.buf_num) {
-					cp = scc->tty->flip.char_buf + TTY_FLIPBUF_SIZE;
-					fp = scc->tty->flip.flag_buf + TTY_FLIPBUF_SIZE;
-					scc->tty->flip.buf_num = 0;
-					scc->tty->flip.char_buf_ptr = scc->tty->flip.char_buf;
-					scc->tty->flip.flag_buf_ptr = scc->tty->flip.flag_buf;
-				} else {
-					cp = scc->tty->flip.char_buf;
-					fp = scc->tty->flip.flag_buf;
-					scc->tty->flip.buf_num = 1;
-					scc->tty->flip.char_buf_ptr = scc->tty->flip.char_buf + TTY_FLIPBUF_SIZE;
-					scc->tty->flip.flag_buf_ptr = scc->tty->flip.flag_buf + TTY_FLIPBUF_SIZE;
-					}
-				count = scc->tty->flip.count;
-				scc->tty->flip.count = 0;
-				scc->tty->ldisc.receive_buf(scc->tty, cp, fp, count);
-				tty_insert_flip_char(scc->tty, scc->rxbuf[i], 0);
-				}
-			}
-
-		if (scc->tty->flip.buf_num) {
-			cp = scc->tty->flip.char_buf + TTY_FLIPBUF_SIZE;
-			fp = scc->tty->flip.flag_buf + TTY_FLIPBUF_SIZE;
-			scc->tty->flip.buf_num = 0;
-			scc->tty->flip.char_buf_ptr = scc->tty->flip.char_buf;
-			scc->tty->flip.flag_buf_ptr = scc->tty->flip.flag_buf;
-		} else {
-			cp = scc->tty->flip.char_buf;
-			fp = scc->tty->flip.flag_buf;
-			scc->tty->flip.buf_num = 1;
-			scc->tty->flip.char_buf_ptr = scc->tty->flip.char_buf + TTY_FLIPBUF_SIZE;
-			scc->tty->flip.flag_buf_ptr = scc->tty->flip.flag_buf + TTY_FLIPBUF_SIZE;
-			}
-		count = scc->tty->flip.count;
-		scc->tty->flip.count = 0;
-		scc->tty->ldisc.receive_buf(scc->tty, cp, fp, count);
-		scc->stat.rxframes++;
-
-		scc->rxbufcnt = 0;
+			/* ignore last received byte (first of the CRC bytes) */
 			
-		} else {
-			scc->rxbufcnt = 0;		/* frame is not good */
+			for (bp = scc->rbp; bp->next != NULLBUF; bp = bp->next) ;
+				bp->cnt--;              /* last byte is first CRC byte */
+				
+			scc_enqueue(&scc->rcvq,scc->rbp);
+			scc->rbp = scc->rbp1 = NULLBUF;
+			scc->stat.rxframes++;
+			scc->stat.rx_queued++;
+			kick_rx_timer(scc);
+		} else {				/* a bad frame */
+			scc_toss_buffer(scc);		/* throw away frame */
 			scc->stat.rxerrs++;
-	  		}		
+		}
 	}
+	
 	Outb(scc->ctrl,ERR_RES);
 }
 
@@ -919,7 +955,6 @@
 	wr(scc,R5,Tx8|DTR|TxCRC_ENAB);	/* TX 8 bits/char, disabled, DTR */
 	wr(scc,R6,0);			/* SDLC address zero (not used) */
 	wr(scc,R7,FLAG);		/* SDLC flag value */
-	wr(scc,R9,VIS);			/* vector includes status */
 	wr(scc,R10,(scc->modem.nrz? NRZ : NRZI)|CRCPS|ABUNDER); /* abort on underrun, preset CRC generator, NRZ(I) */
 	wr(scc,R14, 0);
 
@@ -990,7 +1025,7 @@
 	Outb(scc->ctrl,RES_EXT_INT);	/* must be done twice */
 	
 	scc->status = InReg(scc->ctrl,R0);	/* read initial status */
-	scc->rxbufcnt = 0;
+
 	or(scc,R1,INT_ALL_Rx|TxINT_ENAB|EXT_INT_ENAB); /* enable interrupts */
 	or(scc,R9,MIE);			/* master interrupt enable */
 			
@@ -1198,22 +1233,57 @@
 	scc->t_tail = scc->kiss.tailtime;
 }
 
+static inline void check_rcv_queue(register struct scc_channel *scc)
+{
+	register struct mbuf *bp;
+	
+	if (scc->stat.rx_queued > QUEUE_THRES)
+	{
+		if (scc->rcvq == NULLBUF)
+		{
+			printk("z8530drv: Warning - scc->stat.rx_queued shows overflow"
+			       " (%d) but queue is empty\n", scc->stat.rx_queued);
+			       
+			scc->stat.rx_queued = 0;	/* correct it */
+			scc->stat.nospace = 12345;	/* draw attention to it */
+			return;
+		}
+			
+		bp = scc->rcvq->anext;	/* don't use the one we currently use */
+		
+		while (bp && (scc->stat.rx_queued > QUEUE_HYST))
+		{
+			bp = scc_free_chain(bp, BT_RECEIVE);
+			scc->stat.rx_queued--;
+			scc->stat.nospace++;
+		}
+		
+		scc->rcvq->anext = bp;
+	}
+}
+
 static void
 scc_timer(void)
 {
 	register struct scc_channel *scc;
 	register int chan;
 	unsigned long flags;
+		
 
-	save_flags(flags); cli();
-	
 	for (chan = 0; chan < (Nchips * 2); chan++)
 	{
 		scc = &SCC_Info[chan];
 		
 		if (scc->tty && scc->init)
 		{
+			kiss_encode(scc);
+			
+			save_flags(flags); cli();
+			
+			check_rcv_queue(scc);
+			
 			/* KISS-TNC emulation */
+			
 			if (Expired(t_dwait)) dw_slot_timeout(scc)	; else
 			if (Expired(t_slot))  dw_slot_timeout(scc)	; else
 			if (Expired(t_txdel)) txdel_timeout(scc)   	; else
@@ -1224,10 +1294,12 @@
 			if (Expired(t_mbusy)) busy_timeout(scc);
 			if (Expired(t_maxk))  maxk_idle_timeout(scc);
 			if (Expired(t_idle))  maxk_idle_timeout(scc);
-
+			
+			restore_flags(flags);
 		}
 	}
-
+	
+	save_flags(flags); cli();
 	
 	timer_table[SCC_TIMER].fn = scc_timer;
 	timer_table[SCC_TIMER].expires = jiffies + HZ/TPS;
@@ -1257,6 +1329,24 @@
 }
 
 
+static void
+scc_rx_timer(void)
+{
+	unsigned long flags;
+	
+	kiss_encode(rx_timer_cb.scc);
+	
+	save_flags(flags); cli();
+	
+	timer_table[SCC_TIMER].fn = scc_timer;
+	timer_table[SCC_TIMER].expires = jiffies + rx_timer_cb.expires;
+	timer_active |= 1 << SCC_TIMER;
+	
+	rx_timer_cb.lock = 0;
+	
+	restore_flags(flags);
+}
+
 
 /* ******************************************************************** */
 /* *			KISS interpreter			      * */
@@ -1284,7 +1374,7 @@
 	case PARAM_TXTAIL:
 		scc->kiss.tailtime = VAL; break;
 	case PARAM_FULLDUP:
-		scc->kiss.fulldup = val; break; 
+		scc->kiss.fulldup = val; break;
 	case PARAM_WAIT:
 		scc->kiss.waittime = VAL; break;
 	case PARAM_MAXKEY:
@@ -1448,6 +1538,97 @@
 	
 }
 
+/* ----> Encode received data and write it to the flip-buffer  <---- */
+
+/* receive raw frame from SCC. used for AX.25 */
+static void
+kiss_encode(register struct scc_channel *scc)
+{
+	struct mbuf *bp,*bp2;
+	struct tty_struct * tty = scc->tty;
+	unsigned long flags; 
+	unsigned char ch;
+
+	if(!scc->rcvq)
+	{
+		scc->stat.rx_kiss_state = KISS_IDLE;
+		return;
+	}
+	
+	/* worst case: FEND 0 FESC TFEND -> 4 bytes */
+	
+	while(tty->flip.count < TTY_FLIPBUF_SIZE-3)
+	{ 
+		if (scc->rcvq->cnt)
+		{
+			bp = scc->rcvq;
+			
+			if (scc->stat.rx_kiss_state == KISS_IDLE)
+			{
+				tty_insert_flip_char(tty, FEND, 0);
+				
+				if (scc->kiss.not_slip)
+					tty_insert_flip_char(tty, 0, 0);
+					
+				scc->stat.rx_kiss_state = KISS_RXFRAME;
+			}
+				
+			switch(ch = bp->data[bp->in_use++])
+			{
+				case FEND:
+					tty_insert_flip_char(tty, FESC, 0);
+					tty_insert_flip_char(tty, TFEND, 0);
+					break;
+				case FESC:
+					tty_insert_flip_char(tty, FESC, 0);
+					tty_insert_flip_char(tty, TFESC, 0);
+					break;
+				default:
+					tty_insert_flip_char(tty, ch, 0);
+			}
+			
+			bp->cnt--;
+			
+ 		} else {
+			save_flags(flags); cli();
+			
+			while (!scc->rcvq->cnt)
+	 		{				 /* buffer empty? */
+				bp  = scc->rcvq->next;  /* next buffer */
+				bp2 = scc->rcvq->anext; /* next packet */
+				
+				
+				scc_return_buffer(scc->rcvq, BT_RECEIVE);
+				
+				if (!bp)	/* end of frame ? */
+				{
+					scc->rcvq = bp2;
+					
+					if (--scc->stat.rx_queued < 0)
+						scc->stat.rx_queued = 0;
+					
+					if (scc->stat.rx_kiss_state == KISS_RXFRAME)	/* new packet? */
+					{
+						tty_insert_flip_char(tty, FEND, 0); /* send FEND for old frame */
+						scc->stat.rx_kiss_state = KISS_IDLE; /* generate FEND for new frame */
+					}
+					
+					restore_flags(flags);
+					queue_task(&tty->flip.tqueue, &tq_timer);
+					return;
+					
+				} else scc->rcvq = bp; /* next buffer */
+			}
+			
+			restore_flags(flags);
+		}						
+		
+	}
+	
+ 	queue_task(&tty->flip.tqueue, &tq_timer); /* kick it... */
+}
+
+
 /* ******************************************************************* */
 /* *		Init channel structures, special HW, etc...	     * */
 /* ******************************************************************* */
@@ -1460,7 +1641,7 @@
 	int chip;
 	unsigned long flags;
 
-	/* reset all scc chips */
+	/* reset and pre-init all chips in the system */
 	for (chip = 0; chip < Nchips; chip++)
 	{
 		/* Special SCC cards */
@@ -1469,27 +1650,27 @@
 			Outb(Special_Port,0x08);	/* enable interrupt on the board */
 			
 		if(Board & (PC100 | PRIMUS))		/* this is a PC100/EAGLE card */
-			Outb(Special_Port,Option);	/* set the MODEM mode (22H normally) */
+			Outb(Special_Port,Option);	/* set the MODEM mode (0x22) */
 			
+		/* Init SCC */
+		
 		scc=&SCC_Info[2*chip];
 		if (!scc->ctrl) continue;
 		
 		save_flags(flags); cli();
 		
-		OutReg(scc->ctrl,R9,FHWRES);	/* force hardware reset */
-		OutReg(scc->ctrl,R9,0);		/* end hardware reset */
-		OutReg(scc->ctrl,R9,CHRA);	/* reset channel A */
-		OutReg(scc->ctrl,R9,CHRB);	/* reset channel B */
-		OutReg(scc->ctrl,R1, 0);	/* No Rx irq from channel A */
-		scc=&SCC_Info[2*chip+1];
-		OutReg(scc->ctrl,R1, 0);	/* No Rx irq from channel B */
-		scc=&SCC_Info[2*chip];
-		OutReg(scc->ctrl,R2, chip*16);	/* Set Interrupt vector */
- 
+		/* some general init we can do now */
+		
+		Outb(scc->ctrl, 0);
+		OutReg(scc->ctrl,R9,FHWRES);		/* force hardware reset */
+		udelay(100);				/* give it 'a bit' more time than required */
+		wr(scc, R2, chip*16);			/* interrupt vector */
+		wr(scc, R9, VIS);			/* vector includes status */
+
         	restore_flags(flags);
         }
 
-	if (Ivec == 2) Ivec = 9;
+	if (Ivec == 2) Ivec = 9;			/* this f... IBM AT-design! */
 	request_irq(Ivec, scc_isr,   SA_INTERRUPT, "AX.25 SCC");
  
 	Driver_Initialized = 1;
@@ -1541,9 +1722,6 @@
  	scc = &SCC_Info[chan];
  	
 	tty->driver_data = scc;
-        tty->termios->c_iflag = IGNBRK | IGNPAR;
-        tty->termios->c_cflag = B9600 | CS8 | CLOCAL;
-
  	tty->termios->c_cflag &= ~CBAUD; 
  	
 	if (!Driver_Initialized)
@@ -1574,28 +1752,7 @@
 	timer_table[SCC_TIMER].fn = scc_timer;
 	timer_table[SCC_TIMER].expires = 0;	/* now! */
 	timer_active |= 1 << SCC_TIMER;
-
-/*====================new pe1ayx====================
-planed for the new TX routines
-
-	if (!scc->xmit_buf) {
-		scc->xmit_buf = (unsigned char *) get_free_page(GFP_KERNEL);
-		if (!scc->xmit_buf)
-			return -ENOMEM;
-	}
-
-	scc->xmit_cnt = scc->xmit_head = scc->xmit_tail = 0;
-
-
-====================new pe1ayx end================*/
-
-	if (!tmp_buf) {
-		tmp_buf = (unsigned char *) get_free_page(GFP_KERNEL);
-		if (!tmp_buf)
-			return -ENOMEM;
-	}
-
-
+	
 	return 0;
 }
 
@@ -1748,7 +1905,7 @@
 				scc->kiss.softdcd = 0;		   /* hardware dcd */
 			}
 			
-			scc->init = 1;
+			scc->init = 1;			
 			
 			return 0;
 		}
@@ -1773,7 +1930,7 @@
 		
 		restore_flags(flags);
 			
-		put_fs_long(result,(unsigned long *) arg);
+		put_user_long(result,(unsigned int *) arg);
 		return 0;
 	case TIOCMBIS:
 	case TIOCMBIC:
@@ -1788,7 +1945,7 @@
 			scc->wreg[R5] &= ~RTS;
 			break;
 		case TIOCMSET:
-			value = get_fs_long((unsigned long *) arg);
+			value = get_user_long((unsigned int *) arg);
 			
 			if(value & TIOCM_DTR)
 				scc->wreg[R5] |= DTR;
@@ -1974,7 +2131,6 @@
 		
 		scc->sndq1->anext = bp;
 	}
-	
 }
 
 
@@ -1984,14 +2140,12 @@
 /* send raw frame to SCC. used for AX.25 */
 int scc_write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count)
 {
-	unsigned long flags;
-	static unsigned char *p;
 	struct scc_channel * scc = tty->driver_data;
+	unsigned char tbuf[BUFSIZE], *p;
 	int cnt, cnt2;
-
-	if (!tty || !tmp_buf)
-		return 0;
-		
+	
+	if (!tty) return count;
+	
 	if (scc_paranoia_check(scc, tty->device, "scc_write"))
 		return 0;
 
@@ -1999,43 +2153,31 @@
 	
 	check_tx_queue(scc);
 
-	save_flags(flags);
-
 	cnt2 = count;
 	
 	while (cnt2)
 	{
-		cli();
-		cnt   = cnt2 > SERIAL_XMIT_SIZE? SERIAL_XMIT_SIZE:cnt2;
+		cnt   = cnt2 > BUFSIZE? BUFSIZE:cnt2;
 		cnt2 -= cnt;
 		
-		if (from_user){
-			down(&tmp_buf_sem);
-			memcpy_fromfs(tmp_buf, buf, cnt);
-			up(&tmp_buf_sem);
-			}
+		if (from_user)
+			memcpy_fromfs(tbuf, buf, cnt);
 		else
-			memcpy(tmp_buf, buf, cnt);
+			memcpy(tbuf, buf, cnt);
 		
 		buf += cnt;
 			
-		p=tmp_buf;
+		p=tbuf;
 		
 		while(cnt--) 
 		  if (kiss_decode(scc, *p++))
 		  {
 		  	scc->stat.nospace++;
-		  	restore_flags(flags);
 		  	return 0;
 		  }
 		  	
 	} /* while cnt2 */
-		
-	if ((scc->tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) 
-	     && scc->tty->ldisc.write_wakeup)
-		(scc->tty->ldisc.write_wakeup)(scc->tty);
-
-	restore_flags(flags);
+	
 	return count;
 }
 				
@@ -2059,7 +2201,7 @@
 	struct scc_channel *scc = tty->driver_data;
 	
 	scc_paranoia_check(scc, tty->device, "scc_flush_chars"); /* just to annoy the user... */
-
+	
 	return;	/* no flush needed */
 }
 
@@ -2068,7 +2210,7 @@
 static int scc_write_room(struct tty_struct *tty)
 {
 	struct scc_channel *scc = tty->driver_data;
-
+	
 	if (scc_paranoia_check(scc, tty->device, "scc_write_room"))
 		return 0;
 	
@@ -2084,7 +2226,7 @@
 static int scc_chars_in_buffer(struct tty_struct *tty)
 {
 	struct scc_channel *scc = tty->driver_data;
-
+	
 	if (scc && scc->sndq2)
 		return scc->sndq2->cnt;
 	else
@@ -2094,35 +2236,37 @@
 static void scc_flush_buffer(struct tty_struct *tty)
 {
 	struct scc_channel *scc = tty->driver_data;
-
+	
 	if (scc_paranoia_check(scc, tty->device, "scc_flush_buffer"))
 		return;
 		
 	scc->stat.tx_kiss_state = KISS_IDLE;
-
+	
+	wake_up_interruptible(&tty->write_wait);
+	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+	    tty->ldisc.write_wakeup)
+		(tty->ldisc.write_wakeup)(tty);
 }
 
 static void scc_throttle(struct tty_struct *tty)
 {
 	struct scc_channel *scc = tty->driver_data;
-
+	
 	if (scc_paranoia_check(scc, tty->device, "scc_throttle"))
 		return;
 		
 		
 	/* dummy */
-	
 }
 
 static void scc_unthrottle(struct tty_struct *tty)
 {
 	struct scc_channel *scc = tty->driver_data;
-
+	
 	if (scc_paranoia_check(scc, tty->device, "scc_unthrottle"))
 		return;
 		
 	/* dummy */
-	
 }
 
 static void scc_start(struct tty_struct *tty)
@@ -2146,14 +2290,6 @@
 	/* dummy */
 }
 
-void scc_hangup(struct tty_struct *tty)
-{
-	struct scc_channel *scc = tty->driver_data;
-	
-	if (scc_paranoia_check(scc, tty->device, "scc_hangup"))
-		return;
-}
-
 
 /* ******************************************************************** */
 /* * 			Init SCC driver 			      * */
@@ -2161,11 +2297,7 @@
 
 long scc_init (long kmem_start)
 {
-
-	int chip;
-#ifdef VERBOSE_BOOTMSG
-	int chan;
-#endif	
+	int chip, chan;
 	register io_port ctrl;
 	long flags;
 	
@@ -2173,35 +2305,35 @@
         memset(&scc_driver, 0, sizeof(struct tty_driver));
         scc_driver.magic = TTY_DRIVER_MAGIC;
         scc_driver.name = "sc";
-        scc_driver.major = TTY_MAJOR;		
-        scc_driver.minor_start = 96;
+        scc_driver.major = Z8530_MAJOR;		
+        scc_driver.minor_start = 0;
         scc_driver.num = Nchips*2;
         scc_driver.type = TTY_DRIVER_TYPE_SERIAL;
-        scc_driver.subtype = SERIAL_TYPE_NORMAL;			/* not needed */
+        scc_driver.subtype = 0;			/* not needed */
         scc_driver.init_termios = tty_std_termios;
-        scc_driver.init_termios.c_iflag = IGNBRK | IGNPAR;
-        scc_driver.init_termios.c_cflag = B9600	| CS8 | CLOCAL;
+        scc_driver.init_termios.c_cflag = B9600	| CS8 | CREAD | HUPCL | CLOCAL;
         scc_driver.flags = TTY_DRIVER_REAL_RAW;
         scc_driver.refcount = &scc_refcount;	/* not needed yet */
         scc_driver.table = scc_table;
         scc_driver.termios = (struct termios **) scc_termios;
         scc_driver.termios_locked = (struct termios **) scc_termios_locked;
-
         scc_driver.open = scc_open;
         scc_driver.close = scc_close;
         scc_driver.write = scc_write;
+        scc_driver.start = scc_start;
+        scc_driver.stop = scc_stop;
+        
         scc_driver.put_char = scc_put_char;
         scc_driver.flush_chars = scc_flush_chars;        
 	scc_driver.write_room = scc_write_room;
 	scc_driver.chars_in_buffer = scc_chars_in_buffer;
 	scc_driver.flush_buffer = scc_flush_buffer;
-        scc_driver.ioctl = scc_ioctl;
+	
 	scc_driver.throttle = scc_throttle;
 	scc_driver.unthrottle = scc_unthrottle;
+        
+        scc_driver.ioctl = scc_ioctl;
         scc_driver.set_termios = scc_set_termios;
-        scc_driver.stop = scc_stop;
-        scc_driver.start = scc_start;
-        scc_driver.hangup = scc_hangup;
         
         if (tty_register_driver(&scc_driver))
            panic("Couldn't register Z8530 SCC driver\n");
@@ -2253,6 +2385,12 @@
  
         	restore_flags(flags);
         }
+
+#ifdef DO_FAST_RX
+        rx_timer_cb.lock = 0;
+#else
+	rx_timer_cb.lock = 1;
+#endif
         
 #ifdef VERBOSE_BOOTMSG
 	printk("Init Z8530 driver: %u channels, using irq %u\n",Nchips*2,Ivec);
diff -u --recursive --new-file v1.3.21/linux/drivers/char/scc_config.h linux/drivers/char/scc_config.h
--- v1.3.21/linux/drivers/char/scc_config.h	Tue Jun  6 11:22:06 1995
+++ linux/drivers/char/scc_config.h	Tue Aug 29 07:13:35 1995
@@ -60,6 +60,8 @@
 #undef  SCC_DELAY		/* perhaps a 486DX2 is a *bit* too fast */
 #undef  SCC_LDELAY		/* slow it even a bit more down */
 #undef  DONT_CHECK		/* don't look if the SCCs you specified are available */
+#define DO_FAST_RX		/* experimental timer routine called immediateley */
+				/* after every received frame */
 
 
 /* The external clocking, nrz and fullduplex divider configuration is gone */
diff -u --recursive --new-file v1.3.21/linux/drivers/char/serial.c linux/drivers/char/serial.c
--- v1.3.21/linux/drivers/char/serial.c	Mon Aug 28 14:52:20 1995
+++ linux/drivers/char/serial.c	Tue Aug 29 10:15:51 1995
@@ -71,7 +71,7 @@
 #undef SERIAL_DEBUG_OPEN
 #undef SERIAL_DEBUG_FLOW
 
-#define RS_STROBE_TIME 10
+#define RS_STROBE_TIME (10*HZ)
 #define RS_ISR_PASS_LIMIT 256
 
 #define _INLINE_ inline
@@ -765,7 +765,7 @@
 	struct async_struct *info;
 	unsigned int	i;
 
-	if ((jiffies - last_strobe) >= RS_STROBE_TIME*HZ) {
+	if ((jiffies - last_strobe) >= RS_STROBE_TIME) {
 		for (i=1; i < 16; i++) {
 			info = IRQ_ports[i];
 			if (!info)
@@ -788,7 +788,7 @@
 		}
 	}
 	last_strobe = jiffies;
-	timer_table[RS_TIMER].expires = jiffies + RS_STROBE_TIME * HZ;
+	timer_table[RS_TIMER].expires = jiffies + RS_STROBE_TIME;
 	timer_active |= 1 << RS_TIMER;
 
 	if (IRQ_ports[0]) {
@@ -1016,7 +1016,7 @@
 	/*
 	 * Set up serial timers...
 	 */
-	timer_table[RS_TIMER].expires = jiffies + 2;
+	timer_table[RS_TIMER].expires = jiffies + 2*HZ/100;
 	timer_active |= 1 << RS_TIMER;
 
 	/*
@@ -1519,8 +1519,8 @@
 			(new_serial.flags & ASYNC_FLAGS));
 	info->custom_divisor = new_serial.custom_divisor;
 	info->type = new_serial.type;
-	info->close_delay = new_serial.close_delay;
-	info->closing_wait = new_serial.closing_wait;
+	info->close_delay = new_serial.close_delay * HZ/100;
+	info->closing_wait = new_serial.closing_wait * HZ/100;
 
 	release_region(info->port,8);
 	if (change_port || change_irq) {
@@ -1703,13 +1703,13 @@
 	 * Delay for 0.1 seconds -- we use a busy loop since this may 
 	 * occur during the bootup sequence
 	 */
-	timeout = jiffies+10;
+	timeout = jiffies+HZ/10;
 	while (timeout >= jiffies)
 		;
 	
 	rs_triggered = 0;	/* Reset after letting things settle */
 
-	timeout = jiffies+10;
+	timeout = jiffies+HZ/10;
 	while (timeout >= jiffies)
 		;
 	
@@ -2386,7 +2386,7 @@
 	(void)serial_inp(info, UART_IIR);
 	(void)serial_inp(info, UART_MSR);
 	
-	timeout = jiffies+2;
+	timeout = jiffies+2*HZ/100;
 	while (timeout >= jiffies) {
 		if (rs_irq_triggered)
 			break;
@@ -2648,8 +2648,8 @@
 		info->tty = 0;
 		info->type = PORT_UNKNOWN;
 		info->custom_divisor = 0;
-		info->close_delay = 50;
-		info->closing_wait = 3000;
+		info->close_delay = 5*HZ/10;
+		info->closing_wait = 30*HZ;
 		info->x_char = 0;
 		info->event = 0;
 		info->count = 0;
diff -u --recursive --new-file v1.3.21/linux/drivers/char/tpqic02.c linux/drivers/char/tpqic02.c
--- v1.3.21/linux/drivers/char/tpqic02.c	Wed Aug  2 13:21:01 1995
+++ linux/drivers/char/tpqic02.c	Tue Aug 29 10:15:52 1995
@@ -754,7 +754,7 @@
 		/* not ready and no exception && timeout not expired yet */
 	while (((stat = inb_p(QIC02_STAT_PORT) & QIC02_STAT_MASK) == QIC02_STAT_MASK) && (jiffies<spin_t)) {
 		/* be `nice` to other processes on long operations... */
-		current->timeout = jiffies + 30;	/* nap 0.30 sec between checks, */
+		current->timeout = jiffies + 3*HZ/10;	/* nap 0.30 sec between checks, */
 		current->state = TASK_INTERRUPTIBLE;
 		schedule();		 /* but could be woken up earlier by signals... */
 	}
diff -u --recursive --new-file v1.3.21/linux/drivers/net/3c503.c linux/drivers/net/3c503.c
--- v1.3.21/linux/drivers/net/3c503.c	Tue Aug 15 20:39:02 1995
+++ linux/drivers/net/3c503.c	Tue Aug 29 10:15:52 1995
@@ -95,7 +95,7 @@
 
     for (addr = addrs; *addr; addr++) {
 	int i;
-	unsigned int base_bits = *(unsigned char *)*addr;
+	unsigned int base_bits = readb(*addr);
 	/* Find first set bit. */
 	for(i = 7; i >= 0; i--, base_bits >>= 1)
 	    if (base_bits & 0x1)
@@ -221,19 +221,19 @@
 #ifdef EL2MEMTEST
 	/* This has never found an error, but someone might care. */
 	{			/* Check the card's memory. */
-	    int *mem_base = (int *)dev->mem_start;
-	    int memtest_value = 0xbbadf00d;
-	    mem_base[0] = 0xba5eba5e;
-	    for (i = 1; i < EL2_MEMSIZE/sizeof(mem_base[0]); i++) {
-		mem_base[i] = memtest_value;
-		if (mem_base[0] != 0xba5eba5e
-		    || mem_base[i] != memtest_value) {
+	    unsigned long mem_base = dev->mem_start;
+	    unsigned int test_val = 0xbbadf00d;
+	    writel(0xba5eba5e, mem_base);
+	    for (i = sizeof(test_val); i < EL2_MEMSIZE; i+=sizeof(test_val)) {
+		writel(test_val, mem_base + i);
+		if (readl(mem_base) != 0xba5eba5e
+		    || readl(mem_base + i) != test_val) {
 		    printk(" memory failure or memory address conflict.\n");
 		    dev->mem_start = 0;
 		    break;
 		}
-		memtest_value += 0x55555555;
-		mem_base[i] = 0;
+		test_val += 0x55555555;
+		writel(0, mem_base + i);
 	    }
 	}
 #endif  /* EL2MEMTEST */
diff -u --recursive --new-file v1.3.21/linux/drivers/net/3c505.c linux/drivers/net/3c505.c
--- v1.3.21/linux/drivers/net/3c505.c	Tue Aug 15 20:39:02 1995
+++ linux/drivers/net/3c505.c	Thu Aug 31 08:09:06 1995
@@ -377,8 +377,10 @@
 		} else {
 			printk("%s: timeout after sending PCB\n", dev->name);
 		}
-	} else
+	} else {
+		sti();
 		printk("%s: timeout in middle of sending PCB\n", dev->name);
+	}
 
 	adapter_reset(dev);
 	return FALSE;
diff -u --recursive --new-file v1.3.21/linux/drivers/net/README.arcnet linux/drivers/net/README.arcnet
--- v1.3.21/linux/drivers/net/README.arcnet	Sun Aug 13 14:45:30 1995
+++ linux/drivers/net/README.arcnet	Thu Jan  1 02:00:00 1970
@@ -1,235 +0,0 @@
-
-----------------------------------------------------------------------------
-NOTE:  See also README.arcnet-jumpers in this directory for jumper-setting
-information if you're like many of us and didn't happen to get a manual with
-your ARCnet card.
-----------------------------------------------------------------------------
-
-Since no one seems to listen to me otherwise, perhaps a poem will get your
-attention:
-			This is alpha software
-			If it works I DO CARE.
-			
-Hmm, I think I'm allowed to call that a poem, even though it's only two
-lines.  Hey, I'm in Computer Science, not English.  Give me a break.
-
-The point is:  I REALLY REALLY REALLY REALLY REALLY want to hear from you if
-you test this and get it working.  Or if you don't.  Or anything.
-
-ARCnet 0.32 ALPHA first made it into the Linux kernel 1.1.80 - this was
-nice, but after that even FEWER people started writing to me because they
-didn't even have to install the patch.  <sigh>
-
-Come on, be a sport!  Send me a success report!
-
-(hey, that was even better than my original poem... this is getting bad!)
-
-Anyway, enough complaining.  Let's get started:
-
----------------------------------------------------------------------------
-			
-These are the ARCnet drivers for Linux.
-
-We're now back to more ALPHA releases after the 1.01 release which made it
-into Linux 1.2.2, so please be careful, and send all possible
-success/failure reports to me.  If I don't know when/if/how it works, I
-won't be able to answer people's questions.  Do we want that?  Of course
-not.
-
-Once again:  DO send me success reports!  I want to know if this is working!
-(You know, it might be argued that I'm pushing this point a little too much. 
-If you think so, why not flame me in a quick little e-mail?  Please also
-include the type of card(s) you're using, software, size of network, and
-whether it's working or not.)
-
-My e-mail address is:
-	apenwarr@foxnet.net
-
-
-Where do I discuss these drivers?
----------------------------------
-
-There is a mailing list specifically for discussion of the ARCnet drivers
-for Linux, and anything you might want to interface them with (ie. DOS). 
-I'll also post new versions of the Linux-ARCnet distribution to the list in
-tar-gzip-uuencode format.
-
-To subscribe to the list, send a message to listserv@807-city.on.ca
-with the following line in the BODY (not the SUBJECT) of your message:
-	subscribe linux-arcnet YOUR REAL NAME
-Remember to remove your signature, or you'll get an error back.
-
-Send all bug (or success) reports to me or to the list.
-
-The people on linux-net@vger.rutgers.edu have also been known to be very
-helpful! :)
-
-
-Other Drivers and Info
-----------------------
-
-Also, SMC (one of the companies that makes ARCnet cards) has a WorldWideWeb
-site you might be interested in, which includes several drivers for various
-cards including ARCnet.  Try:
-	http://www.smc.com/
-	
-Performance Technologies makes various network software that supports
-ARCnet.
-	http://www.perftech.com/ or ftp to ftp.perftech.com.
-	
-Novell makes a networking stack for DOS which includes ARCnet drivers.  Try
-ftp'ing to ftp.novell.com.
-
-You can get the Crynwr packet driver collection (including arcether.com, the
-one you'll want for arcnet cards) from oak.oakland.edu:/simtel/msdos/pktdrvr.
-It won't work perfectly on a 386+ without patches, though, and also doesn't
-like several cards.  Mail me if you want a fixed version.  (Ahem:  I may or
-may not have a 100% fixed version by the time I get your mail!)
-
-
-Loadable Module Support
------------------------
-
-This is a available starting with 0.42 ALPHA.
-
-Configure and rebuild Linux.  When asked, say NO to "arcnet support" if you
-want loadable module support.
-
-	make config
-	make dep
-	make clean	
-	make zImage
-	make modules
-	
-	
-Booting into your "ARCnet" Kernel
----------------------------------
-
-If you're using a loadable module, you need to use insmod to load the
-module, and you need to specify various characteristics of your card on the
-command line.  For example:
-	cd /usr/src/linux/modules
-	insmod arcnet.o io=0x300 irqnum=2 shmem=0xd0000
-You can also add a num=1, num=2 etc for additional arcnet cards that will
-use arc1, arc2 etc for their device names (instead of the default, arc0).
-	
-Otherwise the driver will load and probe for your card automatically.
-	
-Now go read the NET-2-HOWTO and ETHERNET-HOWTO for Linux; they should be
-available where you picked up this driver.  Think of your ARCnet as a
-souped-up (or down, as the case may be) ethernet card.
-
-By the way, be sure to change all references from "eth0" to "arc0" in the
-HOWTOs.  Remember that ARCnet isn't a "true" ethernet, and the device name
-is DIFFERENT.
-
-
-How do I get it to work with...?
---------------------------------
-
-NFS: Should be fine linux->linux, just pretend you're using ethernet cards. 
-        oak.oakland.edu:/simtel/msdos/nfs has some nice DOS clients.  There
-        is also a DOS-based NFS server called SOSS.  It doesn't multitask
-        quite the way Linux does (actually, it doesn't multitask AT ALL) but
-        you never know what you might need.
-
-DOS: If you're using the freeware arcether.com, you might want to install
-        the source code patch.  It helps with PC/TCP, and also can get
-        arcether to load if it timed out too quickly during initialization. 
-        Mail me if you need a precompiled version of arcether.com. (ie. you
-        if don't have a DOS assembler)
-	
-Windows:  See DOS :)  Trumpet Winsock works fine with either the Novell or
-	Arcether client, assuming you remember to load winpkt of course.
-
-LAN Manager and Windows for Workgroups: These programs use protocols that
-        are incompatible with the internet standard.  They try to pretend
-        the cards are ethernet, and confuse everyone else on the network. 
-        However, v1.93 ALPHA and later of the Linux ARCnet driver support
-        this protocol via the 'arc0e' device.  After setting up arc0 as
-        usual, ifconfig and set up routes to your ethernet-encap hosts
-        through arc0e.  There may be non-Microsoft products that support
-        this protocol as well, so it was changed in 1.93 ALPHA from arc0w
-        to arc0e.
-        
-	Using the freeware Samba server and clients for Linux, you can now
-	interface quite nicely with TCP/IP-based WfWg or Lan Manager
-	networks.  In addition, the Linux host can be used as a router
-	between the standard and WfWg protocols, so hosts that could
-	previously never talk to each other should now be able to.
-
-        This feature is still in early testing, so please e-mail with any
-	comments/questions you might have.
-	
-OS2: Has not been tested.  The "correct" solution would be to buy either of
-	IBM's "TCP/IP for OS/2" or "Warp Connect" packages.  However,
-	ftp.microsoft.com also has a freeware Lan Manager for OS/2 client
-	which should use the same protocol as WfWg does.  This has not been
-	tested, however.  Please mail me with any results.
-        
-NetBSD/AmiTCP: These use an old version of the Internet standard ARCnet
-	protocol which is incompatible with the Linux driver at present. 
-	Work to support these is underway and should be available in a
-	standard release soon.
-
-
-It works: what now?
--------------------
-
-Send mail describing your setup, preferably including driver version, kernel
-version, ARCnet card model, CPU type, number of systems on your network, and
-list of software in use to me at the following address:
-	apenwarr@foxnet.net
-
-I do send (sometimes automated) replies to all messages I receive.  My email
-can be weird (and also usually gets forwarded all over the place along the
-way to me), so if you don't get a reply within a reasonable time, please
-resend.
-
-
-It doesn't work: what now?
---------------------------
-
-Do the same as above, but also include the output of the ifconfig and route
-commands, as well as any pertinent log entries (ie: anything that starts
-with "arcnet:" and has shown up since the last reboot) in your mail.
-
-If you want to try fixing it yourself (I highly recommend that you mail me
-about the problem first, since it might already have been solved) you may
-want to try some of the debug levels available.  For heavy testing on
-D_DURING or more, it would be a REALLY good idea to kill your klogd
-daemon first!  D_DURING displays 4-5 lines for each packet sent or
-received.  D_TX and RX actually DISPLAY each packet as it is sent or
-received, which is obviously quite big.
-
-You can run the arcdump shell script (available from me or in the full
-ARCnet package if you got it) as root to list the contents of the arcnet
-buffers at any time.  To make any sense at all out of this, you should grab
-the pertinent RFC's. (some are listed near the top of arcnet.c).  arcdump
-assumes your card is at 0xD0000.  If it isn't, edit the script.
-
-Buffers #0 and 1 are used for receiving, and Buffers #2 and 3 are for
-sending.  Ping-pong buffers are implemented both ways.
-
-If your debug level includes D_DURING, the buffers are cleared to a constant
-value of 0x42 every time the card is reset (which should only happen when
-you do an ifconfig up, or when Linux decides that the driver is broken). 
-This is to make it easier to figure out which bytes are being used by a
-packet.
-
-You can change the debug level without recompiling the kernel by typing:
-	ifconfig arc0 down metric 1xxx
-	/etc/rc.d/rc.inet1
-where "xxx" is the debug level you want.  For example, "metric 1015" would put
-you at debug level 15.  Debug level 7 is currently the default.
-
-Note that the debug level is (as of v1.90 ALPHA) a binary combination of
-different debug flags; so debug level 7 is really 1+2+4 or
-D_NORMAL+D_INIT+D_EXTRA.  To reach D_DURING, you would add 8 to this,
-resulting in debug level 15.
-
-
-I want to send money: what now?
--------------------------------
-
-Go take a nap or something.  You'll feel better in the morning.
diff -u --recursive --new-file v1.3.21/linux/drivers/net/README.arcnet-jumpers linux/drivers/net/README.arcnet-jumpers
--- v1.3.21/linux/drivers/net/README.arcnet-jumpers	Thu Jul 13 16:20:20 1995
+++ linux/drivers/net/README.arcnet-jumpers	Thu Jan  1 02:00:00 1970
@@ -1,1911 +0,0 @@
-
------------------------------------------------------------------------------
-This file is a supplement to README.arcnet.  Please read that for general
-driver configuration help.
------------------------------------------------------------------------------
-
-Because so many people (myself included) seem to have obtained ARCnet cards
-without manuals, this will be a quick listing of all jumper settings I can
-find.  Please e-mail apenwarr@foxnet.net with any settings for
-your particular card.
-
-Even if your ARCnet model isn't listed, but has the same jumpers, please
-e-mail me to say so.
-
-If your model isn't listed, and has different settings, PLEASE PLEASE tell
-me.  I had to figure mine out without the manual, and it WASN'T FUN!
-
-Cards Listed in this file (in this order, mostly):
-
-	Manufacturer	Model #		Bits
-	------------	-------		----
-	SMC		PC100		8
-	SMC		PC110		8
-	SMC		PC120		8
-	SMC		PC130		8
-	SMC		PC270E		8
-	SMC		PC500		16
-	SMC		PC500Longboard	16
-	SMC		PC550Longboard	16
-	SMC		PC600		16
-	SMC?		LCS-8830-T	16?
-	Puredata	PDI507		16
-	CNet Tech	CN120-Series	8
-	CNet Tech	CN160-Series	16
-	No Name		--		8/16
-	No Name		Taiwan R.O.C(?)	8
-	Tiara		Tiara Lancard(?)
-	
-
-** SMC = Standard Microsystems Corp.
-** CNet Tech = CNet Technology, Inc.
-
-The model # is listed right above specifics for that card.  Don't forget to
-read "quick briefing" first, since it applies to all ARCnets.
-
-
-Unclassified Stuff
-------------------
-  - Please send any other information you can find.
-  
-  - And some unknowns (other info is welcome!):
-     From: root@ultraworld.xs4all.nl (Timo Hilbrink)
-     To: apenwarr@foxnet.net (Avery Pennarun)
-     Date: Wed, 26 Oct 1994 02:10:32 +0000 (GMT)
-     Reply-To: timoh@xs4all.nl
-
-     [...parts deleted...]
-
-     About the jumpers: On my PC130 there is one more jumper, located near the
-     cable-connector and it's for changing to star or bus topology; 
-     closed: star - open: bus
-     On the PC500 are some more jumper-pins, one block labled with RX,PDN,TXI
-     and another with ALE,LA17,LA18,LA19 these are undocumented..
-
-     [...more parts deleted...]
-
-     --- CUT ---
-
-
-Quick Briefing:
----------------
-
-All ARCnet cards should have a total of four different settings:
-
-  - the I/O address:  this is the "port" your ARCnet card is on.  Probed
-    values, as of v0.14, are only from 0x200 through 0x3F0. (If your card
-    has additional ones, which is possible, please tell me.) This should not
-    be the same as any other device on your system.  According to a doc I
-    got from Novell, MS Windows prefers values of 0x300 or more, eating
-    netconnections on my system otherwise.
-	- Avery's favourite: 0x300.
-
-  - the IRQ:  on 8-bit cards, it might be 2 (9), 3, 4, 5, or 7.
-             on 16-bit cards, it might be 2 (9), 3, 4, 5, 7, or 10-15.  Make
-    sure this is different from any other card on your system.  Note that
-    IRQ2 is the same as IRQ9, as far as Linux is concerned.
-	- Avery's favourite: IRQ2.
-
-  - the memory address:  Unlike most cards, ARCnets use "shared memory" for
-    copying buffers around.  Make SURE it doesn't conflict with any other
-    used memory in your system!
-	A0000		- VGA graphics memory (ok if you don't have VGA)
-        B0000		- Monochrome text mode
-        C0000		\  One of these is your VGA BIOS - usually C0000.
-        E0000		/
-        F0000		- System BIOS
-
-    Anything less than 0xA0000 is, well, a BAD idea since it isn't above
-    640k.
-	- Avery's favourite: 0xD0000
-
-  - the station address:  Every ARCnet card has its own "unique" network
-    address from 0 to 255.  Unlike ethernet, you can set this address
-    yourself.  Since it's only 8 bits, you can only have 254 ARCnet cards on
-    a network.  DON'T use 0 or 255, since these are reserved. (although neat
-    stuff will probably happen if you DO use them).  By the way, if you
-    haven't already guessed, don't set this the same as any other ARCnet on
-    your network!
-	- Avery's favourite:  3 and 4.  Not that it matters.
-
-
-** Standard Microsystems Corp (SMC) **
-PC100, PC110, PC120, PC130 (8-bit cards)
-PC500, PC600 (16-bit cards)
----------------------------------
-  - mainly from Avery Pennarun <apenwarr@foxnet.net>.  Values depicted are
-    from Avery's setup.
-  - special thanks to Timo Hilbrink <timoh@xs4all.nl> for noting that PC120,
-    130, 500, and 600 all have the same switches as Avery's PC100. 
-    PC500/600 have several extra, undocumented pins though. (?)
-  - PC110 settings were verified by Stephen A. Wood <saw@cebaf.gov>
-  - On the other hand, John Edward Bauer <jbauer@badlands.NoDak.edu> said
-    the PC110 settings are all wrong.  In his case, you need to switch all
-    the 1's with 0's.  If you're having problems, try that.
-  - Also, the JP- and S-numbers probably don't match your card exactly.  Try
-    to find jumpers/switches with the same number of settings - it's
-    probably more reliable.
-  
-
-     JP5		       [|]    :    :    :    :
-(IRQ Setting)		      IRQ2  IRQ3 IRQ4 IRQ5 IRQ7
-		Put exactly one jumper on exactly one set of pins.
-
-                          1  2   3  4  5  6   7  8  9 10
-     S1                /----------------------------------\
-(I/O and Memory        |  1  1 * 0  0  0  0 * 1  1  0  1  |
- addresses)            \----------------------------------/
-                          |--|   |--------|   |--------|
-                          (a)       (b)           (m)
-
-		a: The first digit of the I/O address.
-			Setting		Value
-			-------		-----
-			00		0
-			01		1
-			10		2
-			11		3
-
-		b: The second digit of the I/O address.
-			Setting		Value
-			-------		-----
-			0000		0
-			0001		1
-			0010		2
-			...		...
-			1110		E
-			1111		F
-
-		The I/O address is in the form ab0.  For example, if
-		a is 0x2 and b is 0xE, the address will be 0x2E0.
-
-		DO NOT SET THIS LESS THAN 0x200!!!!!
-
-
-		m: The first digit of the memory address.
-			Setting		Value
-			-------		-----
-			0000		0
-			0001		1
-			0010		2
-			...		...
-			1110		E
-			1111		F
-
-		The memory address is in the form m0000.  For example, if
-		m is D, the address will be 0xD0000.
-
-		DO NOT SET THIS TO C0000, F0000, OR LESS THAN A0000!
-
-                          1  2  3  4  5  6  7  8
-     S2                /--------------------------\
-(Station Address)      |  1  1  0  0  0  0  0  0  |
-                       \--------------------------/
-
-			Setting		Value
-			-------		-----
-			00000000	00
-			10000000	01
-			01000000	02
-			...
-			01111111	FE
-			11111111	FF
-
-		Note that this is binary with the digits reversed!
-
-		DO NOT SET THIS TO 0 OR 255 (0xFF)!
-
-
-*****************************************************************************
-
-** Standard Microsystems Corp (SMC) **
-PC130E/PC270E (8-bit cards)
----------------------------
-  - from Juergen Seifert <seifert@htwm.de>
-
-
-STANDARD MICROSYSTEMS CORPORATION (SMC) ARCNET(R)-PC130E/PC270E
-===============================================================
-
-This description has been written by Juergen Seifert <seifert@htwm.de>
-using information from the following Original SMC Manual 
-
-             "Configuration Guide for
-             ARCNET(R)-PC130E/PC270
-            Network Controller Boards
-                Pub. # 900.044A
-                   June, 1989"
-
-ARCNET is a registered trademark of the Datapoint Corporation
-SMC is a registered trademark of the Standard Microsystems Corporation  
-
-The PC130E is an enhanced version of the PC130 board, is equipped with a 
-standard BNC female connector for connection to RG-62/U coax cable.
-Since this board is designed both for point-to-point connection in star
-networks and for connection to bus networks, it is downwardly compatible 
-with all the other standard boards designed for coax networks (that is,
-the PC120, PC110 and PC100 star topology boards and the PC220, PC210 and 
-PC200 bus topology boards).
-
-The PC270E is an enhanced version of the PC260 board, is equipped with two 
-modular RJ11-type jacks for connection to twisted pair wiring.
-It can be used in a star or a daisy-chained network.
-
-
-         8 7 6 5 4 3 2 1
-    ________________________________________________________________
-   |   |       S1        |                                          |
-   |   |_________________|                                          |
-   |    Offs|Base |I/O Addr                                         |
-   |     RAM Addr |                                              ___|
-   |         ___  ___                                       CR3 |___|
-   |        |   \/   |                                      CR4 |___|
-   |        |  PROM  |                                           ___|
-   |        |        |                                        N |   | 8
-   |        | SOCKET |                                        o |   | 7
-   |        |________|                                        d |   | 6
-   |                   ___________________                    e |   | 5
-   |                  |                   |                   A | S | 4
-   |       |oo| EXT2  |                   |                   d | 2 | 3
-   |       |oo| EXT1  |       SMC         |                   d |   | 2
-   |       |oo| ROM   |      90C63        |                   r |___| 1
-   |       |oo| IRQ7  |                   |               |o|  _____|
-   |       |oo| IRQ5  |                   |               |o| | J1  |
-   |       |oo| IRQ4  |                   |              STAR |_____|
-   |       |oo| IRQ3  |                   |                   | J2  |
-   |       |oo| IRQ2  |___________________|                   |_____|
-   |___                                               ______________|
-       |                                             |
-       |_____________________________________________|
-
-Legend:
-
-SMC 90C63	ARCNET Controller / Transceiver /Logic
-S1	1-3:	I/O Base Address Select
-	4-6:	Memory Base Address Select
-	7-8:	RAM Offset Select
-S2	1-8:	Node ID Select
-EXT		Extended Timeout Select
-ROM		ROM Enable Select
-STAR		Selected - Star Topology	(PC130E only)
-		Deselected - Bus Topology	(PC130E only)
-CR3/CR4		Diagnostic LEDs
-J1		BNC RG62/U Connector		(PC130E only)
-J1		6-position Telephone Jack	(PC270E only)
-J2		6-position Telephone Jack	(PC270E only)
-
-Setting one of the switches to Off/Open means "1", On/Closed means "0".
-
-
-Setting the Node ID
--------------------
-
-The eight switches in group S2 are used to set the node ID.
-Each node attached to the network must have an unique node ID which
-must be diffrent from 0.
-Switch 1 serves as the least significant bit (LSB).
-
-The node ID is the sum of the values of all switches set to "1"  
-These values are:
-    Switch | Value
-    -------|-------
-      1    |   1
-      2    |   2
-      3    |   4
-      4    |   8
-      5    |  16
-      6    |  32
-      7    |  64
-      8    | 128
-
-Some Examples:
-
-    Switch         | Hex     | Decimal 
-   8 7 6 5 4 3 2 1 | Node ID | Node ID
-   ----------------|---------|---------
-   0 0 0 0 0 0 0 0 |    not allowed
-   0 0 0 0 0 0 0 1 |    1    |    1 
-   0 0 0 0 0 0 1 0 |    2    |    2
-   0 0 0 0 0 0 1 1 |    3    |    3
-       . . .       |         |
-   0 1 0 1 0 1 0 1 |   55    |   85
-       . . .       |         |
-   1 0 1 0 1 0 1 0 |   AA    |  170
-       . . .       |         |  
-   1 1 1 1 1 1 0 1 |   FD    |  253
-   1 1 1 1 1 1 1 0 |   FE    |  254
-   1 1 1 1 1 1 1 1 |   FF    |  255
-
-
-Setting the I/O Base Address
-----------------------------
-
-The first three switches in switch group S1 are used to select one
-of eight possible I/O Base addresses using the followig table
-
-
-   Switch | Hex I/O
-   1 2 3  | Address
-   -------|--------
-   0 0 0  |  260
-   0 0 1  |  290
-   0 1 0  |  2E0  (Manufactor's default)
-   0 1 1  |  2F0
-   1 0 0  |  300
-   1 0 1  |  350
-   1 1 0  |  380
-   1 1 1  |  3E0
-
-
-Setting the Base Memory (RAM) buffer Address
---------------------------------------------
-
-The memory buffer requires 2K of a 16K block of RAM. The base of this
-16K block can be located in any of eight positions.
-Switches 4-6 of switch group S1 select the Base of the 16K block.
-Within that 16K address space, the buffer may be assigned any one of four 
-positions, determined by the offset, switches 7 and 8 of group S1.
-
-   Switch     | Hex RAM | Hex ROM
-   4 5 6  7 8 | Address | Address *)
-   -----------|---------|-----------
-   0 0 0  0 0 |  C0000  |  C2000
-   0 0 0  0 1 |  C0800  |  C2000
-   0 0 0  1 0 |  C1000  |  C2000
-   0 0 0  1 1 |  C1800  |  C2000
-              |         |
-   0 0 1  0 0 |  C4000  |  C6000
-   0 0 1  0 1 |  C4800  |  C6000
-   0 0 1  1 0 |  C5000  |  C6000
-   0 0 1  1 1 |  C5800  |  C6000
-              |         |
-   0 1 0  0 0 |  CC000  |  CE000
-   0 1 0  0 1 |  CC800  |  CE000
-   0 1 0  1 0 |  CD000  |  CE000
-   0 1 0  1 1 |  CD800  |  CE000
-              |         |
-   0 1 1  0 0 |  D0000  |  D2000  (Manufactor's default)
-   0 1 1  0 1 |  D0800  |  D2000
-   0 1 1  1 0 |  D1000  |  D2000
-   0 1 1  1 1 |  D1800  |  D2000
-              |         |
-   1 0 0  0 0 |  D4000  |  D6000
-   1 0 0  0 1 |  D4800  |  D6000
-   1 0 0  1 0 |  D5000  |  D6000
-   1 0 0  1 1 |  D5800  |  D6000
-              |         |
-   1 0 1  0 0 |  D8000  |  DA000
-   1 0 1  0 1 |  D8800  |  DA000
-   1 0 1  1 0 |  D9000  |  DA000
-   1 0 1  1 1 |  D9800  |  DA000
-              |         |
-   1 1 0  0 0 |  DC000  |  DE000
-   1 1 0  0 1 |  DC800  |  DE000
-   1 1 0  1 0 |  DD000  |  DE000
-   1 1 0  1 1 |  DD800  |  DE000
-              |         |
-   1 1 1  0 0 |  E0000  |  E2000
-   1 1 1  0 1 |  E0800  |  E2000
-   1 1 1  1 0 |  E1000  |  E2000
-   1 1 1  1 1 |  E1800  |  E2000
-  
-*) To enable the 8K Boot PROM install the jumper ROM.
-   The default is jumper ROM not installed.
-
-
-Setting the Timeouts and Interrupt
-----------------------------------
-
-The jumpers labeled EXT1 and EXT2 are used to determine the timeout 
-parameters. These two jumpers are normally left open.
-Refer to the COM9026 Data Sheet for alternate configurations.
-
-To select a hardware interrupt level set one (only one!) of the jumpers
-IRQ2, IRQ3, IRQ4, IRQ5, IRQ7. The Manufactor's default is IRQ2.
- 
-
-Configuring the PC130E for Star or Bus Topology
------------------------------------------------
-
-The single jumper labeled STAR is used to configure the PC130E board for 
-star or bus topology.
-When the jumper is installed, the board may be used in a star network, when 
-it is removed, the board can be used in a bus topology.
-
-
-Diagnostic LEDs
----------------
-
-Two diagnostic LEDs are visible on the rear bracket of the board.
-The green LED monitors the network activity: the red one shows the
-board activity:
-
- Green  | Status               Red      | Status
- -------|-------------------   ---------|-------------------
-  on    | normal activity      flash/on | data transfer
-  blink | reconfiguration      off      | no data transfer;
-  off   | defectiv board or             | incorect memory or
-        | node ID is zero               | I/O address
-
-
-*****************************************************************************
-
-** Standard Microsystems Corp (SMC) **
-PC500/PC550 Long Board (16-bit cards)
--------------------------------------
-  - from Juergen Seifert <seifert@htwm.de>
-
-
-STANDARD MICROSYSTEMS CORPORATION (SMC) ARCNET-PC500/PC550 Long Board
-=====================================================================
-
-Note: There is another Version of the PC500 called Short Version, which 
-      is different in hard- and software! The most important differences
-      are:
-      - The long board has no Shared memory
-      - On the long board the selection of the interrupt is done by binary
-        coded switch, on the short board directly by jumper.
-
-
-This description has been written by Juergen Seifert <seifert@htwm.de>
-using information from the following Original SMC Manual 
-
-             "Configuration Guide for
-             SMC ARCNET-PC500/PC550
-         Series Network Controller Boards
-             Pub. # 900.033 Rev. A
-                November, 1989"
-
-ARCNET is a registered trademark of the Datapoint Corporation
-SMC is a registered trademark of the Standard Microsystems Corporation  
-
-The PC500 is equipped with a standard BNC female connector for connection
-to RG-62/U coax cable.
-The board is designed both for point-to-point connection in star networks
-and for connection to bus networks.
-
-The PC550 is equipped with two modular RJ11-type jacks for connection
-to twisted pair wiring.
-It can be used in a star or a daisy-chained network.
-
-       1 
-       0 9 8 7 6 5 4 3 2 1     6 5 4 3 2 1
-    ____________________________________________________________________
-   < |         SW1         | |     SW2     |                            |
-   > |_____________________| |_____________|                            |
-   <   IRQ    |I/O Addr                                                 |
-   >                                                                 ___|
-   <                                                            CR4 |___|
-   >                                                            CR3 |___|
-   <                                                                 ___|
-   >                                                              N |   | 8
-   <                                                              o |   | 7
-   >                                                              d | S | 6
-   <                                                              e | W | 5
-   >                                                              A | 3 | 4
-   <                                                              d |   | 3
-   >                                                              d |   | 2
-   <                                                              r |___| 1
-   >                                                        |o|    _____|
-   <                                                        |o|   | J1  |
-   >  3 1                                                   JP6   |_____|
-   < |o|o| JP2                                                    | J2  |
-   > |o|o|                                                        |_____|
-   <  4 2__                                               ______________|
-   >    |  |                                             |
-   <____|  |_____________________________________________|
-
-Legend:
-
-SW1	1-6:	I/O Base Address Select
-	7-10:	Interrupt Select
-SW2	1-6:	Reserved for Future Use
-SW3	1-8:	Node ID Select
-JP2	1-4:	Extended Timeout Select
-JP6		Selected - Star Topology	(PC500 only)
-		Deselected - Bus Topology	(PC500 only)
-CR3	Green	Monitors Network Activity
-CR4	Red	Monitors Board Activity
-J1		BNC RG62/U Connector		(PC500 only)
-J1		6-position Telephone Jack	(PC550 only)
-J2		6-position Telephone Jack	(PC550 only)
-
-Setting one of the switches to Off/Open means "1", On/Closed means "0".
-
-
-Setting the Node ID
--------------------
-
-The eight switches in group SW3 are used to set the node ID. Each node
-attached to the network must have an unique node ID which must be 
-diffrent from 0.
-Switch 1 serves as the least significant bit (LSB).
-
-The node ID is the sum of the values of all switches set to "1"  
-These values are:
-
-    Switch | Value
-    -------|-------
-      1    |   1
-      2    |   2
-      3    |   4
-      4    |   8
-      5    |  16
-      6    |  32
-      7    |  64
-      8    | 128
-
-Some Examples:
-
-    Switch         | Hex     | Decimal 
-   8 7 6 5 4 3 2 1 | Node ID | Node ID
-   ----------------|---------|---------
-   0 0 0 0 0 0 0 0 |    not allowed
-   0 0 0 0 0 0 0 1 |    1    |    1 
-   0 0 0 0 0 0 1 0 |    2    |    2
-   0 0 0 0 0 0 1 1 |    3    |    3
-       . . .       |         |
-   0 1 0 1 0 1 0 1 |   55    |   85
-       . . .       |         |
-   1 0 1 0 1 0 1 0 |   AA    |  170
-       . . .       |         |  
-   1 1 1 1 1 1 0 1 |   FD    |  253
-   1 1 1 1 1 1 1 0 |   FE    |  254
-   1 1 1 1 1 1 1 1 |   FF    |  255 
-
-
-Setting the I/O Base Address
-----------------------------
-
-The first six switches in switch group SW1 are used to select one
-of 32 possible I/O Base addresses using the followig table
-
-   Switch       | Hex I/O
-   6 5  4 3 2 1 | Address
-   -------------|--------
-   0 1  0 0 0 0 |  200
-   0 1  0 0 0 1 |  210
-   0 1  0 0 1 0 |  220
-   0 1  0 0 1 1 |  230
-   0 1  0 1 0 0 |  240
-   0 1  0 1 0 1 |  250
-   0 1  0 1 1 0 |  260
-   0 1  0 1 1 1 |  270
-   0 1  1 0 0 0 |  280
-   0 1  1 0 0 1 |  290
-   0 1  1 0 1 0 |  2A0
-   0 1  1 0 1 1 |  2B0
-   0 1  1 1 0 0 |  2C0
-   0 1  1 1 0 1 |  2D0
-   0 1  1 1 1 0 |  2E0 (Manufactor's default)
-   0 1  1 1 1 1 |  2F0
-   1 1  0 0 0 0 |  300
-   1 1  0 0 0 1 |  310
-   1 1  0 0 1 0 |  320
-   1 1  0 0 1 1 |  330
-   1 1  0 1 0 0 |  340
-   1 1  0 1 0 1 |  350
-   1 1  0 1 1 0 |  360
-   1 1  0 1 1 1 |  370
-   1 1  1 0 0 0 |  380
-   1 1  1 0 0 1 |  390
-   1 1  1 0 1 0 |  3A0
-   1 1  1 0 1 1 |  3B0
-   1 1  1 1 0 0 |  3C0
-   1 1  1 1 0 1 |  3D0
-   1 1  1 1 1 0 |  3E0
-   1 1  1 1 1 1 |  3F0
-
-
-Setting the Interrupt
----------------------
-
-Switches seven through ten of switch group SW1 are used to select the 
-interrupt level. The interrupt level is binary coded, so selections 
-from 0 to 15 would be possible, but only the following eight values will
-be supported: 3, 4, 5, 7, 9, 10, 11, 12.
-
-   Switch   | IRQ
-   10 9 8 7 | 
-   ---------|-------- 
-    0 0 1 1 |  3
-    0 1 0 0 |  4
-    0 1 0 1 |  5
-    0 1 1 1 |  7
-    1 0 0 1 |  9 (=2) (default)
-    1 0 1 0 | 10
-    1 0 1 1 | 11
-    1 1 0 0 | 12
-
-
-Setting the Timeouts 
---------------------
-
-The two jumpers JP2 (1-4) are used to determine the timeout parameters. 
-These two jumpers are normally left open.
-Refer to the COM9026 Data Sheet for alternate configurations.
-
-
-Configuring the PC500 for Star or Bus Topology
-----------------------------------------------
-
-The single jumper labeled JP6 is used to configure the PC500 board for 
-star or bus topology.
-When the jumper is installed, the board may be used in a star network, when 
-it is removed, the board can be used in a bus topology.
-
-
-Diagnostic LEDs
----------------
-
-Two diagnostic LEDs are visible on the rear bracket of the board.
-The green LED monitors the network activity: the red one shows the
-board activity:
-
- Green  | Status               Red      | Status
- -------|-------------------   ---------|-------------------
-  on    | normal activity      flash/on | data transfer
-  blink | reconfiguration      off      | no data transfer;
-  off   | defectiv board or             | incorect memory or
-        | node ID is zero               | I/O address
-
-
-*****************************************************************************
-
-** Possibly SMC **
-LCS-8830-T (16-bit card)
-------------------------
-	- from Mathias Katzer <mkatzer@HRZ.Uni-Bielefeld.DE>
-	
-This is a LCS-8830-T made by SMC, I think ('SMC' only appears on one PLCC,
-nowhere else, not even on the few xeroxed sheets from the manual).
-
-SMC Arcnet Board Type LCS-8830-T
-
-   ------------------------------------
-  |                                    |
-  |              JP3 88  8 JP2         |
-  |       #####      | \               |
-  |       #####    ET1 ET2          ###|
-  |                              8  ###|
-  |  U3   SW 1                  JP0 ###|  Phone Jacks
-  |  --                             ###|
-  | |  |                               |
-  | |  |   SW2                         |
-  | |  |                               |
-  | |  |  #####                        |
-  |  --   #####                       ####  BNC Connector 
-  |                                   ####
-  |   888888 JP1                       |
-  |   234567                           |
-   --                           -------
-     |||||||||||||||||||||||||||
-      --------------------------
-
-
-SW1: DIP-Switches for Station Address
-SW2: DIP-Switches for Memory Base and I/O Base addresses
-
-JP0: If closed, internal termination on (default open)
-JP1: IRQ Jumpers
-JP2: Boot-ROM enabled if closed
-JP3: Jumpers for respsonse timeout
- 
-U3: Boot-ROM Socket          
-
-
-ET1 ET2     Response Time     Idle Time    Reconfiguration Time
-
-               78                86               840
- X            285               316              1680
-     X        563               624              1680
- X   X       1130              1237              1680
-
-(X means closed jumper)
-
-(DIP-Switch downwards means "0")
-
-The station address is binary-coded with SW1.
-
-The I/O base address is coded with DIP-Switches 6,7 and 8 of SW2:
-
-Switches        Base
-678             Address
-000		260-26f
-100		290-29f
-010		2e0-2ef
-110		2f0-2ff
-001		300-30f
-101		350-35f
-011		380-38f
-111 		3e0-3ef
-
-
-DIP Switches 1-5 of SW2 encode the RAM and ROM Adress Range:
-
-Switches        Ram           Rom
-12345           Adress Range  Address Range
-00000		C:0000-C:07ff	C:2000-C:3fff
-10000		C:0800-C:0fff
-01000		C:1000-C:17ff
-11000		C:1800-C:1fff
-00100		C:4000-C:47ff	C:6000-C:7fff
-10100		C:4800-C:4fff
-01100		C:5000-C:57ff 
-11100		C:5800-C:5fff
-00010		C:C000-C:C7ff	C:E000-C:ffff
-10010		C:C800-C:Cfff
-01010		C:D000-C:D7ff
-11010		C:D800-C:Dfff
-00110		D:0000-D:07ff	D:2000-D:3fff
-10110		D:0800-D:0fff
-01110		D:1000-D:17ff
-11110		D:1800-D:1fff
-00001		D:4000-D:47ff	D:6000-D:7fff
-10001		D:4800-D:4fff
-01001		D:5000-D:57ff
-11001		D:5800-D:5fff
-00101		D:8000-D:87ff	D:A000-D:bfff
-10101		D:8800-D:8fff
-01101		D:9000-D:97ff
-11101		D:9800-D:9fff 
-00011		D:C000-D:c7ff	D:E000-D:ffff
-10011		D:C800-D:cfff
-01011		D:D000-D:d7ff
-11011		D:D800-D:dfff
-00111		E:0000-E:07ff	E:2000-E:3fff
-10111		E:0800-E:0fff
-01111		E:1000-E:17ff
-11111		E:1800-E:1fff
-
-
-*****************************************************************************
-
-** PureData Corp **
-PDI507 (16-bit card)
---------------------
-	- from Mark Rejhon <mdrejhon@magi.com> (slight modifications by
-	  Avery)
-	- Send questions/suggestions/etc about this text to Mark.
-
-Jumpers:
-
-	There is a jumper array at the bottom of the card, near the edge
-        connector.  This array is labelled J1.  They control the IRQs and
-        something else.  Put only one jumper on the IRQ pins.
-
-	IRQ2    - Use IRQ 2 (same as IRQ 9 as far as software is concerned)
-	IRQ3	- Use IRQ 3 (used by COM2 or COM4 serial port if either exists)
-	IRQ4	- Use IRQ 4 (used by COM1 or COM3 serial port if either exists)
-	IRQ5	- Use IRQ 5 (used by LPT2 parallel port if one exists)
-	IRQ6	- Use IRQ 6 (used by Floppy Disk Controller if one exists)
-	IRQ7	- Use IRQ 7 (used by LPT1 parallel port if one exists)
-
-[Avery's note:  This "unknown" set of two jumpers appears to be on all
-ARCnet cards by SMC as well.  Putting jumpers on them seems to affect the
-status register, but only for the two "reserved" bits, ETS1 and ETS2.  Any
-further information is welcome.]
-
-	ET1	- What is this?  (Not tested, no jumper put on it)
-	ET2	- What is this?  (Not tested, no jumper put on it)
-
-	There is a J2 jumper on two pins.  A jumper should be put on them,
-        since it was already there when I got the card.  I don't know what
-        this jumper is for though.
-
-	There is a two-jumper array for J3.  I don't know what it is for,
-        but there were already two jumpers on it when I got the card.  It's
-        a six pin grid in a two-by-three fashion.  The jumpers were
-        configured as follows:
-
-	   .-------.
-	 o | o   o |
-	   :-------:    ------> Accessible end of card with connectors
-	 o | o   o |             in this direction ------->
-	   `-------'
-
-	There is also a J4 jumper on two pins.  A jumper should be put on
-        them, since it was already there when I got the card.  I don't know
-        what this jumper is for though.
-
-
-DIP Switches:
-
-	The dipswitches accessible on the accessible end of the card while
-        it is installed, is used to set the arcnet address.  There are 8
-        switches.  Use an address from 1 to 254.
-
-	Switch No.
-	12345678	Arcnet address
-	-----------------------------------------
-	00000000	FF  	(Don't use this!)
-	00000001	FE
-	00000010	FD
-	....
-	11111101	2	
-	11111110	1
-	11111111	0	(Don't use this!)
-
-	There is another dipswitch array of 8 switches at the top of the
-        card.  There are five labelled MS0-MS4 which seem to control the
-        memory address, and another three labelled IO0-IO2 which seem to
-        control the base I/O address of the card.
-
-	This was difficult to test by trial and error, and the I/O addresses
-        are in a weird order.  This was tested by setting the DIP switches,
-        rebooting the computer, and attempting to load ARCETHER at various
-        addresses (mostly between 0x200 and 0x400).  The address that caused
-        the red transmit LED to blink, is the one that I thought works.
-
-	Also, the address 0x3D0 seem to have a special meaning, since the
-        ARCETHER packet driver loaded fine, but without the red LED
-        blinking.  I don't know what 0x3D0 is for though.  I recommend using
-        an address of 0x300 since Windows may not like addresses below
-        0x300.
-
-	IO Switch No.
-	210             I/O address
-	-------------------------------
-	111             0x260
-	110             0x290
-	101             0x2E0
-	100             0x2F0
-	011             0x300
-	010             0x350
-	001             0x380
-	000             0x3E0
-
-	The memory switches set a reserved address space of 0x1000 bytes
-        (0x100 segment units, or 4k).  For example if I set an address of
-        0xD000, it will use up addresses 0xD000 to 0xD100.
-
-	The memory switches were tested by booting using QEMM386 stealth,
-        and using LOADHI to see what address automatically became excluded
-        from the upper memory regions, and then attempting to load ARCETHER
-        using these addresses.
-
-	I recommend using an arcnet memory address of 0xD000, and putting
-        the EMS page frame at 0xC000 while using QEMM stealth mode.  That
-        way, you get contiguous high memory from 0xD100 almost all the way
-        the end of the megabyte.
-
-	Memory Switch 0 (MS0) didn't seem to work properly when set to OFF
-        on my card.  It could be malfunctioning on my card.  Experiment with
-        it ON first, and if it doesn't work, set it to OFF.  (It may be a
-        modifier for the 0x200 bit?)
-
-	MS Switch No.
-	43210           Memory address
-	--------------------------------
-	00001           0xE100  (guessed - was not detected by QEMM)
-	00011           0xE000  (guessed - was not detected by QEMM)
-	00101           0xDD00
-	00111           0xDC00
-	01001           0xD900
-	01011           0xD800
-	01101           0xD500
-	01111           0xD400
-	10001           0xD100
-	10011           0xD000
-	10101           0xCD00
-	10111           0xCC00
-	11001           0xC900 (guessed - crashes tested system)
-	11011           0xC800 (guessed - crashes tested system)
-	11101           0xC500 (guessed - crashes tested system)
-	11111           0xC400 (guessed - crashes tested system)
-	
-	
-*****************************************************************************
-
-** CNet Technology Inc. **
-120 Series (8-bit cards)
-------------------------
-  - from Juergen Seifert <seifert@htwm.de>
-
-
-CNET TECHNOLOGY INC. (CNet) ARCNET 120A SERIES
-==============================================
-
-This description has been written by Juergen Seifert <seifert@htwm.de>
-using information from the following Original CNet Manual 
-
-              "ARCNET
-            USER'S MANUAL 
-                for
-               CN120A
-               CN120AB
-               CN120TP
-               CN120ST
-               CN120SBT
-             P/N:12-01-0007
-             Revision 3.00"
-
-ARCNET is a registered trademark of the Datapoint Corporation
-
-P/N 120A   ARCNET 8 bit XT/AT Star
-P/N 120AB  ARCNET 8 bit XT/AT Bus
-P/N 120TP  ARCNET 8 bit XT/AT Twisted Pair
-P/N 120ST  ARCNET 8 bit XT/AT Star, Twisted Pair
-P/N 120SBT ARCNET 8 bit XT/AT Star, Bus, Twisted Pair
-
-    __________________________________________________________________
-   |                                                                  |
-   |                                                               ___|
-   |                                                          LED |___|
-   |                                                               ___|
-   |                                                            N |   | ID7
-   |                                                            o |   | ID6
-   |                                                            d | S | ID5
-   |                                                            e | W | ID4
-   |                     ___________________                    A | 2 | ID3
-   |                    |                   |                   d |   | ID2
-   |                    |                   |  1 2 3 4 5 6 7 8  d |   | ID1
-   |                    |                   | _________________ r |___| ID0
-   |                    |      90C65        ||       SW1       |  ____|
-   |  JP 8 7            |                   ||_________________| |    |
-   |    |o|o|  JP1      |                   |                    | J2 |
-   |    |o|o|  |oo|     |                   |         JP 1 1 1   |    |
-   |   ______________   |                   |            0 1 2   |____|
-   |  |  PROM        |  |___________________|           |o|o|o|  _____|
-   |  >  SOCKET      |  JP 6 5 4 3 2                    |o|o|o| | J1  |
-   |  |______________|    |o|o|o|o|o|                   |o|o|o| |_____|
-   |_____                 |o|o|o|o|o|                   ______________|
-         |                                             |
-         |_____________________________________________|
-
-Legend:
-
-90C65       ARCNET Probe
-S1  1-5:    Base Memory Address Select
-    6-8:    Base I/O Address Select
-S2  1-8:    Node ID Select (ID0-ID7)
-JP1     ROM Enable Select
-JP2     IRQ2
-JP3     IRQ3
-JP4     IRQ4
-JP5     IRQ5
-JP6     IRQ7
-JP7/JP8     ET1, ET2 Timeout Parameters
-JP10/JP11   Coax / Twisted Pair Select  (CN120ST/SBT only)
-JP12        Terminator Select       (CN120AB/ST/SBT only)
-J1      BNC RG62/U Connector        (all except CN120TP)
-J2      Two 6-position Telephone Jack   (CN120TP/ST/SBT only)
-
-Setting one of the switches to Off means "1", On means "0".
-
-
-Setting the Node ID
--------------------
-
-The eight switches in SW2 are used to set the node ID. Each node attached
-to the network must have an unique node ID which must be diffrent from 0.
-Switch 1 (ID0) serves as the least significant bit (LSB).
-
-The node ID is the sum of the values of all switches set to "1"  
-These values are:
-
-   Switch | Label | Value
-   -------|-------|-------
-     1    | ID0   |   1
-     2    | ID1   |   2
-     3    | ID2   |   4
-     4    | ID3   |   8
-     5    | ID4   |  16
-     6    | ID5   |  32
-     7    | ID6   |  64
-     8    | ID7   | 128
-
-Some Examples:
-
-    Switch         | Hex     | Decimal 
-   8 7 6 5 4 3 2 1 | Node ID | Node ID
-   ----------------|---------|---------
-   0 0 0 0 0 0 0 0 |    not allowed
-   0 0 0 0 0 0 0 1 |    1    |    1 
-   0 0 0 0 0 0 1 0 |    2    |    2
-   0 0 0 0 0 0 1 1 |    3    |    3
-       . . .       |         |
-   0 1 0 1 0 1 0 1 |   55    |   85
-       . . .       |         |
-   1 0 1 0 1 0 1 0 |   AA    |  170
-       . . .       |         |  
-   1 1 1 1 1 1 0 1 |   FD    |  253
-   1 1 1 1 1 1 1 0 |   FE    |  254
-   1 1 1 1 1 1 1 1 |   FF    |  255
-
-
-Setting the I/O Base Address
-----------------------------
-
-The last three switches in switch block SW1 are used to select one
-of eight possible I/O Base addresses using the followig table
-
-
-   Switch      | Hex I/O
-    6   7   8  | Address
-   ------------|--------
-   ON  ON  ON  |  260
-   OFF ON  ON  |  290
-   ON  OFF ON  |  2E0  (Manufactor's default)
-   OFF OFF ON  |  2F0
-   ON  ON  OFF |  300
-   OFF ON  OFF |  350
-   ON  OFF OFF |  380
-   OFF OFF OFF |  3E0
-
-
-Setting the Base Memory (RAM) buffer Address
---------------------------------------------
-
-The memory buffer (RAM) requires 2K. The base of this buffer can be 
-located in any of eight positions. The address of the Boot Prom is
-memory base + 8K or memory base + 0x2000.
-Switches 1-5 of switch block SW1 select the Memory Base address.
-
-   Switch              | Hex RAM | Hex ROM
-    1   2   3   4   5  | Address | Address *)
-   --------------------|---------|-----------
-   ON  ON  ON  ON  ON  |  C0000  |  C2000
-   ON  ON  OFF ON  ON  |  C4000  |  C6000
-   ON  ON  ON  OFF ON  |  CC000  |  CE000
-   ON  ON  OFF OFF ON  |  D0000  |  D2000  (Manufactor's default)
-   ON  ON  ON  ON  OFF |  D4000  |  D6000
-   ON  ON  OFF ON  OFF |  D8000  |  DA000
-   ON  ON  ON  OFF OFF |  DC000  |  DE000
-   ON  ON  OFF OFF OFF |  E0000  |  E2000
-  
-*) To enable the Boot ROM install the jumper JP1
-
-Note: Since the switches 1 and 2 are always set to ON it may be possible
-      that they can be used to add an offset of 2K, 4K or 6K to the base
-      address, but this feature is not documented in the manual and I
-      haven't testet it yet.
-
-
-Setting the Interrupt Line
---------------------------
-
-To select a hardware interrupt level install one (only one!) of the jumpers
-JP2, JP3, JP4, JP5, JP6. JP2 is the default.
-
-   Jumper | IRQ     
-   -------|-----
-     2    |  2
-     3    |  3
-     4    |  4
-     5    |  5
-     6    |  7
-
-
-Setting the Internal Terminator on CN120AB/TP/SBT
---------------------------------------------------
-
-The jumper JP12 is used to enable the internal terminator. 
-
-                         -----
-       0                |  0  |     
-     -----   ON         |     |  ON
-    |  0  |             |  0  |
-    |     |  OFF         -----   OFF
-    |  0  |                0
-     -----
-   Terminator          Terminator 
-    disabled            enabled
-  
-
-Selecting the Connector Type on CN120ST/SBT
--------------------------------------------
-
-     JP10    JP11        JP10    JP11
-                         -----   -----
-       0       0        |  0  | |  0  |       
-     -----   -----      |     | |     |
-    |  0  | |  0  |     |  0  | |  0  |
-    |     | |     |      -----   -----
-    |  0  | |  0  |        0       0 
-     -----   -----
-     Coaxial Cable       Twisted Pair Cable 
-       (Default)
-
-
-Setting the Timeout Parameters
-------------------------------
-
-The jumpers labeled EXT1 and EXT2 are used to determine the timeout 
-parameters. These two jumpers are normally left open.
-
-
-
-*****************************************************************************
-
-** CNet Technology Inc. **
-160 Series (16-bit cards)
--------------------------
-  - from Juergen Seifert <seifert@htwm.de>
-
-CNET TECHNOLOGY INC. (CNet) ARCNET 160A SERIES
-==============================================
-
-This description has been written by Juergen Seifert <seifert@htwm.de>
-using information from the following Original CNet Manual 
-
-              "ARCNET
-            USER'S MANUAL 
-                for
-               CN160A
-               CN160AB
-               CN160TP
-             P/N:12-01-0006
-             Revision 3.00"
-
-ARCNET is a registered trademark of the Datapoint Corporation
-
-P/N 160A   ARCNET 16 bit XT/AT Star
-P/N 160AB  ARCNET 16 bit XT/AT Bus
-P/N 160TP  ARCNET 16 bit XT/AT Twisted Pair
-
-   ___________________________________________________________________
-  <                             _________________________          ___|
-  >               |oo| JP2     |                         |    LED |___|
-  <               |oo| JP1     |        9026             |    LED |___|
-  >                            |_________________________|         ___|
-  <                                                             N |   | ID7
-  >                                                      1      o |   | ID6
-  <                                    1 2 3 4 5 6 7 8 9 0      d | S | ID5
-  >         _______________           _____________________     e | W | ID4
-  <        |     PROM      |         |         SW1         |    A | 2 | ID3
-  >        >    SOCKET     |         |_____________________|    d |   | ID2
-  <        |_______________|          | IO-Base   | MEM   |     d |   | ID1
-  >                                                             r |___| ID0
-  <                                                               ____|
-  >                                                              |    |
-  <                                                              | J1 |
-  >                                                              |    |
-  <                                                              |____|
-  >                            1 1 1 1                                |
-  <  3 4 5 6 7      JP     8 9 0 1 2 3                                |
-  > |o|o|o|o|o|           |o|o|o|o|o|o|                               |
-  < |o|o|o|o|o| __        |o|o|o|o|o|o|                    ___________|
-  >            |  |                                       |
-  <____________|  |_______________________________________|
-
-Legend:
-
-9026            ARCNET Probe
-SW1 1-6:    Base I/O Address Select
-    7-10:   Base Memory Address Select
-SW2 1-8:    Node ID Select (ID0-ID7)
-JP1/JP2     ET1, ET2 Timeout Parameters
-JP3-JP13    Interrupt Select
-J1      BNC RG62/U Connector        (CN160A/AB only)
-J1      Two 6-position Telephone Jack   (CN160TP only)
-LED
-
-Setting one of the switches to Off means "1", On means "0".
-
-
-Setting the Node ID
--------------------
-
-The eight switches in SW2 are used to set the node ID. Each node attached
-to the network must have an unique node ID which must be diffrent from 0.
-Switch 1 (ID0) serves as the least significant bit (LSB).
-
-The node ID is the sum of the values of all switches set to "1"  
-These values are:
-
-   Switch | Label | Value
-   -------|-------|-------
-     1    | ID0   |   1
-     2    | ID1   |   2
-     3    | ID2   |   4
-     4    | ID3   |   8
-     5    | ID4   |  16
-     6    | ID5   |  32
-     7    | ID6   |  64
-     8    | ID7   | 128
-
-Some Examples:
-
-    Switch         | Hex     | Decimal 
-   8 7 6 5 4 3 2 1 | Node ID | Node ID
-   ----------------|---------|---------
-   0 0 0 0 0 0 0 0 |    not allowed
-   0 0 0 0 0 0 0 1 |    1    |    1 
-   0 0 0 0 0 0 1 0 |    2    |    2
-   0 0 0 0 0 0 1 1 |    3    |    3
-       . . .       |         |
-   0 1 0 1 0 1 0 1 |   55    |   85
-       . . .       |         |
-   1 0 1 0 1 0 1 0 |   AA    |  170
-       . . .       |         |  
-   1 1 1 1 1 1 0 1 |   FD    |  253
-   1 1 1 1 1 1 1 0 |   FE    |  254
-   1 1 1 1 1 1 1 1 |   FF    |  255
-
-
-Setting the I/O Base Address
-----------------------------
-
-The first six switches in switch block SW1 are used to select the I/O Base
-address using the followig table:
-
-             Switch        | Hex I/O
-    1   2   3   4   5   6  | Address
-   ------------------------|--------
-   OFF ON  ON  OFF OFF ON  |  260
-   OFF ON  OFF ON  ON  OFF |  290
-   OFF ON  OFF OFF OFF ON  |  2E0  (Manufactor's default)
-   OFF ON  OFF OFF OFF OFF |  2F0
-   OFF OFF ON  ON  ON  ON  |  300
-   OFF OFF ON  OFF ON  OFF |  350
-   OFF OFF OFF ON  ON  ON  |  380
-   OFF OFF OFF OFF OFF ON  |  3E0
-
-Note: Other IO-Base addresses seem to be selectable, but only the above
-      combinations are documented.
-
-
-Setting the Base Memory (RAM) buffer Address
---------------------------------------------
-
-The switches 7-10 of switch block SW1 are used to select the Memory
-Base address of the RAM (2K) and the PROM.
-
-   Switch          | Hex RAM | Hex ROM
-    7   8   9  10  | Address | Address
-   ----------------|---------|-----------
-   OFF OFF ON  ON  |  C0000  |  C8000
-   OFF OFF ON  OFF |  D0000  |  D8000 (Default)
-   OFF OFF OFF ON  |  E0000  |  E8000
-
-Note: Other MEM-Base addresses seem to be selectable, but only the above
-      combinations are documented.
-
-
-Setting the Interrupt Line
---------------------------
-
-To select a hardware interrupt level install one (only one!) of the jumpers
-JP3 through JP13 using the following table:
-
-   Jumper | IRQ     
-   -------|-----------------
-     3    |  14
-     4    |  15
-     5    |  12
-     6    |  11
-     7    |  10
-     8    |   3
-     9    |   4
-    10    |   5
-    11    |   6
-    12    |   7
-    13    |   2 (=9) Default!
-
-Note:  - Do not use JP11=IRQ6, it may conflict with your Floppy Disk
-         Controler
-       - Use JP3=IRQ14 only, if you don't have an IDE-, MFM-, or RLL-
-         Hard Disk, it may conflict with their controlers
-
-
-Setting the Timeout Parameters
-------------------------------
-
-The jumpers labeled JP1 and JP2 are used to determine the timeout
-parameters. These two jumpers are normally left open.
-
-
-*****************************************************************************
-
-** No Name **
-8-bit cards, 16-bit cards
--------------------------
-  - from Juergen Seifert <seifert@htwm.de>
-  
-NONAME 8-BIT ARCNET
-===================
-
-I have named this ARCnet card "NONAME", since there is no name of any
-manufactor on the Installation manual nor on the shipping box. The only
-hint to the existence of a manufactor at all is written into cupper,
-it is "Made in Taiwan"
-
-This description has been written by Juergen Seifert <seifert@htwm.de>
-using information from the Original
-                    "ARCnet Installation Manual"
-
-
-    ________________________________________________________________
-   | |STAR| BUS| T/P|                                               |
-   | |____|____|____|                                               |
-   |                            _____________________               |
-   |                           |                     |              |
-   |                           |                     |              |
-   |                           |                     |              |
-   |                           |        SMC          |              |
-   |                           |                     |              |
-   |                           |       COM90C65      |              |
-   |                           |                     |              |
-   |                           |                     |              |
-   |                           |__________-__________|              |
-   |                                                           _____|
-   |      _______________                                     |  CN |
-   |     | PROM          |                                    |_____|
-   |     > SOCKET        |                                          |
-   |     |_______________|         1 2 3 4 5 6 7 8  1 2 3 4 5 6 7 8 |
-   |                               _______________  _______________ |
-   |           |o|o|o|o|o|o|o|o|  |      SW1      ||      SW2      ||
-   |           |o|o|o|o|o|o|o|o|  |_______________||_______________||
-   |___         2 3 4 5 7 E E R        Node ID       IOB__|__MEM____|
-       |        \ IRQ   / T T O                      |
-       |__________________1_2_M______________________|
-
-Legend:
-
-COM90C65:       Arcnet Probe
-S1  1-8:    Node ID Select
-S2  1-3:    I/O Base Address Select
-    4-6:    Memory Base Address Select
-    7-8:    RAM Offset Select
-ET1, ET2    Extended Timeout Select
-ROM     ROM Enable Select
-CN              RG62 Coax Connector
-STAR| BUS | T/P Three fields for placing a sign (colored circle)
-                indicating the topologie of the card
-
-Setting one of the switches to Off means "1", On means "0".
-
-
-Setting the Node ID
--------------------
-
-The eight switches in group SW1 are used to set the node ID.
-Each node attached to the network must have an unique node ID which
-must be diffrent from 0.
-Switch 8 serves as the least significant bit (LSB).
-
-The node ID is the sum of the values of all switches set to "1"  
-These values are:
-
-    Switch | Value
-    -------|-------
-      8    |   1
-      7    |   2
-      6    |   4
-      5    |   8
-      4    |  16
-      3    |  32
-      2    |  64
-      1    | 128
-
-Some Examples:
-
-    Switch         | Hex     | Decimal 
-   1 2 3 4 5 6 7 8 | Node ID | Node ID
-   ----------------|---------|---------
-   0 0 0 0 0 0 0 0 |    not allowed
-   0 0 0 0 0 0 0 1 |    1    |    1 
-   0 0 0 0 0 0 1 0 |    2    |    2
-   0 0 0 0 0 0 1 1 |    3    |    3
-       . . .       |         |
-   0 1 0 1 0 1 0 1 |   55    |   85
-       . . .       |         |
-   1 0 1 0 1 0 1 0 |   AA    |  170
-       . . .       |         |  
-   1 1 1 1 1 1 0 1 |   FD    |  253
-   1 1 1 1 1 1 1 0 |   FE    |  254
-   1 1 1 1 1 1 1 1 |   FF    |  255
-
-
-Setting the I/O Base Address
-----------------------------
-
-The first three switches in switch group SW2 are used to select one
-of eight possible I/O Base addresses using the followig table
-
-   Switch      | Hex I/O
-    1   2   3  | Address
-   ------------|--------
-   ON  ON  ON  |  260
-   ON  ON  OFF |  290
-   ON  OFF ON  |  2E0  (Manufactor's default)
-   ON  OFF OFF |  2F0
-   OFF ON  ON  |  300
-   OFF ON  OFF |  350
-   OFF OFF ON  |  380
-   OFF OFF OFF |  3E0
-
-
-Setting the Base Memory (RAM) buffer Address
---------------------------------------------
-
-The memory buffer requires 2K of a 16K block of RAM. The base of this
-16K block can be located in any of eight positions.
-Switches 4-6 of switch group SW2 select the Base of the 16K block.
-Within that 16K address space, the buffer may be assigned any one of four
-positions, determined by the offset, switches 7 and 8 of group SW2.
-
-   Switch     | Hex RAM | Hex ROM
-   4 5 6  7 8 | Address | Address *)
-   -----------|---------|-----------
-   0 0 0  0 0 |  C0000  |  C2000
-   0 0 0  0 1 |  C0800  |  C2000
-   0 0 0  1 0 |  C1000  |  C2000
-   0 0 0  1 1 |  C1800  |  C2000
-              |         |
-   0 0 1  0 0 |  C4000  |  C6000
-   0 0 1  0 1 |  C4800  |  C6000
-   0 0 1  1 0 |  C5000  |  C6000
-   0 0 1  1 1 |  C5800  |  C6000
-              |         |
-   0 1 0  0 0 |  CC000  |  CE000
-   0 1 0  0 1 |  CC800  |  CE000
-   0 1 0  1 0 |  CD000  |  CE000
-   0 1 0  1 1 |  CD800  |  CE000
-              |         |
-   0 1 1  0 0 |  D0000  |  D2000  (Manufactor's default)
-   0 1 1  0 1 |  D0800  |  D2000
-   0 1 1  1 0 |  D1000  |  D2000
-   0 1 1  1 1 |  D1800  |  D2000
-              |         |
-   1 0 0  0 0 |  D4000  |  D6000
-   1 0 0  0 1 |  D4800  |  D6000
-   1 0 0  1 0 |  D5000  |  D6000
-   1 0 0  1 1 |  D5800  |  D6000
-              |         |
-   1 0 1  0 0 |  D8000  |  DA000
-   1 0 1  0 1 |  D8800  |  DA000
-   1 0 1  1 0 |  D9000  |  DA000
-   1 0 1  1 1 |  D9800  |  DA000
-              |         |
-   1 1 0  0 0 |  DC000  |  DE000
-   1 1 0  0 1 |  DC800  |  DE000
-   1 1 0  1 0 |  DD000  |  DE000
-   1 1 0  1 1 |  DD800  |  DE000
-              |         |
-   1 1 1  0 0 |  E0000  |  E2000
-   1 1 1  0 1 |  E0800  |  E2000
-   1 1 1  1 0 |  E1000  |  E2000
-   1 1 1  1 1 |  E1800  |  E2000
-  
-*) To enable the 8K Boot PROM install the jumper ROM.
-   The default is jumper ROM not installed.
-
-
-Setting Interrupt Request Lines (IRQ)
--------------------------------------
-
-To select a hardware interrupt level set one (only one!) of the jumpers
-IRQ2, IRQ3, IRQ4, IRQ5 or IRQ7. The Manufactor's default is IRQ2.
- 
-
-Setting the Timeouts
---------------------
-
-The two jumpers labeled ET1 and ET2 are used to determine the timeout
-parameters (respons and reconfiguration time). Every node in a network
-must be set to the same timeout values.
-
-   ET1 ET2 | Response Time (us) | Reconfiguration Time (ms)
-   --------|--------------------|--------------------------
-   Off Off |        78          |          840   (Default)
-   Off On  |       285          |         1680
-   On  Off |       563          |         1680
-   On  On  |      1130          |         1680
-
-On means jumper installed, Off means jumper not installed
-
-
-NONAME 16-BIT ARCNET
-====================
-
-The manual of my 8-Bit NONAME ARCnet Card contains another description
-of a 16-Bit Coax / Twisted Pair Card. This description is incomplete,
-because there are missing two pages in the manual booklet. (The table
-of contents reports pages ... 2-9, 2-11, 2-12, 3-1, ... but inside
-the booklet there is a diffrent way of counting ... 2-9, 2-10, A-1,
-(empty page), 3-1, ..., 3-18, A-1 (again), A-2)
-Also the picture of the board layout is not as good as the picture of
-8-Bit card, because there isn't any letter like "SW1" written to the
-picture.
-Should somebody have such a board, please feel free to complete this
-description or to send a mail to me!
-
-This description has been written by Juergen Seifert <seifert@htwm.de>
-using information from the Original
-                    "ARCnet Installation Manual"
-
-
-   ___________________________________________________________________
-  <                    _________________  _________________           |
-  >                   |       SW?       ||      SW?        |          |
-  <                   |_________________||_________________|          |
-  >                       ____________________                        |
-  <                      |                    |                       |
-  >                      |                    |                       |
-  <                      |                    |                       |
-  >                      |                    |                       |
-  <                      |                    |                       |
-  >                      |                    |                       |
-  <                      |                    |                       |
-  >                      |____________________|                       |
-  <                                                               ____|
-  >                       ____________________                   |    |
-  <                      |                    |                  | J1 |
-  >                      |                    <                  |    |
-  <                      |____________________|  ? ? ? ? ? ?     |____|
-  >                                             |o|o|o|o|o|o|         |
-  <                                             |o|o|o|o|o|o|         |
-  >                                                                   |
-  <             __                                         ___________|
-  >            |  |                                       |
-  <____________|  |_______________________________________|
-
-
-Setting one of the switches to Off means "1", On means "0".
-
-
-Setting the Node ID
--------------------
-
-The eight switches in group SW2 are used to set the node ID.
-Each node attached to the network must have an unique node ID which
-must be diffrent from 0.
-Switch 8 serves as the least significant bit (LSB).
-
-The node ID is the sum of the values of all switches set to "1"  
-These values are:
-
-    Switch | Value
-    -------|-------
-      8    |   1
-      7    |   2
-      6    |   4
-      5    |   8
-      4    |  16
-      3    |  32
-      2    |  64
-      1    | 128
-
-Some Examples:
-
-    Switch         | Hex     | Decimal 
-   1 2 3 4 5 6 7 8 | Node ID | Node ID
-   ----------------|---------|---------
-   0 0 0 0 0 0 0 0 |    not allowed
-   0 0 0 0 0 0 0 1 |    1    |    1 
-   0 0 0 0 0 0 1 0 |    2    |    2
-   0 0 0 0 0 0 1 1 |    3    |    3
-       . . .       |         |
-   0 1 0 1 0 1 0 1 |   55    |   85
-       . . .       |         |
-   1 0 1 0 1 0 1 0 |   AA    |  170
-       . . .       |         |  
-   1 1 1 1 1 1 0 1 |   FD    |  253
-   1 1 1 1 1 1 1 0 |   FE    |  254
-   1 1 1 1 1 1 1 1 |   FF    |  255
-
-
-Setting the I/O Base Address
-----------------------------
-
-The first three switches in switch group SW1 are used to select one
-of eight possible I/O Base addresses using the followig table
-
-   Switch      | Hex I/O
-    3   2   1  | Address
-   ------------|--------
-   ON  ON  ON  |  260
-   ON  ON  OFF |  290
-   ON  OFF ON  |  2E0  (Manufactor's default)
-   ON  OFF OFF |  2F0
-   OFF ON  ON  |  300
-   OFF ON  OFF |  350
-   OFF OFF ON  |  380
-   OFF OFF OFF |  3E0
-
-
-Setting the Base Memory (RAM) buffer Address
---------------------------------------------
-
-The memory buffer requires 2K of a 16K block of RAM. The base of this
-16K block can be located in any of eight positions.
-Switches 6-8 of switch group SW1 select the Base of the 16K block.
-Within that 16K address space, the buffer may be assigned any one of four
-positions, determined by the offset, switches 4 and 5 of group SW1.
-
-   Switch     | Hex RAM | Hex ROM
-   8 7 6  5 4 | Address | Address
-   -----------|---------|-----------
-   0 0 0  0 0 |  C0000  |  C2000
-   0 0 0  0 1 |  C0800  |  C2000
-   0 0 0  1 0 |  C1000  |  C2000
-   0 0 0  1 1 |  C1800  |  C2000
-              |         |
-   0 0 1  0 0 |  C4000  |  C6000
-   0 0 1  0 1 |  C4800  |  C6000
-   0 0 1  1 0 |  C5000  |  C6000
-   0 0 1  1 1 |  C5800  |  C6000
-              |         |
-   0 1 0  0 0 |  CC000  |  CE000
-   0 1 0  0 1 |  CC800  |  CE000
-   0 1 0  1 0 |  CD000  |  CE000
-   0 1 0  1 1 |  CD800  |  CE000
-              |         |
-   0 1 1  0 0 |  D0000  |  D2000  (Manufactor's default)
-   0 1 1  0 1 |  D0800  |  D2000
-   0 1 1  1 0 |  D1000  |  D2000
-   0 1 1  1 1 |  D1800  |  D2000
-              |         |
-   1 0 0  0 0 |  D4000  |  D6000
-   1 0 0  0 1 |  D4800  |  D6000
-   1 0 0  1 0 |  D5000  |  D6000
-   1 0 0  1 1 |  D5800  |  D6000
-              |         |
-   1 0 1  0 0 |  D8000  |  DA000
-   1 0 1  0 1 |  D8800  |  DA000
-   1 0 1  1 0 |  D9000  |  DA000
-   1 0 1  1 1 |  D9800  |  DA000
-              |         |
-   1 1 0  0 0 |  DC000  |  DE000
-   1 1 0  0 1 |  DC800  |  DE000
-   1 1 0  1 0 |  DD000  |  DE000
-   1 1 0  1 1 |  DD800  |  DE000
-              |         |
-   1 1 1  0 0 |  E0000  |  E2000
-   1 1 1  0 1 |  E0800  |  E2000
-   1 1 1  1 0 |  E1000  |  E2000
-   1 1 1  1 1 |  E1800  |  E2000
-  
-
-Setting Interrupt Request Lines (IRQ)
--------------------------------------
-
-??????????????????????????????????????
-
-
-Setting the Timeouts
---------------------
-
-??????????????????????????????????????
-
-
-*****************************************************************************
-
-** No Name **
-8-bit cards ("Made in Taiwan R.O.C.")
------------
- - from Vojtech Pavlik <vpav4328@diana.troja.mff.cuni.cz>
-
-I have named this ARCnet card "NONAME", since I got only the card with
-no manual at all and the only text identifying the manufacturer is 
-"MADE IN TAIWAN R.O.C" printed on the card.
-
-This description was written by Vojtech Pavlik 
-(vpav4328@diana.troja.mff.cuni.cz) using parts of the ARCNET-jumpers 
-README file from Linux kernel 1.2.2. 
-
-          ____________________________________________________________
-         |                 1 2 3 4 5 6 7 8                            |
-         | |o|o| JP1       o|o|o|o|o|o|o|o| ON                        |
-         |  +              o|o|o|o|o|o|o|o|                        ___|
-         |  _____________  o|o|o|o|o|o|o|o| OFF         _____     |   | ID7
-         | |             | SW1                         |     |    |   | ID6
-         | > RAM (2k)    |        ____________________ |  H  |    | S | ID5
-         | |_____________|       |                    ||  y  |    | W | ID4
-         |                       |                    ||  b  |    | 2 | ID3
-         |                       |                    ||  r  |    |   | ID2
-         |                       |                    ||  i  |    |   | ID1
-         |                       |       90C65        ||  d  |    |___| ID0
-         |      SW3              |                    ||     |        |      
-         | |o|o|o|o|o|o|o|o| ON  |                    ||  I  |        |
-         | |o|o|o|o|o|o|o|o|     |                    ||  C  |        |
-         | |o|o|o|o|o|o|o|o| OFF |____________________||     |   _____|
-         |  1 2 3 4 5 6 7 8                            |     |  |     |___
-         |  ______________                             |     |  | BNC |___|
-         | |              |                            |_____|  |_____|
-         | > EPROM SOCKET |                                           |
-         | |______________|                                           |
-         |                                              ______________|
-         |                                             |
-         |_____________________________________________|
-
-Legend:
-
-90C65       ARCNET Chip 
-SW1 1-5:    Base Memory Address Select
-    6-8:    Base I/O Address Select
-SW2 1-8:    Node ID Select (ID0-ID7)
-SW3 1-5:    IRQ Select   
-    6-7:    Extra Timeout
-    8  :    Rom Enable   
-JP1         Led connector
-BNC         Coax connector
-
-Although the jumpers SW1 and SW3 are marked SW, not JP, they are jumpers, not 
-switches.
-
-Setting the jumpers to ON means connecting the upper two pins, off the bottom 
-two - or - in case of IRQ setting, connecting none of them at all.
-
-Setting the Node ID
--------------------
-
-The eight switches in SW2 are used to set the node ID. Each node attached
-to the network must have an unique node ID which must be diffrent from 0.
-Switch 1 (ID0) serves as the least significant bit (LSB).
-
-Setting one of the switches to Off means "1", On means "0".
-
-The node ID is the sum of the values of all switches set to "1"  
-These values are:
-
-   Switch | Label | Value
-   -------|-------|-------
-     1    | ID0   |   1
-     2    | ID1   |   2
-     3    | ID2   |   4
-     4    | ID3   |   8
-     5    | ID4   |  16
-     6    | ID5   |  32
-     7    | ID6   |  64
-     8    | ID7   | 128
-
-Some Examples:
-
-    Switch         | Hex     | Decimal 
-   8 7 6 5 4 3 2 1 | Node ID | Node ID
-   ----------------|---------|---------
-   0 0 0 0 0 0 0 0 |    not allowed
-   0 0 0 0 0 0 0 1 |    1    |    1 
-   0 0 0 0 0 0 1 0 |    2    |    2
-   0 0 0 0 0 0 1 1 |    3    |    3
-       . . .       |         |
-   0 1 0 1 0 1 0 1 |   55    |   85
-       . . .       |         |
-   1 0 1 0 1 0 1 0 |   AA    |  170
-       . . .       |         |  
-   1 1 1 1 1 1 0 1 |   FD    |  253
-   1 1 1 1 1 1 1 0 |   FE    |  254
-   1 1 1 1 1 1 1 1 |   FF    |  255
-
-
-Setting the I/O Base Address
-----------------------------
-
-The last three switches in switch block SW1 are used to select one
-of eight possible I/O Base addresses using the followig table
-
-
-   Switch      | Hex I/O
-    6   7   8  | Address
-   ------------|--------
-   ON  ON  ON  |  260
-   OFF ON  ON  |  290
-   ON  OFF ON  |  2E0  (Manufactor's default)
-   OFF OFF ON  |  2F0
-   ON  ON  OFF |  300
-   OFF ON  OFF |  350
-   ON  OFF OFF |  380
-   OFF OFF OFF |  3E0
-
-
-Setting the Base Memory (RAM) buffer Address
---------------------------------------------
-
-The memory buffer (RAM) requires 2K. The base of this buffer can be 
-located in any of eight positions. The address of the Boot Prom is
-memory base + 0x2000.
-Jumpers 3-5 of jumper block SW1 select the Memory Base address.
-
-   Switch              | Hex RAM | Hex ROM
-    1   2   3   4   5  | Address | Address *)
-   --------------------|---------|-----------
-   ON  ON  ON  ON  ON  |  C0000  |  C2000
-   ON  ON  OFF ON  ON  |  C4000  |  C6000
-   ON  ON  ON  OFF ON  |  CC000  |  CE000
-   ON  ON  OFF OFF ON  |  D0000  |  D2000  (Manufactor's default)
-   ON  ON  ON  ON  OFF |  D4000  |  D6000
-   ON  ON  OFF ON  OFF |  D8000  |  DA000
-   ON  ON  ON  OFF OFF |  DC000  |  DE000
-   ON  ON  OFF OFF OFF |  E0000  |  E2000
-  
-*) To enable the Boot ROM set the jumper 8 of jumper block SW3 to position ON.
-
-The jumpers 1 and 2 probably add 0x0800, 0x1000 and 0x1800 to RAM addres.
-
-Setting the Interrupt Line
---------------------------
-
-Jumpers 1-5 of the jumper block SW3 controll the IRQ level.
-
-    Jumper              |  IRQ
-    1   2   3   4   5   |
-   ----------------------------
-    ON  OFF OFF OFF OFF |  2
-    OFF ON  OFF OFF OFF |  3
-    OFF OFF ON  OFF OFF |  4
-    OFF OFF OFF ON  OFF |  5
-    OFF OFF OFF OFF ON  |  7
-
-
-Setting the Timeout Parameters
-------------------------------
-
-The jumpers 6-7 of the jumper block SW3 are used to determine the timeout 
-parameters. These two jumpers are normally left in the OFF position.
-
-
-*****************************************************************************
-** Tiara **
-(model unknown)
--------------------------
-  - from Christoph Lameter <clameter@netcom.com>
-  
-
-Here is information about my card as far as I could figure it out:
------------------------------------------------ tiara
-Tiara LanCard of Tiara Computer Systems.
-
-+----------------------------------------------+
-!           ! Transmitter Unit !               !
-!           +------------------+             -------
-!          MEM                              Coax Connector
-!  ROM    7654321 <- I/O                     -------
-!  :  :   +--------+                           !
-!  :  :   ! 90C66LJ!                         +++
-!  :  :   !        !                         !D  Switch to set
-!  :  :   !        !                         !I  the Nodenumber
-!  :  :   +--------+                         !P
-!                                            !++
-!         234567 <- IRQ                      !
-+------------!!!!!!!!!!!!!!!!!!!!!!!!--------+
-             !!!!!!!!!!!!!!!!!!!!!!!!
-
-0 = Jumper Installed
-1 = Open
-
-Top Jumper line Bit 7 = Rom Enable 654=Memory location 321=I/O
-
-Settings for Memory Location (Top Jumper Line)
-456     Address selected
-000	C0000
-001     C4000
-010     CC000
-011     D0000
-100     D4000
-101     D8000
-110     DC000     
-111     E0000
-
-Settings for I/O Address (Top Jumper Line)
-123     Port
-000	260
-001	290
-010	2E0
-011	2F0
-100	300
-101	350
-110	380
-111	3E0
-
-Settings for IRQ Selection (Lower Jumper Line)
-234567
-011111 IRQ 2
-101111 IRQ 3
-110111 IRQ 4
-111011 IRQ 5
-111110 IRQ 7
-
-*****************************************************************************
-
-
-Other Cards
------------
-
-I have no information on other models of ARCnet cards at the moment.  Please
-send any and all info to:
-	apenwarr@foxnet.net
-
-Thanks.
diff -u --recursive --new-file v1.3.21/linux/drivers/net/README.modules linux/drivers/net/README.modules
--- v1.3.21/linux/drivers/net/README.modules	Sun Aug 13 14:45:30 1995
+++ linux/drivers/net/README.modules	Thu Jan  1 02:00:00 1970
@@ -1,251 +0,0 @@
-Wed 2-Aug-95  <matti.aarnio@utu.fi>
-
-		Linux network driver modules
-
-	Do not mistake this to "README.modules" at the top-level
-	directory!  That document tells about modules in general, while
-	this one tells only about network device driver modules.
-
-	This is a potpourri of INSMOD-time(*) configuration options
-	(if such exists) and their default values of various modules
-	on Linux network drivers collection.
-
-	Some modules have also hidden (= non-documented) tunable values.
-	Choice of not documenting them is based on general belief, that
-	the less user needs to know, the better.  (There are things that
-	driver developer can use, others should not confuse themselves.)
-
-	In many cases it is highly preferred that insmod:ing is done
-	ONLY with defining an explicite address for the card, AND BY
-	NOT USING AUTO-PROBING!
-
-	Now most cards have some explicitely defined base address, they
-	are compiled with (to avoid auto-probing, among other things).
-	If that compiled value does not match your actual configuration,
-	do use  "io=0xXXX" -parameter for the  insmod, and give there
-	a value matching your environment.
-
-	If you are adventureous, you can ask the driver to autoprobe
-	by using "io=0" parameter, however it is potentially dangerous
-	thing to do in a live system.  (If you don't know where the
-	card is located, you can try autoprobing, and after possible
-	crash recovery, insmod with proper IO-address..)
-
-	--------------------------
-	(*)	"INSMOD-time" means when you load module with
-		/sbin/insmod  you can feed it optional parameters.
-		See "man insmod".
-	--------------------------
-
-
-3c501.c:
-	io  = 0x280	IO base address
-	irq = 5		IRQ
-	(Probes ports:	0x280, 0x300)
-
-3c503.c:
-	io = 0x300
-	irq = 0
-	(Probes ports: 0x300, 0x310, 0x330, 0x350, 0x250, 0x280, 0x2A0, 0x2E0)
-
-3c505.c:
-	io = 0x300
-	irq = 0
-	(Probes ports: 0x300, 0x280, 0x310)
-
-3c507.c:
-	io = 0x300
-	irq = 0
-	(Probes ports: 0x300, 0x320, 0x340, 0x280)
-
-3c509.c:
-	io = 0
-	irq = 0
-	( Module load-time probing Works reliably only on EISA, ISA ID-PROBE
-	  IS NOT RELIABLE!  Compile this driver statically into kernel for
-	  now, if you need it auto-probing on an ISA-bus machine. )
-
-8390.c:
-	(No public options, several other modules need this one)
-
-ac3200.c:
-	io = 0
-	irq = 0
-	(EISA probing..)
-
-apricot.c:
-	io = 0x300  (Can't be altered!)
-	irq = 10
-
-arcnet.c:
-	io = 0
-	irqnum = 0
-	shmem = 0
-	num = 0
-	DO SET THESE MANUALLY AT INSMOD!
-	(When probing, looks at the following possible addresses:
-	 Suggested ones:
-		0x300, 0x2E0, 0x2F0, 0x2D0
-	 Other ones:
-		0x200, 0x210, 0x220, 0x230, 0x240, 0x250, 0x260, 0x270,
-		0x280, 0x290, 0x2A0, 0x2B0, 0x2C0,
-		       0x310, 0x320, 0x330, 0x340, 0x350, 0x360, 0x370,
-		0x380, 0x390, 0x3A0,			  0x3E0, 0x3F0  )
-
-at1700.c:
-	io = 0x260
-	irq = 0
-	(Probes ports: 0x260, 0x280, 0x2A0, 0x240, 0x340, 0x320, 0x380, 0x300)
-
-atp.c: *Not modularized*
-	(Probes ports: 0x378, 0x278, 0x3BC;
-	 fixed IRQs: 5 and 7			)
-
-
-auto_irq.c: *Static kernel component*
-
-
-de4x5.c:
-	io = 0x000b
-	irq = 10
-	is_not_dec = 0  -- For SMC card using DEC 21140 set this to 1
-	(EISA, and PCI probing)
-
-de600.c:
-	de600_debug = 0
-	(On port 0x378, irq 7 -- lpt1;  compile time configurable)
-
-de620.c:
-	bnc = 0, utp = 0  <-- Force media by setting either.
-	io = 0x378	(also compile-time configurable)
-	irq = 7
-
-depca.c:
-	io = 0x200
-	irq = 7
-	(Probes ports:	ISA:  0x300, 0x200;
-			EISA: 0x0c00		)
-
-dummy.c:
-	No options
-
-e2100.c:
-	io = 0x300
-	irq = 0
-	(Probes ports: 0x300, 0x280, 0x380, 0x220)
-
-eepro.c:
-	io = 0x200
-	irq = 0
-	(Probes ports: 0x200, 0x240, 0x280, 0x2C0, 0x300, 0x320, 0x340, 0x360)
-
-eexpress.c:
-	io = 0x300
-	irq = 0
-	(Probes ports: 0x300, 0x270, 0x320, 0x340)
-
-eql.c:
-	(No parameters)
-
-ewrk3.c:
-	io = 0x300
-	irq = 5
-	(With module no autoprobing!
-	 On EISA-bus does EISA probing.
-	 Static linkage probes ports on ISA bus:
-		0x100, 0x120, 0x140, 0x160, 0x180, 0x1A0, 0x1C0,
-		0x200, 0x220, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x2E0,
-		0x300,        0x340, 0x360, 0x380, 0x3A0, 0x3C0)
-
-hp-plus.c:
-	io = 0x200
-	irq = 0
-	(Probes ports: 0x200, 0x240, 0x280, 0x2C0, 0x300, 0x320, 0x340)
-
-hp.c:
-	io = 0x300
-	irq = 0
-	(Probes ports: 0x300, 0x320, 0x340, 0x280, 0x2C0, 0x200, 0x240)
-
-hp100.c:
-	hp100_port = 0 (IO-base address)
-	(Does EISA-probing, if on EISA-slot;
-	 On ISA-bus probes all ports from 0x100 thru to 0x3E0
-	 in increments of 0x020)
-
-ibmtr.c:
-	io = 0xA20
-	(Probes ports: 0xA20, 0xA24 -- Ok, 0x220, 0x224, but IBM style..)
-
-lance.c: *Not modularized*
-	(PCI, and ISA probing; "CONFIG_PCI" needed for PCI support)
-	(Probes ISA ports: 0x300, 0x320, 0x340, 0x360)
-
-loopback.c: *Static kernel component*
-
-ne.c:
-	io = 0x300
-	irq = 0
-	(Probes ports: 0x300, 0x280, 0x320, 0x340, 0x360)
-
-net_init.c: *Static kernel component*
-
-ni52.c: *Not modularized*
-	(Probes ports:	0x300, 0x280, 0x360, 0x320, 0x340
-		mems:	0xD0000, 0xD2000, 0xC8000, 0xCA000,
-			0xD4000, 0xD6000, 0xD8000 )
-
-ni65.c: *Not modularized*  **16MB MEMORY BARRIER BUG**
-	(Probes ports:	0x300, 0x320, 0x340, 0x360)
-
-pi2.c:	*Not modularized* (well, NON-STANDARD modularization!)
-	Only one card supported at this time.
-	(Probes ports: 0x380, 0x300, 0x320, 0x340, 0x360, 0x3A0)
-
-plip.c:
-	No options; goes to IO=0x278, IRQ=2
-
-ppp.c:
-	No options (ppp-2.2+ has some, this is based on non-dynamic
-	version from ppp-2.1.2d)
-
-seeq8005.c: *Not modularized*
-	(Probes ports: 0x300, 0x320, 0x340, 0x360)
-
-sk_g16.c: *Not modularized*
-	(Probes ports: 0x100, 0x180, 0x208, 0x220m 0x288, 0x320, 0x328, 0x390)
-
-skeleton.c: *Skeleton*
-
-slhc.c:
-	No configuration parameters
-
-slip.c:
-	slip_maxdev = 256 (default value from SL_NRUNIT on slip.h)
-
-
-smc-ultra.c:
-	io = 0x200
-	irq = 0
-	(Probes ports:	0x200, 0x220, 0x240, 0x280, 0x300, 0x340, 0x380)
-
-tulip.c: *Partial modularization*
-	(init-time memory allocation makes problems..)
-
-tunnel.c:
-	No insmod parameters
-
-wavelan.c:
-	io = 0x390	(Settable, but change not recommended)
-	irq = 0		(Not honoured, if changed..)
-
-wd.c:
-	io = 0x300
-	irq = 0
-	mem = 0		(Force shared-memory on address 0xC8000, or whatever..)
-	(Probes ports:	0x300, 0x280, 0x380, 0x240,
-	 uses AUTOIRQ)
-
-znet.c: *Not modularized*
-	(Only one device on  Zenith Z-Note (notebook?) systems,
-	 configuration information from (EE)PROM)
diff -u --recursive --new-file v1.3.21/linux/drivers/net/de600.c linux/drivers/net/de600.c
--- v1.3.21/linux/drivers/net/de600.c	Wed Aug  9 14:55:40 1995
+++ linux/drivers/net/de600.c	Thu Aug 31 08:09:06 1995
@@ -752,6 +752,7 @@
 #endif /* SHUTDOWN_WHEN_LOST */
 		was_down = 1;
 		dev->tbusy = 1;		/* Transmit busy...  */
+		restore_flags(flags);
 		return 1; /* failed */
 	}
 #endif /* CHECK_LOST_DE600 */
diff -u --recursive --new-file v1.3.21/linux/drivers/net/eql.c linux/drivers/net/eql.c
--- v1.3.21/linux/drivers/net/eql.c	Tue Aug 15 20:39:03 1995
+++ linux/drivers/net/eql.c	Thu Aug 31 08:09:06 1995
@@ -859,6 +859,7 @@
     {
       prev->next = current->next;
       queue->num_slaves--;
+      sti();
       return current;
     }
 
diff -u --recursive --new-file v1.3.21/linux/drivers/net/net_init.c linux/drivers/net/net_init.c
--- v1.3.21/linux/drivers/net/net_init.c	Mon Aug 28 14:52:20 1995
+++ linux/drivers/net/net_init.c	Fri Sep  1 09:10:48 1995
@@ -350,6 +350,15 @@
 			break;
 		}
 	}
+	/* You can i.e use a interfaces in a route though it is not up.
+	   We call close_dev (which is changed: it will down a device even if
+	   dev->flags==0 (but it will not call dev->stop if IFF_UP
+	   is not set).
+	   This will call notifier_call_chain(&netdev_chain, NETDEV_DOWN, dev),
+	   dev_mc_discard(dev), ....
+	*/
+	dev_close(dev);
+
 	restore_flags(flags);
 }
 
diff -u --recursive --new-file v1.3.21/linux/drivers/net/ppp.c linux/drivers/net/ppp.c
--- v1.3.21/linux/drivers/net/ppp.c	Mon Aug 28 14:52:20 1995
+++ linux/drivers/net/ppp.c	Fri Sep  1 09:11:01 1995
@@ -2117,12 +2117,20 @@
 init_module(void)
 {
 	int err;
-	int i;
+	int i,j;
 
 	for (i = 0; i < PPP_NRUNIT; i++)  {
 		if ((err = register_netdev(&dev_ppp[i])))  {
 			if (err == -EEXIST)  {
 				printk("PPP: devices already present. Module not loaded.\n");
+				/* we must unregister already registered units */
+				if(i>0) {
+					for(j = 0; j < i ; j++)
+						unregister_netdev(&dev_ppp[j]);
+					if ((j = tty_register_ldisc(N_PPP, NULL)))  {
+						printk("PPP: can't unregister line discipline (err = %d)\n", j);
+					}
+				}
 			}
 			return err;
 		}
diff -u --recursive --new-file v1.3.21/linux/drivers/pci/pci.c linux/drivers/pci/pci.c
--- v1.3.21/linux/drivers/pci/pci.c	Mon Aug 28 14:52:20 1995
+++ linux/drivers/pci/pci.c	Thu Aug 31 08:16:59 1995
@@ -67,6 +67,7 @@
 	DEVICE( DEC,		DEC_BRD,	"DC21050"),
 	DEVICE( MATROX,		MATROX_MGA_2,	"Atlas PX2085"),
 	DEVICE( MATROX,		MATROX_MGA_IMP,	"MGA Impression"),
+	DEVICE( MATROX,		MATROX_MIL	,"Millenium"),
 	DEVICE( INTEL,		INTEL_82378,	"82378IB"),
 	BRIDGE( INTEL,		INTEL_82424,	"82424ZX Saturn",	0x00),
 	DEVICE( INTEL,		INTEL_82375,	"82375EB"),
@@ -74,13 +75,20 @@
 	DEVICE( INTEL,		INTEL_82430,	"82430ZX Aries"),
 	DEVICE( INTEL,		INTEL_82437,	"82437 Triton"),
 	DEVICE( INTEL,		INTEL_82371,	"82371 Triton"),
-	DEVICE( INTEL,		INTEL_82438,	"82438"),
+	DEVICE( INTEL,		INTEL_82438,	"82438/82371"),
 	DEVICE( INTEL,		INTEL_7116,	"SAA7116"),
 	DEVICE( INTEL,		INTEL_82865,	"82865"),
+	DEVICE( INTEL,		INTEL_P6,	"Experimental P6 bridge"),
+#if 0
 	DEVICE( SMC,		SMC_37C665,	"FDC 37C665"),
 	DEVICE( SMC,		SMC_37C922,	"FDC 37C922"),
-	DEVICE( ATI,		ATI_M32,	"Mach 32"),
-	DEVICE( ATI,		ATI_M64,	"Mach 64"),
+#else
+	DEVICE( PCTECH,		PCTECH_RZ1000,	"RZ1000 (buggy)"),
+#endif
+	DEVICE( ATI,		ATI_68800,	"68800AX"),
+	DEVICE( ATI,		ATI_215CT222,	"215CT222"),
+	DEVICE( ATI,		ATI_210888GX,	"210888GX"),
+	DEVICE( ATI,		ATI_210888CX,	"210888CX"),
 	DEVICE( WEITEK,		WEITEK_P9000,	"P9000"),
 	DEVICE( WEITEK,		WEITEK_P9100,	"P9100"),
 	DEVICE( CIRRUS,		CIRRUS_5430,	"GD 5430"),
@@ -101,7 +109,7 @@
 	DEVICE( TSENG,		TSENG_W32P_b,	"ET4000W32P rev B"),
 	DEVICE( TSENG,		TSENG_W32P_c,	"ET4000W32P rev C"),
 	DEVICE( TSENG,		TSENG_W32P_d,	"ET4000W32P rev D"),
-	DEVICE( CMD,		CMD_640,	"640A"),
+	DEVICE( CMD,		CMD_640,	"640 (buggy)"),
 	DEVICE( VISION,		VISION_QD8500,	"QD-8500"),
 	DEVICE( VISION,		VISION_QD8580,	"QD-8580"),
 	DEVICE( AMD,		AMD_LANCE,	"79C970"),
@@ -126,6 +134,7 @@
 	DEVICE( ZEINET,		ZEINET_1221,	"1221"),
 	DEVICE( EF,		EF_ATM,		"155P-MF1"),
 	DEVICE( HER,		HER_STING,	"Stingray"),
+	DEVICE( HER,		HER_STINGARK,	"Stingray ARK 2000PV"),
   	DEVICE( ATRONICS,	ATRONICS_2015,	"IDE-2015PL"),
 	DEVICE( CT,		CT_65545,	"65545"),
 	DEVICE( FD,		FD_36C70,	"TMC-18C30"),
@@ -141,7 +150,10 @@
 	DEVICE( VORTEX,		VORTEX_GDT,	"GDT 6000b"),
 	DEVICE( HP,		HP_J2585A,	"J2585A"),
 	DEVICE( MUTECH,		MUTECH_MV1000,	"MV-1000"),
-	DEVICE( TEKRAM,		TEKRAM_DC290,	"DC-290")
+	DEVICE( TEKRAM,		TEKRAM_DC290,	"DC-290"),
+	DEVICE( IMAGINGTECH,	IMAGINGTECH_ICPCI, "MVC IC-PCI"),
+	DEVICE( CYCLADES,	CYCLADES_Y,	"Cyclome-Y"),
+	DEVICE( PLX,		PLX_9060,	"PCI9060 i960 bridge")
 };
 
 
@@ -342,7 +354,11 @@
 	      case PCI_VENDOR_ID_DEC:		return "DEC";
 	      case PCI_VENDOR_ID_MATROX:	return "Matrox";
 	      case PCI_VENDOR_ID_INTEL:		return "Intel";
+#if 0
 	      case PCI_VENDOR_ID_SMC:		return "SMC";
+#else
+	      case PCI_VENDOR_ID_PCTECH:	return "PCTECH";
+#endif
 	      case PCI_VENDOR_ID_ATI:		return "ATI";
 	      case PCI_VENDOR_ID_WEITEK:	return "Weitek";
 	      case PCI_VENDOR_ID_CIRRUS:	return "Cirrus Logic";
@@ -378,6 +394,9 @@
 	      case PCI_VENDOR_ID_ACC:		return "ACC MICROELECTRONICS";
 	      case PCI_VENDOR_ID_VORTEX:	return "VORTEX";
 	      case PCI_VENDOR_ID_HP:		return "Hewlett Packard";
+	      case PCI_VENDOR_ID_IMAGINGTECH:	return "Imaging Technology";
+	      case PCI_VENDOR_ID_CYCLADES:	return "Cyclades";
+	      case PCI_VENDOR_ID_OLICOM:	return "Olicom";
 	      default:				return "Unknown vendor";
 	}
 }
@@ -800,10 +819,10 @@
 
 #ifdef DEBUG
 	{
-		int len = get_pci_list(mem_start);
+		int len = get_pci_list((char*)mem_start);
 		if (len) {
-			((char*)mem_start)[len] = '\0';
-			printk("%s\n", mem_start);
+			((char *) mem_start)[len] = '\0';
+			printk("%s\n", (char *) mem_start);
 		}
 	}
 #endif
diff -u --recursive --new-file v1.3.21/linux/drivers/scsi/53c7,8xx.c linux/drivers/scsi/53c7,8xx.c
--- v1.3.21/linux/drivers/scsi/53c7,8xx.c	Wed Aug  2 13:21:06 1995
+++ linux/drivers/scsi/53c7,8xx.c	Tue Aug 29 10:15:52 1995
@@ -1,6 +1,7 @@
 /* 
  * Set these options for all host adapters.
- * 	- Memory mapped IO does not work.
+ * 	- Memory mapped IO does not work on x86 because of cache
+ *	  problems.
  *	- Test 1 does a bus mastering test, which will help
  *	  weed out brain damaged main boards.
  */
@@ -3857,8 +3858,10 @@
     save_flags(flags);
     ncr_halt (host);
     NCR53c7x0_write8(SCNTL1_REG, SCNTL1_RST);
+    mb();
     udelay(25);	/* Minimum amount of time to assert RST */
     NCR53c7x0_write8(SCNTL1_REG, SCNTL1_RST);
+    mb();
     for (c = (struct NCR53c7x0_cmd *) hostdata->running_list, found = 0; c; 
     	c = (struct NCR53c7x0_cmd *) c->next)  {
 	tmp = c->cmd;
@@ -3938,8 +3941,10 @@
  *	reset.  
  */
     NCR53c7x0_write8(SCNTL1_REG, SCNTL1_RST);
+    mb();
     udelay(25);	/* Minimum amount of time to assert RST */
     NCR53c7x0_write8(SCNTL1_REG, SCNTL1_RST);
+    mb();
     restore_flags (flags);
     return 0;
 }
@@ -3968,6 +3973,7 @@
     save_flags(flags);
     cli();
     NCR53c7x0_write8(hostdata->istat, ISTAT_ABRT);
+    mb();
     /* Eat interrupts until we find what we're looking for */
     for (;;) {
 	istat = NCR53c7x0_read8 (hostdata->istat);
@@ -3981,6 +3987,7 @@
 	    }
 	} else if (istat & ISTAT_DIP) {
 	    NCR53c7x0_write8(hostdata->istat, 0);
+	    mb();
 	    tmp = NCR53c7x0_read8(DSTAT_REG);
 	    if (tmp & DSTAT_ABRT)
 		break;
diff -u --recursive --new-file v1.3.21/linux/drivers/scsi/README.st linux/drivers/scsi/README.st
--- v1.3.21/linux/drivers/scsi/README.st	Sun Jan 15 00:54:27 1995
+++ linux/drivers/scsi/README.st	Thu Aug 31 07:44:09 1995
@@ -1,5 +1,5 @@
 This file contains brief information about the SCSI tape driver.
-Last modified: Tue Jan 10 21:32:35 1995 by root@kai.home
+Last modified: Sun Aug 27 12:49:11 1995 by root@kai.makisara.fi
 
 BASICS
 
@@ -15,6 +15,8 @@
 optionally written. In both cases end of data is signified by
 returning zero bytes for two consecutive reads.
 
+The compile options are defined in the file linux/drivers/scsi/st_options.h.
+
 BUFFERING
 
 The driver uses a buffer allocated at system initialization. The size
@@ -108,8 +110,9 @@
            (enabled/disabled) of the write buffering (MT_ST_BUFFER_WRITES),
            asynchronous writes (MT_ST_ASYNC_WRITES), read ahead
            (MT_ST_READ_AHEAD), writing of two filemark (ST_TWO_FM),
-	   using the SCSI spacing to EOD (MT_ST_FAST_EOM), and
-	   debugging (MT_ST_DEBUGGING ; debugging must be compiled into the
+	   using the SCSI spacing to EOD (MT_ST_FAST_EOM), automatic
+	   locking of the drive door (MT_ST_AUTO_LOCK) and debugging
+	   (MT_ST_DEBUGGING ; debugging must be compiled into the
 	   driver).
         MT_ST_WRITE_THRESHOLD
            Sets the write threshold for this device to kilobytes
diff -u --recursive --new-file v1.3.21/linux/drivers/scsi/aha1542.c linux/drivers/scsi/aha1542.c
--- v1.3.21/linux/drivers/scsi/aha1542.c	Wed Aug  2 13:21:06 1995
+++ linux/drivers/scsi/aha1542.c	Thu Aug 31 08:09:07 1995
@@ -155,10 +155,10 @@
 {
   unsigned long flags = 0;
   
+  save_flags(flags);
   if(len == 1) {
     while(1==1){
 	WAIT(STATUS(base), CDF, 0, CDF);
-	save_flags(flags);
 	cli();
 	if(inb(STATUS(base)) & CDF) {restore_flags(flags); continue;}
 	outb(*cmdp, DATA(base));
@@ -166,7 +166,6 @@
 	return 0;
       }
   } else {
-    save_flags(flags);
     cli();
     while (len--)
       {
diff -u --recursive --new-file v1.3.21/linux/drivers/scsi/eata.c linux/drivers/scsi/eata.c
--- v1.3.21/linux/drivers/scsi/eata.c	Wed Aug  2 13:21:08 1995
+++ linux/drivers/scsi/eata.c	Thu Aug 31 08:09:06 1995
@@ -715,6 +715,7 @@
    if (SCarg->host_scribble == NULL) {
       printk("%s: abort, target %d, pid %ld inactive.\n",
 	     BN(j), SCarg->target, SCarg->pid);
+      restore_flags(flags);
       return SCSI_ABORT_NOT_RUNNING;
       }
 
@@ -759,8 +760,8 @@
       restore_flags(flags);
       return SCSI_ABORT_NOT_RUNNING;
       }
-   else
-      panic("%s: abort, mbox %d, invalid cp_stat.\n", BN(j), i);
+   restore_flags(flags);
+   panic("%s: abort, mbox %d, invalid cp_stat.\n", BN(j), i);
 }
 
 int eata2x_reset (Scsi_Cmnd *SCarg) {
diff -u --recursive --new-file v1.3.21/linux/drivers/scsi/eata_dma.c linux/drivers/scsi/eata_dma.c
--- v1.3.21/linux/drivers/scsi/eata_dma.c	Thu Jul 27 10:13:16 1995
+++ linux/drivers/scsi/eata_dma.c	Thu Aug 31 08:09:06 1995
@@ -540,8 +540,9 @@
 	DBG(DBG_ABNORM, printk("eata_dma: abort, queue slot locked.\n"));
 	DBG(DBG_ABNORM && DBG_DELAY, DEL2(500));
 	return (SCSI_ABORT_NOT_RUNNING);
-    } else
-	panic("eata_dma: abort: invalid slot status\n");
+    }
+    restore_flags(flags);
+    panic("eata_dma: abort: invalid slot status\n");
 }
 
 int eata_reset(Scsi_Cmnd * cmd)
diff -u --recursive --new-file v1.3.21/linux/drivers/scsi/eata_pio.c linux/drivers/scsi/eata_pio.c
--- v1.3.21/linux/drivers/scsi/eata_pio.c	Tue Aug  8 12:31:38 1995
+++ linux/drivers/scsi/eata_pio.c	Thu Aug 31 08:09:06 1995
@@ -435,8 +435,9 @@
 	DBG(DBG_ABNORM, printk("eata_pio: abort, queue slot locked.\n"));
 	DBG(DBG_ABNORM && DBG_DELAY, DEL2(500));
 	return (SCSI_ABORT_NOT_RUNNING);
-    } else
-	panic("eata_pio: abort: invalid slot status\n");
+    }
+    restore_flags(flags);
+    panic("eata_pio: abort: invalid slot status\n");
 }
 
 int eata_pio_reset(Scsi_Cmnd * cmd)
diff -u --recursive --new-file v1.3.21/linux/drivers/scsi/st.c linux/drivers/scsi/st.c
--- v1.3.21/linux/drivers/scsi/st.c	Wed Aug  2 13:21:14 1995
+++ linux/drivers/scsi/st.c	Thu Aug 31 07:44:09 1995
@@ -11,7 +11,7 @@
   Copyright 1992, 1993, 1994, 1995 Kai Makisara
 		 email Kai.Makisara@metla.fi
 
-  Last modified: Sat Feb 18 10:51:25 1995 by root@kai.home
+  Last modified: Thu Aug 31 00:04:12 1995 by root@kai.makisara.fi
 */
 #ifdef MODULE
 #include <linux/autoconf.h>
@@ -31,6 +31,10 @@
 #include <asm/segment.h>
 #include <asm/system.h>
 
+/* The driver prints some debugging information on the console if DEBUG
+   is defined and non-zero. */
+#define DEBUG 0
+
 #define MAJOR_NR SCSI_TAPE_MAJOR
 #include "../block/blk.h"
 #include "scsi.h"
@@ -39,31 +43,11 @@
 #include "st.h"
 #include "constants.h"
 
-/* #define DEBUG */
-
-/* #define ST_NOWAIT */
-
-/* #define ST_IN_FILE_POS */
-
-/* #define ST_RECOVERED_WRITE_FATAL */
-
-#define ST_TWO_FM 0
-
-#define ST_FAST_MTEOM 0
-
-#define ST_BUFFER_WRITES 1
-
-#define ST_ASYNC_WRITES 1
-
-#define ST_READ_AHEAD 1
+/* The default definitions have been moved to st_options.h */
 
 #define ST_BLOCK_SIZE 1024
 
-#define ST_MAX_BUFFERS (2 + ST_EXTRA_DEVS)
-
-#define ST_BUFFER_BLOCKS 32
-
-#define ST_WRITE_THRESHOLD_BLOCKS 30
+#include "st_options.h"
 
 #define ST_BUFFER_SIZE (ST_BUFFER_BLOCKS * ST_BLOCK_SIZE)
 #define ST_WRITE_THRESHOLD (ST_WRITE_THRESHOLD_BLOCKS * ST_BLOCK_SIZE)
@@ -74,7 +58,7 @@
 #error "Buffer size should not exceed (2 << 24 - 1) bytes!"
 #endif
 
-#ifdef DEBUG
+#if DEBUG
 static int debugging = 1;
 #endif
 
@@ -92,7 +76,7 @@
 static int st_write_threshold = ST_WRITE_THRESHOLD;
 static int st_max_buffers = ST_MAX_BUFFERS;
 
-static Scsi_Tape * scsi_tapes = NULL;
+Scsi_Tape * scsi_tapes = NULL;
 
 static void st_init(void);
 static int st_attach(Scsi_Device *);
@@ -121,7 +105,7 @@
 
   if (!result /* && SCpnt->sense_buffer[0] == 0 */ )
     return 0;
-#ifdef DEBUG
+#if DEBUG
   if (debugging) {
     printk("st%d: Error: %x, cmd: %x %x %x %x %x %x Len: %d\n", dev, result,
 	   SCpnt->data_cmnd[0], SCpnt->data_cmnd[1], SCpnt->data_cmnd[2],
@@ -148,7 +132,7 @@
 
   if ((sense[0] & 0x70) == 0x70 &&
       scode == RECOVERED_ERROR
-#ifdef ST_RECOVERED_WRITE_FATAL
+#if ST_RECOVERED_WRITE_FATAL
       && SCpnt->data_cmnd[0] != WRITE_6
       && SCpnt->data_cmnd[0] != WRITE_FILEMARKS
 #endif
@@ -201,10 +185,11 @@
       SCpnt->request.dev = -1;
     else
       SCpnt->request.dev = 0xffff;
-    if ((STp->buffer)->writing <= 0)
+    if (!(STp->buffer)->writing || STp->write_pending)
       wake_up( &(STp->waiting) );
+    STp->write_pending = 0;
   }
-#ifdef DEBUG
+#if DEBUG
   else if (debugging)
     printk("st?: Illegal interrupt device %x\n", st_nbr);
 #endif
@@ -224,11 +209,17 @@
 
   save_flags(flags);
   cli();
-  if (STbuffer->last_result < 0) {
-    STbuffer->writing = (- STbuffer->writing);
+  if (STp->write_pending) {
+#if DEBUG
+    STp->nbr_waits++;
+#endif
     sleep_on( &(STp->waiting) );
-    STbuffer->writing = (- STbuffer->writing);
+    STp->write_pending = 0;
   }
+#if DEBUG
+  else
+    STp->nbr_finished++;
+#endif
   restore_flags(flags);
 
   if (STbuffer->writing < STbuffer->buffer_bytes)
@@ -302,7 +293,7 @@
   if ((STp->buffer)->writing) {
     write_behind_check(dev);
     if ((STp->buffer)->last_result_fatal) {
-#ifdef DEBUG
+#if DEBUG
       if (debugging)
 	printk("st%d: Async write error (flush) %x.\n", dev,
 	       (STp->buffer)->last_result);
@@ -313,6 +304,9 @@
     }
   }
 
+  if (STp->block_size == 0)
+    return 0;
+
   result = 0;
   if (STp->dirty == 1) {
     SCpnt = allocate_device(NULL, STp->device, 1);
@@ -320,7 +314,7 @@
     offset = (STp->buffer)->buffer_bytes;
     transfer = ((offset + STp->block_size - 1) /
 		STp->block_size) * STp->block_size;
-#ifdef DEBUG
+#if DEBUG
     if (debugging)
       printk("st%d: Flushing %d bytes.\n", dev, transfer);
 #endif
@@ -454,12 +448,16 @@
     STp->write_prot = ((flags & O_ACCMODE) == O_RDONLY);
 
     STp->dirty = 0;
+    STp->write_pending = 0;
     STp->rw = ST_IDLE;
     STp->ready = ST_READY;
     if (STp->eof != ST_EOD)  /* Save EOD across opens */
       STp->eof = ST_NOEOF;
     STp->eof_hit = 0;
     STp->recover_count = 0;
+#if DEBUG
+    STp->nbr_waits = STp->nbr_finished = 0;
+#endif
 
     SCpnt = allocate_device(NULL, STp->device, 1);
     if (!SCpnt) {
@@ -476,7 +474,6 @@
 		0, st_sleep_done, ST_LONG_TIMEOUT,
 		MAX_READY_RETRIES);
 
-
     /* this must be done with interrupts off */
     save_flags (processor_flags);
     cli();
@@ -495,12 +492,11 @@
 		  0, st_sleep_done, ST_LONG_TIMEOUT,
 		  MAX_READY_RETRIES);
 
-
-    /* this must be done with interrupts off */
-    save_flags (processor_flags);
-    cli();
-    if (SCpnt->request.dev == dev) sleep_on( &(STp->waiting) );
-    restore_flags(processor_flags);
+      /* this must be done with interrupts off */
+      save_flags (processor_flags);
+      cli();
+      if (SCpnt->request.dev == dev) sleep_on( &(STp->waiting) );
+      restore_flags(processor_flags);
 
       (STp->mt_status)->mt_fileno = STp->drv_block = 0;
       STp->eof = ST_NOEOF;
@@ -517,15 +513,15 @@
 	STp->ready = ST_NOT_READY;
       }
       SCpnt->request.dev = -1;  /* Mark as not busy */
-      (STp->buffer)->in_use = 0;
-      STp->buffer = NULL;
       STp->density = 0;   /* Clear the erroneous "residue" */
       STp->write_prot = 0;
       STp->block_size = 0;
       STp->eof = ST_NOEOF;
       (STp->mt_status)->mt_fileno = STp->drv_block = 0;
+      STp->door_locked = ST_UNLOCKED;
       if (scsi_tapes[dev].device->host->hostt->usage_count)
 	(*scsi_tapes[dev].device->host->hostt->usage_count)++;
+      if(st_template.usage_count) (*st_template.usage_count)++;
       return 0;
     }
 
@@ -537,7 +533,6 @@
 		(void *) cmd, (void *) (STp->buffer)->b_data,
 		6, st_sleep_done, ST_TIMEOUT, MAX_READY_RETRIES);
 
-
     /* this must be done with interrupts off */
     save_flags (processor_flags);
     cli();
@@ -549,7 +544,7 @@
 	((STp->buffer)->b_data[2] << 8) | (STp->buffer)->b_data[3];
       STp->min_block = ((STp->buffer)->b_data[4] << 8) |
 	(STp->buffer)->b_data[5];
-#ifdef DEBUG
+#if DEBUG
       if (debugging)
 	printk("st%d: Block limits %d - %d bytes.\n", dev, STp->min_block,
 	       STp->max_block);
@@ -557,7 +552,7 @@
     }
     else {
       STp->min_block = STp->max_block = (-1);
-#ifdef DEBUG
+#if DEBUG
       if (debugging)
 	printk("st%d: Can't read block limits.\n", dev);
 #endif
@@ -572,7 +567,6 @@
 		(void *) cmd, (void *) (STp->buffer)->b_data,
 		12, st_sleep_done, ST_TIMEOUT, MAX_READY_RETRIES);
 
-
     /* this must be done with interrupts off */
     save_flags (processor_flags);
     cli();
@@ -580,34 +574,36 @@
     restore_flags(processor_flags);
 
     if ((STp->buffer)->last_result_fatal != 0) {
-#ifdef DEBUG
+#if DEBUG
       if (debugging)
 	printk("st%d: No Mode Sense.\n", dev);
 #endif
-      (STp->buffer)->b_data[2] =
-      (STp->buffer)->b_data[3] = 0;
+      STp->block_size = ST_DEFAULT_BLOCK;  /* Educated guess (?) */
+      (STp->buffer)->last_result_fatal = 0;  /* Prevent error propagation */
     }
-    SCpnt->request.dev = -1;  /* Mark as not busy */
+    else {
 
-#ifdef DEBUG
-    if (debugging)
-      printk("st%d: Mode sense. Length %d, medium %x, WBS %x, BLL %d\n", dev,
-	     (STp->buffer)->b_data[0], (STp->buffer)->b_data[1],
-	     (STp->buffer)->b_data[2], (STp->buffer)->b_data[3]);
+#if DEBUG
+      if (debugging)
+	printk("st%d: Mode sense. Length %d, medium %x, WBS %x, BLL %d\n", dev,
+	       (STp->buffer)->b_data[0], (STp->buffer)->b_data[1],
+	       (STp->buffer)->b_data[2], (STp->buffer)->b_data[3]);
 #endif
 
-    if ((STp->buffer)->b_data[3] >= 8) {
-      STp->drv_buffer = ((STp->buffer)->b_data[2] >> 4) & 7;
-      STp->density = (STp->buffer)->b_data[4];
-      STp->block_size = (STp->buffer)->b_data[9] * 65536 +
-	(STp->buffer)->b_data[10] * 256 + (STp->buffer)->b_data[11];
-#ifdef DEBUG
-      if (debugging)
-	printk("st%d: Density %x, tape length: %x, drv buffer: %d\n",
-	       dev, STp->density, (STp->buffer)->b_data[5] * 65536 +
-	       (STp->buffer)->b_data[6] * 256 + (STp->buffer)->b_data[7],
-	       STp->drv_buffer);
+      if ((STp->buffer)->b_data[3] >= 8) {
+	STp->drv_buffer = ((STp->buffer)->b_data[2] >> 4) & 7;
+	STp->density = (STp->buffer)->b_data[4];
+	STp->block_size = (STp->buffer)->b_data[9] * 65536 +
+	  (STp->buffer)->b_data[10] * 256 + (STp->buffer)->b_data[11];
+#if DEBUG
+	if (debugging)
+	  printk("st%d: Density %x, tape length: %x, drv buffer: %d\n",
+		 dev, STp->density, (STp->buffer)->b_data[5] * 65536 +
+		 (STp->buffer)->b_data[6] * 256 + (STp->buffer)->b_data[7],
+		 STp->drv_buffer);
 #endif
+      }
+
       if (STp->block_size > st_buffer_size) {
 	printk("st%d: Blocksize %d too large for buffer.\n", dev,
 	       STp->block_size);
@@ -615,10 +611,8 @@
 	STp->in_use = 0;
 	return (-EIO);
       }
-
     }
-    else
-      STp->block_size = 512;  /* "Educated Guess" (?) */
+    SCpnt->request.dev = -1;  /* Mark as not busy */
 
     if (STp->block_size > 0) {
       (STp->buffer)->buffer_blocks = st_buffer_size / STp->block_size;
@@ -631,7 +625,7 @@
     }
     (STp->buffer)->buffer_bytes = (STp->buffer)->read_pointer = 0;
 
-#ifdef DEBUG
+#if DEBUG
     if (debugging)
       printk("st%d: Block size: %d, buffer size: %d (%d blocks).\n", dev,
 	     STp->block_size, (STp->buffer)->buffer_size,
@@ -641,7 +635,7 @@
     STp->drv_write_prot = ((STp->buffer)->b_data[2] & 0x80) != 0;
     if (STp->drv_write_prot) {
       STp->write_prot = 1;
-#ifdef DEBUG
+#if DEBUG
       if (debugging)
 	printk( "st%d: Write protected\n", dev);
 #endif
@@ -682,9 +676,12 @@
 
       result = flush_write_buffer(dev);
 
-#ifdef DEBUG
-      if (debugging)
+#if DEBUG
+      if (debugging) {
 	printk("st%d: File length %ld bytes.\n", dev, (long)(filp->f_pos));
+	printk("st%d: Async write waits %d, finished %d.\n", dev,
+	       STp->nbr_waits, STp->nbr_finished);
+      }
 #endif
 
       if (result == 0 || result == (-ENOSPC)) {
@@ -699,14 +696,12 @@
 		    (void *) cmd, (void *) (STp->buffer)->b_data,
 		    0, st_sleep_done, ST_TIMEOUT, MAX_WRITE_RETRIES);
 
-
 	/* this must be done with interrupts off */
 	save_flags (flags);
 	cli();
 	if (SCpnt->request.dev == dev) sleep_on( &(STp->waiting) );
 	restore_flags(flags);
 
-
 	if ((STp->buffer)->last_result_fatal != 0) {
 	  SCpnt->request.dev = -1;  /* Mark as not busy */
 	  printk("st%d: Error on write filemark.\n", dev);
@@ -722,23 +717,26 @@
 
       }
 
-#ifdef DEBUG
+#if DEBUG
       if (debugging)
 	printk("st%d: Buffer flushed, %d EOF(s) written\n", dev, cmd[4]);
 #endif
     }
     else if (!rewind) {
-#ifndef ST_IN_FILE_POS
+#if ST_IN_FILE_POS
+      flush_buffer(inode, filp, 0);
+#else
       if ((STp->eof == ST_FM) && !STp->eof_hit)
 	back_over_eof(dev);
-#else
-      flush_buffer(inode, filp, 0);
 #endif
     }
 
     if (rewind)
       st_int_ioctl(inode, filp, MTREW, 1);
 
+    if (STp->door_locked == ST_LOCKED_AUTO)
+      st_int_ioctl(inode, filp, MTUNLOCK, 0);
+
     if (STp->buffer != NULL)
       (STp->buffer)->in_use = 0;
     STp->in_use = 0;
@@ -769,7 +767,7 @@
     STp = &(scsi_tapes[dev]);
     if (STp->ready != ST_READY)
       return (-EIO);
-#ifdef DEBUG
+#if DEBUG
     if (!STp->in_use) {
       printk("st%d: Incorrect device.\n", dev);
       return (-EIO);
@@ -782,6 +780,10 @@
     if (STp->block_size == 0 && count > st_buffer_size)
       return (-EOVERFLOW);
 
+    if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED &&
+	!st_int_ioctl(inode, filp, MTLOCK, 0))
+      STp->door_locked = ST_LOCKED_AUTO;
+
     if (STp->rw == ST_READING) {
       retval = flush_buffer(inode, filp, 0);
       if (retval)
@@ -795,7 +797,7 @@
     if ((STp->buffer)->writing) {
       write_behind_check(dev);
       if ((STp->buffer)->last_result_fatal) {
-#ifdef DEBUG
+#if DEBUG
 	if (debugging)
 	  printk("st%d: Async write error (write) %x.\n", dev,
 		 (STp->buffer)->last_result);
@@ -867,15 +869,14 @@
 		   (void *) cmd, (STp->buffer)->b_data, transfer,
 		   st_sleep_done, ST_TIMEOUT, MAX_WRITE_RETRIES);
 
-
-	/* this must be done with interrupts off */
-	save_flags (flags);
-	cli();
-	if (SCpnt->request.dev == dev) sleep_on( &(STp->waiting) );
-	restore_flags(flags);
+      /* this must be done with interrupts off */
+      save_flags (flags);
+      cli();
+      if (SCpnt->request.dev == dev) sleep_on( &(STp->waiting) );
+      restore_flags(flags);
 
       if ((STp->buffer)->last_result_fatal != 0) {
-#ifdef DEBUG
+#if DEBUG
 	if (debugging)
 	  printk("st%d: Error on write:\n", dev);
 #endif
@@ -903,7 +904,7 @@
 	    }
 	    STp->eof = ST_EOM_OK;
 	    retval = (-ENOSPC); /* EOM within current request */
-#ifdef DEBUG
+#if DEBUG
 	    if (debugging)
 	      printk("st%d: EOM with %d bytes unwritten.\n",
 		     dev, transfer);
@@ -913,7 +914,7 @@
 	    STp->eof = ST_EOM_ERROR;
 	    STp->drv_block = (-1);    /* Too cautious? */
 	    retval = (-EIO); /* EOM for old data */
-#ifdef DEBUG
+#if DEBUG
 	    if (debugging)
 	      printk("st%d: EOM with lost data.\n", dev);
 #endif
@@ -977,9 +978,9 @@
       cmd[2] = blks >> 16;
       cmd[3] = blks >> 8;
       cmd[4] = blks;
-      SCpnt->result = (STp->buffer)->last_result = -1;
       SCpnt->sense_buffer[0] = 0;
       SCpnt->request.dev = dev;
+      STp->write_pending = 1;
       scsi_do_cmd (SCpnt,
 		   (void *) cmd, (STp->buffer)->b_data,
 		   (STp->buffer)->writing,
@@ -1009,7 +1010,7 @@
     STp = &(scsi_tapes[dev]);
     if (STp->ready != ST_READY)
       return (-EIO);
-#ifdef DEBUG
+#if DEBUG
     if (!STp->in_use) {
       printk("st%d: Incorrect device.\n", dev);
       return (-EIO);
@@ -1023,6 +1024,10 @@
 	(count % STp->block_size) != 0)
       return (-EIO);	/* Read must be integral number of blocks */
 
+    if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED &&
+	!st_int_ioctl(inode, filp, MTLOCK, 0))
+      STp->door_locked = ST_LOCKED_AUTO;
+
     if (STp->rw == ST_WRITING) {
       transfer = flush_buffer(inode, filp, 0);
       if (transfer)
@@ -1032,7 +1037,7 @@
     if (STp->moves_after_eof < 255)
       STp->moves_after_eof++;
 
-#ifdef DEBUG
+#if DEBUG
     if (debugging && STp->eof != ST_NOEOF)
       printk("st%d: EOF flag up. Bytes %d\n", dev,
 	     (STp->buffer)->buffer_bytes);
@@ -1078,7 +1083,6 @@
 		     (void *) cmd, (STp->buffer)->b_data,
 		     bytes, st_sleep_done, ST_TIMEOUT, MAX_RETRIES);
 
-
 	/* this must be done with interrupts off */
 	save_flags (flags);
 	cli();
@@ -1090,7 +1094,7 @@
 	STp->at_sm = 0;
 
 	if ((STp->buffer)->last_result_fatal) {
-#ifdef DEBUG
+#if DEBUG
 	  if (debugging)
 	    printk("st%d: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n", dev,
 		   SCpnt->sense_buffer[0], SCpnt->sense_buffer[1],
@@ -1131,7 +1135,7 @@
 		else
 		  (STp->buffer)->buffer_bytes =
 		    bytes - transfer * STp->block_size;
-#ifdef DEBUG
+#if DEBUG
 		if (debugging)
 		  printk("st%d: EOM detected (%d bytes read).\n", dev,
 			 (STp->buffer)->buffer_bytes);
@@ -1144,7 +1148,7 @@
 		else
 		  (STp->buffer)->buffer_bytes =
 		    bytes - transfer * STp->block_size;
-#ifdef DEBUG
+#if DEBUG
 		if (debugging)
 		  printk(
 		    "st%d: EOF detected (%d bytes read, transferred %d bytes).\n",
@@ -1153,7 +1157,7 @@
 	      }
 	    } /* end of EOF, EOM, ILI test */
 	    else { /* nonzero sense key */
-#ifdef DEBUG
+#if DEBUG
 	      if (debugging)
 		printk("st%d: Tape error while reading.\n", dev);
 #endif
@@ -1163,7 +1167,7 @@
 		return total;
 	      else if (STp->moves_after_eof == 1 &&
 		       (SCpnt->sense_buffer[2] & 0x0f) == BLANK_CHECK) {
-#ifdef DEBUG
+#if DEBUG
 		if (debugging)
 		  printk("st%d: Zero returned for first BLANK CHECK after EOF.\n",
 			 dev);
@@ -1195,7 +1199,7 @@
 	   STp->eof == ST_NOEOF) */
 
       if ((STp->buffer)->buffer_bytes > 0) {
-#ifdef DEBUG
+#if DEBUG
 	if (debugging && STp->eof != ST_NOEOF)
 	  printk("st%d: EOF up. Left %d, needed %d.\n", dev,
 		 (STp->buffer)->buffer_bytes, count - total);
@@ -1253,14 +1257,15 @@
     STp->do_read_ahead    = (options & MT_ST_READ_AHEAD) != 0;
     STp->two_fm		  = (options & MT_ST_TWO_FM) != 0;
     STp->fast_mteom	  = (options & MT_ST_FAST_MTEOM) != 0;
-#ifdef DEBUG
+    STp->do_auto_lock     = (options & MT_ST_AUTO_LOCK) != 0;
+#if DEBUG
     debugging = (options & MT_ST_DEBUGGING) != 0;
     printk(
 "st%d: options: buffer writes: %d, async writes: %d, read ahead: %d\n",
 	   dev, STp->do_buffer_writes, STp->do_async_writes,
 	   STp->do_read_ahead);
-    printk("              two FMs: %d, fast mteom: %d debugging: %d\n",
-	   STp->two_fm, STp->fast_mteom, debugging);
+    printk("              two FMs: %d, fast mteom: %d auto lock: %d, debugging: %d\n",
+	   STp->two_fm, STp->fast_mteom, STp->do_auto_lock, debugging);
 #endif
   }
   else if ((options & MT_ST_OPTIONS) == MT_ST_WRITE_THRESHOLD) {
@@ -1271,7 +1276,7 @@
       return (-EIO);
     }
     STp->write_threshold = value;
-#ifdef DEBUG
+#if DEBUG
     printk("st%d: Write threshold set to %d bytes.\n", dev,
 	   STp->write_threshold);
 #endif
@@ -1300,7 +1305,7 @@
 
    dev = dev & 127;
    STp = &(scsi_tapes[dev]);
-   if (STp->ready != ST_READY)
+   if (STp->ready != ST_READY && cmd_in != MTLOAD)
      return (-EIO);
    fileno = (STp->mt_status)->mt_fileno ;
    blkno = STp->drv_block;
@@ -1316,7 +1321,7 @@
        cmd[2] = (arg >> 16);
        cmd[3] = (arg >> 8);
        cmd[4] = arg;
-#ifdef DEBUG
+#if DEBUG
        if (debugging)
 	 printk("st%d: Spacing tape forward over %d filemarks.\n", dev,
 		cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
@@ -1334,7 +1339,7 @@
        cmd[2] = (ltmp >> 16);
        cmd[3] = (ltmp >> 8);
        cmd[4] = ltmp;
-#ifdef DEBUG
+#if DEBUG
        if (debugging) {
 	 if (cmd[2] & 0x80)
 	   ltmp = 0xff000000;
@@ -1353,7 +1358,7 @@
        cmd[2] = (arg >> 16);
        cmd[3] = (arg >> 8);
        cmd[4] = arg;
-#ifdef DEBUG
+#if DEBUG
        if (debugging)
 	 printk("st%d: Spacing tape forward %d blocks.\n", dev,
 		cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
@@ -1369,7 +1374,7 @@
        cmd[2] = (ltmp >> 16);
        cmd[3] = (ltmp >> 8);
        cmd[4] = ltmp;
-#ifdef DEBUG
+#if DEBUG
        if (debugging) {
 	 if (cmd[2] & 0x80)
 	   ltmp = 0xff000000;
@@ -1387,7 +1392,7 @@
        cmd[2] = (arg >> 16);
        cmd[3] = (arg >> 8);
        cmd[4] = arg;
-#ifdef DEBUG
+#if DEBUG
        if (debugging)
 	 printk("st%d: Spacing tape forward %d setmarks.\n", dev,
 		cmd[2] * 65536 + cmd[3] * 256 + cmd[4]);
@@ -1404,7 +1409,7 @@
        cmd[2] = (ltmp >> 16);
        cmd[3] = (ltmp >> 8);
        cmd[4] = ltmp;
-#ifdef DEBUG
+#if DEBUG
        if (debugging) {
 	 if (cmd[2] & 0x80)
 	   ltmp = 0xff000000;
@@ -1428,7 +1433,7 @@
        cmd[3] = (arg >> 8);
        cmd[4] = arg;
        timeout = ST_TIMEOUT;
-#ifdef DEBUG
+#if DEBUG
        if (debugging) {
 	 if (cmd_in == MTWEOF)
 	   printk("st%d: Writing %d filemarks.\n", dev,
@@ -1445,11 +1450,11 @@
        break; 
      case MTREW:
        cmd[0] = REZERO_UNIT;
-#ifdef ST_NOWAIT
+#if ST_NOWAIT
        cmd[1] = 1;  /* Don't wait for completion */
        timeout = ST_TIMEOUT;
 #endif
-#ifdef DEBUG
+#if DEBUG
        if (debugging)
 	 printk("st%d: Rewinding tape.\n", dev);
 #endif
@@ -1457,18 +1462,18 @@
        break; 
      case MTOFFL:
        cmd[0] = START_STOP;
-#ifdef ST_NOWAIT
+#if ST_NOWAIT
        cmd[1] = 1;  /* Don't wait for completion */
        timeout = ST_TIMEOUT;
 #endif
-#ifdef DEBUG
+#if DEBUG
        if (debugging)
 	 printk("st%d: Unloading tape.\n", dev);
 #endif
        fileno = blkno = at_sm = 0 ;
        break; 
      case MTNOP:
-#ifdef DEBUG
+#if DEBUG
        if (debugging)
 	 printk("st%d: No op on tape.\n", dev);
 #endif
@@ -1476,12 +1481,12 @@
        break;
      case MTRETEN:
        cmd[0] = START_STOP;
-#ifdef ST_NOWAIT
+#if ST_NOWAIT
        cmd[1] = 1;  /* Don't wait for completion */
        timeout = ST_TIMEOUT;
 #endif
        cmd[4] = 3;
-#ifdef DEBUG
+#if DEBUG
        if (debugging)
 	 printk("st%d: Retensioning tape.\n", dev);
 #endif
@@ -1503,7 +1508,7 @@
 	 fileno = (-1);
        cmd[0] = SPACE;
        cmd[1] = 3;
-#ifdef DEBUG
+#if DEBUG
        if (debugging)
 	 printk("st%d: Spacing to end of recorded medium.\n", dev);
 #endif
@@ -1515,18 +1520,46 @@
 	 return (-EACCES);
        cmd[0] = ERASE;
        cmd[1] = 1;  /* To the end of tape */
-#ifdef ST_NOWAIT
+#if ST_NOWAIT
        cmd[1] |= 2;  /* Don't wait for completion */
        timeout = ST_TIMEOUT;
 #else
        timeout = ST_LONG_TIMEOUT * 8;
 #endif
-#ifdef DEBUG
+#if DEBUG
        if (debugging)
 	 printk("st%d: Erasing tape.\n", dev);
 #endif
        fileno = blkno = at_sm = 0 ;
        break;
+     case MTLOCK:
+       cmd[0] = ALLOW_MEDIUM_REMOVAL;
+       cmd[4] = SCSI_REMOVAL_PREVENT;
+#if DEBUG
+       if (debugging)
+	 printk("st%d: Locking drive door.\n", dev);
+#endif;
+       break;
+     case MTUNLOCK:
+       cmd[0] = ALLOW_MEDIUM_REMOVAL;
+       cmd[4] = SCSI_REMOVAL_ALLOW;
+#if DEBUG
+       if (debugging)
+	 printk("st%d: Unlocking drive door.\n", dev);
+#endif;
+       break;
+     case MTLOAD:
+     case MTUNLOAD:
+       cmd[0] = START_STOP;
+       if (cmd_in == MTLOAD)
+	 cmd[4] |= 1;
+#if ST_NOWAIT
+       cmd[1] |= 2;  /* Don't wait for completion */
+       timeout = ST_TIMEOUT;
+#else
+       timeout = ST_LONG_TIMEOUT * 8;
+#endif
+       break;
      case MTSEEK:
        if ((STp->device)->scsi_level < SCSI_2) {
 	 cmd[0] = QFA_SEEK_BLOCK;
@@ -1543,11 +1576,11 @@
 	 cmd[5] = (arg >> 8);
 	 cmd[6] = arg;
        }
-#ifdef ST_NOWAIT
+#if ST_NOWAIT
        cmd[1] |= 1;  /* Don't wait for completion */
        timeout = ST_TIMEOUT;
 #endif
-#ifdef DEBUG
+#if DEBUG
        if (debugging)
 	 printk("st%d: Seeking tape to block %ld.\n", dev, arg);
 #endif
@@ -1588,7 +1621,7 @@
        (STp->buffer)->b_data[10] = (ltmp >> 8);
        (STp->buffer)->b_data[11] = ltmp;
        timeout = ST_TIMEOUT;
-#ifdef DEBUG
+#if DEBUG
        if (debugging) {
 	 if (cmd_in == MTSETBLK)
 	   printk("st%d: Setting block size to %d bytes.\n", dev,
@@ -1616,13 +1649,11 @@
 	       (void *) cmd, (void *) (STp->buffer)->b_data, datalen,
 	       st_sleep_done, timeout, MAX_RETRIES);
 
-
-	/* this must be done with interrupts off */
-	save_flags (flags);
-	cli();
-	if (SCpnt->request.dev == dev) sleep_on( &(STp->waiting) );
-	restore_flags(flags);
-
+   /* this must be done with interrupts off */
+   save_flags (flags);
+   cli();
+   if (SCpnt->request.dev == dev) sleep_on( &(STp->waiting) );
+   restore_flags(flags);
 
    ioctl_result = (STp->buffer)->last_result_fatal;
 
@@ -1642,6 +1673,10 @@
        STp->drv_block = (STp->mt_status)->mt_fileno = (-1);
        STp->at_sm = 0;
      }
+     if (cmd_in == MTLOCK)
+       STp->door_locked = ST_LOCKED_EXPLICIT;
+     else if (cmd_in == MTUNLOCK)
+       STp->door_locked = ST_UNLOCKED;
      if (cmd_in == MTBSFM)
        ioctl_result = st_int_ioctl(inode, file, MTFSF, 1);
      else if (cmd_in == MTFSFM)
@@ -1728,6 +1763,8 @@
      if (STp->eof == ST_NOEOF &&
 	 (SCpnt->sense_buffer[2] & 0x0f) == BLANK_CHECK)
        STp->eof = ST_EOD;
+     if (cmd_in == MTLOCK)
+       STp->door_locked = ST_LOCK_FAILS;
    }
 
    return ioctl_result;
@@ -1751,7 +1788,7 @@
 
    dev = dev & 127;
    STp = &(scsi_tapes[dev]);
-#ifdef DEBUG
+#if DEBUG
    if (debugging && !STp->in_use) {
      printk("st%d: Incorrect device.\n", dev);
      return (-EIO);
@@ -1764,7 +1801,7 @@
      if (((cmd_in & IOCSIZE_MASK) >> IOCSIZE_SHIFT) != sizeof(mtc))
        return (-EINVAL);
 
-     i = verify_area(VERIFY_WRITE, (void *)arg, sizeof(mtc));
+     i = verify_area(VERIFY_READ, (void *)arg, sizeof(mtc));
      if (i)
 	return i;
 
@@ -1772,7 +1809,8 @@
 
      i = flush_buffer(inode, file, mtc.mt_op == MTSEEK ||
 		      mtc.mt_op == MTREW || mtc.mt_op == MTOFFL ||
-		      mtc.mt_op == MTRETEN || mtc.mt_op == MTEOM);
+		      mtc.mt_op == MTRETEN || mtc.mt_op == MTEOM ||
+		      mtc.mt_op == MTLOCK || mtc.mt_op == MTLOAD);
      if (i < 0)
        return i;
      if (mtc.mt_op != MTNOP && mtc.mt_op != MTSETBLK &&
@@ -1780,6 +1818,9 @@
 	 mtc.mt_op != MTSETDRVBUFFER)
        STp->rw = ST_IDLE;  /* Prevent automatic WEOF */
 
+     if (mtc.mt_op == MTOFFL && STp->door_locked != ST_UNLOCKED)
+       st_int_ioctl(inode, file, MTUNLOCK, 0);  /* Ignore result! */
+
      if (mtc.mt_op == MTSETDRVBUFFER &&
 	 (mtc.mt_count & MT_ST_OPTIONS) != 0)
        return st_set_options(inode, mtc.mt_count);
@@ -1842,7 +1883,7 @@
    else if (cmd == (MTIOCPOS & IOCCMD_MASK)) {
      if (STp->ready != ST_READY)
        return (-EIO);
-#ifdef DEBUG
+#if DEBUG
      if (debugging)
        printk("st%d: get tape position.\n", dev);
 #endif
@@ -1875,17 +1916,15 @@
 		 (void *) scmd, (void *) (STp->buffer)->b_data,
 		 20, st_sleep_done, ST_TIMEOUT, MAX_READY_RETRIES);
 
+     /* this must be done with interrupts off */
+     save_flags (flags);
+     cli();
+     if (SCpnt->request.dev == dev) sleep_on( &(STp->waiting) );
+     restore_flags(flags);
 
-	/* this must be done with interrupts off */
-	save_flags (flags);
-	cli();
-	if (SCpnt->request.dev == dev) sleep_on( &(STp->waiting) );
-	restore_flags(flags);
-
-     
      if ((STp->buffer)->last_result_fatal != 0) {
        mt_pos.mt_blkno = (-1);
-#ifdef DEBUG
+#if DEBUG
        if (debugging)
 	 printk("st%d: Can't read tape position.\n", dev);
 #endif
@@ -1910,10 +1949,8 @@
      memcpy_tofs((char *)arg, (char *) (&mt_pos), sizeof(struct mtpos));
      return result;
    }
-   else if (STp->ready == ST_READY)
-     return scsi_ioctl(STp->device, cmd_in, (void *) arg);
    else
-     return (-EIO);
+     return scsi_ioctl(STp->device, cmd_in, (void *) arg);
 }
 
 
@@ -1971,6 +2008,24 @@
    else
      scsi_tapes[i].mt_status->mt_type = MT_ISSCSI2;
 
+   tpnt->dirty = 0;
+   tpnt->rw = ST_IDLE;
+   tpnt->eof = ST_NOEOF;
+   tpnt->waiting = NULL;
+   tpnt->in_use = 0;
+   tpnt->drv_buffer = 1;  /* Try buffering if no mode sense */
+   tpnt->density = 0;
+   tpnt->do_buffer_writes = ST_BUFFER_WRITES;
+   tpnt->do_async_writes = ST_ASYNC_WRITES;
+   tpnt->do_read_ahead = ST_READ_AHEAD;
+   tpnt->do_auto_lock = ST_AUTO_LOCK;
+   tpnt->two_fm = ST_TWO_FM;
+   tpnt->fast_mteom = ST_FAST_MTEOM;
+   tpnt->write_threshold = st_write_threshold;
+   tpnt->drv_block = 0;
+   tpnt->moves_after_eof = 1;
+   tpnt->at_sm = 0;
+
    st_template.nr_dev++;
    return 0;
 };
@@ -1986,17 +2041,18 @@
   return 1;
 }
 
+static int st_registered = 0;
+
 /* Driver initialization */
 static void st_init()
 {
   int i;
   Scsi_Tape * STp;
-  static int st_registered = 0;
 
   if (st_template.dev_noticed == 0) return;
 
   if(!st_registered) {
-    if (register_chrdev(MAJOR_NR,"st",&st_fops)) {
+    if (register_chrdev(SCSI_TAPE_MAJOR,"st",&st_fops)) {
       printk("Unable to get major %d for SCSI tapes\n",MAJOR_NR);
       return;
     }
@@ -2009,7 +2065,7 @@
 					      sizeof(Scsi_Tape), GFP_ATOMIC);
   st_template.dev_max = st_template.dev_noticed + ST_EXTRA_DEVS;
 
-#ifdef DEBUG
+#if DEBUG
   printk("st: Buffer size %d bytes, write threshold %d bytes.\n",
 	 st_buffer_size, st_write_threshold);
 #endif
@@ -2028,6 +2084,7 @@
     STp->do_buffer_writes = ST_BUFFER_WRITES;
     STp->do_async_writes = ST_ASYNC_WRITES;
     STp->do_read_ahead = ST_READ_AHEAD;
+    STp->do_auto_lock = ST_AUTO_LOCK;
     STp->two_fm = ST_TWO_FM;
     STp->fast_mteom = ST_FAST_MTEOM;
     STp->write_threshold = st_write_threshold;
@@ -2053,7 +2110,7 @@
   for (i=0; i < st_nbr_buffers; i++) {
     st_buffers[i] = (ST_buffer *) scsi_init_malloc(sizeof(ST_buffer) - 
 						   1 + st_buffer_size, GFP_ATOMIC | GFP_DMA);
-#ifdef DEBUG
+#if DEBUG
 /*    printk("st: Buffer address: %p\n", st_buffers[i]); */
 #endif
     st_buffers[i]->in_use = 0;
@@ -2096,7 +2153,8 @@
     return;
   }
   scsi_unregister_module(MODULE_SCSI_DEV, &st_template);
-  unregister_chrdev(SCSI_GENERIC_MAJOR, "st");
+  unregister_chrdev(SCSI_TAPE_MAJOR, "st");
+  st_registered--;
   if(scsi_tapes != NULL) {
     scsi_init_free((char *) scsi_tapes,
 		   (st_template.dev_noticed + ST_EXTRA_DEVS) 
diff -u --recursive --new-file v1.3.21/linux/drivers/scsi/st.h linux/drivers/scsi/st.h
--- v1.3.21/linux/drivers/scsi/st.h	Fri Jan 13 09:08:37 1995
+++ linux/drivers/scsi/st.h	Thu Aug 31 07:44:09 1995
@@ -26,6 +26,7 @@
   struct wait_queue * waiting;
   Scsi_Device* device;
   unsigned char dirty;
+  unsigned char write_pending;
   unsigned char rw;
   unsigned char ready;
   unsigned char eof;
@@ -37,9 +38,11 @@
   unsigned char do_buffer_writes;
   unsigned char do_async_writes;
   unsigned char do_read_ahead;
+  unsigned char do_auto_lock;
   unsigned char two_fm;
   unsigned char fast_mteom;
   unsigned char density;
+  unsigned char door_locked;
   ST_buffer * buffer;
   int block_size;
   int min_block;
@@ -51,8 +54,14 @@
   unsigned char at_sm;
   struct mtget * mt_status;
   Scsi_Cmnd SCpnt;
+#if DEBUG
+  int nbr_finished;
+  int nbr_waits;
+#endif
 } Scsi_Tape;
 
+extern Scsi_Tape * scsi_tapes;
+
 /* Values of eof */
 #define	ST_NOEOF	0
 #define	ST_FM		1
@@ -69,6 +78,12 @@
 #define ST_READY	0
 #define ST_NOT_READY	1
 #define ST_NO_TAPE	2
+
+/* Values for door lock state */
+#define ST_UNLOCKED	0
+#define ST_LOCKED_EXPLICIT 1
+#define ST_LOCKED_AUTO  2
+#define ST_LOCK_FAILS   3
 
 /* Positioning SCSI-commands for Tandberg, etc. drives */
 #define	QFA_REQUEST_BLOCK	0x02
diff -u --recursive --new-file v1.3.21/linux/drivers/scsi/st_options.h linux/drivers/scsi/st_options.h
--- v1.3.21/linux/drivers/scsi/st_options.h	Thu Jan  1 02:00:00 1970
+++ linux/drivers/scsi/st_options.h	Thu Aug 31 07:44:09 1995
@@ -0,0 +1,80 @@
+/*
+   The compile-time configurable defaults for the Linux SCSI tape driver.
+
+   Copyright 1995 Kai Makisara.
+
+   Last modified: Sun Aug 27 22:26:53 1995 by root@kai.makisara.fi
+*/
+
+#ifndef _ST_OPTIONS_H
+#define _ST_OPTIONS_H
+
+/* The driver does not wait for some operations to finish before returning
+   to the user program if ST_NOWAIT is non-zero. This helps if the SCSI
+   adapter does not support multiple outstanding commands. However, the user
+   should not give a new tape command before the previous one has finished. */
+#define ST_NOWAIT 0
+
+/* If ST_IN_FILE_POS is nonzero, the driver positions the tape after the
+   record been read by the user program even if the tape has moved further
+   because of buffered reads. Should be set to zero to support also drives
+   that can't space backwards over records. NOTE: The tape will be
+   spaced backwards over an "accidentally" crossed filemark in any case. */
+#define ST_IN_FILE_POS 0
+
+/* If ST_RECOVERED_WRITE_FATAL is non-zero, recovered errors while writing
+   are considered "hard errors". */
+#define ST_RECOVERED_WRITE_FATAL 0
+
+/* The "guess" for the block size for devices that don't support MODE
+   SENSE. */
+#define ST_DEFAULT_BLOCK 0
+
+/* The tape driver buffer size in kilobytes. */
+#define ST_BUFFER_BLOCKS 32
+
+/* The number of kilobytes of data in the buffer that triggers an
+   asynchronous write in fixed block mode. See also ST_ASYNC_WRITES
+   below. */
+#define ST_WRITE_THRESHOLD_BLOCKS 30
+
+/* The maximum number of tape buffers the driver allocates. The number
+   is also constrained by the number of drives detected. Determines the
+   maximum number of concurrently active tape drives. */
+#define ST_MAX_BUFFERS (2 + ST_EXTRA_DEVS)
+
+
+/* The following lines define defaults for properties that can be set
+   separately for each drive using the MTSTOPTIONS ioctl. */
+
+/* If ST_TWO_FM is non-zero, the driver writes two filemarks after a
+   file being written. Some drives can't handle two filemarks at the
+   end of data. */
+#define ST_TWO_FM 0
+
+/* If ST_BUFFER_WRITES is non-zero, writes in fixed block mode are
+   buffered until the driver buffer is full or asynchronous write is
+   triggered. May make detection of End-Of-Medium early enough fail. */
+#define ST_BUFFER_WRITES 1
+
+/* If ST_ASYNC_WRITES is non-zero, the SCSI write command may be started
+   without waiting for it to finish. May cause problems in multiple
+   tape backups. */
+#define ST_ASYNC_WRITES 1
+
+/* If ST_READ_AHEAD is non-zero, blocks are read ahead in fixed block
+   mode. */
+#define ST_READ_AHEAD 1
+
+/* If ST_AUTO_LOCK is non-zero, the drive door is locked at the first
+   read or write command after the device is opened. The door is opened
+   when the device is closed. */
+#define ST_AUTO_LOCK 0
+
+/* If ST_FAST_MTEOM is non-zero, the MTEOM ioctl is done using the
+   direct SCSI command. The file number status is lost but this method
+   is fast with some drives. Otherwise MTEOM is done by spacing over
+   files and the file number status is retained. */
+#define ST_FAST_MTEOM 0
+
+#endif
diff -u --recursive --new-file v1.3.21/linux/drivers/scsi/u14-34f.c linux/drivers/scsi/u14-34f.c
--- v1.3.21/linux/drivers/scsi/u14-34f.c	Wed Aug  2 13:21:14 1995
+++ linux/drivers/scsi/u14-34f.c	Thu Aug 31 08:09:06 1995
@@ -658,6 +658,7 @@
    if (SCarg->host_scribble == NULL) {
       printk("%s: abort, target %d, pid %ld inactive.\n",
 	     BN(j), SCarg->target, SCarg->pid);
+      restore_flags(flags);
       return SCSI_ABORT_NOT_RUNNING;
       }
 
@@ -702,8 +703,8 @@
       restore_flags(flags);
       return SCSI_ABORT_NOT_RUNNING;
       }
-   else
-      panic("%s: abort, mbox %d, invalid cp_stat.\n", BN(j), i);
+   restore_flags(flags);
+   panic("%s: abort, mbox %d, invalid cp_stat.\n", BN(j), i);
 }
 
 int u14_34f_reset(Scsi_Cmnd * SCarg) {
diff -u --recursive --new-file v1.3.21/linux/fs/Makefile linux/fs/Makefile
--- v1.3.21/linux/fs/Makefile	Tue Aug 15 20:39:04 1995
+++ linux/fs/Makefile	Fri Sep  1 09:11:01 1995
@@ -80,6 +80,8 @@
 
 ifdef CONFIG_HPFS_FS
 SUB_DIRS += hpfs
+else
+MOD_SUB_DIRS += hpfs
 endif
 
 ifdef CONFIG_BINFMT_ELF
diff -u --recursive --new-file v1.3.21/linux/fs/binfmt_elf.c linux/fs/binfmt_elf.c
--- v1.3.21/linux/fs/binfmt_elf.c	Mon Aug 28 14:52:21 1995
+++ linux/fs/binfmt_elf.c	Fri Sep  1 16:21:05 1995
@@ -44,7 +44,7 @@
 extern sysfun_p sys_call_table[];
 #define SYS(name)	(sys_call_table[__NR_##name])
 
-#define DLINFO_ITEMS 8
+#define DLINFO_ITEMS 12
 
 #include <linux/elf.h>
 
@@ -119,7 +119,7 @@
 
 	}
 	sp = (unsigned long *) (0xfffffffc & (unsigned long) p);
-	if(exec) sp -= DLINFO_ITEMS*2;
+	sp -= exec ? DLINFO_ITEMS*2 : 2;
 	dlinfo = sp;
 	sp -= envc+1;
 	envp = sp;
@@ -130,21 +130,27 @@
 		put_user(argv,--sp);
 	}
 
-	/* The constant numbers (0-9) that we are writing here are
-	   described in the header file sys/auxv.h on at least
-	   some versions of SVr4 */
+#define NEW_AUX_ENT(id, val) \
+	  put_user ((id), dlinfo++); \
+	  put_user ((val), dlinfo++)
 	if(exec) { /* Put this here for an ELF program interpreter */
 	  struct elf_phdr * eppnt;
 	  eppnt = (struct elf_phdr *) exec->e_phoff;
-	  put_user(3,dlinfo++); put_user(load_addr + exec->e_phoff,dlinfo++);
-	  put_user(4,dlinfo++); put_user(sizeof(struct elf_phdr),dlinfo++);
-	  put_user(5,dlinfo++); put_user(exec->e_phnum,dlinfo++);
-	  put_user(9,dlinfo++); put_user((unsigned long) exec->e_entry,dlinfo++);
-	  put_user(7,dlinfo++); put_user(interp_load_addr,dlinfo++);
-	  put_user(8,dlinfo++); put_user(0,dlinfo++);
-	  put_user(6,dlinfo++); put_user(PAGE_SIZE,dlinfo++);
-	  put_user(0,dlinfo++); put_user(0,dlinfo++);
+
+	  NEW_AUX_ENT (AT_PHDR, load_addr + exec->e_phoff);
+	  NEW_AUX_ENT (AT_PHENT, sizeof (struct elf_phdr));
+	  NEW_AUX_ENT (AT_PHNUM, exec->e_phnum);
+	  NEW_AUX_ENT (AT_PAGESZ, PAGE_SIZE);
+	  NEW_AUX_ENT (AT_BASE, interp_load_addr);
+	  NEW_AUX_ENT (AT_FLAGS, 0);
+	  NEW_AUX_ENT (AT_ENTRY, (unsigned long) exec->e_entry);
+	  NEW_AUX_ENT (AT_UID, (unsigned long) current->uid);
+	  NEW_AUX_ENT (AT_EUID, (unsigned long) current->euid);
+	  NEW_AUX_ENT (AT_GID, (unsigned long) current->gid);
+	  NEW_AUX_ENT (AT_EGID, (unsigned long) current->egid);
 	}
+	NEW_AUX_ENT (AT_NULL, 0);
+#undef NEW_AUX_ENT
 
 	put_user((unsigned long)argc,--sp);
 	current->mm->arg_start = (unsigned long) p;
@@ -370,7 +376,8 @@
 	
 	
 	/* First of all, some simple consistency checks */
-	if(elf_ex.e_type != ET_EXEC || 
+	if((elf_ex.e_type != ET_EXEC &&
+	    elf_ex.e_type != ET_DYN) || 
 	   (elf_ex.e_machine != EM_386 && elf_ex.e_machine != EM_486) ||
 	   (!bprm->inode->i_op || !bprm->inode->i_op->default_file_ops ||
 	    !bprm->inode->i_op->default_file_ops->mmap)){
diff -u --recursive --new-file v1.3.21/linux/fs/buffer.c linux/fs/buffer.c
--- v1.3.21/linux/fs/buffer.c	Mon Aug 28 14:52:21 1995
+++ linux/fs/buffer.c	Fri Sep  1 07:52:18 1995
@@ -790,15 +790,17 @@
 		if (--buf->b_count)
 			return;
 		wake_up(&buffer_wait);
+#if 0
 		if (buf->b_reuse) {
+			buf->b_reuse = 0;
 			if (!buf->b_lock && !buf->b_dirt && !buf->b_wait) {
-			    	buf->b_reuse = 0;
 				if(buf->b_dev == 0xffff) panic("brelse: Wrong list");
 				remove_from_queues(buf);
 				buf->b_dev = 0xffff;
 				put_last_free(buf);
 			}
 		}
+#endif
 		return;
 	}
 	printk("VFS: brelse: Trying to free free buffer\n");
@@ -1659,10 +1661,11 @@
 void buffer_init(void)
 {
 	int i;
-        int isize = BUFSIZE_INDEX(BLOCK_SIZE);
+	int isize = BUFSIZE_INDEX(BLOCK_SIZE);
+	long memsize = MAP_NR(high_memory) << PAGE_SHIFT;
 
-	if (high_memory >= 4*1024*1024) {
-		if(high_memory >= 16*1024*1024)
+	if (memsize >= 4*1024*1024) {
+		if(memsize >= 16*1024*1024)
 			 nr_hash = 16381;
 		else
 			 nr_hash = 4093;
diff -u --recursive --new-file v1.3.21/linux/fs/exec.c linux/fs/exec.c
--- v1.3.21/linux/fs/exec.c	Fri Jul  7 13:42:58 1995
+++ linux/fs/exec.c	Tue Aug 29 10:15:52 1995
@@ -235,14 +235,14 @@
 	set_fs(USER_DS);
 /* Dump the data area */
 	if (dump.u_dsize != 0) {
-		dump_start = dump.u_tsize << 12;
-		dump_size = dump.u_dsize << 12;
+		dump_start = dump.u_tsize << PAGE_SHIFT;
+		dump_size = dump.u_dsize << PAGE_SHIFT;
 		DUMP_WRITE(dump_start,dump_size);
 	}
 /* Now prepare to dump the stack area */
 	if (dump.u_ssize != 0) {
 		dump_start = dump.start_stack;
-		dump_size = dump.u_ssize << 12;
+		dump_size = dump.u_ssize << PAGE_SHIFT;
 		DUMP_WRITE(dump_start,dump_size);
 	}
 /* Finally dump the task struct.  Not be used by gdb, but could be useful */
@@ -317,14 +317,29 @@
 		insert_vm_struct(current, mpnt);
 	}
 	sp = (unsigned long *) ((-(unsigned long)sizeof(char *)) & (unsigned long) p);
+#ifdef __alpha__
+/* whee.. test-programs are so much fun. */
+	put_user(0, --sp);
+	put_user(0, --sp);
+	if (bprm->loader) {
+		put_user(0, --sp);
+		put_user(0x3eb, --sp);
+		put_user(bprm->loader, --sp);
+		put_user(0x3ea, --sp);
+	}
+	put_user(bprm->exec, --sp);
+	put_user(0x3e9, --sp);
+#endif
 	sp -= envc+1;
 	envp = sp;
 	sp -= argc+1;
 	argv = sp;
+#ifdef __i386__
 	if (!ibcs) {
 		put_user(envp,--sp);
 		put_user(argv,--sp);
 	}
+#endif
 	put_user(argc,--sp);
 	current->mm->arg_start = (unsigned long) p;
 	while (argc-->0) {
@@ -561,6 +576,7 @@
 	int i;
 	int retval;
 	int sh_bang = 0;
+	int loader = 0;
 
 	bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);
 	for (i=0 ; i<MAX_ARG_PAGES ; i++)	/* clear page-table */
@@ -691,6 +707,20 @@
 			goto exec_error1;
 		goto restart_interp;
 	}
+#ifdef __alpha__
+/* handle /sbin/loader.. */
+	if (!loader && (((struct exec *) bprm.buf)->fh.f_flags & 0x3000)) {
+		char * dynloader[] = { "/sbin/loader" };
+		iput(bprm.inode);
+		loader = 1;
+		bprm.p = copy_strings(1, dynloader, bprm.page, bprm.p, 2);
+		bprm.loader = bprm.p;
+		retval = open_namei(dynloader[0], 0, 0, &bprm.inode, NULL);
+		if (retval)
+			goto exec_error1;
+		goto restart_interp;
+	}
+#endif
 	if (!sh_bang) {
 		bprm.p = copy_strings(1, &bprm.filename, bprm.page, bprm.p, 2);
 		bprm.exec = bprm.p;
@@ -855,6 +885,9 @@
 	p = (unsigned long)create_tables((char *)p, bprm,
 					current->personality != PER_LINUX);
 	current->mm->start_stack = p;
+#ifdef __alpha__
+	regs->gp = ex.a_gpvalue;
+#endif
 	start_thread(regs, ex.a_entry, p);
 	if (current->flags & PF_PTRACED)
 		send_sig(SIGTRAP, current, 0);
diff -u --recursive --new-file v1.3.21/linux/fs/hpfs/README linux/fs/hpfs/README
--- v1.3.21/linux/fs/hpfs/README	Wed Feb 23 09:45:39 1994
+++ linux/fs/hpfs/README	Thu Jan  1 02:00:00 1970
@@ -1,25 +0,0 @@
-Linux can read, but not write, OS/2 HPFS partitions.
-
-Mount options are the same as for msdos partitions.
-
-  uid=nnn	All files in the partition will be owned by user id nnn.
-  gid=nnn	All files in the partition will be in group nnn.
-  umask=nnn	The permission mask (see umask(1)) for the partition.
-  conv=binary   Data is returned exactly as is, with CRLF's.  [default]
-  conv=text     (Carriage return, line feed) is replaced with newline.
-  conv=auto     Chooses, file by file, conv=binary or conv=text (by guessing)
-
-There is one mount option unique to HPFS.
-
-  case=lower	Convert file names to lower case.  [default]
-  case=asis     Return file names as is, in mixed case.
-
-Case is not significant in filename matching, like real HPFS.
-
-
-Command line example
-    mkdir -p /os2/c
-    mount -t hpfs -o uid=100,gid=100 /dev/sda6 /os2/c
-
-/etc/fstab example
-    /dev/sdb5	/d/f    hpfs    ro,uid=402,gid=402,umask=002
diff -u --recursive --new-file v1.3.21/linux/fs/hpfs/hpfs_caps.c linux/fs/hpfs/hpfs_caps.c
--- v1.3.21/linux/fs/hpfs/hpfs_caps.c	Wed Apr  5 12:59:50 1995
+++ linux/fs/hpfs/hpfs_caps.c	Fri Sep  1 09:11:01 1995
@@ -62,6 +62,15 @@
    code pages OS/2 is using.  Recoding from on-disk names to UTF-8
    could use the code page tags, though this is not what OS/2 does. */
 
+#ifdef MODULE
+#include <linux/module.h>
+#include <linux/version.h>
+#else
+#define MOD_INC_USE_COUNT
+#define MOD_DEC_USE_COUNT
+#endif
+
+
 static const unsigned char tb_cp850_to_latin1[128] =
 {
   199, 252, 233, 226, 228, 224, 229, 231,
diff -u --recursive --new-file v1.3.21/linux/fs/hpfs/hpfs_fs.c linux/fs/hpfs/hpfs_fs.c
--- v1.3.21/linux/fs/hpfs/hpfs_fs.c	Thu Jul 27 10:13:17 1995
+++ linux/fs/hpfs/hpfs_fs.c	Fri Sep  1 09:11:02 1995
@@ -12,6 +12,14 @@
  *   linux/fs/isofs  Copyright (C) 1991  Eric Youngdale
  */
 
+#ifdef MODULE
+#include <linux/module.h>
+#include <linux/version.h>
+#else
+#define MOD_INC_USE_COUNT
+#define MOD_DEC_USE_COUNT
+#endif
+
 #include <linux/fs.h>
 #include <linux/hpfs_fs.h>
 #include <linux/errno.h>
@@ -343,6 +351,8 @@
 	int conv;
 	int dubious;
 
+	MOD_INC_USE_COUNT;
+
 	/*
 	 * Get the mount options
 	 */
@@ -350,6 +360,7 @@
 	if (!parse_opts(options, &uid, &gid, &umask, &lowercase, &conv)) {
 		printk("HPFS: syntax error in mount options.  Not mounted.\n");
 		s->s_dev = 0;
+		MOD_DEC_USE_COUNT;
 		return 0;
 	}
 
@@ -481,6 +492,7 @@
 	if (!s->s_mounted) {
 		printk("HPFS: hpfs_read_super: inode get failed\n");
 		s->s_dev = 0;
+		MOD_DEC_USE_COUNT;
 		return 0;
 	}
 
@@ -495,6 +507,7 @@
 		printk("HPFS: "
 		       "hpfs_read_super: root dir isn't in the root dir\n");
 		s->s_dev = 0;
+		MOD_DEC_USE_COUNT;
 		return 0;
 	}
 
@@ -514,6 +527,7 @@
  bail:
 	s->s_dev = 0;
 	unlock_super(s);
+	MOD_DEC_USE_COUNT;
 	return 0;
 }
 
@@ -715,6 +729,7 @@
 	lock_super(s);
 	s->s_dev = 0;
 	unlock_super(s);
+	MOD_DEC_USE_COUNT;
 }
 
 /*
@@ -1725,3 +1740,25 @@
 	brelse(qbh->bh[0]);
 	kfree_s(qbh->data, 2048);
 }
+
+#ifdef MODULE
+
+char kernel_version[] = UTS_RELEASE;
+
+static struct file_system_type hpfs_fs_type = {
+        hpfs_read_super, "hpfs", 1, NULL
+};
+
+int init_module(void)
+{
+        register_filesystem(&hpfs_fs_type);
+        return 0;
+}
+
+void cleanup_module(void)
+{
+        unregister_filesystem(&hpfs_fs_type);
+}
+
+#endif
+
diff -u --recursive --new-file v1.3.21/linux/fs/nfs/cache.c linux/fs/nfs/cache.c
--- v1.3.21/linux/fs/nfs/cache.c	Tue Jun  6 11:22:11 1995
+++ linux/fs/nfs/cache.c	Thu Aug 31 08:09:06 1995
@@ -12,6 +12,7 @@
 		nh->data=NULL;
 		nh->free=1;
 	}
+	restore_flags(flags);
 }
 
 void nfs_bl_cache_revalidate(nfs_cache *nh, struct fattr fa)
diff -u --recursive --new-file v1.3.21/linux/fs/open.c linux/fs/open.c
--- v1.3.21/linux/fs/open.c	Tue Aug  8 12:31:39 1995
+++ linux/fs/open.c	Thu Aug 31 14:38:11 1995
@@ -466,16 +466,9 @@
 	struct file * f;
 	int flag,error,fd;
 
-	for(fd=0; fd<NR_OPEN && fd<current->rlim[RLIMIT_NOFILE].rlim_cur; fd++)
-		if (!current->files->fd[fd])
-			break;
-	if (fd>=NR_OPEN || fd>=current->rlim[RLIMIT_NOFILE].rlim_cur)
-		return -EMFILE;
-	FD_CLR(fd,&current->files->close_on_exec);
 	f = get_empty_filp();
 	if (!f)
 		return -ENFILE;
-	current->files->fd[fd] = f;
 	f->f_flags = flag = flags;
 	f->f_mode = (flag+1) & O_ACCMODE;
 	if (f->f_mode)
@@ -483,15 +476,12 @@
 	if (flag & (O_TRUNC | O_CREAT))
 		flag |= 2;
 	error = open_namei(filename,flag,mode,&inode,NULL);
-	if (!error && (f->f_mode & 2)) {
+	if (error)
+		goto cleanup_file;
+	if (f->f_mode & 2) {
 		error = get_write_access(inode);
 		if (error)
-			iput(inode);
-	}
-	if (error) {
-		current->files->fd[fd]=NULL;
-		f->f_count--;
-		return error;
+			goto cleanup_inode;
 	}
 
 	f->f_inode = inode;
@@ -502,16 +492,34 @@
 		f->f_op = inode->i_op->default_file_ops;
 	if (f->f_op && f->f_op->open) {
 		error = f->f_op->open(inode,f);
-		if (error) {
-			if (f->f_mode & 2) put_write_access(inode);
-			iput(inode);
-			f->f_count--;
-			current->files->fd[fd]=NULL;
-			return error;
-		}
+		if (error)
+			goto cleanup_all;
 	}
 	f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
-	return (fd);
+
+	/*
+	 * We have to do this last, because we mustn't export
+	 * an incomplete fd to other processes which may share
+	 * the same file table with us.
+	 */
+	for(fd = 0; fd < NR_OPEN && fd < current->rlim[RLIMIT_NOFILE].rlim_cur; fd++) {
+		if (!current->files->fd[fd]) {
+			current->files->fd[fd] = f;
+			FD_CLR(fd,&current->files->close_on_exec);
+			return fd;
+		}
+	}
+	error = -EMFILE;
+	if (f->f_op && f->f_op->release)
+		f->f_op->release(inode,f);
+cleanup_all:
+	if (f->f_mode & 2)
+		put_write_access(inode);
+cleanup_inode:
+	iput(inode);
+cleanup_file:
+	f->f_count--;
+	return error;
 }
 
 asmlinkage int sys_open(const char * filename,int flags,int mode)
diff -u --recursive --new-file v1.3.21/linux/fs/proc/array.c linux/fs/proc/array.c
--- v1.3.21/linux/fs/proc/array.c	Wed Aug  9 14:55:42 1995
+++ linux/fs/proc/array.c	Tue Aug 29 10:15:52 1995
@@ -56,7 +56,7 @@
 
 static int read_core(struct inode * inode, struct file * file,char * buf, int count)
 {
-	unsigned long p = file->f_pos;
+	unsigned long p = file->f_pos, memsize;
 	int read;
 	int count1;
 	char * pnt;
@@ -64,14 +64,15 @@
 
 	memset(&dump, 0, sizeof(struct user));
 	dump.magic = CMAGIC;
-	dump.u_dsize = high_memory >> 12;
+	dump.u_dsize = MAP_NR(high_memory);
 
 	if (count < 0)
 		return -EINVAL;
-	if (p >= high_memory + PAGE_SIZE)
+	memsize = MAP_NR(high_memory + PAGE_SIZE) << PAGE_SHIFT;
+	if (p >= memsize)
 		return 0;
-	if (count > high_memory + PAGE_SIZE - p)
-		count = high_memory + PAGE_SIZE - p;
+	if (count > memsize - p)
+		count = memsize - p;
 	read = 0;
 
 	if (p < sizeof(struct user) && count > 0) {
@@ -93,7 +94,7 @@
 		count--;
 		read++;
 	}
-	memcpy_tofs(buf,(void *) (p - PAGE_SIZE),count);
+	memcpy_tofs(buf,(void *) (PAGE_OFFSET + p - PAGE_SIZE),count);
 	read += count;
 	file->f_pos += read;
 	return read;
diff -u --recursive --new-file v1.3.21/linux/fs/proc/inode.c linux/fs/proc/inode.c
--- v1.3.21/linux/fs/proc/inode.c	Tue Aug 15 20:39:04 1995
+++ linux/fs/proc/inode.c	Tue Aug 29 10:15:52 1995
@@ -210,7 +210,7 @@
 			case PROC_KCORE:
 				inode->i_mode = S_IFREG | S_IRUSR;
 				inode->i_op = &proc_kcore_inode_operations;
-				inode->i_size = high_memory + PAGE_SIZE;
+				inode->i_size = (MAP_NR(high_memory) << PAGE_SHIFT) + PAGE_SIZE;
 				break;
 #ifdef CONFIG_PROFILE
 			case PROC_PROFILE:
diff -u --recursive --new-file v1.3.21/linux/fs/proc/mem.c linux/fs/proc/mem.c
--- v1.3.21/linux/fs/proc/mem.c	Fri Aug 18 08:44:58 1995
+++ linux/fs/proc/mem.c	Tue Aug 29 09:42:56 1995
@@ -289,8 +289,8 @@
 		if ((vma->vm_flags & VM_WRITE) && !pte_write(*src_table))
 			do_wp_page(src_vma, stmp, 1);
 
-		*src_table = pte_mkdirty(*src_table);
-		*dest_table = *src_table;
+		set_pte(src_table, pte_mkdirty(*src_table));
+		set_pte(dest_table, *src_table);
 		mem_map[MAP_NR(pte_page(*src_table))]++;
 
 		stmp += PAGE_SIZE;
diff -u --recursive --new-file v1.3.21/linux/fs/select.c linux/fs/select.c
--- v1.3.21/linux/fs/select.c	Tue Jun 27 14:11:44 1995
+++ linux/fs/select.c	Fri Sep  1 09:05:37 1995
@@ -92,8 +92,8 @@
 	int i,j;
 	int max = -1;
 
-	for (j = 0 ; j < __FDSET_LONGS ; j++) {
-		i = j << 5;
+	for (j = 0 ; j < __FDSET_INTS ; j++) {
+		i = j * __NFDBITS;
 		if (i >= n)
 			break;
 		set = in->fds_bits[j] | out->fds_bits[j] | ex->fds_bits[j];
@@ -154,10 +154,10 @@
  * We do a VERIFY_WRITE here even though we are only reading this time:
  * we'll write to it eventually..
  */
-static int __get_fd_set(int nr, unsigned long * fs_pointer, fd_set * fdset)
+static int __get_fd_set(int nr, unsigned int * fs_pointer, fd_set * fdset)
 {
 	int error, i;
-	unsigned long * tmp;
+	unsigned int * tmp;
 
 	FD_ZERO(fdset);
 	if (!fs_pointer)
@@ -166,38 +166,38 @@
 	if (error)
 		return error;
 	tmp = fdset->fds_bits;
-	for (i = __FDSET_LONGS; i > 0; i--) {
+	for (i = __FDSET_INTS; i > 0; i--) {
 		if (nr <= 0)
 			break;
 		*tmp = get_user(fs_pointer);
 		tmp++;
 		fs_pointer++;
-		nr -= 8 * sizeof(unsigned long);
+		nr -= 8 * sizeof(unsigned int);
 	}
 	return 0;
 }
 
-static void __set_fd_set(int nr, unsigned long * fs_pointer, unsigned long * fdset)
+static void __set_fd_set(int nr, unsigned int * fs_pointer, unsigned int * fdset)
 {
 	int i;
 
 	if (!fs_pointer)
 		return;
-	for (i = __FDSET_LONGS; i > 0; i--) {
+	for (i = __FDSET_INTS; i > 0; i--) {
 		if (nr <= 0)
 			break;
 		put_user(*fdset, fs_pointer);
 		fdset++;
 		fs_pointer++;
-		nr -= 8 * sizeof(unsigned long);
+		nr -= 8 * sizeof(unsigned int);
 	}
 }
 
 #define get_fd_set(nr,fsp,fdp) \
-__get_fd_set(nr, (unsigned long *) (fsp), fdp)
+__get_fd_set(nr, (unsigned int *) (fsp), fdp)
 
 #define set_fd_set(nr,fsp,fdp) \
-__set_fd_set(nr, (unsigned long *) (fsp), (unsigned long *) (fdp))
+__set_fd_set(nr, (unsigned int *) (fsp), (unsigned int *) (fdp))
 
 /*
  * We can actually return ERESTARTSYS instead of EINTR, but I'd
diff -u --recursive --new-file v1.3.21/linux/fs/smbfs/README linux/fs/smbfs/README
--- v1.3.21/linux/fs/smbfs/README	Mon Aug 28 14:52:22 1995
+++ linux/fs/smbfs/README	Thu Jan  1 02:00:00 1970
@@ -1,12 +0,0 @@
-smbfs is a filesystem which understands the SMB protocol. This is the
-protocol Windows for Workgroups, Windows NT or Lan Manager use to talk
-to each other. smbfs was inspired by samba, the program written by
-Andrew Tridgell that turns any unix host into a file server for DOS or
-Windows clients.  See ftp://nimbus.anu.edu.au/pub/tridge/samba/ for
-this interesting program suite and lots of more information on SMB and
-NetBIOS over TCP/IP. There you also find explanation for conceps like
-netbios name or share.
-
-To use smbfs, you need a special mount program, which can be found in
-the ksmbfs package, found on sunsite.unc.edu:/pub/Linux/ALPHA/smbfs.
-
diff -u --recursive --new-file v1.3.21/linux/fs/super.c linux/fs/super.c
--- v1.3.21/linux/fs/super.c	Tue Aug  8 12:31:41 1995
+++ linux/fs/super.c	Tue Aug 29 10:15:52 1995
@@ -330,7 +330,7 @@
 
 static char unnamed_dev_in_use[256/8] = { 0, };
 
-static dev_t get_unnamed_dev(void)
+dev_t get_unnamed_dev(void)
 {
 	int i;
 
@@ -341,7 +341,7 @@
 	return 0;
 }
 
-static void put_unnamed_dev(dev_t dev)
+void put_unnamed_dev(dev_t dev)
 {
 	if (!dev)
 		return;
@@ -460,7 +460,7 @@
  * We also have to flush all inode-data for this device, as the new mount
  * might need new info.
  */
-static int do_mount(dev_t dev, const char * dir, const char * type, int flags, void * data)
+int do_mount(dev_t dev, const char * dir, const char * type, int flags, void * data)
 {
 	struct inode * dir_i;
 	struct super_block * sb;
diff -u --recursive --new-file v1.3.21/linux/fs/sysv/README linux/fs/sysv/README
--- v1.3.21/linux/fs/sysv/README	Sat Nov  5 13:32:13 1994
+++ linux/fs/sysv/README	Thu Jan  1 02:00:00 1970
@@ -1,37 +0,0 @@
-This is the implementation of the SystemV/Coherent filesystem for Linux.
-It implements all of
-  - Xenix FS,
-  - SystemV/386 FS,
-  - Coherent FS.
-
-This is version beta 4.
-
-To install:
-* Answer the 'System V and Coherent filesystem support' question with 'y'
-  when configuring the kernel.
-* To mount a disk or a partition, use
-    mount [-r] -t sysv device mountpoint
-  The file system type names
-               -t sysv
-               -t xenix
-               -t coherent
-  may be used interchangeably, but the last two will eventually disappear.
-
-Bugs in the present implementation:
-- Coherent FS:
-  - The "free list interleave" n:m is currently ignored.
-  - Only file systems with no filesystem name and no pack name are recognized.
-  (See Coherent "man mkfs" for a description of these features.)
-- SystemV Release 2 FS:
-  The superblock is only searched in the blocks 9, 15, 18, which corresponds to the
-  beginning of track 1 on floppy disks. No support for this FS on hard disk yet.
-
-
-Please report any bugs and suggestions to
-  Bruno Haible <haible@ma2s2.mathematik.uni-karlsruhde.de> or
-  Pascal Haible <haible@izfm.uni-stuttgart.de> .
-
-
-Bruno Haible
-<haible@ma2s2.mathematik.uni-karlsruhe.de>
-
diff -u --recursive --new-file v1.3.21/linux/fs/umsdos/README linux/fs/umsdos/README
--- v1.3.21/linux/fs/umsdos/README	Tue Jan 31 09:39:02 1995
+++ linux/fs/umsdos/README	Thu Jan  1 02:00:00 1970
@@ -1,96 +0,0 @@
-Very short explanation for the impatient!!!
-
-Umsdos is a file system driver that run on top the MSDOS fs driver.
-It is written by Jacques Gelinas (jacques@solucorp.qc.ca)
-
-Umsdos is not a file system per se, but a twist to make a boring
-one into a useful one.
-
-It gives you:
-
-	long file name
-	Permissions and owner
-	Links
-	Special files (devices, pipe...)
-	All is need to be a linux root fs.
-
-There is plenty of documentation on it in the source. A formated document
-made from those comments is available from
-sunsite.unc.edu:/pub/Linux/system/Filesystems/umsdos.
-
-Mostly...
-
-You mount a DOS partition like this
-
-mount -t umsdos /dev/hda3 /mnt
-         ^
----------|
-
-All option are passed to the msdos drivers. Option like uid,gid etc are
-given to msdos.
-
-The default behavior of Umsdos is to do the same thing as the msdos driver
-mostly passing commands to it without much processing. Again, this is
-the default. After doing the mount on a DOS partition, nothing special
-happen. This is why all mount options are passed to the Msdos fs driver.
-
-Umsdos use a special DOS file --linux-.--- to store the information
-which can't be handle by the normal MsDOS file system. This is the trick.
-
---linux-.--- is optional. There is one per directory.
-
-**** If --linux-.--- is missing, then Umsdos process the directory the
-     same way the msdos driver do. Short file name, no goodies, default
-     owner and permissions. So each directory may have or not this
-     --linux-.---
-
-Now, how to get those --linux-.---.
-
-\begin joke_section
-
-	Well send me a directory content
-	and I will send you one customised for you.
-	$5 per directory. Add any applicable taxes.
-\end joke_section
-
-A utility umssync creates those. The kernel maintain them. It is available
-from the same directory above (sunsite) in the file umsdos_progs-0.7.tar.gz.
-A compiled version is available in umsdos_progs-0.7.bin.tar.gz.
-
-So in our example, after mounting mnt, we do
-
-umssync .
-
-This will promote this directory (a recursive option is available) to full
-umsdos capabilities (long name ...). A ls -l before and after won't show
-much difference however. The file which were there are still there. But now
-you can do all this:
-
-	chmod 644 *
-	chown you.your_groupe *
-	ls >THIS_IS.A.VERY.LONG.NAME
-	ln -s toto tata
-	ls -l
-
-Once a directory is promoted, all subdirectory created will inherit that
-promotion.
-
-What happen if you boot DOS and create files in those promoted directories ?
-Umsdos won't notice new files, but will signal removed file (it won't crash).
-Using umssync in /etc/rc will make sure the DOS directory is in sync with
-the --linux-.---.
-
-It is a good idea to put the following command in your RC file just
-after the "mount -a":
-
-	mount -a
-	/sbin/umssync -i+ -c+ -r99 /umsdos_mount_point
-
-	(You put one for each umsdos mount point in the fstab)
-
-This will insure nice operation. A umsdos.fsck is in the making,
-so you will be allowed to managed umsdos partition in the same way
-other filesystem are, using the generic fsck front end.
-
-Hope this helps!
-
diff -u --recursive --new-file v1.3.21/linux/include/asm-alpha/apecs.h linux/include/asm-alpha/apecs.h
--- v1.3.21/linux/include/asm-alpha/apecs.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-alpha/apecs.h	Tue Aug 29 10:15:52 1995
@@ -0,0 +1,413 @@
+#ifndef __ALPHA_APECS__H__
+#define __ALPHA_APECS__H__
+
+#include <linux/types.h>
+
+/*
+ * APECS is the internal name for the 2107x chipset which provides
+ * memory controller and PCI access for the 21064 chip based systems.
+ *
+ * This file is based on:
+ *
+ * DECchip 21071-AA and DECchip 21072-AA Core Logic Chipsets
+ * Data Sheet
+ *
+ * EC-N0648-72
+ *
+ *
+ * david.rusling@reo.mts.dec.com Initial Version.
+ *
+ */
+
+#define APECS_DMA_WIN_BASE	(1024*1024*1024)
+#define APECS_DMA_WIN_SIZE	(1024*1024*1024)
+
+/*
+ * 21071-DA Control and Status registers.
+ * These are used for PCI memory access.
+ */
+#define APECS_IOC_DCSR                  (IDENT_ADDR + 0x1A0000000UL)
+#define APECS_IOC_PEAR                  (IDENT_ADDR + 0x1A0000020UL)
+#define APECS_IOC_SEAR                  (IDENT_ADDR + 0x1A0000040UL)
+#define APECS_IOC_DR1                   (IDENT_ADDR + 0x1A0000060UL)
+#define APECS_IOC_DR2                   (IDENT_ADDR + 0x1A0000080UL)
+#define APECS_IOC_DR3                   (IDENT_ADDR + 0x1A00000A0UL)
+
+#define APECS_IOC_TB1R                  (IDENT_ADDR + 0x1A00000C0UL)
+#define APECS_IOC_TB2R                  (IDENT_ADDR + 0x1A00000E0UL)
+
+#define APECS_IOC_PB1R                  (IDENT_ADDR + 0x1A0000100UL)
+#define APECS_IOC_PB2R                  (IDENT_ADDR + 0x1A0000120UL)
+
+#define APECS_IOC_PM1R                  (IDENT_ADDR + 0x1A0000140UL)
+#define APECS_IOC_PM2R                  (IDENT_ADDR + 0x1A0000160UL)
+
+#define APECS_IOC_HAXR0                 (IDENT_ADDR + 0x1A0000180UL)
+#define APECS_IOC_HAXR1                 (IDENT_ADDR + 0x1A00001A0UL)
+#define APECS_IOC_HAXR2                 (IDENT_ADDR + 0x1A00001C0UL)
+
+#define APECS_IOC_PMLT                  (IDENT_ADDR + 0x1A00001E0UL)
+
+#define APECS_IOC_TLBTAG0               (IDENT_ADDR + 0x1A0000200UL)
+#define APECS_IOC_TLBTAG1               (IDENT_ADDR + 0x1A0000220UL)
+#define APECS_IOC_TLBTAG2               (IDENT_ADDR + 0x1A0000240UL)
+#define APECS_IOC_TLBTAG3               (IDENT_ADDR + 0x1A0000260UL)
+#define APECS_IOC_TLBTAG4               (IDENT_ADDR + 0x1A0000280UL)
+#define APECS_IOC_TLBTAG5               (IDENT_ADDR + 0x1A00002A0UL)
+#define APECS_IOC_TLBTAG6               (IDENT_ADDR + 0x1A00002C0UL)
+#define APECS_IOC_TLBTAG7               (IDENT_ADDR + 0x1A00002E0UL)
+
+#define APECS_IOC_TLBDATA0              (IDENT_ADDR + 0x1A0000300UL)
+#define APECS_IOC_TLBDATA1              (IDENT_ADDR + 0x1A0000320UL)
+#define APECS_IOC_TLBDATA2              (IDENT_ADDR + 0x1A0000340UL)
+#define APECS_IOC_TLBDATA3              (IDENT_ADDR + 0x1A0000360UL)
+#define APECS_IOC_TLBDATA4              (IDENT_ADDR + 0x1A0000380UL)
+#define APECS_IOC_TLBDATA5              (IDENT_ADDR + 0x1A00003A0UL)
+#define APECS_IOC_TLBDATA6              (IDENT_ADDR + 0x1A00003C0UL)
+#define APECS_IOC_TLBDATA7              (IDENT_ADDR + 0x1A00003E0UL)
+
+#define APECS_IOC_TBIA                  (IDENT_ADDR + 0x1A0000400UL)
+
+
+/*
+ * 21071-CA Control and Status registers.
+ * These are used to program memory timing,
+ *  configure memory and initialise the B-Cache.
+ */
+#define APECS_IOC_GCR		        (IDENT_ADDR + 0x180000000UL)
+#define APECS_IOC_EDSR		        (IDENT_ADDR + 0x180000040UL)
+#define APECS_IOC_TAR  		        (IDENT_ADDR + 0x180000060UL)
+#define APECS_IOC_ELAR		        (IDENT_ADDR + 0x180000080UL)
+#define APECS_IOC_EHAR  		(IDENT_ADDR + 0x1800000a0UL)
+#define APECS_IOC_SFT_RST		(IDENT_ADDR + 0x1800000c0UL)
+#define APECS_IOC_LDxLAR 		(IDENT_ADDR + 0x1800000e0UL)
+#define APECS_IOC_LDxHAR 		(IDENT_ADDR + 0x180000100UL)
+#define APECS_IOC_GTR    		(IDENT_ADDR + 0x180000200UL)
+#define APECS_IOC_RTR    		(IDENT_ADDR + 0x180000220UL)
+#define APECS_IOC_VFPR   		(IDENT_ADDR + 0x180000240UL)
+#define APECS_IOC_PDLDR  		(IDENT_ADDR + 0x180000260UL)
+#define APECS_IOC_PDhDR  		(IDENT_ADDR + 0x180000280UL)
+
+/* Bank x Base Address Register */
+#define APECS_IOC_B0BAR  		(IDENT_ADDR + 0x180000800UL)
+#define APECS_IOC_B1BAR  		(IDENT_ADDR + 0x180000820UL)
+#define APECS_IOC_B2BAR  		(IDENT_ADDR + 0x180000840UL)
+#define APECS_IOC_B3BAR  		(IDENT_ADDR + 0x180000860UL)
+#define APECS_IOC_B4BAR  		(IDENT_ADDR + 0x180000880UL)
+#define APECS_IOC_B5BAR  		(IDENT_ADDR + 0x1800008A0UL)
+#define APECS_IOC_B6BAR  		(IDENT_ADDR + 0x1800008C0UL)
+#define APECS_IOC_B7BAR  		(IDENT_ADDR + 0x1800008E0UL)
+#define APECS_IOC_B8BAR  		(IDENT_ADDR + 0x180000900UL)
+
+/* Bank x Configuration Register */
+#define APECS_IOC_B0BCR  		(IDENT_ADDR + 0x180000A00UL)
+#define APECS_IOC_B1BCR  		(IDENT_ADDR + 0x180000A20UL)
+#define APECS_IOC_B2BCR  		(IDENT_ADDR + 0x180000A40UL)
+#define APECS_IOC_B3BCR  		(IDENT_ADDR + 0x180000A60UL)
+#define APECS_IOC_B4BCR  		(IDENT_ADDR + 0x180000A80UL)
+#define APECS_IOC_B5BCR  		(IDENT_ADDR + 0x180000AA0UL)
+#define APECS_IOC_B6BCR  		(IDENT_ADDR + 0x180000AC0UL)
+#define APECS_IOC_B7BCR  		(IDENT_ADDR + 0x180000AE0UL)
+#define APECS_IOC_B8BCR  		(IDENT_ADDR + 0x180000B00UL)
+
+/* Bank x Timing Register A */
+#define APECS_IOC_B0TRA  		(IDENT_ADDR + 0x180000C00UL)
+#define APECS_IOC_B1TRA  		(IDENT_ADDR + 0x180000C20UL)
+#define APECS_IOC_B2TRA  		(IDENT_ADDR + 0x180000C40UL)
+#define APECS_IOC_B3TRA  		(IDENT_ADDR + 0x180000C60UL)
+#define APECS_IOC_B4TRA  		(IDENT_ADDR + 0x180000C80UL)
+#define APECS_IOC_B5TRA  		(IDENT_ADDR + 0x180000CA0UL)
+#define APECS_IOC_B6TRA  		(IDENT_ADDR + 0x180000CC0UL)
+#define APECS_IOC_B7TRA  		(IDENT_ADDR + 0x180000CE0UL)
+#define APECS_IOC_B8TRA  		(IDENT_ADDR + 0x180000D00UL)
+
+/* Bank x Timing Register B */
+#define APECS_IOC_B0TRB                 (IDENT_ADDR + 0x180000E00UL)
+#define APECS_IOC_B1TRB  		(IDENT_ADDR + 0x180000E20UL)
+#define APECS_IOC_B2TRB  		(IDENT_ADDR + 0x180000E40UL)
+#define APECS_IOC_B3TRB  		(IDENT_ADDR + 0x180000E60UL)
+#define APECS_IOC_B4TRB  		(IDENT_ADDR + 0x180000E80UL)
+#define APECS_IOC_B5TRB  		(IDENT_ADDR + 0x180000EA0UL)
+#define APECS_IOC_B6TRB  		(IDENT_ADDR + 0x180000EC0UL)
+#define APECS_IOC_B7TRB  		(IDENT_ADDR + 0x180000EE0UL)
+#define APECS_IOC_B8TRB  		(IDENT_ADDR + 0x180000F00UL)
+
+
+/*
+ * Memory spaces:
+ */
+#define APECS_IACK_SC		        (IDENT_ADDR + 0x1b0000000UL)
+#define APECS_CONF		        (IDENT_ADDR + 0x1e0000000UL)
+#define APECS_IO			(IDENT_ADDR + 0x1c0000000UL)
+#define APECS_SPARSE_MEM		(IDENT_ADDR + 0x200000000UL)
+#define APECS_DENSE_MEM		        (IDENT_ADDR + 0x300000000UL)
+
+/*
+ * Bit definitions for I/O Controller status register 0:
+ */
+#define APECS_IOC_STAT0_CMD		0xf
+#define APECS_IOC_STAT0_ERR		(1<<4)
+#define APECS_IOC_STAT0_LOST		(1<<5)
+#define APECS_IOC_STAT0_THIT		(1<<6)
+#define APECS_IOC_STAT0_TREF		(1<<7)
+#define APECS_IOC_STAT0_CODE_SHIFT	8
+#define APECS_IOC_STAT0_CODE_MASK	0x7
+#define APECS_IOC_STAT0_P_NBR_SHIFT	13
+#define APECS_IOC_STAT0_P_NBR_MASK	0x7ffff
+
+#define HAE_ADDRESS	APECS_IOC_HAXR1
+
+#ifdef __KERNEL__
+
+/*
+ * Translate physical memory address as seen on (PCI) bus into
+ * a kernel virtual address and vv.
+ */
+extern inline unsigned long virt_to_bus(void * address)
+{
+	return virt_to_phys(address) + APECS_DMA_WIN_BASE;
+}
+
+extern inline void * bus_to_virt(unsigned long address)
+{
+	return phys_to_virt(address - APECS_DMA_WIN_BASE);
+}
+
+/*
+ * I/O functions:
+ *
+ * Unlike Jensen, the APECS machines have no concept of local
+ * I/O---everything goes over the PCI bus.
+ *
+ * There is plenty room for optimization here.  In particular,
+ * the Alpha's insb/insw/extb/extw should be useful in moving
+ * data to/from the right byte-lanes.
+ */
+
+#define vuip	volatile unsigned int *
+
+extern inline unsigned int __inb(unsigned long addr)
+{
+	long result = *(vuip) ((addr << 5) + APECS_IO + 0x00);
+	result >>= (addr & 3) * 8;
+	return 0xffUL & result;
+}
+
+extern inline void __outb(unsigned char b, unsigned long addr)
+{
+	unsigned int w;
+
+	asm ("insbl %2,%1,%0" : "r="(w) : "ri"(addr & 0x3), "r"(b));
+	*(vuip) ((addr << 5) + APECS_IO + 0x00) = w;
+	mb();
+}
+
+extern inline unsigned int __inw(unsigned long addr)
+{
+	long result = *(vuip) ((addr << 5) + APECS_IO + 0x08);
+	result >>= (addr & 3) * 8;
+	return 0xffffUL & result;
+}
+
+extern inline void __outw(unsigned short b, unsigned long addr)
+{
+	unsigned int w;
+
+	asm ("inswl %2,%1,%0" : "r="(w) : "ri"(addr & 0x3), "r"(b));
+	*(vuip) ((addr << 5) + APECS_IO + 0x08) = w;
+	mb();
+}
+
+extern inline unsigned int __inl(unsigned long addr)
+{
+	return *(vuip) ((addr << 5) + APECS_IO + 0x18);
+}
+
+extern inline void __outl(unsigned int b, unsigned long addr)
+{
+	*(vuip) ((addr << 5) + APECS_IO + 0x18) = b;
+	mb();
+}
+
+
+/*
+ * Memory functions.  64-bit and 32-bit accesses are done through
+ * dense memory space, everything else through sparse space.
+ */
+extern inline unsigned long __readb(unsigned long addr)
+{
+	unsigned long result, shift, msb;
+
+	shift = (addr & 0x3) * 8;
+	if (addr >= (1UL << 24)) {
+		msb = addr & 0xf8000000;
+		addr -= msb;
+		if (msb != hae.cache) {
+			set_hae(msb);
+		}
+	}
+	result = *(vuip) ((addr << 5) + APECS_SPARSE_MEM + 0x00);
+	result >>= shift;
+	return 0xffUL & result;
+}
+
+extern inline unsigned long __readw(unsigned long addr)
+{
+	unsigned long result, shift, msb;
+
+	shift = (addr & 0x3) * 8;
+	if (addr >= (1UL << 24)) {
+		msb = addr & 0xf8000000;
+		addr -= msb;
+		if (msb != hae.cache) {
+			set_hae(msb);
+		}
+	}
+	result = *(vuip) ((addr << 5) + APECS_SPARSE_MEM + 0x08);
+	result >>= shift;
+	return 0xffffUL & result;
+}
+
+extern inline unsigned long __readl(unsigned long addr)
+{
+	return *(vuip) (addr + APECS_DENSE_MEM);
+}
+
+extern inline void __writeb(unsigned char b, unsigned long addr)
+{
+	unsigned long msb;
+
+	if (addr >= (1UL << 24)) {
+		msb = addr & 0xf8000000;
+		addr -= msb;
+		if (msb != hae.cache) {
+			set_hae(msb);
+		}
+	}
+	*(vuip) ((addr << 5) + APECS_SPARSE_MEM + 0x00) = b * 0x01010101;
+}
+
+extern inline void __writew(unsigned short b, unsigned long addr)
+{
+	unsigned long msb;
+
+	if (addr >= (1UL << 24)) {
+		msb = addr & 0xf8000000;
+		addr -= msb;
+		if (msb != hae.cache) {
+			set_hae(msb);
+		}
+	}
+	*(vuip) ((addr << 5) + APECS_SPARSE_MEM + 0x08) = b * 0x00010001;
+}
+
+extern inline void __writel(unsigned int b, unsigned long addr)
+{
+	*(vuip) (addr + APECS_DENSE_MEM) = b;
+}
+
+/*
+ * Most of the above have so much overhead that it probably doesn't
+ * make sense to have them inlined (better icache behavior).
+ */
+extern unsigned int inb(unsigned long addr);
+extern unsigned int inw(unsigned long addr);
+extern unsigned int inl(unsigned long addr);
+
+extern void outb(unsigned char b, unsigned long addr);
+extern void outw(unsigned short b, unsigned long addr);
+extern void outl(unsigned int b, unsigned long addr);
+
+extern unsigned long readb(unsigned long addr);
+extern unsigned long readw(unsigned long addr);
+
+extern void writeb(unsigned char b, unsigned long addr);
+extern void writew(unsigned short b, unsigned long addr);
+
+#define inb(port) \
+(__builtin_constant_p((port))?__inb(port):(inb)(port))
+
+#define outb(x, port) \
+(__builtin_constant_p((port))?__outb((x),(port)):(outb)((x),(port)))
+
+#define inb_p inb
+#define outb_p outb
+
+extern inline unsigned long readl(unsigned long addr)
+{
+	return __readl(addr);
+}
+
+extern inline void writel(unsigned int b, unsigned long addr)
+{
+	__writel(b, addr);
+}
+
+#undef vuip
+
+extern unsigned long apecs_init (unsigned long mem_start,
+				 unsigned long mem_end);
+
+#endif /* __KERNEL__ */
+
+/*
+ * data structures for handling APECS machine checks
+ */
+
+struct el_common_logout_header {
+        u_int   elfl_size;              /* size in bytes of logout area. */
+        int     elfl_sbz1:31;           /* Should be zero. */
+        char    elfl_retry:1;           /* Retry flag. */
+        u_int   elfl_procoffset;        /* Processor-specific offset. */
+        u_int   elfl_sysoffset;         /* Offset of system-specific. */
+};
+
+struct el_apecs_sysdata_mcheck {
+    u_long      coma_gcr;                       
+    u_long      coma_edsr;                      
+    u_long      coma_ter;                       
+    u_long      coma_elar;                      
+    u_long      coma_ehar;                      
+    u_long      coma_ldlr;                      
+    u_long      coma_ldhr;                      
+    u_long      coma_base0;                     
+    u_long      coma_base1;                     
+    u_long      coma_base2;                     
+    u_long      coma_cnfg0;                     
+    u_long      coma_cnfg1;                     
+    u_long      coma_cnfg2;                     
+    u_long      epic_dcsr;                      
+    u_long      epic_pear;                      
+    u_long      epic_sear;                      
+    u_long      epic_tbr1;                      
+    u_long      epic_tbr2;                      
+    u_long      epic_pbr1;                      
+    u_long      epic_pbr2;                      
+    u_long      epic_pmr1;                      
+    u_long      epic_pmr2;                      
+    u_long      epic_harx1;                     
+    u_long      epic_harx2;                     
+    u_long      epic_pmlt;                      
+    u_long      epic_tag0;                      
+    u_long      epic_tag1;                      
+    u_long      epic_tag2;                      
+    u_long      epic_tag3;                      
+    u_long      epic_tag4;                      
+    u_long      epic_tag5;                      
+    u_long      epic_tag6;                      
+    u_long      epic_tag7;                      
+    u_long      epic_data0;                     
+    u_long      epic_data1;                     
+    u_long      epic_data2;                     
+    u_long      epic_data3;                     
+    u_long      epic_data4;                     
+    u_long      epic_data5;                     
+    u_long      epic_data6;                     
+    u_long      epic_data7;                     
+};
+
+#define RTC_PORT(x)	(0x70 + (x))
+#define RTC_ADDR(x)	(0x80 | (x))
+#define RTC_ALWAYS_BCD	0
+
+#endif /* __ALPHA_APECS__H__ */
diff -u --recursive --new-file v1.3.21/linux/include/asm-alpha/bitops.h linux/include/asm-alpha/bitops.h
--- v1.3.21/linux/include/asm-alpha/bitops.h	Fri Jun  2 13:51:16 1995
+++ linux/include/asm-alpha/bitops.h	Fri Sep  1 08:57:57 1995
@@ -20,18 +20,18 @@
 
 	__asm__ __volatile__(
 		"\n1:\t"
-		"ldq_l %0,%1\n\t"
+		"ldl_l %0,%1\n\t"
 		"and %0,%3,%2\n\t"
 		"bne %2,2f\n\t"
 		"xor %0,%3,%0\n\t"
-		"stq_c %0,%1\n\t"
+		"stl_c %0,%1\n\t"
 		"beq %0,1b\n"
 		"2:"
 		:"=&r" (temp),
-		 "=m" (((unsigned long *) addr)[nr >> 6]),
+		 "=m" (((int *) addr)[nr >> 5]),
 		 "=&r" (oldbit)
-		:"r" (1UL << (nr & 63)),
-		 "m" (((unsigned long *) addr)[nr >> 6]));
+		:"r" (1UL << (nr & 31)),
+		 "m" (((int *) addr)[nr >> 5]));
 	return oldbit != 0;
 }
 
@@ -42,18 +42,18 @@
 
 	__asm__ __volatile__(
 		"\n1:\t"
-		"ldq_l %0,%1\n\t"
+		"ldl_l %0,%1\n\t"
 		"and %0,%3,%2\n\t"
 		"beq %2,2f\n\t"
 		"xor %0,%3,%0\n\t"
-		"stq_c %0,%1\n\t"
+		"stl_c %0,%1\n\t"
 		"beq %0,1b\n"
 		"2:"
 		:"=&r" (temp),
-		 "=m" (((unsigned long *) addr)[nr >> 6]),
+		 "=m" (((int *) addr)[nr >> 5]),
 		 "=&r" (oldbit)
-		:"r" (1UL << (nr & 63)),
-		 "m" (((unsigned long *) addr)[nr >> 6]));
+		:"r" (1UL << (nr & 31)),
+		 "m" (((int *) addr)[nr >> 5]));
 	return oldbit != 0;
 }
 
@@ -64,22 +64,22 @@
 
 	__asm__ __volatile__(
 		"\n1:\t"
-		"ldq_l %0,%1\n\t"
+		"ldl_l %0,%1\n\t"
 		"and %0,%3,%2\n\t"
 		"xor %0,%3,%0\n\t"
-		"stq_c %0,%1\n\t"
+		"stl_c %0,%1\n\t"
 		"beq %0,1b\n"
 		:"=&r" (temp),
-		 "=m" (((unsigned long *) addr)[nr >> 6]),
+		 "=m" (((int *) addr)[nr >> 5]),
 		 "=&r" (oldbit)
-		:"r" (1UL << (nr & 63)),
-		 "m" (((unsigned long *) addr)[nr >> 6]));
+		:"r" (1UL << (nr & 31)),
+		 "m" (((int *) addr)[nr >> 5]));
 	return oldbit != 0;
 }
 
 extern __inline__ unsigned long test_bit(int nr, void * addr)
 {
-	return 1UL & (((unsigned long *) addr)[nr >> 6] >> (nr & 63));
+	return 1UL & (((int *) addr)[nr >> 5] >> (nr & 31));
 }
 
 /*
diff -u --recursive --new-file v1.3.21/linux/include/asm-alpha/hwrpb.h linux/include/asm-alpha/hwrpb.h
--- v1.3.21/linux/include/asm-alpha/hwrpb.h	Fri Jun  2 13:51:16 1995
+++ linux/include/asm-alpha/hwrpb.h	Tue Aug 29 10:15:52 1995
@@ -19,22 +19,24 @@
  * These values are architected.
  */
 
-#define ST_ADU                  1       /* Alpha ADU systype    */
-#define ST_DEC_4000             2       /* Cobra systype        */
-#define ST_DEC_7000             3       /* Ruby systype         */
-#define ST_DEC_3000_500         4       /* Flamingo systype     */
-#define ST_DEC_2000_300         6       /* Jensen systype       */
-#define ST_DEC_3000_300         7       /* Pelican systype      */
-#define ST_DEC_2100_A500        9       /* Sable systype        */
-#define ST_DEC_AXPVME_64       10       /* AXPvme system type   */
-#define ST_DEC_AXPPCI_33       11       /* NoName system type   */
-#define ST_DEC_TLASER          12       /* Turbolaser systype	*/
-#define ST_DEC_2100_A50        13       /* Avanti systype       */
-#define ST_DEC_MUSTANG         14       /* Mustang systype      */
-#define ST_DEC_ALCOR           15       /* Alcor systype	*/
-#define ST_DEC_1000            17       /* Mikasa systype       */
-#define ST_DEC_EB66            19       /* EB66 systype		*/
-#define ST_DEC_EB64P           20       /* EB64+ systype        */
+#define ST_ADU			  1	/* Alpha ADU systype	*/
+#define ST_DEC_4000		  2	/* Cobra systype	*/
+#define ST_DEC_7000		  3	/* Ruby systype		*/
+#define ST_DEC_3000_500		  4	/* Flamingo systype	*/
+#define ST_DEC_2000_300		  6	/* Jensen systype	*/
+#define ST_DEC_3000_300		  7	/* Pelican systype	*/
+#define ST_DEC_2100_A500	  9	/* Sable systype	*/
+#define ST_DEC_AXPVME_64	 10	/* AXPvme system type	*/
+#define ST_DEC_AXPPCI_33	 11	/* NoName system type	*/
+#define ST_DEC_TLASER		 12	/* Turbolaser systype	*/
+#define ST_DEC_2100_A50		 13	/* Avanti systype	*/
+#define ST_DEC_MUSTANG		 14	/* Mustang systype	*/
+#define ST_DEC_ALCOR		 15	/* Alcor (EV5) systype	*/
+#define ST_DEC_1000		 17	/* Mikasa systype	*/
+#define ST_DEC_EB66		 19	/* EB66 systype		*/
+#define ST_DEC_EB64P		 20	/* EB64+ systype	*/
+#define ST_DEC_EB66P		-19	/* EB66 systype		*/
+#define ST_DEC_EBPC64		-20	/* Cabriolet (AlphaPC64) systype */
 
 struct pcb_struct {
 	unsigned long ksp;
diff -u --recursive --new-file v1.3.21/linux/include/asm-alpha/io.h linux/include/asm-alpha/io.h
--- v1.3.21/linux/include/asm-alpha/io.h	Tue Jul 25 18:21:22 1995
+++ linux/include/asm-alpha/io.h	Tue Aug 29 10:15:52 1995
@@ -84,10 +84,12 @@
  * "interesting" (read: slightly braindead) Jensen type hardware
  * and the PCI version
  */
-#ifdef CONFIG_PCI
-#include <asm/lca.h>		/* get chip-specific definitions */
+#if defined(CONFIG_ALPHA_LCA)
+# include <asm/lca.h>		/* get chip-specific definitions */
+#elif defined(CONFIG_ALPHA_APECS)
+# include <asm/apecs.h>		/* get chip-specific definitions */
 #else
-#include <asm/jensen.h>
+# include <asm/jensen.h>
 #endif
 
 #ifdef __KERNEL__
diff -u --recursive --new-file v1.3.21/linux/include/asm-alpha/lca.h linux/include/asm-alpha/lca.h
--- v1.3.21/linux/include/asm-alpha/lca.h	Thu Jul 13 16:20:21 1995
+++ linux/include/asm-alpha/lca.h	Tue Aug 29 10:15:53 1995
@@ -1,5 +1,5 @@
-#ifndef __ALPHA_LCA__H
-#define __ALPHA_LCA__H
+#ifndef __ALPHA_LCA__H__
+#define __ALPHA_LCA__H__
 
 /*
  * Low Cost Alpha (LCA) definitions (these apply to 21066 and 21068,
@@ -247,6 +247,7 @@
 extern inline void __writeb(unsigned char b, unsigned long addr)
 {
 	unsigned long msb;
+	unsigned int w;
 
 	if (addr >= (1UL << 24)) {
 		msb = addr & 0xf8000000;
@@ -255,12 +256,14 @@
 			set_hae(msb);
 		}
 	}
-	*(vuip) ((addr << 5) + LCA_SPARSE_MEM + 0x00) = b * 0x01010101;
+	asm ("insbl %2,%1,%0" : "r="(w) : "ri"(addr & 0x3), "r"(b));
+	*(vuip) ((addr << 5) + LCA_SPARSE_MEM + 0x00) = w;
 }
 
 extern inline void __writew(unsigned short b, unsigned long addr)
 {
 	unsigned long msb;
+	unsigned int w;
 
 	if (addr >= (1UL << 24)) {
 		msb = addr & 0xf8000000;
@@ -269,7 +272,8 @@
 			set_hae(msb);
 		}
 	}
-	*(vuip) ((addr << 5) + LCA_SPARSE_MEM + 0x08) = b * 0x00010001;
+	asm ("inswl %2,%1,%0" : "r="(w) : "ri"(addr & 0x3), "r"(b));
+	*(vuip) ((addr << 5) + LCA_SPARSE_MEM + 0x08) = w;
 }
 
 extern inline void __writel(unsigned int b, unsigned long addr)
@@ -320,8 +324,8 @@
 
 #endif /* __KERNEL__ */
 
-#define RTC_PORT(x) (0x70 + (x))
-#define RTC_ADDR(x) (0x80 | (x))
-#define RTC_ALWAYS_BCD 0
+#define RTC_PORT(x)	(0x70 + (x))
+#define RTC_ADDR(x)	(0x80 | (x))
+#define RTC_ALWAYS_BCD	0
 
-#endif /* __ALPHA_LCA__H */
+#endif /* __ALPHA_LCA__H__ */
diff -u --recursive --new-file v1.3.21/linux/include/asm-alpha/page.h linux/include/asm-alpha/page.h
--- v1.3.21/linux/include/asm-alpha/page.h	Fri Jun  2 13:51:17 1995
+++ linux/include/asm-alpha/page.h	Tue Aug 29 09:42:56 1995
@@ -60,6 +60,12 @@
 	".long 51" \
 	: : :"$1", "$16", "$17", "$22","$23","$24","$25")
 
+/* Certain architectures need to do special things when pte's
+ * within a page table are directly modified.  Thus, the following
+ * hook is made available.
+ */
+#define set_pte(pteptr, pteval) ((*(pteptr)) = (pteval))
+
 /* to align the pointer to the (next) page boundary */
 #define PAGE_ALIGN(addr)		(((addr)+PAGE_SIZE-1)&PAGE_MASK)
 
diff -u --recursive --new-file v1.3.21/linux/include/asm-alpha/string.h linux/include/asm-alpha/string.h
--- v1.3.21/linux/include/asm-alpha/string.h	Tue Jul 25 18:21:23 1995
+++ linux/include/asm-alpha/string.h	Tue Aug 29 10:15:53 1995
@@ -1,5 +1,5 @@
-#ifndef __ALPHA_STRING_H
-#define __ALPHA_STRING_H
+#ifndef __ALPHA_STRING_H__
+#define __ALPHA_STRING_H__
 
 extern void * __constant_c_memset(void *, unsigned long, long);
 extern void * __memset(void *, char, size_t);
@@ -13,4 +13,4 @@
 
 #define __HAVE_ARCH_STRLEN
 
-#endif
+#endif /* __ALPHA_STRING_H__ */
diff -u --recursive --new-file v1.3.21/linux/include/asm-alpha/types.h linux/include/asm-alpha/types.h
--- v1.3.21/linux/include/asm-alpha/types.h	Fri Jun 16 22:02:55 1995
+++ linux/include/asm-alpha/types.h	Fri Sep  1 08:53:29 1995
@@ -100,7 +100,7 @@
 #endif /* __KERNEL__ */
 
 #undef __FD_SET
-static inline void __FD_SET(unsigned long fd, fd_set *fdsetp)
+static __inline__ void __FD_SET(unsigned long fd, fd_set *fdsetp)
 {
 	unsigned long _tmp = fd / __NFDBITS;
 	unsigned long _rem = fd % __NFDBITS;
@@ -108,7 +108,7 @@
 }
 
 #undef __FD_CLR
-static inline void __FD_CLR(unsigned long fd, fd_set *fdsetp)
+static __inline__ void __FD_CLR(unsigned long fd, fd_set *fdsetp)
 {
 	unsigned long _tmp = fd / __NFDBITS;
 	unsigned long _rem = fd % __NFDBITS;
@@ -116,7 +116,7 @@
 }
 
 #undef __FD_ISSET
-static inline int __FD_ISSET(unsigned long fd, fd_set *p)
+static __inline__ int __FD_ISSET(unsigned long fd, fd_set *p)
 { 
 	unsigned long _tmp = fd / __NFDBITS;
 	unsigned long _rem = fd % __NFDBITS;
@@ -124,27 +124,24 @@
 }
 
 /*
- * This will unroll the loop for the normal constant cases (4 or 8 longs,
- * for 256 and 512-bit fd_sets respectively)
+ * This will unroll the loop for the normal constant case (8 ints,
+ * for a 256-bit fd_set)
  */
 #undef __FD_ZERO
-static inline void __FD_ZERO(fd_set *p)
+static __inline__ void __FD_ZERO(fd_set *p)
 {
-	unsigned long *tmp = p->fds_bits;
+	unsigned int *tmp = p->fds_bits;
 	int i;
 
-	if (__builtin_constant_p(__FDSET_LONGS)) {
-		switch (__FDSET_LONGS) {
+	if (__builtin_constant_p(__FDSET_INTS)) {
+		switch (__FDSET_INTS) {
 			case 8:
 				tmp[0] = 0; tmp[1] = 0; tmp[2] = 0; tmp[3] = 0;
 				tmp[4] = 0; tmp[5] = 0; tmp[6] = 0; tmp[7] = 0;
 				return;
-			case 4:
-				tmp[0] = 0; tmp[1] = 0; tmp[2] = 0; tmp[3] = 0;
-				return;
 		}
 	}
-	i = __FDSET_LONGS;
+	i = __FDSET_INTS;
 	while (i) {
 		i--;
 		*tmp = 0;
diff -u --recursive --new-file v1.3.21/linux/include/asm-alpha/unistd.h linux/include/asm-alpha/unistd.h
--- v1.3.21/linux/include/asm-alpha/unistd.h	Tue Jul 25 18:21:23 1995
+++ linux/include/asm-alpha/unistd.h	Tue Aug 29 10:15:53 1995
@@ -35,6 +35,7 @@
 #define __NR_pipe		 42
 #define __NR_open		 45
 #define __NR_getxgid		 47
+#define __NR_acct		 51
 #define __NR_ioctl		 54
 #define __NR_symlink		 57
 #define __NR_readlink		 58
@@ -50,7 +51,7 @@
 #define __NR_vhangup		 76
 #define __NR_getgroups		 79
 #define __NR_setgroups		 80
-#define __NR_setpgrp		 82
+#define __NR_setpgrp		 82	/* BSD alias for setpgid */
 #define __NR_setitimer		 83
 #define __NR_getitimer		 86
 #define __NR_gethostname	 87
@@ -123,6 +124,7 @@
 #define __NR_delete_module	308
 #define __NR_get_kernel_syms	309
 #define __NR_syslog		310
+#define __NR_reboot		311
 
 
 #ifdef __LIBRARY__
diff -u --recursive --new-file v1.3.21/linux/include/asm-i386/io.h linux/include/asm-i386/io.h
--- v1.3.21/linux/include/asm-i386/io.h	Tue Aug 15 20:39:04 1995
+++ linux/include/asm-i386/io.h	Thu Aug 31 08:09:24 1995
@@ -94,7 +94,7 @@
 __OUT1(s##c_p,x) __OUT2(s,s1,"") : : "a" (value), "id" (port)); SLOW_DOWN_IO; }
 
 #define __IN1(s) \
-extern inline unsigned int __in##s(unsigned short port) { unsigned int _v;
+extern inline RETURN_TYPE __in##s(unsigned short port) { RETURN_TYPE _v;
 
 #define __IN2(s,s1,s2) \
 __asm__ __volatile__ ("in" #s " %" s2 "1,%" s1 "0"
@@ -115,8 +115,15 @@
 { __asm__ __volatile__ ("cld ; rep ; outs" #s \
 : "=S" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); }
 
-__IN(b,"b","0" (0))
-__IN(w,"w","0" (0))
+#define RETURN_TYPE unsigned char
+/* __IN(b,"b","0" (0)) */
+__IN(b,"")
+#undef RETURN_TYPE
+#define RETURN_TYPE unsigned short
+/* __IN(w,"w","0" (0)) */
+__IN(w,)
+#undef RETURN_TYPE
+#define RETURN_TYPE unsigned int
 __IN(l,"")
 
 __OUT(b,"b",char)
diff -u --recursive --new-file v1.3.21/linux/include/asm-i386/ioctl.h linux/include/asm-i386/ioctl.h
--- v1.3.21/linux/include/asm-i386/ioctl.h	Thu Jan  1 02:00:00 1970
+++ linux/include/asm-i386/ioctl.h	Tue Aug 29 10:15:53 1995
@@ -0,0 +1,88 @@
+/* $Id: ioctl.h,v 1.5 1993/07/19 21:53:50 root Exp root $
+ *
+ * linux/ioctl.h for Linux by H.H. Bergman.
+ */
+
+#ifndef _ASMI386_IOCTL_H
+#define _ASMI386_IOCTL_H
+
+#include <asm/page.h>		/* for PAGE_SIZE */
+
+/* ioctl command encoding: 32 bits total, command in lower 16 bits,
+ * size of the parameter structure in the lower 14 bits of the
+ * upper 16 bits.
+ * Encoding the size of the parameter structure in the ioctl request
+ * is useful for catching programs compiled with old versions
+ * and to avoid overwriting user space outside the user buffer area.
+ * The highest 2 bits are reserved for indicating the ``access mode''.
+ * NOTE: This limits the max parameter size to 16kB -1 !
+ */
+
+#define IOC_VOID	0x00000000	/* param in size field */
+#define IOC_IN		0x40000000	/* user --> kernel */
+#define IOC_OUT		0x80000000	/* kernel --> user */
+#define IOC_INOUT	(IOC_IN | IOC_OUT)	/* both */
+#define IOCSIZE_MASK	0x3fff0000	/* size (max 16k-1 bytes) */
+#define IOCSIZE_SHIFT	16		/* how to get the size */
+#define IOCSIZE_MAX	((PAGE_SIZE-1)&(IOCSIZE_MASK >> IOCSIZE_SHIFT))
+#define IOCCMD_MASK	0x0000ffff	/* command code */
+#define IOCCMD_SHIFT	0
+#define IOCPARM_MASK IOCCMD_MASK
+#define IOCPARM_SHIFT IOCCMD_SHIFT
+
+#define IOC_SIZE(cmd)	(((cmd) & IOCSIZE_MASK) >> IOCSIZE_SHIFT)
+#define IOCBASECMD(cmd)	((cmd) & ~IOCPARM_MASK)
+#define IOCGROUP(cmd)	(((cmd) >> 8) & 0xFF)
+
+/* _IO(magic, subcode); size field is zero and the 
+ * subcode determines the command.
+ */
+#define _IO(c,d)	(IOC_VOID | ((c)<<8) | (d)) /* param encoded */
+
+/* _IOXX(magic, subcode, arg_t); where arg_t is the type of the
+ * (last) argument field in the ioctl call, if present.
+ */
+#define _IOW(c,d,t)	(IOC_IN | ((sizeof(t)<<16) & IOCSIZE_MASK) | \
+				  ((c)<<8) | (d))
+#define _IOR(c,d,t)	(IOC_OUT | ((sizeof(t)<<16) & IOCSIZE_MASK) | \
+				   ((c)<<8) | (d))
+/* WR rather than RW to avoid conflict with stdio.h */
+#define _IOWR(c,d,t)	(IOC_INOUT | ((sizeof(t)<<16) & IOCSIZE_MASK) | \
+				     ((c)<<8) | (d))
+
+/*
+ * The following is for compatibility across the various Linux
+ * platforms.  The i386 ioctl numbering scheme doesn't really enforce
+ * a type field.  De facto, however, the top 8 bits of the lower 16
+ * bits are indeed used as a type field, so we might just as well make
+ * this explicit here.  Please be sure to use the decoding macros
+ * below from now on.
+ */
+#define _IOC_NRBITS	8
+#define _IOC_TYPEBITS	8
+#define _IOC_SIZEBITS	14
+#define _IOC_DIRBITS	2
+
+#define _IOC_NRMASK	((1 << _IOC_NRBITS)-1)
+#define _IOC_TYPEMASK	((1 << _IOC_TYPEBITS)-1)
+#define _IOC_SIZEMASK	((1 << _IOC_SIZEBITS)-1)
+#define _IOC_DIRMASK	((1 << _IOC_DIRBITS)-1)
+
+#define _IOC_NRSHIFT	0
+#define _IOC_TYPESHIFT	(_IOC_NRSHIFT+_IOC_NRBITS)
+#define _IOC_SIZESHIFT	(_IOC_TYPESHIFT+_IOC_TYPEBITS)
+#define _IOC_DIRSHIFT	(_IOC_SIZESHIFT+_IOC_SIZEBITS)
+
+/*
+ * Direction bits.
+ */
+#define _IOC_NONE	0U
+#define _IOC_READ	1U
+#define _IOC_WRITE	2U
+
+/* used to decode ioctl numbers.. */
+#define _IOC_DIR(nr)		(((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
+#define _IOC_NR(nr)		(((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
+#define _IOC_SIZE(nr)		(((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)
+
+#endif /* _ASMI386_IOCTL_H */
diff -u --recursive --new-file v1.3.21/linux/include/asm-i386/page.h linux/include/asm-i386/page.h
--- v1.3.21/linux/include/asm-i386/page.h	Tue Aug  8 12:31:41 1995
+++ linux/include/asm-i386/page.h	Tue Aug 29 09:42:56 1995
@@ -69,6 +69,12 @@
 #define invalidate_page(task,addr) \
 do { if ((task)->mm == current->mm) invalidate(); } while (0)
 
+/* Certain architectures need to do special things when pte's
+ * within a page table are directly modified.  Thus, the following
+ * hook is made available.
+ */
+#define set_pte(pteptr, pteval) ((*(pteptr)) = (pteval))
+
 /* to align the pointer to the (next) page boundary */
 #define PAGE_ALIGN(addr)	(((addr)+PAGE_SIZE-1)&PAGE_MASK)
 
diff -u --recursive --new-file v1.3.21/linux/include/asm-i386/types.h linux/include/asm-i386/types.h
--- v1.3.21/linux/include/asm-i386/types.h	Tue Jun 27 14:11:44 1995
+++ linux/include/asm-i386/types.h	Fri Sep  1 08:51:15 1995
@@ -97,7 +97,7 @@
 #define __FD_ZERO(fdsetp) \
 		__asm__ __volatile__("cld ; rep ; stosl" \
 			:"=m" (*(fd_set *) (fdsetp)) \
-			:"a" (0), "c" (__FDSET_LONGS), \
+			:"a" (0), "c" (__FDSET_INTS), \
 			"D" ((fd_set *) (fdsetp)) :"cx","di")
 
 #endif
diff -u --recursive --new-file v1.3.21/linux/include/asm-mips/page.h linux/include/asm-mips/page.h
--- v1.3.21/linux/include/asm-mips/page.h	Tue Jan 31 09:36:21 1995
+++ linux/include/asm-mips/page.h	Tue Aug 29 09:42:56 1995
@@ -10,6 +10,12 @@
 #define invalidate()	tlbflush();
 extern asmlinkage void tlbflush(void);
 
+/* Certain architectures need to do special things when pte's
+ * within a page table are directly modified.  Thus, the following
+ * hook is made available.
+ */
+#define set_pte(pteptr, pteval) ((*(pteptr)) = (pteval))
+
 typedef unsigned short mem_map_t;
 
 #ifdef CONFIG_STRICT_MM_TYPECHECKS
diff -u --recursive --new-file v1.3.21/linux/include/asm-sparc/page.h linux/include/asm-sparc/page.h
--- v1.3.21/linux/include/asm-sparc/page.h	Tue Jun 27 14:11:45 1995
+++ linux/include/asm-sparc/page.h	Tue Aug 29 09:42:56 1995
@@ -86,6 +86,7 @@
  */
 
 extern void (*invalidate)(void);
+extern void (*set_pte)(pte_t *ptep, pte_t entry);
 
 /* to align the pointer to the (next) page boundary */
 #define PAGE_ALIGN(addr)  (((addr)+PAGE_SIZE-1)&PAGE_MASK)
diff -u --recursive --new-file v1.3.21/linux/include/linux/aztcd.h linux/include/linux/aztcd.h
--- v1.3.21/linux/include/linux/aztcd.h	Sun Aug 13 14:45:34 1995
+++ linux/include/linux/aztcd.h	Fri Sep  1 08:45:30 1995
@@ -1,4 +1,4 @@
-/* $Id: aztcd.h,v 1.60 1995/08/09 12:38:12 root Exp root $
+/* $Id: aztcd.h,v 1.70 1995/08/19 16:16:45 root Exp root $
  *
  * Definitions for a AztechCD268 CD-ROM interface
  *	Copyright (C) 1994, 1995  Werner Zimmermann
@@ -43,17 +43,20 @@
   don't want the auto-eject feature*/
 #define AZT_AUTO_EJECT          0
 
-/*Set this to 1, if you want multisession support. Be warned, this function has
-not been tested !!!*/
-#define AZT_MULTISESSION        1
-
 /*Set this to 1, if you want to use incompatible ioctls for reading in raw and
   cooked mode */
 #define AZT_PRIVATE_IOCTLS      1
 
-/*---------------------------------------------------------------------------*/
-/*------------nothing to be configured below this line-----------------------*/
+/*Set this to 1, if you want multisession support by the ISO fs. Even if you set 
+  this value to '0' you can use multisession CDs. In that case the drive's firm-
+  ware will do the appropriate redirection automatically. The CD will then look
+  like a single session CD (but nevertheless all data may be read). Please read 
+  chapter '5.1 Multisession support' in README.aztcd for details. Normally it's 
+  uncritical to leave this setting untouched */
+#define AZT_MULTISESSION        1
 
+/*---------------------------------------------------------------------------*/
+/*-----nothing to be configured for normal applications below this line------*/
 
 /* Increase this if you get lots of timeouts; if you get kernel panic, replace
    STEN_LOW_WAIT by STEN_LOW in the source code */
@@ -99,6 +102,7 @@
 #define ACMD_SOFT_RESET		0x10		/* reset drive */
 #define ACMD_PLAY_READ		0x20		/* read data track in cooked mode */
 #define ACMD_PLAY_READ_RAW      0x21		/* reading in raw mode*/
+#define ACMD_SEEK               0x30            /* seek msf address*/
 #define ACMD_SEEK_TO_LEADIN     0x31		/* seek to leadin track*/
 #define ACMD_GET_ERROR		0x40		/* get error code */
 #define ACMD_GET_STATUS		0x41		/* get status */
@@ -129,11 +133,13 @@
 
 struct azt_DiskInfo {
 	unsigned char	first;
+        unsigned char   next;
 	unsigned char	last;
 	struct msf	diskLength;
 	struct msf	firstTrack;
         unsigned char   multi;
-        struct msf      lastTrack;
+        struct msf      nextSession;
+        struct msf      lastSession;
         unsigned char   xa;
         unsigned char   audio;
 };
diff -u --recursive --new-file v1.3.21/linux/include/linux/binfmts.h linux/include/linux/binfmts.h
--- v1.3.21/linux/include/linux/binfmts.h	Fri Jul  7 13:42:58 1995
+++ linux/include/linux/binfmts.h	Tue Aug 29 10:15:53 1995
@@ -6,7 +6,7 @@
 /*
  * MAX_ARG_PAGES defines the number of pages allocated for arguments
  * and envelope for the new program. 32 should suffice, this gives
- * a maximum env+arg of 128kB !
+ * a maximum env+arg of 128kB w/4KB pages!
  */
 #define MAX_ARG_PAGES 32
 
diff -u --recursive --new-file v1.3.21/linux/include/linux/cdrom.h linux/include/linux/cdrom.h
--- v1.3.21/linux/include/linux/cdrom.h	Sun Aug 13 14:45:34 1995
+++ linux/include/linux/cdrom.h	Fri Sep  1 08:45:30 1995
@@ -27,7 +27,7 @@
 #define CD_BLOCK_OFFSET           150  /* offset of first logical frame   */
 #define CD_XA_HEAD                 12  /* header size of XA frame         */
 #define CD_XA_TAIL                280  /* tail size of XA frame           */
-#define CD_XA_SYNC_HEAD (CD_XA_HEAD+12)/* sync bytes + header of XA frame */
+#define CD_XA_SYNC_HEAD CD_XA_HEAD+12  /* sync bytes + header of XA frame */
 /*
  *
  * For IOCTL calls, we will commandeer byte 0x53, or 'S'.
@@ -424,7 +424,11 @@
 #define	CDROMVOLREAD		0x5313 /* let the drive tell its volume setting */
 					/* (struct cdrom_volctrl) */
 
+/* 
+ *these ioctls are used in aztcd.c
+ */
 #define CDROMREADRAW            0x5314  /*read data in raw mode*/
 #define CDROMREADCOOKED         0x5315  /*read data in cooked mode*/
+#define CDROMSEEK               0x5316  /*seek msf address*/
 
 #endif  _LINUX_CDROM_H
diff -u --recursive --new-file v1.3.21/linux/include/linux/cdu31a.h linux/include/linux/cdu31a.h
--- v1.3.21/linux/include/linux/cdu31a.h	Tue Nov  1 19:36:56 1994
+++ linux/include/linux/cdu31a.h	Tue Aug 29 10:15:53 1995
@@ -66,16 +66,16 @@
 
 #define LOG_START_OFFSET        150     /* Offset of first logical sector */
 
-#define SONY_DETECT_TIMEOUT     80      /* Maximum amount of time
+#define SONY_DETECT_TIMEOUT	(8*HZ/10) /* Maximum amount of time
                                            that drive detection code
                                            will wait for response
                                            from drive (in 1/100th's
                                            of seconds). */
  
-#define SONY_JIFFIES_TIMEOUT    1000    /* Maximum number of times the
+#define SONY_JIFFIES_TIMEOUT    1000	/* Maximum number of times the
                                            drive will wait/try for an
                                            operation */
-#define SONY_RESET_TIMEOUT      100     /* Maximum number of times the
+#define SONY_RESET_TIMEOUT      100	/* Maximum number of times the
                                            drive will wait/try a reset
                                            operation */
 #define SONY_READY_RETRIES      20000   /* How many times to retry a
diff -u --recursive --new-file v1.3.21/linux/include/linux/elf.h linux/include/linux/elf.h
--- v1.3.21/linux/include/linux/elf.h	Mon Jun  5 14:37:40 1995
+++ linux/include/linux/elf.h	Fri Sep  1 16:21:05 1995
@@ -79,6 +79,23 @@
 #define ELF32_ST_BIND(x) ((x) >> 4)
 #define ELF32_ST_TYPE(x) (((unsigned int) x) & 0xf)
 
+/* Symbolic values for the entries in the auxiliary table
+   put on the initial stack */
+#define AT_NULL   0	/* end of vector */
+#define AT_IGNORE 1	/* entry should be ignored */
+#define AT_EXECFD 2	/* file descriptor of program */
+#define AT_PHDR   3	/* program headers for program */
+#define AT_PHENT  4	/* size of program header entry */
+#define AT_PHNUM  5	/* number of program headers */
+#define AT_PAGESZ 6	/* system page size */
+#define AT_BASE   7	/* base address of interpreter */
+#define AT_FLAGS  8	/* flags */
+#define AT_ENTRY  9	/* entry point of program */
+#define AT_NOTELF 10	/* program is not ELF */
+#define AT_UID    11	/* real uid */
+#define AT_EUID   12	/* effective uid */
+#define AT_GID    13	/* real gid */
+#define AT_EGID   14	/* effective gid */
 
 
 typedef struct dynamic{
diff -u --recursive --new-file v1.3.21/linux/include/linux/interrupt.h linux/include/linux/interrupt.h
--- v1.3.21/linux/include/linux/interrupt.h	Fri Jul  7 08:54:54 1995
+++ linux/include/linux/interrupt.h	Tue Aug 29 10:15:53 1995
@@ -85,7 +85,7 @@
  * or zero if none occurred, or a negative irq number
  * if more than one irq occurred.
  */
-extern unsigned int probe_irq_on(void);	/* returns 0 on failure */
-extern int probe_irq_off(unsigned int); /* returns 0 or negative on failure */
+extern unsigned long probe_irq_on(void);	/* returns 0 on failure */
+extern int probe_irq_off(unsigned long);	/* returns 0 or negative on failure */
 
 #endif
diff -u --recursive --new-file v1.3.21/linux/include/linux/ioctl.h linux/include/linux/ioctl.h
--- v1.3.21/linux/include/linux/ioctl.h	Wed Aug  9 14:55:42 1995
+++ linux/include/linux/ioctl.h	Tue Aug 29 10:15:53 1995
@@ -1,58 +1,7 @@
-/* $Id: ioctl.h,v 1.5 1993/07/19 21:53:50 root Exp root $
- *
- * linux/ioctl.h for Linux by H.H. Bergman.
- */
-
 #ifndef _LINUX_IOCTL_H
 #define _LINUX_IOCTL_H
 
-#include <asm/page.h>		/* for PAGE_SIZE */
-
-/* ioctl command encoding: 32 bits total, command in lower 16 bits,
- * size of the parameter structure in the lower 14 bits of the
- * upper 16 bits.
- * Encoding the size of the parameter structure in the ioctl request
- * is useful for catching programs compiled with old versions
- * and to avoid overwriting user space outside the user buffer area.
- * The highest 2 bits are reserved for indicating the ``access mode''.
- * NOTE: This limits the max parameter size to 16kB -1 !
- */
-
-#define IOC_VOID	0x00000000	/* param in size field */
-#define IOC_IN		0x40000000	/* user --> kernel */
-#define IOC_OUT		0x80000000	/* kernel --> user */
-#define IOC_INOUT	(IOC_IN | IOC_OUT)	/* both */
-#define IOCSIZE_MASK	0x3fff0000	/* size (max 16k-1 bytes) */
-#define IOCSIZE_SHIFT	16		/* how to get the size */
-#define IOCSIZE_MAX	((PAGE_SIZE-1)&(IOCSIZE_MASK >> IOCSIZE_SHIFT))
-#define IOCCMD_MASK	0x0000ffff	/* command code */
-#define IOCCMD_SHIFT	0
-#define IOCPARM_MASK IOCCMD_MASK
-#define IOCPARM_SHIFT IOCCMD_SHIFT
-
-#define IOC_SIZE(cmd)	(((cmd) & IOCSIZE_MASK) >> IOCSIZE_SHIFT)
-#define IOCBASECMD(cmd)	((cmd) & ~IOCPARM_MASK)
-#define IOCGROUP(cmd)	(((cmd) >> 8) & 0xFF)
-
-#ifndef _IO
-/* _IO(magic, subcode); size field is zero and the 
- * subcode determines the command.
- */
-#define _IO(c,d)	(IOC_VOID | ((c)<<8) | (d)) /* param encoded */
-#endif
-
-#ifndef _IOW
-/* _IOXX(magic, subcode, arg_t); where arg_t is the type of the
- * (last) argument field in the ioctl call, if present.
- */
-#define _IOW(c,d,t)	(IOC_IN | ((sizeof(t)<<16) & IOCSIZE_MASK) | \
-				  ((c)<<8) | (d))
-#define _IOR(c,d,t)	(IOC_OUT | ((sizeof(t)<<16) & IOCSIZE_MASK) | \
-				   ((c)<<8) | (d))
-/* WR rather than RW to avoid conflict with stdio.h */
-#define _IOWR(c,d,t)	(IOC_INOUT | ((sizeof(t)<<16) & IOCSIZE_MASK) | \
-				     ((c)<<8) | (d))
-#endif /* !_IOW */
+#include <asm/ioctl.h>
 
 #endif /* _LINUX_IOCTL_H */
 
diff -u --recursive --new-file v1.3.21/linux/include/linux/major.h linux/include/linux/major.h
--- v1.3.21/linux/include/linux/major.h	Tue Aug 15 20:39:05 1995
+++ linux/include/linux/major.h	Tue Aug 29 07:12:05 1995
@@ -39,7 +39,7 @@
  * 19 - cyclades /dev/ttyC*
  * 20 - cyclades /dev/cub*     mitsumi (mcdx) cdrom
  * 21 - scsi generic
- * 22 -                        ide1
+ * 22 - Z8530 driver           ide1
  * 23 -                        mitsumi cdrom
  * 24 -	                       sony535 cdrom
  * 25 -                        matsushita cdrom       minors 0..3
@@ -79,6 +79,7 @@
 #define CYCLADESAUX_MAJOR 20
 #define MITSUMI_X_CDROM_MAJOR 20
 #define SCSI_GENERIC_MAJOR 21
+#define Z8530_MAJOR 22
 #define IDE1_MAJOR	22
 #define MITSUMI_CDROM_MAJOR 23
 #define CDU535_CDROM_MAJOR 24
diff -u --recursive --new-file v1.3.21/linux/include/linux/malloc.h linux/include/linux/malloc.h
--- v1.3.21/linux/include/linux/malloc.h	Mon Jan 23 23:04:10 1995
+++ linux/include/linux/malloc.h	Fri Sep  1 14:39:39 1995
@@ -1,31 +1,11 @@
 #ifndef _LINUX_MALLOC_H
 #define _LINUX_MALLOC_H
 
-#include <linux/config.h>
 #include <linux/mm.h>
 
-#ifdef CONFIG_DEBUG_MALLOC
-#define kmalloc(a,b) deb_kmalloc(__FILE__,__LINE__,a,b)
-#define kfree_s(a,b) deb_kfree_s(__FILE__,__LINE__,a,b)
-
-void *deb_kmalloc(const char *deb_file, unsigned short deb_line,unsigned int size, int priority);
-void deb_kfree_s (const char *deb_file, unsigned short deb_line,void * obj, int size);
-void deb_kcheck_s(const char *deb_file, unsigned short deb_line,void * obj, int size);
-
-#define kfree(a) deb_kfree_s(__FILE__,__LINE__, a,0)
-#define kcheck(a) deb_kcheck_s(__FILE__,__LINE__, a,0)
-#define kcheck_s(a,b) deb_kcheck_s(__FILE__,__LINE__, a,b)
-
-#else /* !debug */
-
 void * kmalloc(unsigned int size, int priority);
-void kfree_s(void * obj, int size);
-
-#define kcheck_s(a,b) 0
-
-#define kfree(x) kfree_s((x), 0)
-#define kcheck(x) kcheck_s((x), 0)
+void kfree(void * obj);
 
-#endif
+#define kfree_s(a,b) kfree(a)
 
 #endif /* _LINUX_MALLOC_H */
diff -u --recursive --new-file v1.3.21/linux/include/linux/mcd.h linux/include/linux/mcd.h
--- v1.3.21/linux/include/linux/mcd.h	Thu Jul  7 21:26:55 1994
+++ linux/include/linux/mcd.h	Tue Aug 29 07:01:32 1995
@@ -25,7 +25,11 @@
 #define MCD_BASE_ADDR	        0x300
 
 /* *** change this to set the interrupt number */
-#define MCD_INTR_NR		10
+#define MCD_INTR_NR     11
+
+/* *** make the following line uncommented, if you're sure,
+ * *** all configuration is done */
+/* #define I_WAS_HERE */
 
 /* Increase this if you get lots of timeouts */
 #define MCD_STATUS_DELAY	200
@@ -105,3 +109,7 @@
 	struct msf	trackTime;
 	struct msf	diskTime;
 };
+
+#ifndef I_WAS_HERE
+#error Please edit this file first.
+#endif
diff -u --recursive --new-file v1.3.21/linux/include/linux/mcdx.h linux/include/linux/mcdx.h
--- v1.3.21/linux/include/linux/mcdx.h	Tue Jul 11 10:02:59 1995
+++ linux/include/linux/mcdx.h	Tue Aug 29 10:15:53 1995
@@ -1,7 +1,7 @@
 /*
  * Definitions for the Mitsumi CDROM interface
  * Copyright (C) 1995 Heiko Schlittermann
- * VERSION: @VERSION@
+ * VERSION: 1.0a
  * 
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -54,7 +54,7 @@
 #if MCDX_AUTOPROBE == 0
 	#define MCDX_NDRIVES 1
 	#define MCDX_DRIVEMAP {		\
-			{0x300, 10},	\
+			{0x300, 11},	\
 			{0x304, 05},  	\
 			{0x000, 00},  	\
 			{0x000, 00},  	\
@@ -64,27 +64,40 @@
 	#error Autoprobing is not implemented yet.
 #endif
 
+#ifndef MCDX_QUIET
+#define MCDX_QUIET   1
+#endif
+
+#ifndef MCDX_DEBUG
+#define MCDX_DEBUG   0
+#endif
+
+/* *** make the following line uncommented, if you're sure,
+ * *** all configuration is done */
+/* #define I_WAS_HERE */
+
 /*	The name of the device */
-#define MCD "mcdx"	
+#define MCDX "mcdx"	
 
-#ifdef NOWARN
-#define WARN(x)
+#if MCDX_QUIET == 1
+#define INFO(x)
 #else
-#define WARN(x) warn x
+#define INFO(x) warn x
 #endif
 
-#if MCDX_DEBUG
+#define WARN(x) warn x
+
+#if MCDX_DEBUG == 1
 #define TRACE(x) trace x
 #define INIT 		0
 #define MALLOC 		0
 #define IOCTL 		0
 #define OPENCLOSE 	0
-#define HW		0
+#define HW		    0
 #define TALK		0
 #define IRQ 		0
 #define TRANSFER 	0
 #define REQUEST	 	0
-#define MCDX_DEBUG_TALK 0
 #else
 #define TRACE(x)
 #endif
@@ -145,7 +158,7 @@
 /**	no drive specific */
 #define MCDX_CDBLK	2048	/* 2048 cooked data each blk */
 
-#define MCDX_DATA_TIMEOUT	10	/* jiffies */
+#define MCDX_DATA_TIMEOUT	(HZ/10)	/* 0.1 second */
 
 /*
  * Access to the msf array
@@ -159,3 +172,7 @@
  */
 #define MCDX_E		1			/* unspec error */
 #define MCDX_EOM	2			/* end of media */
+
+#ifndef I_WAS_HERE
+#error Please edit this file first.
+#endif
diff -u --recursive --new-file v1.3.21/linux/include/linux/mroute.h linux/include/linux/mroute.h
--- v1.3.21/linux/include/linux/mroute.h	Thu Jan  1 02:00:00 1970
+++ linux/include/linux/mroute.h	Fri Sep  1 14:50:46 1995
@@ -0,0 +1,134 @@
+#ifndef __LINUX_MROUTE_H
+#define __LINUX_MROUTE_H
+/*
+ *	Based on the MROUTING 3.5 defines primarily to keep
+ *	source compatibility with BSD.
+ *
+ *	See the mrouted code for the original history.
+ *
+ */
+
+#define MRT_BASE	200
+#define MRT_INIT	(MRT_BASE)	/* Activate the kernel mroute code 	*/
+#define MRT_DONE	(MRT_BASE+1)	/* Shutdown the kernel mroute		*/
+#define MRT_ADD_VIF	(MRT_BASE+2)	/* Add a virtual interface		*/
+#define MRT_DEL_VIF	(MRT_BASE+3)	/* Delete a virtual interface		*/
+#define MRT_ADD_MFC	(MRT_BASE+4)	/* Add a multicast forwarding entry	*/
+#define MRT_DEL_MFC	(MRT_BASE+5)	/* Delete a multicast forwarding entry	*/
+#define MRT_VERSION	(MRT_BASE+6)	/* Get the kernel multicast version	*/
+#define MRT_ASSERT	(MRT_BASE+7)	/* Activate PIM assert mode		*/
+
+#define SIOCGETVIFCNT	SIOCPROTOPRIVATE	/* IP protocol privates */
+#define SIOCGETSGCNT	(SIOCPROTOPRIVATE+1)
+
+#define MAXVIFS		32	
+typedef unsigned long vifbitmap_t;	/* User mode code depends on this lot */
+typedef unsigned short vifi_t;
+#define ALL_VIFS	((vifi_t)(-1))
+
+/*
+ *	Same idea as select
+ */
+ 
+#define VIFM_SET(n,m)	((m)|=(1<<(n)))
+#define VIFM_CLR(n,m)	((m)&=~(1<<(n)))
+#define VIFM_ISSET(n,m)	((m)&(1<<(n)))
+#define VIFM_CLRALL(m)	((m)=0)
+#define VIFM_COPY(mfrom,mto)	((mto)=(mfrom))
+#define VIFM_SAME(m1,m2)	((m1)==(m2))
+
+/*
+ *	Passed by mrouted for an MRT_ADD_VIF - again we use the
+ *	mrouted 3.6 structures for compatibility
+ */
+ 
+struct vifctl {
+	vifi_t	vifc_vifi;		/* Index of VIF */
+	unsigned char vifc_flags;	/* VIFF_ flags */
+	unsigned char vifc_threshold;	/* ttl limit */
+	unsigned int vifc_rate_limit;	/* Rate limiter values (NI) */
+	struct in_addr vifc_lcl_addr;	/* Our address */
+	struct in_addr vifc_rmt_addr;	/* IPIP tunnel addr */
+};
+
+#define VIFF_TUNNEL	0x1		/* IPIP tunnel */
+#define VIFF_SRCRT	0x02		/* NI */
+
+/*
+ *	Cache manipulation structures for mrouted
+ */
+ 
+struct mfcctl
+{
+	struct in_addr mfcc_origin;		/* Origin of mcast	*/
+	struct in_addr mfcc_mcastgrp;		/* Group in question	*/
+	vifi_t	mfcc_parent;			/* Where it arrived	*/
+	unsigned char mfcc_ttls[MAXVIFS];	/* Where it is going	*/
+};
+
+/* 
+ *	Group count retrieval for mrouted
+ */
+ 
+struct sioc_sg_req
+{
+	struct in_addr src;
+	struct in_addr grp;
+	unsigned long pktcnt;
+	unsigned long bytecnt;
+	unsigned long wrong_if;
+};
+
+/*
+ *	To get vif packet counts
+ */
+
+struct sioc_vif_req
+{
+	vifi_t	vifi;		/* Which iface */
+	unsigned long icount;	/* In packets */
+	unsigned long ocount;	/* Out packets */
+	unsigned long ibytes;	/* In bytes */
+	unsigned long obytes;	/* Out bytes */
+};
+
+/*
+ *	This is the format the mroute daemon expects to see IGMP control
+ *	data. Magically happens to be like an IP packet as per the original
+ */
+ 
+struct igmpmsg
+{
+	unsigned long unused1,unused2;
+	unsigned char im_msgtype;		/* What is this */
+	unsigned char im_mbz;			/* Must be zero */
+	unsigned char im_vif;			/* Interface (this ought to be a vifi_t!) */
+	unsigned char unused3;
+	struct in_addr im_src,im_dst;
+};
+
+/*
+ *	Thats all usermode folks
+ */
+
+#ifdef __KERNEL__
+extern struct sock *mroute_socket;
+extern int ip_mroute_setsockopt(struct sock *, int, char *, int);
+extern int ip_mroute_getsockopt(struct sock *, int, char *, int *);
+extern int ipmr_ioctl(struct sock *sk, int cmd, unsigned long arg);
+extern void mroute_close(struct sock *sk);
+
+struct vif_device
+{
+	struct device *dev;		/* Device we are using */
+	struct route *rt_cache;		/* Tunnel route cache */
+	unsigned long bytes_in,bytes_out;
+	unsigned long pkt_in,pkt_out;	/* Statistics */
+	unsigned long rate_limit;	/* Traffic shaping (NI) */
+	unsigned char threshold;	/* TTL threshold */
+	unsigned short flags;		/* Control flags */
+	unsigned long local,remote;	/* Addresses (remote for tunnels) */
+};
+
+#endif
+#endif
diff -u --recursive --new-file v1.3.21/linux/include/linux/mtio.h linux/include/linux/mtio.h
--- v1.3.21/linux/include/linux/mtio.h	Tue Jun 27 14:11:46 1995
+++ linux/include/linux/mtio.h	Thu Aug 31 07:44:09 1995
@@ -1,5 +1,4 @@
-/* $Id: /usr/src/linux-1.1.64/include/linux/mtio.h at Tue Jan 10 21:02:51 1995 by root@kai.home$
- *
+/* 
  * linux/mtio.h header file for Linux. Written by H. Bergman
  */
 
@@ -43,7 +42,6 @@
 #define MTRAS2	15	/* run self test 2 (destructive) */
 #define MTRAS3  16	/* reserved for self test 3 */
 
-
 #define MTSETBLK 20	/* set block length (SCSI) */
 #define MTSETDENSITY 21	/* set tape density (SCSI) */
 #define MTSEEK	22	/* seek to block (Tandberg, etc.) */
@@ -54,6 +52,12 @@
 #define MTBSS	26	/* space backward over setmarks */
 #define MTWSM	27	/* write setmarks */
 
+#define MTLOCK  28	/* lock the drive door */
+#define MTUNLOCK 29	/* unlock the drive door */
+#define MTLOAD  30	/* execute the SCSI load command */
+#define MTUNLOAD 31	/* execute the SCSI unload command */
+
+
 /* structure for MTIOCGET - mag tape get status command */
 
 struct	mtget {
@@ -195,5 +199,6 @@
 #define MT_ST_DEBUGGING		0x8
 #define MT_ST_TWO_FM		0x10
 #define MT_ST_FAST_MTEOM	0x20
+#define MT_ST_AUTO_LOCK		0x40
 
 #endif /* _LINUX_MTIO_H */
diff -u --recursive --new-file v1.3.21/linux/include/linux/netdevice.h linux/include/linux/netdevice.h
--- v1.3.21/linux/include/linux/netdevice.h	Wed Aug  9 14:55:42 1995
+++ linux/include/linux/netdevice.h	Fri Sep  1 14:59:40 1995
@@ -116,6 +116,7 @@
 
   /* Interface address info. */
   unsigned char		  broadcast[MAX_ADDR_LEN];	/* hw bcast add	*/
+  unsigned char		  pad;				/* make dev_addr aligned to 8 bytes */
   unsigned char		  dev_addr[MAX_ADDR_LEN];	/* hw address	*/
   unsigned char		  addr_len;	/* hardware address length	*/
   unsigned long		  pa_addr;	/* protocol address		*/
@@ -193,6 +194,7 @@
 extern struct device	*ip_dev_check(unsigned long daddr);
 extern unsigned long	ip_my_addr(void);
 extern unsigned long	ip_get_mask(unsigned long addr);
+extern struct device 	*ip_dev_find(unsigned long addr);
 
 extern void		dev_add_pack(struct packet_type *pt);
 extern void		dev_remove_pack(struct packet_type *pt);
diff -u --recursive --new-file v1.3.21/linux/include/linux/nfs_fs.h linux/include/linux/nfs_fs.h
--- v1.3.21/linux/include/linux/nfs_fs.h	Wed Aug  2 13:21:16 1995
+++ linux/include/linux/nfs_fs.h	Fri Sep  1 09:17:54 1995
@@ -30,7 +30,7 @@
  * in tenths of a second.
  */
 
-#define NFS_MAX_RPC_TIMEOUT		600
+#define NFS_MAX_RPC_TIMEOUT		(6*HZ)
 
 /*
  * Size of the lookup cache in units of number of entries cached.
diff -u --recursive --new-file v1.3.21/linux/include/linux/pci.h linux/include/linux/pci.h
--- v1.3.21/linux/include/linux/pci.h	Wed Aug  9 14:55:42 1995
+++ linux/include/linux/pci.h	Thu Aug 31 08:09:24 1995
@@ -256,6 +256,7 @@
 
 #define PCI_VENDOR_ID_MATROX		0x102B
 #define PCI_DEVICE_ID_MATROX_MGA_2	0x0518
+#define PCI_DEVICE_ID_MATROX_MIL	0x0519
 #define PCI_DEVICE_ID_MATROX_MGA_IMP	0x0d10
 
 #define PCI_VENDOR_ID_INTEL		0x8086
@@ -269,14 +270,26 @@
 #define PCI_DEVICE_ID_INTEL_82438	0x1230
 #define PCI_DEVICE_ID_INTEL_7116	0x1223
 #define PCI_DEVICE_ID_INTEL_82865	0x1227
+#define PCI_DEVICE_ID_INTEL_P6		0x84c4
 
-#define PCI_VENDOR_ID_SMC		0x1042
+#if 0
+
+#define PCI_VENDOR_ID_SMC		0x1042	/* Is this really correct?? */
 #define PCI_DEVICE_ID_SMC_37C665	0x1000
 #define PCI_DEVICE_ID_SMC_37C922	0x1001
 
+#else
+
+#define PCI_VENDOR_ID_PCTECH		0x1042	/* Known to be correct */
+#define PCI_DEVICE_ID_PCTECH_RZ1000	0x1000
+
+#endif
+
 #define PCI_VENDOR_ID_ATI		0x1002
-#define PCI_DEVICE_ID_ATI_M32		0x4158
-#define PCI_DEVICE_ID_ATI_M64		0x4758
+#define PCI_DEVICE_ID_ATI_68800		0x4158
+#define PCI_DEVICE_ID_ATI_215CT222	0x4354
+#define PCI_DEVICE_ID_ATI_210888CX	0x4358
+#define PCI_DEVICE_ID_ATI_210888GX	0x4758
 
 #define PCI_VENDOR_ID_WEITEK		0x100e
 #define PCI_DEVICE_ID_WEITEK_P9000	0x9001
@@ -368,6 +381,7 @@
 
 #define PCI_VENDOR_ID_HER		0xedd8
 #define PCI_DEVICE_ID_HER_STING		0xa091
+#define PCI_DEVICE_ID_HER_STINGARK	0xa099
 
 #define PCI_VENDOR_ID_ATRONICS		0x907f
 #define PCI_DEVICE_ID_ATRONICS_2015	0x2015
@@ -388,7 +402,7 @@
 #define PCI_DEVICE_ID_3COM_3C595MII	0x5952
 
 #define PCI_VENDOR_ID_PROMISE		0x105a
-#define	PCI_DEVICE_ID_PROMISE_5300	0x5300
+#define PCI_DEVICE_ID_PROMISE_5300	0x5300
 
 #define PCI_VENDOR_ID_QLOGIC		0x1077
 #define PCI_DEVICE_ID_QLOGIC_ISP1020	0x1020
@@ -410,6 +424,17 @@
 
 #define PCI_VENDOR_ID_MUTECH		0x1159
 #define PCI_DEVICE_ID_MUTECH_MV1000	0x0001
+
+#define PCI_VENDOR_ID_IMAGINGTECH	0x112f
+#define PCI_DEVICE_ID_IMAGINGTECH_ICPCI	0x0000
+
+#define PCI_VENDOR_ID_CYCLADES		0x120e
+#define PCI_DEVICE_ID_CYCLADES_Y	0x0100
+
+#define PCI_VENDOR_ID_PLX		0x113c
+#define PCI_DEVICE_ID_PLX_9060		0x0001
+
+#define PCI_VENDOR_ID_OLICOM		0x108d
 
 /*
  * The PCI interface treats multi-function devices as independent
diff -u --recursive --new-file v1.3.21/linux/include/linux/scc.h linux/include/linux/scc.h
--- v1.3.21/linux/include/linux/scc.h	Tue Aug  8 12:31:42 1995
+++ linux/include/linux/scc.h	Tue Aug 29 07:13:52 1995
@@ -1,3 +1,4 @@
+/* $Id: scc.h,v 1.11 1995/08/24 21:06:24 jreuter Exp jreuter $ */
 
 #ifndef	_SCC_H
 #define	_SCC_H
@@ -14,9 +15,9 @@
 /* Constants */
 
 #define MAXSCC		4	/* number of max. supported chips */
-#define MAX_IBUFS	300	/* change this if you run out of memory */
-#define BUFSIZE	  	64	/* must not exceed 4096 */
-#define TPS		25	/* scc_timer(): 25  Ticks Per Second */
+#define MAX_IBUFS	200	/* change this if you run out of memory */
+#define BUFSIZE	  	128	/* must not exceed 4096 */
+#define TPS		25	/* scc_timer():  Ticks Per Second */
 
 #define SCC_TIMER	3
 
@@ -133,13 +134,15 @@
 
 /* Basic message buffer structure */
 
+/* looks familiar? Hmm, yes... */
+
 struct mbuf {
 	struct mbuf *next;	/* Links mbufs belonging to single packets */
 	struct mbuf *anext;	/* Links packets on queues */
-
+	
 	char type;		/* who allocated this buffer? */
-	unsigned long  time_out;/* buffer time out */
-
+	int  time_out;		/* unimplemented yet */
+	
 	int size;		/* Size of associated data buffer */
 	int refcnt;		/* Reference count */
 	struct mbuf *dup;	/* Pointer to duplicated mbuf */
@@ -237,19 +240,16 @@
         struct scc_stat stat;	/* statistical information */
         struct scc_modem modem; /* modem information */
 
-	char rxbuf[2048];	/* Rx frame buffer max framesize * 2 */
-	int rxbufcnt;		/* Rx frame counter */
-
+	struct mbuf *rbp;	/* rx: Head of mbuf chain being filled */
+	struct mbuf *rbp1;	/* rx: Pointer to mbuf currently being written */
+	struct mbuf *rcvq;	/* Pointer to mbuf packets currently received */
+	
 	struct mbuf *sndq;	/* tx: Packets awaiting transmission */
 	struct mbuf *tbp;	/* tx: Transmit mbuf being sent */
 
 	struct mbuf *sndq1;	/* Pointer to mbuf currently under construction */
 	struct mbuf *sndq2;	/* Pointer to mbuf currently under construction */
 
-/*	unsigned char 		*xmit_buf;
-	int			xmit_head;
-	int			xmit_tail;
-	int			xmit_cnt;*/
 	
 	/* Timer */
 
@@ -263,6 +263,13 @@
 	unsigned int t_mbusy;	/* time until defer if channel busy */	 	
 };
 
+/* some variables for scc_rx_timer() bound together in a struct */
+
+struct rx_timer_CB {
+			char		   lock;
+			unsigned long	   expires;
+			struct scc_channel *scc;
+};
 
 
 /* 8530 Serial Communications Controller Register definitions */
@@ -546,8 +553,8 @@
 #define FDA	0x40		/* FIFO Data Available Status */
 #define FOY	0x80		/* FIFO Overflow Status */
 
+#endif	/* _SCC_H */
+
 /* global functions */
 
 extern long scc_init(long kmem_start);
-
-#endif	/* _SCC_H */
diff -u --recursive --new-file v1.3.21/linux/include/linux/sched.h linux/include/linux/sched.h
--- v1.3.21/linux/include/linux/sched.h	Tue Jul 18 16:28:59 1995
+++ linux/include/linux/sched.h	Fri Sep  1 14:39:29 1995
@@ -95,7 +95,7 @@
 };
 
 #define INIT_FILES { \
-	0, \
+	1, \
 	{ { 0, } }, \
 	{ NULL, } \
 }
@@ -107,7 +107,7 @@
 };
 
 #define INIT_FS { \
-	0, \
+	1, \
 	0022, \
 	NULL, NULL \
 }
@@ -129,7 +129,7 @@
 };
 
 #define INIT_MM { \
-		0, \
+		1, \
 		0, 0, 0, 0, \
 		0, 0, 0, 0, \
 		0, 0, 0, 0, \
@@ -154,7 +154,7 @@
 	struct linux_binfmt *binfmt;
 	struct task_struct *next_task, *prev_task;
 	struct task_struct *next_run,  *prev_run;
-	struct sigaction sigaction[32];
+	struct sigaction *sigaction;
 	unsigned long saved_kernel_stack;
 	unsigned long kernel_stack_page;
 	int exit_code, exit_signal;
@@ -191,11 +191,11 @@
 /* tss for this task */
 	struct thread_struct tss;
 /* filesystem information */
-	struct fs_struct fs[1];
+	struct fs_struct *fs;
 /* open file information */
-	struct files_struct files[1];
+	struct files_struct *files;
 /* memory management info */
-	struct mm_struct mm[1];
+	struct mm_struct *mm;
 };
 
 /*
@@ -213,8 +213,10 @@
  * cloning flags:
  */
 #define CSIGNAL		0x000000ff	/* signal mask to be sent at exit */
-#define COPYVM		0x00000100	/* set if VM copy desired (like normal fork()) */
-#define COPYFD		0x00000200	/* set if fd's should be copied, not shared (NI) */
+#define CLONE_VM	0x00000100	/* set if VM shared between processes */
+#define CLONE_FS	0x00000200	/* set if fs info shared between processes */
+#define CLONE_FILES	0x00000400	/* set if open files shared between processes */
+#define CLONE_SIGHAND	0x00000800	/* set if signal handlers shared */
 
 /*
  * Limit the stack by to some sane default: root can always
@@ -232,7 +234,7 @@
 /* exec domain */&default_exec_domain, \
 /* binfmt */	NULL, \
 /* schedlink */	&init_task,&init_task, &init_task, &init_task, \
-/* signals */	{{ 0, },}, \
+/* signals */	init_sigaction, \
 /* stack */	0,(unsigned long) &init_kernel_stack, \
 /* ec,brk... */	0,0,0,0,0, \
 /* pid etc.. */	0,0,0,0,0, \
@@ -252,9 +254,9 @@
 /* ipc */	NULL, NULL, \
 /* ldt */	NULL, \
 /* tss */	INIT_TSS, \
-/* fs */	{ INIT_FS }, \
-/* files */	{ INIT_FILES }, \
-/* mm */	{ INIT_MM } \
+/* fs */	&init_fs, \
+/* files */	&init_files, \
+/* mm */	&init_mm \
 }
 
 #ifdef __KERNEL__
diff -u --recursive --new-file v1.3.21/linux/include/linux/socket.h linux/include/linux/socket.h
--- v1.3.21/linux/include/linux/socket.h	Mon Aug 28 14:52:23 1995
+++ linux/include/linux/socket.h	Fri Sep  1 14:31:56 1995
@@ -89,8 +89,8 @@
 #define	IPTOS_THROUGHPUT	0x08
 #define	IPTOS_RELIABILITY	0x04
 #define IP_TTL		2
+#define IP_HDRINCL	3
 #ifdef V1_3_WILL_DO_THIS_FUNKY_STUFF
-#define IP_HRDINCL	3
 #define IP_OPTIONS	4
 #endif
 
diff -u --recursive --new-file v1.3.21/linux/include/linux/sonycd535.h linux/include/linux/sonycd535.h
--- v1.3.21/linux/include/linux/sonycd535.h	Sun Feb 12 15:00:45 1995
+++ linux/include/linux/sonycd535.h	Tue Aug 29 10:15:53 1995
@@ -107,9 +107,9 @@
 
 #define LOG_START_OFFSET        150     /* Offset of first logical sector */
 
-#define SONY_JIFFIES_TIMEOUT            500  /* Maximum number of jiffies (10ms)
-                                                  the drive will wait/try for an
-                                                  operation */
+#define SONY_JIFFIES_TIMEOUT	(5*HZ)	/* Maximum time
+					   the drive will wait/try for an
+					   operation */
 #define SONY_READY_RETRIES      (50000)  /* How many times to retry a
                                                   spin waiting for a register
                                                   to come ready */
diff -u --recursive --new-file v1.3.21/linux/include/linux/timex.h linux/include/linux/timex.h
--- v1.3.21/linux/include/linux/timex.h	Thu Jun 29 19:02:55 1995
+++ linux/include/linux/timex.h	Tue Aug 29 10:15:53 1995
@@ -32,7 +32,11 @@
  * OSF/1 kernel. The SHIFT_HZ define expresses the same value as the
  * nearest power of two in order to avoid hardware multiply operations.
  */
-#define SHIFT_HZ 7		/* log2(HZ) */
+#ifdef __alpha__
+# define SHIFT_HZ 10		/* log2(HZ) */
+#else
+# define SHIFT_HZ 7		/* log2(HZ) */
+#endif
 
 /*
  * The SHIFT_KG and SHIFT_KF defines establish the damping of the PLL
@@ -66,7 +70,7 @@
 #define CLOCK_TICK_FACTOR	20	/* Factor of both 1000000 and CLOCK_TICK_RATE */
 #define LATCH  ((CLOCK_TICK_RATE + HZ/2) / HZ)	/* For divider */
 
-#define FINETUNE (((((LATCH * HZ - CLOCK_TICK_RATE) << SHIFT_HZ) * \
+#define FINETUNE ((((((long)LATCH * HZ - CLOCK_TICK_RATE) << SHIFT_HZ) * \
 	(1000000/CLOCK_TICK_FACTOR) / (CLOCK_TICK_RATE/CLOCK_TICK_FACTOR)) \
 		<< (SHIFT_SCALE-SHIFT_HZ)) / HZ)
 
diff -u --recursive --new-file v1.3.21/linux/include/linux/types.h linux/include/linux/types.h
--- v1.3.21/linux/include/linux/types.h	Fri Jun 16 22:02:56 1995
+++ linux/include/linux/types.h	Fri Sep  1 09:12:13 1995
@@ -16,18 +16,18 @@
  * Those macros may have been defined in <gnu/types.h>. But we always
  * use the ones here. 
  */
-#undef __FDSET_LONGS
-#define __FDSET_LONGS (256/(8*sizeof(unsigned long)))
-
-typedef struct fd_set {
-	unsigned long fds_bits [__FDSET_LONGS];
-} fd_set;
-
 #undef __NFDBITS
-#define __NFDBITS	(8 * sizeof(unsigned long))
+#define __NFDBITS	(8 * sizeof(unsigned int))
 
 #undef __FD_SETSIZE
-#define __FD_SETSIZE	(__FDSET_LONGS*__NFDBITS)
+#define __FD_SETSIZE	256
+
+#undef __FDSET_INTS
+#define __FDSET_INTS	(__FD_SETSIZE/__NFDBITS)
+
+typedef struct fd_set {
+	unsigned int fds_bits [__FDSET_INTS];
+} fd_set;
 
 #include <asm/types.h>
 
diff -u --recursive --new-file v1.3.21/linux/include/linux/user.h linux/include/linux/user.h
--- v1.3.21/linux/include/linux/user.h	Wed Dec  8 14:25:58 1993
+++ linux/include/linux/user.h	Tue Aug 29 10:15:53 1995
@@ -69,7 +69,7 @@
   char u_comm[32];		/* User command that was responsible */
   int u_debugreg[8];
 };
-#define NBPG 4096
+#define NBPG PAGE_SIZE
 #define UPAGES 1
 #define HOST_TEXT_START_ADDR (u.start_code)
 #define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG)
diff -u --recursive --new-file v1.3.21/linux/include/linux/xd.h linux/include/linux/xd.h
--- v1.3.21/linux/include/linux/xd.h	Tue Aug 15 20:39:05 1995
+++ linux/include/linux/xd.h	Tue Aug 29 10:15:53 1995
@@ -64,7 +64,7 @@
 #define DMA_MODE	0x03	/* control bits to set for DMA & interrupt */
 
 #define XD_MAXDRIVES	2	/* maximum 2 drives */
-#define XD_TIMEOUT	100	/* 1 second timeout */
+#define XD_TIMEOUT	HZ	/* 1 second timeout */
 #define XD_RETRIES	4	/* maximum 4 retries */
 
 #undef DEBUG			/* define for debugging output */
diff -u --recursive --new-file v1.3.21/linux/include/net/sock.h linux/include/net/sock.h
--- v1.3.21/linux/include/net/sock.h	Tue Aug 15 20:39:05 1995
+++ linux/include/net/sock.h	Fri Sep  1 15:01:37 1995
@@ -209,6 +209,7 @@
   unsigned char		ip_opt_next_strict;	/* Next hop is strict route */
   unsigned long		ip_opt_next_hop;	/* Next hop if forced */
   unsigned char 	*ip_opt_ptr[2];		/* IP option pointers */
+  unsigned char		ip_hdrincl;		/* Include headers ? */
 #ifdef CONFIG_IP_MULTICAST  
   int			ip_mc_ttl;		/* Multicasting TTL */
   int			ip_mc_loop;		/* Loopback */
diff -u --recursive --new-file v1.3.21/linux/init/main.c linux/init/main.c
--- v1.3.21/linux/init/main.c	Tue Aug 15 20:39:05 1995
+++ linux/init/main.c	Tue Aug 29 10:15:53 1995
@@ -283,7 +283,7 @@
 		ticks = jiffies - ticks;
 		if (ticks >= HZ) {
 			loops_per_sec = muldiv(loops_per_sec, HZ, ticks);
-			printk("ok - %lu.%02lu BogoMips\n",
+			printk("ok - %lu.%02lu BogoMIPS\n",
 				loops_per_sec/500000,
 				(loops_per_sec/5000) % 100);
 			return;
diff -u --recursive --new-file v1.3.21/linux/ipc/shm.c linux/ipc/shm.c
--- v1.3.21/linux/ipc/shm.c	Tue Jun 27 14:11:47 1995
+++ linux/ipc/shm.c	Tue Aug 29 10:35:29 1995
@@ -442,7 +442,7 @@
 		page_table = pte_alloc(page_middle,tmp);
 		if (!page_table)
 			return -ENOMEM;
-		pte_val(*page_table) = shm_sgn;
+		set_pte(page_table, __pte(shm_sgn));
 	}
 	invalidate();
 	return 0;
@@ -757,13 +757,13 @@
 		if (!pte_present(pte))
 			continue;
 		if (pte_young(pte)) {
-			*page_table = pte_mkold(pte);
+			set_pte(page_table, pte_mkold(pte));
 			continue;
 		}
 		if (pte_page(pte) != pte_page(page))
 			printk("shm_swap_out: page and pte mismatch\n");
-		pte_val(*page_table) =
-		  shmd->vm_pte + SWP_ENTRY(0, idx << SHM_IDX_SHIFT);
+		set_pte(page_table,
+		  __pte(shmd->vm_pte + SWP_ENTRY(0, idx << SHM_IDX_SHIFT)));
 		mem_map[MAP_NR(pte_page(pte))]--;
 		if (shmd->vm_task->mm->rss > 0)
 			shmd->vm_task->mm->rss--;
diff -u --recursive --new-file v1.3.21/linux/kernel/exit.c linux/kernel/exit.c
--- v1.3.21/linux/kernel/exit.c	Tue Jul 18 16:28:59 1995
+++ linux/kernel/exit.c	Thu Aug 31 13:48:02 1995
@@ -357,19 +357,37 @@
 
 static void exit_files(void)
 {
-	int i;
-
-	for (i=0 ; i<NR_OPEN ; i++)
-		if (current->files->fd[i])
-			sys_close(i);
+	if (!--current->files->count) {
+		int i;
+		for (i=0 ; i<NR_OPEN ; i++)
+			if (current->files->fd[i])
+				sys_close(i);
+	}
+	free_page((long) current->files);
 }
 
 static void exit_fs(void)
 {
-	iput(current->fs->pwd);
-	current->fs->pwd = NULL;
-	iput(current->fs->root);
-	current->fs->root = NULL;
+	if (!--current->fs->count) {
+		iput(current->fs->pwd);
+		current->fs->pwd = NULL;
+		iput(current->fs->root);
+		current->fs->root = NULL;
+	}
+	free_page((long) current->fs);
+}
+
+static void exit_mm(void)
+{
+	if (!--current->mm->count)
+		exit_mmap(current);
+	free_page_tables(current);
+	free_page((long) current->mm);
+}
+
+static void exit_signal(void)
+{
+	free_page((long) current->sigaction);
 }
 
 NORET_TYPE void do_exit(long code)
@@ -384,10 +402,10 @@
 	current->flags |= PF_EXITING;
 	del_timer(&current->real_timer);
 	sem_exit();
-	exit_mmap(current);
-	free_page_tables(current);
+	exit_mm();
 	exit_files();
 	exit_fs();
+	exit_signal();
 	exit_thread();
 	forget_original_parent(current);
 	/* 
diff -u --recursive --new-file v1.3.21/linux/kernel/fork.c linux/kernel/fork.c
--- v1.3.21/linux/kernel/fork.c	Tue Jul 25 18:21:23 1995
+++ linux/kernel/fork.c	Thu Aug 31 13:56:20 1995
@@ -24,6 +24,25 @@
 #include <asm/segment.h>
 #include <asm/system.h>
 
+/*
+ * This is how a process data structure is allocated. In most
+ * cases, the "tsk" pointers point to the same allocation unit
+ * substructures, but if the new process shares part (or all)
+ * of the sub-units with the parent process, the tsk pointers
+ * may point to the parent instead.
+ *
+ * Regardless, we always allocate the full allocation unit, as
+ * the normal fork() semantics require all of them and doing
+ * suballocations would be wasteful.
+ */
+struct allocation_struct {
+	struct task_struct tsk;
+	struct sigaction sigaction[32];
+	struct fs_struct fs;
+	struct files_struct files;
+	struct mm_struct mm;
+};
+
 int nr_tasks=1;
 int nr_running=1;
 long last_pid=0;
@@ -60,28 +79,6 @@
 	return free_task;
 }
 
-static struct file * copy_fd(struct file * old_file)
-{
-	struct file * new_file = get_empty_filp();
-	int error;
-
-	if (new_file) {
-		memcpy(new_file,old_file,sizeof(struct file));
-		new_file->f_count = 1;
-		if (new_file->f_inode)
-			new_file->f_inode->i_count++;
-		if (new_file->f_op && new_file->f_op->open) {
-			error = new_file->f_op->open(new_file->f_inode,new_file);
-			if (error) {
-				iput(new_file->f_inode);
-				new_file->f_count = 0;
-				new_file = NULL;
-			}
-		}
-	}
-	return new_file;
-}
-
 static int dup_mmap(struct task_struct * tsk)
 {
 	struct vm_area_struct * mpnt, **p, *tmp;
@@ -113,50 +110,74 @@
 	return 0;
 }
 
-/*
- * SHAREFD not yet implemented..
- */
-static void copy_files(unsigned long clone_flags, struct task_struct * p)
+static int copy_mm(unsigned long clone_flags, struct allocation_struct * u)
 {
-	int i;
-	struct file * f;
+	if (clone_flags & CLONE_VM) {
+		if (clone_page_tables(&u->tsk))
+			return -1;
+		current->mm->count++;
+		mem_map[MAP_NR(current->mm)]++;
+		return 0;
+	}
+	u->tsk.mm = &u->mm;
+	u->mm = *current->mm;
+	u->mm.count = 1;
+	u->mm.min_flt = u->mm.maj_flt = 0;
+	u->mm.cmin_flt = u->mm.cmaj_flt = 0;
+	if (copy_page_tables(&u->tsk))
+		return -1;
+	if (dup_mmap(&u->tsk))
+		return -1;
+	mem_map[MAP_NR(u)]++;
+	return 0;
+}
 
-	if (clone_flags & COPYFD) {
-		for (i=0; i<NR_OPEN;i++)
-			if ((f = p->files->fd[i]) != NULL)
-				p->files->fd[i] = copy_fd(f);
-	} else {
-		for (i=0; i<NR_OPEN;i++)
-			if ((f = p->files->fd[i]) != NULL)
-				f->f_count++;
+static void copy_fs(unsigned long clone_flags, struct allocation_struct * u)
+{
+	if (clone_flags & CLONE_FS) {
+		current->fs->count++;
+		mem_map[MAP_NR(current->fs)]++;
+		return;
 	}
+	u->tsk.fs = &u->fs;
+	u->fs = *current->fs;
+	u->fs.count = 1;
+	if (u->fs.pwd)
+		u->fs.pwd->i_count++;
+	if (u->fs.root)
+		u->fs.root->i_count++;
+	mem_map[MAP_NR(u)]++;
 }
 
-/*
- * CLONEVM not yet correctly implemented: needs to clone the mmap
- * instead of duplicating it..
- */
-static int copy_mm(unsigned long clone_flags, struct task_struct * p)
+static void copy_files(unsigned long clone_flags, struct allocation_struct * u)
 {
-	if (clone_flags & COPYVM) {
-		p->mm->min_flt = p->mm->maj_flt = 0;
-		p->mm->cmin_flt = p->mm->cmaj_flt = 0;
-		if (copy_page_tables(p))
-			return 1;
-		return dup_mmap(p);
-	} else {
-		if (clone_page_tables(p))
-			return 1;
-		return dup_mmap(p);		/* wrong.. */
+	int i;
+
+	if (clone_flags & CLONE_FILES) {
+		current->files->count++;
+		mem_map[MAP_NR(current->files)]++;
+		return;
+	}
+	u->tsk.files = &u->files;
+	u->files = *current->files;
+	u->files.count = 1;
+	for (i = 0; i < NR_OPEN; i++) {
+		struct file * f = u->files.fd[i];
+		if (f)
+			f->f_count++;
 	}
+	mem_map[MAP_NR(u)]++;
 }
 
-static void copy_fs(unsigned long clone_flags, struct task_struct * p)
-{
-	if (current->fs->pwd)
-		current->fs->pwd->i_count++;
-	if (current->fs->root)
-		current->fs->root->i_count++;
+static void copy_sighand(unsigned long clone_flags, struct allocation_struct * u)
+{
+	if (clone_flags & CLONE_SIGHAND) {
+		mem_map[MAP_NR(current->sigaction)]++;
+		return;
+	}
+	u->tsk.sigaction = u->sigaction;
+	memcpy(u->sigaction, current->sigaction, sizeof(u->sigaction));
+	mem_map[MAP_NR(u)]++;
 }
 
 /*
@@ -169,9 +190,12 @@
 	int nr;
 	unsigned long new_stack;
 	struct task_struct *p;
+	struct allocation_struct *alloc;
 
-	if(!(p = (struct task_struct*)__get_free_page(GFP_KERNEL)))
+	alloc = (struct allocation_struct *) __get_free_page(GFP_KERNEL);
+	if (!alloc)
 		goto bad_fork;
+	p = &alloc->tsk;
 	new_stack = get_free_page(GFP_KERNEL);
 	if (!new_stack)
 		goto bad_fork_free;
@@ -206,18 +230,18 @@
 	p->utime = p->stime = 0;
 	p->cutime = p->cstime = 0;
 	p->start_time = jiffies;
-	p->mm->swappable = 0;	/* don't try to swap it out before it's set up */
 	task[nr] = p;
 	SET_LINKS(p);
 	nr_tasks++;
 
 	/* copy all the process information */
 	copy_thread(nr, clone_flags, usp, p, regs);
-	if (copy_mm(clone_flags, p))
+	if (copy_mm(clone_flags, alloc))
 		goto bad_fork_cleanup;
 	p->semundo = NULL;
-	copy_files(clone_flags, p);
-	copy_fs(clone_flags, p);
+	copy_files(clone_flags, alloc);
+	copy_fs(clone_flags, alloc);
+	copy_sighand(clone_flags, alloc);
 
 	/* ok, now we should be set up.. */
 	p->mm->swappable = 1;
diff -u --recursive --new-file v1.3.21/linux/kernel/ksyms.c linux/kernel/ksyms.c
--- v1.3.21/linux/kernel/ksyms.c	Tue Aug 15 20:39:05 1995
+++ linux/kernel/ksyms.c	Fri Sep  1 14:01:17 1995
@@ -149,7 +149,7 @@
 	X(__get_free_pages),
 	X(free_pages),
 	X(kmalloc),
-	X(kfree_s),
+	X(kfree),
 	X(vmalloc),
 	X(vremap),
 	X(vfree),
diff -u --recursive --new-file v1.3.21/linux/kernel/sched.c linux/kernel/sched.c
--- v1.3.21/linux/kernel/sched.c	Tue Aug  8 12:31:43 1995
+++ linux/kernel/sched.c	Thu Aug 31 13:21:50 1995
@@ -81,6 +81,10 @@
 static unsigned long init_kernel_stack[1024] = { STACK_MAGIC, };
 unsigned long init_user_stack[1024] = { STACK_MAGIC, };
 static struct vm_area_struct init_mmap = INIT_MMAP;
+static struct mm_struct init_mm = INIT_MM;
+static struct fs_struct init_fs = INIT_FS;
+static struct files_struct init_files = INIT_FILES;
+static struct sigaction init_sigaction[32] = { {0,}, };
 struct task_struct init_task = INIT_TASK;
 
 unsigned long volatile jiffies=0;
diff -u --recursive --new-file v1.3.21/linux/kernel/sys.c linux/kernel/sys.c
--- v1.3.21/linux/kernel/sys.c	Sun Aug 13 14:45:35 1995
+++ linux/kernel/sys.c	Tue Aug 29 10:15:53 1995
@@ -433,11 +433,11 @@
 	 * simple, it hopefully works in most obvious cases.. Easy to
 	 * fool it, but this should catch most mistakes.
 	 */
-	freepages = buffermem >> 12;
+	freepages = buffermem >> PAGE_SHIFT;
 	freepages += nr_free_pages;
 	freepages += nr_swap_pages;
 	freepages -= MAP_NR(high_memory) >> 4;
-	freepages -= (newbrk-oldbrk) >> 12;
+	freepages -= (newbrk-oldbrk) >> PAGE_SHIFT;
 	if (freepages < 0)
 		return current->mm->brk;
 #if 0
diff -u --recursive --new-file v1.3.21/linux/kernel/time.c linux/kernel/time.c
--- v1.3.21/linux/kernel/time.c	Tue Jun 27 14:11:47 1995
+++ linux/kernel/time.c	Tue Aug 29 10:15:53 1995
@@ -103,10 +103,11 @@
 	    BCD_TO_BIN(mon);
 	    BCD_TO_BIN(year);
 	  }
-#if defined(__alpha__) && defined(CONFIG_PCI)
+#ifdef ALPHA_PRE_V1_2_SRM_CONSOLE
 	/*
 	 * The meaning of life, the universe, and everything. Plus
-	 * this makes the year come out right.
+	 * this makes the year come out right on SRM consoles earlier
+	 * than v1.2.
 	 */
 	year -= 42;
 #endif
diff -u --recursive --new-file v1.3.21/linux/mm/filemap.c linux/mm/filemap.c
--- v1.3.21/linux/mm/filemap.c	Mon Aug 28 14:52:23 1995
+++ linux/mm/filemap.c	Tue Aug 29 09:42:56 1995
@@ -133,7 +133,7 @@
 	unsigned long page = pte_page(*page_table);
 	unsigned long entry = SWP_ENTRY(SHM_SWP_TYPE, MAP_NR(page));
 
-	pte_val(*page_table) = entry;
+	set_pte(page_table, __pte(entry));
 	invalidate();
 	error = filemap_write_page(vma, offset, page);
 	if (pte_val(*page_table) == entry)
@@ -171,7 +171,7 @@
 			return 0;
 		if (!pte_dirty(pte))
 			return 0;
-		*ptep = pte_mkclean(pte);
+		set_pte(ptep, pte_mkclean(pte));
 		page = pte_page(pte);
 		mem_map[MAP_NR(page)]++;
 	} else {
diff -u --recursive --new-file v1.3.21/linux/mm/kmalloc.c linux/mm/kmalloc.c
--- v1.3.21/linux/mm/kmalloc.c	Thu Jun 29 19:02:55 1995
+++ linux/mm/kmalloc.c	Fri Sep  1 16:13:19 1995
@@ -32,21 +32,22 @@
 /* Private flags. */
 
 #define MF_USED 0xffaa0055
+#define MF_DMA  0xff00aa55
 #define MF_FREE 0x0055ffaa
 
 
-/* 
+/*
  * Much care has gone into making these routines in this file reentrant.
  *
  * The fancy bookkeeping of nbytesmalloced and the like are only used to
- * report them to the user (oooohhhhh, aaaaahhhhh....) are not 
+ * report them to the user (oooohhhhh, aaaaahhhhh....) are not
  * protected by cli(). (If that goes wrong. So what?)
  *
  * These routines restore the interrupt status to allow calling with ints
- * off. 
+ * off.
  */
 
-/* 
+/*
  * A block header. This is in front of every malloc-block, whether free or not.
  */
 struct block_header {
@@ -63,8 +64,8 @@
 #define BH(p) ((struct block_header *)(p))
 
 
-/* 
- * The page descriptor is at the front of every page that malloc has in use. 
+/*
+ * The page descriptor is at the front of every page that malloc has in use.
  */
 struct page_descriptor {
 	struct page_descriptor *next;
@@ -83,7 +84,7 @@
  */
 struct size_descriptor {
 	struct page_descriptor *firstfree;
-	struct page_descriptor *dmafree; /* DMA-able memory */
+	struct page_descriptor *dmafree;	/* DMA-able memory */
 	int size;
 	int nblocks;
 
@@ -91,7 +92,7 @@
 	int nfrees;
 	int nbytesmalloced;
 	int npages;
-	unsigned long gfporder; /* number of pages in the area required */
+	unsigned long gfporder;	/* number of pages in the area required */
 };
 
 /*
@@ -99,38 +100,40 @@
  * 4096 * any power of two
  */
 #if PAGE_SIZE == 4096
-struct size_descriptor sizes[] = { 
-	{ NULL, NULL,  32,127, 0,0,0,0, 0},
-	{ NULL, NULL,  64, 63, 0,0,0,0, 0 },
-	{ NULL, NULL, 128, 31, 0,0,0,0, 0 },
-	{ NULL, NULL, 252, 16, 0,0,0,0, 0 },
-	{ NULL, NULL, 508,  8, 0,0,0,0, 0 },
-	{ NULL, NULL,1020,  4, 0,0,0,0, 0 },
-	{ NULL, NULL,2040,  2, 0,0,0,0, 0 },
-	{ NULL, NULL,4096-16,  1, 0,0,0,0, 0 },
-	{ NULL, NULL,8192-16,  1, 0,0,0,0, 1 },
-	{ NULL, NULL,16384-16,  1, 0,0,0,0, 2 },
-	{ NULL, NULL,32768-16,  1, 0,0,0,0, 3 },
-	{ NULL, NULL,65536-16,  1, 0,0,0,0, 4 },
-	{ NULL, NULL,131072-16,  1, 0,0,0,0, 5 },
-	{ NULL, NULL,   0,  0, 0,0,0,0, 0 }
+struct size_descriptor sizes[] =
+{
+	{NULL, NULL, 32, 127, 0, 0, 0, 0, 0},
+	{NULL, NULL, 64, 63, 0, 0, 0, 0, 0},
+	{NULL, NULL, 128, 31, 0, 0, 0, 0, 0},
+	{NULL, NULL, 252, 16, 0, 0, 0, 0, 0},
+	{NULL, NULL, 508, 8, 0, 0, 0, 0, 0},
+	{NULL, NULL, 1020, 4, 0, 0, 0, 0, 0},
+	{NULL, NULL, 2040, 2, 0, 0, 0, 0, 0},
+	{NULL, NULL, 4096 - 16, 1, 0, 0, 0, 0, 0},
+	{NULL, NULL, 8192 - 16, 1, 0, 0, 0, 0, 1},
+	{NULL, NULL, 16384 - 16, 1, 0, 0, 0, 0, 2},
+	{NULL, NULL, 32768 - 16, 1, 0, 0, 0, 0, 3},
+	{NULL, NULL, 65536 - 16, 1, 0, 0, 0, 0, 4},
+	{NULL, NULL, 131072 - 16, 1, 0, 0, 0, 0, 5},
+	{NULL, NULL, 0, 0, 0, 0, 0, 0, 0}
 };
 #elif PAGE_SIZE == 8192
-struct size_descriptor sizes[] = { 
-	{ NULL, NULL,  64,127, 0,0,0,0, 0},
-	{ NULL, NULL, 128, 63, 0,0,0,0, 0 },
-	{ NULL, NULL, 248, 31, 0,0,0,0, 0 },
-	{ NULL, NULL, 504, 16, 0,0,0,0, 0 },
-	{ NULL, NULL,1016,  8, 0,0,0,0, 0 },
-	{ NULL, NULL,2040,  4, 0,0,0,0, 0 },
-	{ NULL, NULL,4080,  2, 0,0,0,0, 0 },
-	{ NULL, NULL,8192-32,  1, 0,0,0,0, 0 },
-	{ NULL, NULL,16384-32,  1, 0,0,0,0, 1 },
-	{ NULL, NULL,32768-32,  1, 0,0,0,0, 2 },
-	{ NULL, NULL,65536-32,  1, 0,0,0,0, 3 },
-	{ NULL, NULL,131072-32,  1, 0,0,0,0, 4 },
-	{ NULL, NULL,262144-32,  1, 0,0,0,0, 5 },
-	{ NULL, NULL,   0,  0, 0,0,0,0, 0 }
+struct size_descriptor sizes[] =
+{
+	{NULL, NULL, 64, 127, 0, 0, 0, 0, 0},
+	{NULL, NULL, 128, 63, 0, 0, 0, 0, 0},
+	{NULL, NULL, 248, 31, 0, 0, 0, 0, 0},
+	{NULL, NULL, 504, 16, 0, 0, 0, 0, 0},
+	{NULL, NULL, 1016, 8, 0, 0, 0, 0, 0},
+	{NULL, NULL, 2040, 4, 0, 0, 0, 0, 0},
+	{NULL, NULL, 4080, 2, 0, 0, 0, 0, 0},
+	{NULL, NULL, 8192 - 32, 1, 0, 0, 0, 0, 0},
+	{NULL, NULL, 16384 - 32, 1, 0, 0, 0, 0, 1},
+	{NULL, NULL, 32768 - 32, 1, 0, 0, 0, 0, 2},
+	{NULL, NULL, 65536 - 32, 1, 0, 0, 0, 0, 3},
+	{NULL, NULL, 131072 - 32, 1, 0, 0, 0, 0, 4},
+	{NULL, NULL, 262144 - 32, 1, 0, 0, 0, 0, 5},
+	{NULL, NULL, 0, 0, 0, 0, 0, 0, 0}
 };
 #else
 #error you need to make a version for your pagesize
@@ -141,269 +144,201 @@
 #define AREASIZE(order)		(PAGE_SIZE<<(sizes[order].gfporder))
 
 
-long kmalloc_init (long start_mem,long end_mem)
+long kmalloc_init(long start_mem, long end_mem)
 {
 	int order;
 
-/* 
+/*
  * Check the static info array. Things will blow up terribly if it's
  * incorrect. This is a late "compile time" check.....
  */
-for (order = 0;BLOCKSIZE(order);order++)
-    {
-    if ((NBLOCKS (order)*BLOCKSIZE(order) + sizeof (struct page_descriptor)) >
-        AREASIZE(order)) 
-        {
-        printk ("Cannot use %d bytes out of %d in order = %d block mallocs\n",
-                (int) (NBLOCKS (order) * BLOCKSIZE(order) + 
-                        sizeof (struct page_descriptor)),
-                (int) AREASIZE(order),
-                BLOCKSIZE (order));
-        panic ("This only happens if someone messes with kmalloc");
-        }
-    }
-return start_mem;
+	for (order = 0; BLOCKSIZE(order); order++) {
+		if ((NBLOCKS(order) * BLOCKSIZE(order) + sizeof(struct page_descriptor)) >
+		    AREASIZE(order)) {
+			printk("Cannot use %d bytes out of %d in order = %d block mallocs\n",
+			       (int) (NBLOCKS(order) * BLOCKSIZE(order) +
+				      sizeof(struct page_descriptor)),
+			        (int) AREASIZE(order),
+			       BLOCKSIZE(order));
+			panic("This only happens if someone messes with kmalloc");
+		}
+	}
+	return start_mem;
 }
 
 
 
-int get_order (int size)
+int get_order(int size)
 {
 	int order;
 
 	/* Add the size of the header */
-	size += sizeof (struct block_header);
-	for (order = 0;BLOCKSIZE(order);order++)
-		if (size <= BLOCKSIZE (order))
-			return order; 
+	size += sizeof(struct block_header);
+	for (order = 0; BLOCKSIZE(order); order++)
+		if (size <= BLOCKSIZE(order))
+			return order;
 	return -1;
 }
 
-void * kmalloc (size_t size, int priority)
+void *kmalloc(size_t size, int priority)
 {
 	unsigned long flags;
-	int order,tries,i,sz;
-	int dma_flag;
+	unsigned long max_addr, type;
+	int order, i, sz;
 	struct block_header *p;
-	struct page_descriptor *page;
+	struct page_descriptor *page, **pg;
+
+	order = get_order(size);
+	if (order < 0) {
+		printk("kmalloc of too large a block (%d bytes).\n", (int) size);
+		return (NULL);
+	}
+
+	max_addr = ~0UL;
+	type = MF_USED;
+	pg = &sizes[order].firstfree;
+	if (priority & GFP_DMA) {
+		max_addr = MAX_DMA_ADDRESS;
+		type = MF_DMA;
+		pg = &sizes[order].dmafree;
+	}
 
-	dma_flag = (priority & GFP_DMA);
 	priority &= GFP_LEVEL_MASK;
-	  
+
 /* Sanity check... */
 	if (intr_count && priority != GFP_ATOMIC) {
 		static int count = 0;
 		if (++count < 5) {
 			printk("kmalloc called nonatomically from interrupt %p\n",
-				__builtin_return_address(0));
+			       __builtin_return_address(0));
 			priority = GFP_ATOMIC;
 		}
 	}
 
-order = get_order (size);
-if (order < 0)
-    {
-    printk ("kmalloc of too large a block (%d bytes).\n",(int) size);
-    return (NULL);
-    }
-
-save_flags(flags);
-
-/* It seems VERY unlikely to me that it would be possible that this 
-   loop will get executed more than once. */
-tries = MAX_GET_FREE_PAGE_TRIES; 
-while (tries --)
-    {
-    /* Try to allocate a "recently" freed memory block */
-    cli ();
-    if ((page = (dma_flag ? sizes[order].dmafree : sizes[order].firstfree)) &&
-        (p    =  page->firstfree))
-        {
-        if (p->bh_flags == MF_FREE)
-            {
-            page->firstfree = p->bh_next;
-            page->nfree--;
-            if (!page->nfree)
-                {
-		  if(dma_flag)
-		    sizes[order].dmafree = page->next;
-		  else
-		    sizes[order].firstfree = page->next;
-		  page->next = NULL;
-                }
-            restore_flags(flags);
-
-            sizes [order].nmallocs++;
-            sizes [order].nbytesmalloced += size;
-            p->bh_flags =  MF_USED; /* As of now this block is officially in use */
-            p->bh_length = size;
-            return p+1; /* Pointer arithmetic: increments past header */
-            }
-        printk ("Problem: block on freelist at %08lx isn't free.\n",(long)p);
-        return (NULL);
-        }
-    restore_flags(flags);
-
-
-    /* Now we're in trouble: We need to get a new free page..... */
-
-    sz = BLOCKSIZE(order); /* sz is the size of the blocks we're dealing with */
-
-    /* This can be done with ints on: This is private to this invocation */
-    {
-    	unsigned long max_addr = ~0UL;
-    	if (dma_flag)
-    		max_addr = MAX_DMA_ADDRESS;
-	page = (struct page_descriptor *) __get_free_pages (priority & GFP_LEVEL_MASK,
-		sizes[order].gfporder, max_addr);
-    }
-
-    if (!page) {
-        static unsigned long last = 0;
-        if (last + 10*HZ < jiffies) {
-        	last = jiffies;
-	        printk ("Couldn't get a free page.....\n");
-	}
-        return NULL;
-    }
-#if 0
-    printk ("Got page %08x to use for %d byte mallocs....",(long)page,sz);
-#endif
-    sizes[order].npages++;
+	save_flags(flags);
+	cli();
+	page = *pg;
+	if (page) {
+		p = page->firstfree;
+		if (p->bh_flags != MF_FREE) {
+			restore_flags(flags);
+			printk("Problem: block on freelist at %08lx isn't free.\n", (long) p);
+			return NULL;
+		}
+		goto found_it;
+	}
 
-    /* Loop for all but last block: */
-    for (i=NBLOCKS(order),p=BH (page+1);i > 1;i--,p=p->bh_next) 
-        {
-        p->bh_flags = MF_FREE;
-        p->bh_next = BH ( ((long)p)+sz);
-        }
-    /* Last block: */
-    p->bh_flags = MF_FREE;
-    p->bh_next = NULL;
-
-    page->order = order;
-    page->nfree = NBLOCKS(order); 
-    page->firstfree = BH(page+1);
-#if 0
-    printk ("%d blocks per page\n",page->nfree);
-#endif
-    /* Now we're going to muck with the "global" freelist for this size:
-       this should be uninterruptible */
-    cli ();
-    /* 
-     * sizes[order].firstfree used to be NULL, otherwise we wouldn't be
-     * here, but you never know.... 
-     */
-    if (dma_flag) {
-      page->next = sizes[order].dmafree;
-      sizes[order].dmafree = page;
-    } else {
-      page->next = sizes[order].firstfree;
-      sizes[order].firstfree = page;
-    }
-    restore_flags(flags);
-    }
-
-/* Pray that printk won't cause this to happen again :-) */
-
-printk ("Hey. This is very funny. I tried %d times to allocate a whole\n"
-        "new page for an object only %d bytes long, but some other process\n"
-        "beat me to actually allocating it. Also note that this 'error'\n"
-        "message is soooo very long to catch your attention. I'd appreciate\n"
-        "it if you'd be so kind as to report what conditions caused this to\n"
-        "the author of this kmalloc: wolff@dutecai.et.tudelft.nl.\n"
-        "(Executive summary: This can't happen)\n", 
-                MAX_GET_FREE_PAGE_TRIES,
-                (int) size);
-return NULL;
+	/* We need to get a new free page..... */
+
+	/* sz is the size of the blocks we're dealing with */
+	sz = BLOCKSIZE(order);
+
+	/* This can be done with ints on: This is private to this invocation */
+	page = (struct page_descriptor *) __get_free_pages(priority & GFP_LEVEL_MASK,
+			sizes[order].gfporder, max_addr);
+
+	if (!page) {
+		static unsigned long last = 0;
+		if (last + 10 * HZ < jiffies) {
+			last = jiffies;
+			printk("Couldn't get a free page.....\n");
+		}
+		return NULL;
+	}
+	sizes[order].npages++;
+
+	/* Loop for all but last block: */
+	for (i = NBLOCKS(order), p = BH(page + 1); i > 1; i--, p = p->bh_next) {
+		p->bh_flags = MF_FREE;
+		p->bh_next = BH(((long) p) + sz);
+	}
+	/* Last block: */
+	p->bh_flags = MF_FREE;
+	p->bh_next = NULL;
+
+	page->order = order;
+	page->nfree = NBLOCKS(order);
+	p = BH(page+1);
+
+	/*
+	 * Now we're going to muck with the "global" freelist
+	 * for this size: this should be uninterruptible
+	 */
+	cli();
+	page->next = *pg;
+	*pg = page;
+
+found_it:
+	page->firstfree = p->bh_next;
+	page->nfree--;
+	if (!page->nfree)
+		*pg = page->next;
+	restore_flags(flags);
+	sizes[order].nmallocs++;
+	sizes[order].nbytesmalloced += size;
+	p->bh_flags = type;	/* As of now this block is officially in use */
+	p->bh_length = size;
+	return p + 1;		/* Pointer arithmetic: increments past header */
 }
 
-void kfree_s (void *ptr,int size)
+void kfree(void *ptr)
 {
-unsigned long flags;
-int order;
-register struct block_header *p=((struct block_header *)ptr) -1;
-struct page_descriptor *page,*pg2;
-
-page = PAGE_DESC (p);
-order = page->order;
-if ((order < 0) || 
-    (order > sizeof (sizes)/sizeof (sizes[0])) ||
-    (((long)(page->next)) & ~PAGE_MASK) ||
-    (p->bh_flags != MF_USED))
-    {
-    printk ("kfree of non-kmalloced memory: %p, next= %p, order=%d\n",
-                p, page->next, page->order);
-    return;
-    }
-if (size &&
-    size != p->bh_length)
-    {
-    printk ("Trying to free pointer at %p with wrong size: %d instead of %lu.\n",
-        p,size,p->bh_length);
-    return;
-    }
-size = p->bh_length;
-p->bh_flags = MF_FREE; /* As of now this block is officially free */
-save_flags(flags);
-cli ();
-p->bh_next = page->firstfree;
-page->firstfree = p;
-page->nfree ++;
-
-if (page->nfree == 1)
-   { /* Page went from full to one free block: put it on the freelist.  Do not bother
-      trying to put it on the DMA list. */
-   if (page->next)
-        {
-        printk ("Page %p already on freelist dazed and confused....\n", page);
-        }
-   else
-        {
-        page->next = sizes[order].firstfree;
-        sizes[order].firstfree = page;
-        }
-   }
+	int size;
+	unsigned long flags;
+	int order;
+	register struct block_header *p;
+	struct page_descriptor *page, **pg;
 
+	if (!ptr)
+		return;
+	p = ((struct block_header *) ptr) - 1;
+	page = PAGE_DESC(p);
+	order = page->order;
+	pg = &sizes[order].firstfree;
+	if (p->bh_flags == MF_DMA) {
+		p->bh_flags = MF_USED;
+		pg = &sizes[order].dmafree;
+	}
+
+	if ((order < 0) ||
+	    (order > sizeof(sizes) / sizeof(sizes[0])) ||
+	    (((long) (page->next)) & ~PAGE_MASK) ||
+	    (p->bh_flags != MF_USED)) {
+		printk("kfree of non-kmalloced memory: %p, next= %p, order=%d\n",
+		       p, page->next, page->order);
+		return;
+	}
+	size = p->bh_length;
+	p->bh_flags = MF_FREE;	/* As of now this block is officially free */
+	save_flags(flags);
+	cli();
+	p->bh_next = page->firstfree;
+	page->firstfree = p;
+	page->nfree++;
+
+	if (page->nfree == 1) {
+/* Page went from full to one free block: put it on the freelist. */
+		page->next = *pg;
+		*pg = page;
+	}
 /* If page is completely free, free it */
-if (page->nfree == NBLOCKS (page->order))
-    {
-#if 0
-    printk ("Freeing page %08x.\n", (long)page);
-#endif
-    if (sizes[order].firstfree == page)
-        {
-        sizes[order].firstfree = page->next;
-        }
-    else if (sizes[order].dmafree == page)
-        {
-        sizes[order].dmafree = page->next;
-        }
-    else
-        {
-        for (pg2=sizes[order].firstfree;
-                (pg2 != NULL) && (pg2->next != page);
-                        pg2=pg2->next)
-            /* Nothing */;
-	if (!pg2)
-	  for (pg2=sizes[order].dmafree;
-	       (pg2 != NULL) && (pg2->next != page);
-	       pg2=pg2->next)
-            /* Nothing */;
-        if (pg2 != NULL)
-            pg2->next = page->next;
-        else
-            printk ("Ooops. page %p doesn't show on freelist.\n", page);
-        }
-/* FIXME: I'm sure we should do something with npages here (like npages--) */
-    free_pages ((long)page, sizes[order].gfporder);
-    }
-restore_flags(flags);
-
-/* FIXME: ?? Are these increment & decrement operations guaranteed to be
- *	     atomic? Could an IRQ not occur between the read & the write?
- *	     Maybe yes on a x86 with GCC...??
- */
-sizes[order].nfrees++;      /* Noncritical (monitoring) admin stuff */
-sizes[order].nbytesmalloced -= size;
+	if (page->nfree == NBLOCKS(order)) {
+		for (;;) {
+			struct page_descriptor *tmp = *pg;
+			if (!tmp) {
+				printk("Ooops. page %p doesn't show on freelist.\n", page);
+				break;
+			}
+			if (tmp == page) {
+				*pg = page->next;
+				break;
+			}
+			pg = &tmp->next;
+		}
+		sizes[order].npages--;
+		free_pages((long) page, sizes[order].gfporder);
+	}
+	sizes[order].nfrees++;
+	sizes[order].nbytesmalloced -= size;
+	restore_flags(flags);
 }
diff -u --recursive --new-file v1.3.21/linux/mm/memory.c linux/mm/memory.c
--- v1.3.21/linux/mm/memory.c	Tue Aug  8 12:31:43 1995
+++ linux/mm/memory.c	Tue Aug 29 09:42:56 1995
@@ -232,19 +232,19 @@
 		return;
 	if (!pte_present(pte)) {
 		swap_duplicate(pte_val(pte));
-		*new_pte = pte;
+		set_pte(new_pte, pte);
 		return;
 	}
 	if (pte_page(pte) > high_memory || (mem_map[MAP_NR(pte_page(pte))] & MAP_PAGE_RESERVED)) {
-		*new_pte = pte;
+		set_pte(new_pte, pte);
 		return;
 	}
 	if (pte_cow(pte))
 		pte = pte_wrprotect(pte);
 	if (delete_from_swap_cache(pte_page(pte)))
 		pte = pte_mkdirty(pte);
-	*new_pte = pte_mkold(pte);
-	*old_pte = pte;
+	set_pte(new_pte, pte_mkold(pte));
+	set_pte(old_pte, pte);
 	mem_map[MAP_NR(pte_page(pte))]++;
 }
 
@@ -433,7 +433,7 @@
 		end = PMD_SIZE;
 	do {
 		pte_t oldpage = *pte;
-		*pte = zero_pte;
+		set_pte(pte, zero_pte);
 		forget_pte(oldpage);
 		address += PAGE_SIZE;
 		pte++;
@@ -501,7 +501,7 @@
 		pte_t oldpage = *pte;
 		pte_clear(pte);
 		if (offset >= high_memory || (mem_map[MAP_NR(offset)] & MAP_PAGE_RESERVED))
-			*pte = mk_pte(offset, prot);
+			set_pte(pte, mk_pte(offset, prot));
 		forget_pte(oldpage);
 		address += PAGE_SIZE;
 		offset += PAGE_SIZE;
@@ -599,7 +599,7 @@
 		pte_clear(pte);
 		invalidate();
 	}
-	*pte = pte_mkwrite(pte_mkdirty(mk_pte(page, PAGE_COPY)));
+	set_pte(pte, pte_mkwrite(pte_mkdirty(mk_pte(page, PAGE_COPY))));
 /* no need for invalidate */
 	return page;
 }
@@ -658,18 +658,18 @@
 			if (mem_map[MAP_NR(old_page)] & MAP_PAGE_RESERVED)
 				++vma->vm_task->mm->rss;
 			copy_page(old_page,new_page);
-			*page_table = pte_mkwrite(pte_mkdirty(mk_pte(new_page, vma->vm_page_prot)));
+			set_pte(page_table, pte_mkwrite(pte_mkdirty(mk_pte(new_page, vma->vm_page_prot))));
 			free_page(old_page);
 			invalidate();
 			return;
 		}
-		*page_table = BAD_PAGE;
+		set_pte(page_table, BAD_PAGE);
 		free_page(old_page);
 		oom(vma->vm_task);
 		invalidate();
 		return;
 	}
-	*page_table = pte_mkdirty(pte_mkwrite(pte));
+	set_pte(page_table, pte_mkdirty(pte_mkwrite(pte)));
 	invalidate();
 	if (new_page)
 		free_page(new_page);
@@ -865,7 +865,7 @@
 				return 0;
 		}
 		copy_page(pte_page(from), newpage);
-		*to_table = mk_pte(newpage, to_area->vm_page_prot);
+		set_pte(to_table, mk_pte(newpage, to_area->vm_page_prot));
 		return 1;
 	}
 /*
@@ -880,18 +880,18 @@
 	if (in_swap_cache(pte_page(from))) {
 		if (!(from_area->vm_flags & VM_SHARED))
 			return 0;
-		*from_table = pte_mkdirty(from);
+		set_pte(from_table, pte_mkdirty(from));
 		delete_from_swap_cache(pte_page(from));
 	}
 	mem_map[MAP_NR(pte_page(from))]++;
-	*to_table = mk_pte(pte_page(from), to_area->vm_page_prot);
+	set_pte(to_table, mk_pte(pte_page(from), to_area->vm_page_prot));
 /* Check if we need to do anything at all to the 'from' field */
 	if (!pte_write(from))
 		return 1;
 	if (from_area->vm_flags & VM_SHARED)
 		return 1;
 /* ok, need to mark it read-only, so invalidate any possible old TB entry */
-	*from_table = pte_wrprotect(from);
+	set_pte(from_table, pte_wrprotect(from));
 	invalidate();
 	return 1;
 }
@@ -990,7 +990,7 @@
 		page = pte_wrprotect(page);
 	++vma->vm_task->mm->rss;
 	++vma->vm_task->mm->maj_flt;
-	*page_table = page;
+	set_pte(page_table, page);
 	return;
 }
 
@@ -1086,11 +1086,11 @@
 		do_no_page(vma, address, write_access);
 		return;
 	}
-	*pte = pte_mkyoung(*pte);
+	set_pte(pte, pte_mkyoung(*pte));
 	if (!write_access)
 		return;
 	if (pte_write(*pte)) {
-		*pte = pte_mkdirty(*pte);
+		set_pte(pte, pte_mkdirty(*pte));
 		return;
 	}
 	do_wp_page(vma, address, write_access);
diff -u --recursive --new-file v1.3.21/linux/mm/mprotect.c linux/mm/mprotect.c
--- v1.3.21/linux/mm/mprotect.c	Tue May 30 12:17:18 1995
+++ linux/mm/mprotect.c	Tue Aug 29 09:42:56 1995
@@ -38,7 +38,7 @@
 	do {
 		pte_t entry = *pte;
 		if (pte_present(entry))
-			*pte = pte_modify(entry, newprot);
+			set_pte(pte, pte_modify(entry, newprot));
 		address += PAGE_SIZE;
 		pte++;
 	} while (address < end);
diff -u --recursive --new-file v1.3.21/linux/mm/swap.c linux/mm/swap.c
--- v1.3.21/linux/mm/swap.c	Mon Aug 28 14:52:23 1995
+++ linux/mm/swap.c	Tue Aug 29 09:42:56 1995
@@ -320,7 +320,7 @@
 		return;
 	}
 	if (!page) {
-		*page_table = BAD_PAGE;
+		set_pte(page_table, BAD_PAGE);
 		swap_free(entry);
 		oom(current);
 		return;
@@ -333,10 +333,10 @@
 	vma->vm_task->mm->rss++;
 	vma->vm_task->mm->maj_flt++;
 	if (!write_access && add_to_swap_cache(page, entry)) {
-		*page_table = mk_pte(page, vma->vm_page_prot);
+		set_pte(page_table, mk_pte(page, vma->vm_page_prot));
 		return;
 	}
-	*page_table = pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
+	set_pte(page_table, pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot))));
   	swap_free(entry);
   	return;
 }
@@ -369,7 +369,7 @@
 	if (mem_map[MAP_NR(page)] & MAP_PAGE_RESERVED)
 		return 0;
 	if ((pte_dirty(pte) && delete_from_swap_cache(page)) || pte_young(pte))  {
-		*page_table = pte_mkold(pte);
+		set_pte(page_table, pte_mkold(pte));
 		return 0;
 	}	
 	if (pte_dirty(pte)) {
@@ -384,7 +384,7 @@
 			if (!(entry = get_swap_page()))
 				return 0;
 			vma->vm_task->mm->rss--;
-			pte_val(*page_table) = entry;
+			set_pte(page_table, __pte(entry));
 			invalidate();
 			write_swap_page(entry, (char *) page);
 		}
@@ -393,12 +393,12 @@
 	}
         if ((entry = find_in_swap_cache(page)))  {
 		if (mem_map[MAP_NR(page)] != 1) {
-			*page_table = pte_mkdirty(pte);
+			set_pte(page_table, pte_mkdirty(pte));
 			printk("Aiee.. duplicated cached swap-cache entry\n");
 			return 0;
 		}
 		vma->vm_task->mm->rss--;
-		pte_val(*page_table) = entry;
+		set_pte(page_table, __pte(entry));
 		invalidate();
 		free_page(page);
 		return 1;
@@ -860,7 +860,7 @@
 		if (SWP_TYPE(in_swap_cache(page)) != type)
 			return 0;
 		delete_from_swap_cache(page);
-		*dir = pte_mkdirty(pte);
+		set_pte(dir, pte_mkdirty(pte));
 		return 0;
 	}
 	if (SWP_TYPE(pte_val(pte)) != type)
@@ -870,7 +870,7 @@
 		free_page(page);
 		return 1;
 	}
-	*dir = pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
+	set_pte(dir, pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot))));
 	++vma->vm_task->mm->rss;
 	swap_free(pte_val(pte));
 	return 1;
diff -u --recursive --new-file v1.3.21/linux/mm/vmalloc.c linux/mm/vmalloc.c
--- v1.3.21/linux/mm/vmalloc.c	Thu Jul 13 16:20:21 1995
+++ linux/mm/vmalloc.c	Tue Aug 29 10:15:53 1995
@@ -120,7 +120,7 @@
 		page = __get_free_page(GFP_KERNEL);
 		if (!page)
 			return -ENOMEM;
-		*pte = mk_pte(page, PAGE_KERNEL);
+		set_pte(pte, mk_pte(page, PAGE_KERNEL));
 		address += PAGE_SIZE;
 		pte++;
 	}
@@ -179,7 +179,7 @@
 	do {
 		if (!pte_none(*pte))
 			printk("remap_area_pte: page already exists\n");
-		*pte = mk_pte(offset, PAGE_KERNEL);
+		set_pte(pte, mk_pte(offset, PAGE_KERNEL));
 		address += PAGE_SIZE;
 		offset += PAGE_SIZE;
 		pte++;
@@ -277,7 +277,7 @@
 	struct vm_struct *area;
 
 	size = PAGE_ALIGN(size);
-	if (!size || size > high_memory)
+	if (!size || size > (MAP_NR(high_memory) << PAGE_SHIFT))
 		return NULL;
 	area = get_vm_area(size);
 	if (!area)
diff -u --recursive --new-file v1.3.21/linux/net/Changes linux/net/Changes
--- v1.3.21/linux/net/Changes	Mon Aug 28 14:52:23 1995
+++ linux/net/Changes	Fri Sep  1 14:31:56 1995
@@ -177,6 +177,17 @@
 o	Datagram generic iovec support			[IN]
 o	Misc minor bug fixes				[IN]
 
+-------->>>>> 1.3.22 I expect <<<<<-------
+
+o	Device lock against page fault			[IN]
+o	IP_HDRINCL					[TESTED]
+o	IP firewalling spoofing protection		[IN]
+o	IGMP bug fixes and workarounds			[TESTED]
+o	IFF_ALLMULTI protocol layer support		[TESTED]
+o	First parts of IP multicast routing code	[IN]
+o	Generate BSD ENETDOWN errors			[IN]
+
+
 o	Finish merging the bridge code
 o	SIOCSLEEPRT patch
 o	Options support in ip_build_xmit		[PENDING]
diff -u --recursive --new-file v1.3.21/linux/net/README linux/net/README
--- v1.3.21/linux/net/README	Tue Jun  6 11:22:14 1995
+++ linux/net/README	Fri Sep  1 14:31:57 1995
@@ -1,31 +1,23 @@
-Upgrade Notes from 1.0
-[Alan Cox -  Alan.Cox@linux.org]
 
-Upgrading to 1.2.0 from a 1.0 kernel networking set. If you are using
-a complete 1.2 distribution you can ignore this.
+Maintainers and developers for networking code sections
 
-This doesn't attempt to list the changes. That would be too large. Instead
-just what you need and can change
+Code Section		Bug Report Contact
+-------------------+-------------------------------------------
+802 [other	]	alan@cymru.net	
+    [token ring	]	needs a maintainer/debugger
+appletalk		alan@cymru.net and netatalk@umich.edu
+ax25			g4klx@g4klx.demon.co.uk
+core			alan@cymru.net
+ethernet		alan@cymru.net
+ipv4			alan@cymru.net
+ipx			alan@cymru.net,greg@caldera.com
+netrom			g4klx@g4klx.demon.co.uk
+unix			alan@cymru.net
 
-arp,ifconfig, etc. Get net-tools-1.1.95 (or 1.2.0 if its out) from
-ftp.linux.org.uk:/pub/Linux/Networking/PROGRAMS/NetTools, and install
-these. You will also acquire a couple of new tools "plipconfig" for tuning
-plip links and "ipfw" for ip firewall management.
 
-bootpd: The original bootpd has a bug that the 1.2 kernel spots. You will
-need to upgrade this to the version in
-ftp.linux.org.uk:/pub/Linux/Networking/PROGRAMS/Upgrades
+	If in doubt contact me <alan@cymru.net> first.
 
-
-Standard programs that you ought to update are
-
-named 4.7.x	to 4.9.x	Stops named dying occasionally
-pop3d 1.001     to 1.004	Fixes a bug that can lose mail
-
-A complete current networking set for Linux can be obtained by getting
-the NetKit[A,B...] series archives from ftp.funet.fi. Funet also carries
-binaries for Linux mbone applications if you now wish to make use of
-these facilities.
+---------------------------------------------------------------------------
 
 For commercial UK custom Linux networking projects, drivers and development
 (but not free support!) I can be contacted via
@@ -35,7 +27,9 @@
 	Fax: +44 1792 295811
 	Tel: +44 1792 295213
 
-Please don't send commercial queries to my email address as I have that
+	Email: alan@cymru.net
+
+Please don't send commercial queries to my .ac.uk email address as I have that
 in an academic and _not_ commercial capacity. On the other hand feel
 free to send bug reports, queries and enhancements that way.
 
diff -u --recursive --new-file v1.3.21/linux/net/ax25/README.AX25 linux/net/ax25/README.AX25
--- v1.3.21/linux/net/ax25/README.AX25	Fri Jul  7 08:54:56 1995
+++ linux/net/ax25/README.AX25	Thu Jan  1 02:00:00 1970
@@ -1,50 +0,0 @@
-This is version 029 of the new AX.25 and NET/ROM code for Linux. It
-incorporates many enhancements since the last release, notably the rewriting
-of the connected mode IP code and the IP over NET/ROM code. The opportunity
-has been taken to add the G8BPQ NET/ROM extensions and to add BPQ Ethernet
-support. The latter has been much eased by the use of the new variable
-length header code by Alan Cox.
-
-To use the BPQ Ethernet option, first up the ethernet interface in the usual
-manner, the IP address of the interface is not that important but it will
-be required for the ARP table. Next create an ARP entry in the ARP table of
-type ax25 for the interface binding it to an AX.25 callsign, this callsign
-will be the callsign of that interface. By default BPQ Ethernet uses a
-multi-cast address, this implementation does not, instead the standard
-ethernet broadcast address is used. Therefore the NET.CFG file for the
-ODI driver should look similar to this:
-
------------------------------- cut here ------------------------------------
-
-LINK SUPPORT
-
-	MAX STACKS 1
-	MAX BOARDS 1
-
-LINK DRIVER E2000			; or other MLID to suit your card
-
-	INT 10				;
-	PORT 300			; to suit your card
-
-	FRAME ETHERNET_II
-
-	PROTOCOL BPQ 8FF ETHERNET_II	; required for BPQ - can change PID
-
-BPQPARMS				; optional - only needed if you want
-					; to override the default target addr
-
-	ETH_ADDR  FF:FF:FF:FF:FF:FF	; Target address
-
------------------------------ cut here -------------------------------------
-
-The above configuration assumes that only BPQ Ethernet is being used.
-
-It is not possible to run IP over AX.25 on the BPQ Ethernet port. To simply
-route IP frames to (say) eth0 would create standard ethernet IP frames and
-completely bypass the AX.25 code. However it is possible to use IP over
-NET/ROM across a BPQ Ethernet link, the performance of such a system is
-very acceptable indeed.
-
-Jonathan Naylor G4KLX
-
-g4klx@amsat.org
diff -u --recursive --new-file v1.3.21/linux/net/core/dev.c linux/net/core/dev.c
--- v1.3.21/linux/net/core/dev.c	Tue Aug 15 20:39:07 1995
+++ linux/net/core/dev.c	Fri Sep  1 14:31:56 1995
@@ -36,6 +36,7 @@
  *		Alan Cox	:	Hashed net_bh()
  *	Richard Kooijman	:	Timestamp fixes.
  *		Alan Cox	:	Wrong field in SIOCGIFDSTADDR
+ *		Alan Cox	:	Device lock protection.
  *
  *	Cleaned up and recommented by Alan Cox 2nd April 1994. I hope to have
  *	the rest as well commented in the end.
@@ -81,6 +82,12 @@
 struct packet_type *ptype_all = NULL;		/* Taps */
 
 /*
+ *	Device list lock
+ */
+ 
+int dev_lockct=0;
+ 
+/*
  *	Our notifier list
  */
  
@@ -242,45 +249,42 @@
  
 int dev_close(struct device *dev)
 {
+	int ct=0;
+
 	/*
-	 *	Only close a device if it is up.
+	 *	Call the device specific close. This cannot fail.
+	 *	Only if device is UP
 	 */
-	 
-	if (dev->flags != 0) 
+	if ((dev->flags & IFF_UP) && dev->stop)
+		dev->stop(dev);
+
+	dev->flags = 0;
+
+	/*
+	 *	Tell people we are going down
+	 */
+	notifier_call_chain(&netdev_chain, NETDEV_DOWN, dev);
+	/*
+	 *	Flush the multicast chain
+	 */
+	dev_mc_discard(dev);
+	/*
+	 *	Blank the IP addresses
+	 */
+	dev->pa_addr = 0;
+	dev->pa_dstaddr = 0;
+	dev->pa_brdaddr = 0;
+	dev->pa_mask = 0;
+	/*
+	 *	Purge any queued packets when we down the link 
+	 */
+	while(ct<DEV_NUMBUFFS)
 	{
-  		int ct=0;
-		dev->flags = 0;
-		/*
-		 *	Call the device specific close. This cannot fail.
-		 */
-		if (dev->stop) 
-			dev->stop(dev);
-		/*
-		 *	Tell people we are going down
-		 */
-		notifier_call_chain(&netdev_chain, NETDEV_DOWN, dev);
-		/*
-		 *	Flush the multicast chain
-		 */
-		dev_mc_discard(dev);
-		/*
-		 *	Blank the IP addresses
-		 */
-		dev->pa_addr = 0;
-		dev->pa_dstaddr = 0;
-		dev->pa_brdaddr = 0;
-		dev->pa_mask = 0;
-		/*
-		 *	Purge any queued packets when we down the link 
-		 */
-		while(ct<DEV_NUMBUFFS)
-		{
-			struct sk_buff *skb;
-			while((skb=skb_dequeue(&dev->buffs[ct]))!=NULL)
-				if(skb->free)
-					kfree_skb(skb,FREE_WRITE);
-			ct++;
-		}
+		struct sk_buff *skb;
+		while((skb=skb_dequeue(&dev->buffs[ct]))!=NULL)
+			if(skb->free)
+				kfree_skb(skb,FREE_WRITE);
+		ct++;
 	}
 	return(0);
 }
@@ -995,6 +999,14 @@
 		case SIOCSIFFLAGS:	/* Set interface flags */
 			{
 				int old_flags = dev->flags;
+				
+				/*
+				 *	We are not allowed to potentially close/unload
+				 *	a device until we get this lock.
+				 */
+				
+				dev_lock_wait();
+				
 				dev->flags = ifr.ifr_flags & (
 					IFF_UP | IFF_BROADCAST | IFF_DEBUG | IFF_LOOPBACK |
 					IFF_POINTOPOINT | IFF_NOTRAILERS | IFF_RUNNING |
diff -u --recursive --new-file v1.3.21/linux/net/ipv4/Makefile linux/net/ipv4/Makefile
--- v1.3.21/linux/net/ipv4/Makefile	Tue Aug 15 20:39:11 1995
+++ linux/net/ipv4/Makefile	Fri Sep  1 14:31:56 1995
@@ -10,7 +10,7 @@
 O_TARGET := ipv4.o
 IPV4_OBJS	:= utils.o route.o proc.o timer.o protocol.o packet.o \
 		   arp.o ip.o raw.o icmp.o tcp.o udp.o devinet.o af_inet.o \
-		   igmp.o ip_fw.o ipip.o
+		   igmp.o ip_fw.o ipip.o ipmr.o
 
 ifdef CONFIG_INET_RARP
 IPV4_OBJS := $(IPV4_OBJS) rarp.o
diff -u --recursive --new-file v1.3.21/linux/net/ipv4/README.TCP linux/net/ipv4/README.TCP
--- v1.3.21/linux/net/ipv4/README.TCP	Tue Jun  6 11:22:26 1995
+++ linux/net/ipv4/README.TCP	Thu Jan  1 02:00:00 1970
@@ -1,39 +0,0 @@
-How the new TCP output machine [nyi] works.
-
-
-Data is kept on a single queue. The skb->users flag tells us if the frame is
-one that has been queued already. To add a frame we throw it on the end. Ack
-walks down the list from the start.
-
-We keep a set of control flags
-
-
-	sk->tcp_pend_event
-
-		TCP_PEND_ACK			Ack needed
-		TCP_ACK_NOW			Needed now
-		TCP_WINDOW			Window update check
-		TCP_WINZERO			Zero probing
-
-
-	sk->transmit_queue		The transmission frame begin
-	sk->transmit_new		First new frame pointer
-	sk->transmit_end		Where to add frames
-
-	sk->tcp_last_tx_ack		Last ack seen
-	sk->tcp_dup_ack			Dup ack count for fast retransmit
-
-
-Frames are queued for output by tcp_write. We do our best to send the frames
-off immediately if possible, but otherwise queue and compute the body
-checksum in the copy. 
-
-When a write is done we try to clear any pending events and piggy back them.
-If the window is full we queue full sized frames. On the firs timeout in
-zero window we split this.
-
-On a timer we walk the retransmit list to send any retransmits, update the
-backoff timers etc. A change of route table stamp causes a change of header
-and recompute. We add any new tcp level headers and refinish the checksum
-before sending. 
-
diff -u --recursive --new-file v1.3.21/linux/net/ipv4/af_inet.c linux/net/ipv4/af_inet.c
--- v1.3.21/linux/net/ipv4/af_inet.c	Mon Aug 28 14:52:25 1995
+++ linux/net/ipv4/af_inet.c	Fri Sep  1 14:31:57 1995
@@ -43,6 +43,7 @@
  *		Alan Cox	:	New buffering now used smartly.
  *		Alan Cox	:	BSD rather than common sense interpretation of
  *					listen.
+ *		Germano Caronni	:	Assorted small races.
  *
  *		This program is free software; you can redistribute it and/or
  *		modify it under the terms of the GNU General Public License
@@ -726,6 +727,10 @@
 	sock->data =(void *) sk;
 	sk->dummy_th.doff = sizeof(sk->dummy_th)/4;
 	sk->ip_ttl=64;
+	if(sk->type==SOCK_RAW && protocol==IPPROTO_RAW)
+		sk->ip_hdrincl=1;
+	else
+		sk->ip_hdrincl=0;
 #ifdef CONFIG_IP_MULTICAST
 	sk->ip_mc_loop=1;
 	sk->ip_mc_ttl=1;
@@ -978,8 +983,10 @@
 	{
 		if(sk->err!=0)
 		{
+			cli();
 			err=sk->err;
 			sk->err=0;
+			sti();
 			return -err;
 		}
 		return -EALREADY;	/* Connecting is currently in progress */
@@ -1023,10 +1030,10 @@
 		   icmp error packets wanting to close a tcp or udp socket. */
 		if(sk->err && sk->protocol == IPPROTO_TCP)
 		{
-			sti();
 			sock->state = SS_UNCONNECTED;
 			err = -sk->err;
 			sk->err=0;
+			sti();
 			return err; /* set by tcp_err() */
 		}
 	}
@@ -1036,8 +1043,10 @@
 	if (sk->state != TCP_ESTABLISHED && sk->err) 
 	{
 		sock->state = SS_UNCONNECTED;
+		cli();
 		err=sk->err;
 		sk->err=0;
+		sti();
 		return(-err);
 	}
 	return(0);
diff -u --recursive --new-file v1.3.21/linux/net/ipv4/arp.c linux/net/ipv4/arp.c
--- v1.3.21/linux/net/ipv4/arp.c	Mon Aug 28 14:52:25 1995
+++ linux/net/ipv4/arp.c	Fri Sep  1 14:31:56 1995
@@ -42,6 +42,7 @@
  *		Mike Shaver     :       RFC1122 checks.
  *		Jonathan Naylor :	Only lookup the hardware address for
  *					the correct hardware type.
+ *		Germano Caronni	:	Assorted subtle races
  */
 
 /* RFC1122 Status:
@@ -278,6 +279,7 @@
 		skb_device_lock(skb);
 		restore_flags(flags);
 		dev_kfree_skb(skb, FREE_WRITE);
+		cli();
 	}
 	restore_flags(flags);
 	del_timer(&entry->timer);
@@ -556,8 +558,10 @@
 	{
 		if (entry->ip == ip_addr)
 		{
-			if ((entry->flags & ATF_PERM) && !force)
+			if ((entry->flags & ATF_PERM) && !force) {
+				sti();
 				return;
+			}
 			*pentry = entry->next;
 			del_timer(&entry->timer);
 			sti();
diff -u --recursive --new-file v1.3.21/linux/net/ipv4/devinet.c linux/net/ipv4/devinet.c
--- v1.3.21/linux/net/ipv4/devinet.c	Tue Jun  6 12:16:43 1995
+++ linux/net/ipv4/devinet.c	Fri Sep  1 14:31:56 1995
@@ -15,6 +15,7 @@
  *		Alan Cox, <gw4pts@gw4pts.ampr.org>
  */
  
+#include <linux/config.h>
 #include <asm/segment.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
@@ -213,3 +214,17 @@
 	return NULL;
 }
 
+/*
+ *	Find the first device with a given source address.
+ */
+ 
+struct device *ip_dev_find(unsigned long addr)
+{
+	struct device *dev;
+	for(dev = dev_base; dev; dev=dev->next)
+	{
+		if((dev->flags&IFF_UP) && dev->pa_addr==addr)
+			return dev;
+	}
+	return NULL;
+}
diff -u --recursive --new-file v1.3.21/linux/net/ipv4/igmp.c linux/net/ipv4/igmp.c
--- v1.3.21/linux/net/ipv4/igmp.c	Fri Aug 18 08:44:59 1995
+++ linux/net/ipv4/igmp.c	Fri Sep  1 14:31:56 1995
@@ -15,6 +15,14 @@
  *					the memory usage of all the tiny little
  *					functions.
  *		Alan Cox	:	Dumped the header building experiment.
+ *		Alan Cox	:	Minor tweaks ready for multicast routing
+ *					and extended IGMP protocol.
+ *		Alan Cox	:	Removed a load of inline directives. Gcc 2.5.8
+ *					writes utterly bogus code otherwise (sigh)
+ *					fixed IGMP loopback to behave in the manner
+ *					desired by mrouted, fixed the fact it has been
+ *					broken since 1.3.6 and cleaned up a few minor
+ *					points.
  */
  
  
@@ -47,7 +55,7 @@
  */
  
  
-extern __inline__ void igmp_stop_timer(struct ip_mc_list *im)
+static void igmp_stop_timer(struct ip_mc_list *im)
 {
 	del_timer(&im->timer);
 	im->tm_running=0;
@@ -64,7 +72,7 @@
  *	Inlined as its only called once.
  */
 
-extern __inline__ void igmp_start_timer(struct ip_mc_list *im)
+static void igmp_start_timer(struct ip_mc_list *im)
 {
 	int tv;
 	if(im->tm_running)
@@ -90,7 +98,7 @@
 	if(skb==NULL)
 		return;
 	tmp=ip_build_header(skb, INADDR_ANY, address, &dev, IPPROTO_IGMP, NULL,
-				skb->truesize, 0, 1);
+				28 , 0, 1);
 	if(tmp<0)
 	{
 		kfree_skb(skb, FREE_WRITE);
@@ -98,7 +106,7 @@
 	}
 	ih=(struct igmphdr *)skb_put(skb,sizeof(struct igmphdr));
 	ih->type=IGMP_HOST_MEMBERSHIP_REPORT;
-	ih->unused=0;
+	ih->code=0;
 	ih->csum=0;
 	ih->group=address;
 	ih->csum=ip_compute_csum((void *)ih,sizeof(struct igmphdr));	/* Checksum fill */
@@ -113,7 +121,7 @@
 	igmp_send_report(im->interface, im->multiaddr, IGMP_HOST_MEMBERSHIP_REPORT);
 }
 
-extern __inline__ void igmp_init_timer(struct ip_mc_list *im)
+static void igmp_init_timer(struct ip_mc_list *im)
 {
 	im->tm_running=0;
 	init_timer(&im->timer);
@@ -122,7 +130,7 @@
 }
 	
 
-extern __inline__ void igmp_heard_report(struct device *dev, unsigned long address)
+static void igmp_heard_report(struct device *dev, unsigned long address)
 {
 	struct ip_mc_list *im;
 	for(im=dev->ip_mc_list;im!=NULL;im=im->next)
@@ -130,12 +138,14 @@
 			igmp_stop_timer(im);
 }
 
-extern __inline__ void igmp_heard_query(struct device *dev)
+static void igmp_heard_query(struct device *dev)
 {
 	struct ip_mc_list *im;
 	for(im=dev->ip_mc_list;im!=NULL;im=im->next)
+	{
 		if(!im->tm_running && im->multiaddr!=IGMP_ALL_HOSTS)
 			igmp_start_timer(im);
+	}
 }
 
 /*
@@ -186,15 +196,13 @@
 	del_timer(&im->timer);
 	igmp_send_report(im->interface, im->multiaddr, IGMP_HOST_LEAVE_MESSAGE);
 	ip_mc_filter_del(im->interface, im->multiaddr);
-/*	printk("Left group %lX\n",im->multiaddr);*/
 }
 
 extern __inline__ void igmp_group_added(struct ip_mc_list *im)
 {
 	igmp_init_timer(im);
-	igmp_send_report(im->interface, im->multiaddr, IGMP_HOST_MEMBERSHIP_REPORT);
 	ip_mc_filter_add(im->interface, im->multiaddr);
-/*	printk("Joined group %lX\n",im->multiaddr);*/
+	igmp_send_report(im->interface, im->multiaddr, IGMP_HOST_MEMBERSHIP_REPORT);
 }
 
 int igmp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
@@ -204,9 +212,21 @@
 	/* This basically follows the spec line by line -- see RFC1112 */
 	struct igmphdr *ih;
 	
-	ih=(struct igmphdr *)skb->data;
+	/*
+	 *	Mrouted needs to able to query local interfaces. So
+	 *	report for the device this was sent at. (Which can
+	 *	be the loopback this time)
+	 */
+	 
+	if(dev->flags&IFF_LOOPBACK)
+	{
+		dev=ip_dev_find(saddr);
+		if(dev==NULL)
+			dev=&loopback_dev;
+	}
+	ih=(struct igmphdr *)skb->h.raw;
 		
-	if(skb->len <sizeof(struct igmphdr) || skb->ip_hdr->ttl!=1 || ip_compute_csum((void *)skb->h.raw,sizeof(struct igmphdr)))
+	if(skb->len <sizeof(struct igmphdr) || skb->ip_hdr->ttl>1 || ip_compute_csum((void *)skb->h.raw,sizeof(struct igmphdr)))
 	{
 		kfree_skb(skb, FREE_READ);
 		return 0;
@@ -307,6 +327,7 @@
 	i->users=1;
 	i->interface=dev;
 	i->multiaddr=IGMP_ALL_HOSTS;
+	i->tm_running=0;
 	i->next=dev->ip_mc_list;
 	dev->ip_mc_list=i;
 	ip_mc_filter_add(i->interface, i->multiaddr);
diff -u --recursive --new-file v1.3.21/linux/net/ipv4/ip.c linux/net/ipv4/ip.c
--- v1.3.21/linux/net/ipv4/ip.c	Mon Aug 28 14:52:26 1995
+++ linux/net/ipv4/ip.c	Fri Sep  1 14:31:56 1995
@@ -88,6 +88,8 @@
  *		Alan Cox	:	Fixed forwarding (by even more popular demand 8))
  *		Alan Cox	:	Fixed SNMP statistics [I think]
  *	Gerhard Koerting	:	IP fragmentation forwarding fix
+ *		Alan Cox	:	Device lock against page fault.
+ *		Alan Cox	:	IP_HDRINCL facility.
  *
  *  
  *
@@ -143,6 +145,7 @@
 #include <net/checksum.h>
 #include <linux/igmp.h>
 #include <linux/ip_fw.h>
+#include <linux/mroute.h>
 
 #define CONFIG_IP_DEFRAG
 
@@ -1523,8 +1526,7 @@
 	if ( iph->daddr == skb->dev->pa_addr || (brd = ip_chk_addr(iph->daddr)) != 0)
 	{
 #ifdef CONFIG_IP_MULTICAST	
-
-		if(brd==IS_MULTICAST && iph->daddr!=IGMP_ALL_HOSTS && !(dev->flags&IFF_LOOPBACK))
+		if(!(dev->flags&IFF_ALLMULTI) && brd==IS_MULTICAST && iph->daddr!=IGMP_ALL_HOSTS && !(dev->flags&IFF_LOOPBACK))
 		{
 			/*
 			 *	Check it is for one of our groups
@@ -1729,7 +1731,7 @@
 static void ip_loopback(struct device *old_dev, struct sk_buff *skb)
 {
 	struct device *dev=&loopback_dev;
-	int len=skb->len-old_dev->hard_header_len;
+	int len=ntohs(skb->ip_hdr->tot_len);
 	struct sk_buff *newskb=dev_alloc_skb(len+dev->hard_header_len+15);
 	
 	if(newskb==NULL)
@@ -1932,8 +1934,10 @@
 	{
 		if(sk==NULL || sk->ip_mc_loop)
 		{
-			if(iph->daddr==IGMP_ALL_HOSTS)
+			if(iph->daddr==IGMP_ALL_HOSTS || (dev->flags&IFF_ALLMULTI))
+			{
 				ip_loopback(dev,skb);
+			}
 			else
 			{
 				struct ip_mc_list *imc=dev->ip_mc_list;
@@ -1978,6 +1982,8 @@
 	}
 	else
 	{
+		if(sk)
+			sk->err = ENETDOWN;
 		ip_statistics.IpOutDiscards++;
 		if (free)
 			kfree_skb(skb, FREE_WRITE);
@@ -2069,18 +2075,28 @@
 	struct ip_fw tmp_fw;
 #endif	
 	if (optval == NULL)
-		return(-EINVAL);
-
-	err=verify_area(VERIFY_READ, optval, sizeof(int));
-	if(err)
-		return err;
-
-	val = get_user((int *) optval);
-	ucval=get_user((unsigned char *) optval);
-
+	{
+		val=0;
+		ucval=0;
+	}
+	else
+	{
+		err=verify_area(VERIFY_READ, optval, sizeof(int));
+		if(err)
+			return err;
+		val = get_user((int *) optval);
+		ucval=get_user((unsigned char *) optval);
+	}
+	
 	if(level!=SOL_IP)
 		return -EOPNOTSUPP;
-
+#ifdef CONFIG_IP_MROUTE
+	if(optname>=MRT_BASE && optname <=MRT_BASE+10)
+	{
+		return ip_mroute_setsockopt(sk,optname,optval,optlen);
+	}
+#endif
+	
 	switch(optname)
 	{
 		case IP_TOS:
@@ -2097,6 +2113,11 @@
 				return -EINVAL;
 			sk->ip_ttl=val;
 			return 0;
+		case IP_HDRINCL:
+			if(sk->type!=SOCK_RAW)
+				return -ENOPROTOOPT;
+			sk->ip_hdrincl=val?1:0;
+			return 0;
 #ifdef CONFIG_IP_MULTICAST
 		case IP_MULTICAST_TTL: 
 		{
@@ -2324,6 +2345,13 @@
 	if(level!=SOL_IP)
 		return -EOPNOTSUPP;
 
+#ifdef CONFIG_IP_MROUTE
+	if(optname>=MRT_BASE && optname <=MRT_BASE+10)
+	{
+		return ip_mroute_getsockopt(sk,optname,optval,optlen);
+	}
+#endif
+
 	switch(optname)
 	{
 		case IP_TOS:
@@ -2332,6 +2360,9 @@
 		case IP_TTL:
 			val=sk->ip_ttl;
 			break;
+		case IP_HDRINCL:
+			val=sk->ip_hdrincl;
+			break;
 #ifdef CONFIG_IP_MULTICAST			
 		case IP_MULTICAST_TTL:
 			val=sk->ip_mc_ttl;
@@ -2526,7 +2557,8 @@
 				skb->arp=1;
 		}
 		skb->ip_hdr=iph=(struct iphdr *)skb_put(skb,length);
-		if(type!=IPPROTO_RAW)
+		dev_lock_list();
+		if(!sk->ip_hdrincl)
 		{
 			iph->version=4;
 			iph->ihl=5;
@@ -2544,6 +2576,7 @@
 		}
 		else
 			getfrag(frag,saddr,(void *)iph,0,length);
+		dev_unlock_list();
 #ifdef CONFIG_IP_ACCT
 		ip_fw_chk((void *)skb->data,dev,ip_acct_chain, IP_FW_F_ACCEPT,1);
 #endif		
@@ -2559,7 +2592,7 @@
 			
 			
 	fragheaderlen = dev->hard_header_len;
-	if(type != IPPROTO_RAW)
+	if(!sk->ip_hdrincl)
 		fragheaderlen += 20;
 		
 	/*
@@ -2598,10 +2631,16 @@
 	 *	Can't fragment raw packets 
 	 */
 	 
-	if (type == IPPROTO_RAW && offset > 0)
+	if (sk->ip_hdrincl && offset > 0)
  		return(-EMSGSIZE);
 
 	/*
+	 *	Lock the device lists.
+	 */
+
+	dev_lock_list();
+	
+	/*
 	 *	Get an identifier
 	 */
 	 
@@ -2627,6 +2666,7 @@
 			ip_statistics.IpOutDiscards++;
 			if(nfrags>1)
 				ip_statistics.IpFragCreates++;			
+			dev_unlock_list();
 			return(error);
 		}
 		
@@ -2674,7 +2714,7 @@
 		 *	Only write IP header onto non-raw packets 
 		 */
 		 
-		if(type != IPPROTO_RAW) 
+		if(!sk->ip_hdrincl) 
 		{
 
 			iph->version = 4;
@@ -2732,11 +2772,13 @@
 			/*
 			 *	Loop back any frames. The check for IGMP_ALL_HOSTS is because
 			 *	you are always magically a member of this group.
+			 *
+			 *	Always loop back all host messages when running as a multicast router.
 			 */
 			 
-			if(sk==NULL || sk->ip_mc_loop) 
+			if(sk==NULL || sk->ip_mc_loop)
 			{
-				if(skb->daddr==IGMP_ALL_HOSTS)
+				if(skb->daddr==IGMP_ALL_HOSTS || (dev->flags&IFF_ALLMULTI))
 					ip_loopback(rt?rt->rt_dev:dev,skb);
 				else 
 				{
@@ -2784,22 +2826,25 @@
 		{
 			/*
 			 *	Whoops... 
-			 *
-			 *	FIXME:	There is a small nasty here. During the ip_build_xmit we could
-			 *	page fault between the route lookup and device send, the device might be
-			 *	removed and unloaded.... We need to add device locks on this.
 			 */
 			 
 			ip_statistics.IpOutDiscards++;
 			if(nfrags>1)
 				ip_statistics.IpFragCreates+=nfrags;
 			kfree_skb(skb, FREE_WRITE);
+			dev_unlock_list();
+			/*
+			 *	BSD behaviour.
+			 */
+			if(sk!=NULL)
+				sk->err=ENETDOWN;
 			return(0); /* lose rest of fragments */
 		}
 	} 
 	while (offset >= 0);
 	if(nfrags>1)
 		ip_statistics.IpFragCreates+=nfrags;
+	dev_unlock_list();
 	return(0);
 }
     
diff -u --recursive --new-file v1.3.21/linux/net/ipv4/ip_fw.c linux/net/ipv4/ip_fw.c
--- v1.3.21/linux/net/ipv4/ip_fw.c	Mon Aug 28 14:52:26 1995
+++ linux/net/ipv4/ip_fw.c	Fri Sep  1 14:31:56 1995
@@ -22,6 +22,8 @@
  *	Established connections (ACK check), ACK check on bidirectional rules,
  *	ICMP type check.
  *		Wilfred Mollenvanger 7/7/1995.
+ *	TCP attack protection.
+ *		Alan Cox 25/8/95, based on information from bugtraq.
  *
  * Masquerading functionality
  *
@@ -37,6 +39,9 @@
  *	Pauline Middelink	:	Added masquerading.
  *	Alan Cox		:	Fixed an error in the merge.
  *
+ * TODO:
+ *	Fix the PORT spoof crash.
+ *
  *	All the real work was done by .....
  *
  */
@@ -190,6 +195,7 @@
 	unsigned short		f_prt=0, prt;
 	char			notcpsyn=1, notcpack=1, frag1, match;
 	unsigned short		f_flag;
+	unsigned short		offset;
 
 	/*
 	 *	If the chain is empty follow policy. The BSD one
@@ -214,11 +220,38 @@
 	 *	of system.
 	 */
 
-	frag1 = ((ntohs(ip->frag_off) & IP_OFFSET) == 0);
+	offset = ntohs(ip->frag_off) & IP_OFFSET;
+	
+	frag1 = (offset == 0);
+
+	/*
+	 *	Don't allow a fragment of TCP 8 bytes in. Nobody
+	 *	normal causes this. Its a cracker trying to break
+	 *	in by doing a flag overwrite to pass the direction
+	 *	checks.
+	 */
+	 
+	if (offset == 1 && ip->protocol == IPPROTO_TCP)
+		return 0;
+		
 	if (!frag1 && (opt != 1) && (ip->protocol == IPPROTO_TCP ||
 			ip->protocol == IPPROTO_UDP))
 		return(1);
-
+		
+	/*
+	 *	 Header fragment for TCP is too small to check the bits.
+	 */
+	 
+	if(ip->protocol==IPPROTO_TCP && (ip->ihl<<2)+16 > ntohs(ip->tot_len))
+		return 0;
+	
+	/*
+	 *	Too short.
+	 */
+	 
+	else if(ntohs(ip->tot_len)<8+(ip->ihl<<2))
+		return 0;
+		
 	src = ip->saddr;
 	dst = ip->daddr;
 
diff -u --recursive --new-file v1.3.21/linux/net/ipv4/ipip.c linux/net/ipv4/ipip.c
--- v1.3.21/linux/net/ipv4/ipip.c	Fri Aug 18 08:44:59 1995
+++ linux/net/ipv4/ipip.c	Fri Sep  1 14:35:17 1995
@@ -9,6 +9,7 @@
  *					a module taking up 2 pages).
  *		Alan Cox	: 	Fixed bug with 1.3.18 and IPIP not working (now needs to set skb->h.iph)
  *					to keep ip_forward happy.
+ *		Alan Cox	:	More fixes for 1.3.21, and firewall fix. Maybe this will work soon 8).
  *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License
@@ -18,6 +19,7 @@
  */
  
 #include <linux/types.h>
+#include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
@@ -25,8 +27,12 @@
 #include <net/datalink.h>
 #include <net/sock.h>
 #include <net/ip.h>
+#include <net/icmp.h>
+#include <linux/tcp.h>
+#include <linux/udp.h>
 #include <net/protocol.h>
 #include <net/ipip.h>
+#include <linux/ip_fw.h>
 
 /*
  * NB. we must include the kernel idenfication string in to install the module.
@@ -46,19 +52,64 @@
 
 
 /*
- *	The driver.
+ *	The IPIP protocol driver.
+ *
+ *	On entry here
+ *		skb->data is the original IP header
+ *		skb->ip_hdr points to the initial IP header.
+ *		skb->h.raw points at the new header.
  */
 
 int ipip_rcv(struct sk_buff *skb, struct device *dev, struct options *opt, 
 		unsigned long daddr, unsigned short len, unsigned long saddr,
                                    int redo, struct inet_protocol *protocol)
 {
+#ifdef CONFIG_IP_FIREWALL
+	int err;
+#endif
 	/* Don't unlink in the middle of a turnaround */
 	MOD_INC_USE_COUNT;
 #ifdef TUNNEL_DEBUG
 	printk("ipip_rcv: got a packet!\n");
 #endif
-	skb->h.iph=skb->data;	/* Correct IP header pointer on to new header */
+	/*
+	 *	Discard the original IP header
+	 */
+	 
+	skb_pull(skb, ((struct iphdr *)skb->data)->ihl<<2);
+	
+	/*
+	 *	Adjust pointers
+	 */
+	 
+	skb->h.iph=(struct iphdr *)skb->data;
+	skb->ip_hdr=(struct iphdr *)skb->data;
+	
+#ifdef CONFIG_IP_FIREWALL
+	/*
+	 *	Check the firewall [well spotted Olaf]
+	 */
+	 
+	if((err=ip_fw_chk(skb->ip_hdr,dev,ip_fw_blk_chain, ip_fw_blk_policy,0))<1)
+	{
+		if(err==-1)
+			icmp_send(skb,ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0 , dev);
+		kfree_skb(skb, FREE_READ);
+		return 0;
+	}	
+#endif
+
+	/*
+	 *	If you want to add LZ compressed IP or things like that here,
+	 *	and in drivers/net/tunnel.c are the places to add.
+	 */
+	
+	/* skb=lzw_uncompress(skb); */
+	
+	/*
+	 *	Feed to IP forward.
+	 */
+	 
 	if(ip_forward(skb, dev, 0, daddr, 0))
 		kfree_skb(skb, FREE_READ);
 	MOD_DEC_USE_COUNT;
diff -u --recursive --new-file v1.3.21/linux/net/ipv4/ipmr.c linux/net/ipv4/ipmr.c
--- v1.3.21/linux/net/ipv4/ipmr.c	Thu Jan  1 02:00:00 1970
+++ linux/net/ipv4/ipmr.c	Fri Sep  1 16:32:40 1995
@@ -0,0 +1,287 @@
+/*
+ *	IP multicast routing support for mrouted 3.6
+ *
+ *		(c) 1995 Alan Cox, <alan@cymru.net>
+ *	  Linux Consultancy and Custom Driver Development
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	as published by the Free Software Foundation; either version
+ *	2 of the License, or (at your option) any later version.
+ */
+
+#include <asm/system.h>
+#include <asm/segment.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/kernel.h>
+#include <linux/fcntl.h>
+#include <linux/socket.h>
+#include <linux/in.h>
+#include <linux/inet.h>
+#include <linux/netdevice.h>
+#include <linux/mroute.h>
+#include <net/ip.h>
+#include <net/protocol.h>
+#include <linux/skbuff.h>
+#include <net/sock.h>
+#include <net/icmp.h>
+#include <net/udp.h>
+#include <net/checksum.h>
+
+#ifdef CONFIG_IP_MROUTE
+
+/*
+ *	Multicast router conrol variables
+ */
+
+static struct vif_device vif_table[MAXVIFS];
+static unsigned long vifc_map;
+int mroute_do_pim = 0;
+ 
+/*
+ *	Socket options and virtual interface manipulation. The whole
+ *	virtual interface system is a complete heap, but unfortunately
+ *	thats how BSD mrouted happens to think. Maybe one day with a proper
+ *	MOSPF/PIM router set up we can clean this up.
+ */
+ 
+int ip_mroute_setsockopt(struct sock *sk,int optname,char *optval,int optlen)
+{
+	int err;
+	struct vifctl vif;
+	
+	if(optname!=MRT_INIT)
+	{
+		if(sk!=mroute_socket)
+			return -EACCES;
+	}
+	
+	switch(optname)
+	{
+		case MRT_INIT:
+			if(sk->type!=SOCK_RAW || sk->num!=IPPROTO_IGMP)
+				return -EOPNOTSUPP;
+			if(optlen!=sizeof(int))
+				return -ENOPROTOOPT;
+			if((err=verify_area(VERIFY_READ,optval,sizeof(int)))<0)
+				return err;
+			if(get_user((int *)optval)!=1)
+				return -ENOPROTOOPT;
+			if(mroute_socket)
+				return -EADDRINUSE;
+			mroute_socket=sk;
+			/* Initialise state */
+			return 0;
+		case MRT_DONE:
+			mroute_close(sk);
+			mroute_socket=NULL;
+			return 0;
+		case MRT_ADD_VIF:
+		case MRT_DEL_VIF:
+			if(optlen!=sizeof(vif))
+				return -EINVAL;
+			if((err=verify_area(VERIFY_READ, optval, sizeof(vif)))<0)
+				return err;
+			memcpy_fromfs(&vif,optval,sizeof(vif));
+			if(vif.vifc_vifi > MAXVIFS)
+				return -ENFILE;
+			if(optname==MRT_ADD_VIF)
+			{
+				struct vif_device *v=&vif_table[vif.vifc_vifi];
+				struct device *dev;
+				/* Empty vif ? */
+				if(vifc_map&(1<<vif.vifc_vifi))
+					return -EADDRINUSE;
+				/* Find the interface */
+				dev=ip_dev_find(vif.vifc_lcl_addr.s_addr);
+				if(!dev)
+					return -EADDRNOTAVAIL;
+				/* Must be tunnelled or multicastable */
+				if(vif.vifc_flags&VIFF_TUNNEL)
+				{
+					if(vif.vifc_flags&VIFF_SRCRT)
+						return -EOPNOTSUPP;
+					/* IPIP will do all the work */
+				}
+				else
+				{
+					if(dev->flags&IFF_MULTICAST)
+					{
+						/* Most ethernet cards dont know
+						   how to do this yet.. */
+						dev->flags|=IFF_ALLMULTI;
+						dev_mc_upload(dev);
+					}
+					else
+					{
+						/* We are stuck.. */
+						return -EOPNOTSUPP;
+					}
+				}
+				/*
+				 *	Fill in the VIF structures
+				 */
+				cli();
+				v->rate_limit=vif.vifc_rate_limit;
+				v->local=vif.vifc_lcl_addr.s_addr;
+				v->remote=vif.vifc_rmt_addr.s_addr;
+				v->flags=vif.vifc_flags;
+				v->threshold=vif.vifc_threshold;
+				v->dev=dev;
+				v->bytes_in = 0;
+				v->bytes_out = 0;
+				v->pkt_in = 0;
+				v->pkt_out = 0;
+				vifc_map|=(1<<vif.vifc_vifi);
+				sti();
+				return 0;
+			}
+			else
+			/*
+			 *	VIF deletion
+			 */
+			{
+				struct vif_device *v=&vif_table[vif.vifc_vifi];
+				if(vifc_map&(1<<vif.vifc_vifi))
+				{
+					if(!(v->flags&VIFF_TUNNEL))
+					{
+						v->dev->flags&=~IFF_ALLMULTI;
+						dev_mc_upload(v->dev);
+					}
+					vifc_map&=~(1<<vif.vifc_vifi);
+					return 0;					
+				}
+				else
+					return -EADDRNOTAVAIL;
+			}
+		/*
+		 *	Manipulate the forwarding caches. These live
+		 *	in a sort of kernel/user symbiosis.
+		 */
+		case MRT_ADD_MFC:
+		case MRT_DEL_MFC:
+			return -EOPNOTSUPP;
+		/*
+		 *	Control PIM assert.
+		 */
+		case MRT_ASSERT:
+			if(optlen!=sizeof(int))
+				return -EINVAL;
+			if((err=verify_area(VERIFY_READ, optval,sizeof(int)))<0)
+				return err;
+			mroute_do_pim= (optval)?1:0;
+			return 0;
+		/*
+		 *	Spurious command, or MRT_VERSION which you cannot
+		 *	set.
+		 */
+		default:
+			return -EOPNOTSUPP;
+	}
+}
+
+/*
+ *	Getsock opt support for the multicast routing system.
+ */
+ 
+int ip_mroute_getsockopt(struct sock *sk,int optname,char *optval,int *optlen)
+{
+	int olr;
+	int err;
+
+	if(sk!=mroute_socket)
+		return -EACCES;
+	if(optname!=MRT_VERSION && optname!=MRT_ASSERT)
+		return -EOPNOTSUPP;
+	
+	olr=get_user(optlen);
+	if(olr!=sizeof(int))
+		return -EINVAL;
+	err=verify_area(VERIFY_WRITE, optval,sizeof(int));
+	if(err)
+		return err;
+	put_user(sizeof(int),optlen);
+	if(optname==MRT_VERSION)
+		put_user(0x0305,(int *)optval);
+	else
+		put_user(mroute_do_pim,(int *)optval);
+	return 0;
+}
+
+/*
+ *	The IP multicast ioctl support routines.
+ */
+ 
+int ipmr_ioctl(struct sock *sk, int cmd, unsigned long arg)
+{
+	int err;
+	struct sioc_sg_req sr;
+	struct sioc_vif_req vr;
+	struct vif_device *vif;
+	
+	switch(cmd)
+	{
+		case SIOCGETVIFCNT:
+			err=verify_area(VERIFY_WRITE, (void *)arg, sizeof(vr));
+			if(err)
+				return err;
+			memcpy_fromfs(&vr,(void *)arg,sizeof(sr));
+			if(vr.vifi>=MAXVIFS)
+				return -EINVAL;
+			vif=&vif_table[vr.vifi];
+			if(vifc_map&(1<<vr.vifi))
+			{
+				vr.icount=vif->pkt_in;
+				vr.ocount=vif->pkt_out;
+				vr.ibytes=vif->bytes_in;
+				vr.obytes=vif->bytes_out;
+				memcpy_tofs((void *)arg,&vr,sizeof(sr));
+				return 0;
+			}
+			return -EADDRNOTAVAIL;
+		case SIOCGETSGCNT:
+			err=verify_area(VERIFY_WRITE, (void *)arg, sizeof(sr));
+			if(err)
+				return err;
+			memcpy_fromfs(&sr,(void *)arg,sizeof(sr));
+			memcpy_tofs((void *)arg,&sr,sizeof(sr));
+			return 0;
+		default:
+			return -EINVAL;
+	}
+}
+
+/*
+ *	Close the multicast socket, and clear the vif tables etc
+ */
+ 
+void mroute_close(struct sock *sk)
+{
+	int i;
+	struct vif_device *v=&vif_table[0];
+		
+	/*
+	 *	Shut down all active vif entries
+	 */
+	 
+	for(i=0;i<MAXVIFS;i++)
+	{
+		if(vifc_map&(1<<i))
+		{
+			if(!(v->flags&VIFF_TUNNEL))
+			{
+				v->dev->flags&=~IFF_ALLMULTI;
+				dev_mc_upload(v->dev);
+			}
+		}
+		v++;
+	}		
+	vifc_map=0;	
+}
+
+#endif
diff -u --recursive --new-file v1.3.21/linux/net/ipv4/protocol.c linux/net/ipv4/protocol.c
--- v1.3.21/linux/net/ipv4/protocol.c	Tue Jun  6 12:16:44 1995
+++ linux/net/ipv4/protocol.c	Fri Sep  1 14:31:56 1995
@@ -15,6 +15,7 @@
  *				  udp_err is never called!
  *		Alan Cox	: Added new fields for init and ready for
  *				  proper fragmentation (_NO_ 4K limits!)
+ *		Richard Colella	: Hang on hash collision
  *
  *		This program is free software; you can redistribute it and/or
  *		modify it under the terms of the GNU General Public License
@@ -155,7 +156,7 @@
 		prot->copy = 1;
 		break;
 	}
-	p2 = (struct inet_protocol *) prot->next;
+	p2 = (struct inet_protocol *) p2->next;
   }
 }
 
diff -u --recursive --new-file v1.3.21/linux/net/ipv4/raw.c linux/net/ipv4/raw.c
--- v1.3.21/linux/net/ipv4/raw.c	Wed Aug  2 13:21:18 1995
+++ linux/net/ipv4/raw.c	Fri Sep  1 14:55:07 1995
@@ -27,6 +27,8 @@
  *		Alan Cox	:	Use new kernel side addresses
  *	Arnt Gulbrandsen	:	Fixed MSG_DONTROUTE in raw sockets.
  *		Alan Cox	:	BSD style RAW socket demultiplexing.
+ *		Alan Cox	:	Beginnings of mrouted support.
+ *		Alan Cox	:	Added IP_HDRINCL option.
  *
  *		This program is free software; you can redistribute it and/or
  *		modify it under the terms of the GNU General Public License
@@ -46,6 +48,7 @@
 #include <linux/in.h>
 #include <linux/inet.h>
 #include <linux/netdevice.h>
+#include <linux/mroute.h>
 #include <net/ip.h>
 #include <net/protocol.h>
 #include <linux/skbuff.h>
@@ -54,6 +57,10 @@
 #include <net/udp.h>
 #include <net/checksum.h>
 
+#ifdef CONFIG_IP_MROUTE
+struct sock *mroute_socket=NULL;
+#endif
+
 static inline unsigned long min(unsigned long a, unsigned long b)
 {
 	if (a < b) 
@@ -199,7 +206,7 @@
 	if (sk->broadcast == 0 && ip_chk_addr(sin.sin_addr.s_addr)==IS_BROADCAST)
 		return -EACCES;
 
-	if(sk->num==IPPROTO_RAW)
+	if(sk->ip_hdrincl)
 		err=ip_build_xmit(sk, raw_getrawfrag, from, len, sin.sin_addr.s_addr, flags, sin.sin_port);
 	else
 		err=ip_build_xmit(sk, raw_getfrag, from, len, sin.sin_addr.s_addr, flags, sin.sin_port);
@@ -217,6 +224,13 @@
 static void raw_close(struct sock *sk, int timeout)
 {
 	sk->state = TCP_CLOSE;
+#ifdef CONFIG_IP_MROUTE	
+	if(sk==mroute_socket)
+	{
+		mroute_close(sk);
+		mroute_socket=NULL;
+	}
+#endif	
 }
 
 
@@ -238,7 +252,6 @@
 	int copied=0;
 	struct sk_buff *skb;
 	int err;
-	int truesize;
 
 	if (flags & MSG_OOB)
 		return -EOPNOTSUPP;
@@ -253,9 +266,8 @@
 	if(skb==NULL)
  		return err;
 
-	truesize=skb->len;
-	copied = min(len, truesize);
-  
+	copied = min(len, skb->len);
+	
 	skb_copy_datagram(skb, 0, to, copied);
 	sk->stamp=skb->stamp;
 
@@ -267,7 +279,7 @@
 	}
 	skb_free_datagram(skb);
 	release_sock(sk);
-	return (truesize);	/* len not copied. BSD returns the true size of the message so you know a bit fell off! */
+	return (copied);
 }
 
 
@@ -298,7 +310,11 @@
 	NULL,
 	NULL,
 	datagram_select,
+#ifdef CONFIG_IP_MROUTE	
+	ipmr_ioctl,
+#else
 	NULL,
+#endif		
 	raw_init,
 	NULL,
 	ip_setsockopt,
diff -u --recursive --new-file v1.3.21/linux/net/ipv4/tcp.c linux/net/ipv4/tcp.c
--- v1.3.21/linux/net/ipv4/tcp.c	Mon Aug 28 14:52:26 1995
+++ linux/net/ipv4/tcp.c	Thu Aug 31 08:14:43 1995
@@ -879,22 +879,21 @@
 		return;
 	}
 
-/*	sk->err = icmp_err_convert[err & 0xff].errno;  -- moved as TCP should hide non fatals internally (and does) */
-
 	/*
 	 * If we've already connected we will keep trying
 	 * until we time out, or the user gives up.
 	 */
 
-	if (err < 13 && (icmp_err_convert[err & 0xff].fatal || sk->state == TCP_SYN_SENT))
+	err &= 0xff;
+	if (err < 13 && (icmp_err_convert[err].fatal || sk->state == TCP_SYN_SENT))
 	{
+		sk->err = icmp_err_convert[err].errno;
 		if (sk->state == TCP_SYN_SENT) 
 		{
 			tcp_statistics.TcpAttemptFails++;
 			tcp_set_state(sk,TCP_CLOSE);
 			sk->error_report(sk);		/* Wake people up to see the error (see connect in sock.c) */
 		}
-		sk->err = icmp_err_convert[err & 0xff].errno;		
 	}
 	return;
 }
diff -u --recursive --new-file v1.3.21/linux/net/ipv4/udp.c linux/net/ipv4/udp.c
--- v1.3.21/linux/net/ipv4/udp.c	Mon Aug 28 14:52:26 1995
+++ linux/net/ipv4/udp.c	Thu Aug 31 08:30:55 1995
@@ -189,9 +189,10 @@
 	/* 4.1.3.3. */
 	/* After the comment above, that should be no surprise. */
 
-	if (err < 13 && icmp_err_convert[err & 0xff].fatal)
+	err &= 0xff;
+	if (err < 13 && icmp_err_convert[err].fatal)
 	{
-		sk->err = icmp_err_convert[err & 0xff].errno;
+		sk->err = icmp_err_convert[err].errno;
 		sk->error_report(sk);
 	}
 }
diff -u --recursive --new-file v1.3.21/linux/net/unix/af_unix.c linux/net/unix/af_unix.c
--- v1.3.21/linux/net/unix/af_unix.c	Mon Aug 28 14:52:27 1995
+++ linux/net/unix/af_unix.c	Thu Aug 31 08:09:07 1995
@@ -524,6 +524,7 @@
 		sk->protinfo.af_unix.other->protinfo.af_unix.locks--;
 		sk->protinfo.af_unix.other=NULL;
 		sock->state=SS_UNCONNECTED;
+		sti();
 		return -ECONNREFUSED;
 	}
 	
@@ -532,6 +533,7 @@
 	 */
 	 
 	sock->state=SS_CONNECTED;
+	sti();
 	return 0;
 	
 }
@@ -722,6 +724,7 @@
 			other->protinfo.af_unix.locks--;
 			sk->protinfo.af_unix.other=NULL;
 			sock->state=SS_UNCONNECTED;
+			sti();
 			return -ECONNRESET;
 		}
 	}
@@ -732,6 +735,7 @@
 		if(other==NULL)
 		{
 			kfree_skb(skb, FREE_WRITE);
+			sti();
 			return err;
 		}
 	}
@@ -790,11 +794,18 @@
 			{
 				up(&sk->protinfo.af_unix.readsem);
 				if(sk->shutdown & RCV_SHUTDOWN)
+				{
+					sti();
 					return copied;
+				}
 				if(copied)
+				{
+					sti();
 					return copied;
+				}
 				if(noblock)
 				{
+					sti();
 					return -EAGAIN;
 				}
 				sk->socket->flags |= SO_WAITDATA;
@@ -845,6 +856,7 @@
 						break;
 				}
 			}
+			sti();
 		}	
 	}	
 	up(&sk->protinfo.af_unix.readsem);
diff -u --recursive --new-file v1.3.21/linux/scripts/Configure linux/scripts/Configure
--- v1.3.21/linux/scripts/Configure	Tue Aug 15 20:39:12 1995
+++ linux/scripts/Configure	Tue Aug 29 10:15:53 1995
@@ -55,6 +55,22 @@
 }
 
 #
+# define_bool sets the value of a boolean argument
+#
+#	define_bool define value
+#
+function define_bool () {
+	if [ "$2" = "y" ]; then
+		echo "$1=y" >>$CONFIG
+		echo "#define $1 1" >>$CONFIG_H
+	else
+		echo "# $1 is not set" >>$CONFIG
+		echo "#undef  $1" >>$CONFIG_H
+	fi
+	eval "$1=$2"
+}
+
+#
 # bool processes a boolean argument
 #
 #	bool question define default
@@ -65,14 +81,18 @@
 	while [ "$ans" != "y" -a "$ans" != "n" ]; do
 		readln "$1 ($2) [$def] " "$def"
 	done
-	if [ "$ans" = "y" ]; then
-		echo "$2=y" >>$CONFIG
-		echo "#define $2 1" >>$CONFIG_H
-	else
-		echo "# $2 is not set" >>$CONFIG
-		echo "#undef  $2" >>$CONFIG_H
-	fi
-	eval "$2=$ans"
+	define_bool "$2" "$ans"
+}
+
+#
+# define_int sets the value of a integer argument
+#
+#	define_int define value
+#
+function define_int () {
+	echo "$1=$2" >>$CONFIG
+	echo "#define $1 ($2)" >>$CONFIG_H
+	eval "$1=$2"
 }
 
 #
@@ -87,9 +107,71 @@
 	while [ $[$ans+0] != "$ans" ]; do
 		readln "$1 ($2) [$def] " "$def"
 	done
-	echo "$2=$ans" >>$CONFIG
-	echo "#define $2 ($ans)" >>$CONFIG_H
-	eval "$2=$ans"
+	define_int "$2" "$ans"
+}
+
+#
+# choice processes a choice list (1-out-of-n)
+#
+#	choice question choice-list default
+#
+# The choice list has a syntax of:
+#	NAME:VALUE { WHITESPACE '|' NAME:VALUE }
+# The user may enter any unique prefix of one of the NAMEs and
+# choice will define VALUE as if it were a boolean option.
+# VALUE must be in all uppercase.  Normally, VALUE is of the
+# form CONFIG_<something>.  Thus, if the user selects <something>,
+# the CPP symbol CONFIG_<something> will be defined and the
+# shell variable CONFIG_<something> will be set to "y".
+#
+function choice () {
+	question="$1"
+	choices="$2"
+	def="$3"
+
+	# determine default answer:
+	names=""
+	set -- $choices
+	while [ -n "$2" ]; do
+		if [ -n "$names" ]; then
+			names="$names, $1"
+		else
+			names="$1"
+		fi
+		if [ "$(eval echo \"\${$2}\")" = "y" ]; then
+			def=$1
+		fi
+		shift; shift
+	done
+
+	val=""
+	while [ -z "$val" ]; do
+		readln "$question ($names) [$def] " "$def"
+		ans=$(echo $ans | tr a-z A-Z)
+		set -- $choices
+		val=""
+		while [ -n "$1" ]; do
+			name=$(echo $1 | tr a-z A-Z)
+			case "$name" in
+				${ans}*)
+					if [ "$name" = "$ans" ]; then
+						val="$2"
+						break	# stop on exact match
+					fi
+					if [ -n "$val" ]; then
+						echo \
+		"  Sorry, \"$ans\" is ambiguous; please enter a longer string."
+						val=""
+						break
+					else
+						val="$2"
+					fi;;
+			esac
+			shift; shift
+		done
+	done
+	echo "  defining $val"
+	define_bool "$val" "y"
 }
 
 CONFIG=.tmpconfig
diff -u --recursive --new-file v1.3.21/linux/versions.mk linux/versions.mk
--- v1.3.21/linux/versions.mk	Mon Aug 28 14:52:27 1995
+++ linux/versions.mk	Thu Aug 31 08:09:24 1995
@@ -15,7 +15,7 @@
 	$(CC) $(CFLAGS) -E -DCONFIG_MODVERSIONS -D__GENKSYMS__ $< | /sbin/genksyms -w $(TOPINCL)/modules
 	@ln -sf $(TOPINCL)/modules/$@ .
 
-$(SYMTAB_OBJS):
+$(SYMTAB_OBJS): $(TOPINCL)/modversions.h
 	$(CC) $(CFLAGS) -DEXPORT_SYMTAB -c $(@:.o=.c)
 
 $(SYMTAB_OBJS:.o=.ver): $(TOPINCL)/autoconf.h
