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
--- /dev/null
+\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}
--- /dev/null
+ 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
--- /dev/null
+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
--- /dev/null
+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.
+
--- /dev/null
+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>
+
--- /dev/null
+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!
+
--- /dev/null
+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>
--- /dev/null
+
+-----------------------------------------------------------------------------
+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.
--- /dev/null
+
+----------------------------------------------------------------------------
+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.
--- /dev/null
+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
--- /dev/null
+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)
--- /dev/null
+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.
+
--- /dev/null
+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.
VERSION = 1
PATCHLEVEL = 3
-SUBLEVEL = 21
+SUBLEVEL = 22
ARCH = i386
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
+++ /dev/null
-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>
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
# 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
$(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:
.sbss : {
*(.sbss)
*(.scommon)
+ . = ALIGN(16);
}
.bss : {
*(.bss)
# 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
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
$(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
--- /dev/null
+/*
+ * 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 */
#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.
}
}
/* 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);
}
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:
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));
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;
}
}
#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);
}
/*
* 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];
#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.
*
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
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:
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
.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)
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
.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
/* 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
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);
}
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);
}
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",
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
}
}
struct irqaction * action;
unsigned long flags;
- if (irq > 15)
+ if (irq >= NUM_IRQS)
return -EINVAL;
action = irq + irq_action;
if (action->handler)
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;
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;
}
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));
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
*
* 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);
/* 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;
}
* 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
}
machine_check(vector, la_ptr, ®s);
break;
case 3:
- device_interrupt(vector, ®s);
+#if defined(CONFIG_ALPHA_JENSEN) || defined(CONFIG_ALPHA_NONAME)
+ srm_device_interrupt(vector, ®s);
+#elif defined(CONFIG_ALPHA_CABRIOLET) || defined(CONFIG_ALPHA_EB66P)
+ cabriolet_and_eb66p_device_interrupt(vector, ®s);
+#elif defined(CONFIG_ALPHA_EB66) || defined(CONFIG_ALPHA_EB64P)
+ eb66_and_eb64p_device_interrupt(vector, ®s);
+#endif
return;
case 4:
printk("Performance counter interrupt\n");
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
}
#include <linux/bios32.h>
#include <linux/pci.h>
+#include <asm/ptrace.h>
#include <asm/system.h>
#include <asm/io.h>
* BIOS32-style PCI interface:
*/
-#ifdef CONFIG_PCI
+#ifdef CONFIG_ALPHA_LCA
#define vulp volatile unsigned long *
if (device > 12) {
return -1;
- } /* if */
+ }
*((volatile unsigned long*) LCA_IOC_CONF) = 0;
addr = (1 << (11 + device)) | (func << 8) | where;
/* 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);
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);
mb();
wrmces(0x7); /* reset machine check */
}
- swpipl(old_ipl);
+ restore_flags(flags);
}
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
*(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 */
*/
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);
* 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, ®s);
}
/* 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>
#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)
}
/*
- * 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;
}
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)) {
*(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;
{
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;
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) {
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;
/*
* 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;
* 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;
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;
*/
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;
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];
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(®s,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(®s,-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(®s,-EPERM);
+ if (pid == 1) /* you may not mess with init */
return -EPERM;
- }
- if (!(child = get_task(pid))) {
- set_failure(®s,-ESRCH);
+ if (!(child = get_task(pid)))
return -ESRCH;
- }
if (request == PTRACE_ATTACH) {
- if (child == current) {
- set_failure(®s,-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(®s,-EPERM);
+ (current->gid != child->gid)) && !suser())
return -EPERM;
- }
/* the same process cannot be attached many times */
- if (child->flags & PF_PTRACED) {
- set_failure(®s,-EPERM);
+ if (child->flags & PF_PTRACED)
return -EPERM;
- }
child->flags |= PF_PTRACED;
if (child->p_pptr != current) {
REMOVE_LINKS(child);
}
if (!(child->flags & PF_PTRACED)) {
DBG(DBG_MEM, ("child not traced\n"));
- set_failure(®s,-ESRCH);
return -ESRCH;
}
if (child->state != TASK_STOPPED) {
DBG(DBG_MEM, ("child process not stopped\n"));
- if (request != PTRACE_KILL) {
- set_failure(®s,-ESRCH);
+ if (request != PTRACE_KILL)
return -ESRCH;
- }
}
if (child->p_pptr != current) {
DBG(DBG_MEM, ("child not parent of this process\n"));
- set_failure(®s,-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(®s,res);
+ DBG(DBG_MEM, ("peek %#lx->%#lx\n", addr, tmp));
+ if (res < 0)
return res;
- } else {
- set_success(®s,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(®s, -EIO);
- return -EIO;
- }
- tmp = get_stack_long(child, addr);
- DBG(DBG_MEM, ("%d = reg 0x%lx=tmp\n",reg,tmp));
- }
- set_success(®s,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(®s,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(®s,-EIO);
- return -EIO;
- }
- res = put_stack_long(child, addr, data);
- if (res) {
- set_failure(®s,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(®s,-EIO);
+ if ((unsigned long) data > NSIG)
return -EIO;
- }
if (request == PTRACE_SYSCALL)
child->flags |= PF_TRACESYS;
else
wake_up_process(child);
/* make sure single-step breakpoint is gone. */
ptrace_cancel_bpt(child);
- set_success(®s,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(®s,-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;
}
case PTRACE_DETACH: { /* detach a process that was attached. */
- if ((unsigned long) data > NSIG) {
- set_failure(®s,-EIO);
+ if ((unsigned long) data > NSIG)
return -EIO;
- }
child->flags &= ~(PF_PTRACED|PF_TRACESYS);
wake_up_process(child);
child->exit_code = data;
}
default:
- set_failure(®s,-EIO);
return -EIO;
}
}
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;
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';
*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
}
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"
"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,
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
}
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..
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;
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);
current->state = TASK_STOPPED;
notify_parent(current);
schedule();
+ single_stepping |= ptrace_cancel_bpt(current);
if (!(signr = current->exit_code))
continue;
current->exit_code = 0;
SA_NOCLDSTOP))
notify_parent(current);
schedule();
+ single_stepping |= ptrace_cancel_bpt(current);
continue;
case SIGQUIT: case SIGILL: case SIGTRAP:
(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;
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;
}
* This file initializes the trap entry points
*/
+#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/tty.h>
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)
}
/*
- * 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);
+ }
}
/*
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
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
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
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;
return irqs;
}
-int probe_irq_off (unsigned int irqs)
+int probe_irq_off (unsigned long irqs)
{
unsigned int i, irqmask;
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;
asmlinkage int sys_fork(struct pt_regs regs)
{
- return do_fork(COPYVM | SIGCHLD, regs.esp, ®s);
+ return do_fork(SIGCHLD, regs.esp, ®s);
}
asmlinkage int sys_clone(struct pt_regs regs)
{
-#ifdef CLONE_ACTUALLY_WORKS_OK
unsigned long clone_flags;
unsigned long newsp;
clone_flags = regs.ecx;
if (!newsp)
newsp = regs.esp;
- if (newsp == regs.esp)
- clone_flags |= COPYVM;
return do_fork(clone_flags, newsp, ®s);
-#else
- return -ENOSYS;
-#endif
}
/*
*(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();
}
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();
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;
#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;
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;
}
/*
}
/* 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();
}
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;
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);
}
/*
#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);
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)
/* 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;
flush_vac_context();
}
+void
+sun4c_set_pte(pte_t *ptep, pte_t entry)
+{
+ /* for now... */
+ *ptep = entry;
+}
+
void
sun4c_switch_to_context(int context)
{
/* 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;
-$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
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
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
- 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"
*** 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
"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.
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
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.
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.
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.)
o Read digital audio (i.e. copy directly), due to missing
hardware features.
+
+
+heiko@lotte.sax.de
-#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 !
*/
#define AZT_TEST4 /* QUICK_LOOP-counter */
#define AZT_TEST5 /* port(1) state */
#define AZT_DEBUG
+#define AZT_DEBUG_MULTISESSION
#endif
#define CURRENT_VALID \
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);
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);
#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;
printk("aztcd: Error aztStatTimer: Timeout\n");
return;
}
- SET_TIMER(aztStatTimer, 1);
+ SET_TIMER(aztStatTimer, HZ/100);
}
void aztcd_setup(char *str, int *ints)
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 ???
}
aztAudioStatus = CDROM_AUDIO_PLAY;
break;
-#if AZT_MULTISESSION
case CDROMMULTISESSION: /*multisession support -- experimental*/
{ struct cdrom_multisession ms;
#ifdef AZT_DEBUG
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;
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;
}
}
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);
}
azt_state = AZT_S_START;
AztTries = 5;
- SET_TIMER(azt_poll, 1);
+ SET_TIMER(azt_poll, HZ/100);
}
break;
}
STEN_LOW_WAIT;
};
- SET_TIMER(azt_poll, 1);
+ SET_TIMER(azt_poll, HZ/100);
}
static void azt_invalidate_buffers(void)
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;
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)) {
{ 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?*/
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
* 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
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);
}
-/*
- * 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;
}
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;
}
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
#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)
#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)
}
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);
result_buffer[0] = 0x20;
result_buffer[1] = SONY_SIGNAL_OP_ERR;
*result_size = 2;
+ restore_flags(flags);
return;
}
}
{
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;
}
interruptible_sleep_on(&sony_wait);
if (current->signal & ~current->blocked)
{
+ restore_flags(flags);
return -EAGAIN;
}
}
#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
} 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);
}
}
static int output_byte(char byte)
{
int counter;
- unsigned char status;
+ unsigned char status = 0; /* keep gcc quiet */
unsigned char rstatus;
if (FDCS->reset)
/* 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;
* 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>
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
* 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);
/*
- * 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)
/*
#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)
{
}
/*
- * 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)
{
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
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 {
#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,
((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)) {
*/
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)
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:
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 */
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 */
}
}
+#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.
* "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;
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;
}
}
printk(" -- BAD OPTION\n");
return;
bad_hwif:
- printk("-- NOT SUPPORTED ON ide%d", hwif);
+ printk("-- NOT SUPPORTED ON ide%d", hw);
done:
printk("\n");
}
* 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)
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;
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, ®))
+ || (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, ®))
+ || (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
/*
* 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 */
/*
#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 */
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 */
#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 */
return;
}
release_region(mcd_port,4);
+ free_irq(mcd_irq);
printk("mcd module released.\n");
}
#endif MODULE
/*
* 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
#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>
#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
#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 *******************************************************/
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;
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;
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
#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);
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);
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 ************************************************/
/* 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,
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)
|| (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;
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));
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;
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);
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))))
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;
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;
return 0;
}
+ case CDROMVOLCTRL: {
+ TRACE((IOCTL, "ioctl() volctrl\n"));
+ return 0;
+ }
+
default:
WARN(("ioctl(): unknown request 0x%04x\n", cmd));
return -EINVAL;
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;
}
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;
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;
break;
default:
- panic(MCD "do_request: unknown command.\n");
+ panic(MCDX "do_request: unknown command.\n");
break;
}
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
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"));
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,
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;
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;
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
}
/* 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
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;
}
* returns -1 on timeout, drive status otherwise
*/
{
- const DELAY = 1; /* minimum delay */
char c;
int st;
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);
}
}
- if (!drives) {
- WARN(("init_module() cannot init any drive\n"));
+ if (!drives)
return -EIO;
- }
return 0;
}
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
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++)
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));
/* 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 */
}
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;
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 */
}
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);
}
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));
}
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)
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))
|| 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;
/* 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;
}
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;
&& (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;
}
#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];
sub->dt.minute = buf[8];
sub->dt.second = buf[9];
sub->dt.frame = buf[10];
+
return ans;
}
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];
{
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];
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;
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);
}
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
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
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];
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
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;
+}
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>
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;
}
}
}
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
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--)
{
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
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--)
{
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
}
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; ; )
{
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;
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
{
if (!(i&s_not_result_ready)) break;
}
if ((j!=0)||(timeout<jiffies)) break;
- sbp_sleep(1);
+ sbp_sleep(HZ/100);
j = 1;
}
while (1);
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
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];
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);
}
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();
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
{
i=cc_LockDoor(0);
--j;
- sbp_sleep(1);
+ sbp_sleep(HZ/100);
}
while ((i<0)&&(j));
if (i<0)
{
i=cc_LockDoor(1);
--j;
- sbp_sleep(1);
+ sbp_sleep(HZ/100);
}
while ((i<0)&&(j));
if (j==0)
{
i=cc_LockDoor(1);
--j;
- sbp_sleep(1);
+ sbp_sleep(HZ/100);
}
while ((i<0)&&(j));
}
#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);
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;
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);
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--)
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)
{
for (frame=1;frame<2 && !error_flag; frame++)
{
try=maxtim_data;
- for (timeout=jiffies+900; ; )
+ for (timeout=jiffies+9*HZ; ; )
{
for ( ; try!=0;try--)
{
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)
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--)
{
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;
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;
{
SBPCD_CLI;
i=maxtim_data;
- for (timeout=jiffies+100; timeout > jiffies; timeout--)
+ for (timeout=jiffies+HZ; timeout > jiffies; timeout--)
{
for ( ;i!=0;i--)
{
if (!famL_drive)
{
OUT(CDo_reset,0);
- sbp_sleep(100);
+ sbp_sleep(HZ);
}
#endif 0
D_S[d].error_byte);
if (D_S[d].error_byte==aud_12)
{
- timeout=jiffies+200;
+ timeout=jiffies+2*HZ;
do
{
i=GetStatus();
} 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" );
/*
* Get back in some time.
*/
- SJCD_SET_TIMER( sjcd_poll, 1 );
+ SJCD_SET_TIMER( sjcd_poll, HZ/100 );
}
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;
}
/*
- * 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
* 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.
* 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>
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;
}
/*
- * 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:
*/
* 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;
+// 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
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!
------------
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
+++ /dev/null
-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.
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;
}
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. */
* 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)
;
base_addr[CySRER] |= CyTxMpty;
sti();
- timeout = jiffies+2;
+ timeout = jiffies+2*HZ/100;
while (timeout >= jiffies) {
if (cy_irq_triggered)
break;
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);
return -ENODEV;
switch ( cmd ) {
case LPTIME:
- LP_TIME(minor) = arg;
+ LP_TIME(minor) = arg * HZ/100;
break;
case LPCHAR:
LP_CHAR(minor) = arg;
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;
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;
#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 */
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++;
}
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) {
#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);
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);
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];
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 * */
/* * 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)
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);
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;
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++)
abp = bp->anext;
while (bp) bp = scc_return_buffer(bp, type);
- restore_flags(flags); cli();
+ restore_flags(flags);
return abp;
}
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 */
/* 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)
{
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)
static void
scc_rxint(register struct scc_channel *scc)
{
- unsigned char ch;
+ register struct mbuf *bp;
scc->stat.rxints++;
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);
}
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);
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 */
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
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;
}
+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 * */
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:
}
+/* ----> 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... * */
/* ******************************************************************* */
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 */
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;
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)
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;
}
scc->kiss.softdcd = 0; /* hardware dcd */
}
- scc->init = 1;
+ scc->init = 1;
return 0;
}
restore_flags(flags);
- put_fs_long(result,(unsigned long *) arg);
+ put_user_long(result,(unsigned int *) arg);
return 0;
case TIOCMBIS:
case TIOCMBIC:
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;
scc->sndq1->anext = bp;
}
-
}
/* 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;
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;
}
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 */
}
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;
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
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)
/* 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 * */
long scc_init (long kmem_start)
{
-
- int chip;
-#ifdef VERBOSE_BOOTMSG
- int chan;
-#endif
+ int chip, chan;
register io_port ctrl;
long flags;
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");
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);
#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 */
#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
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)
}
}
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]) {
/*
* 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;
/*
(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) {
* 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)
;
(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;
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;
/* 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... */
}
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)
#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 */
} 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;
+++ /dev/null
-
-----------------------------------------------------------------------------
-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.
+++ /dev/null
-
------------------------------------------------------------------------------
-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.
+++ /dev/null
-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)
#endif /* SHUTDOWN_WHEN_LOST */
was_down = 1;
dev->tbusy = 1; /* Transmit busy... */
+ restore_flags(flags);
return 1; /* failed */
}
#endif /* CHECK_LOST_DE600 */
{
prev->next = current->next;
queue->num_slaves--;
+ sti();
return current;
}
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);
}
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;
}
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"),
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"),
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"),
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"),
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")
};
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";
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";
}
}
#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
/*
* 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.
*/
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;
* 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;
}
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);
}
} else if (istat & ISTAT_DIP) {
NCR53c7x0_write8(hostdata->istat, 0);
+ mb();
tmp = NCR53c7x0_read8(DSTAT_REG);
if (tmp & DSTAT_ABRT)
break;
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
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
(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
{
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));
return 0;
}
} else {
- save_flags(flags);
cli();
while (len--)
{
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;
}
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) {
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)
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)
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)
#error "Buffer size should not exceed (2 << 24 - 1) bytes!"
#endif
-#ifdef DEBUG
+#if DEBUG
static int debugging = 1;
#endif
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 *);
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],
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
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
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)
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);
}
}
+ if (STp->block_size == 0)
+ return 0;
+
result = 0;
if (STp->dirty == 1) {
SCpnt = allocate_device(NULL, STp->device, 1);
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
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) {
0, st_sleep_done, ST_LONG_TIMEOUT,
MAX_READY_RETRIES);
-
/* this must be done with interrupts off */
save_flags (processor_flags);
cli();
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;
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;
}
(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();
((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);
}
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
(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();
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);
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;
}
(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,
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
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)) {
(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);
}
-#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;
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);
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)
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);
(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
}
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);
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
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,
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);
(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)
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);
(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();
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],
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);
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",
}
} /* 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
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);
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);
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) {
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
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;
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]);
cmd[2] = (ltmp >> 16);
cmd[3] = (ltmp >> 8);
cmd[4] = ltmp;
-#ifdef DEBUG
+#if DEBUG
if (debugging) {
if (cmd[2] & 0x80)
ltmp = 0xff000000;
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]);
cmd[2] = (ltmp >> 16);
cmd[3] = (ltmp >> 8);
cmd[4] = ltmp;
-#ifdef DEBUG
+#if DEBUG
if (debugging) {
if (cmd[2] & 0x80)
ltmp = 0xff000000;
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]);
cmd[2] = (ltmp >> 16);
cmd[3] = (ltmp >> 8);
cmd[4] = ltmp;
-#ifdef DEBUG
+#if DEBUG
if (debugging) {
if (cmd[2] & 0x80)
ltmp = 0xff000000;
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,
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
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
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
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
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;
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
(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,
(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;
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)
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;
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);
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;
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 &&
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);
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
(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
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
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;
};
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;
}
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
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;
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;
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)
struct wait_queue * waiting;
Scsi_Device* device;
unsigned char dirty;
+ unsigned char write_pending;
unsigned char rw;
unsigned char ready;
unsigned char eof;
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;
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
#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
--- /dev/null
+/*
+ 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
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;
}
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) {
ifdef CONFIG_HPFS_FS
SUB_DIRS += hpfs
+else
+MOD_SUB_DIRS += hpfs
endif
ifdef CONFIG_BINFMT_ELF
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>
}
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;
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;
/* 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)){
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");
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;
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 */
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) {
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 */
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;
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);
+++ /dev/null
-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
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,
* 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>
int conv;
int dubious;
+ MOD_INC_USE_COUNT;
+
/*
* Get the mount options
*/
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;
}
if (!s->s_mounted) {
printk("HPFS: hpfs_read_super: inode get failed\n");
s->s_dev = 0;
+ MOD_DEC_USE_COUNT;
return 0;
}
printk("HPFS: "
"hpfs_read_super: root dir isn't in the root dir\n");
s->s_dev = 0;
+ MOD_DEC_USE_COUNT;
return 0;
}
bail:
s->s_dev = 0;
unlock_super(s);
+ MOD_DEC_USE_COUNT;
return 0;
}
lock_super(s);
s->s_dev = 0;
unlock_super(s);
+ MOD_DEC_USE_COUNT;
}
/*
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
+
nh->data=NULL;
nh->free=1;
}
+ restore_flags(flags);
}
void nfs_bl_cache_revalidate(nfs_cache *nh, struct fattr fa)
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,¤t->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)
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;
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,¤t->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)
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;
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) {
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;
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:
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;
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];
* 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)
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
+++ /dev/null
-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.
-
static char unnamed_dev_in_use[256/8] = { 0, };
-static dev_t get_unnamed_dev(void)
+dev_t get_unnamed_dev(void)
{
int i;
return 0;
}
-static void put_unnamed_dev(dev_t dev)
+void put_unnamed_dev(dev_t dev)
{
if (!dev)
return;
* 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;
+++ /dev/null
-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>
-
+++ /dev/null
-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!
-
--- /dev/null
+#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__ */
__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;
}
__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;
}
__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));
}
/*
* 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;
* "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__
-#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,
extern inline void __writeb(unsigned char b, unsigned long addr)
{
unsigned long msb;
+ unsigned int w;
if (addr >= (1UL << 24)) {
msb = addr & 0xf8000000;
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;
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)
#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__ */
".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)
-#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);
#define __HAVE_ARCH_STRLEN
-#endif
+#endif /* __ALPHA_STRING_H__ */
#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;
}
#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;
}
#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;
}
/*
- * 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;
#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
#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__
__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"
{ __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)
--- /dev/null
+/* $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 */
#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)
#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
#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
*/
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)
-/* $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 */
#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 */
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;
};
/*
* 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
#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'.
#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
#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
#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{
* 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
-/* $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 */
* 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
#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
#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 */
#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
struct msf trackTime;
struct msf diskTime;
};
+
+#ifndef I_WAS_HERE
+#error Please edit this file first.
+#endif
/*
* 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
#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
--- /dev/null
+#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
-/* $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
*/
#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.) */
#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 {
#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 */
/* 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 */
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);
* 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.
#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
+/* $Id: scc.h,v 1.11 1995/08/24 21:06:24 jreuter Exp jreuter $ */
#ifndef _SCC_H
#define _SCC_H
/* 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
/* 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 */
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 */
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 */
#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 */
};
#define INIT_FILES { \
- 0, \
+ 1, \
{ { 0, } }, \
{ NULL, } \
}
};
#define INIT_FS { \
- 0, \
+ 1, \
0022, \
NULL, NULL \
}
};
#define INIT_MM { \
- 0, \
+ 1, \
0, 0, 0, 0, \
0, 0, 0, 0, \
0, 0, 0, 0, \
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;
/* 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;
};
/*
* 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
/* 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, \
/* 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__
#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
#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 */
* 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
#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)
* 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>
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)
#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 */
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 */
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;
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;
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--;
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)
current->flags |= PF_EXITING;
del_timer(¤t->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);
/*
#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;
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;
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)]++;
}
/*
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;
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;
X(__get_free_pages),
X(free_pages),
X(kmalloc),
- X(kfree_s),
+ X(kfree),
X(vmalloc),
X(vremap),
X(vfree),
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;
* 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
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
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)
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 {
/* 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 {
#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;
*/
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;
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 */
};
/*
* 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
#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);
}
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))]++;
}
end = PMD_SIZE;
do {
pte_t oldpage = *pte;
- *pte = zero_pte;
+ set_pte(pte, zero_pte);
forget_pte(oldpage);
address += PAGE_SIZE;
pte++;
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;
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;
}
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);
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;
}
/*
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;
}
page = pte_wrprotect(page);
++vma->vm_task->mm->rss;
++vma->vm_task->mm->maj_flt;
- *page_table = page;
+ set_pte(page_table, page);
return;
}
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);
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);
return;
}
if (!page) {
- *page_table = BAD_PAGE;
+ set_pte(page_table, BAD_PAGE);
swap_free(entry);
oom(current);
return;
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;
}
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)) {
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);
}
}
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;
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)
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;
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++;
}
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++;
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)
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]
-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
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.
+++ /dev/null
-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
* 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
*/
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);
}
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 |
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
+++ /dev/null
-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.
-
* 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
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;
{
if(sk->err!=0)
{
+ cli();
err=sk->err;
sk->err=0;
+ sti();
return -err;
}
return -EALREADY; /* Connecting is currently in progress */
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() */
}
}
if (sk->state != TCP_ESTABLISHED && sk->err)
{
sock->state = SS_UNCONNECTED;
+ cli();
err=sk->err;
sk->err=0;
+ sti();
return(-err);
}
return(0);
* Mike Shaver : RFC1122 checks.
* Jonathan Naylor : Only lookup the hardware address for
* the correct hardware type.
+ * Germano Caronni : Assorted subtle races
*/
/* RFC1122 Status:
skb_device_lock(skb);
restore_flags(flags);
dev_kfree_skb(skb, FREE_WRITE);
+ cli();
}
restore_flags(flags);
del_timer(&entry->timer);
{
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();
* Alan Cox, <gw4pts@gw4pts.ampr.org>
*/
+#include <linux/config.h>
#include <asm/segment.h>
#include <asm/system.h>
#include <asm/bitops.h>
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;
+}
* 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.
*/
*/
-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;
* 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)
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);
}
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 */
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);
}
-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)
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);
+ }
}
/*
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,
/* 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;
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);
* 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
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
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)
{
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;
}
else
{
+ if(sk)
+ sk->err = ENETDOWN;
ip_statistics.IpOutDiscards++;
if (free)
kfree_skb(skb, FREE_WRITE);
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:
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:
{
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:
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;
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;
}
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
fragheaderlen = dev->hard_header_len;
- if(type != IPPROTO_RAW)
+ if(!sk->ip_hdrincl)
fragheaderlen += 20;
/*
* 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
*/
ip_statistics.IpOutDiscards++;
if(nfrags>1)
ip_statistics.IpFragCreates++;
+ dev_unlock_list();
return(error);
}
* Only write IP header onto non-raw packets
*/
- if(type != IPPROTO_RAW)
+ if(!sk->ip_hdrincl)
{
iph->version = 4;
/*
* 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
{
{
/*
* 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);
}
* 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
*
* 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 .....
*
*/
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
* 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;
* 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
*/
#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.
/*
- * 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;
--- /dev/null
+/*
+ * 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
* 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
prot->copy = 1;
break;
}
- p2 = (struct inet_protocol *) prot->next;
+ p2 = (struct inet_protocol *) p2->next;
}
}
* 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
#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)
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);
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
}
int copied=0;
struct sk_buff *skb;
int err;
- int truesize;
if (flags & MSG_OOB)
return -EOPNOTSUPP;
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;
}
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);
}
NULL,
NULL,
datagram_select,
+#ifdef CONFIG_IP_MROUTE
+ ipmr_ioctl,
+#else
NULL,
+#endif
raw_init,
NULL,
ip_setsockopt,
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;
}
/* 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);
}
}
sk->protinfo.af_unix.other->protinfo.af_unix.locks--;
sk->protinfo.af_unix.other=NULL;
sock->state=SS_UNCONNECTED;
+ sti();
return -ECONNREFUSED;
}
*/
sock->state=SS_CONNECTED;
+ sti();
return 0;
}
other->protinfo.af_unix.locks--;
sk->protinfo.af_unix.other=NULL;
sock->state=SS_UNCONNECTED;
+ sti();
return -ECONNRESET;
}
}
if(other==NULL)
{
kfree_skb(skb, FREE_WRITE);
+ sti();
return err;
}
}
{
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;
break;
}
}
+ sti();
}
}
up(&sk->protinfo.af_unix.readsem);
(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
#
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"
}
#
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
$(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