]> git.neil.brown.name Git - history.git/commitdiff
Import 1.3.22 1.3.22
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:10:12 +0000 (15:10 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:10:12 +0000 (15:10 -0500)
186 files changed:
CREDITS
Documentation/devices.tex [new file with mode: 0644]
Documentation/devices.txt [new file with mode: 0644]
Documentation/filesystems/hpfs.txt [new file with mode: 0644]
Documentation/filesystems/smbfs.txt [new file with mode: 0644]
Documentation/filesystems/sysv-fs.txt [new file with mode: 0644]
Documentation/filesystems/umsdos.txt [new file with mode: 0644]
Documentation/modules.txt [new file with mode: 0644]
Documentation/networking/arcnet-jumpers.txt [new file with mode: 0644]
Documentation/networking/arcnet.txt [new file with mode: 0644]
Documentation/networking/ax25.txt [new file with mode: 0644]
Documentation/networking/net-modules.txt [new file with mode: 0644]
Documentation/networking/tcp.txt [new file with mode: 0644]
Documentation/unicode.txt [new file with mode: 0644]
Makefile
README
README.modules [deleted file]
arch/alpha/Makefile
arch/alpha/boot/Makefile
arch/alpha/boot/bootloader.lds
arch/alpha/config.in
arch/alpha/kernel/Makefile
arch/alpha/kernel/apecs.c [new file with mode: 0644]
arch/alpha/kernel/bios32.c
arch/alpha/kernel/entry.S
arch/alpha/kernel/irq.c
arch/alpha/kernel/lca.c
arch/alpha/kernel/process.c
arch/alpha/kernel/ptrace.c
arch/alpha/kernel/setup.c
arch/alpha/kernel/signal.c
arch/alpha/kernel/traps.c
arch/i386/config.in
arch/i386/kernel/irq.c
arch/i386/kernel/process.c
arch/i386/kernel/ptrace.c
arch/i386/kernel/vm86.c
arch/i386/mm/init.c
arch/mips/kernel/process.c
arch/mips/kernel/ptrace.c
arch/mips/mm/init.c
arch/sparc/kernel/process.c
arch/sparc/mm/loadmmu.c
arch/sparc/mm/srmmu.c
arch/sparc/mm/sun4c.c
drivers/block/README.aztcd
drivers/block/README.ide
drivers/block/README.mcd
drivers/block/README.mcdx
drivers/block/aztcd.c
drivers/block/blk.h
drivers/block/cdu31a.c
drivers/block/cm206.c
drivers/block/floppy.c
drivers/block/genhd.c
drivers/block/ide.c
drivers/block/ide.h
drivers/block/mcd.c
drivers/block/mcdx.c
drivers/block/optcd.c
drivers/block/sbpcd.c
drivers/block/sjcd.c
drivers/block/triton.c
drivers/char/README.scc
drivers/char/README.unicode [deleted file]
drivers/char/console.c
drivers/char/cyclades.c
drivers/char/lp.c
drivers/char/mem.c
drivers/char/psaux.c
drivers/char/scc.c
drivers/char/scc_config.h
drivers/char/serial.c
drivers/char/tpqic02.c
drivers/net/3c503.c
drivers/net/3c505.c
drivers/net/README.arcnet [deleted file]
drivers/net/README.arcnet-jumpers [deleted file]
drivers/net/README.modules [deleted file]
drivers/net/de600.c
drivers/net/eql.c
drivers/net/net_init.c
drivers/net/ppp.c
drivers/pci/pci.c
drivers/scsi/53c7,8xx.c
drivers/scsi/README.st
drivers/scsi/aha1542.c
drivers/scsi/eata.c
drivers/scsi/eata_dma.c
drivers/scsi/eata_pio.c
drivers/scsi/st.c
drivers/scsi/st.h
drivers/scsi/st_options.h [new file with mode: 0644]
drivers/scsi/u14-34f.c
fs/Makefile
fs/binfmt_elf.c
fs/buffer.c
fs/exec.c
fs/hpfs/README [deleted file]
fs/hpfs/hpfs_caps.c
fs/hpfs/hpfs_fs.c
fs/nfs/cache.c
fs/open.c
fs/proc/array.c
fs/proc/inode.c
fs/proc/mem.c
fs/select.c
fs/smbfs/README [deleted file]
fs/super.c
fs/sysv/README [deleted file]
fs/umsdos/README [deleted file]
include/asm-alpha/apecs.h [new file with mode: 0644]
include/asm-alpha/bitops.h
include/asm-alpha/hwrpb.h
include/asm-alpha/io.h
include/asm-alpha/lca.h
include/asm-alpha/page.h
include/asm-alpha/string.h
include/asm-alpha/types.h
include/asm-alpha/unistd.h
include/asm-i386/io.h
include/asm-i386/ioctl.h [new file with mode: 0644]
include/asm-i386/page.h
include/asm-i386/types.h
include/asm-mips/page.h
include/asm-sparc/page.h
include/linux/aztcd.h
include/linux/binfmts.h
include/linux/cdrom.h
include/linux/cdu31a.h
include/linux/elf.h
include/linux/interrupt.h
include/linux/ioctl.h
include/linux/major.h
include/linux/malloc.h
include/linux/mcd.h
include/linux/mcdx.h
include/linux/mroute.h [new file with mode: 0644]
include/linux/mtio.h
include/linux/netdevice.h
include/linux/nfs_fs.h
include/linux/pci.h
include/linux/scc.h
include/linux/sched.h
include/linux/socket.h
include/linux/sonycd535.h
include/linux/timex.h
include/linux/types.h
include/linux/user.h
include/linux/xd.h
include/net/sock.h
init/main.c
ipc/shm.c
kernel/exit.c
kernel/fork.c
kernel/ksyms.c
kernel/sched.c
kernel/sys.c
kernel/time.c
mm/filemap.c
mm/kmalloc.c
mm/memory.c
mm/mprotect.c
mm/swap.c
mm/vmalloc.c
net/Changes
net/README
net/ax25/README.AX25 [deleted file]
net/core/dev.c
net/ipv4/Makefile
net/ipv4/README.TCP [deleted file]
net/ipv4/af_inet.c
net/ipv4/arp.c
net/ipv4/devinet.c
net/ipv4/igmp.c
net/ipv4/ip.c
net/ipv4/ip_fw.c
net/ipv4/ipip.c
net/ipv4/ipmr.c [new file with mode: 0644]
net/ipv4/protocol.c
net/ipv4/raw.c
net/ipv4/tcp.c
net/ipv4/udp.c
net/unix/af_unix.c
scripts/Configure
versions.mk

diff --git a/CREDITS b/CREDITS
index 69bf9accae28015f642674da8843b44e3ab0ad8a..98ba55d838ae7a5c1dca0c15a8bc8cdd275ed922 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -522,8 +522,9 @@ S: Germany
 
 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 --git a/Documentation/devices.tex b/Documentation/devices.tex
new file mode 100644 (file)
index 0000000..210eeec
--- /dev/null
@@ -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 --git a/Documentation/devices.txt b/Documentation/devices.txt
new file mode 100644 (file)
index 0000000..17c897d
--- /dev/null
@@ -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 --git a/Documentation/filesystems/hpfs.txt b/Documentation/filesystems/hpfs.txt
new file mode 100644 (file)
index 0000000..7e4fe88
--- /dev/null
@@ -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 --git a/Documentation/filesystems/smbfs.txt b/Documentation/filesystems/smbfs.txt
new file mode 100644 (file)
index 0000000..937262d
--- /dev/null
@@ -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 --git a/Documentation/filesystems/sysv-fs.txt b/Documentation/filesystems/sysv-fs.txt
new file mode 100644 (file)
index 0000000..d318eb6
--- /dev/null
@@ -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 --git a/Documentation/filesystems/umsdos.txt b/Documentation/filesystems/umsdos.txt
new file mode 100644 (file)
index 0000000..320dac6
--- /dev/null
@@ -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 --git a/Documentation/modules.txt b/Documentation/modules.txt
new file mode 100644 (file)
index 0000000..c7b976c
--- /dev/null
@@ -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 --git a/Documentation/networking/arcnet-jumpers.txt b/Documentation/networking/arcnet-jumpers.txt
new file mode 100644 (file)
index 0000000..09c4a69
--- /dev/null
@@ -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 --git a/Documentation/networking/arcnet.txt b/Documentation/networking/arcnet.txt
new file mode 100644 (file)
index 0000000..0ff778b
--- /dev/null
@@ -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 --git a/Documentation/networking/ax25.txt b/Documentation/networking/ax25.txt
new file mode 100644 (file)
index 0000000..c7ebdf4
--- /dev/null
@@ -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 --git a/Documentation/networking/net-modules.txt b/Documentation/networking/net-modules.txt
new file mode 100644 (file)
index 0000000..4961083
--- /dev/null
@@ -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 --git a/Documentation/networking/tcp.txt b/Documentation/networking/tcp.txt
new file mode 100644 (file)
index 0000000..f18963f
--- /dev/null
@@ -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 --git a/Documentation/unicode.txt b/Documentation/unicode.txt
new file mode 100644 (file)
index 0000000..2e32052
--- /dev/null
@@ -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.
index 421cc33d3a7b55e3b967c972d516a7e0c36b123d..da24d67a3171ee45897c4c663637e5267ab923d6 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 1
 PATCHLEVEL = 3
-SUBLEVEL = 21
+SUBLEVEL = 22
 
 ARCH = i386
 
diff --git a/README b/README
index af6c437ae3fae6fb974a3b4e9db344e446ae32c9..621085eea7af5b5870c2fc15a0195e998552fbcf 100644 (file)
--- a/README
+++ b/README
@@ -42,6 +42,10 @@ DOCUMENTATION:
    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 --git a/README.modules b/README.modules
deleted file mode 100644 (file)
index 4c2c629..0000000
+++ /dev/null
@@ -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>
index beff9f4ed755d4d5ec3176a6a1ce43f7170a29ef..a09d02bc6ff5b7ab3fcf821c073151773bd36e95 100644 (file)
 
 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
index c4cbe4f5dc836fe275809fe5e1217474064819c3..61801b661f07764966cf70b4f7c8cf79af241bf3 100644 (file)
@@ -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 @@ tools/build: tools/build.c
        $(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:
index 5f459ca818576902d53ac881ab477b777a69b36f..77806e69f0f7c933c91432a1afc9faa1d3db9f82 100644 (file)
@@ -40,6 +40,7 @@ SECTIONS
   .sbss : {
     *(.sbss)
     *(.scommon)
+    . = ALIGN(16);
   }
   .bss : {
     *(.bss)
index 95276a3a8431ee84567f78f85e21c1e6ebc35fb2..acf96a95428c7b9ee1d0b0cefc50a4bbfc21c026 100644 (file)
@@ -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 @@ fi
 
 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
index a7e2f302c023393d524161d195374f7c3b21b638..c5ae09bd226428d5bd0d2c7ba74609bd31eab9b8 100644 (file)
@@ -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 --git a/arch/alpha/kernel/apecs.c b/arch/alpha/kernel/apecs.c
new file mode 100644 (file)
index 0000000..f6bbdce
--- /dev/null
@@ -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 */
index ae9d44a608246577007d447bf23f7c565402d42d..2651a396d2dc8d64bedd293178bfe27b384339d0 100644 (file)
@@ -49,7 +49,7 @@ int pcibios_present(void)
 #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 @@ static void layout_dev(struct pci_dev *dev)
                }
         }
        /* 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 @@ unsigned long pcibios_init(unsigned long mem_start,
        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 @@ static void noname_fixup(void)
        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 @@ static void noname_fixup(void)
 
                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 @@ static void noname_fixup(void)
        }
 #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 @@ unsigned long pcibios_fixup(unsigned long mem_start, unsigned long mem_end)
        /*
         * 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];
 
index 90519b929c3240a55a5192ff579d5ac07f4ec54c..b8da79343c9adf8df79b3afc6c5a09c3dc0a3e2f 100644 (file)
 #define TASK_BLOCKED   32
 #define TASK_FLAGS     40
 
+/*
+ * task flags (must match include/linux/sched.h):
+ */
+#define        PF_PTRACED      0x00000010
+
 /*
  * This defines the normal kernel pt-regs layout.
  *
@@ -373,9 +378,27 @@ entUnaUser:
        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 @@ entSys:
        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 @@ ret_from_reschedule:
 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 @@ signal_return:
 .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 @@ sys_sigsuspend:
        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 @@ sys_call_table:
        .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 @@ sys_call_table:
 /* 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
 
index e819f89635722730d6476e51db7e06877e9b8903..e90527a9007977e53232d99139ec8f1a3eea57a0 100644 (file)
 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 @@ void enable_irq(unsigned int irq_nr)
 
        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 @@ struct irqaction {
        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 @@ int get_irq_list(char *buf)
 
 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 @@ int request_irq(unsigned int irq, void (*handler)(int, struct pt_regs *),
        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 @@ int request_irq(unsigned int irq, void (*handler)(int, struct pt_regs *),
        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 @@ void free_irq(unsigned int irq)
        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 @@ void free_irq(unsigned int irq)
        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 @@ static inline void handle_irq(int irq, struct pt_regs * regs)
        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);
+}
 
-static void local_device_interrupt(unsigned long vector, struct pt_regs * regs)
+/*
+ * Handle ISA interrupt via the PICs.
+ */
+static inline void isa_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 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);
+       }
+}
 
-               /* com2: map to irq 3 */
-               case 0x920:
-                       handle_irq(3, regs);
-                       return;
+static inline void cabriolet_and_eb66p_device_interrupt(unsigned long vector,
+                                                       struct pt_regs * regs)
+{
+       unsigned long pld;
+       unsigned int i;
+       unsigned long flags;
 
-               /* keyboard: map to irq 1 */
-               case 0x980:
-                       handle_irq(1, regs);
-                       return;
+       save_flags(flags);
+       cli();
 
-               /* mouse: map to irq 9 */
-               case 0x990:
-                       handle_irq(9, regs);
-                       return;
-               default:
-                       printk("Unknown local interrupt %lx\n", vector);
+       /* read the interrupt summary registers */
+       pld = inb(0x804) | (inb(0x805) << 8) | (inb(0x806) << 16);
+
+       /*
+        * 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 @@ static void local_device_interrupt(unsigned long vector, struct pt_regs * regs)
  *     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 @@ unsigned int probe_irq_on(void)
                /* 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 @@ unsigned int probe_irq_on(void)
  * 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 @@ asmlinkage void do_entInt(unsigned long type, unsigned long vector, unsigned lon
                        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 @@ void init_IRQ(void)
        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
 }
index c32c308fb1f66aa808c9a6dc5f12f412f2e3a3d0..3ae016bd1faf42991fc6796f278cdabb5d3a706f 100644 (file)
@@ -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 @@ static int mk_conf_addr(unsigned char bus, unsigned char device_fn,
 
                if (device > 12) {
                        return -1;
-               } /* if */
+               }
 
                *((volatile unsigned long*) LCA_IOC_CONF) = 0;
                addr = (1 << (11 + device)) | (func << 8) | where;
@@ -84,19 +85,19 @@ static int mk_conf_addr(unsigned char bus, unsigned char device_fn,
                /* 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 @@ static unsigned int conf_read(unsigned long addr)
 
                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 @@ static void conf_write(unsigned long addr, unsigned int value)
                mb();
                wrmces(0x7);                    /* reset machine check */
        }
-       swpipl(old_ipl);
+       restore_flags(flags);
 }
 
 
@@ -172,12 +173,9 @@ int pcibios_read_config_byte (unsigned char bus, unsigned char device_fn,
 
        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 @@ int pcibios_read_config_word (unsigned char bus, unsigned char device_fn,
 
        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 @@ int pcibios_read_config_dword (unsigned char bus, unsigned char device_fn,
        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 @@ int pcibios_write_config_byte (unsigned char bus, unsigned char device_fn,
 
        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 @@ int pcibios_write_config_word (unsigned char bus, unsigned char device_fn,
 
        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 @@ int pcibios_write_config_dword (unsigned char bus, unsigned char device_fn,
 
        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 @@ unsigned long lca_init(unsigned long mem_start, unsigned long mem_end)
        *(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 */
index b9d91d424d7945ab692c539784b35270744cf5a2..aa46e9d5523c9a27611518a60a100d5fdc765947 100644 (file)
@@ -91,9 +91,7 @@ void flush_thread(void)
  */
 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 @@ asmlinkage int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
  * 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);
 }
index 8e37b0722f9299ed8593665cc202293b4b8e21f9..09cc776cb2c3400f15260cbcc567305da1c2f4d4 100644 (file)
@@ -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;
 
 #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 @@ static inline struct task_struct * get_task(int pid)
 }
 
 /*
- * 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 @@ static unsigned long get_long(struct vm_area_struct * vma, unsigned long addr)
        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 @@ repeat:
                *(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 @@ static int read_long(struct task_struct * tsk, unsigned long addr,
 {
        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 @@ static int write_long(struct task_struct * tsk, unsigned long addr,
        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 @@ static int write_long(struct task_struct * tsk, unsigned long addr,
                        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 @@ static int write_long(struct task_struct * tsk, unsigned long addr,
 /*
  * 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 @@ static int read_int(struct task_struct * tsk, unsigned long addr, unsigned int *
  * 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;
@@ -440,37 +408,16 @@ static int write_int(struct task_struct * tsk, unsigned long addr, unsigned int
        return write_long(tsk, addr, l);
 }
 
-/*
- * 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 @@ static int set_bpt(struct task_struct *child)
                 */
                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 @@ static int set_bpt(struct task_struct *child)
        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 @@ int ptrace_cancel_bpt(struct task_struct *child)
        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 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data, int a4,
        }
        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;
-                 }
-
-               case PTRACE_SYSCALL: /* continue and stop at next 
+                       DBG(DBG_MEM, ("poke $%ld<-%#lx\n", addr, data));
+                       return put_reg(child, addr, data);
+
+               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 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data, int a4,
                        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 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data, int a4,
                }
 
                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 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data, int a4,
                }
 
                default:
-                 set_failure(&regs,-EIO);
                  return -EIO;
          }
 }
index db648776a2c81b3197c1edfcf1ecabbdaec10aec..0608c2956fec07dff53a7e6959256f0d1e367448 100644 (file)
@@ -73,7 +73,8 @@ static unsigned long find_end_memory(void)
        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 @@ void setup_arch(char **cmdline_p,
 
        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 @@ void setup_arch(char **cmdline_p,
        *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 @@ int get_cpuinfo(char *buffer)
        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 @@ int get_cpuinfo(char *buffer)
                       "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 @@ int get_cpuinfo(char *buffer)
                       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
 }
index 0199e29704b4c7b21fd8dd83c0efa6f4003cb9e1..8bac950eec7e9bb0dadb4bf78a574597d83015ac 100644 (file)
@@ -25,6 +25,9 @@ asmlinkage int do_signal(unsigned long, struct pt_regs *, struct switch_stack *,
        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 @@ asmlinkage void do_sigreturn(struct sigcontext_struct * sc,
        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 @@ asmlinkage int do_signal(unsigned long oldmask,
        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 @@ asmlinkage int do_signal(unsigned long oldmask,
                        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 @@ asmlinkage int do_signal(unsigned long oldmask,
                                                SA_NOCLDSTOP))
                                        notify_parent(current);
                                schedule();
+                               single_stepping |= ptrace_cancel_bpt(current);
                                continue;
 
                        case SIGQUIT: case SIGILL: case SIGTRAP:
@@ -292,12 +302,16 @@ asmlinkage int do_signal(unsigned long oldmask,
            (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 @@ asmlinkage int do_signal(unsigned long oldmask,
        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;
 }
index 4733f42225aae6a2d191a4e931d940476f01825e..2a29b02b38a845b9789602815f711d30bce840ec 100644 (file)
@@ -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 allregs {
 
 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);
+       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.count;
-       unaligned.va = (unsigned long) va - 4;
-       unaligned.pc = regs.pc;
+       ++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 @@ asmlinkage void do_entUna(void * va, unsigned long opcode, unsigned long reg,
 }
 
 /*
- * 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);
+       } 
 }
 
 /*
index 9bae0d8e61b659251178faa82403feac37c09d7f..f79b9ea9ba9d3382197f22e00dd74296132556e3 100644 (file)
@@ -57,13 +57,16 @@ if [ "$CONFIG_IP_FORWARD" = "y" -a "$CONFIG_IP_FIREWALL" = "y" ]; then
   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 @@ if [ "$CONFIG_PPP" = "y" ]; then
 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 @@ comment 'CD-ROM drivers (not for SCSI or IDE/ATAPI drives)'
 
 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
index 23085dc6ca7385dc027926bbc66cd3ac46807708..6643198d9e85b439317258f9524471d8ee634d44 100644 (file)
@@ -295,7 +295,7 @@ static void math_error_irq(int cpl, struct pt_regs *regs)
 
 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 @@ unsigned int probe_irq_on (void)
        return irqs;
 }
 
-int probe_irq_off (unsigned int irqs)
+int probe_irq_off (unsigned long irqs)
 {
        unsigned int i, irqmask;
 
index 87dacbe333ba3d7b612a174528c1f96a383c2e40..f7f70426c9d51524bde3d60b557caf8b5dfa813c 100644 (file)
@@ -232,12 +232,17 @@ void dump_thread(struct pt_regs * regs, struct user * dump)
        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 @@ void dump_thread(struct pt_regs * regs, struct user * dump)
 
 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 @@ asmlinkage int sys_clone(struct pt_regs regs)
        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
 }
 
 /*
index cdffafc2249abc68b330888e3fb1f47cebdfcdcc..6f64cdadc455b59c4a98e2aa49a30c4d3f20e0fd 100644 (file)
@@ -177,7 +177,7 @@ repeat:
                *(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();
 }
 
index fe601d1afee71cf2520a67d7243037bbf52cec75..b4084d9e3881a3ea92ec3a946f902e5d9b79c593 100644 (file)
@@ -93,7 +93,7 @@ static void mark_screen_rdonly(struct task_struct * tsk)
        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();
index d1742e1fa04ed1ec4abc9e36a20e97d0b35ed554..2a5f4f53dc756fc23861a24241fe72a7e6c15e12 100644 (file)
@@ -157,7 +157,7 @@ unsigned long paging_init(unsigned long start_mem, unsigned long end_mem)
                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;
index 5e4cacf03c7afd99726868fb1e9fb024cc5d2dd1..7ffde05390adfecb46049eb7474ac8648b338f08 100644 (file)
@@ -87,7 +87,7 @@ void flush_thread(void)
 
 #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 @@ unsigned long copy_thread(int nr, unsigned long clone_flags, struct task_struct
        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;
 }
 
 /*
index 8ae5524b8164bb4240e9451d401016e93d8a5a19..8e99aa657f0e6d63339c9bea1a219974105c9913 100644 (file)
@@ -156,7 +156,7 @@ repeat:
        }
 /* 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();
 }
 
index e3d69835425170ded75782e063f17dcfd81cd71a..5aed0fa692c8646c9a2a3dfd5b0c0e700a4a7b19 100644 (file)
@@ -163,7 +163,7 @@ unsigned long paging_init(unsigned long start_mem, unsigned long end_mem)
                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;
index b522d6cbe46febc0ec5b8848ed7e0a3694e45117..9dfa2f2158bd5e9e478614226770311fa62af00f 100644 (file)
@@ -139,7 +139,7 @@ void dump_thread(struct pt_regs * regs, struct user * dump)
 
 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);
 }
 
 /*
index c0ca5fce0afc71e5d3eee9370dfcf93dca543e0f..605bca0306dc366a079bf42b7e3130bc31d79c0d 100644 (file)
@@ -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);
index b4941e4d972d70d84db19c679f6f5edac117308a..9a327d36d07ded86cd476ec6b354510a4f4b9186 100644 (file)
@@ -427,6 +427,13 @@ srmmu_invalidate(void)
        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 @@ ld_mmu_srmmu(void)
        
        /* 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;
index c14d44ae746c604da500553f21be76d6e8d6e763..71d838b733fb742d3f6adf416b94936facac4973 100644 (file)
@@ -363,6 +363,13 @@ sun4c_invalidate(void)
        flush_vac_context();
 }
 
+void
+sun4c_set_pte(pte_t *ptep, pte_t entry)
+{
+       /* for now... */
+       *ptep = entry;
+}
+
 void
 sun4c_switch_to_context(int context)
 {
@@ -630,6 +637,7 @@ ld_mmu_sun4c(void)
        
        /* 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;
index 6857245d565eeead905b359ddb0bfc0b6ef2bda9..9c6453792530d9e257e74efbdb50711dd658d419 100644 (file)
@@ -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 @@ Contents of this file:
                          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 @@ configured and mail me (see 6.) the appropriate information.
 
 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
index efbb1e4fe207e3e1a555938daadbd3244c572e74..60c571ecdc431ad42f29e92b4891debf85936fae 100644 (file)
@@ -27,28 +27,31 @@ NEW!                  (both are now probed for)
        - 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 @@ For work in progress, see the comments in ide.c, ide-cd.c, and triton.c.
 ***  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 @@ The following two are valid ONLY on ide0 or ide1:
 
   "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 @@ kernels I think.
 
    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
index cb72aae4f9cb72e0e78c6d8d031089577c18a1c4..39537f9f0b085752c1e0d255b48650fb66d0b868 100644 (file)
@@ -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.
index d4164b01977dd79abf2ad6a47b100527270ea072..28b5b66b7613df4cccd880a02791d165ec06e95f 100644 (file)
@@ -5,13 +5,17 @@ drives: each driver can use his own drive.
 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 @@ This driver:
                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 @@ This driver never will:
 
        o       Read digital audio (i.e. copy directly), due to missing
                hardware features. 
+
+
+heiko@lotte.sax.de
index 0e61dd54055bd46d0818d5ae3dc16031b00cd54b..2a1566d00be5bb71a9f194266b3ae95ee510a624 100644 (file)
@@ -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)
        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-
         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 @@ static int aztPresent = 0;
 #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 char aztTocUpToDate = 0;
 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  sendAztCmd(int cmd, struct azt_Play_msf *params);
 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 @@ void dten_low(void)
 #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 @@ static void aztStatTimer(void)
        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 @@ static int sendAztCmd(int cmd, struct azt_Play_msf *params)
    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 @@ static int aztcd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsi
                }
                aztAudioStatus = CDROM_AUDIO_PLAY;
                break;
-#if AZT_MULTISESSION
        case CDROMMULTISESSION: /*multisession support -- experimental*/
                { struct cdrom_multisession ms;
 #ifdef AZT_DEBUG
@@ -643,12 +683,12 @@ static int aztcd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsi
                  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 @@ static int aztcd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsi
                  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 @@ azt_Play.end.min, azt_Play.end.sec, azt_Play.end.frame);
                  }
                 } 
                 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 @@ static void do_aztcd_request(void)
        }
        azt_state = AZT_S_START;
        AztTries = 5;
-       SET_TIMER(azt_poll, 1);
+       SET_TIMER(azt_poll, HZ/100);
       }
       break;
     }
@@ -1372,7 +1424,7 @@ static void azt_poll(void)
       STEN_LOW_WAIT;     
     };
 
-  SET_TIMER(azt_poll, 1);
+  SET_TIMER(azt_poll, HZ/100);
 }
 
 static void azt_invalidate_buffers(void)
@@ -1413,24 +1465,10 @@ int aztcd_open(struct inode *ip, struct file *fp)
 
            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 @@ int init_module(void)
           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 @@ int init_module(void)
                    { 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 @@ int init_module(void)
                        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 @@ int aztGetQChannelInfo(struct azt_Toc *qp)
  * 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 @@ static int aztUpdateToc()
        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 @@ static int aztUpdateToc()
 }
 
 
-/*
- * 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 @@ static int aztGetDiskInfo()
        }
       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 @@ static int aztGetDiskInfo()
       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 aztGetToc  Time:%li\n",jiffies);
+  printk("aztcd: starting aztGetMultiDiskInfo\n");
 #endif
-       for (i = 0; i < MAX_TRACKS; i++)
-               Toc[i].pointIndex = 0;
 
-       i = DiskInfo.last + 3;
+  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);
 
-/* Is there a good reason to stop motor before TOC read?
-       if (aztSendCmd(ACMD_STOP)) RETURNM("aztGetToc 1",-1);
-       STEN_LOW_WAIT;
-*/
+#ifdef AZT_DEBUG
+  printk ("aztcd: exiting aztGetMultiDiskInfo  Time:%li\n",jiffies);
+#endif
+  return 0;
+}
+#endif
 
-       azt_mode = 0x05;
-       if (aztSendCmd(ACMD_SEEK_TO_LEADIN)) RETURNM("aztGetToc 2",-1); /*???*/
-       STEN_LOW_WAIT;
+/*
+ * Read the table of contents (TOC)
+ */
+static int aztGetToc(int multi)
+{ int i, px;
+  int limit;
+  struct azt_Toc qInfo;
 
-       for (limit = 300; limit > 0; limit--)
-       {
-               if (aztGetQChannelInfo(&qInfo) < 0)
-                       break;
-
-               px = azt_bcd2bin(qInfo.pointIndex);
-               if (px > 0 && px < MAX_TRACKS && qInfo.track == 0)
-                       if (Toc[px].pointIndex == 0)
-                       {
-                               Toc[px] = qInfo;
-                               i--;
-                       }
-
-               if (i <= 0)
-                       break;
-       }
+#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;
+*/
 
-       Toc[DiskInfo.last + 1].diskTime = DiskInfo.diskLength;
+  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;
 
-        /*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;
+       px = azt_bcd2bin(qInfo.pointIndex);
 
-        /*try to detect XA disks*/
-        i = getAztStatus();
-       DiskInfo.xa    = i & AST_MODE; /* XA info sometimes unreliable ??? */
+       if (px > 0 && px < MAX_TRACKS && qInfo.track == 0)
+           if (Toc[px].pointIndex == 0)
+              { Toc[px] = qInfo;
+                i--;
+              }
 
-        /*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;
+       if (i <= 0)
+           break;
+      }
 
-#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);
+  Toc[DiskInfo.last + 1].diskTime = DiskInfo.diskLength;
+
+
+#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
index d8d936fe36705826bb3619caecbf4a68204e9966..d568b944b79994270d72730cdf8276aac639943b 100644 (file)
@@ -128,7 +128,7 @@ static void floppy_off(unsigned int nr);
 #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 @@ static void floppy_off(unsigned int nr);
 
 #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)
index daa63633668c8e854ba7d91c52deef16af09cf62..5b3388b890577ba93102110a462148d69cfa4ca3 100644 (file)
@@ -625,7 +625,7 @@ restart_on_error(void)
    }
 
    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 @@ do_sony_cd_cmd(unsigned char cmd,
             result_buffer[0] = 0x20;
             result_buffer[1] = SONY_SIGNAL_OP_ERR;
             *result_size = 2;
+            restore_flags(flags);
             return;
          }
       }
@@ -887,7 +888,7 @@ retry_cd_operation:
    {
       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 @@ read_audio(struct cdrom_read_audio *ra,
       interruptible_sleep_on(&sony_wait);
       if (current->signal & ~current->blocked)
       {
+         restore_flags(flags);
          return -EAGAIN;
       }
    }
index d0afcd6099d9154bc5062a1a967d62987670c4a8..487f7eb6c36d6ac85f58623fe362d8c92aaea16a 100644 (file)
@@ -126,9 +126,9 @@ static int cm206_irq = CM206_IRQ;
 #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
index 34755464467bbc512c76a059db5d188bfc711323..c5cf11fe03d60fdd92efacf35560ffb18fb6645e 100644 (file)
@@ -908,7 +908,7 @@ static void fd_watchdog(void)
        } 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 void setup_DMA(void)
 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 @@ static int output_byte(char byte)
 /* 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;
index 75529637b67760495acddfadd67541f7f690f2f3..2055d993161a0a9e3d5a5b07e25f93f49e0ad890 100644 (file)
@@ -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 @@ static void extended_partition(struct gendisk *hd, int dev)
                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 @@ static void extended_partition(struct gendisk *hd, int dev)
                 * 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);
index 9ff7285cdf0ddd5e90d21fec32e998533a167756..1bb6dc72a4b62182c67261e15d386239add4222a 100644 (file)
@@ -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)
  */
  *                     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
  */
 
 #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 @@ static inline void do_vlb_sync (unsigned short port) {
 #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 @@ void ide_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount)
 }
 
 /*
- * 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 @@ void ide_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount)
                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 @@ int ide_error (ide_drive_t *drive, const char *msg, byte stat)
        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 @@ static inline void do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned
 #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,
@@ -1286,6 +1328,10 @@ static inline void do_request (ide_hwif_t *hwif, struct request *rq)
        ((ide_hwgroup_t *)hwif->hwgroup)->drive = drive;
 #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)) {
@@ -1473,6 +1519,10 @@ static void unexpected_intr (int irq, ide_hwgroup_t *hwgroup)
         */
        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 @@ static int ide_ioctl (struct inode *inode, struct file *file,
                                        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 try_to_identify (ide_drive_t *drive, byte cmd)
 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 */
@@ -2131,6 +2184,10 @@ static int do_probe (ide_drive_t *drive, byte cmd)
        printk("probing for %s: present=%d, type=%s, probetype=%s\n",
                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 */
@@ -2251,6 +2308,116 @@ static void probe_for_drives (ide_hwif_t *hwif)
        }
 }
 
+#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 @@ static int match_parm (char *s, const char *keywords[], int vals[], int max_vals
  * "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 @@ void ide_setup (char *s)
                                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 @@ bad_option:
        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 @@ int ide_xlate_1024 (dev_t i_rdev, int need_offset, const char *msg)
  * 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 @@ static void probe_cmos_for_drives (ide_hwif_t *hwif)
                        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 @@ static struct file_operations ide_fops = {
        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 @@ unsigned long ide_init (unsigned long mem_start, unsigned long mem_end)
        /*
         * 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 */
 
        /*
index f22803bf62e0e0d819c14f572257f7b4acb0a0fc..b8f02b9bba3c7a5a6fb5688c9662ad4686a10e05 100644 (file)
 #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 @@ typedef struct hwif_s {
        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 @@ void ide_cdrom_setup (ide_drive_t *);
 #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 */
 
index daff426f133c74f797a4885bc7bb7ff9e9610a45..e29b076033fc63e78a5f5c672664448d4fa918be 100644 (file)
@@ -1662,6 +1662,7 @@ void cleanup_module(void)
        return;    
      }
   release_region(mcd_port,4);
+  free_irq(mcd_irq);
   printk("mcd module released.\n");
 }
 #endif MODULE
index 63c8ded5123b8f50a1538631be2f8c6d79f1c2cc..1f8ef94eb5f27fa8346e4b22c944e5140aa8b4d7 100644 (file)
@@ -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 @@ static const char *mcdx_c_version
 #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 @@ char kernel_version[]=UTS_RELEASE;
 #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 SINGLE = 0x01;
 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_drive_stuff {
        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 @@ struct s_drive_stuff {
     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 @@ static unsigned int bcd2uint(unsigned char);
 #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_config(struct s_drive_stuff*, int);
 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_setdatamode(struct s_drive_stuff*, enum datamodes, int);
 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 @@ static struct file_operations mcdx_fops = {
 
 /* 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 @@ mcdx_ioctl(
                        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 @@ mcdx_ioctl(
                                        || (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 @@ mcdx_ioctl(
 
                        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 @@ mcdx_ioctl(
                        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 @@ mcdx_ioctl(
                        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 @@ mcdx_ioctl(
                                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 @@ mcdx_ioctl(
                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 @@ mcdx_ioctl(
                        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 @@ mcdx_ioctl(
                        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 @@ void do_mcdx_request()
     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 @@ void do_mcdx_request()
 
     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 @@ void do_mcdx_request()
                                      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 @@ void do_mcdx_request()
          break;
 
       default:
-         panic(MCD "do_request: unknown command.\n");
+         panic(MCDX "do_request: unknown command.\n");
          break;
     }
 
@@ -530,19 +614,20 @@ static int
 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 @@ mcdx_open(struct inode *ip, struct file *fp)
         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 @@ mcdx_open(struct inode *ip, struct file *fp)
                                        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 @@ mcdx_open(struct inode *ip, struct file *fp)
                        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 @@ mcdx_close(struct inode *ip, struct file *fp)
                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 @@ int check_mcdx_media_change(dev_t full_dev)
        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 @@ static void mcdx_delay(struct s_drive_stuff *stuff, long jifs)
 /*     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 @@ mcdx_intr(int irq, struct pt_regs* regs)
     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 @@ mcdx_talk (
  * returns -1 on timeout, drive status otherwise
  */
 {
-    const DELAY = 1;                           /* minimum delay */
        char c;
        int st;
 
@@ -770,79 +866,77 @@ mcdx_talk (
     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"));
+
+        /* 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)));
+        }
+    }
 
-               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"));
-
+#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 @@ int init_module(void)
                }
        }
 
-    if (!drives) {
-               WARN(("init_module() cannot init any drive\n"));
+    if (!drives) 
                return -EIO;
-    }
 
     return 0;
 }
@@ -897,10 +989,9 @@ void cleanup_module(void)
                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 @@ void trace(int level, const char* fmt, ...)
        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 @@ unsigned long mcdx_init(unsigned long mem_start, unsigned long mem_end)
        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 @@ unsigned long mcdx_init(unsigned long mem_start, unsigned long mem_end)
 
                /* 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 @@ unsigned long mcdx_init(unsigned long mem_start, unsigned long mem_end)
                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 @@ unsigned long mcdx_init(unsigned long mem_start, unsigned long mem_end)
                 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 @@ unsigned long mcdx_init(unsigned long mem_start, unsigned long mem_end)
 
                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 @@ unsigned long mcdx_init(unsigned long mem_start, unsigned long mem_end)
 
                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 @@ static int mcdx_transfer(struct s_drive_stuff *stuffp,
                        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 @@ static int mcdx_transfer(struct s_drive_stuff *stuffp,
            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 @@ static int mcdx_transfer(struct s_drive_stuff *stuffp,
                                || 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 @@ static int mcdx_transfer(struct s_drive_stuff *stuffp,
                /* 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 @@ static unsigned int msf2log(const struct s_msf* pmsf)
 }
        
 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 @@ int mcdx_readtoc(struct s_drive_stuff* stuffp)
                                        && (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 @@ int mcdx_readtoc(struct s_drive_stuff* stuffp)
        }
 #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 @@ mcdx_requestsubqcode(struct s_drive_stuff *stuffp, struct s_subqcode *sub, int t
        sub->dt.minute = buf[8];
        sub->dt.second = buf[9];
        sub->dt.frame = buf[10];
+
        return ans;
 }
 
@@ -1403,7 +1591,7 @@ mcdx_requestmultidiskinfo(struct s_drive_stuff *stuffp, struct s_multi *multi, i
        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 @@ mcdx_requesttocdata(struct s_drive_stuff *stuffp, struct s_diskinfo *info, int t
 {
        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 @@ mcdx_setdrivemode(struct s_drive_stuff *stuffp, enum drivemodes mode, int tries)
 
        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 @@ mcdx_setdrivemode(struct s_drive_stuff *stuffp, enum drivemodes mode, int tries)
          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 @@ mcdx_setdatamode(struct s_drive_stuff *stuffp, enum datamodes mode, int tries)
          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 @@ mcdx_config(struct s_drive_stuff *stuffp, int tries)
        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 @@ mcdx_requestversion(struct s_drive_stuff *stuffp, struct s_version *ver, int tri
        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 @@ mcdx_reset(struct s_drive_stuff *stuffp, enum resetmodes mode, int tries)
                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 @@ mcdx_lockdoor(struct s_drive_stuff *stuffp, int lock, int tries)
        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;
+}
index c844aed9daa7ce5fdc0a66c1279408d7a0377cd2..22664f946f4685db951e1a8bad39302a4e2fcfd8 100644 (file)
@@ -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 @@ int init_module(void) {
 
     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;
     }
   }
        }
index 5b9d46aaf49030c38024637213e3f2acc10d79bb..6888eec89b89ef29c6bf19fe810f750e265dc8b1 100644 (file)
@@ -901,14 +901,14 @@ static void flush_status(void)
        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 @@ static int CDi_stat_loop(void)
        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 @@ static int CDi_stat_loop(void)
                        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 @@ static int CDi_stat_loop(void)
                        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 @@ static int CDi_stat_loop(void)
                                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 @@ static int ResponseInfo(void)
                }
        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 @@ static int ResponseInfo(void)
                                        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 @@ static int ResponseStatus(void)
        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 @@ static int ResponseStatus(void)
                                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 @@ static int cmd_out_T(void)
        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 @@ static int cmd_out_T(void)
                                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 @@ static int cmd_out_T(void)
                        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 @@ static int cc_DriveReset(void)
                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 @@ static int DriveReset(void)
                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 @@ static int UnLockDoor(void)
        {
                i=cc_LockDoor(0);
                --j;
-               sbp_sleep(1);
+               sbp_sleep(HZ/100);
        }
        while ((i<0)&&(j));
        if (i<0)
@@ -2095,7 +2095,7 @@ static int LockDoor(void)
        {
                i=cc_LockDoor(1);
                --j;
-               sbp_sleep(1);
+               sbp_sleep(HZ/100);
        }
        while ((i<0)&&(j));
        if (j==0)
@@ -2106,7 +2106,7 @@ static int LockDoor(void)
                {
                        i=cc_LockDoor(1);
                        --j;
-                       sbp_sleep(1);
+                       sbp_sleep(HZ/100);
                }
                while ((i<0)&&(j));
        }
@@ -2944,10 +2944,10 @@ static void check_datarate(void)
 #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 @@ static int check_version(void)
                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 @@ static int check_version(void)
                                        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 @@ static int sbpcd_ioctl(struct inode *inode, struct file *file, u_int cmd,
                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 @@ static int sbpcd_ioctl(struct inode *inode, struct file *file, u_int cmd,
                                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 @@ static int sbpcd_ioctl(struct inode *inode, struct file *file, u_int cmd,
                        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 @@ static int sbpcd_ioctl(struct inode *inode, struct file *file, u_int cmd,
                                        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 @@ static int sbpcd_ioctl(struct inode *inode, struct file *file, u_int cmd,
                        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 @@ static void DO_SBPCD_REQUEST(void)
                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 @@ static int sbp_data(void)
        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 @@ static int sbp_data(void)
        {
                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 @@ int init_module(void)
        if (!famL_drive)
        {
                OUT(CDo_reset,0);
-               sbp_sleep(100);
+               sbp_sleep(HZ);
        }
 #endif 0
 
@@ -5190,7 +5190,7 @@ int init_module(void)
                    D_S[d].error_byte);
                if (D_S[d].error_byte==aud_12)
                {
-                       timeout=jiffies+200;
+                       timeout=jiffies+2*HZ;
                        do
                        {
                                i=GetStatus();
index 1be79d1bcc05ce8d8b6a58f78ac20427e1b84fe9..7e6b1931ad460b03bd287f2ad5099a5682477109 100644 (file)
@@ -380,13 +380,13 @@ static void sjcd_status_timer( void ){
   } 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 @@ static void sjcd_poll( void ){
   /*
    * 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 @@ static void do_sjcd_request( void ){
          }
        }
        sjcd_transfer_state = SJCD_S_START;
-       SJCD_SET_TIMER( sjcd_poll, 1 );
+       SJCD_SET_TIMER( sjcd_poll, HZ/100 );
       }
       break;
     }
index 75cbd214953a06673fb91f9fa3061b1f884604d2..d518cf0375dea6d3d228ca60fe8dfaa99bc4c94a 100644 (file)
@@ -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.
  *
  *   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 @@ static void dma_intr (ide_drive_t *drive)
        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 @@ static void print_triton_drive_flags (unsigned int unit, byte flags)
 }
 
 /*
- * 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 @@ void ide_init_triton (ide_hwif_t  hwifs[])
         * 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;
index c48c33c2365d6ea9313b426205630efbaa31ab53..9d3f2f91313dab8c80117cb968e7505b6b58c525 100644 (file)
@@ -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 @@ If you can't solve a problem, send me
 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 @@ You  m u s t  use "clock dpll" in /etc/z8530drv.rc for operation,
 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 --git a/drivers/char/README.unicode b/drivers/char/README.unicode
deleted file mode 100644 (file)
index 2e32052..0000000
+++ /dev/null
@@ -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.
index 17c7a1ef501d8de61ae472ccce5e7df52f24535e..6d8f206939e52df5ceee49aaa06e61ea2e6b2b3f 100644 (file)
@@ -2030,7 +2030,7 @@ long con_init(long kmem_start)
        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 @@ long con_init(long kmem_start)
                        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. */
index 9a59aef2b8d2c1f292444cded356839a01b5d24b..e52e8f1993132042af0d30cd035f2e82b17d85e3 100644 (file)
@@ -1025,13 +1025,13 @@ check_wild_interrupts(void)
         * 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 @@ get_auto_irq(int card)
        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 @@ cy_close(struct tty_struct * tty, struct file * filp)
     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);
index 89047db2137ad8ad813f3216427540c57e1e2c8f..6870bffa15dbaf7b92f54b06bf736a218d89b428 100644 (file)
@@ -409,7 +409,7 @@ static int lp_ioctl(struct inode *inode, struct file *file,
                return -ENODEV;
        switch ( cmd ) {
                case LPTIME:
-                       LP_TIME(minor) = arg;
+                       LP_TIME(minor) = arg * HZ/100;
                        break;
                case LPCHAR:
                        LP_CHAR(minor) = arg;
index 3e2280153695fb2099cb19d12ebc4f9889d3f4a7..17e255a47969be1b3bc9871b8a0a30d0015f2b2b 100644 (file)
@@ -42,7 +42,7 @@ static int read_mem(struct inode * inode, struct file * file,char * buf, int cou
 
        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 @@ static int write_mem(struct inode * inode, struct file * file,const char * buf,
 
        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;
index f3641f74766cf138ba7c60380658751dd55f7310..1353449295d4cb90242d73f5933f757eb9cb8a55 100644 (file)
 #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 @@ static void aux_interrupt(int cpl, struct pt_regs * regs)
        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 @@ unsigned long psaux_init(unsigned long kmem_start)
        }
        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) {
index e7d445f6830a4e6029ddaccf491ec03f559a9dd2..cd9b70fa436e3fa89fe5ba12238223e10574dc84 100644 (file)
 #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; 
+   
+   ******************************************************************** 
+
+
+   ...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:
+   --------------------
 
-   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                               
+   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, 
    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>
 #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 scc_stop(struct tty_struct *tty);
 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_spint(register struct scc_channel *scc);
 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 @@ unsigned char Driver_Initialized = 0;
 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 @@ cl(register struct scc_channel *scc, register unsigned char reg, register unsign
 /* *                   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 @@ void scc_alloc_buffer_pool(void)
        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 @@ scc_get_buffer(char type)
                        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 @@ scc_return_buffer(register struct mbuf *bp, char type)
                
        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 @@ scc_free_chain(register struct mbuf *bp, char type)
        abp = bp->anext;
        while (bp) bp = scc_return_buffer(bp, type);
                
-       restore_flags(flags); cli();
+       restore_flags(flags);
        return abp;
 }
 
@@ -512,13 +551,13 @@ scc_isr(int irq, struct pt_regs *regs)
        
        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 */
@@ -649,6 +688,21 @@ scc_txint(register struct scc_channel *scc)
 
 /* 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)
 {
@@ -656,14 +710,18 @@ flush_FIFO(register struct scc_channel *scc)
        
        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 @@ scc_exint(register struct scc_channel *scc)
 static void
 scc_rxint(register struct scc_channel *scc)
 {
-       unsigned char ch;
+       register struct mbuf *bp;
 
        scc->stat.rxints++;
 
@@ -752,120 +810,98 @@ scc_rxint(register struct scc_channel *scc)
                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 @@ init_channel(register struct scc_channel *scc)
        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 @@ init_channel(register struct scc_channel *scc)
        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 @@ static inline void maxk_idle_timeout(register struct scc_channel *scc)
        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 @@ scc_timer(void)
                        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 @@ scc_init_timer(struct scc_channel *scc)
 }
 
 
+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 @@ kiss_set_param(struct scc_channel *scc,char cmd, unsigned int val)
        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 @@ static inline int kiss_decode(struct scc_channel *scc, unsigned char ch)
        
 }
 
+/* ----> 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 @@ z8530_init(void)
        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 @@ z8530_init(void)
                        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 @@ int scc_open(struct tty_struct *tty, struct file * filp)
        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 @@ int scc_open(struct tty_struct *tty, struct file * filp)
        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_ioctl(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned
                                scc->kiss.softdcd = 0;             /* hardware dcd */
                        }
                        
-                       scc->init = 1;
+                       scc->init = 1;                  
                        
                        return 0;
                }
@@ -1773,7 +1930,7 @@ scc_ioctl(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned
                
                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_ioctl(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned
                        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 @@ static inline void check_tx_queue(register struct scc_channel *scc)
                
                scc->sndq1->anext = bp;
        }
-       
 }
 
 
@@ -1984,14 +2140,12 @@ static inline void check_tx_queue(register struct scc_channel *scc)
 /* 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 @@ int scc_write(struct tty_struct *tty, int from_user, const unsigned char *buf, i
        
        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 @@ static void scc_flush_chars(struct tty_struct * tty)
        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 void scc_flush_chars(struct tty_struct * tty)
 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_write_room(struct tty_struct *tty)
 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 int scc_chars_in_buffer(struct tty_struct *tty)
 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 @@ static void scc_stop(struct tty_struct *tty)
        /* 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 @@ void scc_hangup(struct tty_struct *tty)
 
 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 @@ long scc_init (long kmem_start)
         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 @@ long scc_init (long kmem_start)
  
                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);
index a52b7e2a27a3b3cc1c0895d9685e42bd2f818413..278895747b6f9f27ed274ef842cc321fe45fd6f1 100644 (file)
@@ -60,6 +60,8 @@ int SCC_Enhanced[MAXSCC] =    {0,     /* ...one...    */
 #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 */
index c9f18a3ce71a92af37747c9f1609ea525c120f28..5e3817083cca758ac496deab028effb1a9fcf5c0 100644 (file)
@@ -71,7 +71,7 @@ static int serial_refcount;
 #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 @@ static void rs_timer(void)
        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 @@ static void rs_timer(void)
                }
        }
        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 @@ static int startup(struct async_struct * info)
        /*
         * 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 @@ static int set_serial_info(struct async_struct * info,
                        (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 @@ static int check_wild_interrupts(int doprint)
         * 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 @@ static int get_auto_irq(struct async_struct *info)
        (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 @@ long rs_init(long kmem_start)
                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;
index 19cad53084cc6701593975ea06e3acc5f0aec00b..a9ff859c8e0d6ac8ead7300980cb5d4b97679e88 100644 (file)
@@ -754,7 +754,7 @@ static int wait_for_ready(time_t timeout)
                /* 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... */
        }
index 00443ee89543bdecbe2344e0ccfe2c553db98cd5..0b602150a9f9f25a13c0c1603b83c0e499eef805 100644 (file)
@@ -95,7 +95,7 @@ el2_probe(struct device *dev)
 
     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 @@ el2_probe1(struct device *dev, int ioaddr)
 #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 */
index c08ec87b40d28e8ce52d0f7fb4a180eb731c5028..0b3d016e5c0ace8e9ff148673017b45423419694 100644 (file)
@@ -377,8 +377,10 @@ send_pcb (struct device * dev, pcb_struct * pcb)
                } 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 --git a/drivers/net/README.arcnet b/drivers/net/README.arcnet
deleted file mode 100644 (file)
index 0ff778b..0000000
+++ /dev/null
@@ -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 --git a/drivers/net/README.arcnet-jumpers b/drivers/net/README.arcnet-jumpers
deleted file mode 100644 (file)
index 09c4a69..0000000
+++ /dev/null
@@ -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 --git a/drivers/net/README.modules b/drivers/net/README.modules
deleted file mode 100644 (file)
index 4961083..0000000
+++ /dev/null
@@ -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)
index 24b24dfe83acfb7869405bcdedf82818b64fd82c..80c97d140b9fc926a35b19214bc59a8c688abe55 100644 (file)
@@ -752,6 +752,7 @@ adapter_init(struct device *dev)
 #endif /* SHUTDOWN_WHEN_LOST */
                was_down = 1;
                dev->tbusy = 1;         /* Transmit busy...  */
+               restore_flags(flags);
                return 1; /* failed */
        }
 #endif /* CHECK_LOST_DE600 */
index 8af5647b87d2ffd854bafa9631cba0a06f970dc3..37f61cf20147761baa56ceb1147c9488d195e274 100644 (file)
@@ -859,6 +859,7 @@ eql_remove_slave(slave_queue_t *queue, slave_t *slave)
     {
       prev->next = current->next;
       queue->num_slaves--;
+      sti();
       return current;
     }
 
index 5e77af0d0c97ade72d8bf4aa5f5168cb9691c3dd..94c0303de34c96c5d1e2dd7f64b53310ec57d5a5 100644 (file)
@@ -350,6 +350,15 @@ void unregister_netdev(struct device *dev)
                        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);
 }
 
index 6f85d9a83d7d9acb5705a68c69131a5a98b8cdd2..d52d38d5b8f1bf60fb77b70b07a456585a1122c6 100644 (file)
@@ -2117,12 +2117,20 @@ int
 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;
                }
index 56fa844217f1306317392136886951825b2c7130..8baf79ba91a6b6fde5a8499391a31fbb8803db15 100644 (file)
@@ -67,6 +67,7 @@ struct pci_dev_info dev_info[] = {
        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 @@ struct pci_dev_info dev_info[] = {
        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 @@ struct pci_dev_info dev_info[] = {
        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 @@ struct pci_dev_info dev_info[] = {
        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 @@ struct pci_dev_info dev_info[] = {
        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 @@ const char *pci_strvendor(unsigned int vendor)
              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 @@ const char *pci_strvendor(unsigned int vendor)
              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 @@ unsigned long pci_init (unsigned long mem_start, unsigned long mem_end)
 
 #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
index 359edf2a0d26b6b1cf63a3a00d89b9c4eb36cbf0..ef2bc826f4b7f6656129144cb688531f4f270ce3 100644 (file)
@@ -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 @@ NCR53c7xx_reset (Scsi_Cmnd *cmd) {
     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 @@ shutdown (struct Scsi_Host *host) {
  *     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 @@ ncr_halt (struct Scsi_Host *host) {
     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 @@ ncr_halt (struct Scsi_Host *host) {
            }
        } else if (istat & ISTAT_DIP) {
            NCR53c7x0_write8(hostdata->istat, 0);
+           mb();
            tmp = NCR53c7x0_read8(DSTAT_REG);
            if (tmp & DSTAT_ABRT)
                break;
index cce8d031f0ab37d6e30978302b6eca2779822959..420eb50d43a75c2b57f36364b9420cf024a89e72 100644 (file)
@@ -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 @@ writing and the last operation has been a write. Two filemarks can be
 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 @@ MTSETDRVBUFFER
            (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
index 0fb1a492a2b661c26442618a5aadc3c9564b3744..871e256385a9bb01f242d61c1b0f87611da3d9de 100644 (file)
@@ -155,10 +155,10 @@ static int aha1542_out(unsigned int base, unchar *cmdp, int len)
 {
   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 @@ static int aha1542_out(unsigned int base, unchar *cmdp, int len)
        return 0;
       }
   } else {
-    save_flags(flags);
     cli();
     while (len--)
       {
index 22871d8dad5730977fa909d92d51a4132992d16e..d5422f2e283d8dcadb709944bacb5a67845a1078 100644 (file)
@@ -715,6 +715,7 @@ int eata2x_abort (Scsi_Cmnd *SCarg) {
    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 @@ int eata2x_abort (Scsi_Cmnd *SCarg) {
       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) {
index 7582b0e61f25c057f1bc898c1200dbf4edde03b2..1b339191d084ab8e2082a223c8bbf43e22b601c2 100644 (file)
@@ -540,8 +540,9 @@ int eata_abort(Scsi_Cmnd * cmd)
        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)
index c6c561a46b3817cdffb8790512e6e5f87ab34768..34051697034035b2f10b0d5af64fdb8193dea4f5 100644 (file)
@@ -435,8 +435,9 @@ int eata_pio_abort(Scsi_Cmnd * cmd)
        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)
index bedaec4f24ff73e8f54e6cb0209dfbc05929c5f1..e0f758752483b3ab98594bd4a6c065a5c1e0bb20 100644 (file)
@@ -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>
 #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"
 #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_buffer_size = ST_BUFFER_SIZE;
 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 @@ st_chk_result(Scsi_Cmnd * SCpnt)
 
   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 @@ st_chk_result(Scsi_Cmnd * SCpnt)
 
   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 @@ st_sleep_done (Scsi_Cmnd * SCpnt)
       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 @@ write_behind_check(int dev)
 
   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 @@ flush_write_buffer(int dev)
   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 @@ flush_write_buffer(int dev)
     }
   }
 
+  if (STp->block_size == 0)
+    return 0;
+
   result = 0;
   if (STp->dirty == 1) {
     SCpnt = allocate_device(NULL, STp->device, 1);
@@ -320,7 +314,7 @@ flush_write_buffer(int dev)
     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 @@ scsi_tape_open(struct inode * inode, struct file * filp)
     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 @@ scsi_tape_open(struct inode * inode, struct file * filp)
                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 @@ scsi_tape_open(struct inode * inode, struct file * filp)
                  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 @@ scsi_tape_open(struct inode * inode, struct file * filp)
        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 @@ scsi_tape_open(struct inode * inode, struct file * filp)
                (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 @@ scsi_tape_open(struct inode * inode, struct file * filp)
        ((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 @@ scsi_tape_open(struct inode * inode, struct file * filp)
     }
     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 @@ scsi_tape_open(struct inode * inode, struct file * filp)
                (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 @@ scsi_tape_open(struct inode * inode, struct file * filp)
     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 @@ scsi_tape_open(struct inode * inode, struct file * filp)
        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 @@ scsi_tape_open(struct inode * inode, struct file * filp)
     }
     (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 @@ scsi_tape_open(struct inode * inode, struct file * filp)
     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 @@ scsi_tape_close(struct inode * inode, struct file * filp)
 
       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 @@ scsi_tape_close(struct inode * inode, struct file * filp)
                    (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 @@ scsi_tape_close(struct inode * inode, struct file * filp)
 
       }
 
-#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 @@ st_write(struct inode * inode, struct file * filp, const char * buf, int count)
     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 @@ st_write(struct inode * inode, struct file * filp, const char * buf, int count)
     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 @@ st_write(struct inode * inode, struct file * filp, const char * buf, int count)
     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 @@ st_write(struct inode * inode, struct file * filp, const char * buf, int count)
                   (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 @@ st_write(struct inode * inode, struct file * filp, const char * buf, int count)
            }
            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 @@ st_write(struct inode * inode, struct file * filp, const char * buf, int count)
            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 @@ st_write(struct inode * inode, struct file * filp, const char * buf, int count)
       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 @@ st_read(struct inode * inode, struct file * filp, char * buf, int count)
     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 @@ st_read(struct inode * inode, struct file * filp, char * buf, int count)
        (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 @@ st_read(struct inode * inode, struct file * filp, char * buf, int count)
     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 @@ st_read(struct inode * inode, struct file * filp, char * buf, int count)
                     (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 @@ st_read(struct inode * inode, struct file * filp, char * buf, int count)
        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 @@ st_read(struct inode * inode, struct file * filp, char * buf, int count)
                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 @@ st_read(struct inode * inode, struct file * filp, char * buf, int count)
                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 @@ st_read(struct inode * inode, struct file * filp, char * buf, int count)
              }
            } /* 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 @@ st_read(struct inode * inode, struct file * filp, char * buf, int count)
                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 @@ st_read(struct inode * inode, struct file * filp, char * buf, int count)
           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 @@ st_set_options(struct inode * inode, long options)
     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 @@ st_set_options(struct inode * inode, long options)
       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 @@ st_int_ioctl(struct inode * inode,struct file * file,
 
    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 @@ st_int_ioctl(struct inode * inode,struct file * file,
        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 @@ st_int_ioctl(struct inode * inode,struct file * file,
        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 @@ st_int_ioctl(struct inode * inode,struct file * file,
        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 @@ st_int_ioctl(struct inode * inode,struct file * file,
        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 @@ st_int_ioctl(struct inode * inode,struct file * file,
        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 @@ st_int_ioctl(struct inode * inode,struct file * file,
        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 @@ st_int_ioctl(struct inode * inode,struct file * file,
        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 @@ st_int_ioctl(struct inode * inode,struct file * file,
        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 @@ st_int_ioctl(struct inode * inode,struct file * file,
        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 @@ st_int_ioctl(struct inode * inode,struct file * file,
        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 @@ st_int_ioctl(struct inode * inode,struct file * file,
         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 @@ st_int_ioctl(struct inode * inode,struct file * file,
         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 @@ st_int_ioctl(struct inode * inode,struct file * file,
         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 @@ st_int_ioctl(struct inode * inode,struct file * file,
        (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 @@ st_int_ioctl(struct inode * inode,struct file * file,
               (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 @@ st_int_ioctl(struct inode * inode,struct file * file,
        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 @@ st_int_ioctl(struct inode * inode,struct file * file,
      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 @@ st_ioctl(struct inode * inode,struct file * file,
 
    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 @@ st_ioctl(struct inode * inode,struct file * file,
      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 @@ st_ioctl(struct inode * inode,struct file * file,
 
      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 @@ st_ioctl(struct inode * inode,struct file * file,
         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 @@ st_ioctl(struct inode * inode,struct file * file,
    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 @@ st_ioctl(struct inode * inode,struct file * file,
                 (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 @@ st_ioctl(struct inode * inode,struct file * file,
      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);
 }
 
 \f
@@ -1971,6 +2008,24 @@ static int st_attach(Scsi_Device * SDp){
    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 @@ static int st_detect(Scsi_Device * SDp)
   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 @@ static void st_init()
                                              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 @@ static void st_init()
     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 @@ static void st_init()
   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 @@ void cleanup_module( void)
     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) 
index e6632159e3b3fb4438bc87802e7964d89a45fb2c..bf0d688dd1e639cba87416d930e4270977697a1a 100644 (file)
@@ -26,6 +26,7 @@ typedef struct {
   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 @@ typedef struct {
   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 @@ typedef struct {
   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
@@ -70,6 +79,12 @@ typedef struct {
 #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
 #define        QFA_SEEK_BLOCK          0x0c
diff --git a/drivers/scsi/st_options.h b/drivers/scsi/st_options.h
new file mode 100644 (file)
index 0000000..dbdaf99
--- /dev/null
@@ -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
index 1b3bac07d578ab2efd46e94c4a6a4d4e837ec930..69e21acdf6a52794b7974f34555074c3fdba8db6 100644 (file)
@@ -658,6 +658,7 @@ int u14_34f_abort(Scsi_Cmnd *SCarg) {
    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 @@ int u14_34f_abort(Scsi_Cmnd *SCarg) {
       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) {
index 58d0294abe90e5b1e7ab6a6a8c855a754b67a08b..9825fb47126cc491fa3e4b0a583d94ea6978c3ef 100644 (file)
@@ -80,6 +80,8 @@ endif
 
 ifdef CONFIG_HPFS_FS
 SUB_DIRS += hpfs
+else
+MOD_SUB_DIRS += hpfs
 endif
 
 ifdef CONFIG_BINFMT_ELF
index 01db8a604a30fad0d7cca6c89c277cd76c8fc749..9c43ff50b69bf5d010dfe650590a35999c8f99c2 100644 (file)
@@ -44,7 +44,7 @@ typedef int (*sysfun_p)(int, ...);
 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 @@ unsigned long * create_elf_tables(char * p,int argc,int envc,struct elfhdr * exe
 
        }
        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 @@ unsigned long * create_elf_tables(char * p,int argc,int envc,struct elfhdr * exe
                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 @@ load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
        
        
        /* 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)){
index a175baaabdeb1b712d1bfb4f3c28a2a0adc2607b..90583ab7d6f7c98b32f0ee7154a430bc8e3b71fb 100644 (file)
@@ -790,15 +790,17 @@ void brelse(struct buffer_head * buf)
                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 @@ unsigned long generate_cluster(dev_t dev, int b[], int size)
 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;
index bd9f2d5ad4ac4683f5bb95bbb039f23e3f052d11..b71fff2599fe8666796ff9838505037cf81bc7c7 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -235,14 +235,14 @@ int aout_core_dump(long signr, struct pt_regs * regs)
        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 @@ unsigned long * create_tables(char * p, struct linux_binprm * bprm, int ibcs)
                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 do_execve(char * filename, char ** argv, char ** envp, struct pt_regs * regs
        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 @@ restart_interp:
                        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 @@ beyond_if:
        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 --git a/fs/hpfs/README b/fs/hpfs/README
deleted file mode 100644 (file)
index 7e4fe88..0000000
+++ /dev/null
@@ -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
index 61331c1d2b0186e770ea8e0b3df53513c22bb88f..c6673a8049b7bfcb4760fe329ffc3829ac157887 100644 (file)
    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,
index 0c5c074a6cd9877c1dede5ab49f659427af9800c..ad30f9b5d09d629b38fa1439ebd593184fc2c98a 100644 (file)
  *   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 @@ struct super_block *hpfs_read_super(struct super_block *s,
        int conv;
        int dubious;
 
+       MOD_INC_USE_COUNT;
+
        /*
         * Get the mount options
         */
@@ -350,6 +360,7 @@ struct super_block *hpfs_read_super(struct super_block *s,
        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 @@ struct super_block *hpfs_read_super(struct super_block *s,
        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 @@ struct super_block *hpfs_read_super(struct super_block *s,
                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 @@ struct super_block *hpfs_read_super(struct super_block *s,
  bail:
        s->s_dev = 0;
        unlock_super(s);
+       MOD_DEC_USE_COUNT;
        return 0;
 }
 
@@ -715,6 +729,7 @@ static void hpfs_put_super(struct super_block *s)
        lock_super(s);
        s->s_dev = 0;
        unlock_super(s);
+       MOD_DEC_USE_COUNT;
 }
 
 /*
@@ -1725,3 +1740,25 @@ static void brelse4(struct quad_buffer_head *qbh)
        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
+
index 57f3cc411ea9656a7dd9862a2011bc3d10974f42..29a58991d99975969c0ccc221829045cf5cd5932 100644 (file)
@@ -12,6 +12,7 @@ void nfs_bl_cache_invalidate(nfs_cache *nh)
                nh->data=NULL;
                nh->free=1;
        }
+       restore_flags(flags);
 }
 
 void nfs_bl_cache_revalidate(nfs_cache *nh, struct fattr fa)
index 7ab4a7e4f749423a52e93948769cc50be0a86b68..97fb27743fe7c202910c3a128f1e512cb6b1d6f4 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -466,16 +466,9 @@ int do_open(const char * filename,int flags,int mode)
        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 @@ int do_open(const char * filename,int flags,int mode)
        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 @@ int do_open(const char * filename,int flags,int mode)
                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)
index 7671e47cfe562c6b7ecde1d35d8079618af56fa1..cd21603148e6f7ee3edc088b1e002684dca53b48 100644 (file)
@@ -56,7 +56,7 @@ int get_malloc(char * buffer);
 
 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 @@ static int read_core(struct inode * inode, struct file * file,char * buf, int co
 
        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 @@ static int read_core(struct inode * inode, struct file * file,char * buf, int co
                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;
index 7181ab7a788927a0d5052b535b413add169797e6..0c9d4d3b6a137c40f38bd7b843eef8007b447e56 100644 (file)
@@ -210,7 +210,7 @@ void proc_read_inode(struct inode * inode)
                        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:
index 9d053a637fe528fbf462cece3760a1a313db0e23..da1e48d5d040fb1ea8a90bea2f9d1540eacd62b4 100644 (file)
@@ -289,8 +289,8 @@ int mem_mmap(struct inode * inode, struct file * file,
                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;
index 84f87748ff2cd8195f4a1e99033fef04aaff08a1..98a7dddb8aa880045fcb9e4917b9bb5953f89b3b 100644 (file)
@@ -92,8 +92,8 @@ static int do_select(int n, fd_set *in, fd_set *out, fd_set *ex,
        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 @@ repeat:
  * 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 @@ static int __get_fd_set(int nr, unsigned long * fs_pointer, fd_set * fdset)
        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 --git a/fs/smbfs/README b/fs/smbfs/README
deleted file mode 100644 (file)
index 937262d..0000000
+++ /dev/null
@@ -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.
-
index 6cfd256f8e8fc2d75fdad90efe63fd82df206761..b04e3c3e46b8de0757c47daed98dd6cbe7695d64 100644 (file)
@@ -330,7 +330,7 @@ static struct super_block * read_super(dev_t dev,const char *name,int flags,
 
 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 @@ static dev_t get_unnamed_dev(void)
        return 0;
 }
 
-static void put_unnamed_dev(dev_t dev)
+void put_unnamed_dev(dev_t dev)
 {
        if (!dev)
                return;
@@ -460,7 +460,7 @@ asmlinkage int sys_umount(char * name)
  * 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 --git a/fs/sysv/README b/fs/sysv/README
deleted file mode 100644 (file)
index d318eb6..0000000
+++ /dev/null
@@ -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 --git a/fs/umsdos/README b/fs/umsdos/README
deleted file mode 100644 (file)
index 320dac6..0000000
+++ /dev/null
@@ -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 --git a/include/asm-alpha/apecs.h b/include/asm-alpha/apecs.h
new file mode 100644 (file)
index 0000000..451c8b6
--- /dev/null
@@ -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__ */
index 420ffa02c9a298549352c5919311d4cad65b01ae..885bf77f431892f048eb3821f468b7a1fda40a6f 100644 (file)
@@ -20,18 +20,18 @@ extern __inline__ unsigned long set_bit(unsigned long nr, void * addr)
 
        __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 @@ extern __inline__ unsigned long clear_bit(unsigned long nr, void * addr)
 
        __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 @@ extern __inline__ unsigned long change_bit(unsigned long nr, void * addr)
 
        __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));
 }
 
 /*
index 35204d7c27d07429e2303f68d5d75d70b01067a6..4fffac6e5befa11c7336655db549a97dceee77ee 100644 (file)
  * 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;
index 81b9d28814acdaa8094c526604e19fae4a483e58..2a62069628af02968ab295040da9fee8f554e0f7 100644 (file)
@@ -84,10 +84,12 @@ extern void _outl (unsigned int l,unsigned long port);
  * "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__
index 09805fee4cbc95681acc2686bc6cfcbc06ed9627..db313b470da635b08d57e3299ead3c5cf213cd88 100644 (file)
@@ -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 unsigned long __readl(unsigned long addr)
 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 @@ extern inline void __writeb(unsigned char b, unsigned long addr)
                        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 @@ extern inline void __writew(unsigned short b, unsigned long addr)
                        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 @@ extern unsigned long lca_init (unsigned long mem_start, unsigned long mem_end);
 
 #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__ */
index 64bc63db02343def13495a6d81c72df700006233..6ff3326ad642f513c826d1acc1dc2038f37b29e0 100644 (file)
@@ -60,6 +60,12 @@ __asm__ __volatile__( \
        ".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)
 
index 3484d0dd143627c59d6b0c9dcadc029c7e922413..896bfc3e150916d13a5bd5bd0d1fe5aa72ed8161 100644 (file)
@@ -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 @@ extern void * __memcpy(void *, const void *, size_t);
 
 #define __HAVE_ARCH_STRLEN
 
-#endif
+#endif /* __ALPHA_STRING_H__ */
index a5fdbd4109ce01ea0bcae077cdf0652dd85a97d6..4276f2f2626fd47e9ca65e3ddb6fe8c8df2b6f36 100644 (file)
@@ -100,7 +100,7 @@ typedef unsigned long u64;
 #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 @@ static inline void __FD_SET(unsigned long fd, fd_set *fdsetp)
 }
 
 #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 @@ static inline void __FD_CLR(unsigned long fd, fd_set *fdsetp)
 }
 
 #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 @@ static inline int __FD_ISSET(unsigned long fd, fd_set *p)
 }
 
 /*
- * 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;
index 4712c971602aa804284e0fb9ba6cd120fcdc686c..41124cec563c18bf74ee366875e4fe5a792d12cf 100644 (file)
@@ -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
 #define __NR_delete_module     308
 #define __NR_get_kernel_syms   309
 #define __NR_syslog            310
+#define __NR_reboot            311
 
 
 #ifdef __LIBRARY__
index 4a7e7571741a223f141542e600d32ccfc2bb20dd..3c9a00fb1e961a2ac85464777c71f23c931d2f41 100644 (file)
@@ -94,7 +94,7 @@ __OUT1(s##_p,x) __OUT2(s,s1,"w") : : "a" (value), "d" (port)); SLOW_DOWN_IO; } \
 __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 @@ extern inline void outs##s(unsigned short port, const void * addr, unsigned long
 { __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 --git a/include/asm-i386/ioctl.h b/include/asm-i386/ioctl.h
new file mode 100644 (file)
index 0000000..8068397
--- /dev/null
@@ -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 */
index 86cbf5584a43b0218699c331de9245b1071ec03f..285f3f61ac3aa70f6ddd679e2ea37b55357f9fcc 100644 (file)
@@ -69,6 +69,12 @@ do { if ((task)->mm == current->mm) invalidate(); } while (0)
 #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)
 
index a4c82ae8aabe0232667d971ec4e5a4c3984d56d7..ec3df86ef18d0d6fdfb678b049ab5a291641210e 100644 (file)
@@ -97,7 +97,7 @@ typedef unsigned long long u64;
 #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
index 5a80d7e1f58ab5d5db644188a3708b83aad6fe68..fc7b893dd319a8a6e1468a9b7ea4f99d8ecb2056 100644 (file)
 #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
index 39677f1a88873b96fb85c07e22c275194bd4a41b..b614bdd2321b5e878f5203062cd9772be185c323 100644 (file)
@@ -86,6 +86,7 @@ typedef unsigned long pgprot_t;
  */
 
 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)
index 49a4837ee707d15ed3beac588d53d0373c398c57..36c58b1a8350aa96882601e881b0d7c90e230502 100644 (file)
@@ -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
   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 @@ not been tested !!!*/
 #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_Play_msf {
 
 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;
 };
index 336dfdd9dd5c16775cb5de0074f3067b8264e263..cd5beb22b1c1c8d53dd400e593e22b60c14c4973 100644 (file)
@@ -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
 
index 47cee7c21f713d9ba41768e783ae2012adc9a03d..474bc056093e505d0a07f9bf51e53d2f5ddb83d4 100644 (file)
@@ -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 @@ struct cdrom_multisession
 #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
index fc1150fef49bf2797b5ec8160a421a11e55dd88f..fe42b6f527417d11b12ab1496154fb9d46eec62b 100644 (file)
 
 #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
index cf024730725bd77c03cfbde7759dd790c4b8e3bf..caef9d382fa990239263bf9569e6d1833427deca 100644 (file)
@@ -79,6 +79,23 @@ typedef unsigned long        Elf32_Word;
 #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{
index e101d2f7c42d94efe63296f4f8f716022df0cc0e..d06f971f4fc4d4773f951f8a123f041168a8102e 100644 (file)
@@ -85,7 +85,7 @@ extern inline void end_bh_atomic(void)
  * 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
index 12bb269d1249226ae0e0ab2eec3b40708f7dd228..aa91eb3951ef6c92dffdaa6155637d9f01c71d7e 100644 (file)
@@ -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 */
 
index 0deae9c019e99b71a6f435ced3fb1c83530f1858..35494cda78413558e589f5cba537a05ef26e24d8 100644 (file)
@@ -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
index b0105150c64927220af848d13580d7e639c972d1..0ef085783db0ca30957fa88d6c70a818f6ce9e78 100644 (file)
@@ -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 */
index 975a3f840a565f156b2832159bcb35bcc3da7751..b5eb2fb001b96147317eb5b9cebbb4b23ba4ad52 100644 (file)
 #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 mcd_Toc {
        struct msf      trackTime;
        struct msf      diskTime;
 };
+
+#ifndef I_WAS_HERE
+#error Please edit this file first.
+#endif
index 2ee9de3a9f1635a602633bfb3a40e0a712716ff6..4f273f517e80bcd59c4240b8ad97931436a1326a 100644 (file)
@@ -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},    \
        #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
 /**    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
  */
 #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 --git a/include/linux/mroute.h b/include/linux/mroute.h
new file mode 100644 (file)
index 0000000..a5f5f6b
--- /dev/null
@@ -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
index 175a83e0db9781677d5d777c822064f669921e7e..bdfefd904074bdaf979a005e594c4218b38da410 100644 (file)
@@ -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 @@ struct        mtop {
 #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 @@ struct       mtop {
 #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 @@ struct      mtpos {
 #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 */
index 0d6103d3816cc1f72868644e88d845c6aaa66dc5..0a2978bf631acc8c7b1883c0816c6f6d40d2b0d8 100644 (file)
@@ -116,6 +116,7 @@ struct device
 
   /* 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 int          ip_chk_addr(unsigned long addr);
 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);
index 81e2dc844945f75ff44cccb4a65a2f4420028f71..573afc7ea0676dbc2bcbf9eded0b37141c98e5b1 100644 (file)
@@ -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.
index 55ae04155fdd7312d503d12c0843cde7ad3c4a62..cb66b696138d332aa9432adca1a8a8f99919c769 100644 (file)
 
 #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
 #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
 
 #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
 #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
 #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
  * devices.  The slot/function address of each device is encoded
index 4ab4f5bf5b91a02629373ba22806c39d78ead832..af83c94300ec0a63b559fcfb22af5f439ab4c871 100644 (file)
@@ -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 @@ typedef unsigned short ioaddr;  /* old def */
 
 /* 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_channel {
         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 @@ struct scc_channel {
        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 @@ struct scc_channel {
 #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 */
index c50d4c8a378f286e2c80ac5d393addf97fa74a19..727f162a13eb86285a4e1b01e992c47926be1e1e 100644 (file)
@@ -95,7 +95,7 @@ struct files_struct {
 };
 
 #define INIT_FILES { \
-       0, \
+       1, \
        { { 0, } }, \
        { NULL, } \
 }
@@ -107,7 +107,7 @@ struct fs_struct {
 };
 
 #define INIT_FS { \
-       0, \
+       1, \
        0022, \
        NULL, NULL \
 }
@@ -129,7 +129,7 @@ struct mm_struct {
 };
 
 #define INIT_MM { \
-               0, \
+               1, \
                0, 0, 0, 0, \
                0, 0, 0, 0, \
                0, 0, 0, 0, \
@@ -154,7 +154,7 @@ struct task_struct {
        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 @@ struct task_struct {
 /* 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 @@ struct task_struct {
  * 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 @@ struct task_struct {
 /* 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 @@ struct task_struct {
 /* 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__
index d98bf6981c01b927d4cd1e0b77b894425a55f9b2..49174f7fced5cd96474d9f91eb3bb83cc7ff6777 100644 (file)
@@ -89,8 +89,8 @@ struct msghdr
 #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
 
index 387e6f8143c1cfb0b226a18c1e7b2aae9b307533..5dea1ef168d61b19b1894d84c2c59a3c6ef0534f 100644 (file)
 
 #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 */
index 2078382202aa5a26db143908fe5388a7dcd6a617..f27c2804b0f5802284ae70667ec0f3c422482e0f 100644 (file)
  * 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)
 
index 5876090ae03e391c05adb6754dbc47c2ac87a819..43c04a5e02e75daa7ce8288e3dfc408a861dd15b 100644 (file)
  * 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>
 
index 3fbee19e4efb17309bc0db9fb4900cc720ffd3d9..94df3abf4ac55815344f4798f7c8d9f70d3e9e5e 100644 (file)
@@ -69,7 +69,7 @@ struct user{
   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)
index 83cea4e9dde30014ce00968a0ab66a796c617c87..ddca8bf095d2d52faffaea6254f1ea7d95367701 100644 (file)
@@ -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 */
index 126c14d68e0fa463367971b538f975a51606dac0..c3047f8177e357b93e6559ccc39ca16533eaa02e 100644 (file)
@@ -209,6 +209,7 @@ struct sock {
   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 */
index f73cb1a8b0af81b086b819431b193ae70ac18e3b..012eff471fd3dcdc6d72f8bf29646d53904b6013 100644 (file)
@@ -283,7 +283,7 @@ static void calibrate_delay(void)
                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;
index 4a4fd0ad905038203a644effc97cd54408a7211a..b815590c3ddf9c0074411e1d6811138f31b318fb 100644 (file)
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -442,7 +442,7 @@ static int shm_map (struct vm_area_struct *shmd)
                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 @@ int shm_swap (int prio, unsigned long limit)
                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--;
index fa5ca2fb0c7a5e554065f36482e5ad7b29220c0f..b312e2109f022406a1f667bff31ead30744e8482 100644 (file)
@@ -357,19 +357,37 @@ static void forget_original_parent(struct task_struct * father)
 
 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 @@ fake_volatile:
        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);
        /* 
index 698857f3346a3cbba5442f1463f816bb78a52039..72397e75806a7efa6d657738d43e13279adc5fe2 100644 (file)
 #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 @@ repeat:
        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 @@ static int dup_mmap(struct task_struct * tsk)
        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 & 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++;
+       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;
 }
 
-/*
- * 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_fs(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.. */
+       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)]++;
 }
 
-static void copy_fs(unsigned long clone_flags, struct task_struct * p)
+static void copy_files(unsigned long clone_flags, struct allocation_struct * u)
 {
-       if (current->fs->pwd)
-               current->fs->pwd->i_count++;
-       if (current->fs->root)
-               current->fs->root->i_count++;
+       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_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 do_fork(unsigned long clone_flags, unsigned long usp, struct pt_regs *regs)
        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 @@ int do_fork(unsigned long clone_flags, unsigned long usp, struct pt_regs *regs)
        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;
index 8a68032d4762b006132e31c845b33bb751d9ab46..c616c86e829b0e14b4384dc2073312c5ba40f973 100644 (file)
@@ -149,7 +149,7 @@ struct symbol_table symbol_table = {
        X(__get_free_pages),
        X(free_pages),
        X(kmalloc),
-       X(kfree_s),
+       X(kfree),
        X(vmalloc),
        X(vremap),
        X(vfree),
index a93ec36dee175a54e5d79ba21a3ecee36eefd9a9..911a414a909d7a0bb5e7623ba0b4709e82454d26 100644 (file)
@@ -81,6 +81,10 @@ extern int timer_interrupt(void);
 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;
index 53ffef5737799dad3120435f5aff9fe082715b02..b90fc3dc47923986db8c087eaa509310beb1f323 100644 (file)
@@ -433,11 +433,11 @@ asmlinkage unsigned long sys_brk(unsigned long brk)
         * 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
index 8bea4ed2e5c0fd68774cb3aad272f441127a2229..c78a819ecdb46f00e8d22be1f39bcf5190fea866 100644 (file)
@@ -103,10 +103,11 @@ void time_init(void)
            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
index 04134503f654b99a148d4bcfa85f809e6f0003ab..cc85594f8bb694b6fa96d1c737dec5dfe6c8435d 100644 (file)
@@ -133,7 +133,7 @@ int filemap_swapout(struct vm_area_struct * vma,
        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 @@ static inline int filemap_sync_pte(pte_t * ptep, struct vm_area_struct *vma,
                        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 {
index 70ea181efa9bd285982faf75fd6ed9e243345a12..3f061818cf66fc56ad50548a5989f0ed07d001d5 100644 (file)
 /* 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 @@ struct block_header {
 #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 page_descriptor {
  */
 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 @@ struct size_descriptor {
        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 @@ struct size_descriptor {
  * 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 @@ struct size_descriptor sizes[] = {
 #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");
+       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;
        }
-        return NULL;
-    }
-#if 0
-    printk ("Got page %08x to use for %d byte mallocs....",(long)page,sz);
-#endif
-    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); 
-    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);
 }
index 5e76966d3988f82c54f41ff21d32cc6bb9b84d76..ff930b80e0e87a47422ea9f42f863b1bc3f0f45b 100644 (file)
@@ -232,19 +232,19 @@ static inline void copy_one_pte(pte_t * old_pte, pte_t * new_pte)
                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 @@ static inline void zeromap_pte_range(pte_t * pte, unsigned long address, unsigne
                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 @@ static inline void remap_pte_range(pte_t * pte, unsigned long address, unsigned
                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 @@ unsigned long put_dirty_page(struct task_struct * tsk, unsigned long page, unsig
                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 @@ void do_wp_page(struct vm_area_struct * vma, unsigned long address,
                        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 @@ static int try_to_share(unsigned long to_address, struct vm_area_struct * to_are
                                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 @@ static int try_to_share(unsigned long to_address, struct vm_area_struct * to_are
        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 @@ static inline void do_swap_page(struct vm_area_struct * vma, unsigned long addre
                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 @@ static inline void handle_pte_fault(struct vm_area_struct * vma, unsigned long a
                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);
index ecf73730c04511b8d6214b1e5dd039e14bedc136..571693f927a09a96175304af7a842f9e0a9810b8 100644 (file)
@@ -38,7 +38,7 @@ static inline void change_pte_range(pmd_t * pmd, unsigned long address,
        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);
index 0c6a82bc14d85477f9f180e9d6dd90547b5149ea..6bd76938cb1b5f183d9b15d6e4d44a73691a1182 100644 (file)
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -320,7 +320,7 @@ void swap_in(struct vm_area_struct * vma, pte_t * page_table,
                return;
        }
        if (!page) {
-               *page_table = BAD_PAGE;
+               set_pte(page_table, BAD_PAGE);
                swap_free(entry);
                oom(current);
                return;
@@ -333,10 +333,10 @@ void swap_in(struct vm_area_struct * vma, pte_t * page_table,
        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 @@ static inline int try_to_swap_out(struct vm_area_struct* vma, unsigned long addr
        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 @@ static inline int try_to_swap_out(struct vm_area_struct* vma, unsigned long addr
                        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 @@ static inline int try_to_swap_out(struct vm_area_struct* vma, unsigned long addr
        }
         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 @@ static inline int unuse_pte(struct vm_area_struct * vma, unsigned long address,
                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 @@ static inline int unuse_pte(struct vm_area_struct * vma, unsigned long address,
                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;
index 1155e981043e5352a5b2c3208548fca9265f5343..fc778a65eaf5805b491f41ef0bc7953190923f04 100644 (file)
@@ -120,7 +120,7 @@ static inline int alloc_area_pte(pte_t * pte, unsigned long address, unsigned lo
                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 @@ static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned l
        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 @@ void * vmalloc(unsigned long size)
        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)
index adb4fc5edd027c8190379ce50439fb907add9f7d..c68d5619db4125d31f32f078d44180e2b593141d 100644 (file)
@@ -177,6 +177,17 @@ o  Sendmsg/recvmsg for AX.25/Appletalk             [IN]
 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]
index 33ffd8a4144f9d92d04ce6c86db8543813e976ef..7c9432a948b32d06d1fb2de50edfc7f364a3ec3a 100644 (file)
@@ -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 @@ For commercial UK custom Linux networking projects, drivers and development
        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 --git a/net/ax25/README.AX25 b/net/ax25/README.AX25
deleted file mode 100644 (file)
index c7ebdf4..0000000
+++ /dev/null
@@ -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
index 673b325777687da70d3708cf5ea3e9c6fbb16cc1..f04905c12b818a8bbd48f77dbc9804372a4435dd 100644 (file)
@@ -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.
 struct packet_type *ptype_base[16];
 struct packet_type *ptype_all = NULL;          /* Taps */
 
+/*
+ *     Device list lock
+ */
+int dev_lockct=0;
 /*
  *     Our notifier list
  */
@@ -242,45 +249,42 @@ int dev_open(struct device *dev)
  
 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 @@ static int dev_ifsioc(void *arg, unsigned int getset)
                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 |
index 98a2d959cc4411ccf72326ab56ad0a3784a50364..ae0a78b933a18efa56fa84183a57a655393af041 100644 (file)
@@ -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 --git a/net/ipv4/README.TCP b/net/ipv4/README.TCP
deleted file mode 100644 (file)
index f18963f..0000000
+++ /dev/null
@@ -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. 
-
index 4a9c16a1c5db9fe680355d2fe903221f7557e191..dae9678089f6839814b2264d635b7513acfe9e99 100644 (file)
@@ -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 @@ static int inet_create(struct socket *sock, int protocol)
        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 @@ static int inet_connect(struct socket *sock, struct sockaddr * uaddr,
        {
                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 @@ static int inet_connect(struct socket *sock, struct sockaddr * uaddr,
                   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 @@ static int inet_connect(struct socket *sock, struct sockaddr * uaddr,
        if (sk->state != TCP_ESTABLISHED && sk->err) 
        {
                sock->state = SS_UNCONNECTED;
+               cli();
                err=sk->err;
                sk->err=0;
+               sti();
                return(-err);
        }
        return(0);
index 7ddbc46837e3f51d162b2830ff4a63483bff0da5..7a8cdc0a1996b82ffe1cedad65820141fbb38202 100644 (file)
@@ -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 @@ static void arp_release_entry(struct arp_table *entry)
                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 @@ ugly:
        {
                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();
index 794a7e897b0101630b714fb44a7f01440640fcbc..f9ca468317799323025a1ae78274d0c27be2878f 100644 (file)
@@ -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 @@ struct device * ip_dev_check(unsigned long addr)
        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;
+}
index 43b4c1132841a402b7b90c4cd4b3395594eeb0f6..80a4843de2bec1e5e0a8e765db435728a13e21ed 100644 (file)
  *                                     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 @@ extern __inline__ int random(void)
  *     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 @@ static void igmp_send_report(struct device *dev, unsigned long address, int type
        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 @@ static void igmp_send_report(struct device *dev, unsigned long address, int type
        }
        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 @@ static void igmp_timer_expire(unsigned long data)
        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_init_timer(struct ip_mc_list *im)
 }
        
 
-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 @@ extern __inline__ void igmp_heard_report(struct device *dev, unsigned long addre
                        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 @@ extern __inline__ void igmp_group_dropped(struct ip_mc_list *im)
        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 @@ int igmp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
        /* 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 @@ void ip_mc_allhost(struct device *dev)
        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);
index 6deb43646a7fe0a931e211dce2a27876a3cce5d5..f203ff1a4501d7f7498d39b91ed763156da93bab 100644 (file)
@@ -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.
  *
  *  
  *
 #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 @@ int ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
        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 @@ int ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
 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 @@ void ip_queue_xmit(struct sock *sk, struct device *dev,
        {
                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 @@ void ip_queue_xmit(struct sock *sk, struct device *dev,
        }
        else
        {
+               if(sk)
+                       sk->err = ENETDOWN;
                ip_statistics.IpOutDiscards++;
                if (free)
                        kfree_skb(skb, FREE_WRITE);
@@ -2069,18 +2075,28 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt
        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 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt
                                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 @@ int ip_getsockopt(struct sock *sk, int level, int optname, char *optval, int *op
        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 @@ int ip_getsockopt(struct sock *sk, int level, int optname, char *optval, int *op
                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 @@ int ip_build_xmit(struct sock *sk,
                                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 @@ int ip_build_xmit(struct sock *sk,
                }
                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 @@ int ip_build_xmit(struct sock *sk,
                        
                        
        fragheaderlen = dev->hard_header_len;
-       if(type != IPPROTO_RAW)
+       if(!sk->ip_hdrincl)
                fragheaderlen += 20;
                
        /*
@@ -2598,9 +2631,15 @@ int ip_build_xmit(struct sock *sk,
         *      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 @@ int ip_build_xmit(struct sock *sk,
                        ip_statistics.IpOutDiscards++;
                        if(nfrags>1)
                                ip_statistics.IpFragCreates++;                  
+                       dev_unlock_list();
                        return(error);
                }
                
@@ -2674,7 +2714,7 @@ int ip_build_xmit(struct sock *sk,
                 *      Only write IP header onto non-raw packets 
                 */
                 
-               if(type != IPPROTO_RAW
+               if(!sk->ip_hdrincl
                {
 
                        iph->version = 4;
@@ -2732,11 +2772,13 @@ int ip_build_xmit(struct sock *sk,
                        /*
                         *      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 @@ int ip_build_xmit(struct sock *sk,
                {
                        /*
                         *      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);
 }
     
index d960f2869baec349e6010689de7c1db62d99b2c1..32a78f00a410d64b74bd46670a54d238eae09986 100644 (file)
@@ -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 @@ int ip_fw_chk(struct iphdr *ip, struct device *rif, struct ip_fw *chain, int pol
        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 @@ int ip_fw_chk(struct iphdr *ip, struct device *rif, struct ip_fw *chain, int pol
         *      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;
 
index 730f5fccfe0d7382310596e34d6b253ff2ff0d03..519d1077924e242a75b583f00fa415f46a84090d 100644 (file)
@@ -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>
 #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 @@ static char kernel_version[] = UTS_RELEASE;
 
 
 /*
- *     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 --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
new file mode 100644 (file)
index 0000000..72bdd2d
--- /dev/null
@@ -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
index f10cc82545607aff297df91c52230fe60ab19bbb..14c56bfe3836297db170c6ef97133985fa7c60d9 100644 (file)
@@ -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 @@ inet_add_protocol(struct inet_protocol *prot)
                prot->copy = 1;
                break;
        }
-       p2 = (struct inet_protocol *) prot->next;
+       p2 = (struct inet_protocol *) p2->next;
   }
 }
 
index 0339895ad54fa448d84fb4758edd1a94aff52e1e..c9999f13b9577b1f486d76cfa0023ac5ae5ca295 100644 (file)
@@ -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>
 #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 @@ static int raw_sendto(struct sock *sk, const unsigned char *from,
        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 int raw_write(struct sock *sk, const unsigned char *buff, int len, int no
 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 raw_recvfrom(struct sock *sk, unsigned char *to, int len,
        int copied=0;
        struct sk_buff *skb;
        int err;
-       int truesize;
 
        if (flags & MSG_OOB)
                return -EOPNOTSUPP;
@@ -253,9 +266,8 @@ int raw_recvfrom(struct sock *sk, unsigned char *to, int len,
        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 @@ int raw_recvfrom(struct sock *sk, unsigned char *to, int len,
        }
        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 @@ struct proto raw_prot = {
        NULL,
        NULL,
        datagram_select,
+#ifdef CONFIG_IP_MROUTE        
+       ipmr_ioctl,
+#else
        NULL,
+#endif         
        raw_init,
        NULL,
        ip_setsockopt,
index 3a5aea847832618c2a37e9306a786de2b8040dfb..06bb1ef0a2161453bd399b8c4ea5489b4dfaa1de 100644 (file)
@@ -879,22 +879,21 @@ void tcp_err(int err, unsigned char *header, unsigned long daddr,
                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;
 }
index 9dfb716a30e0d1d68e9167e5095db1f6f6b332f2..231dc6d37920abd9e4c193dd61375966f60e4063 100644 (file)
@@ -189,9 +189,10 @@ void udp_err(int err, unsigned char *header, unsigned long daddr,
        /* 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);
        }
 }
index 37f3c4edce34a25441b632cbf1f10a7b4a995d3a..e91b9ec61cdaa28e199f44de631da44eca96c1c3 100644 (file)
@@ -524,6 +524,7 @@ static int unix_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le
                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 @@ static int unix_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le
         */
         
        sock->state=SS_CONNECTED;
+       sti();
        return 0;
        
 }
@@ -722,6 +724,7 @@ static int unix_sendmsg(struct socket *sock, struct msghdr *msg, int len, int no
                        other->protinfo.af_unix.locks--;
                        sk->protinfo.af_unix.other=NULL;
                        sock->state=SS_UNCONNECTED;
+                       sti();
                        return -ECONNRESET;
                }
        }
@@ -732,6 +735,7 @@ static int unix_sendmsg(struct socket *sock, struct msghdr *msg, int len, int no
                if(other==NULL)
                {
                        kfree_skb(skb, FREE_WRITE);
+                       sti();
                        return err;
                }
        }
@@ -790,11 +794,18 @@ static int unix_recvmsg(struct socket *sock, struct msghdr *msg, int size, int n
                        {
                                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 @@ static int unix_recvmsg(struct socket *sock, struct msghdr *msg, int size, int n
                                                break;
                                }
                        }
+                       sti();
                }       
        }       
        up(&sk->protinfo.af_unix.readsem);
index 27d6be416993a03cb079aa6fb923cabb4d4870da..ba41e29d2b9a265650cff6846b5edfc1f4ec576d 100644 (file)
@@ -54,6 +54,22 @@ function comment () {
        (echo "" ; echo "/*"; echo " * $1" ; echo " */") >>$CONFIG_H
 }
 
+#
+# 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
 #
@@ -65,14 +81,18 @@ function bool () {
        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 @@ function int () {
        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
index 41aadcd6bc1eb1c591c0dca1ee0d12620eab4f37..905a04f71329e117d10610b1da14227c9f271061 100644 (file)
@@ -15,7 +15,7 @@ TOPINCL := $(TOPDIR)/include/linux
        $(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