diff -u --recursive --new-file v2.1.117/linux/CREDITS linux/CREDITS
--- v2.1.117/linux/CREDITS	Thu Aug 20 17:05:15 1998
+++ linux/CREDITS	Tue Aug 25 13:49:08 1998
@@ -67,6 +67,7 @@
 D: Parport hacker
 D: Implemented a workaround for some interrupt buggy printers
 D: Author of pscan that helps to fix lp/parport bug
+D: Author of lil (Linux Interrupt Latency benchmark)
 D: Various other kernel hacks
 S: Via Ciaclini 26
 S: Imola 40026
@@ -333,18 +334,19 @@
 S: Australia
 
 N: Alan Cox
-E: alan@lxorguk.ukuu.org.uk (linux related - except big patches)
-E: iialan@www.uk.linux.org (linux.org.uk/big patches)
-E: alan@cymru.net (commercial CymruNET stuff)
+W: http://roadrunner.swansea.linux.org.uk/alan.shtml
+E: alan@lxorguk.ukuu.org.uk
+E: alan@www.linux.org.uk (linux.org.uk stuff)
 E: Alan.Cox@linux.org (if others fail)
-D: NET2Debugged/NET3 author
-D: Network layer debugging
-D: Initial AX.25 & IPX releases
-D: Original Linux netatalk patches.
+D: Linux Networking (0.99.10->2.0.29)
+D: Original Appletalk, AX.25, and IPX code
 D: Current 3c501 hacker. >>More 3c501 info/tricks wanted<<.
 D: Watchdog timer drivers
-D: Linux/SMP
-S: CymruNet Limited
+D: Linux/SMP x86 (up to 2.0 only)
+D: Initial Mac68K port
+D: Video4Linux design, bw-qcam and PMS driver ports.
+D: 2.1.x modular sound
+S: c/o I2IT Limited
 S: The Innovation Centre
 S: Singleton Park
 S: Swansea, SA2 8PP
diff -u --recursive --new-file v2.1.117/linux/Documentation/radiotrack.txt linux/Documentation/radiotrack.txt
--- v2.1.117/linux/Documentation/radiotrack.txt	Tue Aug 18 22:02:01 1998
+++ linux/Documentation/radiotrack.txt	Wed Dec 31 16:00:00 1969
@@ -1,147 +0,0 @@
-NOTES ON RADIOTRACK CARD CONTROL
-by Stephen M. Benoit (benoits@servicepro.com)  Dec 14, 1996
-----------------------------------------------------------------------------
-
-Document version 1.0
-
-ACKNOWLEDGMENTS
-----------------
-This document was made based on 'C' code for Linux from Gideon le Grange
-(legrang@active.co.za or legrang@cs.sun.ac.za) in 1994, and elaborations from
-Frans Brinkman (brinkman@esd.nl) in 1996.  The results reported here are from
-experiments that the author performed on his own setup, so your mileage may
-vary... I make no guarantees, claims or warrantees to the suitability or
-validity of this information.  No other documentation on the AIMS
-Lab (http://www.aimslab.com/) RadioTrack card was made available to the
-author.  This document is offered in the hopes that it might help users who
-want to use the RadioTrack card in an environment other than MS Windows.
-
-WHY THIS DOCUMENT?
-------------------
-I have a RadioTrack card from back when I ran an MS-Windows platform.  After
-converting to Linux, I found Gideon le Grange's command-line software for
-running the card, and found that it was good!  Frans Brinkman made a
-comfortable X-windows interface, and added a scanning feature.  For hack
-value, I wanted to see if the tuner could be tuned beyond the usual FM radio
-broadcast band, so I could pick up the audio carriers from North American
-broadcast TV channels, situated just below and above the 87.0-109.0 MHz range.
-I did not get much success, but I learned about programming ioports under
-Linux and gained some insights about the hardware design used for the card.
-
-So, without further delay, here are the details.
-
-
-PHYSICAL DESCRIPTION
---------------------
-The RadioTrack card is an ISA 8-bit FM radio card.  The radio frequency (RF)
-input is simply an antenna lead, and the output is a power audio signal
-available through a miniature phono plug.  Its RF frequencies of operation are
-more or less limited from 87.0 to 109.0 MHz (the commercial FM broadcast
-band).  Although the registers can be programmed to request frequencies beyond
-these limits, experiments did not give promising results.  The variable
-frequency oscillator (VFO) that demodulates the intermediate frequency (IF)
-signal probably has a small range of useful frequencies, and wraps around or
-gets clipped beyond the limits mentioned above.
-
-
-CONTROLLING THE CARD WITH IOPORT
---------------------------------
-The RadioTrack (base) ioport is configurable for 0x30c or 0x20c.  Only one
-ioport seems to be involved.  The ioport decoding circuitry must be pretty
-simple, as individual ioport bits are directly matched to specific functions
-(or blocks) of the radio card.  This way, many functions can be changed in
-parallel with one write to the ioport.  The only feedback available through
-the ioports appears to be the "Stereo Detect" bit.
-
-The bits of the ioport are arranged as follows:
-
-  MSb                                                         LSb
-+------+------+------+--------+--------+-------+---------+--------+
-| VolA | VolB | ???? | Stereo | Radio  | TuneA | TuneB   | Tune   |
-|  (+) |  (-) |      | Detect | Audio  | (bit) | (latch) | Update |
-|      |      |      | Enable | Enable |       |         | Enable |
-+------+------+------+--------+--------+-------+---------+--------+
-
-
-VolA . VolB  [AB......]
------------
-0 0 : audio mute
-0 1 : volume +    (some delay required)
-1 0 : volume -    (some delay required)
-1 1 : stay at present volume
-
-Stereo Detect Enable [...S....]
---------------------
-0 : No Detect
-1 : Detect
-
-  Results available by reading ioport >60 msec after last port write.
-  0xff ==> no stereo detected,  0xfd ==> stereo detected.
-
-Radio to Audio (path) Enable [....R...]
-----------------------------
-0 : Disable path (silence)
-1 : Enable path  (audio produced)
-
-TuneA . TuneB [.....AB.]
--------------
-0 0 : "zero" bit phase 1
-0 1 : "zero" bit phase 2
-
-1 0 : "one" bit phase 1
-1 1 : "one" bit phase 2
-
-  24-bit code, where bits = (freq*40) + 10486188.
-  The Most Significant 11 bits must be 1010 xxxx 0x0 to be valid.
-  The bits are shifted in LSb first.
-
-Tune Update Enable [.......T]
-------------------
-0 : Tuner held constant
-1 : Tuner updating in progress
-
-
-PROGRAMMING EXAMPLES
---------------------
-Default:        BASE <-- 0xc8  (current volume, no stereo detect,
-				radio enable, tuner adjust disable)
-
-Card Off:	BASE <-- 0x00  (audio mute, no stereo detect,
-				radio disable, tuner adjust disable)
-
-Card On:	BASE <-- 0x00  (see "Card Off", clears any unfinished business)
-		BASE <-- 0xc8  (see "Default")
-
-Volume Down:    BASE <-- 0x48  (volume down, no stereo detect,
-				radio enable, tuner adjust disable)
-		* wait 10 msec *
-		BASE <-- 0xc8  (see "Default")
-
-Volume Up:      BASE <-- 0x88  (volume up, no stereo detect,
-				radio enable, tuner adjust disable)
-		* wait 10 msec *
-		BASE <-- 0xc8  (see "Default")
-
-Check Stereo:   BASE <-- 0xd8  (current volume, stereo detect,
-				radio enable, tuner adjust disable)
-		* wait 100 msec *
-		x <-- BASE     (read ioport)
-		BASE <-- 0xc8  (see "Default")
-
-		x=0xff ==> "not stereo", x=0xfd ==> "stereo detected"
-
-Set Frequency:  code = (freq*40) + 10486188
-                foreach of the 24 bits in code,
-                (from Least to Most Significant):
-                  to write a "zero" bit,
-                    BASE <-- 0x01  (audio mute, no stereo detect, radio
-				    disable, "zero" bit phase 1, tuner adjust)
-                    BASE <-- 0x03  (audio mute, no stereo detect, radio
-				    disable, "zero" bit phase 2, tuner adjust)
-                  to write a "one" bit,
-                    BASE <-- 0x05  (audio mute, no stereo detect, radio
-				    disable, "one" bit phase 1, tuner adjust)
-                    BASE <-- 0x07  (audio mute, no stereo detect, radio
-				    disable, "one" bit phase 2, tuner adjust)
-
-----------------------------------------------------------------------------
diff -u --recursive --new-file v2.1.117/linux/Documentation/video4linux/API.html linux/Documentation/video4linux/API.html
--- v2.1.117/linux/Documentation/video4linux/API.html	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/video4linux/API.html	Sun Aug 23 13:32:25 1998
@@ -0,0 +1,354 @@
+<HTML><HEAD>
+<TITLE>Video4Linux Kernel API Reference v0.1:19980516</TITLE>
+</HEAD>
+<BODY bgcolor="#ffffff">
+<H3>Devices</H3>
+Video4Linux provides the following sets of device files. These live on the
+character device formerly known as "/dev/bttv". /dev/bttv should be a
+symlink to /dev/video0 for most people. 
+<P>
+<TABLE>
+<TR><TH>Device Name</TH><TH>Minor Range</TH><TH>Function</TH>
+<TR><TD>/dev/video</TD><TD>0-63</TD><TD>Video Capture Interface</TD>
+<TR><TD>/dev/radio</TD><TD>64-127</TD><TD>AM/FM Radio Devices</TD>
+<TR><TD>/dev/vtx</TD><TD>192-223</TD><TD>Teletext Interface Chips</TD>
+<TR><TD>/dev/vbi</TD><TD>224-239</TD><TD>Raw VBI Data (Intercast/teletext)</TD>
+</TABLE>
+<P>
+Video4Linux programs open and scan the devices to find what they are looking
+for. Capability queries define what each interface supports. The 
+described API is only defined for video capture cards. The relevant subset
+applies to radio cards. Teletext interfaces talk the existing VTX API.
+<P>
+<H3>Capability Query Ioctl</H3>
+The <B>VIDIOCGCAP</B> ioctl call is used to obtain the capability
+information for a video device. The <b>struct video_capability</b> object
+passed to the ioctl is completed and returned. It contains the following
+information
+<P>
+<TABLE>
+<TR><TD><b>name[32]</b><TD>Cannonical name for this interface</TD>
+<TR><TD><b>type</b><TD>Type of interface</TD>
+<TR><TD><b>channels</b><TD>Number of radio/tv channels if appropriate</TD>
+<TR><TD><b>audios</b><TD>Number of audio devices if appropriate</TD>
+<TR><TD><b>maxwidth</b><TD>Maximum capture width in pixels</TD>
+<TR><TD><b>maxheight</b><TD>Maximum capture height in pixels</TD>
+<TR><TD><b>minwidth</b><TD>Minimum capture width in pixels</TD>
+<TR><TD><b>minheight</b><TD>Minimum capture height in pixels</TD>
+</TABLE>
+<P>
+The type field lists the capability flags for the device. These are
+as follows
+<P>
+<TABLE>
+<TR><TH>Name</TH><TH>Description</TH>
+<TR><TD><b>VID_TYPE_CAPTURE</b><TD>Can capture to memory</TD>
+<TR><TD><b>VID_TYPE_TUNER</b><TD>Has a tuner of some form</TD>
+<TR><TD><b>VID_TYPE_TELETEXT</b><TD>Has teletext capability</TD>
+<TR><TD><b>VID_TYPE_OVERLAY</b><TD>Can overlay its image onto the frame buffer</TD>
+<TR><TD><b>VID_TYPE_CHROMAKEY</b><TD>Overlay is Chromakeyed</TD>
+<TR><TD><b>VID_TYPE_CLIPPING</b><TD>Overlay clipping is supported</TD>
+<TR><TD><b>VID_TYPE_FRAMERAM</b><TD>Overlay overwrites frame buffer memory</TD>
+<TR><TD><b>VID_TYPE_SCALES</b><TD>The hardware supports image scaling</TD>
+<TR><TD><b>VID_TYPE_MONOCHROME</b><TD>Image capture is grey scale only</TD>
+<TR><TD><b>VID_TYPE_SUBCAPTURE</b><TD>Capture can be of only part of the image</TD>
+</TABLE>
+<P>
+The minimum and maximum sizes listed for a capture device do not imply all
+that all height/width ratios or sizes within the range are possible. A
+request to set a size will be honoured by the largest available capture
+size whose capture is no large than the requested rectangle in either
+direction. For example the quickcam has 3 fixed settings. 
+<P>
+<H3>Frame Buffer</H3>
+Capture cards that drop data directly onto the frame buffer must be told the
+base address of the frame buffer, its size and organisation. This is a 
+privileged ioctl and one that eventually X itself should set.
+<P>
+The <b>VIDIOCSFBUF</b> ioctl sets the frame buffer parameters for a capture
+card. If the card does not do direct writes to the frame buffer then this
+ioctl will be unsupported. The <b>VIDIOCGFBUF</b> ioctl returns the
+currently used parameters. The structure used in both cases is a 
+<b>struct video_buffer</b>.
+<P>
+<TABLE>
+<TR><TD><b>void *base</b></TD><TD>Base physical address of the buffer</TD>
+<TR><TD><b>int height</b></TD><TD>Height of the frame buffer</TD>
+<TR><TD><b>int width</b></TD><TD>Width of the frame buffer</TD>
+<TR><TD><b>int depth</b></TD><TD>Depth of the frame buffer</TD>
+<TR><TD><b>int bytesperline</b></TD><TD>Number of bytes of memory between the start of two adjacent lines</TD>
+</TABLE>
+<P>
+Note that these values reflect the physical layout of the frame buffer. 
+The visible area may be smaller. In fact under XFree86 this is commonly the
+case. XFree86 DGA can provide the parameters required to set up this ioctl.
+Setting the base address to NULL indicates there is no physical frame buffer
+access.
+<P>
+<H3>Capture Windows</H3>
+The capture area is described by a <b>struct video_window</b>. This defines
+a capture area and the clipping information if relevant. The 
+<b>VIDIOCGWIN</b> ioctl recovers the current settings and the 
+<b>VIDIOCSWIN</b> sets new values. A successful call to <b>VIDIOCSWIN</b> 
+indicates that a suitable set of parameters have been chosen. They do not
+indicate that exactly what was requested was granted. The program should
+call <b>VIDIOCGWIN</b> to check if the nearest match was suitable. The
+<b>struct video_window</b> contains the following fields.
+<P>
+<TABLE>
+<TR><TD><b>x</b><TD>The X co-ordinate specified in X windows format.</TD>
+<TR><TD><b>y</b><TD>The Y co-ordinate specified in X windows format.</TD>
+<TR><TD><b>width</b><TD>The width of the image capture.</TD>
+<TR><TD><b>height</b><TD>The height of the image capture.</TD>
+<TR><TD><b>chromakey</b><TD>A host order RGB32 value for the chroma key.</TD>
+<TR><TD><b>flags</b><TD>Additional capture flags.</TD>
+<TR><TD><b>clips</b><TD>A list of clipping rectangles. <em>(Set only)</em)</TD>
+<TR><TD><b>clipcount</b><TD>The number of clipping rectangles. <em>(Set only)</em></TD>
+</TABLE>
+<P>
+Clipping rectangles are passed as an array. Each clip consists of the following
+fields available to the user.
+<P>
+<TABLE>
+<TR><TD><b>x</b></TD><TD>X co-ordinate of rectangle to skip</TD>
+<TR><TD><b>y</b></TD><TD>Y co-ordinate of rectangle to skip</TD>
+<TR><TD><b>width</b></TD><TD>Width of rectangle to skip</TD>
+<TR><TD><b>height</b></TD><TD>Height of rectangle to skip</TD>
+</TABLE>
+<P>
+Merely setting the window does not enable capturing. Overlay capturing
+is activatied by passing the <b>VIDIOCCAPTURE</b> ioctl a value of 1, and
+disabled by passing it a value of 0. 
+<P>
+Some capture devices can capture a subfield of the image they actually see.
+This is indicated when VIDEO_TYPE_SUBCAPTURE is defined.
+The video_capture describes the time and spacial subfields to capture.
+The video_capture structure contains the following fields.
+<P>
+<TABLE>
+<TR><TD><b>x</b></TD><TD>X co-ordinate of source rectangle to grab</TD>
+<TR><TD><b>y</b></TD><TD>Y co-ordinate of source rectangle to grab</TD>
+<TR><TD><b>width</b></TD><TD>Width of source rectangle to grab</TD>
+<TR><TD><b>height</b></TD><TD>Height of source rectangle to grab</TD>
+<TR><TD><b>decimation</b></TD><TD>Decimation to apply</TD>
+<TR><TD><b>flags</b></TD><TD>Flag settings for grabbing</TD>
+</TABLE>
+The available flags are
+<P>
+<TABLE>
+<TR><TH>Name</TH><TH>Description</TH>
+<TR><TD><b>VIDEO_CAPTURE_ODD</b><TD>Capture only odd frames</TD>
+<TR><TD><b>VIDEO_CAPTURE_EVEN</b><TD>Capture only even frames</TD>
+</TABLE>
+<P>
+<H3>Video Sources</H3>
+Each video4linux video or audio device captures from one or more 
+source <b>channels</b>. Each channel can be queries with the 
+<b>VDIOCGCHAN</b> ioctl call. Before invoking this function the caller
+must set the channel field to the channel that is being queried. On return
+the <b>struct video_channel</b> is filled in with information about the
+nature of the channel itself.
+<P>
+The <b>VIDIOCSCHAN</b> ioctl takes an integer argument and switches the
+capture to this input. It is not defined whether paramters such as colour
+settings or tuning are maintained across a channel switch. The caller should
+maintain settings as desired for each channel. (This is reasonable as 
+different video inputs may have different properties).
+<P>
+The <b>struct video_channel</b> consists of the following
+<P>
+<TABLE>
+<TR><TD><b>channel</b></TD><TD>The channel number</TD>
+<TR><TD><b>name</b></TD><TD>The input name - preferably reflecting the label
+on the card input itself</TD>
+<TR><TD><b>tuners</b></TD><TD>Number of tuners for this input</TD>
+<TR><TD><b>flags</b></TD><TD>Properties the tuner has</TD>
+<TR><TD><b>type</b></TD><TD>Input type (if known)</TD>
+<TR><TD><b>norm</b><TD>The norm for this channel</TD>
+</TABLE>
+<P>
+The flags defined are
+<P>
+<TABLE>
+<TR><TD><b>VIDEO_VC_TUNER</b><TD>Channel has tuners.</TD>
+<TR><TD><b>VIDEO_VC_AUDIO</b><TD>Channel has audio.</TD>
+<TR><TD><b>VIDEO_VC_NORM</b><TD>Channel has norm setting.</TD>
+</TABLE>
+<P>
+The types defined are
+<P>
+<TABLE>
+<TR><TD><b>VIDEO_TYPE_TV</b><TD>The input is a TV input.</TD>
+<TR><TD><b>VIDEO_TYPE_CAMERA</b><TD>The input is a camera.</TD>
+</TABLE>
+<P>
+<H3>Image Properties</H3>
+The image properties of the picture can be queried with the <b>VIDIOCGPICT</b>
+ioctl which fills in a <b>struct video_picture</b>. The <b>VIDIOCSPICT</b> 
+ioctl allows values to be changed. All values except for the palette type
+are scaled between 0-65535. 
+<P>
+The <b>struct video_picture</b> consists of the following fields
+<P>
+<TABLE>
+<TR><TD><b>brightness</b><TD>Picture brightness</TD>
+<TR><TD><b>hue</b><TD>Picture hue (colour only)</TD>
+<TR><TD><b>colour</b><TD>Picture colour (colour only)</TD>
+<TR><TD><b>contrast</b><TD>Picture contrast</TD>
+<TR><TD><b>whiteness</b><TD>The whiteness (greyscale only)</TD>
+<TR><TD><b>depth</b><TD>The capture depth (may need to match the frame buffer depth)</TD>
+<TR><TD><b>palette</b><TD>Reports the palette that should be used for this image</TD>
+</TABLE>
+<P>
+The following palettes are defined
+<P>
+<TABLE>
+<TR><TD><b>VIDEO_PALETTE_GREY</b><TD>Linear intensity grey scale (255 is brightest).</TD>
+<TR><TD><b>VIDEO_PALETTE_HI240</b><TD>The BT848 8bit colour cube.</TD>
+<TR><TD><b>VIDEO_PALETTE_RGB565</b><TD>RGB565 packed into 16 bit words.</TD>
+<TR><TD><b>VIDEO_PALETTE_RGB555</b><TD>RGV555 packed into 16 bit words, top bit undefined.</TD>
+<TR><TD><b>VIDEO_PALETTE_RGB24</b><TD>RGB888 packed into 24bit words.</TD>
+<TR><TD><b>VIDEO_PALETTE_RGB32</b><TD>RGB888 packed into the low 3 bytes of 32bit words. The top 8bits are undefined.</TD>
+<TR><TD><b>VIDEO_PALETTE_YUV422</b><TD>Video style YUV422 - 8bits packed 4bits Y 2bits U 2bits V</TD>
+<TR><TD><b>VIDEO_PALETTE_YUYV</b><TD>Describe me</TD>
+<TR><TD><b>VIDEO_PALETTE_UYVY</b><TD>Describe me</TD>
+<TR><TD><b>VIDEO_PALETTE_YUV420</b><TD>YUV420 capture</TD>
+<TR><TD><b>VIDEO_PALETTE_YUV411</b><TD>YUV411 capture</TD>
+<TR><TD><b>VIDEO_PALETTE_RAW</b><TD>RAW capture (BT848)</TD>
+<TR><TD><b>VIDEO_PALETTE_YUV422P</b><TD>YUV 4:2:2 Planar</TD>
+<TR><TD><b>VIDEO_PALETTE_YUV411P</b><TD>YUV 4:1:1 Planar</TD>
+</TABLE>
+<P>
+<H3>Tuning</H3>
+Each video input channel can have one or more tuners associated with it. Many
+devices will not have tuners. TV cards and radio cards will have one or more
+tuners attached.
+<P>
+Tuners are described by a <b>struct video_tuner</b> which can be obtained by
+the <b>VIDIOCGTUNER</b> ioctl. Fill in the tuner number in the structure
+then pass the structure to the ioctl to have the data filled in. The 
+tuner can be switched using <b>VIDIOCSTUNER</b> which takes an integer argument
+giving the tuner to use. A struct tuner has the following fields
+<P>
+<TABLE>
+<TR><TD><b>tuner</b><TD>Number of the tuner</TD>
+<TR><TD><b>name</b><TD>Cannonical name for this tuner (eg FM/AM/TV)</TD>
+<TR><TD><b>rangelow</b><TD>Lowest tunable frequency</TD>
+<TR><TD><b>rangehigh</b><TD>Highest tunable frequency</TD>
+<TR><TD><b>flags</b><TD>Flags describing the tuner</TD>
+<TR><TD><b>mode</b><TD>The video signal mode if relevant</TD>
+<TR><TD><b>signal</b><TD>Signal strength if known - between 0-65535</TD>
+</TABLE>
+<P>
+The following flags exist
+<P>
+<TABLE>
+<TR><TD><b>VIDEO_TUNER_PAL</b><TD>PAL tuning is supported</TD>
+<TR><TD><b>VIDEO_TUNER_NTSC</b><TD>NTSC tuning is supported</TD>
+<TR><TD><b>VIDEO_TUNER_SECAM</b><TD>SECAM tuning is supported</TD>
+<TR><TD><b>VIDEO_TUNER_LOW</b><TD>Frequency is in a lower range</TD>
+<TR><TD><b>VIDEO_TUNER_NORM</b><TD>The norm for this tuner is settable</TD>
+<TR><TD><b>VIDEO_TUNER_STEREO_ON</b><TD>The tuner is seeing stereo audio</TD>
+</TABLE>
+<P>
+The following modes are defined
+<P>
+<TABLE>
+<TR><TD><b>VIDEO_MODE_PAL</b><TD>The tuner is in PAL mode</TD>
+<TR><TD><b>VIDEO_MODE_NTSC</b><TD>The tuner is in NTSC mode</TD>
+<TR><TD><b>VIDEO_MODE_SECAM</b><TD>The tuner is in SECAM mode</TD>
+<TR><TD><b>VIDEO_MODE_AUTO</b><TD>The tuner auto switches, or mode does not apply</TD>
+</TABLE>
+<P>
+Tuning frequencies are an unsigned 32bit value in 1/16th MHz or if the
+<b>VIDEO_TUNER_LOW</b> flag is set they are in 1/16th KHz. The current
+frequency is obtained as an unsigned long via the <b>VIDIOCGFREQ</b> ioctl and
+set by the <b>VIDIOCSFREQ</b> ioctl.
+<P>
+<H3>Audio</H3>
+TV and Radio devices have one or more audio inputs that may be selected. 
+The audio properties are queried by passing a <b>struct video_audio</b> to <b>VIDIOCGAUDIO</b> ioctl. The
+<b>VIDIOCSAUDIO</b> ioctl sets audio properties.
+<P>
+The structure contains the following fields
+<P>
+<TABLE>
+<TR><TD><b>audio</b><TD>The channel number</TD>
+<TR><TD><b>volume</b><TD>The voume level</TD>
+<TR><TD><b>bass</b><TD>The bass level</TD>
+<TR><TD><b>treble</b><TD>The treble level</TD>
+<TR><TD><b>flags</b><TD>Flags describing the audio channel</TD>
+<TR><TD><b>name</b><TD>Canonical name for the audio input</TD>
+<TR><TD><b>mode</b><TD>The mode the audio input is in</TD>
+<TR><TD><b>balance</b><TD>The left/right balance</TD>
+<TR><TD><b>step</b><TD>Actual step used by the hardware</TD>
+</TABLE>
+<P>
+The following flags are defined
+<P>
+<TABLE>
+<TR><TD><b>VIDEO_AUDIO_MUTE</b><TD>The audio is muted</TD>
+<TR><TD><b>VIDEO_AUDIO_MUTABLE</b><TD>Audio muting is supported</TD>
+<TR><TD><b>VIDEO_AUDIO_VOLUME</b><TD>The volume is controllable</TD>
+<TR><TD><b>VIDEO_AUDIO_BASS</b><TD>The bass is controllable</TD>
+<TR><TD><b>VIDEO_AUDIO_TREBLE</b><TD>The treble is controllable</TD>
+<TR><TD><b>VIDEO_AUDIO_BALANCE</b><TD>The balance is controllable</TD>
+</TABLE>
+<P>
+The following decoding modes are defined
+<P>
+<TABLE>
+<TR><TD><b>VIDEO_SOUND_MONO</b><TD>Mono signal</TD>
+<TR><TD><b>VIDEO_SOUND_STEREO</b><TD>Stereo signal (NICAM for TV)</TD>
+<TR><TD><b>VIDEO_SOUND_LANG1</b><TD>European TV alternate language 1</TD>
+<TR><TD><b>VIDEO_SOUND_LANG2</b><TD>European TV alternate language 2</TD>
+</TABLE>
+<P>
+<H3>Reading Images</H3>
+Each call to the <b>read</b> syscall returns the next available image from
+the device. It is up to the caller to set the format and then to pass a 
+suitable size buffer and length to the function. Not all devices will support
+read operations.
+<P>
+A second way to handle image capture is via the mmap interface if supported.
+To use the mmap interface a user first sets the desired image size and depth
+properties. Next the VIDIOCGMBUF ioctl is issued. This reports the size
+of buffer to mmap and the offset within the buffer for each frame. The
+number of frames supported is device dependant and may only be one. 
+<P>
+The video_mbuf structure contains the following fields
+<P>
+<TABLE>
+<TR><TD><b>size</b><TD>The number of bytes to map</TD>
+<TR><TD><b>frames</b><TD>The number of frames</TD>
+<TR><TD><b>offsets</b><TD>The offset of each frame</TD>
+</TABLE>
+<P>
+Once the mmap has been made the VIDIOCMCAPTURE ioctl sets the image size
+you wish to use (which should match or be below the initial query size).
+Having done so it will begin capturing to the memory mapped buffer. Whenever
+a buffer is "used" by the program it should called VIDIOCSYNC to free this
+frame up and continue. <em>to add:</em>VIDIOCSYNC takes the frame number
+you are freeing as its argument. When the buffer is unmapped or all the
+buffers are full capture ceases. While capturing to memory the driver will
+make a "best effort" attempt to capture to screen as well if requested. This
+normally means all frames that "miss" memory mapped capture will go to the
+display.
+<P>
+A final ioctl exists to allow a device to obtain related devices if a
+driver has multiple components (for example video0 may not be associated
+with vbi0 which would cause an intercast display program to make a bad
+mistake). The VIDIOCGUNIT ioctl reports the unit numbers of the associated
+devices if any exist. The video_unit structure has the following fields.
+<P>
+<TABLE>
+<TR><TD><b>video</b><TD>Video capture device</TD>
+<TR><TD><b>vbi</b><TD>VBI capture device</TD>
+<TR><TD><b>radio</b><TD>Radio device</TD>
+<TR><TD><b>audio</b><TD>Audio mixer</TD>
+<TR><TD><b>teletext</b><TD>Teletext device</TD>
+</TABLE>
+<P>
+
+</BODY>
+</HTML>
diff -u --recursive --new-file v2.1.117/linux/Documentation/video4linux/bttv/CARDS linux/Documentation/video4linux/bttv/CARDS
--- v2.1.117/linux/Documentation/video4linux/bttv/CARDS	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/video4linux/bttv/CARDS	Sun Aug 23 13:32:25 1998
@@ -0,0 +1,104 @@
+Suppported cards:
+
+
+Bt848/Bt848a/Bt849/Bt878/Bt879 cards
+------------------------------------
+
+All cards with Bt848/Bt848a/Bt849/Bt878/Bt879 and normal Composite/S-VHS inputs
+are supported.
+Teletext and Intercast support (PAL only) via VBI samples decoding in software.
+
+Some cards with additional multiplexing of inputs are only partially 
+supported (unless specifications by the card manufacturer are given).
+
+All other cards only differ by additional components as tuners, sound decoders,
+EEPROMs, teletext decoders ...
+
+Tuner and sound decoder support for Bt878/879 is not fully working yet.
+
+
+MATRIX Vision
+-------------
+
+MV-Delta
+- Bt848A
+- 4 Composite inputs, 1 S-VHS input (shared with 4th composite)
+- EEPROM
+
+http://www.matrix-vision.de/
+
+This card has no tuner but supports all 4 composite (1 shared with an
+S-VHS input) of the Bt848A.
+Very nice card if you only have satellite TV but several tuners connected
+to the card via composite.
+
+Many thanks to Matrix-Vision for giving us 2 cards for free which made
+Bt848a/Bt849 single crytal operation support possible!!!
+
+
+
+Miro/Pinnacle PCTV
+------------------
+
+- Bt848 
+  some (all??) come with 2 crystals for PAL/SECAM and NTSC 
+- PAL, SECAM or NTSC TV tuner (Philips or TEMIC)
+- MSP34xx sound decoder on add on board
+  decoder is supported but AFAIK does not yet work 
+  (other sound MUX setting in GPIO port needed??? somebody who fixed this???)
+- 1 tuner, 1 composite and 1 S-VHS input
+- tuner type is autodetected
+
+http://www.miro.de/
+http://www.miro.com/
+
+
+Many thanks for the free card which made first NTSC support possible back
+in 1997!
+
+
+Hauppauge Win/TV pci
+--------------------
+
+There are many different versions of the Hauppauge cards with different 
+tuners (TV+Radio ...), teletext decoders.
+Note that even cards with same model numbers have (depending on the revision)
+different chips on it.
+
+- Bt848 (and others but always in 2 crystal operation???)
+  newer cards have a Bt878, I2C support for it is still experimental 
+- PAL, SECAM, NTSC or tuner with or without Radio support
+
+e.g.:
+  PAL: 
+  TDA5737: VHF, hyperband and UHF mixer/oscillator for TV and VCR 3-band tuners
+  TSA5522: 1.4 GHz I2C-bus controlled synthesizer, I2C 0xc2-0xc3
+  
+  NTSC:
+  TDA5731: VHF, hyperband and UHF mixer/oscillator for TV and VCR 3-band tuners
+  TSA5518: no datasheet available on Philips site
+- Philips SAA5246 or SAA5284 ( or no) Teletext decoder chip	
+  with buffer RAM (e.g. Winbond W24257AS-35: 32Kx8 CMOS static RAM)
+  SAA5246 (I2C 0x22) is supported
+- 256 bytes EEPROM: Microchip 24LC02B or Philips 8582E2Y 
+  with configuration information
+  I2C address 0xa0 (24LC02B also responds to 0xa2-0xaf)
+- 1 tuner, 1 composite and (depending on model) 1 S-VHS input
+- 14052B: mux for selection of sound source
+- sound decoder: TDA9800, MSP34xx (stereo cards) 
+
+
+AverMedia
+---------
+
+...
+
+
+
+
+
+ 
+
+
+
+
diff -u --recursive --new-file v2.1.117/linux/Documentation/video4linux/bttv/CONTRIBUTORS linux/Documentation/video4linux/bttv/CONTRIBUTORS
--- v2.1.117/linux/Documentation/video4linux/bttv/CONTRIBUTORS	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/video4linux/bttv/CONTRIBUTORS	Sun Aug 23 13:32:25 1998
@@ -0,0 +1,20 @@
+Contributors to bttv: 
+
+Michael Chu <mmchu@pobox.com>
+  AverMedia fix and more flexible card recognition
+
+Alan Cox <alan@cymru.net>
+  Video4Linux interface and 2.1.x kernel adaptation
+
+Chris Kleitsch
+  Hardware I2C
+  
+Gerd Knorr <kraxel@cs.tu-berlin.de> 
+  Radio card (ITT sound processor)
+
++ many more (please mail me if you are missing in this list and would
+             like to be mentioned)
+
+
+
+
diff -u --recursive --new-file v2.1.117/linux/Documentation/video4linux/bttv/ICs linux/Documentation/video4linux/bttv/ICs
--- v2.1.117/linux/Documentation/video4linux/bttv/ICs	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/video4linux/bttv/ICs	Sun Aug 23 13:32:25 1998
@@ -0,0 +1,37 @@
+all boards:
+
+Brooktree Bt848/848A/849/878/879: video capture chip
+
+
+
+Miro PCTV:
+
+Philips or Temic Tuner
+
+
+
+Hauppauge Win/TV pci (version 405):
+
+Microchip 24LC02B or
+Philips 8582E2Y: 256 Byte EEPROM with configuration information
+                 I2C 0xa0-0xa1, (24LC02B also responds to 0xa2-0xaf)
+Philips SAA5246AGP/E: Videotext decoder chip, I2C 0x22-0x23
+TDA9800: sound decoder
+Winbond W24257AS-35: 32Kx8 CMOS static RAM (Videotext buffer mem)
+14052B: analog switch for selection of sound source
+
+PAL: 
+TDA5737: VHF, hyperband and UHF mixer/oscillator for TV and VCR 3-band tuners
+TSA5522: 1.4 GHz I2C-bus controlled synthesizer, I2C 0xc2-0xc3
+
+NTSC:
+TDA5731: VHF, hyperband and UHF mixer/oscillator for TV and VCR 3-band tuners
+TSA5518: no datasheet available on Philips site
+
+
+
+STB TV pci:
+
+???
+if you want better support for STB cards send me info!
+Look at the board! What chips are on it?
diff -u --recursive --new-file v2.1.117/linux/Documentation/video4linux/bttv/INSTALL linux/Documentation/video4linux/bttv/INSTALL
--- v2.1.117/linux/Documentation/video4linux/bttv/INSTALL	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/video4linux/bttv/INSTALL	Sun Aug 23 13:32:25 1998
@@ -0,0 +1,73 @@
+- Make sure you have a recent 2.0.x kernel (I recommend AT LEAST 2.0.33!)
+  or a recent 2.1.x kernel.
+  Older kernels might lead to problems. 
+
+- Do NOT compile videodev into your kernel!
+  Use the module supplied with bttv.
+
+- Edit "driver/Makefile":
+
+  - If you do NOT have a Miro card:
+    Adjust TUNER to a number between 0 and 7. 
+
+    This number has the following meaning:
+
+    0: Temic PAL tuner
+    1: Philips PAL_I tuner
+    2: Philips NTSC tuner
+    3: Philips SECAM tuner
+    4: no tuner
+    5: Philips PAL tuner
+    6: Temic NTSC tuner
+    7: Temic PAL tuner
+
+    The number corresponds to the number (-1) given at the GPIO port of the
+    Bt848 on Miro cards.
+
+
+  - Adjust CARD to one of the numbers below:
+
+    0: Auto-Detect
+    1: Miro
+    2: Hauppauge
+    3: STB
+    4: Intel
+    5: Diamond
+    6: AVerMedia
+
+
+  - You may have to adjust BTTV_MAJOR to a different number depending on your
+    kernel version. The official number 81 does not work on some setups.
+    But instead of changing it, better update to a newer kernel.
+
+  - If you have a Bt848a or Bt849 on your board you might have to
+    uncomment: -DUSE_PLL 
+
+- do a "make" in the main directory.
+
+If you have Hauppauge card read "README.HAUPPAUGE" before proceeding.
+
+- type "make ins"
+
+  This creates the bttv devices in /dev and installs the bttv module
+
+  Look in the kernel log file (/var/adm/syslog or /var/log/kernel or something
+  else depending on your /etc/syslogd.conf or just call "dmesg")
+  and see what bttv reported (lines starting with "bttv:")
+  If the installation failed and you send e-mail to me always include those
+  lines! Dumps of the insmod output alone do not help at all.
+
+- Start X11 in hi or true color mode 
+  8 bit color is also supported but really ugly!
+  (If you have an S3 card you might have to start X11 before installing
+   the module!)
+
+  If you have Motif or LessTif, "xtvscreen" in the "XTV" directory should
+  have been compiled with the "make" above.
+  Otherwise use the statically linked version which should be available 
+  on the web site you got bttv from.
+  Read the documentation in "XTV" and start xtvscreen.
+
+- make applications by typing "make" in "apps"
+   
+
diff -u --recursive --new-file v2.1.117/linux/Documentation/video4linux/bttv/PROBLEMS linux/Documentation/video4linux/bttv/PROBLEMS
--- v2.1.117/linux/Documentation/video4linux/bttv/PROBLEMS	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/video4linux/bttv/PROBLEMS	Sun Aug 23 13:32:25 1998
@@ -0,0 +1,62 @@
+- Start capturing by pressing "c" or by selecting it via a menu!
+
+- Start capturing by pressing "c" or by selecting it via a menu!!!
+
+- The memory of some S3 cards is not recognized right:
+  
+  First of all, if you are not using Xfree-3.2 or newer, upgrade AT LEAST to
+  XFree-3.2A! This solved the problem for most people.
+
+  Start up X11 like this: "XF86_S3 -probeonly" and write down where the
+  linear frame buffer is.
+  If it is different to the address found by bttv install bttv like this:
+  "insmod bttv vidmem=0xfb0"
+  if the linear frame buffer is at 0xfb000000 (i.e. omit the last 5 zeros!)
+
+  Some S3 cards even take up 64MB of memory but only report 32MB to the BIOS.
+  If this 64MB area overlaps the IO memory of the Bt848 you also have to
+  remap this. E.g.: insmod bttv vidmem=0xfb0 remap=0xfa0
+
+  If the videomemory is found at the right place and there are no address
+  conflicts but still no picture (or the computer even crashes.),
+  try disabling features of your PCI chipset in the BIOS Setup.
+
+  Frank Kapahnke <frank@kapahnke.prima.ruhr.de> also reported that problems
+  with his S3 868 went away when he upgraded to XFree 3.2.
+
+
+- I still only get a black picture with my S3 card!
+
+  Even with XFree-3.2A some people have problems with their S3 cards
+  (mostly with Trio 64 but also with some others)
+  Get the free demo version of Accelerated X from www.xinside.com and try
+  bttv with it. bttv seems to work with most S3 cards with Accelerated X.
+  
+  Since I do not know much (better make that almost nothing) about VGA card
+  programming I do not know the reason for this.
+  Looks like XFree does something different when setting up the video memory?
+  Maybe somebody can enlighten me?  
+  Would be nice if somebody could get this to work with XFree since 
+  Accelerated X costs more than some of the grabber cards ... 
+ 
+  Better linear frame buffer support for S3 cards will probably be in
+  XFree 4.0.
+  
+- Grabbing is not switched off when changing consoles with XFree.
+  That's because XFree and some AcceleratedX versions do not send unmap
+  events.
+
+- Some popup windows (e.g. of the window manager) are not refreshed.
+  
+  Disable backing store by starting X with the option "-bs"
+
+- When using 32bpp in XFree or 24+8bpp mode in AccelX 3.1 the system
+  can sometimes lock up if you use more than 1 bt848 card at the same time.
+  You will always get pixel errors when e.g. using more than 1 card in full
+  screen mode. Maybe we need something faster than the PCI bus ...
+
+
+- Some S3 cards and the Matrox Mystique will produce pixel erros with
+  full resolution in 32bit mode.
+
+- Some video cards have problems with Accelerated X 4.1
\ No newline at end of file
diff -u --recursive --new-file v2.1.117/linux/Documentation/video4linux/bttv/README linux/Documentation/video4linux/bttv/README
--- v2.1.117/linux/Documentation/video4linux/bttv/README	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/video4linux/bttv/README	Sun Aug 23 13:32:25 1998
@@ -0,0 +1,41 @@
+bttv - BT848 frame grabber driver
+
+Copyright (C) 1996,97 Ralph Metzler  (rjkm@thp.uni-koeln.de)
+                    & Marcus Metzler (mocm@thp.uni-koeln.de)
+                    according to GNU GPL in file COPYING.
+
+
+Bttv is a device driver for frame grabber cards using the Bt848 family
+of video decoder chips.
+Among those are the Bt848, Bt848A, Bt849, Bt878 and Bt879.
+The only major differences between the cards by different manufacturers 
+are the types of tuners and extra components on the boards.
+E.g., some cards by Hauppauge have an additional Videotext decoder 
+and/or sound decoder chip.
+Also type (Composite or S-VHS) and number of inputs differ.
+Other Brooktree chips (e.g. the Bt829) or chips by other manufacturers 
+(Philips, Zoran, ...) are NOT supported by bttv.
+
+You can use several cards at the same time.
+Interrupts can be shared with other Bt848 cards or any other drivers
+which allow it.
+The (arbitrary) maximum number of cards is 4 but can be adjusted by
+changing BTTV_MAX at the beginning of bttv.c if you need more.
+(But which board has more than 4 PCI slots plus 1 for the VGA card?)
+
+Bttv is a standard component of all newer 2.1.x kernels.
+This distribution additionally supports 2.0.x kernels and all other
+changes and improvements which did not make it into the kernel version
+yet. 
+It also includes versions of videodev.c, i2.c, tuner.c and others
+which are the same as in the latest 2.1.x kernel but with 2.0.x support.
+A kernel version >2.0.30 is recommended.
+
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+Although bttv is now used and tested by many people it still might crash your
+computer! Take all precautions to avoid data loss until you are certain
+bttv runs on your setup without problems.
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+The latest version of bttv can be found at:
+http://www.thp.uni-koeln.de/~rjkm/linux/bttv.html
diff -u --recursive --new-file v2.1.117/linux/Documentation/video4linux/bttv/README.FIRST linux/Documentation/video4linux/bttv/README.FIRST
--- v2.1.117/linux/Documentation/video4linux/bttv/README.FIRST	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/video4linux/bttv/README.FIRST	Sun Aug 23 13:32:25 1998
@@ -0,0 +1,4 @@
+o Please direct queries about the in kernel version of this driver to
+  Alan Cox first not to Ralph, or better yet join the video4linux mailing
+  list (mail majordomo@phunk.org with "subscribe video4linux")
+
diff -u --recursive --new-file v2.1.117/linux/Documentation/video4linux/bttv/README.Hauppauge linux/Documentation/video4linux/bttv/README.Hauppauge
--- v2.1.117/linux/Documentation/video4linux/bttv/README.Hauppauge	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/video4linux/bttv/README.Hauppauge	Sun Aug 23 13:32:25 1998
@@ -0,0 +1,29 @@
+The current I2C-Code could by accident overwrite the configuration EEPROM on 
+Hauppauge boards!!! 
+(E.g. the videotext driver and the bt848 driver do not know about each other.
+This might cause unwanted states on the I2C bus which overwrite the EEPROM)
+
+Back up this EEPROM before doing anything else by typing:
+(do this AFTER installing bttv.o with "make ins" but BEFORE starting the
+X application)
+
+make readee
+readee > tvee.h
+
+If you encounter any problems in Windows95 (like "PNP component not found" ...)
+go back into linux, load bttv and type:
+
+make writeee
+writeee
+
+to write the backed up contents.
+If you backed up your EEPROM as described above, this will restore it to its
+original state.
+A detailed description of the meaning of the EEPROM bytes by
+Hauppauge would of course be even more helpful! 
+
+If you have board type 405 and you did not make a backup, my tvee.h file in 
+mytvee.h might be of help.
+
+Forget about all of the above if you do not have a Hauppauge board.
+
diff -u --recursive --new-file v2.1.117/linux/Documentation/video4linux/bttv/README.MIRO linux/Documentation/video4linux/bttv/README.MIRO
--- v2.1.117/linux/Documentation/video4linux/bttv/README.MIRO	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/video4linux/bttv/README.MIRO	Sun Aug 23 13:32:25 1998
@@ -0,0 +1,3 @@
+The right tuner type should automatically be detected.
+Look in your kernel log files to see which one bttv thinks it is.
+
diff -u --recursive --new-file v2.1.117/linux/Documentation/video4linux/bttv/README.PCI linux/Documentation/video4linux/bttv/README.PCI
--- v2.1.117/linux/Documentation/video4linux/bttv/README.PCI	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/video4linux/bttv/README.PCI	Sun Aug 23 13:32:25 1998
@@ -0,0 +1,36 @@
+Because some people were asking about the bandwidth the Bt848 might use up
+on the PCI bus I did a little benchmark.
+
+"bonnie -s 200" with a Fireball TM 3.8 Gb using Busmaster DMA on an ASUS P6NP5
+
+without capturing:
+
+              -------Sequential Output-------- ---Sequential Input-- --Random--
+              -Per Char- --Block--- -Rewrite-- -Per Char- --Block--- --Seeks---
+Machine    MB K/sec %CPU K/sec %CPU K/sec %CPU K/sec %CPU K/sec %CPU  /sec %CPU
+          200  5353 76.6  5898 16.9  2363 12.1  5889 51.3  6416 10.2  37.8  0.9
+
+
+while capturing full screen PAL (786x576) with 24bpp:
+
+              -------Sequential Output-------- ---Sequential Input-- --Random--
+              -Per Char- --Block--- -Rewrite-- -Per Char- --Block--- --Seeks---
+Machine    MB K/sec %CPU K/sec %CPU K/sec %CPU K/sec %CPU K/sec %CPU  /sec %CPU
+          200  5619 69.3  5939 16.9  2334 12.0  5859 50.9  6441 10.5  37.9  0.9
+
+The differences are small and probably within the normal error margin of
+bonnie.
+So, one bt848 card does not have much(any?) impact on the normal operation 
+of a Linux system.
+If you have several cards running this will look very differently!
+The same is probably true if your Linux box is used as a file server 
+with 15 (or 30) SCSI drives.
+ 
+I tested having 2 Bt848 cards grabbing in 32 bit mode (That's almost 100MB/s!)
+while running bonnie.
+The xtvscreen windows showed severe pixel errors.
+After a while the ide driver failed to use DMA and switched DMA off.
+It continued running but the results where bad.
+
+
+
diff -u --recursive --new-file v2.1.117/linux/Documentation/video4linux/bttv/README.RADIO linux/Documentation/video4linux/bttv/README.RADIO
--- v2.1.117/linux/Documentation/video4linux/bttv/README.RADIO	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/video4linux/bttv/README.RADIO	Sun Aug 23 13:32:25 1998
@@ -0,0 +1,15 @@
+Support is in now:
+  - Turn on the "big red switch" of the sound processor.
+  - two ioctls to access (some) registers of the sound processor.
+  - a function in the TV-Widget which monitors the signal quality
+    and does the mono/stereo switching.
+
+So you should have TV with (stereo) sound now.  Radio does _not_ work.
+It probably does not work with sat receivers. I can't test this and
+therefore hav'nt added support for it yet. If someone needs this and
+can help testing the sat stuff, drop me a note.
+
+  Gerd
+
+--
+Gerd Knorr <kraxel@cs.tu-berlin.de>
diff -u --recursive --new-file v2.1.117/linux/Documentation/video4linux/bttv/THANKS linux/Documentation/video4linux/bttv/THANKS
--- v2.1.117/linux/Documentation/video4linux/bttv/THANKS	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/video4linux/bttv/THANKS	Sun Aug 23 13:32:25 1998
@@ -0,0 +1,24 @@
+Many thanks to:
+
+- Markus Schroeder <schroedm@uni-duesseldorf.de> for information on the Bt848 
+  and tuner programming and his control program xtvc.
+
+- Martin Buck <martin-2.buck@student.uni-ulm.de> for his great Videotext
+  package.
+
+- Gerd Knorr <kraxel@cs.tu-berlin.de> for the MSP3400 support and the modular
+  I2C, tuner, ... support.
+
+
+- MATRIX Vision for giving us 2 cards for free, which made support of
+  single crystal operation possible.
+
+- MIRO for providing a free PCTV card and detailed information about the
+  components on their cards. (E.g. how the tuner type is detected)
+  Without their card I could not have debugged the NTSC mode.
+	
+- Hauppauge for telling how the sound input is selected and what compenents
+  they do and will use on their radio cards.
+  Also many thanks for faxing me the FM1216 data sheet.
+
+
diff -u --recursive --new-file v2.1.117/linux/Documentation/video4linux/radiotrack.txt linux/Documentation/video4linux/radiotrack.txt
--- v2.1.117/linux/Documentation/video4linux/radiotrack.txt	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/video4linux/radiotrack.txt	Sun Aug 23 13:32:25 1998
@@ -0,0 +1,147 @@
+NOTES ON RADIOTRACK CARD CONTROL
+by Stephen M. Benoit (benoits@servicepro.com)  Dec 14, 1996
+----------------------------------------------------------------------------
+
+Document version 1.0
+
+ACKNOWLEDGMENTS
+----------------
+This document was made based on 'C' code for Linux from Gideon le Grange
+(legrang@active.co.za or legrang@cs.sun.ac.za) in 1994, and elaborations from
+Frans Brinkman (brinkman@esd.nl) in 1996.  The results reported here are from
+experiments that the author performed on his own setup, so your mileage may
+vary... I make no guarantees, claims or warrantees to the suitability or
+validity of this information.  No other documentation on the AIMS
+Lab (http://www.aimslab.com/) RadioTrack card was made available to the
+author.  This document is offered in the hopes that it might help users who
+want to use the RadioTrack card in an environment other than MS Windows.
+
+WHY THIS DOCUMENT?
+------------------
+I have a RadioTrack card from back when I ran an MS-Windows platform.  After
+converting to Linux, I found Gideon le Grange's command-line software for
+running the card, and found that it was good!  Frans Brinkman made a
+comfortable X-windows interface, and added a scanning feature.  For hack
+value, I wanted to see if the tuner could be tuned beyond the usual FM radio
+broadcast band, so I could pick up the audio carriers from North American
+broadcast TV channels, situated just below and above the 87.0-109.0 MHz range.
+I did not get much success, but I learned about programming ioports under
+Linux and gained some insights about the hardware design used for the card.
+
+So, without further delay, here are the details.
+
+
+PHYSICAL DESCRIPTION
+--------------------
+The RadioTrack card is an ISA 8-bit FM radio card.  The radio frequency (RF)
+input is simply an antenna lead, and the output is a power audio signal
+available through a miniature phono plug.  Its RF frequencies of operation are
+more or less limited from 87.0 to 109.0 MHz (the commercial FM broadcast
+band).  Although the registers can be programmed to request frequencies beyond
+these limits, experiments did not give promising results.  The variable
+frequency oscillator (VFO) that demodulates the intermediate frequency (IF)
+signal probably has a small range of useful frequencies, and wraps around or
+gets clipped beyond the limits mentioned above.
+
+
+CONTROLLING THE CARD WITH IOPORT
+--------------------------------
+The RadioTrack (base) ioport is configurable for 0x30c or 0x20c.  Only one
+ioport seems to be involved.  The ioport decoding circuitry must be pretty
+simple, as individual ioport bits are directly matched to specific functions
+(or blocks) of the radio card.  This way, many functions can be changed in
+parallel with one write to the ioport.  The only feedback available through
+the ioports appears to be the "Stereo Detect" bit.
+
+The bits of the ioport are arranged as follows:
+
+  MSb                                                         LSb
++------+------+------+--------+--------+-------+---------+--------+
+| VolA | VolB | ???? | Stereo | Radio  | TuneA | TuneB   | Tune   |
+|  (+) |  (-) |      | Detect | Audio  | (bit) | (latch) | Update |
+|      |      |      | Enable | Enable |       |         | Enable |
++------+------+------+--------+--------+-------+---------+--------+
+
+
+VolA . VolB  [AB......]
+-----------
+0 0 : audio mute
+0 1 : volume +    (some delay required)
+1 0 : volume -    (some delay required)
+1 1 : stay at present volume
+
+Stereo Detect Enable [...S....]
+--------------------
+0 : No Detect
+1 : Detect
+
+  Results available by reading ioport >60 msec after last port write.
+  0xff ==> no stereo detected,  0xfd ==> stereo detected.
+
+Radio to Audio (path) Enable [....R...]
+----------------------------
+0 : Disable path (silence)
+1 : Enable path  (audio produced)
+
+TuneA . TuneB [.....AB.]
+-------------
+0 0 : "zero" bit phase 1
+0 1 : "zero" bit phase 2
+
+1 0 : "one" bit phase 1
+1 1 : "one" bit phase 2
+
+  24-bit code, where bits = (freq*40) + 10486188.
+  The Most Significant 11 bits must be 1010 xxxx 0x0 to be valid.
+  The bits are shifted in LSb first.
+
+Tune Update Enable [.......T]
+------------------
+0 : Tuner held constant
+1 : Tuner updating in progress
+
+
+PROGRAMMING EXAMPLES
+--------------------
+Default:        BASE <-- 0xc8  (current volume, no stereo detect,
+				radio enable, tuner adjust disable)
+
+Card Off:	BASE <-- 0x00  (audio mute, no stereo detect,
+				radio disable, tuner adjust disable)
+
+Card On:	BASE <-- 0x00  (see "Card Off", clears any unfinished business)
+		BASE <-- 0xc8  (see "Default")
+
+Volume Down:    BASE <-- 0x48  (volume down, no stereo detect,
+				radio enable, tuner adjust disable)
+		* wait 10 msec *
+		BASE <-- 0xc8  (see "Default")
+
+Volume Up:      BASE <-- 0x88  (volume up, no stereo detect,
+				radio enable, tuner adjust disable)
+		* wait 10 msec *
+		BASE <-- 0xc8  (see "Default")
+
+Check Stereo:   BASE <-- 0xd8  (current volume, stereo detect,
+				radio enable, tuner adjust disable)
+		* wait 100 msec *
+		x <-- BASE     (read ioport)
+		BASE <-- 0xc8  (see "Default")
+
+		x=0xff ==> "not stereo", x=0xfd ==> "stereo detected"
+
+Set Frequency:  code = (freq*40) + 10486188
+                foreach of the 24 bits in code,
+                (from Least to Most Significant):
+                  to write a "zero" bit,
+                    BASE <-- 0x01  (audio mute, no stereo detect, radio
+				    disable, "zero" bit phase 1, tuner adjust)
+                    BASE <-- 0x03  (audio mute, no stereo detect, radio
+				    disable, "zero" bit phase 2, tuner adjust)
+                  to write a "one" bit,
+                    BASE <-- 0x05  (audio mute, no stereo detect, radio
+				    disable, "one" bit phase 1, tuner adjust)
+                    BASE <-- 0x07  (audio mute, no stereo detect, radio
+				    disable, "one" bit phase 2, tuner adjust)
+
+----------------------------------------------------------------------------
diff -u --recursive --new-file v2.1.117/linux/MAINTAINERS linux/MAINTAINERS
--- v2.1.117/linux/MAINTAINERS	Tue Aug 18 22:02:01 1998
+++ linux/MAINTAINERS	Tue Aug 25 13:49:08 1998
@@ -47,6 +47,10 @@
 
 Maintainers List (try to look for most precise areas first)
 
+Note: For the hard of thinking, this list is meant to remain in Alphabetical
+order. If you could add yourselves to it in Alphabetical order that would
+so much easier [Ed]
+
 P: Person
 M: Mail patches to
 L: Mailing list that is relevant to this area
@@ -66,7 +70,7 @@
 
 3C501 NETWORK DRIVER
 P:	Alan Cox
-M:	net-patches@lxorguk.ukuu.org.uk
+M:	alan@the.3c501.cabal.tm
 L:	linux-net@vger.rutgers.edu
 S:	Maintained
 
@@ -124,6 +128,19 @@
 L:	linux-net@vger.rutgers.edu
 S:	Maintained
 
+ARM MFM AND FLOPPY DRIVERS
+P:	Dave Gilbert
+M:	linux@treblig.org
+S:	Maintained
+
+ARM PORT
+P:	Russell King
+M:	linux@arm.uk.linux.org
+L:	linux-arm@vger.rutgers.edu
+L:	arm-linux@tardis.ed.ac.uk
+W:	http://www.arm.uk.linux.org/~rmk/armlinux.html
+S:	Maintained
+
 AX.25 NETWORK LAYER
 P:	Jon Naylor
 M:	jsn@cs.nott.ac.uk
@@ -365,7 +382,7 @@
 M:	Alan.Cox@linux.org
 W:	http://www.mac.linux-m68k.org/home.html
 L:	linux-mac68k@wave.lm.com
-S:	Maintained
+S:	As time permits [Michael confess, you are the mac68k maintainer 8)]
 
 MENUCONFIG:
 P:	Michael Elizabeth Chastain
@@ -548,8 +565,8 @@
 
 SOUND
 P:	Alan Cox 
-M:	Alan.Cox@linux.org
-S:	Maintained
+M:	alan@redhat.com
+S:	Supported
 
 SPARC:
 P:	Eddie C. Dost
@@ -641,6 +658,7 @@
 VIDEO FOR LINUX
 P:	Alan Cox
 M:	Alan.Cox@linux.org
+W:	http://roadrunner.swansea.linux.org.uk/v4l.shtml
 S:	Maintained
 
 WAN ROUTER AND SANGOMA WANPIPE DRIVERS (X.25, FRAME RELAY, PPP)
@@ -669,18 +687,6 @@
 L:	linux-hams@vger.rutgers.edu
 S:	Maintained
 
-ARM PORT
-P:	Russell King
-M:	linux@arm.uk.linux.org
-L:	linux-arm@vger.rutgers.edu
-L:	arm-linux@tardis.ed.ac.uk
-W:	http://www.arm.uk.linux.org/~rmk/armlinux.html
-S:	Maintained
-
-ARM MFM AND FLOPPY DRIVERS
-P:	Dave Gilbert
-M:	linux@treblig.org
-S:	Maintained
 
 REST:
 P:	Linus Torvalds
diff -u --recursive --new-file v2.1.117/linux/Makefile linux/Makefile
--- v2.1.117/linux/Makefile	Thu Aug 20 17:05:15 1998
+++ linux/Makefile	Mon Aug 24 15:17:30 1998
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 1
-SUBLEVEL = 117
+SUBLEVEL = 118
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
 
@@ -125,7 +125,7 @@
 DRIVERS := $(DRIVERS) drivers/scsi/scsi.a
 endif
 
-ifneq ($(CONFIG_CD_NO_IDESCSI)$(CONFIG_BLK_DEV_IDECD)$(CONFIG_BLK_DEV_SR),)
+ifneq ($(CONFIG_CD_NO_IDESCSI)$(CONFIG_BLK_DEV_IDECD)$(CONFIG_BLK_DEV_SR)$(CONFIG_PARIDE_PCD),)
 DRIVERS := $(DRIVERS) drivers/cdrom/cdrom.a
 endif
 
diff -u --recursive --new-file v2.1.117/linux/arch/i386/kernel/bios32.c linux/arch/i386/kernel/bios32.c
--- v2.1.117/linux/arch/i386/kernel/bios32.c	Thu Aug  6 14:06:28 1998
+++ linux/arch/i386/kernel/bios32.c	Mon Aug 24 15:12:32 1998
@@ -1,7 +1,7 @@
 /*
  * bios32.c - Low-Level PCI Access
  *
- * $Id: bios32.c,v 1.44 1998/08/04 14:54:56 mj Exp $
+ * $Id: bios32.c,v 1.45 1998/08/15 10:41:04 mj Exp $
  *
  * Copyright 1993, 1994 Drew Eckhardt
  *      Visionary Computing
@@ -945,7 +945,8 @@
 __initfunc(void pcibios_fixup_peer_bridges(void))
 {
 	struct pci_bus *b = &pci_root;
-	int i;
+	int i, cnt=-1;
+	struct pci_dev *d;
 
 #ifdef CONFIG_PCI_DIRECT
 	/*
@@ -956,23 +957,34 @@
 	if (access_pci == &pci_direct_conf2)
 		return;
 #endif
+	for(d=b->devices; d; d=d->sibling)
+		if ((d->class >> 8) == PCI_CLASS_BRIDGE_HOST)
+			cnt++;
 	do {
 		int n = b->subordinate+1;
+		int found = 0;
 		u16 l;
 		for(i=0; i<256; i += 8)
 			if (!pcibios_read_config_word(n, i, PCI_VENDOR_ID, &l) &&
 			    l != 0x0000 && l != 0xffff) {
 				DBG("Found device at %02x:%02x\n", n, i);
-				printk("PCI: Discovered primary peer bus %02x\n", n);
-				b = kmalloc(sizeof(*b), GFP_KERNEL);
-				memset(b, 0, sizeof(*b));
-				b->next = pci_root.next;
-				pci_root.next = b;
-				b->number = b->secondary = n;
-				b->subordinate = 0xff;
-				b->subordinate = pci_scan_bus(b);
-				break;
+				found++;
+				if (!pcibios_read_config_word(n, i, PCI_CLASS_DEVICE, &l) &&
+				    l == PCI_CLASS_BRIDGE_HOST)
+					cnt++;
 			}
+		if (found && cnt > 0) {
+			cnt--;
+			printk("PCI: Discovered primary peer bus %02x\n", n);
+			b = kmalloc(sizeof(*b), GFP_KERNEL);
+			memset(b, 0, sizeof(*b));
+			b->next = pci_root.next;
+			pci_root.next = b;
+			b->number = b->secondary = n;
+			b->subordinate = 0xff;
+			b->subordinate = pci_scan_bus(b);
+			break;
+		}
 	} while (i < 256);
 }
 
@@ -1032,21 +1044,25 @@
 #ifdef __SMP__
 		/*
 		 * Recalculate IRQ numbers if we use the I/O APIC
+		 *
+		 * NOTE! If the "original" interrupt is marked as an old-fashioned
+		 * irq, we have to keep it old-fashioned even if it's a PCI device
+		 * and we could have found it in the MP-table transform.
 		 */
-		{
-		int irq;
-		unsigned char pin;
-
-		pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
-		if (pin) {
-			pin--;		/* interrupt pins are numbered starting from 1 */
-			irq = IO_APIC_get_PCI_irq_vector (dev->bus->number, PCI_SLOT(dev->devfn), pin);
-			if (irq >= 0) {
-				printk("PCI->APIC IRQ transform: (B%d,I%d,P%d) -> %d\n",
-					dev->bus->number, PCI_SLOT(dev->devfn), pin, irq);
-				dev->irq = irq;
-				}
-		}
+		if (IO_APIC_IRQ(dev->irq)) {
+			int irq;
+			unsigned char pin;
+
+			pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+			if (pin) {
+				pin--;		/* interrupt pins are numbered starting from 1 */
+				irq = IO_APIC_get_PCI_irq_vector (dev->bus->number, PCI_SLOT(dev->devfn), pin);
+				if (irq >= 0) {
+					printk("PCI->APIC IRQ transform: (B%d,I%d,P%d) -> %d\n",
+						dev->bus->number, PCI_SLOT(dev->devfn), pin, irq);
+					dev->irq = irq;
+					}
+			}
 		}
 #endif
 		/*
diff -u --recursive --new-file v2.1.117/linux/arch/i386/kernel/mca.c linux/arch/i386/kernel/mca.c
--- v2.1.117/linux/arch/i386/kernel/mca.c	Wed Apr  8 19:36:25 1998
+++ linux/arch/i386/kernel/mca.c	Mon Aug 24 13:14:09 1998
@@ -68,7 +68,7 @@
 static ssize_t proc_mca_read( struct file*, char*, size_t, loff_t *);
 static struct file_operations proc_mca_operations = {
 	NULL, proc_mca_read,
-	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
 };
 static struct inode_operations proc_mca_inode_operations = {
 	&proc_mca_operations,
diff -u --recursive --new-file v2.1.117/linux/arch/i386/kernel/mtrr.c linux/arch/i386/kernel/mtrr.c
--- v2.1.117/linux/arch/i386/kernel/mtrr.c	Tue Jul 28 14:21:07 1998
+++ linux/arch/i386/kernel/mtrr.c	Mon Aug 24 13:43:28 1998
@@ -1086,6 +1086,7 @@
     mtrr_ioctl,  /*  IOctl             */
     NULL,        /*  MMAP              */
     mtrr_open,   /*  Open              */
+    NULL,        /*  Flush             */
     mtrr_close,  /*  Release           */
     NULL,        /*  Fsync             */
     NULL,        /*  Fasync            */
diff -u --recursive --new-file v2.1.117/linux/arch/i386/kernel/process.c linux/arch/i386/kernel/process.c
--- v2.1.117/linux/arch/i386/kernel/process.c	Tue Aug 18 22:02:02 1998
+++ linux/arch/i386/kernel/process.c	Tue Aug 25 11:32:52 1998
@@ -727,6 +727,13 @@
 	gdt_table[next->tss.tr >> 3].b &= 0xfffffdff;
 	asm volatile("ltr %0": :"g" (*(unsigned short *)&next->tss.tr));
 
+	/*
+	 * Save away %fs and %gs. No need to save %es and %ds, as
+	 * those are always kernel segments while inside the kernel.
+	 */
+	asm volatile("movl %%fs,%0":"=m" (*(int *)&prev->tss.fs));
+	asm volatile("movl %%gs,%0":"=m" (*(int *)&prev->tss.gs));
+
 	/* Re-load LDT if necessary */
 	if (next->mm->segments != prev->mm->segments)
 		asm volatile("lldt %0": :"g" (*(unsigned short *)&next->tss.ldt));
@@ -736,13 +743,8 @@
 		asm volatile("movl %0,%%cr3": :"r" (next->tss.cr3));
 
 	/*
-	 * Save away %fs and %gs. No need to save %es and %ds, as
-	 * those are always kernel segments while inside the kernel.
-	 * Restore the new values.
+	 * Restore %fs and %gs.
 	 */
-	asm volatile("movl %%fs,%0":"=m" (*(int *)&prev->tss.fs));
-	asm volatile("movl %%gs,%0":"=m" (*(int *)&prev->tss.gs));
-
 	loadsegment(fs,next->tss.fs);
 	loadsegment(gs,next->tss.gs);
 
@@ -761,28 +763,19 @@
 
 asmlinkage int sys_fork(struct pt_regs regs)
 {
-	int ret;
-
-	lock_kernel();
-	ret = do_fork(SIGCHLD, regs.esp, &regs);
-	unlock_kernel();
-	return ret;
+	return do_fork(SIGCHLD, regs.esp, &regs);
 }
 
 asmlinkage int sys_clone(struct pt_regs regs)
 {
 	unsigned long clone_flags;
 	unsigned long newsp;
-	int ret;
 
-	lock_kernel();
 	clone_flags = regs.ebx;
 	newsp = regs.ecx;
 	if (!newsp)
 		newsp = regs.esp;
-	ret = do_fork(clone_flags, newsp, &regs);
-	unlock_kernel();
-	return ret;
+	return do_fork(clone_flags, newsp, &regs);
 }
 
 /*
diff -u --recursive --new-file v2.1.117/linux/arch/i386/kernel/signal.c linux/arch/i386/kernel/signal.c
--- v2.1.117/linux/arch/i386/kernel/signal.c	Tue Aug 18 22:02:02 1998
+++ linux/arch/i386/kernel/signal.c	Tue Aug 25 17:42:46 1998
@@ -184,26 +184,17 @@
 
 #define COPY_SEG(seg)							\
 	{ unsigned short tmp;						\
-	   err |= __get_user(tmp, &sc->seg);				\
-	  if ((tmp & 0xfffc)		/* not a NULL selectors */	\
-	      && (tmp & 0x4) != 0x4	/* not a LDT selector */	\
-	      && (tmp & 3) != 3)	/* not a RPL3 GDT selector */	\
-		  goto badframe;					\
+	  err |= __get_user(tmp, &sc->seg);				\
 	  regs->x##seg = tmp; }
 
 #define COPY_SEG_STRICT(seg)						\
 	{ unsigned short tmp;						\
 	  err |= __get_user(tmp, &sc->seg);				\
-	  if ((tmp & 0xfffc) && (tmp & 3) != 3) goto badframe;		\
-	  regs->x##seg = tmp; }
+	  regs->x##seg = tmp|3; }
 
 #define GET_SEG(seg)							\
 	{ unsigned short tmp;						\
 	  err |= __get_user(tmp, &sc->seg);				\
-	  if ((tmp & 0xfffc)		/* not a NULL selectors */	\
-	      && (tmp & 0x4) != 0x4	/* not a LDT selector */	\
-	      && (tmp & 3) != 3)	/* not a RPL3 GDT selector */	\
-		  goto badframe;					\
 	  loadsegment(seg,tmp); }
 
 	GET_SEG(gs);
@@ -459,15 +450,12 @@
 	/* Set up registers for signal handler */
 	regs->esp = (unsigned long) frame;
 	regs->eip = (unsigned long) ka->sa.sa_handler;
-	{
-		unsigned long seg = __USER_DS;
-		__asm__("movl %w0,%%fs ; movl %w0,%%gs": "=r"(seg) : "0"(seg));
-		set_fs(USER_DS);
-		regs->xds = seg;
-		regs->xes = seg;
-		regs->xss = seg;
-		regs->xcs = __USER_CS;
-	}
+
+	set_fs(USER_DS);
+	regs->xds = __USER_DS;
+	regs->xes = __USER_DS;
+	regs->xss = __USER_DS;
+	regs->xcs = __USER_CS;
 	regs->eflags &= ~TF_MASK;
 
 #if DEBUG_SIG
@@ -533,15 +521,12 @@
 	/* Set up registers for signal handler */
 	regs->esp = (unsigned long) frame;
 	regs->eip = (unsigned long) ka->sa.sa_handler;
-	{
-		unsigned long seg = __USER_DS;
-		__asm__("movl %w0,%%fs ; movl %w0,%%gs": "=r"(seg) : "0"(seg));
-		set_fs(USER_DS);
-		regs->xds = seg;
-		regs->xes = seg;
-		regs->xss = seg;
-		regs->xcs = __USER_CS;
-	}
+
+	set_fs(USER_DS);
+	regs->xds = __USER_DS;
+	regs->xes = __USER_DS;
+	regs->xss = __USER_DS;
+	regs->xcs = __USER_CS;
 	regs->eflags &= ~TF_MASK;
 
 #if DEBUG_SIG
diff -u --recursive --new-file v2.1.117/linux/arch/i386/lib/usercopy.c linux/arch/i386/lib/usercopy.c
--- v2.1.117/linux/arch/i386/lib/usercopy.c	Fri Jan 23 18:10:31 1998
+++ linux/arch/i386/lib/usercopy.c	Mon Aug 24 12:29:35 1998
@@ -7,7 +7,7 @@
  */
 #include <asm/uaccess.h>
 
-inline unsigned long
+unsigned long
 __generic_copy_to_user(void *to, const void *from, unsigned long n)
 {
 	if (access_ok(VERIFY_WRITE, to, n))
@@ -15,11 +15,11 @@
 	return n;
 }
 
-inline unsigned long
+unsigned long
 __generic_copy_from_user(void *to, const void *from, unsigned long n)
 {
 	if (access_ok(VERIFY_READ, from, n))
-		__copy_user(to,from,n);
+		__copy_user_zeroing(to,from,n);
 	return n;
 }
 
diff -u --recursive --new-file v2.1.117/linux/arch/i386/mm/init.c linux/arch/i386/mm/init.c
--- v2.1.117/linux/arch/i386/mm/init.c	Tue Aug 18 22:02:02 1998
+++ linux/arch/i386/mm/init.c	Thu Aug 20 16:18:09 1998
@@ -220,7 +220,7 @@
 
 	for (idx=1; idx <= __end_of_fixed_addresses; idx += PTRS_PER_PTE)
 	{
-		address = fix_to_virt(__end_of_fixed_addresses-idx);
+		address = __fix_to_virt(__end_of_fixed_addresses-idx);
 		pg_dir = swapper_pg_dir + (address >> PGDIR_SHIFT);
 		memset((void *)start_mem, 0, PAGE_SIZE);
 		pgd_val(*pg_dir) = _PAGE_TABLE | __pa(start_mem);
@@ -246,8 +246,12 @@
 
 void set_fixmap (enum fixed_addresses idx, unsigned long phys)
 {
-	unsigned long address = fix_to_virt(idx);
+	unsigned long address = __fix_to_virt(idx);
 
+	if (idx >= __end_of_fixed_addresses) {
+		printk("Invalid set_fixmap\n");
+		return;
+	}
 	set_pte_phys (address,phys);
 }
 
diff -u --recursive --new-file v2.1.117/linux/arch/m68k/atari/stram.c linux/arch/m68k/atari/stram.c
--- v2.1.117/linux/arch/m68k/atari/stram.c	Mon Aug  3 12:45:44 1998
+++ linux/arch/m68k/atari/stram.c	Mon Aug 24 13:44:38 1998
@@ -218,31 +218,31 @@
 #ifdef CONFIG_STRAM_SWAP
 static int swap_init( unsigned long start_mem, unsigned long swap_data );
 static inline int unswap_pte( struct vm_area_struct * vma, unsigned long
-                              address, pte_t *dir, unsigned long entry,
-                              unsigned long page, int isswap );
+			      address, pte_t *dir, unsigned long entry,
+			      unsigned long page, int isswap );
 static inline int unswap_pmd( struct vm_area_struct * vma, pmd_t *dir,
-                              unsigned long address, unsigned long size,
-                              unsigned long offset, unsigned long entry,
-                              unsigned long page, int isswap );
+			      unsigned long address, unsigned long size,
+			      unsigned long offset, unsigned long entry,
+			      unsigned long page, int isswap );
 static inline int unswap_pgd( struct vm_area_struct * vma, pgd_t *dir,
-                              unsigned long address, unsigned long size,
-                              unsigned long entry, unsigned long page, int
-                              isswap );
+			      unsigned long address, unsigned long size,
+			      unsigned long entry, unsigned long page, int
+			      isswap );
 static int unswap_vma( struct vm_area_struct * vma, pgd_t *pgdir, unsigned
-                       long entry, unsigned long page, int isswap );
+		       long entry, unsigned long page, int isswap );
 static int unswap_process( struct mm_struct * mm, unsigned long entry,
-                           unsigned long page, int isswap );
+			   unsigned long page, int isswap );
 static int unswap_by_move( unsigned char *map, unsigned long max, unsigned
-                           long start, unsigned long n_pages );
+			   long start, unsigned long n_pages );
 static int unswap_by_read( unsigned char *map, unsigned long max, unsigned
-                           long start, unsigned long n_pages );
+			   long start, unsigned long n_pages );
 static void *get_stram_region( unsigned long n_pages );
 static void free_stram_region( unsigned long offset, unsigned long n_pages
-                               );
+			       );
 static int in_some_region( unsigned long addr );
 static unsigned long find_free_region( unsigned long n_pages, unsigned long
-                                       *total_free, unsigned long
-                                       *region_free );
+				       *total_free, unsigned long
+				       *region_free );
 static void do_stram_request( void );
 static int stram_open( struct inode *inode, struct file *filp );
 static int stram_release( struct inode *inode, struct file *filp );
@@ -1249,16 +1249,17 @@
 
 
 static struct file_operations stram_fops = {
-        NULL,                   /* lseek - default */
-        block_read,             /* read - general block-dev read */
-        block_write,            /* write - general block-dev write */
-        NULL,                   /* readdir - bad */
-        NULL,                   /* select */
-        NULL,                   /* ioctl */
-        NULL,                   /* mmap */
-        stram_open,             /* open */
-        stram_release,          /* release */
-        block_fsync             /* fsync */
+	NULL,                   /* lseek - default */
+	block_read,             /* read - general block-dev read */
+	block_write,            /* write - general block-dev write */
+	NULL,                   /* readdir - bad */
+	NULL,                   /* select */
+	NULL,                   /* ioctl */
+	NULL,                   /* mmap */
+	stram_open,             /* open */
+	NULL,			/* flush */
+	stram_release,          /* release */
+	block_fsync             /* fsync */
 };
 
 __initfunc(int stram_device_init(void))
@@ -1269,12 +1270,12 @@
 	return( -ENXIO );
 
     if (!max_swap_size)
-        /* swapping not enabled */
+	/* swapping not enabled */
 	return( -ENXIO );
 	
     if (register_blkdev( STRAM_MAJOR, "stram", &stram_fops)) {
-        printk( KERN_ERR "stram: Unable to get major %d\n", STRAM_MAJOR );
-        return( -ENXIO );
+	printk( KERN_ERR "stram: Unable to get major %d\n", STRAM_MAJOR );
+	return( -ENXIO );
     }
 
     blk_dev[STRAM_MAJOR].request_fn = do_stram_request;
diff -u --recursive --new-file v2.1.117/linux/arch/m68k/bvme6000/rtc.c linux/arch/m68k/bvme6000/rtc.c
--- v2.1.117/linux/arch/m68k/bvme6000/rtc.c	Tue Jun 23 10:01:20 1998
+++ linux/arch/m68k/bvme6000/rtc.c	Mon Aug 24 13:14:10 1998
@@ -153,6 +153,7 @@
 	rtc_ioctl,
 	NULL,		/* No mmap */
 	rtc_open,
+	NULL,		/* flush */
 	rtc_release
 };
 
diff -u --recursive --new-file v2.1.117/linux/arch/m68k/mac/adb-bus.c linux/arch/m68k/mac/adb-bus.c
--- v2.1.117/linux/arch/m68k/mac/adb-bus.c	Tue Aug 18 22:02:03 1998
+++ linux/arch/m68k/mac/adb-bus.c	Mon Aug 24 13:02:43 1998
@@ -2504,6 +2504,7 @@
 	NULL,		/* no ioctl yet */
 	NULL,		/* no mmap */
 	adb_open,
+	NULL,		/* flush */
 	adb_release
 };
 
@@ -2688,6 +2689,7 @@
 	NULL,		/* no ioctl */
 	NULL,		/* no mmap */
 	adb_open,
+	NULL,		/* flush */
 	adb_release
 };
 
diff -u --recursive --new-file v2.1.117/linux/arch/m68k/mvme16x/rtc.c linux/arch/m68k/mvme16x/rtc.c
--- v2.1.117/linux/arch/m68k/mvme16x/rtc.c	Tue Jun 23 10:01:21 1998
+++ linux/arch/m68k/mvme16x/rtc.c	Mon Aug 24 13:14:10 1998
@@ -144,6 +144,7 @@
 	rtc_ioctl,
 	NULL,		/* No mmap */
 	rtc_open,
+	NULL,		/* flush */
 	rtc_release
 };
 
diff -u --recursive --new-file v2.1.117/linux/arch/ppc/kernel/ppc_htab.c linux/arch/ppc/kernel/ppc_htab.c
--- v2.1.117/linux/arch/ppc/kernel/ppc_htab.c	Thu Aug  6 14:06:29 1998
+++ linux/arch/ppc/kernel/ppc_htab.c	Mon Aug 24 13:14:10 1998
@@ -49,6 +49,7 @@
     NULL,		/* ioctl   */
     NULL,		/* mmap	   */
     NULL,		/* no special open code	   */
+    NULL,		/* flush */
     NULL,		/* no special release code */
     NULL		/* can't fsync */
 };
diff -u --recursive --new-file v2.1.117/linux/arch/sparc64/solaris/socksys.c linux/arch/sparc64/solaris/socksys.c
--- v2.1.117/linux/arch/sparc64/solaris/socksys.c	Thu Apr 23 20:21:32 1998
+++ linux/arch/sparc64/solaris/socksys.c	Mon Aug 24 13:14:10 1998
@@ -57,6 +57,7 @@
 	NULL,		/* ioctl */
 	NULL,		/* mmap */
 	NULL,		/* open */
+	NULL,		/* flush */
 	NULL,		/* release */
 };
 
@@ -170,6 +171,7 @@
 	NULL,		/* ioctl */
 	NULL,		/* mmap */
 	socksys_open,	/* open */
+	NULL,		/* flush */
 	socksys_release,/* release */
 };
 
diff -u --recursive --new-file v2.1.117/linux/drivers/Makefile linux/drivers/Makefile
--- v2.1.117/linux/drivers/Makefile	Thu Aug  6 14:06:31 1998
+++ linux/drivers/Makefile	Thu Aug 20 15:17:05 1998
@@ -63,7 +63,7 @@
   endif
 endif
 
-ifneq ($(CONFIG_CD_NO_IDESCSI)$(CONFIG_BLK_DEV_IDECD)$(CONFIG_BLK_DEV_SR),)
+ifneq ($(CONFIG_CD_NO_IDESCSI)$(CONFIG_BLK_DEV_IDECD)$(CONFIG_BLK_DEV_SR)$(CONFIG_PARIDE_PCD),)
 SUB_DIRS += cdrom
 MOD_SUB_DIRS += cdrom
 endif
diff -u --recursive --new-file v2.1.117/linux/drivers/acorn/block/fd1772.c linux/drivers/acorn/block/fd1772.c
--- v2.1.117/linux/drivers/acorn/block/fd1772.c	Sun Jun  7 11:16:28 1998
+++ linux/drivers/acorn/block/fd1772.c	Mon Aug 24 13:02:44 1998
@@ -1589,6 +1589,7 @@
 	fd_ioctl,		/* ioctl */
 	NULL,			/* mmap */
 	floppy_open,		/* open */
+	NULL,			/* flush */
 	floppy_release,		/* release */
 	block_fsync,		/* fsync */
 	NULL,			/* fasync */
diff -u --recursive --new-file v2.1.117/linux/drivers/acorn/block/mfmhd.c linux/drivers/acorn/block/mfmhd.c
--- v2.1.117/linux/drivers/acorn/block/mfmhd.c	Tue Jul 21 00:15:30 1998
+++ linux/drivers/acorn/block/mfmhd.c	Mon Aug 24 13:14:09 1998
@@ -1372,6 +1372,7 @@
 	mfm_ioctl,		/* ioctl */
 	NULL,			/* mmap */
 	mfm_open,		/* open */
+	NULL,			/* flush */
 	mfm_release,		/* release */
 	block_fsync,		/* fsync */
 	NULL,			/* fasync */
diff -u --recursive --new-file v2.1.117/linux/drivers/ap1000/ap.c linux/drivers/ap1000/ap.c
--- v2.1.117/linux/drivers/ap1000/ap.c	Sun Jan 26 02:07:10 1997
+++ linux/drivers/ap1000/ap.c	Mon Aug 24 13:45:51 1998
@@ -48,12 +48,10 @@
 
 static volatile int request_count = 0;
 
-#ifdef MODULE
 static void ap_release(struct inode * inode, struct file * filp)
 {
 	MOD_DEC_USE_COUNT;
 }
-#endif
 
 static void ap_request(void)
 {
@@ -247,20 +245,17 @@
 } 
 
 static struct file_operations ap_fops = {
-        NULL,                   /* lseek - default */
-        block_read,             /* read - general block-dev read */
-        block_write,            /* write - general block-dev write */
-        NULL,                   /* readdir - bad */
-        NULL,                   /* poll */
-        ap_ioctl,               /* ioctl */
-        NULL,                   /* mmap */
-        ap_open,                /* open */
-#ifndef MODULE
-	NULL,		/* no special release code... */
-#else
-	ap_release,	/* module needs to decrement use count */
-#endif
-        block_fsync,            /* fsync */
+	NULL,                   /* lseek - default */
+	block_read,             /* read - general block-dev read */
+	block_write,            /* write - general block-dev write */
+	NULL,                   /* readdir - bad */
+	NULL,                   /* poll */
+	ap_ioctl,               /* ioctl */
+	NULL,                   /* mmap */
+	ap_open,                /* open */
+	NULL,			/* flush */
+	ap_release,		/* module needs to decrement use count */
+	block_fsync,            /* fsync */
 };
 
 
diff -u --recursive --new-file v2.1.117/linux/drivers/ap1000/ddv.c linux/drivers/ap1000/ddv.c
--- v2.1.117/linux/drivers/ap1000/ddv.c	Fri May  8 23:14:47 1998
+++ linux/drivers/ap1000/ddv.c	Mon Aug 24 13:02:44 1998
@@ -884,6 +884,7 @@
         ddv_ioctl,               /* ioctl */
         NULL,                   /* mmap */
         ddv_open,                /* open */
+	NULL,			/* flush */
 	ddv_release,
         block_fsync          /* fsync */
 };
diff -u --recursive --new-file v2.1.117/linux/drivers/ap1000/ringbuf.c linux/drivers/ap1000/ringbuf.c
--- v2.1.117/linux/drivers/ap1000/ringbuf.c	Fri Jan 16 20:38:21 1998
+++ linux/drivers/ap1000/ringbuf.c	Mon Aug 24 13:14:10 1998
@@ -302,6 +302,7 @@
 	ringbuf_ioctl,	/* ioctl */
 	NULL,           /* mmap */
 	NULL,		/* no special open code */
+	NULL,		/* flush */
 	NULL,		/* no special release code */
 	NULL		/* can't fsync */
 };
diff -u --recursive --new-file v2.1.117/linux/drivers/block/Makefile linux/drivers/block/Makefile
--- v2.1.117/linux/drivers/block/Makefile	Wed Jul  1 19:38:53 1998
+++ linux/drivers/block/Makefile	Thu Aug 20 15:17:05 1998
@@ -269,10 +269,10 @@
 
 ifeq ($(CONFIG_PARIDE),y)
 SUB_DIRS	+= paride
-MOD_SUB_DIRS	+= paride
+MOD_IN_SUB_DIRS	+= paride
 else
   ifeq ($(CONFIG_PARIDE),m)
-  MOD_SUB_DIRS	+= paride
+  MOD_IN_SUB_DIRS	+= paride
   endif
 endif
 
diff -u --recursive --new-file v2.1.117/linux/drivers/block/acsi.c linux/drivers/block/acsi.c
--- v2.1.117/linux/drivers/block/acsi.c	Wed Jun 24 22:54:04 1998
+++ linux/drivers/block/acsi.c	Mon Aug 24 13:02:43 1998
@@ -1788,7 +1788,8 @@
 	acsi_ioctl,		/* ioctl */
 	NULL,			/* mmap */
 	acsi_open,		/* open */
-	acsi_release,	/* release */
+	NULL,			/* flush */
+	acsi_release,		/* release */
 	block_fsync,		/* fsync */
 	NULL,			/* fasync */
 	acsi_media_change,	/* media_change */
diff -u --recursive --new-file v2.1.117/linux/drivers/block/acsi_slm.c linux/drivers/block/acsi_slm.c
--- v2.1.117/linux/drivers/block/acsi_slm.c	Mon Feb 23 18:12:03 1998
+++ linux/drivers/block/acsi_slm.c	Mon Aug 24 13:02:43 1998
@@ -288,7 +288,8 @@
 	slm_ioctl,		/* ioctl */
 	NULL,			/* mmap */
 	slm_open,		/* open */
-	slm_release,	/* release */
+	NULL,			/* flush */
+	slm_release,		/* release */
 	NULL			/* fsync */
 };
 
diff -u --recursive --new-file v2.1.117/linux/drivers/block/amiflop.c linux/drivers/block/amiflop.c
--- v2.1.117/linux/drivers/block/amiflop.c	Tue Jun 23 10:01:22 1998
+++ linux/drivers/block/amiflop.c	Mon Aug 24 13:02:43 1998
@@ -1747,6 +1747,7 @@
 	fd_ioctl,		/* ioctl */
 	NULL,			/* mmap */
 	floppy_open,		/* open */
+	NULL,			/* flush */
 	floppy_release, 	/* release */
 	block_fsync,		/* fsync */
 	NULL,			/* fasync */
diff -u --recursive --new-file v2.1.117/linux/drivers/block/ataflop.c linux/drivers/block/ataflop.c
--- v2.1.117/linux/drivers/block/ataflop.c	Mon Aug  3 12:45:44 1998
+++ linux/drivers/block/ataflop.c	Mon Aug 24 13:02:43 1998
@@ -2008,6 +2008,7 @@
 	fd_ioctl,		/* ioctl */
 	NULL,			/* mmap */
 	floppy_open,		/* open */
+	NULL,			/* flush */
 	floppy_release, 	/* release */
 	block_fsync,		/* fsync */
 	NULL,			/* fasync */
diff -u --recursive --new-file v2.1.117/linux/drivers/block/floppy.c linux/drivers/block/floppy.c
--- v2.1.117/linux/drivers/block/floppy.c	Wed Jun 24 22:54:04 1998
+++ linux/drivers/block/floppy.c	Mon Aug 24 13:02:44 1998
@@ -3836,6 +3836,7 @@
 	fd_ioctl,		/* ioctl */
 	NULL,			/* mmap */
 	floppy_open,		/* open */
+	NULL,			/* flush */
 	floppy_release,		/* release */
 	block_fsync,		/* fsync */
 	NULL,			/* fasync */
diff -u --recursive --new-file v2.1.117/linux/drivers/block/genhd.c linux/drivers/block/genhd.c
--- v2.1.117/linux/drivers/block/genhd.c	Tue Aug 18 22:02:03 1998
+++ linux/drivers/block/genhd.c	Tue Aug 25 14:12:07 1998
@@ -411,28 +411,22 @@
 		} else {
 			/*
 			 * Examine the partition table for common translations.
-			 * This is necessary for drives for situations where
-			 * the translated geometry is unavailable from the BIOS.
+			 * This is useful for drives in situations where the
+			 * translated geometry is unavailable from the BIOS.
 			 */
-			int	xlate_done = 0;
-			for (i = 0; i < 4 && !xlate_done; i++) {
+			for (i = 0; i < 4; i++) {
 				struct partition *q = &p[i];
 				if (NR_SECTS(q)
 				   && (q->sector & 63) == 1
 				   && (q->end_sector & 63) == 63) {
 					unsigned int heads = q->end_head + 1;
-					if (heads == 32 || heads == 64 || heads == 128 || heads == 255) {
-
+					if (heads == 32 || heads == 64 ||
+					    heads == 128 || heads == 255 ||
+					    heads == 240) {
 						(void) ide_xlate_1024(dev, heads, " [PTBL]");
-						xlate_done = 1;
+						break;
 					}
 				}
-			}
-			if (!xlate_done) {
-				/*
-				 * Default translation is equivalent of "BIOS LBA":
-				 */
-				ide_xlate_1024(dev, -2, " [LBA]");
 			}
 		}
 	}
diff -u --recursive --new-file v2.1.117/linux/drivers/block/ide.c linux/drivers/block/ide.c
--- v2.1.117/linux/drivers/block/ide.c	Tue Aug 18 22:02:03 1998
+++ linux/drivers/block/ide.c	Mon Aug 24 14:07:42 1998
@@ -2869,6 +2869,7 @@
 	ide_ioctl,		/* ioctl */
 	NULL,			/* mmap */
 	ide_open,		/* open */
+	NULL,			/* flush */
 	ide_release,		/* release */
 	block_fsync,		/* fsync */
 	NULL,			/* fasync */
diff -u --recursive --new-file v2.1.117/linux/drivers/block/loop.c linux/drivers/block/loop.c
--- v2.1.117/linux/drivers/block/loop.c	Tue Aug 18 22:02:03 1998
+++ linux/drivers/block/loop.c	Mon Aug 24 13:14:09 1998
@@ -670,6 +670,7 @@
 	lo_ioctl,		/* ioctl */
 	NULL,			/* mmap */
 	lo_open,		/* open */
+	NULL,			/* flush */
 	lo_release		/* release */
 };
 
diff -u --recursive --new-file v2.1.117/linux/drivers/block/md.c linux/drivers/block/md.c
--- v2.1.117/linux/drivers/block/md.c	Wed Jun 24 22:54:04 1998
+++ linux/drivers/block/md.c	Mon Aug 24 13:14:09 1998
@@ -754,6 +754,7 @@
   md_ioctl,
   NULL,
   md_open,
+  NULL,
   md_release,
   block_fsync
 };
diff -u --recursive --new-file v2.1.117/linux/drivers/block/nbd.c linux/drivers/block/nbd.c
--- v2.1.117/linux/drivers/block/nbd.c	Tue Aug 18 22:02:03 1998
+++ linux/drivers/block/nbd.c	Mon Aug 24 13:14:09 1998
@@ -415,6 +415,7 @@
 	nbd_ioctl,		/* ioctl */
 	NULL,			/* mmap */
 	nbd_open,		/* open */
+	NULL,			/* flush */
 	nbd_release		/* release */
 };
 
diff -u --recursive --new-file v2.1.117/linux/drivers/block/paride/Makefile linux/drivers/block/paride/Makefile
--- v2.1.117/linux/drivers/block/paride/Makefile	Tue Jun 23 10:01:22 1998
+++ linux/drivers/block/paride/Makefile	Thu Aug 20 15:17:05 1998
@@ -12,6 +12,7 @@
 MOD_SUB_DIRS := $(SUB_DIRS)
 ALL_SUB_DIRS := $(SUB_DIRS)
 
+MOD_LIST_NAME := PARIDE_MODULES
 L_TARGET := paride.a
 MX_OBJS  :=
 LX_OBJS  := 
@@ -30,7 +31,7 @@
   LX_OBJS += pd.o
 else
   ifeq ($(CONFIG_PARIDE_PD),m)
-    MX_OBJS += pd.o
+    M_OBJS += pd.o
   endif
 endif
 
@@ -38,7 +39,7 @@
   LX_OBJS += pcd.o
 else
   ifeq ($(CONFIG_PARIDE_PCD),m)
-    MX_OBJS += pcd.o
+    M_OBJS += pcd.o
   endif
 endif
 
@@ -46,7 +47,7 @@
   LX_OBJS += pf.o
 else
   ifeq ($(CONFIG_PARIDE_PF),m)
-    MX_OBJS += pf.o
+    M_OBJS += pf.o
   endif
 endif
 
@@ -54,7 +55,7 @@
   LX_OBJS += pt.o
 else
   ifeq ($(CONFIG_PARIDE_PT),m)
-    MX_OBJS += pt.o
+    M_OBJS += pt.o
   endif
 endif
 
@@ -62,7 +63,7 @@
   LX_OBJS += pg.o
 else
   ifeq ($(CONFIG_PARIDE_PG),m)
-    MX_OBJS += pg.o
+    M_OBJS += pg.o
   endif
 endif
 
@@ -70,7 +71,7 @@
   LX_OBJS += aten.o
 else
   ifeq ($(CONFIG_PARIDE_ATEN),m)
-    MX_OBJS += aten.o
+    M_OBJS += aten.o
   endif
 endif
 
@@ -78,7 +79,7 @@
   LX_OBJS += bpck.o
 else
   ifeq ($(CONFIG_PARIDE_BPCK),m)
-    MX_OBJS += bpck.o
+    M_OBJS += bpck.o
   endif
 endif
 
@@ -86,7 +87,7 @@
   LX_OBJS += comm.o
 else
   ifeq ($(CONFIG_PARIDE_COMM),m)
-    MX_OBJS += comm.o
+    M_OBJS += comm.o
   endif
 endif
 
@@ -94,7 +95,7 @@
   LX_OBJS += dstr.o
 else
   ifeq ($(CONFIG_PARIDE_DSTR),m)
-    MX_OBJS += dstr.o
+    M_OBJS += dstr.o
   endif
 endif
 
@@ -102,7 +103,7 @@
   LX_OBJS += kbic.o
 else
   ifeq ($(CONFIG_PARIDE_KBIC),m)
-    MX_OBJS += kbic.o
+    M_OBJS += kbic.o
   endif
 endif
 
@@ -110,7 +111,7 @@
   LX_OBJS += epat.o
 else
   ifeq ($(CONFIG_PARIDE_EPAT),m)
-    MX_OBJS += epat.o
+    M_OBJS += epat.o
   endif
 endif
 
@@ -118,7 +119,7 @@
   LX_OBJS += epia.o
 else
   ifeq ($(CONFIG_PARIDE_EPIA),m)
-    MX_OBJS += epia.o
+    M_OBJS += epia.o
   endif
 endif
 
@@ -126,7 +127,7 @@
   LX_OBJS += fit2.o
 else
   ifeq ($(CONFIG_PARIDE_FIT2),m)
-    MX_OBJS += fit2.o
+    M_OBJS += fit2.o
   endif
 endif
 
@@ -134,7 +135,7 @@
   LX_OBJS += fit3.o
 else
   ifeq ($(CONFIG_PARIDE_FIT3),m)
-    MX_OBJS += fit3.o
+    M_OBJS += fit3.o
   endif
 endif
 
@@ -142,7 +143,7 @@
   LX_OBJS += frpw.o
 else
   ifeq ($(CONFIG_PARIDE_FRPW),m)
-    MX_OBJS += frpw.o
+    M_OBJS += frpw.o
   endif
 endif
 
@@ -150,7 +151,7 @@
   LX_OBJS += on20.o
 else
   ifeq ($(CONFIG_PARIDE_ON20),m)
-    MX_OBJS += on20.o
+    M_OBJS += on20.o
   endif
 endif
 
@@ -158,7 +159,7 @@
   LX_OBJS += on26.o
 else
   ifeq ($(CONFIG_PARIDE_ON26),m)
-    MX_OBJS += on26.o
+    M_OBJS += on26.o
   endif
 endif
 
@@ -166,7 +167,7 @@
   LX_OBJS += ktti.o
 else
   ifeq ($(CONFIG_PARIDE_KTTI),m)
-    MX_OBJS += ktti.o
+    M_OBJS += ktti.o
   endif
 endif
 
diff -u --recursive --new-file v2.1.117/linux/drivers/block/paride/bpck.c linux/drivers/block/paride/bpck.c
--- v2.1.117/linux/drivers/block/paride/bpck.c	Wed May 20 19:10:38 1998
+++ linux/drivers/block/paride/bpck.c	Thu Aug 20 15:17:05 1998
@@ -10,10 +10,11 @@
 /* Changes:
 
 	1.01	GRG 1998.05.05 init_proto, release_proto, pi->delay 
+	1.02    GRG 1998.08.15 default pi->delay returned to 4
 
 */
 
-#define	BPCK_VERSION	"1.01" 
+#define	BPCK_VERSION	"1.02" 
 
 #include <linux/module.h>
 #include <linux/delay.h>
@@ -450,7 +451,7 @@
 {       MOD_DEC_USE_COUNT;
 }
 
-struct pi_protocol bpck = { "bpck",0,5,2,1,256,
+struct pi_protocol bpck = { "bpck",0,5,2,4,256,
 			  bpck_write_regr,
 			  bpck_read_regr,
 			  bpck_write_block,
diff -u --recursive --new-file v2.1.117/linux/drivers/block/paride/paride.c linux/drivers/block/paride/paride.c
--- v2.1.117/linux/drivers/block/paride/paride.c	Wed Jun 24 22:54:04 1998
+++ linux/drivers/block/paride/paride.c	Thu Aug 20 15:17:05 1998
@@ -11,10 +11,11 @@
 
 	1.01	GRG 1998.05.03	Use spinlocks
 	1.02	GRG 1998.05.05  init_proto, release_proto, ktti
+	1.03	GRG 1998.08.15  eliminate compiler warning
 
 */
 
-#define PI_VERSION      "1.02"
+#define PI_VERSION      "1.03"
 
 #include <linux/module.h>
 #include <linux/config.h>
@@ -249,7 +250,7 @@
 
 	if (verbose) printk("%s: 0x%x is %s\n",pi->device,pi->port,pp->name);
 	
-	pi->parname = pp->name;
+	pi->parname = (char *)pp->name;
 
 #endif
 }
diff -u --recursive --new-file v2.1.117/linux/drivers/block/paride/pcd.c linux/drivers/block/paride/pcd.c
--- v2.1.117/linux/drivers/block/paride/pcd.c	Mon Aug  3 12:45:44 1998
+++ linux/drivers/block/paride/pcd.c	Thu Aug 20 15:17:05 1998
@@ -2,11 +2,11 @@
 	pcd.c	(c) 1997-8  Grant R. Guenther <grant@torque.net>
 		            Under the terms of the GNU public license.
 
-	This is a high-level driver for parallel port ATAPI CDROM
+	This is a high-level driver for parallel port ATAPI CD-ROM
         drives based on chips supported by the paride module.
 
         By default, the driver will autoprobe for a single parallel
-        port ATAPI CDROM drive, but if their individual parameters are
+        port ATAPI CD-ROM drive, but if their individual parameters are
         specified, the driver can handle up to 4 drives.
 
         The behaviour of the pcd driver can be altered by setting
@@ -38,7 +38,7 @@
                         of the mode numbers supported by the adapter.
                         (-1 if not given)
 
-		<slv>   ATAPI CDROMs can be jumpered to master or slave.
+		<slv>   ATAPI CD-ROMs can be jumpered to master or slave.
 			Set this to 0 to choose the master drive, 1 to
                         choose the slave, -1 (the default) to choose the
 			first drive found.
@@ -61,10 +61,11 @@
                         (default "pcd")
 
             verbose     This parameter controls the amount of logging
-                        that is done while the driver probes for
-                        devices.  Set it to 0 for a quiet load, or 1 to
-                        see all the progress messages.  (default 0)
-
+                        that the driver will do.  Set it to 0 for
+                        normal operation, 1 to see autoprobe progress
+                        messages, or 2 to see additional debugging
+                        output.  (default 0)
+  
             nice        This parameter controls the driver's use of
                         idle CPU time, at the expense of some speed.
  
@@ -85,16 +86,20 @@
 
 /* Changes:
 
-	1.01	GRG 1997.01.24	Added test unit ready support
+	1.01	GRG 1998.01.24	Added test unit ready support
 	1.02    GRG 1998.05.06  Changes to pcd_completion, ready_wait,
 				and loosen interpretation of ATAPI
 			        standard for clearing error status.
 				Use spinlocks. Eliminate sti().
 	1.03    GRG 1998.06.16  Eliminated an Ugh
+	1.04	GRG 1998.08.15  Added extra debugging, improvements to
+				pcd_completion, use HZ in loop timing
+	1.05	GRG 1998.08.16	Conformed to "Uniform CD-ROM" standard
+	1.06    GRG 1998.08.19  Added audio ioctl support
 
 */
 
-#define	PCD_VERSION	"1.03"
+#define	PCD_VERSION	"1.06"
 #define PCD_MAJOR	46
 #define PCD_NAME	"pcd"
 #define PCD_UNITS	4
@@ -185,9 +190,10 @@
 #define PCD_RETRIES	     5
 #define PCD_TMO		   800		/* timeout in jiffies */
 #define PCD_DELAY           50          /* spin delay in uS */
-#define PCD_READY_TMO	    20
+#define PCD_READY_TMO	    20		/* in seconds */
+#define PCD_RESET_TMO	    30		/* in tenths of a second */
 
-#define PCD_SPIN		(10000/PCD_DELAY)*PCD_TMO
+#define PCD_SPIN	(1000000*PCD_TMO)/(HZ*PCD_DELAY)
 
 #define IDE_ERR		0x01
 #define IDE_DRQ         0x08
@@ -197,33 +203,33 @@
 int pcd_init(void);
 void cleanup_module( void );
 
-static int 	pcd_open(struct inode *inode, struct file *file);
-static void 	do_pcd_request(void);
-static void 	do_pcd_read(void);
-static int 	pcd_ioctl(struct inode *inode,struct file *file,
-                         unsigned int cmd, unsigned long arg);
-
-static int pcd_release (struct inode *inode, struct file *file);
+static int pcd_open(struct cdrom_device_info *cdi, int purpose);
+static void pcd_release(struct cdrom_device_info *cdi);
+static int pcd_drive_status(struct cdrom_device_info *cdi, int slot_nr);
+static int pcd_media_changed(struct cdrom_device_info *cdi, int slot_nr);
+static int pcd_tray_move(struct cdrom_device_info *cdi, int position);
+static int pcd_lock_door(struct cdrom_device_info *cdi, int lock);
+static int pcd_drive_reset(struct cdrom_device_info *cdi);
+static int pcd_get_mcn (struct cdrom_device_info *cdi, struct cdrom_mcn *mcn);
+static int pcd_audio_ioctl(struct cdrom_device_info *cdi,
+				unsigned int cmd, void *arg);
 
 static int 	pcd_detect(void);
-static void     pcd_lock(int unit);
-static void     pcd_unlock(int unit);
-static void     pcd_eject(int unit);
-static int      pcd_check_media(int unit);
 static void     do_pcd_read_drq(void);
+static void 	do_pcd_request(void);
+static void 	do_pcd_read(void);
 
 static int pcd_blocksizes[PCD_UNITS];
 
-#define PCD_NAMELEN	8
-
 struct pcd_unit {
-	struct pi_adapter pia;	/* interface to paride layer */
+	struct pi_adapter pia;		/* interface to paride layer */
 	struct pi_adapter *pi;
-	int drive;		/* master/slave */
-	int last_sense;		/* result of last request sense */
-	int access;		/* count of active opens */
-	int present;		/* does this unit exist ? */
-	char name[PCD_NAMELEN];	/* pcd0, pcd1, etc */
+	int drive;			/* master/slave */
+	int last_sense;			/* result of last request sense */
+	int changed;			/* media change seen */
+	int present;			/* does this unit exist ? */
+	char *name;			/* pcd0, pcd1, etc */
+	struct cdrom_device_info info;	/* uniform cdrom interface */
 	};
 
 struct pcd_unit pcd[PCD_UNITS];
@@ -251,22 +257,32 @@
 static int pcd_count;			/* number of blocks still to do */
 static char * pcd_buf;			/* buffer for request in progress */
 
+static int pcd_warned = 0;		/* Have we logged a phase warning ? */
+
 /* kernel glue structures */
 
-static struct file_operations pcd_fops = {
-	NULL,			/* lseek - default */
-	block_read,		/* read - general block-dev read */
-	block_write,		/* write - general block-dev write */
-	NULL,			/* readdir - bad */
-	NULL,			/* select */
-	pcd_ioctl,		/* ioctl */
-	NULL,			/* mmap */
-	pcd_open,		/* open */
-	pcd_release,		/* release */
-	block_fsync,		/* fsync */
-	NULL,			/* fasync */
-	NULL,                   /* media change ? */
-	NULL			/* revalidate new media */
+static struct cdrom_device_ops pcd_dops = {
+	pcd_open,
+	pcd_release,
+	pcd_drive_status,
+	pcd_media_changed,
+	pcd_tray_move,
+	pcd_lock_door,
+	0,			/* select speed */
+	0,			/* select disk  */
+	0, 			/* get last session */
+	pcd_get_mcn,
+	pcd_drive_reset,
+	pcd_audio_ioctl,
+	0,			/* dev_ioctl */
+	CDC_CLOSE_TRAY    |
+	CDC_OPEN_TRAY     |
+	CDC_LOCK          |
+	CDC_MCN		  |
+	CDC_MEDIA_CHANGED |
+	CDC_RESET	  |
+	CDC_PLAY_AUDIO,
+	0
 };
 
 static void pcd_init_units( void )
@@ -276,21 +292,31 @@
         pcd_drive_count = 0;
         for (unit=0;unit<PCD_UNITS;unit++) {
                 PCD.pi = & PCD.pia;
-                PCD.access = 0;
                 PCD.present = 0;
 		PCD.last_sense = 0;
-                j = 0;
-                while ((j < PCD_NAMELEN-2) && (PCD.name[j]=name[j])) j++;
-                PCD.name[j++] = '0' + unit;
-                PCD.name[j] = 0;
+		PCD.changed = 1;
                 PCD.drive = DU[D_SLV];
                 if (DU[D_PRT]) pcd_drive_count++;
+ 
+                j = 0;
+                while ((j < (sizeof(PCD.info.name)-2)) && 
+		       (PCD.info.name[j]=name[j])) j++;
+                PCD.info.name[j++] = '0' + unit;
+                PCD.info.name[j] = 0;
+		PCD.name = &PCD.info.name[0];
+
+		PCD.info.ops = &pcd_dops;
+		PCD.info.handle = NULL;
+		PCD.info.dev = MKDEV(major,unit);
+		PCD.info.speed = 0;
+		PCD.info.capacity = 1;
+		PCD.info.mask = 0;
         }
 }
 
 int pcd_init (void)	/* preliminary initialisation */
 
-{       int 	i;
+{       int 	i, unit;
 
 	if (disable) return -1;
 
@@ -298,10 +324,14 @@
 
 	if (pcd_detect()) return -1;
 
-	if (register_blkdev(MAJOR_NR,name,&pcd_fops)) {
+	if (register_blkdev(MAJOR_NR,name,&cdrom_fops)) {
 		printk("pcd: unable to get major number %d\n",MAJOR_NR);
 		return -1;
 	}
+
+	for (unit=0;unit<PCD_UNITS;unit++)
+		if (PCD.present) register_cdrom(&PCD.info);
+
 	blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
 	read_ahead[MAJOR_NR] = 8;	/* 8 sector (4kB) read ahead */
 
@@ -311,100 +341,20 @@
 	return 0;
 }
 
-static int pcd_open (struct inode *inode, struct file *file)
+static int pcd_open(struct cdrom_device_info *cdi, int purpose)
 
-{	int unit = DEVICE_NR(inode->i_rdev);
+{	int unit = DEVICE_NR(cdi->dev);
 
 	if  ((unit >= PCD_UNITS) || (!PCD.present)) return -ENODEV;
 
-	if (file->f_mode & 2) return -EROFS;  /* wants to write ? */
-
 	MOD_INC_USE_COUNT;
 
-	if (pcd_check_media(unit)) {
-		MOD_DEC_USE_COUNT;
-		return -ENXIO;
-	}
-
-	pcd_lock(unit);
-
-	PCD.access++;
 	return 0;
 }
 
-static void do_pcd_request (void)
-
-{       int unit;
-
-	if (pcd_busy) return;
-        while (1) {
-	    if ((!CURRENT) || (CURRENT->rq_status == RQ_INACTIVE)) return;
-	    INIT_REQUEST;
-	    if (CURRENT->cmd == READ) {
-		unit = MINOR(CURRENT->rq_dev);
-		if (unit != pcd_unit) {
-			pcd_bufblk = -1;
-			pcd_unit = unit;
-		}
-	        pcd_sector = CURRENT->sector;
-	        pcd_count = CURRENT->nr_sectors;
-	        pcd_buf = CURRENT->buffer;
-		pcd_busy = 1;
-	        ps_set_intr(do_pcd_read,0,0,nice); 
-		return;
-	    } 
-	    else end_request(0);
-	}
-}
-
-static int pcd_ioctl(struct inode *inode,struct file *file,
-		    unsigned int cmd, unsigned long arg)
-
-/* we currently support only the EJECT ioctl. */
-
-{	int unit = DEVICE_NR(inode->i_rdev);
-	if  ((unit >= PCD_UNITS) || (!PCD.present)) return -ENODEV;
-
-	switch (cmd) {
-            case CDROMEJECT: if (PCD.access == 1) {
-				pcd_eject(unit);
-				return 0;
-			     }
-	    default:
-	        return -EINVAL;
-	}
-}
-
-static int pcd_release (struct inode *inode, struct file *file)
-
-{	kdev_t	devp;
-	int 	unit;
-
-        struct super_block *sb;
-
-	devp = inode->i_rdev;
-	unit = DEVICE_NR(devp);
-
-	if  ((unit >= PCD_UNITS) || (PCD.access <= 0)) 
-			return -EINVAL;
-       
-	PCD.access--;
-
-	if (!PCD.access) { 
-		fsync_dev(devp);
-
-                sb = get_super(devp);
-                if (sb) invalidate_inodes(sb);
-
-	    	invalidate_buffers(devp);
-	    	pcd_unlock(unit);
-
-	}
-
-	MOD_DEC_USE_COUNT;
-
-        return 0;
+static void pcd_release(struct cdrom_device_info *cdi)
 
+{	MOD_DEC_USE_COUNT;
 }
 
 #ifdef MODULE
@@ -423,11 +373,14 @@
 void	cleanup_module(void)
 
 {	int unit;
-
-	unregister_blkdev(MAJOR_NR,name);
 	
         for (unit=0;unit<PCD_UNITS;unit++) 
-           if (PCD.present) pi_release(PI);
+           if (PCD.present) {
+		pi_release(PI);
+		unregister_cdrom(&PCD.info);
+	   }
+
+	unregister_blkdev(MAJOR_NR,name);
 }
 
 #endif
@@ -489,39 +442,68 @@
 
 static int pcd_completion( int unit, char * buf,  char * fun )
 
-{	int r, s, n;
+{	int r, d, p, n, k, j;
 
-	r = pcd_wait(unit,IDE_BUSY,IDE_DRQ|IDE_READY|IDE_ERR,fun,"completion");
+	r = -1; k = 0; j = 0;
 
-	if ((RR(0,2)&2) && (RR(0,7)&IDE_DRQ)) { 
-	        n = (((RR(0,4)+256*RR(0,5))+3)&0xfffc);
-	        pi_read_block(PI,buf,n);
+	if (!pcd_wait(unit,IDE_BUSY,IDE_DRQ|IDE_READY|IDE_ERR,
+						fun,"completion")) {
+	    r = 0;
+	    while (RR(0,7)&IDE_DRQ) {
+	        d = (RR(0,4)+256*RR(0,5));
+	        n = ((d+3)&0xfffc);
+	        p = RR(0,2)&3;
+
+	        if ((p == 2) && (n > 0) && (j == 0)) {
+		    pi_read_block(PI,buf,n);
+	            if (verbose > 1) 
+			printk("%s: %s: Read %d bytes\n",PCD.name,fun,n);
+		    r = 0; j++;
+	        } else {
+		    if (verbose > 1) 
+		        printk("%s: %s: Unexpected phase %d, d=%d, k=%d\n",
+					PCD.name,fun,p,d,k);
+		    if ((verbose < 2) && !pcd_warned) {
+	               	pcd_warned = 1;
+			printk("%s: WARNING: ATAPI phase errors\n",PCD.name);
+			}
+		    mdelay(1);
+	        } 
+		if (k++ > PCD_TMO) {
+			printk("%s: Stuck DRQ\n",PCD.name);
+			break;
+		}
+	        if (pcd_wait(unit,IDE_BUSY,IDE_DRQ|IDE_READY|IDE_ERR,
+				fun,"completion")) { 
+			r = -1;
+			break;
+		}
+	    }
 	}
-
-	s = pcd_wait(unit,IDE_BUSY,IDE_READY|IDE_ERR,fun,"data done");
-
+	
 	pi_disconnect(PI); 
 
-	return (r?r:s);
+	return r;
 }
 
-static void pcd_req_sense( int unit, int quiet )
+static void pcd_req_sense( int unit, char *fun )
 
 {	char	rs_cmd[12] = { 0x03,0,0,0,16,0,0,0,0,0,0,0 };
 	char	buf[16];
-	int 	r;
+	int 	r, c;
 
 	r = pcd_command(unit,rs_cmd,16,"Request sense");
 	mdelay(1);
 	if (!r) pcd_completion(unit,buf,"Request sense");
 
-	PCD.last_sense = -1;
+	PCD.last_sense = -1;  c = 2;
 	if (!r) {
-            if (!quiet) printk("%s: Sense key: %x, ASC: %x, ASQ: %x\n",
-	                       PCD.name,buf[2]&0xf,buf[12],buf[13]);
-	    PCD.last_sense = (buf[2]&0xf) | ((buf[12]&0xff)<<8)
-                                          | ((buf[13]&0xff)<<16) ;
+            if (fun) printk("%s: %s: Sense key: %x, ASC: %x, ASQ: %x\n",
+	                       PCD.name,fun,buf[2]&0xf,buf[12],buf[13]);
+	    c = buf[2]&0xf;
+	    PCD.last_sense = c | ((buf[12]&0xff)<<8) | ((buf[13]&0xff)<<16);
         } 
+	if ((c == 2) || (c == 6)) PCD.changed = 1;
 }
 
 static int pcd_atapi( int unit, char * cmd, int dlen, char * buf, char * fun )
@@ -531,45 +513,42 @@
 	r = pcd_command(unit,cmd,dlen,fun);
 	mdelay(1);
 	if (!r) r = pcd_completion(unit,buf,fun);
-	if (r) pcd_req_sense(unit,!fun);
+	if (r) pcd_req_sense(unit,fun);
 	
 	return r;
 }
 
-#define DBMSG(msg)	NULL
+#define DBMSG(msg)	((verbose>1)?(msg):NULL)
 
-static void pcd_lock(int unit)
+static int pcd_media_changed(struct cdrom_device_info *cdi, int slot_nr)
 
-{	char	lo_cmd[12] = { 0x1e,0,0,0,1,0,0,0,0,0,0,0 };
-	char	cl_cmd[12] = { 0x1b,0,0,0,3,0,0,0,0,0,0,0 };
+{	int 	r;
+	int	unit = DEVICE_NR(cdi->dev);
 
-	pcd_atapi(unit,cl_cmd,0,pcd_scratch,DBMSG("cd1")); 
-	pcd_atapi(unit,cl_cmd,0,pcd_scratch,DBMSG("cd2"));
-	pcd_atapi(unit,cl_cmd,0,pcd_scratch,DBMSG("cd3"));
-	pcd_atapi(unit,cl_cmd,0,pcd_scratch,DBMSG("cd4"));
-	pcd_atapi(unit,cl_cmd,0,pcd_scratch,"close door");
+	r = PCD.changed;
+	PCD.changed = 0;
 
-        pcd_atapi(unit,lo_cmd,0,pcd_scratch,DBMSG("ld"));
-        pcd_atapi(unit,lo_cmd,0,pcd_scratch,"lock door");
+	return r;    
 }
 
-static void pcd_unlock( int unit )
+static int pcd_lock_door(struct cdrom_device_info *cdi, int lock)
 
-{	char	un_cmd[12] = { 0x1e,0,0,0,0,0,0,0,0,0,0,0 };
+{	char	un_cmd[12] = { 0x1e,0,0,0,lock,0,0,0,0,0,0,0 };
+        int     unit = DEVICE_NR(cdi->dev);
 
-	pcd_atapi(unit,un_cmd,0,pcd_scratch,"unlock door");
+	return pcd_atapi(unit,un_cmd,0,pcd_scratch,
+				lock?"lock door":"unlock door");
 }
 
-static void pcd_eject( int unit)
+static int pcd_tray_move(struct cdrom_device_info *cdi, int position)
 
-{	char	ej_cmd[12] = { 0x1b,0,0,0,2,0,0,0,0,0,0,0 };
+{	char	ej_cmd[12] = { 0x1b,0,0,0,3-position,0,0,0,0,0,0,0 };
+	int	unit = DEVICE_NR(cdi->dev);
 
-	pcd_unlock(unit);
-	pcd_atapi(unit,ej_cmd,0,pcd_scratch,"eject");
+	return pcd_atapi(unit,ej_cmd,0,pcd_scratch,
+				position?"eject":"close tray");
 }
 
-#define PCD_RESET_TMO	30		/* in tenths of a second */
-
 static void pcd_sleep( int cs )
 
 {       current->state = TASK_INTERRUPTIBLE;
@@ -579,11 +558,6 @@
 
 static int pcd_reset( int unit )
 
-/* the ATAPI standard actually specifies the contents of all 7 registers
-   after a reset, but the specification is ambiguous concerning the last
-   two bytes, and different drives interpret the standard differently.
-*/
-
 {	int	i, k, flg;
 	int	expect[5] = {1,1,1,0x14,0xeb};
 
@@ -591,11 +565,11 @@
 	WR(0,6,0xa0 + 0x10*PCD.drive);
 	WR(0,7,8);
 
-	pcd_sleep(2);  		/* delay a bit*/
+	pcd_sleep(2);  		/* delay a bit */
 
 	k = 0;
 	while ((k++ < PCD_RESET_TMO) && (RR(1,6)&IDE_BUSY))
-		pcd_sleep(10);
+		pcd_sleep(HZ/10);
 
 	flg = 1;
 	for(i=0;i<5;i++) flg &= (RR(0,i+1) == expect[i]);
@@ -611,6 +585,11 @@
 	return flg-1;	
 }
 
+static int pcd_drive_reset(struct cdrom_device_info *cdi)
+
+{	return pcd_reset(DEVICE_NR(cdi->dev));
+}
+
 static int pcd_ready_wait( int unit, int tmo )
 
 {       char    tr_cmd[12] = {0,0,0,0,0,0,0,0,0,0,0,0};
@@ -629,12 +608,16 @@
         return 0x000020;        /* timeout */
 }
 
-static int pcd_check_media( int unit )
+static int pcd_drive_status(struct cdrom_device_info *cdi, int slot_nr)
 
 {	char    rc_cmd[12] = { 0x25,0,0,0,0,0,0,0,0,0,0,0};
+	int	unit = DEVICE_NR(cdi->dev);
 
-	pcd_ready_wait(unit,PCD_READY_TMO);
-	return (pcd_atapi(unit,rc_cmd,8,pcd_scratch,DBMSG("check media")));
+	if (pcd_ready_wait(unit,PCD_READY_TMO)) 
+		return CDS_DRIVE_NOT_READY;
+	if (pcd_atapi(unit,rc_cmd,8,pcd_scratch,DBMSG("check media")))
+		return CDS_NO_DISC;
+	return CDS_DISC_OK;
 }
 
 static int pcd_identify( int unit, char * id )
@@ -648,7 +631,7 @@
 
 	if (s) return -1;
 	if ((pcd_buffer[0] & 0x1f) != 5) {
-	  if (verbose) printk("%s: %s is not a CDROM\n",
+	  if (verbose) printk("%s: %s is not a CD-ROM\n",
 			PCD.name,PCD.drive?"Slave":"Master");
 	  return -1;
 	}
@@ -709,12 +692,37 @@
 
 	if (k) return 0;
 	
-	printk("%s: No CDROM drive found\n",name);
+	printk("%s: No CD-ROM drive found\n",name);
 	return -1;
 }
 
 /* I/O request processing */
 
+static void do_pcd_request (void)
+
+{       int unit;
+
+	if (pcd_busy) return;
+        while (1) {
+	    if ((!CURRENT) || (CURRENT->rq_status == RQ_INACTIVE)) return;
+	    INIT_REQUEST;
+	    if (CURRENT->cmd == READ) {
+		unit = MINOR(CURRENT->rq_dev);
+		if (unit != pcd_unit) {
+			pcd_bufblk = -1;
+			pcd_unit = unit;
+		}
+	        pcd_sector = CURRENT->sector;
+	        pcd_count = CURRENT->nr_sectors;
+	        pcd_buf = CURRENT->buffer;
+		pcd_busy = 1;
+	        ps_set_intr(do_pcd_read,0,0,nice); 
+		return;
+	    } 
+	    else end_request(0);
+	}
+}
+
 static int pcd_ready( void )
 
 {	int	unit = pcd_unit;
@@ -793,7 +801,7 @@
 
 	if (pcd_completion(unit,pcd_buffer,"read block")) {
                 if (pcd_retries < PCD_RETRIES) {
-                        mdelay(1);
+                        mdelay(1); 
                         pcd_retries++;
 			pi_do_claimed(PI,pcd_start);
                         return;
@@ -812,6 +820,227 @@
 	do_pcd_request();
 	spin_unlock_irqrestore(&io_request_lock,saved_flags); 
 }
+
+/* the audio_ioctl stuff is adapted from sr_ioctl.c */
+
+static int pcd_audio_ioctl(struct cdrom_device_info *cdi,
+                                unsigned int cmd, void *arg)
+
+{	int	unit = DEVICE_NR(cdi->dev);
+ 
+    	switch (cmd) { 
+    
+	case CDROMPAUSE: 
+
+	{       char cmd[12]={SCMD_PAUSE_RESUME,0,0,0,0,0,0,0,0,0,0,0};
+
+		return (pcd_atapi(unit,cmd,0,NULL,"pause")) * EIO;
+	}
+
+	case CDROMRESUME:
+	
+	{       char cmd[12]={SCMD_PAUSE_RESUME,0,0,0,0,0,0,0,1,0,0,0};
+
+		return (pcd_atapi(unit,cmd,0,NULL,"resume")) * EIO;
+	}
+	
+	case CDROMPLAYMSF:
+
+	{	char cmd[12]={SCMD_PLAYAUDIO_MSF,0,0,0,0,0,0,0,0,0,0,0};
+		struct cdrom_msf* msf = (struct cdrom_msf*)arg;
+
+		cmd[3] = msf->cdmsf_min0;
+		cmd[4] = msf->cdmsf_sec0;
+		cmd[5] = msf->cdmsf_frame0;
+		cmd[6] = msf->cdmsf_min1;
+		cmd[7] = msf->cdmsf_sec1;
+		cmd[8] = msf->cdmsf_frame1;
+	
+		return (pcd_atapi(unit,cmd,0,NULL,"play msf")) * EIO;
+    	}
+
+    	case CDROMPLAYBLK:
+
+    	{	char cmd[12]={SCMD_PLAYAUDIO10,0,0,0,0,0,0,0,0,0,0,0};
+		struct cdrom_blk* blk = (struct cdrom_blk*)arg;
+
+		cmd[2] = blk->from >> 24;
+		cmd[3] = blk->from >> 16;
+		cmd[4] = blk->from >> 8;
+		cmd[5] = blk->from;
+		cmd[7] = blk->len >> 8;
+		cmd[8] = blk->len;
+	
+		return (pcd_atapi(unit,cmd,0,NULL,"play block")) * EIO;
+    	}
+		
+    	case CDROMPLAYTRKIND:
+
+    	{	char cmd[12]={SCMD_PLAYAUDIO_TI,0,0,0,0,0,0,0,0,0,0,0};
+		struct cdrom_ti* ti = (struct cdrom_ti*)arg;
+
+		cmd[4] = ti->cdti_trk0;
+		cmd[5] = ti->cdti_ind0;
+		cmd[7] = ti->cdti_trk1;
+		cmd[8] = ti->cdti_ind1;
+
+		return (pcd_atapi(unit,cmd,0,NULL,"play track")) * EIO;
+    	}
+	
+    	case CDROMREADTOCHDR:
+    
+	{	char cmd[12]={SCMD_READ_TOC,0,0,0,0,0,0,0,12,0,0,0};
+		struct cdrom_tochdr* tochdr = (struct cdrom_tochdr*)arg;
+		char buffer[32];
+		int r;
+	
+		r = pcd_atapi(unit,cmd,12,buffer,"read toc header");
+
+		tochdr->cdth_trk0 = buffer[2];
+		tochdr->cdth_trk1 = buffer[3];
+	
+		return r * EIO;
+    	}
+	
+    	case CDROMREADTOCENTRY:
+
+    	{	char cmd[12]={SCMD_READ_TOC,0,0,0,0,0,0,0,12,0,0,0};
+
+		struct cdrom_tocentry* tocentry = (struct cdrom_tocentry*)arg;
+		unsigned char buffer[32];
+		int	r;
+	
+		cmd[1] = (tocentry->cdte_format == CDROM_MSF ? 0x02 : 0);
+		cmd[6] = tocentry->cdte_track;
+	
+		r = pcd_atapi(unit,cmd,12,buffer,"read toc entry");
+
+        	tocentry->cdte_ctrl = buffer[5] & 0xf;	
+        	tocentry->cdte_adr = buffer[5] >> 4;
+        	tocentry->cdte_datamode = (tocentry->cdte_ctrl & 0x04)?1:0;
+		if (tocentry->cdte_format == CDROM_MSF) {
+		    tocentry->cdte_addr.msf.minute = buffer[9];
+	    	    tocentry->cdte_addr.msf.second = buffer[10];
+	            tocentry->cdte_addr.msf.frame = buffer[11];
+	        } else
+	            tocentry->cdte_addr.lba = 
+				(((((buffer[8] << 8) + buffer[9]) << 8)
+                                       + buffer[10]) << 8) + buffer[11];
+	
+                return r * EIO;
+        }
+
+    	case CDROMSTOP:
+
+	{	char cmd[12]={0x1b,1,0,0,0,0,0,0,0,0,0,0};
+
+                return (pcd_atapi(unit,cmd,0,NULL,"stop")) * EIO;
+        }                                                         
+	
+    	case CDROMSTART:
+
+        {       char cmd[12]={0x1b,1,0,0,1,0,0,0,0,0,0,0};
+
+                return (pcd_atapi(unit,cmd,0,NULL,"start")) * EIO;
+        } 
+	
+    	case CDROMVOLCTRL:
+
+	{	char cmd[12]={0x5a,0,0,0,0,0,0,0,0,0,0,0};
+		char buffer[32];
+		char mask[32];
+		struct cdrom_volctrl* volctrl = (struct cdrom_volctrl*)arg;
+
+		cmd[2] = 0xe;
+		cmd[4] = 28;
+
+                if (pcd_atapi(unit,cmd,28,buffer,"mode sense vol")) 
+			return -EIO;
+
+		cmd[2] = 0x4e;
+	
+		if (pcd_atapi(unit,cmd,28,buffer,"mode sense vol mask"))
+			return -EIO;
+	
+		buffer[0] = 0;
+	
+		buffer[21] = volctrl->channel0 & mask[21];
+		buffer[23] = volctrl->channel1 & mask[23];
+		buffer[25] = volctrl->channel2 & mask[25];
+		buffer[27] = volctrl->channel3 & mask[27];
+	
+		cmd[0] = 0x55;
+		cmd[1] = 0x10;
+
+		return pcd_atapi(unit,cmd,28,buffer,"mode select vol") * EIO;
+    	}
+
+    	case CDROMVOLREAD:
+
+        {       char cmd[12]={0x5a,0,0,0,0,0,0,0,0,0,0,0};
+                char buffer[32];
+                struct cdrom_volctrl* volctrl = (struct cdrom_volctrl*)arg;
+                int     r;
+
+                cmd[2] = 0xe;
+                cmd[4] = 28;
+
+                r = pcd_atapi(unit,cmd,28,buffer,"mode sense vol read");
+
+		volctrl->channel0 = buffer[21];
+		volctrl->channel1 = buffer[23];
+		volctrl->channel2 = buffer[25];
+		volctrl->channel3 = buffer[27];
+
+                return r * EIO;
+        }
+  
+	
+    	case CDROMSUBCHNL:
+
+	{	char cmd[12]={SCMD_READ_SUBCHANNEL,2,0x40,1,0,0,0,0,16,0,0,0};
+		struct cdrom_subchnl* subchnl = (struct cdrom_subchnl*)arg;
+		char buffer[32];
+	
+                if (pcd_atapi(unit,cmd,16,buffer,"read subchannel"))
+                        return -EIO;
+   	
+		subchnl->cdsc_audiostatus = buffer[1];
+		subchnl->cdsc_format = CDROM_MSF;
+		subchnl->cdsc_ctrl = buffer[5] & 0xf;
+		subchnl->cdsc_trk = buffer[6];
+		subchnl->cdsc_ind = buffer[7];
+	
+		subchnl->cdsc_reladdr.msf.minute = buffer[13];
+		subchnl->cdsc_reladdr.msf.second = buffer[14];
+		subchnl->cdsc_reladdr.msf.frame = buffer[15];
+		subchnl->cdsc_absaddr.msf.minute = buffer[9];
+		subchnl->cdsc_absaddr.msf.second = buffer[10];
+		subchnl->cdsc_absaddr.msf.frame = buffer[11];
+
+		return 0;	
+    	}
+
+    	default:
+
+        	return -ENOSYS;
+    	}
+}
+	
+static int pcd_get_mcn (struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
+
+{	char 	cmd[12]={SCMD_READ_SUBCHANNEL,0,0x40,2,0,0,0,0,24,0,0,0};
+        char 	buffer[32];
+	int	k;
+	int	unit = DEVICE_NR(cdi->dev);
+
+        if (pcd_atapi(unit,cmd,24,buffer,"get mcn")) return -EIO;
+
+	for (k=0;k<13;k++) mcn->medium_catalog_number[k] = buffer[k+9];
+	mcn->medium_catalog_number[13] = 0;
 	
+	return 0;
+}
+
 /* end of pcd.c */
 
diff -u --recursive --new-file v2.1.117/linux/drivers/block/paride/pd.c linux/drivers/block/paride/pd.c
--- v2.1.117/linux/drivers/block/paride/pd.c	Wed Jun 24 22:54:04 1998
+++ linux/drivers/block/paride/pd.c	Mon Aug 24 13:14:10 1998
@@ -78,9 +78,10 @@
 			(default 64)
 
 	    verbose	This parameter controls the amount of logging
-			that is done while the driver probes for
-			devices.  Set it to 0 for a quiet load, or to 1
-			see all the progress messages.  (default 0)
+			that the driver will do.  Set it to 0 for 
+			normal operation, 1 to see autoprobe progress
+			messages, or 2 to see additional debugging
+			output.  (default 0)
 
             nice        This parameter controls the driver's use of
                         idle CPU time, at the expense of some speed.
@@ -108,10 +109,11 @@
 	1.02    GRG 1998.05.06  SMP spinlock changes, 
 				Added slave support
 	1.03    GRG 1998.06.16  Eliminate an Ugh.
+	1.04	GRG 1998.08.15  Extra debugging, use HZ in loop timing
 
 */
 
-#define PD_VERSION      "1.03"
+#define PD_VERSION      "1.04"
 #define PD_MAJOR	45
 #define PD_NAME		"pd"
 #define PD_UNITS	4
@@ -223,7 +225,7 @@
 #define PD_TMO          800             /* interrupt timeout in jiffies */
 #define PD_SPIN_DEL     50              /* spin delay in micro-seconds  */
 
-#define PD_SPIN         (10000/PD_SPIN_DEL)*PD_TMO  
+#define PD_SPIN         (1000000*PD_TMO)/(HZ*PD_SPIN_DEL)  
 
 #define STAT_ERR        0x00001
 #define STAT_INDEX      0x00002
@@ -359,6 +361,7 @@
         pd_ioctl,               /* ioctl */
         NULL,                   /* mmap */
         pd_open,                /* open */
+	NULL,			/* flush */
         pd_release,             /* release */
         block_fsync,            /* fsync */
         NULL,                   /* fasync */
@@ -666,7 +669,7 @@
 	udelay(250);
 }
 
-#define DBMSG(msg)	NULL
+#define DBMSG(msg)	((verbose>1)?(msg):NULL)
 
 static int pd_wait_for( int unit, int w, char * msg )    /* polled wait */
 
diff -u --recursive --new-file v2.1.117/linux/drivers/block/paride/pf.c linux/drivers/block/paride/pf.c
--- v2.1.117/linux/drivers/block/paride/pf.c	Wed Jun 24 22:54:04 1998
+++ linux/drivers/block/paride/pf.c	Mon Aug 24 13:14:10 1998
@@ -76,10 +76,11 @@
                         (default 64)
 
             verbose     This parameter controls the amount of logging
-                        that is done while the driver probes for
-                        devices.  Set it to 0 for a quiet load, or 1 to
-                        see all the progress messages.  (default 0)
-
+                        that the driver will do.  Set it to 0 for
+                        normal operation, 1 to see autoprobe progress
+                        messages, or 2 to see additional debugging
+                        output.  (default 0)
+ 
 	    nice        This parameter controls the driver's use of
 			idle CPU time, at the expense of some speed.
 
@@ -107,10 +108,11 @@
 				Small change in pf_completion to round
 				up transfer size.
 	1.02    GRG 1998.06.16  Eliminated an Ugh
+	1.03    GRG 1998.08.16  Use HZ in loop timings, extra debugging
 
 */
 
-#define PF_VERSION      "1.02"
+#define PF_VERSION      "1.03"
 #define PF_MAJOR	47
 #define PF_NAME		"pf"
 #define PF_UNITS	4
@@ -217,7 +219,7 @@
 #define PF_TMO          800             /* interrupt timeout in jiffies */
 #define PF_SPIN_DEL     50              /* spin delay in micro-seconds  */
 
-#define PF_SPIN         (10000/PF_SPIN_DEL)*PF_TMO  
+#define PF_SPIN         (1000000*PF_TMO)/(HZ*PF_SPIN_DEL)
 
 #define STAT_ERR        0x00001
 #define STAT_INDEX      0x00002
@@ -316,6 +318,7 @@
         pf_ioctl,               /* ioctl */
         NULL,                   /* mmap */
         pf_open,                /* open */
+	NULL,			/* flush */
         pf_release,             /* release */
         block_fsync,            /* fsync */
         NULL,                   /* fasync */
@@ -627,7 +630,7 @@
         return r;
 }
 
-#define DBMSG(msg)      NULL
+#define DBMSG(msg)      ((verbose>1)?(msg):NULL)
 
 static void pf_lock(int unit, int func)
 
diff -u --recursive --new-file v2.1.117/linux/drivers/block/paride/pg.c linux/drivers/block/paride/pg.c
--- v2.1.117/linux/drivers/block/paride/pg.c	Wed Jun 24 22:54:04 1998
+++ linux/drivers/block/paride/pg.c	Mon Aug 24 13:46:50 1998
@@ -1,35 +1,35 @@
 /* 
-        pg.c    (c) 1998  Grant R. Guenther <grant@torque.net>
-                          Under the terms of the GNU public license.
+	pg.c    (c) 1998  Grant R. Guenther <grant@torque.net>
+			  Under the terms of the GNU public license.
 
 	The pg driver provides a simple character device interface for
-        sending ATAPI commands to a device.  With the exception of the
+	sending ATAPI commands to a device.  With the exception of the
 	ATAPI reset operation, all operations are performed by a pair
-        of read and write operations to the appropriate /dev/pgN device.
+	of read and write operations to the appropriate /dev/pgN device.
 	A write operation delivers a command and any outbound data in
-        a single buffer.  Normally, the write will succeed unless the
-        device is offline or malfunctioning, or there is already another
+	a single buffer.  Normally, the write will succeed unless the
+	device is offline or malfunctioning, or there is already another
 	command pending.  If the write succeeds, it should be followed
-        immediately by a read operation, to obtain any returned data and
-        status information.  A read will fail if there is no operation
-        in progress.
+	immediately by a read operation, to obtain any returned data and
+	status information.  A read will fail if there is no operation
+	in progress.
 
 	As a special case, the device can be reset with a write operation,
-        and in this case, no following read is expected, or permitted.
+	and in this case, no following read is expected, or permitted.
 
 	There are no ioctl() operations.  Any single operation
 	may transfer at most PG_MAX_DATA bytes.  Note that the driver must
-        copy the data through an internal buffer.  In keeping with all
+	copy the data through an internal buffer.  In keeping with all
 	current ATAPI devices, command packets are assumed to be exactly
 	12 bytes in length.
 
 	To permit future changes to this interface, the headers in the
 	read and write buffers contain a single character "magic" flag.
-        Currently this flag must be the character "P".
+	Currently this flag must be the character "P".
 
-        By default, the driver will autoprobe for a single parallel
-        port ATAPI device, but if their individual parameters are
-        specified, the driver can handle up to 4 devices.
+	By default, the driver will autoprobe for a single parallel
+	port ATAPI device, but if their individual parameters are
+	specified, the driver can handle up to 4 devices.
 
 	To use this device, you must have the following device 
 	special files defined:
@@ -41,48 +41,48 @@
 
 	(You'll need to change the 97 to something else if you use
 	the 'major' parameter to install the driver on a different
-        major number.)
+	major number.)
 
-        The behaviour of the pg driver can be altered by setting
-        some parameters from the insmod command line.  The following
-        parameters are adjustable:
-
-            drive0      These four arguments can be arrays of       
-            drive1      1-6 integers as follows:
-            drive2
-            drive3      <prt>,<pro>,<uni>,<mod>,<slv>,<dly>
-
-                        Where,
-
-                <prt>   is the base of the parallel port address for
-                        the corresponding drive.  (required)
-
-                <pro>   is the protocol number for the adapter that
-                        supports this drive.  These numbers are
-                        logged by 'paride' when the protocol modules
-                        are initialised.  (0 if not given)
-
-                <uni>   for those adapters that support chained
-                        devices, this is the unit selector for the
-                        chain of devices on the given port.  It should
-                        be zero for devices that don't support chaining.
-                        (0 if not given)
-
-                <mod>   this can be -1 to choose the best mode, or one
-                        of the mode numbers supported by the adapter.
-                        (-1 if not given)
-
-                <slv>   ATAPI devices can be jumpered to master or slave.
-                        Set this to 0 to choose the master drive, 1 to
-                        choose the slave, -1 (the default) to choose the
-                        first drive found.
-
-                <dly>   some parallel ports require the driver to 
-                        go more slowly.  -1 sets a default value that
-                        should work with the chosen protocol.  Otherwise,
-                        set this to a small integer, the larger it is
-                        the slower the port i/o.  In some cases, setting
-                        this to zero will speed up the device. (default -1)
+	The behaviour of the pg driver can be altered by setting
+	some parameters from the insmod command line.  The following
+	parameters are adjustable:
+
+	    drive0      These four arguments can be arrays of       
+	    drive1      1-6 integers as follows:
+	    drive2
+	    drive3      <prt>,<pro>,<uni>,<mod>,<slv>,<dly>
+
+			Where,
+
+		<prt>   is the base of the parallel port address for
+			the corresponding drive.  (required)
+
+		<pro>   is the protocol number for the adapter that
+			supports this drive.  These numbers are
+			logged by 'paride' when the protocol modules
+			are initialised.  (0 if not given)
+
+		<uni>   for those adapters that support chained
+			devices, this is the unit selector for the
+			chain of devices on the given port.  It should
+			be zero for devices that don't support chaining.
+			(0 if not given)
+
+		<mod>   this can be -1 to choose the best mode, or one
+			of the mode numbers supported by the adapter.
+			(-1 if not given)
+
+		<slv>   ATAPI devices can be jumpered to master or slave.
+			Set this to 0 to choose the master drive, 1 to
+			choose the slave, -1 (the default) to choose the
+			first drive found.
+
+		<dly>   some parallel ports require the driver to 
+			go more slowly.  -1 sets a default value that
+			should work with the chosen protocol.  Otherwise,
+			set this to a small integer, the larger it is
+			the slower the port i/o.  In some cases, setting
+			this to zero will speed up the device. (default -1)
 
 	    major	You may use this parameter to overide the
 			default major number (97) that this driver
@@ -94,23 +94,23 @@
 			device (in /proc output, for instance).
 			(default "pg").
 
-            verbose     This parameter controls the amount of logging
-                        that is done by the driver.  Set it to 0 for 
+	    verbose     This parameter controls the amount of logging
+			that is done by the driver.  Set it to 0 for 
 			quiet operation, to 1 to enable progress
 			messages while the driver probes for devices,
 			or to 2 for full debug logging.  (default 0)
 
-        If this driver is built into the kernel, you can use 
-        the following command line parameters, with the same values
-        as the corresponding module parameters listed above:
-
-            pg.drive0
-            pg.drive1
-            pg.drive2
-            pg.drive3
+	If this driver is built into the kernel, you can use 
+	the following command line parameters, with the same values
+	as the corresponding module parameters listed above:
+
+	    pg.drive0
+	    pg.drive1
+	    pg.drive2
+	    pg.drive3
 
-        In addition, you can use the parameter pg.disable to disable
-        the driver entirely.
+	In addition, you can use the parameter pg.disable to disable
+	the driver entirely.
 
 */
 
@@ -175,9 +175,9 @@
 #include "setup.h"
 
 static STT pg_stt[5] = {{"drive0",6,drive0},
-                        {"drive1",6,drive1},
-                        {"drive2",6,drive2},
-                        {"drive3",6,drive3},
+			{"drive1",6,drive1},
+			{"drive2",6,drive2},
+			{"drive3",6,drive3},
 			{"disable",1,&disable}};
 
 void pg_setup( char *str, int *ints)
@@ -221,9 +221,9 @@
 static int pg_open(struct inode *inode, struct file *file);
 static int pg_release (struct inode *inode, struct file *file);
 static ssize_t pg_read(struct file * filp, char * buf, 
-                       size_t count, loff_t *ppos);
+		       size_t count, loff_t *ppos);
 static ssize_t pg_write(struct file * filp, const char * buf, 
-                        size_t count, loff_t *ppos);
+			size_t count, loff_t *ppos);
 static int pg_detect(void);
 
 static int pg_identify (int unit, int log);
@@ -257,39 +257,40 @@
 /* kernel glue structures */
 
 static struct file_operations pg_fops = {
-        NULL,                   /* lseek - default */
-        pg_read,                /* read */
-        pg_write,               /* write */
-        NULL,                   /* readdir - bad */
-        NULL,                   /* select */
-        NULL,                   /* ioctl */
-        NULL,                   /* mmap */
-        pg_open,                /* open */
-        pg_release,             /* release */
-        NULL,                   /* fsync */
-        NULL,                   /* fasync */
-        NULL,                   /* media change ? */
-        NULL                    /* revalidate new media */
+	NULL,                   /* lseek - default */
+	pg_read,                /* read */
+	pg_write,               /* write */
+	NULL,                   /* readdir - bad */
+	NULL,                   /* select */
+	NULL,                   /* ioctl */
+	NULL,                   /* mmap */
+	pg_open,                /* open */
+	NULL,			/* flush */
+	pg_release,             /* release */
+	NULL,                   /* fsync */
+	NULL,                   /* fasync */
+	NULL,                   /* media change ? */
+	NULL                    /* revalidate new media */
 };
 
 void pg_init_units( void )
 
 {       int     unit, j;
 
-        pg_drive_count = 0;
-        for (unit=0;unit<PG_UNITS;unit++) {
-                PG.pi = & PG.pia;
-                PG.access = 0;
-                PG.busy = 0;
-                PG.present = 0;
+	pg_drive_count = 0;
+	for (unit=0;unit<PG_UNITS;unit++) {
+		PG.pi = & PG.pia;
+		PG.access = 0;
+		PG.busy = 0;
+		PG.present = 0;
 		PG.bufptr = NULL;
 		PG.drive = DU[D_SLV];
-                j = 0;
-                while ((j < PG_NAMELEN-2) && (PG.name[j]=name[j])) j++;
-                PG.name[j++] = '0' + unit;
-                PG.name[j] = 0;
-                if (DU[D_PRT]) pg_drive_count++;
-        }
+		j = 0;
+		while ((j < PG_NAMELEN-2) && (PG.name[j]=name[j])) j++;
+		PG.name[j++] = '0' + unit;
+		PG.name[j] = 0;
+		if (DU[D_PRT]) pg_drive_count++;
+	}
 } 
 
 int pg_init (void)      /* preliminary initialisation */
@@ -302,15 +303,15 @@
 
 	if (pg_detect()) return -1;
 
-        if (register_chrdev(major,name,&pg_fops)) {
-                printk("pg_init: unable to get major number %d\n",
-                        major);
-	        for (unit=0;unit<PG_UNITS;unit++)
-        	  if (PG.present) pi_release(PI);
-                return -1;
-        }
+	if (register_chrdev(major,name,&pg_fops)) {
+		printk("pg_init: unable to get major number %d\n",
+			major);
+		for (unit=0;unit<PG_UNITS;unit++)
+		  if (PG.present) pi_release(PI);
+		return -1;
+	}
 
-        return 0;
+	return 0;
 }
 
 #ifdef MODULE
@@ -323,16 +324,16 @@
 
 {       int     err;
 
-        err = pg_init();
+	err = pg_init();
 
-        return err;
+	return err;
 }
 
 void    cleanup_module(void)
 
 {       int unit;
 
-        unregister_chrdev(major,name);
+	unregister_chrdev(major,name);
 
 	for (unit=0;unit<PG_UNITS;unit++)
 	  if (PG.present) pi_release(PI);
@@ -348,8 +349,8 @@
 static void pg_sleep( int cs )
 
 {       current->state = TASK_INTERRUPTIBLE;
-        current->timeout = jiffies + cs;
-        schedule();
+	current->timeout = jiffies + cs;
+	schedule();
 }
 
 static int pg_wait( int unit, int go, int stop, int tmo, char * msg )
@@ -358,26 +359,26 @@
 
 	PG.status = 0;
 
-        j = 0;
-        while ((((r=RR(1,6))&go)||(stop&&(!(r&stop))))&&(jiffies<tmo)) {
-                if (j++ < PG_SPIN) udelay(PG_SPIN_DEL);
+	j = 0;
+	while ((((r=RR(1,6))&go)||(stop&&(!(r&stop))))&&(jiffies<tmo)) {
+		if (j++ < PG_SPIN) udelay(PG_SPIN_DEL);
 		else pg_sleep(1);
 	}
 
-        if ((r&(STAT_ERR&stop))||(jiffies>=tmo)) {
-           s = RR(0,7);
-           e = RR(0,1);
-           p = RR(0,2);
-           if (verbose > 1)
+	if ((r&(STAT_ERR&stop))||(jiffies>=tmo)) {
+	   s = RR(0,7);
+	   e = RR(0,1);
+	   p = RR(0,2);
+	   if (verbose > 1)
 	     printk("%s: %s: stat=0x%x err=0x%x phase=%d%s\n",
-                   PG.name,msg,s,e,p,(jiffies>=tmo)?" timeout":"");
+		   PG.name,msg,s,e,p,(jiffies>=tmo)?" timeout":"");
 
 
-           if (jiffies>=tmo) e |= 0x100;
+	   if (jiffies>=tmo) e |= 0x100;
 	   PG.status = (e >> 4) & 0xff;
-           return -1;
-        }
-        return 0;
+	   return -1;
+	}
+	return 0;
 }
 
 static int pg_command( int unit, char * cmd, int dlen, int tmo )
@@ -386,64 +387,64 @@
 
 	pi_connect(PI);
 
-        WR(0,6,DRIVE);
+	WR(0,6,DRIVE);
+
+	if (pg_wait(unit,STAT_BUSY|STAT_DRQ,0,tmo,"before command")) {
+		pi_disconnect(PI);
+		return -1;
+	}
+
+	WR(0,4,dlen % 256);
+	WR(0,5,dlen / 256);
+	WR(0,7,0xa0);          /* ATAPI packet command */
+
+	if (pg_wait(unit,STAT_BUSY,STAT_DRQ,tmo,"command DRQ")) {
+		pi_disconnect(PI);
+		return -1;
+	}
 
-        if (pg_wait(unit,STAT_BUSY|STAT_DRQ,0,tmo,"before command")) {
-                pi_disconnect(PI);
-                return -1;
-        }
-
-        WR(0,4,dlen % 256);
-        WR(0,5,dlen / 256);
-        WR(0,7,0xa0);          /* ATAPI packet command */
-
-        if (pg_wait(unit,STAT_BUSY,STAT_DRQ,tmo,"command DRQ")) {
-                pi_disconnect(PI);
-                return -1;
-        }
-
-        if (RR(0,2) != 1) {
-           printk("%s: command phase error\n",PG.name);
-           pi_disconnect(PI);
-           return -1;
-        }
+	if (RR(0,2) != 1) {
+	   printk("%s: command phase error\n",PG.name);
+	   pi_disconnect(PI);
+	   return -1;
+	}
 
-        pi_write_block(PI,cmd,12);
+	pi_write_block(PI,cmd,12);
 
 	if (verbose > 1) {
 		printk("%s: Command sent, dlen=%d packet= ", PG.name,dlen);
 		for (k=0;k<12;k++) printk("%02x ",cmd[k]&0xff);
 		printk("\n");
 	}
-        return 0;
+	return 0;
 }
 
 static int pg_completion( int unit, char * buf, int tmo)
 
 {       int r, d, n, p;
 
-        r = pg_wait(unit,STAT_BUSY,STAT_DRQ|STAT_READY|STAT_ERR,
+	r = pg_wait(unit,STAT_BUSY,STAT_DRQ|STAT_READY|STAT_ERR,
 			tmo,"completion");
 
 	PG.dlen = 0;
 
-        while (RR(0,7)&STAT_DRQ) {
-           d = (RR(0,4)+256*RR(0,5));
-           n = ((d+3)&0xfffc);
+	while (RR(0,7)&STAT_DRQ) {
+	   d = (RR(0,4)+256*RR(0,5));
+	   n = ((d+3)&0xfffc);
 	   p = RR(0,2)&3;
 	   if (p == 0) pi_write_block(PI,buf,n);
 	   if (p == 2) pi_read_block(PI,buf,n);
 	   if (verbose > 1) printk("%s: %s %d bytes\n",PG.name,
 				    p?"Read":"Write",n);
-           PG.dlen += (1-p)*d;
-           buf += d;
-           r = pg_wait(unit,STAT_BUSY,STAT_DRQ|STAT_READY|STAT_ERR,
-                        tmo,"completion");
-        }
+	   PG.dlen += (1-p)*d;
+	   buf += d;
+	   r = pg_wait(unit,STAT_BUSY,STAT_DRQ|STAT_READY|STAT_ERR,
+			tmo,"completion");
+	}
 
-        pi_disconnect(PI); 
+	pi_disconnect(PI); 
 
-        return r;
+	return r;
 }
 
 static int pg_reset( int unit )
@@ -457,9 +458,9 @@
 
 	pg_sleep(2);
 
-        k = 0;
-        while ((k++ < PG_RESET_TMO) && (RR(1,6)&STAT_BUSY))
-                pg_sleep(1);
+	k = 0;
+	while ((k++ < PG_RESET_TMO) && (RR(1,6)&STAT_BUSY))
+		pg_sleep(1);
 
 	flg = 1;
 	for(i=0;i<5;i++) flg &= (RR(0,i+1) == expect[i]);
@@ -494,7 +495,7 @@
 	char    id_cmd[12] = { ATAPI_IDENTIFY,0,0,0,36,0,0,0,0,0,0,0};
 	char	buf[36];
 
-        s = pg_command(unit,id_cmd,36,jiffies+PG_TMO);
+	s = pg_command(unit,id_cmd,36,jiffies+PG_TMO);
 	if (s) return -1;
 	s = pg_completion(unit,buf,jiffies+PG_TMO);
 	if (s) return -1;
@@ -502,7 +503,7 @@
 	if (log) {
 		xs(buf,mf,8,8);
 		xs(buf,id,16,16);
-        	printk("%s: %s %s, %s\n",PG.name,mf,id,ms[PG.drive]);
+		printk("%s: %s %s, %s\n",PG.name,mf,id,ms[PG.drive]);
 	}
 
 	return 0;
@@ -511,7 +512,7 @@
 static int pg_probe( int unit )
 
 /*	returns  0, with id set if drive is detected
-	        -1, if drive detection failed
+		-1, if drive detection failed
 */
 
 {	if (PG.drive == -1) {
@@ -520,7 +521,7 @@
 	} else {
 	   if (!pg_reset(unit)) return pg_identify(unit,1);
 	}
-        return -1; 
+	return -1; 
 }
 
 static int pg_detect( void )
@@ -534,22 +535,22 @@
 	if (pg_drive_count == 0) {
 	    unit = 0;
 	    if (pi_init(PI,1,-1,-1,-1,-1,-1,pg_scratch,
-                        PI_PG,verbose,PG.name)) {
-	        if (!pg_probe(unit)) {
+			PI_PG,verbose,PG.name)) {
+		if (!pg_probe(unit)) {
 			PG.present = 1;
 			k++;
-	        } else pi_release(PI);
+		} else pi_release(PI);
 	    }
 
 	} else for (unit=0;unit<PG_UNITS;unit++) if (DU[D_PRT])
 	    if (pi_init(PI,0,DU[D_PRT],DU[D_MOD],DU[D_UNI],
 			DU[D_PRO],DU[D_DLY],pg_scratch,PI_PG,verbose,
 			PG.name)) { 
-                if (!pg_probe(unit)) {
-                        PG.present = 1;
-                        k++;
-                } else pi_release(PI);
-            }
+		if (!pg_probe(unit)) {
+			PG.present = 1;
+			k++;
+		} else pi_release(PI);
+	    }
 
 	if (k) return 0;
 
@@ -563,16 +564,16 @@
 
 {       int	unit = DEVICE_NR(inode->i_rdev);
 
-        if ((unit >= PG_UNITS) || (!PG.present)) return -ENODEV;
+	if ((unit >= PG_UNITS) || (!PG.present)) return -ENODEV;
 
-        PG.access++;
+	PG.access++;
 
 	if (PG.access > 1) {
 		PG.access--;
 		return -EBUSY;
 	}
 
-        MOD_INC_USE_COUNT;
+	MOD_INC_USE_COUNT;
 
 	if (PG.busy) {
 		pg_reset(unit);
@@ -590,34 +591,34 @@
 		return -ENOMEM;
 	}
 
-        return 0;
+	return 0;
 }
 
 static int pg_release (struct inode *inode, struct file *file)
 {
-        int	unit = DEVICE_NR(inode->i_rdev);
+	int	unit = DEVICE_NR(inode->i_rdev);
 
-        if ((unit >= PG_UNITS) || (PG.access <= 0)) 
-                return -EINVAL;
+	if ((unit >= PG_UNITS) || (PG.access <= 0)) 
+		return -EINVAL;
 
 	PG.access--;
 
 	kfree(PG.bufptr);
 	PG.bufptr = NULL;
 
-        MOD_DEC_USE_COUNT;
+	MOD_DEC_USE_COUNT;
 
 	return 0;
 
 }
 
 static ssize_t pg_write(struct file * filp, const char * buf, 
-                        size_t count, loff_t *ppos)
+			size_t count, loff_t *ppos)
 
 {       struct inode            *ino = filp->f_dentry->d_inode;
-        int                     unit = DEVICE_NR(ino->i_rdev);
-        struct pg_write_hdr     hdr;
-        int                     hs = sizeof(hdr);
+	int                     unit = DEVICE_NR(ino->i_rdev);
+	struct pg_write_hdr     hdr;
+	int                     hs = sizeof(hdr);
 
 	if (PG.busy) return -EBUSY;
 	if (count < hs) return -EINVAL;
@@ -652,7 +653,7 @@
 }
 
 static ssize_t pg_read(struct file * filp, char * buf, 
-                       size_t count, loff_t *ppos)
+		       size_t count, loff_t *ppos)
 
 {  	struct inode 		*ino = filp->f_dentry->d_inode;
 	int			unit = DEVICE_NR(ino->i_rdev);
@@ -673,7 +674,7 @@
 	copy = 0;
 
 	if (hdr.dlen < 0) {
-        	hdr.dlen = -1 * hdr.dlen;
+		hdr.dlen = -1 * hdr.dlen;
 		copy = hdr.dlen;
 		if (copy > (count - hs)) copy = count - hs;
 	}
diff -u --recursive --new-file v2.1.117/linux/drivers/block/paride/pt.c linux/drivers/block/paride/pt.c
--- v2.1.117/linux/drivers/block/paride/pt.c	Wed Jun 24 22:54:04 1998
+++ linux/drivers/block/paride/pt.c	Mon Aug 24 13:14:10 1998
@@ -72,10 +72,11 @@
 			(default "pt").
 
             verbose     This parameter controls the amount of logging
-                        that is done while the driver probes for
-                        devices.  Set it to 0 for a quiet load, or 1 to
-                        see all the progress messages.  (default 0)
-
+                        that the driver will do.  Set it to 0 for
+                        normal operation, 1 to see autoprobe progress
+                        messages, or 2 to see additional debugging
+                        output.  (default 0)
+ 
         If this driver is built into the kernel, you can use 
         the following command line parameters, with the same values
         as the corresponding module parameters listed above:
@@ -97,10 +98,12 @@
 				for clearing error status.
 				Eliminate sti();
 	1.02    GRG 1998.06.16  Eliminate an Ugh.
+	1.03    GRG 1998.08.15  Adjusted PT_TMO, use HZ in loop timing,
+				extra debugging
 
 */
 
-#define PT_VERSION      "1.02"
+#define PT_VERSION      "1.03"
 #define PT_MAJOR	96
 #define PT_NAME		"pt"
 #define PT_UNITS	4
@@ -174,13 +177,13 @@
 #include "paride.h"
 
 #define PT_MAX_RETRIES  5
-#define PT_TMO          800             /* interrupt timeout in jiffies */
+#define PT_TMO          3000            /* interrupt timeout in jiffies */
 #define PT_SPIN_DEL     50              /* spin delay in micro-seconds  */
-#define PT_RESET_TMO    30		/* 3 seconds */
+#define PT_RESET_TMO    30		/* 30 seconds */
 #define PT_READY_TMO	60		/* 60 seconds */
 #define PT_REWIND_TMO	1200		/* 20 minutes */
 
-#define PT_SPIN         (10000/PT_SPIN_DEL)*PT_TMO  
+#define PT_SPIN         ((1000000/(HZ*PT_SPIN_DEL))*PT_TMO)  
 
 #define STAT_ERR        0x00001
 #define STAT_INDEX      0x00002
@@ -265,6 +268,7 @@
         pt_ioctl,               /* ioctl */
         NULL,                   /* mmap */
         pt_open,                /* open */
+	NULL,			/* flush */
         pt_release,             /* release */
         NULL,                   /* fsync */
         NULL,                   /* fasync */
@@ -505,7 +509,7 @@
         pt_media_access_cmd(unit,PT_TMO,wm_cmd,"write filemark");
 }
 
-#define DBMSG(msg)      NULL
+#define DBMSG(msg)      ((verbose>1)?(msg):NULL)
 
 static int pt_reset( int unit )
 
diff -u --recursive --new-file v2.1.117/linux/drivers/block/ps2esdi.c linux/drivers/block/ps2esdi.c
--- v2.1.117/linux/drivers/block/ps2esdi.c	Thu May  7 22:51:48 1998
+++ linux/drivers/block/ps2esdi.c	Mon Aug 24 13:14:10 1998
@@ -157,6 +157,7 @@
 	ps2esdi_ioctl,		/* ioctl */
 	NULL,			/* mmap */
 	ps2esdi_open,		/* open */
+	NULL,			/* flush */
 	ps2esdi_release,	/* release */
 	block_fsync		/* fsync */
 };
diff -u --recursive --new-file v2.1.117/linux/drivers/block/rd.c linux/drivers/block/rd.c
--- v2.1.117/linux/drivers/block/rd.c	Wed Jun 24 22:54:04 1998
+++ linux/drivers/block/rd.c	Mon Aug 24 13:47:39 1998
@@ -223,6 +223,7 @@
 	NULL, 		/* ioctl */
 	NULL,		/* mmap */
 	NULL,		/* open */
+	NULL,		/* flush */
 	initrd_release,	/* release */
 	NULL		/* fsync */ 
 };
@@ -249,13 +250,11 @@
 	return 0;
 }
 
-#ifdef MODULE
 static int rd_release(struct inode * inode, struct file * filp)
 {
 	MOD_DEC_USE_COUNT;
 	return 0;
 }
-#endif
 
 static struct file_operations fd_fops = {
 	NULL,		/* lseek - default */
@@ -266,11 +265,8 @@
 	rd_ioctl, 	/* ioctl */
 	NULL,		/* mmap */
 	rd_open,	/* open */
-#ifndef MODULE
-	NULL,		/* no special release code... */
-#else
+	NULL,		/* flush */
 	rd_release,	/* module needs to decrement use count */
-#endif
 	block_fsync		/* fsync */ 
 };
 
diff -u --recursive --new-file v2.1.117/linux/drivers/block/swim3.c linux/drivers/block/swim3.c
--- v2.1.117/linux/drivers/block/swim3.c	Fri May  8 23:14:47 1998
+++ linux/drivers/block/swim3.c	Mon Aug 24 13:02:44 1998
@@ -968,7 +968,8 @@
 	floppy_ioctl,		/* ioctl */
 	NULL,			/* mmap */
 	floppy_open,		/* open */
-	floppy_release,		/* release */
+	NULL,			/* flush */
+	floppy_release,		/* release *
 	block_fsync,		/* fsync */
 	NULL,			/* fasync */
 	floppy_check_change,	/* check_media_change */
diff -u --recursive --new-file v2.1.117/linux/drivers/block/xd.c linux/drivers/block/xd.c
--- v2.1.117/linux/drivers/block/xd.c	Wed Jun 24 22:54:04 1998
+++ linux/drivers/block/xd.c	Mon Aug 24 13:02:45 1998
@@ -157,6 +157,7 @@
 	xd_ioctl,		/* ioctl */
 	NULL,			/* mmap */
 	xd_open,		/* open */
+	NULL,			/* flush */
 	xd_release,		/* release */
 	block_fsync		/* fsync */
 };
diff -u --recursive --new-file v2.1.117/linux/drivers/block/z2ram.c linux/drivers/block/z2ram.c
--- v2.1.117/linux/drivers/block/z2ram.c	Tue May 13 22:41:06 1997
+++ linux/drivers/block/z2ram.c	Mon Aug 24 13:48:08 1998
@@ -63,46 +63,46 @@
 
     while ( TRUE )
     {
-        INIT_REQUEST;
+	INIT_REQUEST;
 
-        start = CURRENT->sector << 9;
-        len  = CURRENT->current_nr_sectors << 9;
+	start = CURRENT->sector << 9;
+	len  = CURRENT->current_nr_sectors << 9;
 
-        if ( ( start + len ) > z2ram_size )
-        {
-            printk( KERN_ERR DEVICE_NAME ": bad access: block=%ld, count=%ld\n",
-                CURRENT->sector,
-                CURRENT->current_nr_sectors);
-            end_request( FALSE );
-            continue;
-        }
-
-        if ( ( CURRENT->cmd != READ ) && ( CURRENT->cmd != WRITE ) )
-        {
-            printk( KERN_ERR DEVICE_NAME ": bad command: %d\n", CURRENT->cmd );
-            end_request( FALSE );
-            continue;
-        }
-
-        while ( len ) 
-        {
-            addr = start & Z2RAM_CHUNKMASK;
-            size = Z2RAM_CHUNKSIZE - addr;
-            if ( len < size )
-                size = len;
-
-            addr += z2ram_map[ start >> Z2RAM_CHUNKSHIFT ];
-
-            if ( CURRENT->cmd == READ )
-                memcpy( CURRENT->buffer, (char *)addr, size );
-            else
-                memcpy( (char *)addr, CURRENT->buffer, size );
-
-            start += size;
-            len -= size;
-        }
+	if ( ( start + len ) > z2ram_size )
+	{
+	    printk( KERN_ERR DEVICE_NAME ": bad access: block=%ld, count=%ld\n",
+		CURRENT->sector,
+		CURRENT->current_nr_sectors);
+	    end_request( FALSE );
+	    continue;
+	}
+
+	if ( ( CURRENT->cmd != READ ) && ( CURRENT->cmd != WRITE ) )
+	{
+	    printk( KERN_ERR DEVICE_NAME ": bad command: %d\n", CURRENT->cmd );
+	    end_request( FALSE );
+	    continue;
+	}
+
+	while ( len ) 
+	{
+	    addr = start & Z2RAM_CHUNKMASK;
+	    size = Z2RAM_CHUNKSIZE - addr;
+	    if ( len < size )
+		size = len;
+
+	    addr += z2ram_map[ start >> Z2RAM_CHUNKSHIFT ];
+
+	    if ( CURRENT->cmd == READ )
+		memcpy( CURRENT->buffer, (char *)addr, size );
+	    else
+		memcpy( (char *)addr, CURRENT->buffer, size );
+
+	    start += size;
+	    len -= size;
+	}
 
-        end_request( TRUE );
+	end_request( TRUE );
     }
 }
 
@@ -113,13 +113,13 @@
 
     for ( i = 0; i < Z2RAM_SIZE / Z2RAM_CHUNKSIZE; i++ )
     {
-        if ( test_bit( i, zorro_unused_z2ram ) )
-        {
-            z2_count++;
-            z2ram_map[ z2ram_size++ ] = 
-                ZTWO_VADDR( Z2RAM_START ) + ( i << Z2RAM_CHUNKSHIFT );
-            clear_bit( i, zorro_unused_z2ram );
-        }
+	if ( test_bit( i, zorro_unused_z2ram ) )
+	{
+	    z2_count++;
+	    z2ram_map[ z2ram_size++ ] = 
+		ZTWO_VADDR( Z2RAM_START ) + ( i << Z2RAM_CHUNKSHIFT );
+	    clear_bit( i, zorro_unused_z2ram );
+	}
     }
 
     return;
@@ -131,18 +131,18 @@
 
     while ( amiga_chip_avail() > ( Z2RAM_CHUNKSIZE * 4 ) )
     {
-        chip_count++;
-        z2ram_map[ z2ram_size ] =
-            (u_long)amiga_chip_alloc( Z2RAM_CHUNKSIZE );
-
-        if ( z2ram_map[ z2ram_size ] == 0 )
-        {
-            break;
-        }
+	chip_count++;
+	z2ram_map[ z2ram_size ] =
+	    (u_long)amiga_chip_alloc( Z2RAM_CHUNKSIZE );
+
+	if ( z2ram_map[ z2ram_size ] == 0 )
+	{
+	    break;
+	}
 
-        z2ram_size++;
+	z2ram_size++;
     }
-        
+	
     return;
 }
 
@@ -151,99 +151,99 @@
 {
     int device;
     int max_z2_map = ( Z2RAM_SIZE / Z2RAM_CHUNKSIZE ) *
-        sizeof( z2ram_map[0] );
+	sizeof( z2ram_map[0] );
     int max_chip_map = ( amiga_chip_size / Z2RAM_CHUNKSIZE ) *
-        sizeof( z2ram_map[0] );
+	sizeof( z2ram_map[0] );
 
     device = DEVICE_NR( inode->i_rdev );
 
     if ( current_device != -1 && current_device != device )
     {
-        return -EBUSY;
+	return -EBUSY;
     }
 
     if ( current_device == -1 )
     {
-        z2_count   = 0;
-        chip_count = 0;
-        z2ram_size = 0;
-
-        switch ( device )
-        {
-            case Z2MINOR_COMBINED:
-
-                z2ram_map = kmalloc( max_z2_map + max_chip_map, GFP_KERNEL );
-                if ( z2ram_map == NULL )
-                {
-                    printk( KERN_ERR DEVICE_NAME
-                        ": cannot get mem for z2ram_map\n" );
-                    return -ENOMEM;
-                }
-
-                get_z2ram();
-                get_chipram();
-
-                if ( z2ram_size != 0 )
-                    printk( KERN_INFO DEVICE_NAME 
-                        ": using %iK Zorro II RAM and %iK Chip RAM (Total %dK)\n",
-                        z2_count * Z2RAM_CHUNK1024,
-                        chip_count * Z2RAM_CHUNK1024,
-                        ( z2_count + chip_count ) * Z2RAM_CHUNK1024 );
+	z2_count   = 0;
+	chip_count = 0;
+	z2ram_size = 0;
+
+	switch ( device )
+	{
+	    case Z2MINOR_COMBINED:
+
+		z2ram_map = kmalloc( max_z2_map + max_chip_map, GFP_KERNEL );
+		if ( z2ram_map == NULL )
+		{
+		    printk( KERN_ERR DEVICE_NAME
+			": cannot get mem for z2ram_map\n" );
+		    return -ENOMEM;
+		}
+
+		get_z2ram();
+		get_chipram();
+
+		if ( z2ram_size != 0 )
+		    printk( KERN_INFO DEVICE_NAME 
+			": using %iK Zorro II RAM and %iK Chip RAM (Total %dK)\n",
+			z2_count * Z2RAM_CHUNK1024,
+			chip_count * Z2RAM_CHUNK1024,
+			( z2_count + chip_count ) * Z2RAM_CHUNK1024 );
 
-            break;
+	    break;
 
     	    case Z2MINOR_Z2ONLY:
-                z2ram_map = kmalloc( max_z2_map, GFP_KERNEL );
-                if ( z2ram_map == NULL )
-                {
-                    printk( KERN_ERR DEVICE_NAME
-                        ": cannot get mem for z2ram_map\n" );
-                    return -ENOMEM;
-                }
-
-                get_z2ram();
-
-                if ( z2ram_size != 0 )
-                    printk( KERN_INFO DEVICE_NAME 
-                        ": using %iK of Zorro II RAM\n",
-                        z2_count * Z2RAM_CHUNK1024 );
-
-            break;
-
-            case Z2MINOR_CHIPONLY:
-                z2ram_map = kmalloc( max_chip_map, GFP_KERNEL );
-                if ( z2ram_map == NULL )
-                {
-                    printk( KERN_ERR DEVICE_NAME
-                        ": cannot get mem for z2ram_map\n" );
-                    return -ENOMEM;
-                }
-
-                get_chipram();
-
-                if ( z2ram_size != 0 )
-                    printk( KERN_INFO DEVICE_NAME 
-                        ": using %iK Chip RAM\n",
-                        chip_count * Z2RAM_CHUNK1024 );
-                    
-            break;
-
-            default:
-                return -ENODEV;
-        }
-
-        if ( z2ram_size == 0 )
-        {
-            kfree( z2ram_map );
-            printk( KERN_NOTICE DEVICE_NAME
-                ": no unused ZII/Chip RAM found\n" );
-            return -ENOMEM;
-        }
-
-        current_device = device;
-        z2ram_size <<= Z2RAM_CHUNKSHIFT;
-        z2_sizes[ device ] = z2ram_size >> 10;
-        blk_size[ MAJOR_NR ] = z2_sizes;
+		z2ram_map = kmalloc( max_z2_map, GFP_KERNEL );
+		if ( z2ram_map == NULL )
+		{
+		    printk( KERN_ERR DEVICE_NAME
+			": cannot get mem for z2ram_map\n" );
+		    return -ENOMEM;
+		}
+
+		get_z2ram();
+
+		if ( z2ram_size != 0 )
+		    printk( KERN_INFO DEVICE_NAME 
+			": using %iK of Zorro II RAM\n",
+			z2_count * Z2RAM_CHUNK1024 );
+
+	    break;
+
+	    case Z2MINOR_CHIPONLY:
+		z2ram_map = kmalloc( max_chip_map, GFP_KERNEL );
+		if ( z2ram_map == NULL )
+		{
+		    printk( KERN_ERR DEVICE_NAME
+			": cannot get mem for z2ram_map\n" );
+		    return -ENOMEM;
+		}
+
+		get_chipram();
+
+		if ( z2ram_size != 0 )
+		    printk( KERN_INFO DEVICE_NAME 
+			": using %iK Chip RAM\n",
+			chip_count * Z2RAM_CHUNK1024 );
+		    
+	    break;
+
+	    default:
+		return -ENODEV;
+	}
+
+	if ( z2ram_size == 0 )
+	{
+	    kfree( z2ram_map );
+	    printk( KERN_NOTICE DEVICE_NAME
+		": no unused ZII/Chip RAM found\n" );
+	    return -ENOMEM;
+	}
+
+	current_device = device;
+	z2ram_size <<= Z2RAM_CHUNKSHIFT;
+	z2_sizes[ device ] = z2ram_size >> 10;
+	blk_size[ MAJOR_NR ] = z2_sizes;
     }
 
 #if defined(MODULE)
@@ -258,7 +258,7 @@
 {
 
     if ( current_device == -1 )
-        return;     
+	return;     
 
     sync_dev( inode->i_rdev );
 
@@ -271,16 +271,17 @@
 
 static struct file_operations z2_fops =
 {
-        NULL,                   /* lseek - default */
-        block_read,             /* read - general block-dev read */
-        block_write,            /* write - general block-dev write */
-        NULL,                   /* readdir - bad */
-        NULL,                   /* poll */
-        NULL,                   /* ioctl */
-        NULL,                   /* mmap */
-        z2_open,                /* open */
-        z2_release,             /* release */
-        block_fsync             /* fsync */
+	NULL,                   /* lseek - default */
+	block_read,             /* read - general block-dev read */
+	block_write,            /* write - general block-dev write */
+	NULL,                   /* readdir - bad */
+	NULL,                   /* poll */
+	NULL,                   /* ioctl */
+	NULL,                   /* mmap */
+	z2_open,                /* open */
+	NULL,			/* flush */
+	z2_release,             /* release */
+	block_fsync             /* fsync */
 };
 
 __initfunc(int
@@ -288,13 +289,13 @@
 {
 
     if ( !MACH_IS_AMIGA )
-        return -ENXIO;
+	return -ENXIO;
 
     if ( register_blkdev( MAJOR_NR, DEVICE_NAME, &z2_fops ) )
     {
-        printk( KERN_ERR DEVICE_NAME ": Unable to get major %d\n",
-            MAJOR_NR );
-        return -EBUSY;
+	printk( KERN_ERR DEVICE_NAME ": Unable to get major %d\n",
+	    MAJOR_NR );
+	return -EBUSY;
     }
    
     blk_dev[ MAJOR_NR ].request_fn = DEVICE_REQUEST;
@@ -313,7 +314,7 @@
     error = z2_init();
     if ( error == 0 )
     {
-        printk( KERN_INFO DEVICE_NAME ": loaded as module\n" );
+	printk( KERN_INFO DEVICE_NAME ": loaded as module\n" );
     }
     
     return error;
@@ -325,29 +326,29 @@
     int i, j;
 
     if ( unregister_blkdev( MAJOR_NR, DEVICE_NAME ) != 0 )
-        printk( KERN_ERR DEVICE_NAME ": unregister of device failed\n");
+	printk( KERN_ERR DEVICE_NAME ": unregister of device failed\n");
 
     if ( current_device != -1 )
     {
-        i = 0;
+	i = 0;
 
-        for ( j = 0 ; j < z2_count; j++ )
-        {
-            set_bit( i++, zorro_unused_z2ram ); 
-        }
-
-        for ( j = 0 ; j < chip_count; j++ )
-        {
-            if ( z2ram_map[ i ] )
-            {
-                amiga_chip_free( (void *) z2ram_map[ i++ ] );
-            }
-        }
-
-        if ( z2ram_map != NULL )
-        {
-            kfree( z2ram_map );
-        }
+	for ( j = 0 ; j < z2_count; j++ )
+	{
+	    set_bit( i++, zorro_unused_z2ram ); 
+	}
+
+	for ( j = 0 ; j < chip_count; j++ )
+	{
+	    if ( z2ram_map[ i ] )
+	    {
+		amiga_chip_free( (void *) z2ram_map[ i++ ] );
+	    }
+	}
+
+	if ( z2ram_map != NULL )
+	{
+	    kfree( z2ram_map );
+	}
     }
 
     return;
diff -u --recursive --new-file v2.1.117/linux/drivers/cdrom/Makefile linux/drivers/cdrom/Makefile
--- v2.1.117/linux/drivers/cdrom/Makefile	Wed Apr  1 20:11:48 1998
+++ linux/drivers/cdrom/Makefile	Thu Aug 20 15:17:06 1998
@@ -25,6 +25,7 @@
 
 obj-$(CONFIG_BLK_DEV_IDECD)	+=              cdrom.o
 obj-$(CONFIG_BLK_DEV_SR)	+=              cdrom.o
+obj-$(CONFIG_PARIDE_PCD)	+=		cdrom.o
 
 obj-$(CONFIG_AZTCD)		+= aztcd.o
 obj-$(CONFIG_CDU31A)		+= cdu31a.o     cdrom.o
diff -u --recursive --new-file v2.1.117/linux/drivers/cdrom/aztcd.c linux/drivers/cdrom/aztcd.c
--- v2.1.117/linux/drivers/cdrom/aztcd.c	Wed Dec  3 04:29:41 1997
+++ linux/drivers/cdrom/aztcd.c	Mon Aug 24 13:02:43 1998
@@ -379,6 +379,7 @@
 	aztcd_ioctl,            /* ioctl */
 	NULL,                   /* mmap */
 	aztcd_open,             /* open */
+	NULL,			/* flush */
 	aztcd_release,          /* release */
 	NULL,                   /* fsync */
 	NULL,                   /* fasync*/
diff -u --recursive --new-file v2.1.117/linux/drivers/cdrom/cdrom.c linux/drivers/cdrom/cdrom.c
--- v2.1.117/linux/drivers/cdrom/cdrom.c	Mon Aug  3 12:45:45 1998
+++ linux/drivers/cdrom/cdrom.c	Mon Aug 24 13:02:44 1998
@@ -184,6 +184,7 @@
 	cdrom_ioctl,                    /* ioctl */
 	NULL,                           /* mmap */
 	cdrom_open,                     /* open */
+	NULL,				/* flush */
 	cdrom_release,                  /* release */
 	NULL,                           /* fsync */
 	NULL,                           /* fasync */
@@ -1081,10 +1082,12 @@
 	initialized = 1;
 }
 
+#ifdef MODULE
 static void cdrom_sysctl_unregister(void)
 {
 	unregister_sysctl_table(cdrom_sysctl_header);
 }
+#endif /* endif MODULE */
 #endif /* endif CONFIG_SYSCTL */
 
 #ifdef MODULE
diff -u --recursive --new-file v2.1.117/linux/drivers/cdrom/gscd.c linux/drivers/cdrom/gscd.c
--- v2.1.117/linux/drivers/cdrom/gscd.c	Tue Dec  2 11:41:44 1997
+++ linux/drivers/cdrom/gscd.c	Mon Aug 24 13:02:44 1998
@@ -160,6 +160,7 @@
 	gscd_ioctl,		/* ioctl */
 	NULL,			/* mmap */
 	gscd_open,		/* open */
+	NULL,			/* flush */
 	gscd_release,		/* release */
 	NULL,                   /* fsync */
 	NULL,                   /* fasync*/
diff -u --recursive --new-file v2.1.117/linux/drivers/cdrom/optcd.c linux/drivers/cdrom/optcd.c
--- v2.1.117/linux/drivers/cdrom/optcd.c	Tue Dec  2 11:41:44 1997
+++ linux/drivers/cdrom/optcd.c	Mon Aug 24 13:14:10 1998
@@ -2008,6 +2008,7 @@
 	opt_ioctl,		/* ioctl */
 	NULL,			/* mmap */
 	opt_open,		/* open */
+	NULL,			/* flush */
 	opt_release,		/* release */
 	NULL,			/* fsync */
 	NULL,			/* fasync */
diff -u --recursive --new-file v2.1.117/linux/drivers/cdrom/sbpcd.c linux/drivers/cdrom/sbpcd.c
--- v2.1.117/linux/drivers/cdrom/sbpcd.c	Sun Jun  7 11:16:29 1998
+++ linux/drivers/cdrom/sbpcd.c	Sat Aug 22 12:33:04 1998
@@ -4540,7 +4540,7 @@
 		/* resume playing audio tracks when a previous PLAY AUDIO call has  */
 		/* been paused with a PAUSE command.                                */
 		/* It will resume playing from the location saved in SubQ_run_tot.  */
-		if (D_S[d].audio_state!=audio_pausing) return -EINVAL;
+		if (D_S[d].audio_state!=audio_pausing) RETURN_UP(-EINVAL);
 		if (famL_drive)
 			i=cc_PlayAudio(D_S[d].pos_audio_start,
 				       D_S[d].pos_audio_end);
@@ -4654,7 +4654,9 @@
 #endif SAFE_MIXED
 		i=cc_Pause_Resume(1);
 		D_S[d].audio_state=0;
+#if 0
 		cc_DriveReset();
+#endif
 		RETURN_UP(i);
 		
 	case CDROMSTART:  /* Spin up the drive */
@@ -4676,7 +4678,7 @@
 	case CDROMVOLREAD:   /* read Volume settings from drive */
 		msg(DBG_IOC,"ioctl: CDROMVOLREAD entered.\n");
 		st=cc_GetVolume();
-		if (st<0) return (st);
+		if (st<0) RETURN_UP(st);
 		volctrl.channel0=D_S[d].vol_ctrl0;
 		volctrl.channel1=D_S[d].vol_ctrl1;
 		volctrl.channel2=0;
diff -u --recursive --new-file v2.1.117/linux/drivers/cdrom/sjcd.c linux/drivers/cdrom/sjcd.c
--- v2.1.117/linux/drivers/cdrom/sjcd.c	Tue Dec  2 11:41:45 1997
+++ linux/drivers/cdrom/sjcd.c	Mon Aug 24 13:14:10 1998
@@ -1429,6 +1429,7 @@
   sjcd_ioctl,         /* ioctl */
   NULL,               /* mmap */
   sjcd_open,          /* open */
+  NULL,		      /* flush */
   sjcd_release,       /* release */
   NULL,               /* fsync */
   NULL,               /* fasync */
diff -u --recursive --new-file v2.1.117/linux/drivers/cdrom/sonycd535.c linux/drivers/cdrom/sonycd535.c
--- v2.1.117/linux/drivers/cdrom/sonycd535.c	Sun Jun  7 11:16:29 1998
+++ linux/drivers/cdrom/sonycd535.c	Mon Aug 24 13:14:10 1998
@@ -1469,16 +1469,17 @@
 {
 	NULL,						/* lseek - default */
 	block_read,					/* read - general block-dev read */
-	block_write,				/* write - general block-dev write */
+	block_write,					/* write - general block-dev write */
 	NULL,						/* readdir - bad */
 	NULL,						/* poll */
 	cdu_ioctl,					/* ioctl */
 	NULL,						/* mmap */
 	cdu_open,					/* open */
-	cdu_release,				/* release */
+	NULL,						/* flush */
+	cdu_release,					/* release */
 	NULL,						/* fsync */
 	NULL,						/* fasync */
-	cdu535_check_media_change,	/* check media change */
+	cdu535_check_media_change,			/* check media change */
 	NULL						/* revalidate */
 };
 
diff -u --recursive --new-file v2.1.117/linux/drivers/char/Config.in linux/drivers/char/Config.in
--- v2.1.117/linux/drivers/char/Config.in	Thu Aug  6 14:06:31 1998
+++ linux/drivers/char/Config.in	Sun Aug 23 13:33:22 1998
@@ -113,10 +113,15 @@
   if [ "$CONFIG_RADIO_RTRACK" = "y" ]; then
     hex '  RadioTrack i/o port (0x20f or 0x30f)' CONFIG_RADIO_RTRACK_PORT 20f
   fi
+  dep_tristate 'AIMSlab RadioTrack II support' CONFIG_RADIO_RTRACK2 $CONFIG_VIDEO_DEV
+  if [ "$CONFIG_RADIO_RTRACK2" = "y" ]; then
+    hex '  RadioTrack II i/o port (0x20c or 0x30c)' CONFIG_RADIO_RTRACK2_PORT 30c
+  fi
   dep_tristate 'Aztech/Packard Bell Radio' CONFIG_RADIO_AZTECH $CONFIG_VIDEO_DEV
   if [ "$CONFIG_RADIO_AZTECH" = "y" ]; then
     hex '  Aztech/Packard Bell I/O port (0x350 or 0x358)' CONFIG_RADIO_AZTECH_PORT 350
   fi
+  dep_tristate 'Miro PCM20 Radio' CONFIG_RADIO_MIROPCM20 $CONFIG_VIDEO_DEV
   dep_tristate 'BT848 Video For Linux' CONFIG_VIDEO_BT848 $CONFIG_VIDEO_DEV
   if [ "$CONFIG_PARPORT" != "n" ]; then
     dep_tristate 'Quickcam BW Video For Linux' CONFIG_VIDEO_BWQCAM $CONFIG_VIDEO_DEV
diff -u --recursive --new-file v2.1.117/linux/drivers/char/Makefile linux/drivers/char/Makefile
--- v2.1.117/linux/drivers/char/Makefile	Thu Aug 20 17:05:15 1998
+++ linux/drivers/char/Makefile	Sun Aug 23 13:32:25 1998
@@ -407,6 +407,14 @@
   endif
 endif                                             
 
+ifeq ($(CONFIG_RADIO_MIROPCM20),y)
+L_OBJS += radio-miropcm20.o
+else
+  ifeq ($(CONFIG_RADIO_MIROPCM20),m)
+  M_OBJS += radio-miropcm20.o
+  endif
+endif
+
 ifeq ($(CONFIG_QIC02_TAPE),y)
 L_OBJS += tpqic02.o
 else
diff -u --recursive --new-file v2.1.117/linux/drivers/char/acquirewdt.c linux/drivers/char/acquirewdt.c
--- v2.1.117/linux/drivers/char/acquirewdt.c	Mon Jan 12 15:12:42 1998
+++ linux/drivers/char/acquirewdt.c	Mon Aug 24 13:02:43 1998
@@ -174,6 +174,7 @@
 	acq_ioctl,
 	NULL,		/* No mmap */
 	acq_open,
+	NULL,		/* flush */
 	acq_close
 };
 
diff -u --recursive --new-file v2.1.117/linux/drivers/char/adbmouse.c linux/drivers/char/adbmouse.c
--- v2.1.117/linux/drivers/char/adbmouse.c	Thu Aug 20 17:05:15 1998
+++ linux/drivers/char/adbmouse.c	Mon Aug 24 13:02:43 1998
@@ -236,6 +236,7 @@
     NULL,		/* mouse_ioctl */
     NULL,		/* mouse_mmap */
     open_mouse,
+    NULL,		/* flush */
     release_mouse,
     NULL,
     fasync_mouse,
diff -u --recursive --new-file v2.1.117/linux/drivers/char/amigamouse.c linux/drivers/char/amigamouse.c
--- v2.1.117/linux/drivers/char/amigamouse.c	Thu Aug 20 17:05:15 1998
+++ linux/drivers/char/amigamouse.c	Mon Aug 24 13:02:43 1998
@@ -299,6 +299,7 @@
 	NULL, 		/* mouse_ioctl */
 	NULL,		/* mouse_mmap */
 	open_mouse,
+	NULL,		/* flush */
 	release_mouse,
 	NULL,
 	fasync_mouse,
diff -u --recursive --new-file v2.1.117/linux/drivers/char/apm_bios.c linux/drivers/char/apm_bios.c
--- v2.1.117/linux/drivers/char/apm_bios.c	Tue Aug 18 22:02:03 1998
+++ linux/drivers/char/apm_bios.c	Mon Aug 24 13:02:43 1998
@@ -401,6 +401,7 @@
 	do_ioctl,
 	NULL,		/* mmap */
 	do_open,
+	NULL,		/* flush */
 	do_release,
 	NULL,		/* fsync */
 	NULL		/* fasync */
diff -u --recursive --new-file v2.1.117/linux/drivers/char/atarimouse.c linux/drivers/char/atarimouse.c
--- v2.1.117/linux/drivers/char/atarimouse.c	Thu Aug 20 17:05:15 1998
+++ linux/drivers/char/atarimouse.c	Mon Aug 24 13:02:43 1998
@@ -149,6 +149,7 @@
     NULL,		/* mouse_ioctl */
     NULL,		/* mouse_mmap */
     open_mouse,
+    NULL,		/* flush */
     release_mouse,
     NULL,
     fasync_mouse,
diff -u --recursive --new-file v2.1.117/linux/drivers/char/atixlmouse.c linux/drivers/char/atixlmouse.c
--- v2.1.117/linux/drivers/char/atixlmouse.c	Thu Aug 20 17:05:15 1998
+++ linux/drivers/char/atixlmouse.c	Mon Aug 24 13:02:43 1998
@@ -191,6 +191,7 @@
 	NULL, 		/* mouse_ioctl */
 	NULL,		/* mouse_mmap */
 	open_mouse,
+	NULL,		/* flush */
 	release_mouse,
 	NULL,
 	fasync_mouse,
diff -u --recursive --new-file v2.1.117/linux/drivers/char/bt848.h linux/drivers/char/bt848.h
--- v2.1.117/linux/drivers/char/bt848.h	Thu Aug 20 17:05:15 1998
+++ linux/drivers/char/bt848.h	Sun Aug 23 13:32:25 1998
@@ -30,6 +30,12 @@
 #ifndef PCI_DEVICE_ID_BT849
 #define PCI_DEVICE_ID_BT849     0x351
 #endif
+#ifndef PCI_DEVICE_ID_BT878
+#define PCI_DEVICE_ID_BT878     0x36e
+#endif
+#ifndef PCI_DEVICE_ID_BT879
+#define PCI_DEVICE_ID_BT879     0x36f
+#endif
 
 
 /* Brooktree 848 registers */
@@ -286,10 +292,6 @@
 #define BT848_RISC_COUNT       0x120
 #define BT848_GPIO_DATA        0x200
 
-/* Bt878 register */
-
-#define BT878_DEVCTRL 0x40
-#define BT878_NTBF 0x02
 
 /* Bt848 RISC commands */
 
@@ -340,7 +342,14 @@
 #define BT848_FCAP             0x0E8
 #define BT848_PLL_F_LO         0x0F0
 #define BT848_PLL_F_HI         0x0F4
+
 #define BT848_PLL_XCI          0x0F8
+#define BT848_PLL_X            (1<<7)
+#define BT848_PLL_C            (1<<6)
 
+/* Bt878 register */
+
+#define BT878_DEVCTRL 0x40
+#define BT878_EN_TBFX 0x02
 
 #endif
diff -u --recursive --new-file v2.1.117/linux/drivers/char/bttv.c linux/drivers/char/bttv.c
--- v2.1.117/linux/drivers/char/bttv.c	Thu Aug 20 17:05:15 1998
+++ linux/drivers/char/bttv.c	Sun Aug 23 13:32:25 1998
@@ -65,18 +65,12 @@
 #define DEBUG(x)		/* Debug driver */	
 #define IDEBUG(x) 		/* Debug interrupt handler */
 
-static unsigned int remap=0;    /* remap Bt848 */
-static unsigned int vidmem=0;   /* manually set video mem address */
-static int triton1=0;
-static int radio=0;
-
-static unsigned int card=0;
-
-MODULE_PARM(remap,"i");
 MODULE_PARM(vidmem,"i");
 MODULE_PARM(triton1,"i");
-MODULE_PARM(radio,"i");
-MODULE_PARM(card,"i");
+MODULE_PARM(remap,"1-4i");
+MODULE_PARM(radio,"1-4i");
+MODULE_PARM(card,"1-4i");
+MODULE_PARM(pll,"1-4i");
 
 static int find_vga(void);
 static void bt848_set_risc_jmps(struct bttv *btv);
@@ -84,12 +78,19 @@
 /* Anybody who uses more than four? */
 #define BTTV_MAX 4
 
+static unsigned int vidmem=0;   /* manually set video mem address */
+static int triton1=0;
+
+static unsigned int remap[BTTV_MAX];    /* remap Bt848 */
+static unsigned int radio[BTTV_MAX];
+static unsigned int card[BTTV_MAX] = { 0, 0, 
+                                       0, 0 };
+static unsigned int pll[BTTV_MAX] = { 0, 0, 0, 0 };
+
 static int bttv_num;			/* number of Bt848s in use */
 static struct bttv bttvs[BTTV_MAX];
 
 #define I2C_TIMING (0x7<<4)
-#define I2C_COMMAND (I2C_TIMING | BT848_I2C_SCL | BT848_I2C_SDA)
-
 #define I2C_DELAY   10
 #define I2C_SET(CTRL,DATA) \
     { btwrite((CTRL<<1)|(DATA), BT848_I2C); udelay(I2C_DELAY); }
@@ -128,10 +129,6 @@
 
 static inline unsigned long uvirt_to_bus(unsigned long adr) 
 {
-	/*  printk("adr: 0x%8x, ",adr);
-	printk("phys: 0x%8x, ",(uvirt_to_phys(adr)));
-	printk("bus: 0x%8x\n",virt_to_bus(phys_to_virt(uvirt_to_phys(adr))));
-	*/
 	return virt_to_bus(phys_to_virt(uvirt_to_phys(adr)));
 }
 
@@ -199,7 +196,8 @@
 	if(!btv->fbuffer)
 		btv->fbuffer=(unsigned char *) rvmalloc(2*BTTV_MAX_FBUF);
 	else
-		printk(KERN_ERR "bttv: Double alloc of fbuffer!\n");
+		printk(KERN_ERR "bttv%d: Double alloc of fbuffer!\n",
+			btv->nr);
 	if(!btv->fbuffer)
 		return -ENOBUFS;
 	return 0;
@@ -236,7 +234,7 @@
 	/* clear status bit ; BT848_INT_RACK is ro */
 	btwrite(BT848_INT_I2CDONE, BT848_INT_STAT);
   
-	btwrite(((addr & 0xff) << 24) | I2C_COMMAND, BT848_I2C);
+	btwrite(((addr & 0xff) << 24) | btv->i2c_command, BT848_I2C);
   
 	/*
 	 * Timeout for I2CRead is 1 second (this should be enough, really!)
@@ -251,7 +249,8 @@
   
 	if (!i) 
 	{
-		printk(KERN_DEBUG "bttv: I2CRead timeout\n");
+		printk(KERN_DEBUG "bttv%d: I2CRead timeout\n",
+			btv->nr);
 		return -1;
 	}
 	if (!(stat & BT848_INT_RACK))
@@ -274,7 +273,7 @@
 	/* clear status bit; BT848_INT_RACK is ro */
 	btwrite(BT848_INT_I2CDONE, BT848_INT_STAT);
   
-	data=((addr & 0xff) << 24) | ((b1 & 0xff) << 16) | I2C_COMMAND;
+	data=((addr & 0xff) << 24) | ((b1 & 0xff) << 16) | btv->i2c_command;
 	if (both)
 	{
 		data|=((b2 & 0xff) << 8);
@@ -293,7 +292,8 @@
   
 	if (!i) 
 	{
-		printk(KERN_DEBUG "bttv: I2CWrite timeout\n");
+		printk(KERN_DEBUG "bttv%d: I2CWrite timeout\n",
+			btv->nr);
 		return -1;
 	}
 	if (!(stat & BT848_INT_RACK))
@@ -356,9 +356,10 @@
 			if (btv->tuner_type != -1) 
 			{
 				tunertype=btv->tuner_type;
-				i2c_control_device(&(btv->i2c), I2C_DRIVERID_TUNER,
-					TUNER_SET_TYPE,&tunertype);
-			}
+ 				i2c_control_device(&(btv->i2c), 
+                                                   I2C_DRIVERID_TUNER,
+                                                   TUNER_SET_TYPE,&tunertype);
+ 			}
 			break;
 	}
 }
@@ -406,6 +407,7 @@
         u32 gpiomask;
         u32 muxsel[8];
         u32 audiomux[6]; /* Tuner, Radio, internal, external, mute, stereo */
+        u32 gpiomask2; /* GPIO MUX mask */
 };
 
 static struct tvcard tvcards[] = 
@@ -423,12 +425,14 @@
 	/* Diamond DTV2000 */
         { 3, 0, 2, 3, { 2, 3, 1, 1}, { 0, 1, 0, 1, 3}},
 	/* AVerMedia TVPhone */
-        { 3, 0, 2,15, { 2, 3, 1, 1}, {12, 0,11,11, 0}},
+        { 3, 0, 3,15, { 2, 3, 1, 1}, {12, 0,11,11, 0}},
         /* Matrix Vision MV-Delta */
-        { 5,-1, 4, 0, { 2, 3, 1, 0, 0}},
+        { 5,-1, 3, 0, { 2, 3, 1, 0, 0}},
         /* Fly Video II */
         { 3, 0, 2, 0xc00, { 2, 3, 1, 1}, 
         {0, 0xc00, 0x800, 0x400, 0xc00, 0}},
+        /* TurboTV */
+        { 3, 0, 2, 3, { 2, 3, 1, 1}, { 1, 1, 2, 3, 0}},
 };
 #define TVCARDS (sizeof(tvcards)/sizeof(tvcard))
 
@@ -503,12 +507,46 @@
 
 /* If Bt848a or Bt849, use PLL for PAL/SECAM and crystal for NTSC*/
 
+/* Frequency = (F_input / PLL_X) * PLL_I.PLL_F/PLL_C 
+   PLL_X = Reference pre-divider (0=1, 1=2) 
+   PLL_C = Post divider (0=6, 1=4)
+   PLL_I = Integer input 
+   PLL_F = Fractional input 
+   
+   F_input = 28.636363 MHz: 
+   PAL (CLKx2 = 35.46895 MHz): PLL_X = 1, PLL_I = 0x0E, PLL_F = 0xDCF9, PLL_C = 0
+*/
+
+static void set_pll_freq(struct bttv *btv, unsigned int fin, unsigned int fout)
+{
+        unsigned char fl, fh, fi;
+        
+        /* prevent overflows */
+        fin/=4;
+        fout/=4;
+
+        fout*=12;
+        fi=fout/fin;
+
+        fout=(fout-fin*fi)*256;
+        fh=fout/fin;
+
+        fout=(fout-fin*fh)*256;
+        fl=fout/fin;
+
+        /*printk("0x%02x 0x%02x 0x%02x\n", fi, fh, fl);*/
+        btwrite(fl,BT848_PLL_F_LO);
+        btwrite(fh,BT848_PLL_F_HI);
+        btwrite(fi|BT848_PLL_X,BT848_PLL_XCI);
+}
+
 static int set_pll(struct bttv *btv)
 {
         int i;
+        unsigned long tv;
 
-	if (!btv->pll)
-	       	return 0;
+        if (!btv->pll)
+		return 0;
         if ((btread(BT848_IFORM)&BT848_IFORM_XT0))
         {
                 /* printk ("switching PLL off\n");*/
@@ -524,13 +562,24 @@
         
         /* printk ("setting PLL for PAL/SECAM\n");*/
 
+	set_pll_freq(btv, 28636363, 35468950);
+/*	
         btwrite(0x00,BT848_TGCTRL);
         btwrite(0xf9,BT848_PLL_F_LO);
         btwrite(0xdc,BT848_PLL_F_HI);
-        btwrite(0x8e,BT848_PLL_XCI);
+        btwrite(14|BT848_PLL_X,BT848_PLL_XCI);
+*/
+	/*
+	 *	Let other people run while the PLL stabilizes
+	 */
+	
+	tv=jiffies+HZ/10;	/* .1 seconds */
+	do
+	{
+		schedule();
+	}
+	while(time_before(jiffies,tv));
 
-	/* Ugh ugh ugh .. schedule ? */
-        udelay(100000);
         for (i=0; i<100; i++) 
         {
                 if ((btread(BT848_DSTATUS)&BT848_DSTATUS_PLOCK))
@@ -548,7 +597,8 @@
 
 static void bt848_muxsel(struct bttv *btv, unsigned int input)
 {
-	btwrite(tvcards[btv->type].gpiomask, BT848_GPIO_OUT_EN);
+	btaor(tvcards[btv->type].gpiomask2,~tvcards[btv->type].gpiomask2,
+        	BT848_GPIO_OUT_EN);
 
 	/* This seems to get rid of some synchronization problems */
 	btand(~(3<<5), BT848_IFORM);
@@ -569,23 +619,7 @@
 	audio(btv, (input!=tvcards[btv->type].tuner) ? 
               AUDIO_EXTERN : AUDIO_TUNER);
 	btaor(tvcards[btv->type].muxsel[input]>>4,
-              ~tvcards[btv->type].gpiomask, BT848_GPIO_DATA);
-#if 0
-	if (input==3) 
-	{
-		btor(BT848_CONTROL_COMP, BT848_E_CONTROL);
-		btor(BT848_CONTROL_COMP, BT848_O_CONTROL);
-	}
-	else
-	{
-		btand(~BT848_CONTROL_COMP, BT848_E_CONTROL);
-		btand(~BT848_CONTROL_COMP, BT848_O_CONTROL);
-	}
-	if (input==2)
-		input=3;
-	btaor(((input+2)&3)<<5, ~(3<<5), BT848_IFORM);
-	audio(btv, input ? AUDIO_EXTERN : AUDIO_TUNER);
-#endif
+		~tvcards[btv->type].gpiomask2, BT848_GPIO_DATA);
 }
 
 
@@ -645,27 +679,28 @@
        BT848_COLOR_FMT_RGB15,
        BT848_COLOR_FMT_YUY2,
        BT848_COLOR_FMT_BtYUV,
-       -1,
-       -1,
-       -1,
+       0,
+       0,
+       0,
        BT848_COLOR_FMT_RAW,
        BT848_COLOR_FMT_YCrCb422,
        BT848_COLOR_FMT_YCrCb411,
 };
 #define PALETTEFMT_MAX 11
 
-static int  make_rawrisctab(struct bttv *btv, unsigned int *ro,
+static int make_rawrisctab(struct bttv *btv, unsigned int *ro,
                             unsigned int *re, unsigned int *vbuf)
 {
         unsigned long line;
-	unsigned long bpl=1024;
+	unsigned long bpl=1024;		/* bytes per line */
 	unsigned long vadr=(unsigned long) vbuf;
 
 	*(ro++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1; *(ro++)=0;
 	*(re++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1; *(re++)=0;
   
         /* In PAL 650 blocks of 256 DWORDs are sampled, but only if VDELAY
-           is 2. We'll have to handle this inside the IRQ handler ... */
+           is 2 and without separate VBI grabbing.
+           We'll have to handle this inside the IRQ handler ... */
 
 	for (line=0; line < 640; line++)
 	{
@@ -802,6 +837,152 @@
 	*x+=dx;
 }
 
+static void make_clip_tab(struct bttv *btv, struct video_clip *cr, int ncr)
+{
+	int i,t;
+	int yy, y, x, dx;
+	struct video_clip first, *cur, *cur2, *nx, first2, *prev, *nx2;
+	int bpp, bpl, width, height, inter;
+	unsigned int **rp,*ro,*re;
+	unsigned long adr;
+	int cx,cx2,cy,cy2;
+
+	inter=(btv->win.interlace&1)^1;
+	bpp=btv->win.bpp;
+	bpl=btv->win.bpl;
+	ro=btv->risc_odd;
+	re=btv->risc_even;
+	width=btv->win.width;
+	height=btv->win.height;
+	adr=btv->win.vidadr+btv->win.x*bpp+btv->win.y*bpl;
+
+	/* clip clipping rects against viewing window AND screen 
+	   so we do not have to rely on the user program
+	 */
+	cx=(btv->win.x<0) ? (-btv->win.x) : 0;
+	cy=(btv->win.y<0) ? (-btv->win.y) : 0;
+	cx2=(btv->win.x+width>btv->win.swidth) ? 
+	        (btv->win.swidth-btv->win.x) : width;
+	cy2=(btv->win.y+height>btv->win.sheight) ? 
+	        (btv->win.sheight-btv->win.y) : height;
+	first.next=NULL;
+	for (i=0; i<ncr; i++)
+	{
+                if ((t=cy-cr[i].y)>0)
+		{
+		        if (cr[i].height<=t)
+			        continue;
+                        cr[i].height-=t;
+			cr[i].y=cy;
+		} 
+		if ((t=cy2-cr[i].y)<cr[i].height) 
+		{
+		        if (t<=0)
+			        continue;
+			cr[i].height=t;
+		}
+                if ((t=cx-cr[i].x)>0)
+		{
+		        if (cr[i].width<=t)
+			        continue;
+                        cr[i].width-=t;
+			cr[i].x=cx;
+		} 
+		if ((t=cx2-cr[i].x)<cr[i].width) 
+		{
+		        if (t<=0)
+			        continue;
+			cr[i].width=t;
+		}
+	        cur=&first;
+		while ((nx=cur->next) && (cr[i].y > cur->next->y))
+		        cur=nx; 
+		cur->next=&(cr[i]);
+		cr[i].next=nx;
+	}
+	first2.next=NULL;
+	
+	*(ro++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1; *(ro++)=0;
+	*(re++)=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1; *(re++)=0;
+	
+	/* loop through all lines */
+	for (yy=0; yy<(height<<inter); yy++) 
+        {
+                y=yy>>inter;
+                rp= (yy&1) ? &re : &ro;
+	  
+                /* remove rects with y2 > y */
+                if ((cur=first2.next))
+                {
+                        prev=&first2;
+                        do
+                        {
+                                if (cur->y+cur->height <= y) 
+                                        prev->next=cur->next;
+                                else
+                                        prev=cur;
+                        } 
+                        while ((cur=cur->next));
+                }
+                
+                /* add rect to second (x-sorted) list if rect.y == y  */
+                if ((cur=first.next))
+                {
+                        while ((cur) && (cur->y == y))
+                        { 
+                                first.next=cur->next;
+                                cur2=&first2;
+                                while ((nx2=cur2->next) && (cur->x > cur2->next->x)) 
+                                        cur2=nx2; 
+                                cur2->next=cur;
+                                cur->next=nx2;
+                                cur=first.next;
+                        }
+                }
+                x=0;
+                if ((btv->win.y+y<=0)||(btv->win.y+y>=btv->win.sheight))
+                        write_risc_segment(rp, adr, BT848_RISC_SKIP, &x,
+                                           width, bpp, width);
+                else 
+                {
+                        dx=cx;
+                        for (cur2=first2.next; cur2; cur2=cur2->next)
+                        {
+                                if (x+dx < cur2->x)
+                                {
+                                        write_risc_segment(rp, adr, BT848_RISC_SKIP,
+                                                           &x, dx, bpp, width);
+                                        dx=cur2->x-x;
+                                        write_risc_segment(rp, adr, BT848_RISC_WRITEC,
+                                                           &x, dx, bpp, width);
+                                        dx=cur2->width;
+                                }
+                                else if (x+dx < cur2->x+cur2->width) 
+                                        dx=cur2->x+cur2->width-x; 
+                        }
+                        if (cx2<width)
+                        {
+                                write_risc_segment(rp, adr, BT848_RISC_SKIP,
+                                                   &x, dx, bpp, width);
+                                write_risc_segment(rp, adr, BT848_RISC_WRITEC,
+                                                   &x, cx2-x, bpp, width);
+                                dx=width-x;
+                        }
+                        write_risc_segment(rp, adr, BT848_RISC_SKIP,
+                                           &x, dx, bpp, width);
+                        write_risc_segment(rp, adr, BT848_RISC_WRITEC,
+                                           &x, width-x, bpp, width);
+                }
+                if ((!inter)||(yy&1))
+                        adr+=bpl;
+	}
+        
+        *(ro++)=BT848_RISC_JUMP;
+	*(ro++)=btv->bus_vbi_even;
+	*(re++)=BT848_RISC_JUMP;
+	*(re++)=btv->bus_vbi_odd;
+}
+
 
 /*
  *	Set the registers for the size we have specified. Don't bother
@@ -814,36 +995,50 @@
  
 struct tvnorm 
 {
-        u16 cropwidth, cropheight;
+        u32 Fsc;
+        u16 swidth, sheight; /* scaled standard width, height */
 	u16 totalwidth;
 	u8 adelay, bdelay, iform;
 	u32 scaledtwidth;
 	u16 hdelayx1, hactivex1;
-	u16 vdelay;
+	u16 vdelay, fporch;
 };
 
 static struct tvnorm tvnorms[] = {
 	/* PAL-BDGHI */
-        { 768, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1),
-	    944, 186, 922, 0x20},
+        /* max. active video is actually 922, but 924 is divisible by 4 and 3! */
+        { 35468950,
+          924, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1),
+          1135, 186, 924, 0x20},
+/*
+        { 35468950, 
+          768, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_BDGHI|BT848_IFORM_XT1),
+	  944, 186, 922, 0x20},
+*/
 	/* NTSC */
-	{ 640, 480,  910, 0x68, 0x5d, (BT848_IFORM_NTSC|BT848_IFORM_XT0),
-	    780, 135, 754, 0x16},
+	{ 28636363,
+          640, 480,  910, 0x68, 0x5d, (BT848_IFORM_NTSC|BT848_IFORM_XT0),
+          780, 135, 754, 0x1a},
 	/* SECAM */
-	{ 768, 576, 1135, 0x7f, 0xb0, (BT848_IFORM_SECAM|BT848_IFORM_XT1),
-	    944, 186, 922, 0x20},
+	{ 28636363, 
+          640, 480, 910, 0x68, 0x5d, (BT848_IFORM_PAL_M|BT848_IFORM_XT0),
+	  780, 135, 754, 0x16},
 	/* PAL-M */
-	{ 640, 480, 910, 0x68, 0x5d, (BT848_IFORM_PAL_M|BT848_IFORM_XT0),
-	    780, 135, 754, 0x16},
+	{ 28636363, 
+          640, 480, 910, 0x68, 0x5d, (BT848_IFORM_PAL_M|BT848_IFORM_XT0),
+	  780, 135, 754, 0x16},
 	/* PAL-N */
-	{ 768, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_N|BT848_IFORM_XT1),
-	    944, 186, 922, 0x20},
+	{ 35468950, 
+          768, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_N|BT848_IFORM_XT1),
+	  944, 186, 922, 0x20},
 	/* PAL-NC */
-	{ 768, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_NC|BT848_IFORM_XT0),
-	    944, 186, 922, 0x20},
+	{ 35468950, 
+          768, 576, 1135, 0x7f, 0x72, (BT848_IFORM_PAL_NC|BT848_IFORM_XT0),
+	  944, 186, 922, 0x20},
 	/* NTSC-Japan */
-	{ 640, 480,  910, 0x68, 0x5d, (BT848_IFORM_NTSC_J|BT848_IFORM_XT0),
-	    780, 135, 754, 0x16},
+	{ 28636363,
+          640, 480,  910, 0x68, 0x5d, (BT848_IFORM_NTSC_J|BT848_IFORM_XT0),
+	  780, 135, 754, 0x16},
 };
 #define TVNORMS (sizeof(tvnorms)/sizeof(tvnorm))
 
@@ -891,6 +1086,10 @@
 
 	tvn=&tvnorms[btv->win.norm];
 	
+        btv->win.cropheight=tvn->sheight;
+        btv->win.cropwidth=tvn->swidth;
+
+/*
 	if (btv->win.cropwidth>tvn->cropwidth)
                 btv->win.cropwidth=tvn->cropwidth;
 	if (btv->win.cropheight>tvn->cropheight)
@@ -900,7 +1099,7 @@
                 width=btv->win.cropwidth;
 	if (height>btv->win.cropheight)
 	        height=btv->win.cropheight;
-
+*/
 	btwrite(tvn->adelay, BT848_ADELAY);
 	btwrite(tvn->bdelay, BT848_BDELAY);
 	btaor(tvn->iform,~(BT848_IFORM_NORM|BT848_IFORM_XTBOTH), BT848_IFORM);
@@ -916,12 +1115,13 @@
      
 	btv->win.interlace = (height>btv->win.cropheight/2) ? 1 : 0;
 	inter=(btv->win.interlace&1)^1;
+	vdelay=btv->win.cropy+tvn->vdelay;
+
 	xsf = (hactive*tvn->scaledtwidth)/btv->win.cropwidth;
 	hscale = ((tvn->totalwidth*4096UL)/xsf-4096);
-	vdelay=btv->win.cropy+tvn->vdelay;
 
-	hdelay=(tvn->hdelayx1*tvn->scaledtwidth)/tvn->totalwidth;
-	hdelay=((hdelay+btv->win.cropx)*hactive)/btv->win.cropwidth;
+	hdelay=tvn->hdelayx1+btv->win.cropx;
+	hdelay=(hdelay*hactive)/btv->win.cropwidth;
 	hdelay&=0x3fe;
 
 	sr=((btv->win.cropheight>>inter)*512)/height-512;
@@ -948,22 +1148,23 @@
 {
         unsigned short format;
 
-        btv->win.color_fmt=format= (btv->win.depth==15) ? BT848_COLOR_FMT_RGB15 :
-		bpp2fmt[(btv->win.bpp-1)&3];
-                	
+        btv->win.color_fmt = format = 
+                (btv->win.depth==15) ? BT848_COLOR_FMT_RGB15 :
+                        bpp2fmt[(btv->win.bpp-1)&3];
+
 	/*	RGB8 seems to be a 9x5x5 GRB color cube starting at
 	 *	color 16. Why the h... can't they even mention this in the
 	 *	data sheet?  [AC - because it's a standard format so I guess
 	 *	it never occurred to them]
 	 *	Enable dithering in this mode.
 	 */
-#if 0	 
+
 	if (format==BT848_COLOR_FMT_RGB8)
-                btand(~0x10, BT848_CAP_CTL); 
+                btand(~BT848_CAP_CTL_DITH_FRAME, BT848_CAP_CTL); 
 	else
-	        btor(0x10, BT848_CAP_CTL);
-#endif
-        bt848_set_geo(btv,btv->win.width, btv->win.height, format);
+	        btor(BT848_CAP_CTL_DITH_FRAME, BT848_CAP_CTL);
+
+        bt848_set_geo(btv, btv->win.width, btv->win.height, format);
 }
 
 /*
@@ -978,7 +1179,7 @@
 	audio(btv, AUDIO_MUTE);
 	udelay(AUDIO_MUTE_DELAY);
 
-	if (btv->radio) 
+	if (radio[btv->nr]) 
 	{
 		if (btv->have_tuner)
 			i2c_control_device(&(btv->i2c), I2C_DRIVERID_TUNER,
@@ -1027,7 +1228,7 @@
 		if(fbuffer_alloc(btv))
 			return -ENOBUFS;
 	}
-	if(btv->grabbing>1)
+	if(btv->grabbing >= MAX_GBUFFERS)
 		return -ENOBUFS;
 	
 	/*
@@ -1040,9 +1241,16 @@
 	if(mp->height <0 || mp->width <0)
 		return -EINVAL;
 	
+/*      This doesn´t work like this for NTSC anyway.
+        So, better check the total image size ...
+*/
+/*
 	if(mp->height>576 || mp->width>768)
 		return -EINVAL;
-
+*/
+	if (mp->height*mp->width*fmtbppx2[mp->format&0x0f]/2>BTTV_MAX_FBUF)
+		return -EINVAL;
+ 
 	/*
 	 *	FIXME: Check the format of the grab here. This is probably
 	 *	also less restrictive than the normal overlay grabs. Stuff
@@ -1055,27 +1263,31 @@
 	 
 	vbuf=(unsigned int *)(btv->fbuffer+BTTV_MAX_FBUF*mp->frame);
 /*	if (!(btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC))
-                return -EAGAIN; */
+                return -EAGAIN;*/
 	ro=btv->grisc+(((btv->grabcount++)&1) ? 4096 :0);
 	re=ro+2048;
 	btv->gwidth=mp->width;
 	btv->gheight=mp->height;
+
 	if (mp->format > PALETTEFMT_MAX)
 		return -EINVAL;
 	btv->gfmt=palette2fmt[mp->format];
-	if(btv->gfmt==-1)
+	if(btv->gfmt==0)
 		return -EINVAL;
 		
 	make_vrisctab(btv, ro, re, vbuf, btv->gwidth, btv->gheight, btv->gfmt);
 	/* bt848_set_risc_jmps(btv); */
 	btor(3, BT848_CAP_CTL);
 	btor(3, BT848_GPIO_DMA_CTL);
+        btv->frame_stat[mp->frame] = GBUFFER_GRABBING;
         if (btv->grabbing) {
 		btv->gro_next=virt_to_bus(ro);
 		btv->gre_next=virt_to_bus(re);
+                btv->grf_next=mp->frame;
         } else {
 		btv->gro=virt_to_bus(ro);
 		btv->gre=virt_to_bus(re);
+                btv->grf=mp->frame;
         }
 	if (!(btv->grabbing++)) 
 		btv->risc_jmp[12]=BT848_RISC_JUMP|(0x8<<16)|BT848_RISC_IRQ;
@@ -1159,7 +1371,12 @@
 				btv->user--;
 				return -EINVAL;
 			}
-			break;
+                        btv->grabbing = 0;
+                        btv->grab = 0;
+                        btv->lastgrab = 0;
+                        for (i = 0; i < MAX_GBUFFERS; i++)
+				btv->frame_stat[i] = GBUFFER_UNUSED;
+                        break;
 		case 1:
 			break;
 	}
@@ -1227,265 +1444,6 @@
 	btaor(datahi, ~1, BT848_O_CONTROL);
 }
 
-
-/*
- *	Cliprect -> risc table.
- *
- *	FIXME: This is generating wrong code when we have some kinds of
- *	rectangle lists. If you generate overlapped rectangles then it
- *	gets a bit confused. Since we add the frame buffer clip rectangles
- *	we need to fix this. Better yet to rewrite this function.
- */
- 
-static void write_risc_data(struct bttv *btv, struct video_clip *vp, int count)
-{
-	int i;
-	u32 yy, y, x, dx, ox;
-	u32 *rmem, *rmem2;
-	struct video_clip first, *cur, *cur2, *nx, first2, *prev, *nx2;
-	u32 *rp, rpo=0, rpe=0, p, bpsl;
-	u32 *rpp;
-	u32 mask;
-	int interlace;
-	int depth;
-  
-	rmem=(u32 *)btv->risc_odd;
-	rmem2=(u32 *)btv->risc_even;
-	depth=btv->win.bpp;
-  
-	/* create y-sorted list  */
-	
-	first.next=NULL;
-	for (i=0; i<count; i++) 
-	{
-		cur=&first;
-		while ((nx=cur->next) && (vp[i].y > cur->next->y))
-			cur=nx; 
-		cur->next=&(vp[i]);
-		vp[i].next=nx;
-	}
-	first2.next=NULL;
-	
-	rmem[rpo++]=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1|(0xf<<20);
-	rmem[rpo++]=0;
-
-	rmem2[rpe++]=BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1;
-	rmem2[rpe++]=0;
-
-
-	/*
-	 *	32bit depth frame buffers need extra flags setting
-	 */
-	 
-	if (depth==4)
-		mask=BT848_RISC_BYTE3;
-	else
-		mask=0;
-		
-	bpsl=btv->win.width*btv->win.bpp;
-	p=btv->win.vidadr+btv->win.x*btv->win.bpp+
-		btv->win.y*btv->win.bpl;
-
-	interlace=btv->win.interlace;
-
-	/*
-	 *	Loop through all lines 
-	 */
-	 
-	for (yy=0; yy<(btv->win.height<<(1^interlace)); yy++) 
-	{
-		y=yy>>(1^interlace);
-		
-		/*
-		 *	Even or odd frame generation. We have to 
-		 *	write the RISC instructions to the right stream.
-		 */
-		 
-		if(!(y&1))
-		{
-			rp=&rpo;
-			rpp=rmem;
-		}
-		else
-		{
-			rp=&rpe;
-			rpp=rmem2;
-		}
-		
-		
-		/*
-		 *	first2 is the header of a list of "active" rectangles. We add
-		 *	rectangles as we hit their top and remove them as they fall off
-		 *	the bottom
-		 */
-		
-		 /* remove rects with y2 > y */
-		if ((cur=first2.next)) 
-		{
-			prev=&first2;
-			do 
-			{
-				if (cur->y+cur->height < y) 
-					prev->next=cur->next;
-				else
-					prev=cur;
-			}
-			while ((cur=cur->next));
-		}
-
-		/*
-		 *	Fixme - we have to handle overlapped rectangles
-		 *	here, but the overlap might be partial
-		 */
-		 
- 		/* add rect to second (x-sorted) list if rect.y == y  */
-		if ((cur=first.next)) 
-		{
-			while ((cur) && (cur->y == y))
-			{ 
-				first.next=cur->next;
-				cur2=&first2;
-				while ((nx2=cur2->next) && (cur->x > cur2->next->x)) 
-					cur2=nx2; 
-				cur2->next=cur;
-				cur->next=nx2;
-				cur=first.next;
-			}
-		}
-		
-		
-		/*
-		 *	Begin writing the RISC script
-		 */
-    
-		dx=x=0;
-		
-		/*
-		 *	Starting at x position 0 on a new scan line
-		 *	write to location p, don't yet write the number
-		 *	of pixels for the instruction
-		 */
-		 
-		rpp[(*rp)++]=BT848_RISC_WRITE|BT848_RISC_SOL;
-		rpp[(*rp)++]=p;
-		
-		/*
-		 *	For each rectangle we have in the "active" list - sorted left to
-		 *	right..
-		 */
-		 
-		for (cur2=first2.next; cur2; cur2=cur2->next) 
-		{
-			/*
-			 *	If we are to the left of the first drawing area
-			 */
-			 
-			if (x+dx < cur2->x) 
-			{
-				/* Bytes pending ? */
-				if (dx) 
-				{
-					/* For a delta away from the start we need to write a SKIP */
-					if (x) 
-						rpp[(*rp)++]=BT848_RISC_SKIP|(dx*depth);
-					else
-					/* Rewrite the start of line WRITE to a SKIP */
-						rpp[(*rp)-2]|=BT848_RISC_BYTE_ALL|(dx*depth);
-					/* Move X to the next point (drawing start) */
-					x=x+dx;
-				}
-				/* Ok how far are we from the start of the next rectangle ? */
-				dx=cur2->x-x;
-				/* dx is now the size of data to write */
-				
-				/* If this isnt the left edge generate a "write continue" */
-				if (x) 
-					rpp[(*rp)++]=BT848_RISC_WRITEC|(dx*depth)|mask;
-				else
-					/* Fill in the byte count on the initial WRITE */
-					rpp[(*rp)-2]|=(dx*depth)|mask;
-				/* Move to the start of the rectangle */
-				x=cur2->x;
-				/* x is our left dx is byte size of hole */
-				dx=cur2->width+1;
-			}
-			else
-			/* Already in a clip zone.. set dx */
-				if (x+dx < cur2->x+cur2->width) 
-					dx=cur2->x+cur2->width-x+1;
-		}
-		/* now treat the rest of the line */
-		ox=x;
-		if (dx) 
-		{
-			/* Complete the SKIP to eat to the end of the gap */
-			if (x) 
-				rpp[(*rp)++]=BT848_RISC_SKIP|(dx*depth);
-			else
-			/* Rewrite to SKIP start to this point */
-				rpp[(*rp)-2]|=BT848_RISC_BYTE_ALL|(dx*depth);
-			x=x+dx;
-		}
-		
-		/*
-		 *	Not at the right hand edge ?
-		 */
-		 
-		if ((dx=btv->win.width-x)!=0) 
-		{
-			/* Write to edge of display */
-			if (x)
-				rpp[(*rp)++]=BT848_RISC_WRITEC|(dx*depth)|BT848_RISC_EOL|mask;
-			else
-			/* Entire frame is a write - patch first order */
-				rpp[(*rp)-2]|=(dx*depth)|BT848_RISC_EOL|mask;
-		}
-		else
-		{
-			/* End of line if needed */
-			if (ox)
-				rpp[(*rp)-1]|=BT848_RISC_EOL|mask;
-			else 
-			{
-				/* Skip the line : write a SKIP + start/end of line marks */
-				(*rp)--;
-				rpp[(*rp)-1]=BT848_RISC_SKIP|
-				        (btv->win.width*depth)|
-					  BT848_RISC_EOL|BT848_RISC_SOL;
-			}
-		}
-		/*
-		 *	Move the video render pointer on a line 
-		 */
-		if (interlace||(y&1))
-			p+=btv->win.bpl;
-	}
-	
-	/*
-	 *	Attach the interframe jumps
-	 */
-
-	rmem[rpo++]=BT848_RISC_JUMP; 
-	rmem[rpo++]=btv->bus_vbi_even;
-
-	rmem2[rpe++]=BT848_RISC_JUMP;
-	rmem2[rpe++]=btv->bus_vbi_odd;
-}
-
-/*
- *	Helper for adding clips.
- */
-
-static void new_risc_clip(struct video_window *vw, struct video_clip *vcp, int x, int y, int w, int h)
-{
-	vcp[vw->clipcount].x=x;
-	vcp[vw->clipcount].y=y;
-	vcp[vw->clipcount].width=w;
-	vcp[vw->clipcount].height=h;
-	vw->clipcount++;
-}
-
-
 /*
  *	ioctl routine
  */
@@ -1495,7 +1453,7 @@
 {
 	unsigned char eedata[256];
 	struct bttv *btv=(struct bttv *)dev;
-  	static int lastchan=0;
+ 	int i;
   	
 	switch (cmd)
 	{	
@@ -1510,8 +1468,8 @@
 				VID_TYPE_CLIPPING|
 				VID_TYPE_FRAMERAM|
 				VID_TYPE_SCALES;
-			b.channels = 4; /* tv  , input, svhs */
-			b.audios = 4; /* tv, input, svhs */
+			b.channels = tvcards[btv->type].inputs;
+			b.audios = tvcards[btv->type].inputs;
 			b.maxwidth = 768;
 			b.maxheight = 576;
 			b.minwidth = 32;
@@ -1528,26 +1486,21 @@
 			v.flags=VIDEO_VC_AUDIO;
 			v.tuners=0;
 			v.type=VIDEO_TYPE_CAMERA;
-			switch(v.channel)
-			{
-				case 0:
-					strcpy(v.name,"Television");
-					v.flags|=VIDEO_VC_TUNER;
-					v.type=VIDEO_TYPE_TV;
-					v.tuners=1;
-					break;
-				case 1:
-					strcpy(v.name,"Composite1");
-					break;
-				case 2:
-					strcpy(v.name,"Composite2");
-					break;
-				case 3:
-					strcpy(v.name,"SVHS");
-					break;
-				default:
-					return -EINVAL;
-			}
+			v.norm = btv->win.norm;
+                        if (v.channel>=tvcards[btv->type].inputs)
+                                return -EINVAL;
+                        if(v.channel==tvcards[btv->type].tuner) 
+                        {
+                                strcpy(v.name,"Television");
+                                v.flags|=VIDEO_VC_TUNER;
+                                v.type=VIDEO_TYPE_TV;
+                                v.tuners=1;
+                        } 
+                        else if(v.channel==tvcards[btv->type].svhs) 
+                                strcpy(v.name,"SVHS");
+                        else
+                                sprintf(v.name,"Composite%d",v.channel);
+
 			if(copy_to_user(arg,&v,sizeof(v)))
 				return -EFAULT;
 			return 0;
@@ -1557,11 +1510,19 @@
 		 */
 		case VIDIOCSCHAN:
 		{
-			int v;
-			if(copy_from_user(&v, arg, sizeof(v)))
+			struct video_channel v;
+			if(copy_from_user(&v, arg,sizeof(v)))
 				return -EFAULT;
-			bt848_muxsel(btv, v);
-			lastchan=v;
+                        
+                        if (v.channel>tvcards[btv->type].inputs)
+                                return -EINVAL;
+			bt848_muxsel(btv, v.channel);
+			if(v.norm!=VIDEO_MODE_PAL&&v.norm!=VIDEO_MODE_NTSC
+			   &&v.norm!=VIDEO_MODE_SECAM)
+				return -EOPNOTSUPP;
+			btv->win.norm = v.norm;
+			bt848_set_winsize(btv);
+			btv->channel=v.channel;
 			return 0;
 		}
 		case VIDIOCGTUNER:
@@ -1569,7 +1530,7 @@
 			struct video_tuner v;
 			if(copy_from_user(&v,arg,sizeof(v))!=0)
 				return -EFAULT;
-			if(v.tuner||lastchan)	/* Only tuner 0 */
+			if(v.tuner||btv->channel)	/* Only tuner 0 */
 				return -EINVAL;
 			strcpy(v.name, "Television");
 			v.rangelow=0;
@@ -1581,23 +1542,22 @@
 				return -EFAULT;
 			return 0;
 		}
-		/* We have but tuner 0 */
+		/* We have but one tuner */
 		case VIDIOCSTUNER:
 		{
 			struct video_tuner v;
 			if(copy_from_user(&v, arg, sizeof(v)))
 				return -EFAULT;
-			/* Only channel 0 has a tuner */
-			if(v.tuner!=0 || lastchan)
-				return -EINVAL;
+
+			/* Only one channel has a tuner */
+                        if(v.tuner!=tvcards[btv->type].tuner)
+ 				return -EINVAL;
+ 				
 			if(v.mode!=VIDEO_MODE_PAL&&v.mode!=VIDEO_MODE_NTSC
 			   &&v.mode!=VIDEO_MODE_SECAM)
 				return -EOPNOTSUPP;
-			/* FIXME: norm should be in video_channel struct 
-			   composite source can have different norms too
-			 */
-			btv->win.norm = v.mode;
-			bt848_set_winsize(btv);
+ 			btv->win.norm = v.mode;
+ 			bt848_set_winsize(btv);
 			return 0;
 		}
 		case VIDIOCGPICT:
@@ -1682,24 +1642,7 @@
 				return -ENOMEM;
 			if(vw.clipcount && copy_from_user(vcp,vw.clips,sizeof(struct video_clip)*vw.clipcount))
 				return -EFAULT;
-			/*
-			 *	Impose display clips
-			 */
-			if(btv->win.x<0)
-				new_risc_clip(&vw, vcp, 0, 0, -btv->win.x, btv->win.height-1);
-			if(btv->win.y<0)
-				new_risc_clip(&vw, vcp, 0, 0, btv->win.width-1,-btv->win.y);
-			if(btv->win.x+btv->win.width> btv->win.swidth)
-				new_risc_clip(&vw, vcp, btv->win.swidth-btv->win.x, 0, btv->win.width-1, btv->win.height-1);
-			if(btv->win.y+btv->win.height > btv->win.sheight)
-				new_risc_clip(&vw, vcp, 0, btv->win.sheight-btv->win.y, btv->win.width-1, btv->win.height-1);
-			/*
-			 *	Question: Do we need to walk the clip list
-			 *	and saw off any clips outside the window 
-			 *	frame or will write_risc_tab do the right
-			 *	thing ?
-			 */
-			write_risc_data(btv,vcp, vw.clipcount);
+			make_clip_tab(btv,vcp, vw.clipcount);
 			vfree(vcp);
 			if(on && btv->win.vidadr!=0)
 				bt848_cap(btv,1);
@@ -1764,7 +1707,7 @@
 	                btv->win.vidadr=(unsigned long)v.base;
 			btv->win.sheight=v.height;
 			btv->win.swidth=v.width;
-			btv->win.bpp=((v.depth+1)&0x38)/8;
+			btv->win.bpp=((v.depth+7)&0x38)/8;
 			btv->win.depth=v.depth;
 			btv->win.bpl=v.bytesperline;
 			
@@ -1832,8 +1775,8 @@
 				return -EFAULT;
 			if(v.flags&VIDEO_AUDIO_MUTE)
 				audio(btv, AUDIO_MUTE);
-			/* One audio source per tuner */
-			if(v.audio!=0)
+ 			/* One audio source per tuner */
+ 			if(v.audio!=0)
 				return -EINVAL;
 			bt848_muxsel(btv,v.audio);
 			if(!(v.flags&VIDEO_AUDIO_MUTE))
@@ -1858,12 +1801,19 @@
 		}
 
 	        case VIDIOCSYNC:
-	        	if (!btv->grabbing)
-	        		return -EAGAIN;
-		        if (btv->grab==btv->lastgrab)
-			        interruptible_sleep_on(&btv->capq);
-		        btv->lastgrab++;
-		        return 0;
+			if(copy_from_user((void *)&i,arg,sizeof(int)))
+				return -EFAULT;
+                        switch (btv->frame_stat[i]) {
+                        case GBUFFER_UNUSED:
+                                return -EINVAL;
+                        case GBUFFER_GRABBING:
+ 			        interruptible_sleep_on(&btv->capq);
+                                /* fall */
+                        case GBUFFER_DONE:
+                                btv->frame_stat[i] = GBUFFER_UNUSED;
+                                break;
+                        }
+                        return 0;
 
 		case BTTV_WRITEE:
 			if(!capable(CAP_SYS_ADMIN))
@@ -1881,11 +1831,19 @@
 				return -EFAULT;
 			break;
 
+		case BTTV_FIELDNR:
+			if(copy_to_user((void *) arg, (void *) &btv->last_field, 
+                                        sizeof(btv->last_field)))
+				return -EFAULT;
+                        break;
+
 	        case VIDIOCMCAPTURE:
 		{
                         struct video_mmap vm;
 			if(copy_from_user((void *) &vm, (void *) arg, sizeof(vm)))
 				return -EFAULT;
+                        if (btv->frame_stat[vm.frame] == GBUFFER_GRABBING)
+                                return -EBUSY;
 		        return vgrab(btv, &vm);
 		}
 		
@@ -2127,21 +2085,34 @@
 static int radio_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
 {
         struct bttv *btv=(struct bttv *)(dev-1);
-  	static int lastchan=0;
 	switch (cmd) {	
 	case VIDIOCGCAP:
-		/* XXX */
+	{
+		struct video_capability v;
+		strcpy(v.name,btv->video_dev.name);
+		v.type = VID_TYPE_TUNER;
+		v.channels = 1;
+		v.audios = 1;
+		/* No we don't do pictures */
+		v.maxwidth = 0;
+		v.maxheight = 0;
+		v.minwidth = 0;
+		v.minheight = 0;
+		if (copy_to_user(arg, &v, sizeof(v)))
+			return -EFAULT;
+		return 0;
 		break;
+	}
 	case VIDIOCGTUNER:
 	{
 		struct video_tuner v;
 		if(copy_from_user(&v,arg,sizeof(v))!=0)
 			return -EFAULT;
-		if(v.tuner||lastchan)	/* Only tuner 0 */
+		if(v.tuner||btv->channel)	/* Only tuner 0 */
 			return -EINVAL;
 		strcpy(v.name, "Radio");
 		v.rangelow=(int)(87.5*16);
-		v.rangehigh=(int)(108.0*16);
+		v.rangehigh=(int)(108*16);
 		v.flags= 0; /* XXX */
 		v.mode = 0; /* XXX */
 		if(copy_to_user(arg,&v,sizeof(v)))
@@ -2154,7 +2125,7 @@
 		if(copy_from_user(&v, arg, sizeof(v)))
 			return -EFAULT;
 		/* Only channel 0 has a tuner */
-		if(v.tuner!=0 || lastchan)
+		if(v.tuner!=0 || btv->channel)
 			return -EINVAL;
 		/* XXX anything to do ??? */
 		return 0;
@@ -2198,6 +2169,8 @@
 };
 
 static struct vidbases vbs[] = {
+	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_215CT222,
+                "ATI MACH64 CT", PCI_BASE_ADDRESS_0},
 	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_210888GX,
 		"ATI MACH64 Winturbo", PCI_BASE_ADDRESS_0},
  	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_215GT,
@@ -2214,8 +2187,12 @@
 	{ PCI_VENDOR_ID_MATROX, 0x051a, "Matrox Mystique", PCI_BASE_ADDRESS_1},
 	{ PCI_VENDOR_ID_N9, PCI_DEVICE_ID_N9_I128, 
 		"Number Nine Imagine 128", PCI_BASE_ADDRESS_0},
+	{ PCI_VENDOR_ID_N9, PCI_DEVICE_ID_N9_I128_2, 
+		"Number Nine Imagine 128 Series 2", PCI_BASE_ADDRESS_0},
 	{ PCI_VENDOR_ID_S3, 0, "S3", PCI_BASE_ADDRESS_0},
 	{ PCI_VENDOR_ID_TSENG, 0, "TSENG", PCI_BASE_ADDRESS_0},
+	{ PCI_VENDOR_ID_NVIDIA_SGS, PCI_DEVICE_ID_NVIDIA_SGS_RIVA128,
+                "Riva128", PCI_BASE_ADDRESS_1},
 };
 
 
@@ -2409,13 +2386,16 @@
 
 /* Figure out card and tuner type */
 
-static void idcard(struct bttv *btv)
+static void idcard(int i)
 {
+        struct bttv *btv = &bttvs[i];
+
+	int tunertype;
 	btwrite(0, BT848_GPIO_OUT_EN);
-	DEBUG(printk(KERN_DEBUG "bttv: GPIO: 0x%08x\n", btread(BT848_GPIO_DATA)));
+	DEBUG(printk(KERN_DEBUG "bttv%d: GPIO: 0x%08x\n", i, btread(BT848_GPIO_DATA)));
 
 	/* Default the card to the user-selected one. */
-	btv->type=card;
+	btv->type=card[i];
         btv->tuner_type=-1; /* use default tuner type */
 
 	/* If we were asked to auto-detect, then do so! 
@@ -2440,13 +2420,13 @@
         if (I2CRead(&(btv->i2c), I2C_TDA9850) >=0)
         {
         	btv->audio_chip = TDA9850;
-        	printk(KERN_INFO "bttv: audio chip: TDA9850\n");
+        	printk(KERN_INFO "bttv%d: audio chip: TDA9850\n", i);
         }
 
         if (I2CRead(&(btv->i2c), I2C_TDA8425) >=0)
         {
             btv->audio_chip = TDA8425;
-            printk("bttv: audio chip: TDA8425\n");
+            printk("bttv%d: audio chip: TDA8425\n", i);
         }
         
         switch(btv->audio_chip)
@@ -2460,11 +2440,18 @@
         }
 
 	/* How do I detect the tuner type for other cards but Miro ??? */
-	printk(KERN_INFO "bttv: model: ");
+	printk(KERN_INFO "bttv%d: model: ", btv->nr);
 	switch (btv->type) 
 	{
 		case BTTV_MIRO:
 			printk("MIRO\n");
+			if (btv->have_tuner) 
+			{
+				tunertype=((btread(BT848_GPIO_DATA)>>10)-1)&7;
+				i2c_control_device(&(btv->i2c),
+						   I2C_DRIVERID_TUNER,
+						   TUNER_SET_TYPE,&tunertype);
+			}
 			strcpy(btv->video_dev.name,"BT848(Miro)");
 			break;
 		case BTTV_HAUPPAUGE:
@@ -2558,8 +2545,18 @@
 
 	/* reset the bt848 */
 	btwrite(0, BT848_SRESET);
+	DEBUG(printk(KERN_DEBUG "bttv%d: bt848_mem: 0x%08x\n",i,(unsigned int) btv->bt848_mem));
 
-	DEBUG(printk(KERN_DEBUG "bttv: bt848_mem: 0x%08x\n",(unsigned int) btv->bt848_mem));
+#ifdef RESET_MSP_HAUPPAUGE
+        /* Reset the MSP on some Hauppauge cards */
+        /* Thanks to Kyösti Mälkki (kmalkki@cc.hut.fi)! */
+        /* Can this hurt cards without one? What about Miros with MSP? */
+        btaor(32, ~32, BT848_GPIO_OUT_EN);
+        btaor(0, ~32, BT848_GPIO_DATA);
+        udelay(2500);
+        btaor(32, ~32, BT848_GPIO_DATA);
+        btaor(0, ~32, BT848_GPIO_OUT_EN);
+#endif
 
 	/* default setup for max. PAL size in a 1024xXXX hicolor framebuffer */
 
@@ -2591,6 +2588,7 @@
 	btv->grabcount=0;
 	btv->grab=0;
 	btv->lastgrab=0;
+        btv->field=btv->last_field=0;
 
 	/* i2c */
 	memcpy(&(btv->i2c),&bttv_i2c_bus_template,sizeof(struct i2c_bus));
@@ -2642,8 +2640,8 @@
 	btwrite(0xd8, BT848_CONTRAST_LO);
 	bt848_bright(btv, 0x10);
 
-	btwrite(0x60, BT848_E_VSCALE_HI);
-	btwrite(0x60, BT848_O_VSCALE_HI);
+	btwrite(0x20, BT848_E_VSCALE_HI);
+	btwrite(0x20, BT848_O_VSCALE_HI);
 	btwrite(/*BT848_ADC_SYNC_T|*/
 		BT848_ADC_RESERVED|BT848_ADC_CRUSH, BT848_ADC);
 
@@ -2662,9 +2660,10 @@
 	btwrite(0xfffffUL, BT848_INT_STAT);
         
 	/* set interrupt mask */
-	btwrite(triton1|
-/*	        BT848_INT_PABORT|BT848_INT_RIPERR|BT848_INT_PPERR|
-		BT848_INT_FDSR|BT848_INT_FTRGT|BT848_INT_FBUS|*/
+	btwrite(btv->triton1|
+                /*BT848_INT_PABORT|BT848_INT_RIPERR|BT848_INT_PPERR|
+                  BT848_INT_FDSR|BT848_INT_FTRGT|BT848_INT_FBUS|*/
+                BT848_INT_VSYNC|
 		BT848_INT_SCERR|
 		BT848_INT_RISCI|BT848_INT_OCERR|BT848_INT_VPRES|
 		BT848_INT_FMTCHG|BT848_INT_HLOCK,
@@ -2680,7 +2679,7 @@
 	memcpy(&btv->video_dev,&bttv_template, sizeof(bttv_template));
 	memcpy(&btv->vbi_dev,&vbi_template, sizeof(vbi_template));
 	memcpy(&btv->radio_dev,&radio_template,sizeof(radio_template));
-	idcard(btv);
+	idcard(i);
 
 	if(video_register_device(&btv->video_dev,VFL_TYPE_GRABBER)<0)
 		return -1;
@@ -2689,7 +2688,7 @@
 	        video_unregister_device(&btv->video_dev);
 		return -1;
 	}
-	if (radio)
+	if (radio[i])
 	{
 		if(video_register_device(&btv->radio_dev, VFL_TYPE_RADIO)<0) 
                 {
@@ -2720,28 +2719,28 @@
 		if (!astat)
 			return;
 		btwrite(astat,BT848_INT_STAT);
-		IDEBUG(printk ("bttv: astat %08x\n",astat));
-		IDEBUG(printk ("bttv:  stat %08x\n",stat));
+		IDEBUG(printk ("bttv%d: astat %08x\n", btv->nr, astat));
+		IDEBUG(printk ("bttv%d:  stat %08x\n", btv->nr, stat));
 
 		/* get device status bits */
 		dstat=btread(BT848_DSTATUS);
     
 		if (astat&BT848_INT_FMTCHG) 
 		{
-			IDEBUG(printk ("bttv: IRQ_FMTCHG\n"));
+			IDEBUG(printk ("bttv%d: IRQ_FMTCHG\n", btv->nr));
 			/*btv->win.norm&=
 			  (dstat&BT848_DSTATUS_NUML) ? (~1) : (~0); */
 		}
 		if (astat&BT848_INT_VPRES) 
 		{
-			IDEBUG(printk ("bttv: IRQ_VPRES\n"));
+			IDEBUG(printk ("bttv%d: IRQ_VPRES\n", btv->nr));
 		}
 		if (astat&BT848_INT_VSYNC) 
 		{
-			IDEBUG(printk ("bttv: IRQ_VSYNC\n"));
+			IDEBUG(printk ("bttv%d: IRQ_VSYNC\n", btv->nr));
 		}
 		if (astat&BT848_INT_SCERR) {
-			IDEBUG(printk ("bttv: IRQ_SCERR\n"));
+			IDEBUG(printk ("bttv%d: IRQ_SCERR\n", btv->nr));
 			bt848_dma(btv, 0);
 			bt848_dma(btv, 1);
 			wake_up_interruptible(&btv->vbiq);
@@ -2750,7 +2749,7 @@
 		}
 		if (astat&BT848_INT_RISCI) 
 		{
-			IDEBUG(printk ("bttv: IRQ_RISCI\n"));
+			IDEBUG(printk ("bttv%d: IRQ_RISCI\n", btv->nr));
 
 			/* captured VBI frame */
 			if (stat&(1<<28)) 
@@ -2763,10 +2762,14 @@
 			if (stat&(2<<28)) 
 			{
 				wake_up_interruptible(&btv->capq);
+                                btv->last_field=btv->field;
+                                btv->grab++;
+                                btv->frame_stat[btv->grf] = GBUFFER_DONE;
 			        if ((--btv->grabbing))
 				{
 					btv->gro = btv->gro_next;
 					btv->gre = btv->gre_next;
+					btv->grf = btv->grf_next;
                                         btv->risc_jmp[5]=btv->gro;
 					btv->risc_jmp[11]=btv->gre;
 					bt848_set_geo(btv, btv->gwidth,
@@ -2792,31 +2795,31 @@
 		}
 		if (astat&BT848_INT_OCERR) 
 		{
-			IDEBUG(printk ("bttv: IRQ_OCERR\n"));
+			IDEBUG(printk ("bttv%d: IRQ_OCERR\n", btv->nr));
 		}
 		if (astat&BT848_INT_PABORT) 
 		{
-			IDEBUG(printk ("bttv: IRQ_PABORT\n"));
+			IDEBUG(printk ("bttv%d: IRQ_PABORT\n", btv->nr));
 		}
 		if (astat&BT848_INT_RIPERR) 
 		{
-			IDEBUG(printk ("bttv: IRQ_RIPERR\n"));
+			IDEBUG(printk ("bttv%d: IRQ_RIPERR\n", btv->nr));
 		}
 		if (astat&BT848_INT_PPERR) 
 		{
-			IDEBUG(printk ("bttv: IRQ_PPERR\n"));
+			IDEBUG(printk ("bttv%d: IRQ_PPERR\n", btv->nr));
 		}
 		if (astat&BT848_INT_FDSR) 
 		{
-			IDEBUG(printk ("bttv: IRQ_FDSR\n"));
+			IDEBUG(printk ("bttv%d: IRQ_FDSR\n", btv->nr));
 		}
 		if (astat&BT848_INT_FTRGT) 
 		{
-			IDEBUG(printk ("bttv: IRQ_FTRGT\n"));
+			IDEBUG(printk ("bttv%d: IRQ_FTRGT\n", btv->nr));
 		}
 		if (astat&BT848_INT_FBUS) 
 		{
-			IDEBUG(printk ("bttv: IRQ_FBUS\n"));
+			IDEBUG(printk ("bttv%d: IRQ_FBUS\n", btv->nr));
 		}
 		if (astat&BT848_INT_HLOCK) 
 		{
@@ -2832,12 +2835,12 @@
     
 		count++;
 		if (count > 10)
-			printk (KERN_WARNING "bttv: irq loop %d\n", count);
+			printk (KERN_WARNING "bttv%d: irq loop %d\n", btv->nr, count);
 		if (count > 20) 
 		{
 			btwrite(0, BT848_INT_MASK);
 			printk(KERN_ERR 
-			       "bttv: IRQ lockup, cleared int mask\n");
+			       "bttv%d: IRQ lockup, cleared int mask\n", btv->nr);
 		}
 	}
 }
@@ -2847,120 +2850,132 @@
 /*
  *	Scan for a Bt848 card, request the irq and map the io memory 
  */
- 
-static int find_bt848(void)
+
+int configure_bt848(struct pci_dev *dev, int bttv_num)
 {
-	unsigned char command, latency;
 	int result;
+	unsigned char bus, devfn, command;
 	struct bttv *btv;
-	struct pci_dev *dev;
 
-	bttv_num=0;
+        btv=&bttvs[bttv_num];
+        btv->dev=dev;
+        btv->nr = bttv_num;
+        btv->bus=bus=dev->bus->number;
+        btv->devfn=devfn=dev->devfn;
+        btv->bt848_mem=NULL;
+        btv->vbibuf=NULL;
+        btv->risc_jmp=NULL;
+        btv->vbi_odd=NULL;
+        btv->vbi_even=NULL;
+        btv->vbiq=NULL;
+        btv->capq=NULL;
+        btv->capqo=NULL;
+        btv->capqe=NULL;
+        btv->vbip=VBIBUF_SIZE;
+
+        btv->id=dev->device;
+        btv->irq=dev->irq;
+        btv->bt848_adr=dev->base_address[0];
+        if (btv->id >= 878)
+                btv->i2c_command = 0x83;                   
+        else
+                btv->i2c_command=(I2C_TIMING | BT848_I2C_SCL | BT848_I2C_SDA);
 
-	if (!pcibios_present()) 
-	{
-		DEBUG(printk(KERN_DEBUG "bttv: PCI-BIOS not present or not accessible!\n"));
-		return 0;
-	}
-	for (dev = pci_devices; dev != NULL; dev = dev->next) 
-	{
-		if (dev->vendor != PCI_VENDOR_ID_BROOKTREE)
-			continue;
-		if (dev->device != PCI_DEVICE_ID_BT849 &&
-			dev->device != PCI_DEVICE_ID_BT848)
-			continue;
-
-		/* Ok, Bt848 or Bt849 found! */
-		btv=&bttvs[bttv_num];
-		btv->dev=dev;
-		btv->bt848_mem=NULL;
-		btv->vbibuf=NULL;
-		btv->risc_jmp=NULL;
-		btv->vbi_odd=NULL;
-		btv->vbi_even=NULL;
-		btv->vbiq=NULL;
-		btv->capq=NULL;
-		btv->capqo=NULL;
-		btv->capqe=NULL;
-
-		btv->vbip=VBIBUF_SIZE;
+        if (remap[bttv_num])
+        {
+                if (remap[bttv_num] < 0x1000)
+                        remap[bttv_num]<<=20;
+                remap[bttv_num]&=PCI_BASE_ADDRESS_MEM_MASK;
+                printk(KERN_INFO "bttv%d: remapping to : 0x%08x.\n",
+                       bttv_num,remap[bttv_num]);
+                remap[bttv_num]|=btv->bt848_adr&(~PCI_BASE_ADDRESS_MEM_MASK);
+                pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, remap[bttv_num]);
+                pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &btv->bt848_adr);
+                btv->dev->base_address[0] = btv->bt848_adr;
+        }					
+        btv->bt848_adr&=PCI_BASE_ADDRESS_MEM_MASK;
+        pci_read_config_byte(dev, PCI_CLASS_REVISION, &btv->revision);
+        printk(KERN_INFO "bttv%d: Brooktree Bt%d (rev %d) ",
+               bttv_num,btv->id, btv->revision);
+        printk("bus: %d, devfn: %d, ",
+               btv->bus, btv->devfn);
+        printk("irq: %d, ",btv->irq);
+        printk("memory: 0x%08x.\n", btv->bt848_adr);
+        
+        btv->pll=0;
+        if(pll[btv->nr])
+                if (!(btv->id==848 && btv->revision==0x11))
+                {
+                        printk(KERN_INFO "bttv%d: internal PLL, single crystal operation enabled\n",bttv_num);
+                        btv->pll=1;
+                }
+        
+        btv->bt848_mem=ioremap(btv->bt848_adr, 0x1000);
+        
+	/* clear interrupt mask */
+	btwrite(0, BT848_INT_MASK);
 
-		pci_read_config_word (btv->dev, PCI_DEVICE_ID,      &btv->id);
+        result = request_irq(btv->irq, bttv_irq,
+                             SA_SHIRQ | SA_INTERRUPT,"bttv",(void *)btv);
+        if (result==-EINVAL) 
+        {
+                printk(KERN_ERR "bttv%d: Bad irq number or handler\n",
+                       bttv_num);
+                return -EINVAL;
+        }
+        if (result==-EBUSY)
+        {
+                printk(KERN_ERR "bttv%d: IRQ %d busy, change your PnP config in BIOS\n",bttv_num,btv->irq);
+                return result;
+        }
+        if (result < 0) 
+                return result;
+        
+        pci_set_master(dev);
 
-		/* pci_read_config_dword(btv->dev, PCI_BASE_ADDRESS_0, &btv->bt848_adr); */
-		btv->bt848_adr = btv->dev->base_address[0];
-    
-		if (remap&&(!bttv_num))
-		{ 
-			remap<<=20;
-			remap&=PCI_BASE_ADDRESS_MEM_MASK;
-			printk(KERN_INFO "Remapping to : 0x%08x.\n", remap);
-			remap|=btv->bt848_adr&(~PCI_BASE_ADDRESS_MEM_MASK);
-			pci_write_config_dword(btv->dev, PCI_BASE_ADDRESS_0, remap);
-			pci_read_config_dword(btv->dev,  PCI_BASE_ADDRESS_0, &btv->bt848_adr);
-			btv->dev->base_address[0] = btv->bt848_adr;
-		}					
-    
-		btv->bt848_adr&=PCI_BASE_ADDRESS_MEM_MASK;
-		pci_read_config_byte(btv->dev, PCI_CLASS_REVISION,
-			     &btv->revision);
-		printk(KERN_INFO "bttv: Brooktree Bt%d (rev %d) ",
-			btv->id, btv->revision);
-		printk("bus: %d, devfn: %d, ",
-			btv->dev->bus->number, btv->dev->devfn);
-		printk("irq: %d, ",btv->dev->irq);
-		printk("memory: 0x%08x.\n", btv->bt848_adr);
-    
-    		btv->pll = 0;
-#ifdef USE_PLL
-                if (btv->id==849 || (btv->id==848 && btv->revision==0x12))
+        btv->triton1=triton1 ? BT848_INT_ETBF : 0;
+        if (triton1 && btv->id >= 878) 
+        {
+                btv->triton1 = 0;
+                printk("bttv: Enabling 430FX compatibilty for bt878\n");
+                pci_read_config_byte(dev, BT878_DEVCTRL, &command);
+                command|=BT878_EN_TBFX;
+                pci_write_config_byte(dev, BT878_DEVCTRL, command);
+                pci_read_config_byte(dev, BT878_DEVCTRL, &command);
+                if (!(command&BT878_EN_TBFX)) 
                 {
-                        printk(KERN_INFO "bttv: internal PLL, single crystal operation enabled.\n");
-                        btv->pll=1;
+                        printk("bttv: 430FX compatibility could not be enabled\n");
+                        return -1;
                 }
-#endif
-                
-		btv->bt848_mem=ioremap(btv->bt848_adr, 0x1000);
+        }
+        
+        return 0;
+}
 
-		result = request_irq(btv->dev->irq, bttv_irq,
-			SA_SHIRQ | SA_INTERRUPT,"bttv",(void *)btv);
-		if (result==-EINVAL) 
-		{
-			printk(KERN_ERR "bttv: Bad irq number or handler\n");
-			return -EINVAL;
-		}
-		if (result==-EBUSY)
-		{
-			printk(KERN_ERR "bttv: IRQ %d busy, change your PnP config in BIOS\n",btv->dev->irq);
-			return result;
-		}
-		if (result < 0) 
-			return result;
+static int find_bt848(void)
+{
+        struct pci_dev *dev = pci_devices;
+        int result=0;
 
-		/* Enable bus-mastering */
-		pci_read_config_byte(btv->dev, PCI_COMMAND, &command);
-		command|=PCI_COMMAND_MASTER;
-		pci_write_config_byte(btv->dev, PCI_COMMAND, command);
-		pci_read_config_byte(btv->dev, PCI_COMMAND, &command);
-		if (!(command&PCI_COMMAND_MASTER)) 
-		{
-			printk(KERN_ERR "bttv: PCI bus-mastering could not be enabled\n");
-			return -1;
-		}
-		pci_read_config_byte(btv->dev, PCI_LATENCY_TIMER, &latency);
-		if (!latency) 
-		{
-			latency=32;
-			pci_write_config_byte(btv->dev, PCI_LATENCY_TIMER, latency);
-		}
-		DEBUG(printk(KERN_DEBUG "bttv: latency: %02x\n", latency));
-		bttv_num++;
-	}
+        bttv_num=0;
+
+        while (dev)
+        {
+                if (dev->vendor == PCI_VENDOR_ID_BROOKTREE)
+                        if ((dev->device == PCI_DEVICE_ID_BT848)||
+                            (dev->device == PCI_DEVICE_ID_BT849)||
+                            (dev->device == PCI_DEVICE_ID_BT878)||
+                            (dev->device == PCI_DEVICE_ID_BT879))
+                                result=configure_bt848(dev,bttv_num++);
+                if (result)
+                        return result;
+                dev = dev->next;
+        }
 	if(bttv_num)
 		printk(KERN_INFO "bttv: %d Bt848 card(s) found.\n", bttv_num);
 	return bttv_num;
 }
-
+ 
 
 static void release_bttv(void)
 {
@@ -3009,7 +3024,7 @@
 			vfree((void *) btv->vbibuf);
 
 
-		free_irq(btv->dev->irq,btv);
+		free_irq(btv->irq,btv);
 		DEBUG(printk(KERN_DEBUG "bt848_mem: 0x%08x.\n", btv->bt848_mem));
 		if (btv->bt848_mem)
 			iounmap(btv->bt848_mem);
diff -u --recursive --new-file v2.1.117/linux/drivers/char/bttv.h linux/drivers/char/bttv.h
--- v2.1.117/linux/drivers/char/bttv.h	Sun Jul 26 11:57:15 1998
+++ linux/drivers/char/bttv.h	Sun Aug 23 13:32:25 1998
@@ -32,17 +32,11 @@
 #include <linux/videodev.h>
 
 #define MAX_CLIPRECS	100
+#define MAX_GBUFFERS	2
 #define RISCMEM_LEN	(32744*2)
-#define BTTV_MAX_FBUF	0x144000
-
-
-/* clipping rectangle */
-struct cliprec 
-{
-	int x, y, x2, y2;
-	struct cliprec *next;
-};
 
+/* maximum needed buffer size for extended VBI frame mode capturing */
+#define BTTV_MAX_FBUF	0x151000
 
 #ifdef __KERNEL__
 
@@ -75,9 +69,14 @@
 	int have_msp3400;
 	int have_tuner;
         int tuner_type;
-
+        int channel;
+        
+        unsigned int nr;
 	unsigned short id;
+	unsigned char bus;          /* PCI bus the Bt848 is on */
+	unsigned char devfn;
 	struct pci_dev *dev;
+	unsigned char irq;          /* IRQ used by Bt848 card */
 	unsigned char revision;
 	unsigned int bt848_adr;      /* bus address of IO mem returned by PCI BIOS */
 	unsigned char *bt848_mem;   /* pointer to mapped IO memory */
@@ -106,24 +105,37 @@
 	u32 *risc_odd;
 	u32 *risc_even;
 	int cap;
-	struct cliprec *cliprecs;
-	int ncr;		/* number of clipping rectangles */
+	struct video_clip *cliprecs;
 
 	struct gbuffer *ogbuffers;
 	struct gbuffer *egbuffers;
 	u16 gwidth, gheight, gfmt;
 	u32 *grisc;
+	
 	unsigned long gro;
 	unsigned long gre;
 	unsigned long gro_next;
 	unsigned long gre_next;
-	char *fbuffer;
+
+        int grf,grf_next;  /* frame numbers in grab queue */
+        int frame_stat[MAX_GBUFFERS];
+#define GBUFFER_UNUSED       0
+#define GBUFFER_GRABBING     1
+#define GBUFFER_DONE         2
+
+        char *fbuffer;
 	int gmode;
 	int grabbing;
 	int lastgrab;
 	int grab;
 	int grabcount;
+
 	int pll;
+	unsigned int Fsc;
+	unsigned int field;
+	unsigned int last_field; /* number of last grabbed field */
+	int i2c_command;
+	int triton1;
 };
 
 #endif
@@ -148,6 +160,7 @@
 #define BTTV_READEE		_IOW('v',  BASE_VIDIOCPRIVATE+0, char [256])
 #define BTTV_WRITEE		_IOR('v',  BASE_VIDIOCPRIVATE+1, char [256])
 #define BTTV_GRAB		_IOR('v' , BASE_VIDIOCPRIVATE+2, struct gbuf)
+#define BTTV_FIELDNR		_IOR('v' , BASE_VIDIOCPRIVATE+2, unsigned int)
 
 
 #define BTTV_UNKNOWN       0x00
@@ -185,7 +198,6 @@
 #define TDA9850_ALI1       0x08
 #define TDA9850_ALI2       0x09
 #define TDA9850_ALI3       0x0a
-
 
 #define TDA8425_VL         0x00
 #define TDA8425_VR         0x01
diff -u --recursive --new-file v2.1.117/linux/drivers/char/busmouse.c linux/drivers/char/busmouse.c
--- v2.1.117/linux/drivers/char/busmouse.c	Thu Aug 20 17:05:15 1998
+++ linux/drivers/char/busmouse.c	Mon Aug 24 13:02:43 1998
@@ -238,6 +238,7 @@
 	NULL, 		/* mouse_ioctl */
 	NULL,		/* mouse_mmap */
 	open_mouse,
+	NULL,		/* flush */
 	close_mouse,
 	NULL,
 	fasync_mouse,
diff -u --recursive --new-file v2.1.117/linux/drivers/char/cyclades.c linux/drivers/char/cyclades.c
--- v2.1.117/linux/drivers/char/cyclades.c	Tue Aug 18 22:02:03 1998
+++ linux/drivers/char/cyclades.c	Fri Aug 21 09:31:30 1998
@@ -1,7 +1,7 @@
 #define BLOCKMOVE
 #define	Z_WAKE
 static char rcsid[] =
-"$Revision: 2.2.1.5 $$Date: 1998/08/10 18:10:28 $";
+"$Revision: 2.2.1.6 $$Date: 1998/08/20 17:15:39 $";
 
 /*
  *  linux/drivers/char/cyclades.c
@@ -31,6 +31,11 @@
  *   void cleanup_module(void);
  *
  * $Log: cyclades.c,v $
+ * Revision 2.2.1.6  1998/08/20 17:15:39 ivan
+ * Fixed bug in cy_close function, which causes malfunction
+ * of one of the first 4 ports when a higher port is closed
+ * (Cyclom-Y only).
+ *
  * Revision 2.2.1.5  1998/08/10 18:10:28 ivan
  * Fixed Cyclom-4Yo hardware detection bug.
  *
@@ -2679,9 +2684,11 @@
     }
 
     if (!IS_CYC_Z(cy_card[info->card])) {
-	unsigned char *base_addr = (unsigned char *) 
-					cy_card[info->card].base_addr;
+	int channel = info->line - cy_card[info->card].first_line;
 	int index = cy_card[info->card].bus_index;
+	unsigned char *base_addr = (unsigned char *)
+			(cy_card[info->card].base_addr +
+			 (cy_chip_offset[channel>>2] <<index));
 	/* Stop accepting input */
 	cy_writeb((u_long)base_addr+(CySRER<<index),
 			cy_readb(base_addr+(CySRER<<index)) & ~CyRxData);
diff -u --recursive --new-file v2.1.117/linux/drivers/char/dn_keyb.c linux/drivers/char/dn_keyb.c
--- v2.1.117/linux/drivers/char/dn_keyb.c	Thu Aug 20 17:05:15 1998
+++ linux/drivers/char/dn_keyb.c	Mon Aug 24 13:02:44 1998
@@ -560,6 +560,7 @@
         NULL,           /* mouse_ioctl */
         NULL,           /* mouse_mmap */
         open_mouse,
+	NULL,		/* flush */
         release_mouse,
         NULL,
         fasync_mouse,
diff -u --recursive --new-file v2.1.117/linux/drivers/char/dsp56k.c linux/drivers/char/dsp56k.c
--- v2.1.117/linux/drivers/char/dsp56k.c	Mon Aug  3 12:45:45 1998
+++ linux/drivers/char/dsp56k.c	Mon Aug 24 13:02:44 1998
@@ -510,6 +510,7 @@
 	dsp56k_ioctl,
 	NULL,    /* no special dsp56k_mmap */
 	dsp56k_open,
+	NULL,	/* flush */
 	dsp56k_release,
 	NULL,    /* no special dsp56k_fsync */
 	NULL,    /* no special dsp56k_fasync */
diff -u --recursive --new-file v2.1.117/linux/drivers/char/fbmem.c linux/drivers/char/fbmem.c
--- v2.1.117/linux/drivers/char/fbmem.c	Tue Jul 28 14:21:08 1998
+++ linux/drivers/char/fbmem.c	Mon Aug 24 13:02:44 1998
@@ -468,6 +468,7 @@
 	fb_ioctl,	/* ioctl 	*/
 	fb_mmap,	/* mmap		*/
 	fb_open,	/* open 	*/
+	NULL,		/* flush	*/
 	fb_release,	/* release 	*/
 	NULL		/* fsync 	*/
 };
diff -u --recursive --new-file v2.1.117/linux/drivers/char/ftape/lowlevel/ftape-proc.c linux/drivers/char/ftape/lowlevel/ftape-proc.c
--- v2.1.117/linux/drivers/char/ftape/lowlevel/ftape-proc.c	Tue Nov 25 14:45:27 1997
+++ linux/drivers/char/ftape/lowlevel/ftape-proc.c	Mon Aug 24 13:02:44 1998
@@ -94,6 +94,7 @@
 	NULL,			/* ioctl   */
 	NULL,			/* mmap	   */
 	NULL,			/* no special open code	   */
+	NULL,			/* flush */
 	NULL,			/* no special release code */
 	NULL,			/* can't fsync */
 };
diff -u --recursive --new-file v2.1.117/linux/drivers/char/ftape/zftape/zftape-init.c linux/drivers/char/ftape/zftape/zftape-init.c
--- v2.1.117/linux/drivers/char/ftape/zftape/zftape-init.c	Tue Mar 17 22:18:14 1998
+++ linux/drivers/char/ftape/zftape/zftape-init.c	Mon Aug 24 13:02:45 1998
@@ -134,6 +134,7 @@
 	zft_ioctl,		/* ioctl */
 	zft_mmap,		/* mmap */
 	zft_open,		/* open */
+	NULL,			/* flush */
 	zft_close,		/* release */
 	NULL,			/* fsync */
 };
diff -u --recursive --new-file v2.1.117/linux/drivers/char/h8.c linux/drivers/char/h8.c
--- v2.1.117/linux/drivers/char/h8.c	Tue Jul 21 00:15:31 1998
+++ linux/drivers/char/h8.c	Mon Aug 24 13:02:44 1998
@@ -113,6 +113,7 @@
         NULL,
         NULL,           /* mmap */
         NULL,
+	NULL,		/* flush */
         NULL,
         NULL,           /* fsync */
         NULL            /* fasync */
diff -u --recursive --new-file v2.1.117/linux/drivers/char/hfmodem/main.c linux/drivers/char/hfmodem/main.c
--- v2.1.117/linux/drivers/char/hfmodem/main.c	Mon Feb 23 18:12:04 1998
+++ linux/drivers/char/hfmodem/main.c	Mon Aug 24 13:14:09 1998
@@ -565,6 +565,7 @@
 	hfmodem_ioctl,      /* hfmodem_ioctl */
 	NULL,		    /* hfmodem_mmap */
 	hfmodem_open,       /* hfmodem_open */
+	NULL,		    /* flush */
 	hfmodem_close,      /* hfmodem_close */
 	NULL,               /* hfmodem_fsync */
 	NULL,               /* hfmodem_fasync */
diff -u --recursive --new-file v2.1.117/linux/drivers/char/lp.c linux/drivers/char/lp.c
--- v2.1.117/linux/drivers/char/lp.c	Tue Aug 18 22:02:03 1998
+++ linux/drivers/char/lp.c	Mon Aug 24 13:14:09 1998
@@ -714,6 +714,7 @@
 	lp_ioctl,
 	NULL,		/* lp_mmap */
 	lp_open,
+	NULL,		/* flush */
 	lp_release
 };
 
diff -u --recursive --new-file v2.1.117/linux/drivers/char/lp_m68k.c linux/drivers/char/lp_m68k.c
--- v2.1.117/linux/drivers/char/lp_m68k.c	Mon Aug  3 12:45:45 1998
+++ linux/drivers/char/lp_m68k.c	Mon Aug 24 13:14:09 1998
@@ -467,6 +467,7 @@
 	lp_ioctl,
 	NULL,		/* lp_mmap */
 	lp_open,
+	NULL,		/* flush */
 	lp_release
 };
 
diff -u --recursive --new-file v2.1.117/linux/drivers/char/macmouse.c linux/drivers/char/macmouse.c
--- v2.1.117/linux/drivers/char/macmouse.c	Thu Aug 20 17:05:15 1998
+++ linux/drivers/char/macmouse.c	Mon Aug 24 13:14:09 1998
@@ -242,6 +242,7 @@
     NULL,		/* mouse_ioctl */
     NULL,		/* mouse_mmap */
     open_mouse,
+    NULL,		/* flush */
     release_mouse,
     NULL,
     fasync_mouse,
diff -u --recursive --new-file v2.1.117/linux/drivers/char/mem.c linux/drivers/char/mem.c
--- v2.1.117/linux/drivers/char/mem.c	Mon Aug  3 12:45:45 1998
+++ linux/drivers/char/mem.c	Mon Aug 24 13:14:09 1998
@@ -415,6 +415,7 @@
 	NULL,		/* mem_ioctl */
 	mmap_mem,
 	NULL,		/* no special open code */
+	NULL,		/* flush */
 	NULL,		/* no special release code */
 	NULL		/* fsync */
 };
@@ -428,6 +429,7 @@
 	NULL,		/* kmem_ioctl */
 	mmap_kmem,
 	NULL,		/* no special open code */
+	NULL,		/* flush */
 	NULL,		/* no special release code */
 	NULL		/* fsync */
 };
@@ -441,6 +443,7 @@
 	NULL,		/* null_ioctl */
 	NULL,		/* null_mmap */
 	NULL,		/* no special open code */
+	NULL,		/* flush */
 	NULL,		/* no special release code */
 	NULL		/* fsync */
 };
@@ -454,6 +457,7 @@
 	NULL,		/* port_ioctl */
 	NULL,		/* port_mmap */
 	NULL,		/* no special open code */
+	NULL,		/* flush */
 	NULL,		/* no special release code */
 	NULL		/* fsync */
 };
@@ -467,6 +471,7 @@
 	NULL,		/* zero_ioctl */
 	mmap_zero,
 	NULL,		/* no special open code */
+	NULL,		/* flush */
 	NULL		/* no special release code */
 };
 
@@ -479,6 +484,7 @@
 	NULL,		/* full_ioctl */	
 	NULL,		/* full_mmap */
 	NULL,		/* no special open code */
+	NULL,		/* flush */
 	NULL		/* no special release code */
 };
 
@@ -526,6 +532,7 @@
 	NULL,		/* ioctl */
 	NULL,		/* mmap */
 	memory_open,	/* just a selector for the real open */
+	NULL,		/* flush */
 	NULL,		/* release */
 	NULL		/* fsync */
 };
diff -u --recursive --new-file v2.1.117/linux/drivers/char/misc.c linux/drivers/char/misc.c
--- v2.1.117/linux/drivers/char/misc.c	Thu Aug  6 14:06:31 1998
+++ linux/drivers/char/misc.c	Mon Aug 24 13:14:09 1998
@@ -139,6 +139,7 @@
 	NULL,		/* ioctl */
 	NULL,		/* mmap */
         misc_open,
+	NULL,		/* flush */
         NULL		/* release */
 };
 
diff -u --recursive --new-file v2.1.117/linux/drivers/char/msbusmouse.c linux/drivers/char/msbusmouse.c
--- v2.1.117/linux/drivers/char/msbusmouse.c	Thu Aug 20 17:05:15 1998
+++ linux/drivers/char/msbusmouse.c	Mon Aug 24 13:14:09 1998
@@ -174,6 +174,7 @@
 	NULL, 		/* mouse_ioctl */
 	NULL,		/* mouse_mmap */
 	open_mouse,
+	NULL,		/* flush */
 	release_mouse,
 	NULL,
 	fasync_mouse,
diff -u --recursive --new-file v2.1.117/linux/drivers/char/n_tty.c linux/drivers/char/n_tty.c
--- v2.1.117/linux/drivers/char/n_tty.c	Mon Aug  3 12:45:45 1998
+++ linux/drivers/char/n_tty.c	Thu Aug 20 14:25:15 1998
@@ -842,22 +842,25 @@
  * buffer, and once to drain the space from the (physical) beginning of
  * the buffer to head pointer.
  */
-static inline void copy_from_read_buf(struct tty_struct *tty,
+static inline int copy_from_read_buf(struct tty_struct *tty,
 				      unsigned char **b,
 				      size_t *nr)
 
 {
+	int retval;
 	ssize_t n;
 
+	retval = 0;
 	n = MIN(*nr, MIN(tty->read_cnt, N_TTY_BUF_SIZE - tty->read_tail));
-	if (!n)
-		return;
-	/* N.B. copy_to_user may work only partially */
-	n -= copy_to_user(*b, &tty->read_buf[tty->read_tail], n);
-	tty->read_tail = (tty->read_tail + n) & (N_TTY_BUF_SIZE-1);
-	tty->read_cnt -= n;
-	*b += n;
-	*nr -= n;
+	if (n) {
+		retval = copy_to_user(*b, &tty->read_buf[tty->read_tail], n);
+		n -= retval;
+		tty->read_tail = (tty->read_tail + n) & (N_TTY_BUF_SIZE-1);
+		tty->read_cnt -= n;
+		*b += n;
+		*nr -= n;
+	}
+	return retval;
 }
 
 static ssize_t read_chan(struct tty_struct *tty, struct file *file,
@@ -996,9 +999,13 @@
 				}
 			}
 		} else {
-			/* N.B. check for errors writing to user space? */
-			copy_from_read_buf(tty, &b, &nr);
-			copy_from_read_buf(tty, &b, &nr);
+			int uncopied;
+			uncopied = copy_from_read_buf(tty, &b, &nr);
+			uncopied += copy_from_read_buf(tty, &b, &nr);
+			if (uncopied) {
+				retval = -EFAULT;
+				break;
+			}
 		}
 
 		/* If there is enough space in the read buffer now, let the
diff -u --recursive --new-file v2.1.117/linux/drivers/char/nvram.c linux/drivers/char/nvram.c
--- v2.1.117/linux/drivers/char/nvram.c	Tue Jun 23 10:01:22 1998
+++ linux/drivers/char/nvram.c	Mon Aug 24 13:14:09 1998
@@ -402,6 +402,7 @@
 	nvram_ioctl,
 	NULL,			/* No mmap */
 	nvram_open,
+	NULL,			/* flush */
 	nvram_release
 };
 
diff -u --recursive --new-file v2.1.117/linux/drivers/char/pc110pad.c linux/drivers/char/pc110pad.c
--- v2.1.117/linux/drivers/char/pc110pad.c	Thu Aug 20 17:05:15 1998
+++ linux/drivers/char/pc110pad.c	Mon Aug 24 13:14:10 1998
@@ -626,6 +626,7 @@
 	pad_ioctl,
 	NULL,		/* pad_mmap */
 	open_pad,
+	NULL,		/* flush */
 	close_pad,
 	NULL,		/* fsync */
 	fasync_pad,
diff -u --recursive --new-file v2.1.117/linux/drivers/char/pcwd.c linux/drivers/char/pcwd.c
--- v2.1.117/linux/drivers/char/pcwd.c	Sun Jun  7 11:16:30 1998
+++ linux/drivers/char/pcwd.c	Mon Aug 24 13:14:10 1998
@@ -515,6 +515,7 @@
 	pcwd_ioctl,	/* IOctl */
 	NULL,		/* MMAP */
 	pcwd_open,	/* Open */
+	NULL,		/* flush */
 	pcwd_close,	/* Release */
 	NULL,		/* Fsync */
 	NULL,		/* Fasync */
diff -u --recursive --new-file v2.1.117/linux/drivers/char/psaux.c linux/drivers/char/psaux.c
--- v2.1.117/linux/drivers/char/psaux.c	Thu Aug 20 17:05:15 1998
+++ linux/drivers/char/psaux.c	Mon Aug 24 13:14:10 1998
@@ -582,6 +582,7 @@
 	NULL, 		/* ioctl */
 	NULL,		/* mmap */
 	open_aux,
+	NULL,		/* flush */
 	release_aux,
 	NULL,
 	fasync_aux,
diff -u --recursive --new-file v2.1.117/linux/drivers/char/radio-aimslab.c linux/drivers/char/radio-aimslab.c
--- v2.1.117/linux/drivers/char/radio-aimslab.c	Thu Aug 20 17:05:16 1998
+++ linux/drivers/char/radio-aimslab.c	Sun Aug 23 13:32:25 1998
@@ -216,6 +216,7 @@
 			v.maxheight=0;
 			v.minwidth=0;
 			v.minheight=0;
+			strcpy(v.name, "RadioTrack");
 			if(copy_to_user(arg,&v,sizeof(v)))
 				return -EFAULT;
 			return 0;
diff -u --recursive --new-file v2.1.117/linux/drivers/char/radio-aztech.c linux/drivers/char/radio-aztech.c
--- v2.1.117/linux/drivers/char/radio-aztech.c	Thu Aug 20 17:05:16 1998
+++ linux/drivers/char/radio-aztech.c	Sun Aug 23 13:32:25 1998
@@ -167,6 +167,7 @@
 			v.maxheight=0;
 			v.minwidth=0;
 			v.minheight=0;
+			strcpy(v.name, "Aztech Radio");
 			if(copy_to_user(arg,&v,sizeof(v)))
 				return -EFAULT;
 			return 0;
diff -u --recursive --new-file v2.1.117/linux/drivers/char/radio-miropcm20.c linux/drivers/char/radio-miropcm20.c
--- v2.1.117/linux/drivers/char/radio-miropcm20.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/radio-miropcm20.c	Mon Aug 24 09:19:19 1998
@@ -0,0 +1,245 @@
+/* Miro PCM20 radio driver for Linux radio support
+ * (c) 1998 Ruurd Reitsma <R.A.Reitsma@wbmt.tudelft.nl>
+ * Thanks to Norberto Pellici for the ACI device interface specification
+ * The API part is based on the radiotrack driver by M. Kirkwood
+ * This driver relies on the aci mixer (drivers/sound/lowlevel/aci.c)
+ * Look there for further info...
+ */
+
+#include <linux/module.h>		/* Modules 			*/
+#include <linux/init.h>			/* Initdata			*/
+#include <asm/uaccess.h>		/* copy to/from user		*/
+#include <linux/videodev.h>		/* kernel radio structs		*/
+#include <linux/config.h>		/* CONFIG_RADIO_MIROPCM20 	*/
+#include "../sound/lowlevel/miroaci.h"	/* ACI Control by acimixer	*/
+
+static int users = 0;
+
+struct pcm20_device
+{
+	int port;
+	int curvol;
+	unsigned long curfreq;
+	int muted;
+};
+
+
+/* local things */
+
+
+static void pcm20_mute(struct pcm20_device *dev)
+{
+
+	dev->muted = 1;
+	aci_write_cmd(0xa3,0x01);			
+
+}
+
+static int pcm20_setvol(struct pcm20_device *dev, int vol)
+{
+
+	if(vol == dev->curvol) {	/* requested volume = current */
+		if (dev->muted) {	/* user is unmuting the card  */
+			dev->muted = 0;
+			aci_write_cmd(0xa3,0x00); 	/* enable card */
+		}	
+	
+		return 0;
+	}
+
+	if(vol == 0) {			/* volume = 0 means mute the card */
+		aci_write_cmd(0x3d, 0x20);
+		aci_write_cmd(0x35, 0x20);
+		return 0;
+	}
+
+	dev->muted = 0;
+	aci_write_cmd(0x3d, 32-vol); 	/* Right Channel */
+	aci_write_cmd(0x35, 32-vol);	/* Left Channel */
+	dev->curvol = vol;
+
+	return 0;
+}
+
+static int pcm20_setfreq(struct pcm20_device *dev, unsigned long freq)
+{
+	unsigned char freql;
+	unsigned char freqh;
+
+	freq = (freq * 10) / 16;
+	freql = freq & 0xff;
+	freqh = freq >> 8;	
+
+
+	aci_write_cmd_d(0xa7, freql, freqh);	/*  Tune to frequency	*/
+
+	return 0;
+}
+
+int pcm20_getsigstr(struct pcm20_device *dev)
+{
+	unsigned char buf;
+	aci_indexed_cmd(0xf0, 0x32, &buf);
+	if ((buf & 0x80) == 0x80)	
+		return 0;
+	return 1;		/* signal present		*/
+}
+
+static int pcm20_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
+{
+	struct pcm20_device *pcm20=dev->priv;
+	
+	switch(cmd)
+	{
+		case VIDIOCGCAP:
+		{
+			struct video_capability v;
+			v.type=VID_TYPE_TUNER;
+			strcpy(v.name, "Miro PCM20");
+			v.channels=1;
+			v.audios=1;
+			/* No we don't do pictures */
+			v.maxwidth=0;
+			v.maxheight=0;
+			v.minwidth=0;
+			v.minheight=0;
+			if(copy_to_user(arg,&v,sizeof(v)))
+				return -EFAULT;
+			return 0;
+		}
+		case VIDIOCGTUNER:
+		{
+			struct video_tuner v;
+			if(copy_from_user(&v, arg,sizeof(v))!=0) 
+				return -EFAULT;
+			if(v.tuner)	/* Only 1 tuner */ 
+				return -EINVAL;
+			v.rangelow=(int)(87.5*16);
+			v.rangehigh=(int)(108.0*16);
+			v.flags=0;
+			v.mode=VIDEO_MODE_AUTO;
+			v.signal=0xFFFF*pcm20_getsigstr(pcm20);
+			if(copy_to_user(arg,&v, sizeof(v)))
+				return -EFAULT;
+			return 0;
+		}
+		case VIDIOCSTUNER:
+		{
+			struct video_tuner v;
+			if(copy_from_user(&v, arg, sizeof(v)))
+				return -EFAULT;
+			if(v.tuner!=0)
+				return -EINVAL;
+			/* Only 1 tuner so no setting needed ! */
+			return 0;
+		}
+		case VIDIOCGFREQ:
+			if(copy_to_user(arg, &pcm20->curfreq, sizeof(pcm20->curfreq)))
+				return -EFAULT;
+			return 0;
+		case VIDIOCSFREQ:
+			if(copy_from_user(&pcm20->curfreq, arg,sizeof(pcm20->curfreq)))
+				return -EFAULT;
+			pcm20_setfreq(pcm20, pcm20->curfreq);
+			return 0;
+		case VIDIOCGAUDIO:
+		{	
+			struct video_audio v;
+			memset(&v,0, sizeof(v));
+			v.flags|=VIDEO_AUDIO_MUTABLE|VIDEO_AUDIO_VOLUME;
+			v.volume=pcm20->curvol * 2048;
+			strcpy(v.name, "Radio");
+			if(copy_to_user(arg,&v, sizeof(v)))
+				return -EFAULT;
+			return 0;			
+		}
+		case VIDIOCSAUDIO:
+		{
+			struct video_audio v;
+			if(copy_from_user(&v, arg, sizeof(v))) 
+				return -EFAULT;	
+			if(v.audio) 
+				return -EINVAL;
+
+			if(v.flags&VIDEO_AUDIO_MUTE) 
+				pcm20_mute(pcm20);
+			else
+				pcm20_setvol(pcm20,v.volume/2048);	
+
+			return 0;
+		}
+		default:
+			return -ENOIOCTLCMD;
+	}
+}
+
+static int pcm20_open(struct video_device *dev, int flags)
+{
+	if(users)
+		return -EBUSY;
+	users++;
+	MOD_INC_USE_COUNT;
+	return 0;
+}
+
+static void pcm20_close(struct video_device *dev)
+{
+	users--;
+	MOD_DEC_USE_COUNT;
+}
+
+static struct pcm20_device pcm20_unit;
+
+static struct video_device pcm20_radio=
+{
+	"Miro PCM 20 radio",
+	VID_TYPE_TUNER,
+	VID_HARDWARE_RTRACK,
+	pcm20_open,
+	pcm20_close,
+	NULL,	/* Can't read  (no capture ability) */
+	NULL,	/* Can't write */
+	NULL,	/* Can't poll */
+	pcm20_ioctl,
+	NULL,
+	NULL
+};
+
+__initfunc(int pcm20_init(struct video_init *v))
+{
+
+	pcm20_radio.priv=&pcm20_unit;
+	
+	if(video_register_device(&pcm20_radio, VFL_TYPE_RADIO)==-1)
+		return -EINVAL;
+		
+	printk(KERN_INFO "Miro PCM20 radio card driver.\n");
+
+ 	/* mute card - prevents noisy bootups */
+
+	/* this ensures that the volume is all the way down  */
+
+	pcm20_unit.curvol = 0;
+
+	return 0;
+}
+
+#ifdef MODULE
+
+MODULE_AUTHOR("Ruurd Reitsma");
+MODULE_DESCRIPTION("A driver for the Miro PCM20 radio card.");
+
+EXPORT_NO_SYMBOLS;
+
+int init_module(void)
+{
+
+	return pcm20_init(NULL); 
+}
+
+void cleanup_module(void)
+{
+	video_unregister_device(&pcm20_radio);
+}
+
+#endif
diff -u --recursive --new-file v2.1.117/linux/drivers/char/radio-rtrack2.c linux/drivers/char/radio-rtrack2.c
--- v2.1.117/linux/drivers/char/radio-rtrack2.c	Thu Aug 20 17:05:16 1998
+++ linux/drivers/char/radio-rtrack2.c	Sun Aug 23 13:32:25 1998
@@ -113,6 +113,7 @@
 			v.maxheight=0;
 			v.minwidth=0;
 			v.minheight=0;
+			strcpy(v.name, "RadioTrack II");
 			if(copy_to_user(arg,&v,sizeof(v)))
 				return -EFAULT;
 			return 0;
diff -u --recursive --new-file v2.1.117/linux/drivers/char/radio-sf16fmi.c linux/drivers/char/radio-sf16fmi.c
--- v2.1.117/linux/drivers/char/radio-sf16fmi.c	Thu Aug 20 17:05:16 1998
+++ linux/drivers/char/radio-sf16fmi.c	Sun Aug 23 13:32:25 1998
@@ -22,14 +22,12 @@
 #include <linux/videodev.h>	/* kernel radio structs		*/
 #include <linux/config.h>	/* CONFIG_RADIO_SF16MI_PORT 	*/
 
-#include "rsf16fmi.h"
-
 struct fmi_device
 {
 	int port;
-	int curvol;
-	unsigned long curfreq;
-	int flags;
+        int curvol; /* 1 or 0 */
+        unsigned long curfreq; /* RSF16_PREC * freq in MHz */
+        __u32 flags;
 };
 
 #ifndef CONFIG_RADIO_SF16FMI_PORT
@@ -39,11 +37,16 @@
 static int io = CONFIG_RADIO_SF16FMI_PORT; 
 static int users = 0;
 
-/* local things */
-/* freq in 1/16kHz to internal number */
-#define RSF16_ENCODE(x)	((x/16+10700)/50)
+/* freq is in 1/16 kHz to internal number, hw precision is 50 kHz */
+/* It is only usefull to give freq in intervall of 800 (=0.05Mhz),
+ * other bits will be truncated, e.g 92.7400016 -> 92.7, but 
+ * 92.7400017 -> 92.75
+ */
+#define RSF16_ENCODE(x)	((x)/800+214)
+#define RSF16_MINFREQ 88*16000
+#define RSF16_MAXFREQ 108*16000
 
-static void outbits(int bits, int data, int port)
+static void outbits(int bits, unsigned int data, int port)
 {
 	while(bits--) {
  		if(data & 1) {
@@ -73,7 +76,7 @@
 
 static int fmi_setfreq(struct fmi_device *dev, unsigned long freq)
 {
-	int myport = dev->port;
+        int myport = dev->port;
 
 	outbits(16, RSF16_ENCODE(freq), myport);
 	outbits(8, 0xC0, myport);
@@ -105,6 +108,7 @@
 		case VIDIOCGCAP:
 		{
 			struct video_capability v;
+			strcpy(v.name, "SF16-FMx radio");
 			v.type=VID_TYPE_TUNER;
 			v.channels=1;
 			v.audios=1;
@@ -120,17 +124,16 @@
 		case VIDIOCGTUNER:
 		{
 			struct video_tuner v;
+			int mult;
+
 			if(copy_from_user(&v, arg,sizeof(v))!=0)
 				return -EFAULT;
 			if(v.tuner)	/* Only 1 tuner */
 				return -EINVAL;
-			if (fmi->flags & VIDEO_TUNER_LOW) {
-				v.rangelow = 87500 * 16;
-				v.rangehigh = 108000 * 16;
-			} else {
-				v.rangelow=(int)(175*8 /* 87.5 *16 */);
-				v.rangehigh=(int)(108*16);
-			}
+			strcpy(v.name, "FM");
+			mult = (fmi->flags & VIDEO_TUNER_LOW) ? 1 : 1000;
+			v.rangelow = RSF16_MINFREQ/mult;
+			v.rangehigh = RSF16_MAXFREQ/mult;
 			v.flags=fmi->flags;
 			v.mode=VIDEO_MODE_AUTO;
 			v.signal=0xFFFF*fmi_getsigstr(fmi);
@@ -165,6 +168,8 @@
 				return -EFAULT;
 			if (!(fmi->flags & VIDEO_TUNER_LOW))
 				tmp *= 1000;
+			if ( tmp<RSF16_MINFREQ || tmp>RSF16_MAXFREQ )
+			  return -EINVAL;
 			fmi->curfreq = tmp;
 			fmi_setfreq(fmi, fmi->curfreq);
 			return 0;
@@ -172,12 +177,15 @@
 		case VIDIOCGAUDIO:
 		{	
 			struct video_audio v;
-			memset(&v,0, sizeof(v));
-			v.flags|=VIDEO_AUDIO_MUTABLE;
-			v.mode=VIDEO_SOUND_MONO;
-			v.volume=fmi->curvol;
-			v.step=65535;
+			v.audio=0;
+			v.volume=0;
+			v.bass=0;
+			v.treble=0;
+			v.flags=( (!fmi->curvol)*VIDEO_AUDIO_MUTE | VIDEO_AUDIO_MUTABLE);
 			strcpy(v.name, "Radio");
+			v.mode=VIDEO_SOUND_MONO;
+			v.balance=0;
+			v.step=0; /* No volume, just (un)mute */
 			if(copy_to_user(arg,&v, sizeof(v)))
 				return -EFAULT;
 			return 0;			
@@ -189,15 +197,23 @@
 				return -EFAULT;
 			if(v.audio)
 				return -EINVAL;
-			fmi->curvol=v.volume;
-			if(v.flags&VIDEO_AUDIO_MUTE)
-				fmi_mute(fmi->port);
-			else if(fmi->curvol)
-				fmi_unmute(fmi->port);
-			else
-				fmi_mute(fmi->port);
+			fmi->curvol= v.flags&VIDEO_AUDIO_MUTE ? 0 : 1;
+			fmi->curvol ? 
+			  fmi_unmute(fmi->port) : fmi_mute(fmi->port);
 			return 0;
 		}
+	        case VIDIOCGUNIT:
+		{
+               		struct video_unit v;
+			v.video=VIDEO_NO_UNIT;
+			v.vbi=VIDEO_NO_UNIT;
+			v.radio=dev->minor;
+			v.audio=0; /* How do we find out this??? */
+			v.teletext=VIDEO_NO_UNIT;
+			if(copy_to_user(arg, &v, sizeof(v)))
+				return -EFAULT;
+			return 0;			
+		}
 		default:
 			return -ENOIOCTLCMD;
 	}
@@ -222,7 +238,7 @@
 
 static struct video_device fmi_radio=
 {
-	"SF16FMI radio",
+	"SF16FMx radio",
 	VID_TYPE_TUNER,
 	VID_HARDWARE_SF16MI,
 	fmi_open,
@@ -243,15 +259,17 @@
 		return -EBUSY;
 	}
 
-	fmi_unit.port=io;
+	fmi_unit.port = io;
+	fmi_unit.curvol = 0;
+	fmi_unit.curfreq = 0;
 	fmi_unit.flags = VIDEO_TUNER_LOW;
-	fmi_radio.priv=&fmi_unit;
+	fmi_radio.priv = &fmi_unit;
 	
 	if(video_register_device(&fmi_radio, VFL_TYPE_RADIO)==-1)
 		return -EINVAL;
 		
 	request_region(io, 2, "fmi");
-	printk(KERN_INFO "SF16FMI radio card driver.\n");
+	printk(KERN_INFO "SF16FMx radio card driver at 0x%x.\n", io);
 	printk(KERN_INFO "(c) 1998 Petr Vandrovec, vandrove@vc.cvut.cz.\n");
 	/* mute card - prevents noisy bootups */
 	fmi_mute(io);
diff -u --recursive --new-file v2.1.117/linux/drivers/char/radio-zoltrix.c linux/drivers/char/radio-zoltrix.c
--- v2.1.117/linux/drivers/char/radio-zoltrix.c	Thu Aug 20 17:05:16 1998
+++ linux/drivers/char/radio-zoltrix.c	Sun Aug 23 13:32:25 1998
@@ -176,6 +176,7 @@
 			v.maxheight = 0;
 			v.minwidth = 0;
 			v.minheight = 0;
+			strcpy(v.name, "Zoltrix Radio");
 			if (copy_to_user(arg, &v, sizeof(v)))
 				return -EFAULT;
 			return 0;
diff -u --recursive --new-file v2.1.117/linux/drivers/char/random.c linux/drivers/char/random.c
--- v2.1.117/linux/drivers/char/random.c	Tue Jul 21 00:15:31 1998
+++ linux/drivers/char/random.c	Mon Aug 24 13:14:10 1998
@@ -1526,6 +1526,7 @@
 	random_ioctl,
 	NULL,		/* random_mmap */
 	NULL,		/* no special open code */
+	NULL,		/* flush */
 	NULL		/* no special release code */
 };
 
@@ -1538,6 +1539,7 @@
 	random_ioctl,
 	NULL,		/* urandom_mmap */
 	NULL,		/* no special open code */
+	NULL,		/* flush */
 	NULL		/* no special release code */
 };
 
diff -u --recursive --new-file v2.1.117/linux/drivers/char/rtc.c linux/drivers/char/rtc.c
--- v2.1.117/linux/drivers/char/rtc.c	Wed Jun 24 22:54:05 1998
+++ linux/drivers/char/rtc.c	Mon Aug 24 13:14:10 1998
@@ -506,6 +506,7 @@
 	rtc_ioctl,
 	NULL,		/* No mmap */
 	rtc_open,
+	NULL,		/* flush */
 	rtc_release
 };
 
diff -u --recursive --new-file v2.1.117/linux/drivers/char/softdog.c linux/drivers/char/softdog.c
--- v2.1.117/linux/drivers/char/softdog.c	Mon Jan 12 15:12:42 1998
+++ linux/drivers/char/softdog.c	Mon Aug 24 13:14:10 1998
@@ -168,6 +168,7 @@
 	softdog_ioctl,	/* Ioctl */
 	NULL,		/* MMap */
 	softdog_open,
+	NULL,		/* flush */
 	softdog_release,
 	NULL,		
 	NULL		/* Fasync */
diff -u --recursive --new-file v2.1.117/linux/drivers/char/stallion.c linux/drivers/char/stallion.c
--- v2.1.117/linux/drivers/char/stallion.c	Thu Aug  6 14:06:31 1998
+++ linux/drivers/char/stallion.c	Mon Aug 24 13:14:10 1998
@@ -672,6 +672,7 @@
 	stl_memioctl,
 	NULL,
 	stl_memopen,
+	NULL,		/* flush */
 	stl_memclose,
 	NULL
 };
diff -u --recursive --new-file v2.1.117/linux/drivers/char/tpqic02.c linux/drivers/char/tpqic02.c
--- v2.1.117/linux/drivers/char/tpqic02.c	Fri Jan 23 18:10:31 1998
+++ linux/drivers/char/tpqic02.c	Mon Aug 24 13:02:44 1998
@@ -2756,6 +2756,7 @@
 	qic02_tape_ioctl,		/* ioctl */
 	NULL,				/* mmap not allowed */
 	qic02_tape_open,		/* open */
+	NULL,				/* flush */
 	qic02_tape_release,		/* release */
 	NULL,				/* fsync */
 	NULL,				/* fasync */
diff -u --recursive --new-file v2.1.117/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c
--- v2.1.117/linux/drivers/char/tty_io.c	Thu Aug 20 17:05:16 1998
+++ linux/drivers/char/tty_io.c	Mon Aug 24 13:02:44 1998
@@ -358,6 +358,7 @@
 	tty_ioctl,
 	NULL,		/* tty_mmap */
 	tty_open,
+	NULL,		/* flush */
 	tty_release,
 	NULL,		/* tty_fsync */
 	tty_fasync
@@ -372,6 +373,7 @@
 	hung_up_tty_ioctl,
 	NULL,		/* hung_up_tty_mmap */
 	NULL,		/* hung_up_tty_open */
+	NULL,		/* flush */
 	tty_release,	/* hung_up_tty_release */
 	NULL,		/* hung_up_tty_fsync  */
 	NULL		/* hung_up_tty_fasync */
@@ -1976,7 +1978,7 @@
  * Just do some early initializations, and do the complex setup
  * later.
  */
-long console_init(long kmem_start, long kmem_end)
+long __init console_init(long kmem_start, long kmem_end)
 {
 	/* Setup the default TTY line discipline. */
 	memset(ldiscs, 0, sizeof(ldiscs));
diff -u --recursive --new-file v2.1.117/linux/drivers/char/tuner.c linux/drivers/char/tuner.c
--- v2.1.117/linux/drivers/char/tuner.c	Sun Jul 26 11:57:15 1998
+++ linux/drivers/char/tuner.c	Sun Aug 23 13:32:25 1998
@@ -108,7 +108,7 @@
 	else
 		config = tun->UHF;
 
-	div=freq + (int)(16*38.9);
+	div=freq + tun->IFPCoff;
   	div&=0x7fff;
 
 	LOCK_I2C_BUS(t->bus);
diff -u --recursive --new-file v2.1.117/linux/drivers/char/vc_screen.c linux/drivers/char/vc_screen.c
--- v2.1.117/linux/drivers/char/vc_screen.c	Mon Aug  3 12:45:45 1998
+++ linux/drivers/char/vc_screen.c	Mon Aug 24 13:02:44 1998
@@ -258,6 +258,7 @@
 	NULL,		/* ioctl */
 	NULL,		/* mmap */
 	vcs_open,	/* open */
+	NULL,		/* flush */
 	NULL,		/* release */
 	NULL		/* fsync */
 };
diff -u --recursive --new-file v2.1.117/linux/drivers/char/videodev.c linux/drivers/char/videodev.c
--- v2.1.117/linux/drivers/char/videodev.c	Tue Aug 18 22:02:04 1998
+++ linux/drivers/char/videodev.c	Mon Aug 24 13:02:44 1998
@@ -62,6 +62,9 @@
 #ifdef CONFIG_RADIO_SF16FMI
 extern int fmi_init(struct video_init *);
 #endif
+#ifdef CONFIG_RADIO_MIROPCM20
+extern int pcm20_init(struct video_init *);
+#endif
 
 static struct video_init video_init_list[]={
 #ifdef CONFIG_VIDEO_BT848
@@ -88,6 +91,9 @@
 #endif	
 #ifdef CONFIG_RADIO_SF16FMI
 	{"SF16FMI", fmi_init}, 
+#endif
+#ifdef CONFIG_RADIO_MIROPCM20
+	{"PCM20", pcm20_init}, 
 #endif	
 	{"end", NULL}
 };
@@ -315,6 +321,7 @@
 	video_ioctl,
 	video_mmap,
 	video_open,
+	NULL,		/* flush */
 	video_release
 };
 
diff -u --recursive --new-file v2.1.117/linux/drivers/char/wdt.c linux/drivers/char/wdt.c
--- v2.1.117/linux/drivers/char/wdt.c	Wed Jun 24 22:54:05 1998
+++ linux/drivers/char/wdt.c	Mon Aug 24 13:02:44 1998
@@ -327,6 +327,7 @@
 	wdt_ioctl,
 	NULL,		/* No mmap */
 	wdt_open,
+	NULL,		/* flush */
 	wdt_release
 };
 
diff -u --recursive --new-file v2.1.117/linux/drivers/isdn/avmb1/capi.c linux/drivers/isdn/avmb1/capi.c
--- v2.1.117/linux/drivers/isdn/avmb1/capi.c	Thu May  7 22:51:49 1998
+++ linux/drivers/isdn/avmb1/capi.c	Mon Aug 24 13:02:44 1998
@@ -464,6 +464,7 @@
 	capi_ioctl,
 	NULL,			/* capi_mmap */
 	capi_open,
+	NULL,			/* flush */
 	capi_release,
 	NULL,			/* capi_fsync */
 	NULL,			/* capi_fasync */
diff -u --recursive --new-file v2.1.117/linux/drivers/macintosh/adb.c linux/drivers/macintosh/adb.c
--- v2.1.117/linux/drivers/macintosh/adb.c	Fri May  8 23:14:47 1998
+++ linux/drivers/macintosh/adb.c	Mon Aug 24 13:02:43 1998
@@ -442,6 +442,7 @@
 	NULL,		/* no ioctl yet */
 	NULL,		/* no mmap */
 	adb_open,
+	NULL,		/* flush */
 	adb_release
 };
 
diff -u --recursive --new-file v2.1.117/linux/drivers/macintosh/nvram.c linux/drivers/macintosh/nvram.c
--- v2.1.117/linux/drivers/macintosh/nvram.c	Fri May  8 23:14:47 1998
+++ linux/drivers/macintosh/nvram.c	Mon Aug 24 13:14:09 1998
@@ -82,6 +82,7 @@
 	NULL,		/* nvram_ioctl */
 	NULL,		/* nvram_mmap */
 	nvram_open,
+	NULL,		/* flush */
 	NULL,		/* no special release code */
 	NULL		/* fsync */
 };
diff -u --recursive --new-file v2.1.117/linux/drivers/macintosh/via-pmu.c linux/drivers/macintosh/via-pmu.c
--- v2.1.117/linux/drivers/macintosh/via-pmu.c	Thu Aug  6 14:06:32 1998
+++ linux/drivers/macintosh/via-pmu.c	Mon Aug 24 13:02:44 1998
@@ -903,6 +903,7 @@
 	pmu_ioctl,
 	NULL,		/* no mmap */
 	pmu_open,
+	NULL,		/* flush */
 	NULL		/* no release */
 };
 
diff -u --recursive --new-file v2.1.117/linux/drivers/pci/oldproc.c linux/drivers/pci/oldproc.c
--- v2.1.117/linux/drivers/pci/oldproc.c	Tue Jul 28 14:21:08 1998
+++ linux/drivers/pci/oldproc.c	Mon Aug 24 15:12:32 1998
@@ -1,5 +1,5 @@
 /*
- *	$Id: oldproc.c,v 1.16 1998/07/19 17:50:18 davem Exp $
+ *	$Id: oldproc.c,v 1.20 1998/08/23 12:12:01 mj Exp $
  *
  *	Backward-compatible procfs interface for PCI.
  *
@@ -122,7 +122,9 @@
 	DEVICE( IBM,		IBM_82351,	"82351"),
 	DEVICE( IBM,		IBM_SERVERAID,	"ServeRAID"),
 	DEVICE( IBM,		IBM_TR_WAKE,	"Wake On LAN Token Ring"),
+	DEVICE( IBM,		IBM_MPIC,	"MPIC-2 Interrupt Controller"),
 	DEVICE( IBM,		IBM_3780IDSP,	"MWave DSP"),
+	DEVICE( IBM,		IBM_MPIC_2,	"MPIC-2 ASIC Interrupt Controller"),
 	DEVICE( WD,		WD_7197,	"WD 7197"),
 	DEVICE( AMD,		AMD_LANCE,	"79C970"),
 	DEVICE( AMD,		AMD_SCSI,	"53C974"),
diff -u --recursive --new-file v2.1.117/linux/drivers/pci/pci.c linux/drivers/pci/pci.c
--- v2.1.117/linux/drivers/pci/pci.c	Tue Jul 21 00:15:31 1998
+++ linux/drivers/pci/pci.c	Mon Aug 24 15:12:32 1998
@@ -1,5 +1,5 @@
 /*
- *	$Id: pci.c,v 1.86 1998/07/15 20:34:47 mj Exp $
+ *	$Id: pci.c,v 1.88 1998/08/15 10:37:12 mj Exp $
  *
  *	PCI Bus Services, see include/linux/pci.h for further explanation.
  *
@@ -170,13 +170,14 @@
 			/* not a multi-function device */
 			continue;
 		}
-		pcibios_read_config_byte(bus->number, devfn, PCI_HEADER_TYPE, &hdr_type);
+		if (pcibios_read_config_byte(bus->number, devfn, PCI_HEADER_TYPE, &hdr_type))
+			continue;
 		if (!PCI_FUNC(devfn))
 			is_multi = hdr_type & 0x80;
 
-		pcibios_read_config_dword(bus->number, devfn, PCI_VENDOR_ID, &l);
-		/* some broken boards return 0 if a slot is empty: */
-		if (l == 0xffffffff || l == 0x00000000 || l == 0x0000ffff || l == 0xffff0000) {
+		if (pcibios_read_config_dword(bus->number, devfn, PCI_VENDOR_ID, &l) ||
+		    /* some broken boards return 0 if a slot is empty: */
+		    l == 0xffffffff || l == 0x00000000 || l == 0x0000ffff || l == 0xffff0000) {
 			is_multi = 0;
 			continue;
 		}
diff -u --recursive --new-file v2.1.117/linux/drivers/pci/proc.c linux/drivers/pci/proc.c
--- v2.1.117/linux/drivers/pci/proc.c	Wed May 20 19:10:39 1998
+++ linux/drivers/pci/proc.c	Mon Aug 24 13:14:10 1998
@@ -204,6 +204,7 @@
 	NULL,		/* ioctl */
 	NULL,		/* mmap */
 	NULL,		/* no special open code */
+	NULL,		/* flush */
 	NULL,		/* no special release code */
 	NULL		/* can't fsync */
 };
diff -u --recursive --new-file v2.1.117/linux/drivers/sbus/audio/audio.c linux/drivers/sbus/audio/audio.c
--- v2.1.117/linux/drivers/sbus/audio/audio.c	Thu Aug  6 14:06:32 1998
+++ linux/drivers/sbus/audio/audio.c	Mon Aug 24 13:02:43 1998
@@ -881,6 +881,7 @@
 	sparcaudio_ioctl,
 	NULL,			/* sparcaudio_mmap */
 	NULL,
+	NULL,			/* flush */
 	sparcaudioctl_release
 };
 
diff -u --recursive --new-file v2.1.117/linux/drivers/sbus/char/bpp.c linux/drivers/sbus/char/bpp.c
--- v2.1.117/linux/drivers/sbus/char/bpp.c	Thu Aug  6 14:06:32 1998
+++ linux/drivers/sbus/char/bpp.c	Mon Aug 24 13:02:43 1998
@@ -866,6 +866,7 @@
 	bpp_ioctl,
 	NULL,		/* bpp_mmap */
 	bpp_open,
+	NULL,		/* flush */
 	bpp_release,
 };
 
diff -u --recursive --new-file v2.1.117/linux/drivers/sbus/char/envctrl.c linux/drivers/sbus/char/envctrl.c
--- v2.1.117/linux/drivers/sbus/char/envctrl.c	Thu Aug  6 14:06:32 1998
+++ linux/drivers/sbus/char/envctrl.c	Mon Aug 24 13:02:44 1998
@@ -298,6 +298,7 @@
 	envctrl_ioctl,
 	NULL,		/* mmap */
 	envctrl_open,
+	NULL,		/* flush */
 	envctrl_release
 };
 
diff -u --recursive --new-file v2.1.117/linux/drivers/sbus/char/flash.c linux/drivers/sbus/char/flash.c
--- v2.1.117/linux/drivers/sbus/char/flash.c	Thu Aug  6 14:06:32 1998
+++ linux/drivers/sbus/char/flash.c	Mon Aug 24 13:02:44 1998
@@ -143,6 +143,7 @@
 	NULL,		/* ioctl */
 	flash_mmap,
 	flash_open,
+	NULL,		/* flush */
 	flash_release
 };
 
diff -u --recursive --new-file v2.1.117/linux/drivers/sbus/char/openprom.c linux/drivers/sbus/char/openprom.c
--- v2.1.117/linux/drivers/sbus/char/openprom.c	Mon Jan 12 15:15:45 1998
+++ linux/drivers/sbus/char/openprom.c	Mon Aug 24 13:14:09 1998
@@ -564,6 +564,7 @@
 	openprom_ioctl,
 	NULL,			/* openprom_mmap */
 	openprom_open,
+	NULL,			/* flush */
 	openprom_release
 };
 
diff -u --recursive --new-file v2.1.117/linux/drivers/sbus/char/pcikbd.c linux/drivers/sbus/char/pcikbd.c
--- v2.1.117/linux/drivers/sbus/char/pcikbd.c	Thu Aug  6 14:06:32 1998
+++ linux/drivers/sbus/char/pcikbd.c	Mon Aug 24 13:14:10 1998
@@ -869,6 +869,7 @@
 	NULL, 		/* ioctl */
 	NULL,		/* mmap */
 	aux_open,
+	NULL,		/* flush */
 	aux_release,
 	NULL,
 	aux_fasync,
diff -u --recursive --new-file v2.1.117/linux/drivers/sbus/char/rtc.c linux/drivers/sbus/char/rtc.c
--- v2.1.117/linux/drivers/sbus/char/rtc.c	Thu Aug  6 14:06:32 1998
+++ linux/drivers/sbus/char/rtc.c	Mon Aug 24 13:14:10 1998
@@ -133,6 +133,7 @@
 	rtc_ioctl,
 	NULL,		/* rtc_mmap */
 	rtc_open,
+	NULL,		/* flush */
 	rtc_release
 };
 
diff -u --recursive --new-file v2.1.117/linux/drivers/sbus/char/sunkbd.c linux/drivers/sbus/char/sunkbd.c
--- v2.1.117/linux/drivers/sbus/char/sunkbd.c	Thu Aug  6 14:06:32 1998
+++ linux/drivers/sbus/char/sunkbd.c	Mon Aug 24 13:14:10 1998
@@ -1494,6 +1494,7 @@
 	kbd_ioctl,		/* ioctl */
 	NULL,			/* mmap */
 	kbd_open,		/* open */
+	NULL,			/* flush */
 	kbd_close,		/* close */
 	NULL,			/* fsync */
 	kbd_fasync,		/* fasync */
diff -u --recursive --new-file v2.1.117/linux/drivers/sbus/char/sunmouse.c linux/drivers/sbus/char/sunmouse.c
--- v2.1.117/linux/drivers/sbus/char/sunmouse.c	Thu Aug  6 14:06:32 1998
+++ linux/drivers/sbus/char/sunmouse.c	Mon Aug 24 13:14:10 1998
@@ -474,6 +474,7 @@
 	sun_mouse_ioctl,
 	NULL,
 	sun_mouse_open,
+	NULL,		/* flush */
 	sun_mouse_close,
 	NULL,
 	sun_mouse_fasync,
diff -u --recursive --new-file v2.1.117/linux/drivers/sbus/char/vfc_dev.c linux/drivers/sbus/char/vfc_dev.c
--- v2.1.117/linux/drivers/sbus/char/vfc_dev.c	Thu May  7 22:51:50 1998
+++ linux/drivers/sbus/char/vfc_dev.c	Mon Aug 24 13:02:44 1998
@@ -603,6 +603,7 @@
 	vfc_ioctl,   
 	vfc_mmap, 
 	vfc_open,
+	NULL,		/* flush */
 	vfc_release,
 };
 
diff -u --recursive --new-file v2.1.117/linux/drivers/scsi/Makefile linux/drivers/scsi/Makefile
--- v2.1.117/linux/drivers/scsi/Makefile	Thu Aug  6 14:06:32 1998
+++ linux/drivers/scsi/Makefile	Sun Aug 23 13:42:08 1998
@@ -15,7 +15,7 @@
 
 CFLAGS_aha152x.o =   -DDEBUG_AHA152X -DAUTOCONF
 CFLAGS_gdth.o    = # -DDEBUG_GDTH=2 -D__SERIAL__ -D__COM2__ -DGDTH_STATISTICS
-CFLAGS_seagate.o =   -DARBITRATE -DSLOW_HANDSHAKE -DFAST32 -DPARITY
+CFLAGS_seagate.o =   -DARBITRATE -DPARITY -DSEAGATE_USE_ASM
 
 .SUFFIXES:
 .SUFFIXES: .c .o .h .a
diff -u --recursive --new-file v2.1.117/linux/drivers/scsi/sd.c linux/drivers/scsi/sd.c
--- v2.1.117/linux/drivers/scsi/sd.c	Tue Jul 28 14:21:08 1998
+++ linux/drivers/scsi/sd.c	Mon Aug 24 13:14:10 1998
@@ -222,6 +222,7 @@
     sd_ioctl,                    /* ioctl */
     NULL,                        /* mmap */
     sd_open,                     /* open code */
+    NULL,			 /* flush */
     sd_release,                  /* release */
     block_fsync,                 /* fsync */
     NULL,                        /* fasync */
diff -u --recursive --new-file v2.1.117/linux/drivers/scsi/seagate.c linux/drivers/scsi/seagate.c
--- v2.1.117/linux/drivers/scsi/seagate.c	Thu May 14 19:47:41 1998
+++ linux/drivers/scsi/seagate.c	Sun Aug 23 13:42:08 1998
@@ -1,30 +1,23 @@
 /*
  *    seagate.c Copyright (C) 1992, 1993 Drew Eckhardt
  *      low level scsi driver for ST01/ST02, Future Domain TMC-885,
- *      TMC-950  by
- *
- *              Drew Eckhardt
- *
- *      <drew@colorado.edu>
+ *      TMC-950 by Drew Eckhardt <drew@colorado.edu>
  *
  *      Note : TMC-880 boards don't work because they have two bits in
  *              the status register flipped, I'll fix this "RSN"
+ *	[why do I have strong feeling that above message is from 1993? :-) pavel@ucw.cz]
  *
  *      This card does all the I/O via memory mapped I/O, so there is no need
  *      to check or allocate a region of the I/O address space.
  */
 
-/* Modified 1996 to use new read{b,w,l}, write{b,w,l}, and phys_to_virt
-   macros. This meant redefining st0x_cr_sr and st0x_dr, as well as
-   replacing the "DATA = foo;" and "CONTROL = foo;" structures with 
-   WRITE_DATA(foo) and WRITE_CONTROL(foo) macros.
-
-   Replaced assembler routines with C. There's probably a performance hit,
-   but I only have a cdrom and can't tell. Define SEAGATE_USE_ASM if you
-   want the old assembler code.
-
-   Look for the string "SJT" for details.
-
+/* 1996 - to use new read{b,w,l}, write{b,w,l}, and phys_to_virt
+ * macros, replaced assembler routines with C. There's probably a
+ * performance hit, but I only have a cdrom and can't tell. Define
+ * SEAGATE_USE_ASM if you want the old assembler code -- SJT
+ *
+ * 1998-jul-29 - created DPRINTK macros and made it work under 
+ * linux 2.1.112, simplified some #defines etc. <pavel@ucw.cz>
  */
 
 /*
@@ -50,7 +43,7 @@
  *      let us do one command per Lun when I integrate my
  *      reorganization changes into the distribution sources.
  *
- * -DDEBUG
+ * -DDEBUG=65535
  *      Will activate debug code.
  *
  * -DFAST or -DFAST32 
@@ -63,13 +56,12 @@
  *      Will use older seagate assembly code. should be (very small amount)
  *      Faster.
  *
- * -DSLOW_HANDSHAKE
+ * -DSLOW_RATE=50
  *      Will allow compatibility with broken devices that don't
  *      handshake fast enough (ie, some CD ROM's) for the Seagate
  *      code.
  *
- * -DSLOW_RATE=x
- *      x is some number, It will let you specify a default
+ *      50 is some number, It will let you specify a default
  *      transfer rate if handshaking isn't working correctly.
  *
  * -DOLDCNTDATASCEME  There is a new sceme to set the CONTROL
@@ -97,16 +89,25 @@
 #include <linux/string.h>
 #include <linux/config.h>
 #include <linux/proc_fs.h>
+#include <linux/init.h>
 
 #include <linux/blk.h>
 #include "scsi.h"
 #include "hosts.h"
 #include "seagate.h"
 #include "constants.h"
-#include<linux/stat.h>
+#include <linux/stat.h>
 #include <asm/uaccess.h>
 #include "sd.h"
 #include <scsi/scsi_ioctl.h>
+#include <asm/delay.h>
+
+#ifdef DEBUG
+#define DPRINTK( when, msg... ) do { if ( (DEBUG & (when)) == (when) ) printk( msg ); } while (0)
+#else
+#define DPRINTK( when, msg... ) do { } while (0)
+#endif
+#define DANY( msg... ) DPRINTK( 0xffff, msg );
 
 static struct proc_dir_entry proc_scsi_seagate =
 {
@@ -118,24 +119,16 @@
 #define IRQ 5
 #endif
 
-#if (defined(FAST32) && !defined(FAST))
+#ifdef FAST32
 #define FAST
 #endif
 
-#if defined(SLOW_RATE) && !defined(SLOW_HANDSHAKE)
-#define SLOW_HANDSHAKE
-#endif
-
-#if defined(SLOW_HANDSHAKE) && !defined(SLOW_RATE)
-#define SLOW_RATE 50
-#endif
+#undef LINKED		/* Linked commands are currently broken! */
 
-#if defined(LINKED)
-#undef LINKED                           /* Linked commands are currently
-                                           broken! */
+#if defined(OVERRIDE) && !defined(CONTROLLER)
+#error Please use -DCONTROLLER=SEAGATE or -DCONTROLLER=FD to override controller type
 #endif
 
-
 /*
 	Thanks to Brian Antoine for the example code in his Messy-Loss ST-01
 		driver, and Mitsugu Suzuki for information on the ST-01
@@ -206,7 +199,7 @@
 #define PHASE_MSGIN 0x40
 #define PHASE_MSGOUT 0x80
 #define PHASE_STATUSIN 0x100
-#define PHASE_ETC (PHASE_DATAIN | PHASE_DATA_OUT | PHASE_CMDOUT | PHASE_MSGIN | PHASE_MSGOUT | PHASE_STATUSIN)
+#define PHASE_ETC (PHASE_DATAIN | PHASE_DATAOUT | PHASE_CMDOUT | PHASE_MSGIN | PHASE_MSGOUT | PHASE_STATUSIN)
 #define PRINT_COMMAND 0x200
 #define PHASE_EXIT 0x400
 #define PHASE_RESELECT 0x800
@@ -223,8 +216,6 @@
 #define ST0X_BUS_FREE_DELAY 25
 #define ST0X_SELECTION_DELAY 25
 
-#define eoi() __asm__("push %%eax\nmovb $0x20, %%al\noutb %%al, $0x20\npop %%eax"::)
-	
 #define SEAGATE 1	/* these determine the type of the controller */
 #define FD	2
 
@@ -242,10 +233,6 @@
 static unsigned int base_address = 0;   /* Where the card ROM starts, used to 
                                            calculate memory mapped register
                                            location.  */
-#ifdef notyet
-static volatile int abort_confirm = 0;
-
-#endif
 
 static unsigned long st0x_cr_sr;        /* control register write, status
                                            register read.  256 bytes in
@@ -262,15 +249,13 @@
 static unsigned char controller_type = 0;       /* set to SEAGATE for ST0x
                                                    boards or FD for TMC-8xx
                                                    boards */
-static unsigned char irq = IRQ;
+static int irq = IRQ;
 
 #define retcode(result) (((result) << 16) | (message << 8) | status)
-#define STATUS (readb(st0x_cr_sr))
-#define DATA (readb(st0x_dr))
-/* SJT: Start. */
-#define WRITE_CONTROL(d) writeb((d), st0x_cr_sr)
-#define WRITE_DATA(d) writeb((d), st0x_dr)
-/* SJT: End. */
+#define STATUS ((u8) readb(st0x_cr_sr))
+#define DATA ((u8) readb(st0x_dr))
+#define WRITE_CONTROL(d) { writeb((d), st0x_cr_sr); }
+#define WRITE_DATA(d) { writeb((d), st0x_dr); }
 
 void st0x_setup (char *str, int *ints)
 {
@@ -302,9 +287,8 @@
 }
 Signature;
 
-static const Signature signatures[] =
+static const Signature __initdata signatures[] =
 {
-#ifdef CONFIG_SCSI_SEAGATE
   {"ST01 v1.7  (C) Copyright 1987 Seagate", 15, 37, SEAGATE},
   {"SCSI BIOS 2.00  (C) Copyright 1987 Seagate", 15, 40, SEAGATE},
 
@@ -331,9 +315,7 @@
   {"FUTURE DOMAIN CORP. (C) 1992 V8.00.004/02/92", 5, 44, FD},
   {"IBM F1 BIOS V1.1004/30/92", 5, 25, FD},
   {"FUTURE DOMAIN TMC-950", 5, 21, FD},
-#endif                                  /* CONFIG_SCSI_SEAGATE */
-}
-;
+};
 
 #define NUM_SIGNATURES (sizeof(signatures) / sizeof(Signature))
 #endif /* n OVERRIDE */
@@ -348,10 +330,11 @@
 
 #ifdef FAST
 static int fast = 1;
-
+#else
+#define fast 0
 #endif
 
-#ifdef SLOW_HANDSHAKE
+#ifdef SLOW_RATE
 /*
  * Support for broken devices :
  * The Seagate board has a handshaking problem.  Namely, a lack
@@ -387,10 +370,13 @@
  * the best thing for us to do will be to calibrate a timing
  * loop in the initialization code using the timer chip before
  * gettimeofday() can screw with it.
+ *
+ * FIXME: this is broken (not borken :-). Empty loop costs less than
+ * loop with ISA access in it! -- pavel@ucw.cz
  */
 
 static int borken_calibration = 0;
-static void borken_init (void)
+static void __init borken_init (void)
 {
   register int count = 0, start = jiffies + 1, stop = start + 25;
 
@@ -399,53 +385,47 @@
 
 /*
  * Ok, we now have a count for .25 seconds.  Convert to a
- * count per second and divide by transfer rate in K.
- */
+ * count per second and divide by transfer rate in K.  */
 
   borken_calibration = (count * 4) / (SLOW_RATE * 1024);
 
   if (borken_calibration < 1)
     borken_calibration = 1;
-#if (DEBUG & DEBUG_BORKEN)
-  printk ("scsi%d : borken calibrated to %dK/sec, %d cycles per transfer\n",
-          hostno, BORKEN_RATE, borken_calibration);
-#endif
 }
 
 static inline void borken_wait (void)
 {
   register int count;
 
-  for (count = borken_calibration; count && (STATUS & STAT_REQ);
-       --count) ;
+  for (count = borken_calibration; count && (STATUS & STAT_REQ); --count) ;
 #if (DEBUG & DEBUG_BORKEN)
   if (count)
     printk ("scsi%d : borken timeout\n", hostno);
 #endif
 }
 
-#endif /* def SLOW_HANDSHAKE */
+#endif /* def SLOW_RATE */
+
+/* These beasts only live on ISA, and ISA means 8MHz. Each ULOOP()
+ * contains at least one ISA access, which takes more than 0.125
+ * usec. So if we loop 8 times time in usec, we are safe.
+ */
+
+#define ULOOP( i ) for (clock = i*8;;)
+#define TIMEOUT (!(clock--))
 
-int seagate_st0x_detect (Scsi_Host_Template * tpnt)
+int __init seagate_st0x_detect (Scsi_Host_Template * tpnt)
 {
   struct Scsi_Host *instance;
-
-#ifndef OVERRIDE
   int i, j;
 
-#endif
-
   tpnt->proc_dir = &proc_scsi_seagate;
 /*
- *    First, we try for the manual override.
- */
-#ifdef DEBUG
-  printk ("Autodetecting ST0x / TMC-8xx\n");
-#endif
+ *    First, we try for the manual override.  */
+  DANY ("Autodetecting ST0x / TMC-8xx\n");
 
-  if (hostno != -1)
-  {
-    printk ("ERROR : seagate_st0x_detect() called twice.\n");
+  if (hostno != -1) {
+    printk (KERN_ERR "seagate_st0x_detect() called twice?!\n");
     return 0;
   }
 
@@ -456,17 +436,10 @@
   {
 #ifdef OVERRIDE
     base_address = OVERRIDE;
-
-/* CONTROLLER is used to override controller (SEAGATE or FD). PM: 07/01/93 */
-#ifdef CONTROLLER
     controller_type = CONTROLLER;
-#else
-#error Please use -DCONTROLLER=SEAGATE or -DCONTROLLER=FD to override controller type
-#endif /* CONTROLLER */
-#ifdef DEBUG
-    printk ("Base address overridden to %x, controller type is %s\n",
+
+    DANY("Base address overridden to %x, controller type is %s\n",
             base_address, controller_type == SEAGATE ? "SEAGATE" : "FD");
-#endif
 #else /* OVERRIDE */
 /*
  *    To detect this card, we simply look for the signature
@@ -493,33 +466,46 @@
   tpnt->this_id = (controller_type == SEAGATE) ? 7 : 6;
   tpnt->name = (controller_type == SEAGATE) ? ST0X_ID_STR : FD_ID_STR;
 
-  if (base_address)
-  {
-    st0x_cr_sr = base_address + (controller_type == SEAGATE ? 0x1a00 : 0x1c00);
-    st0x_dr = st0x_cr_sr + 0x200;
-#ifdef DEBUG
-    printk ("%s detected. Base address = %x, cr = %x, dr = %x\n",
-            tpnt->name, base_address, st0x_cr_sr, st0x_dr);
-#endif
+  if (!base_address) {
+    DANY ("ST0x / TMC-8xx not detected.\n");
+    return 0;
+  }
+
+  st0x_cr_sr = base_address + (controller_type == SEAGATE ? 0x1a00 : 0x1c00);
+  st0x_dr = st0x_cr_sr + 0x200;
+
+  DANY ("%s detected. Base address = %x, cr = %x, dr = %x\n",
+	tpnt->name, base_address, st0x_cr_sr, st0x_dr);
+
 /*
  *    At all times, we will use IRQ 5.  Should also check for IRQ3 if we
  *      loose our first interrupt.
  */
-    instance = scsi_register (tpnt, 0);
-    hostno = instance->host_no;
-    if (request_irq ((int) irq, do_seagate_reconnect_intr, SA_INTERRUPT,
-                (controller_type == SEAGATE) ? "seagate" : "tmc-8xx", NULL))
-    {
-      printk ("scsi%d : unable to allocate IRQ%d\n", hostno, (int) irq);
-      return 0;
-    }
-    instance->irq = irq;
-    instance->io_port = base_address;
-#ifdef SLOW_HANDSHAKE
-    borken_init ();
+  instance = scsi_register (tpnt, 0);
+  hostno = instance->host_no;
+  if (request_irq (irq, do_seagate_reconnect_intr, SA_INTERRUPT,
+		   (controller_type == SEAGATE) ? "seagate" : "tmc-8xx", NULL)) {
+    printk ("scsi%d : unable to allocate IRQ%d\n", hostno, irq);
+    return 0;
+  }
+  instance->irq = irq;
+  instance->io_port = base_address;
+#ifdef SLOW_RATE
+  printk( "Calibrating borken timer... " );
+  borken_init ();
+  printk( " %d cycles per transfer\n", borken_calibration );
 #endif
 
-    printk ("%s options:"
+  printk( "This is one second... " );
+  {
+    int clock;
+    ULOOP( 1*1000*1000 ) {
+      volatile int x = STATUS;
+      if (TIMEOUT) break;
+    }
+  }
+
+  printk ("done, %s options:"
 #ifdef ARBITRATE
             " ARBITRATE"
 #endif
@@ -527,10 +513,9 @@
             " DEBUG"
 #endif
 #ifdef FAST
-#ifdef FAST32
-            " FAST32"
-#else
             " FAST"
+#ifdef FAST32
+            "32"
 #endif
 #endif
 #ifdef LINKED
@@ -542,8 +527,8 @@
 #ifdef SEAGATE_USE_ASM
             " SEAGATE_USE_ASM"
 #endif
-#ifdef SLOW_HANDSHAKE
-            " SLOW_HANDSHAKE"
+#ifdef SLOW_RATE
+            " SLOW_RATE"
 #endif
 #ifdef SWAPSTAT
             " SWAPSTAT"
@@ -551,16 +536,8 @@
 #ifdef SWAPCNTDATA
             " SWAPCNTDATA"
 #endif
-            "\n", tpnt->name);
-    return 1;
-  }
-  else
-  {
-#ifdef DEBUG
-    printk ("ST0x / TMC-8xx not detected.\n");
-#endif
-    return 0;
-  }
+	  "\n", tpnt->name);
+  return 1;
 }
 
 const char *seagate_st0x_info (struct Scsi_Host *shpnt)
@@ -585,7 +562,6 @@
 static int current_bufflen;
 
 #ifdef LINKED
-
 /*
  * linked_connected indicates whether or not we are currently connected to
  * linked_target, linked_lun and in an INFORMATION TRANSFER phase,
@@ -594,7 +570,6 @@
 
 static int linked_connected = 0;
 static unsigned char linked_target, linked_lun;
-
 #endif
 
 static void (*done_fn) (Scsi_Cmnd *) = NULL;
@@ -609,17 +584,14 @@
 #define RECONNECT_NOW   1
 #define CAN_RECONNECT   2
 
-#ifdef LINKED
-
 /*
  * LINKED_RIGHT indicates that we are currently connected to the correct target
  * for this command, LINKED_WRONG indicates that we are connected to the wrong
- * target.  Note that these imply CAN_RECONNECT.
+ * target. Note that these imply CAN_RECONNECT and require defined(LINKED).
  */
 
 #define LINKED_RIGHT    3
 #define LINKED_WRONG    4
-#endif
 
 /*
  * This determines if we are expecting to reconnect or not.
@@ -633,8 +605,7 @@
  * asserting SEL.
  */
 
-static void do_seagate_reconnect_intr (int irq, void *dev_id, 
-                                    struct pt_regs *regs)
+static void do_seagate_reconnect_intr (int irq, void *dev_id, struct pt_regs *regs)
 {
   unsigned long flags;
 
@@ -643,15 +614,12 @@
   spin_unlock_irqrestore(&io_request_lock, flags);
 }
 
-static void seagate_reconnect_intr (int irq, void *dev_id, 
-                                    struct pt_regs *regs)
+static void seagate_reconnect_intr (int irq, void *dev_id, struct pt_regs *regs)
 {
   int temp;
   Scsi_Cmnd *SCtmp;
 
-#if (DEBUG & PHASE_RESELECT)
-  printk ("scsi%d : seagate_reconnect_intr() called\n", hostno);
-#endif
+  DPRINTK (PHASE_RESELECT, "scsi%d : seagate_reconnect_intr() called\n", hostno);
 
   if (!should_reconnect)
     printk ("scsi%d: unexpected interrupt.\n", hostno);
@@ -659,11 +627,9 @@
   {
     should_reconnect = 0;
 
-#if (DEBUG & PHASE_RESELECT)
-    printk ("scsi%d : internal_command("
-            "%d, %08x, %08x, %d, RECONNECT_NOW\n", hostno,
+    DPRINTK (PHASE_RESELECT, "scsi%d : internal_command("
+            "%d, %08x, %08x, RECONNECT_NOW\n", hostno,
             current_target, current_data, current_bufflen);
-#endif
 
     temp = internal_command (current_target, current_lun, current_cmnd,
                              current_data, current_bufflen, RECONNECT_NOW);
@@ -672,10 +638,8 @@
     {
       if (done_fn)
       {
-#if (DEBUG & PHASE_RESELECT)
-        printk ("scsi%d : done_fn(%d,%08x)", hostno,
+        DPRINTK (PHASE_RESELECT, "scsi%d : done_fn(%d,%08x)", hostno,
                 hostno, temp);
-#endif
         if (!SCint)
           panic ("SCint == NULL in seagate");
         SCtmp = SCint;
@@ -707,6 +671,7 @@
   int result, reconnect;
   Scsi_Cmnd *SCtmp;
 
+  DANY( "seagate: que_command" );
   done_fn = done;
   current_target = SCpnt->target;
   current_lun = SCpnt->lun;
@@ -714,10 +679,7 @@
   current_data = (unsigned char *) SCpnt->request_buffer;
   current_bufflen = SCpnt->request_bufflen;
   SCint = SCpnt;
-  if (recursion_depth)
-  {
-    return 0;
-  };
+  if (recursion_depth) return 0;
   recursion_depth++;
   do
   {
@@ -729,22 +691,16 @@
     current_cmnd[SCpnt->cmd_len] |= 0x01;
     if (linked_connected)
     {
-#if (DEBUG & DEBUG_LINKED)
-      printk ("scsi%d : using linked commands, current I_T_L nexus is ",
-              hostno);
-#endif
+      DPRINTK (DEBUG_LINKED, 
+	       "scsi%d : using linked commands, current I_T_L nexus is ", hostno);
       if ((linked_target == current_target) && (linked_lun == current_lun))
       {
-#if (DEBUG & DEBUG_LINKED)
-        printk ("correct\n");
-#endif
+        DPRINTK (DEBUG_LINKED, "correct\n");
         reconnect = LINKED_RIGHT;
       }
       else
       {
-#if (DEBUG & DEBUG_LINKED)
-        printk ("incorrect\n");
-#endif
+        DPRINTK (DEBUG_LINKED, "incorrect\n");
         reconnect = LINKED_WRONG;
       }
     }
@@ -753,10 +709,8 @@
       reconnect = CAN_RECONNECT;
 
     result = internal_command (SCint->target, SCint->lun, SCint->cmnd,
-                               SCint->request_buffer, SCint->request_bufflen,
-                               reconnect);
-    if (msg_byte (result) == DISCONNECT)
-      break;
+                               SCint->request_buffer, SCint->request_bufflen, reconnect);
+    if (msg_byte (result) == DISCONNECT) break;
     SCtmp = SCint;
     SCint = NULL;
     SCtmp->result = result;
@@ -775,59 +729,33 @@
 }
 
 static int internal_command (unsigned char target, unsigned char lun, 
-                             const void *cmnd, void *buff, int bufflen, 
-                             int reselect)
+                             const void *cmnd, void *buff, int bufflen, int reselect)
 {
-  int len = 0;
   unsigned char *data = NULL;
   struct scatterlist *buffer = NULL;
-  int nobuffs = 0;
-  int clock;
-  int temp;
-
-#ifdef SLOW_HANDSHAKE
-  int borken;                           /* Does the current target require
-                                           Very Slow I/O ?  */
-#endif
-
-#if (DEBUG & PHASE_DATAIN) || (DEBUG & PHASE_DATOUT)
-  int transfered = 0;
-
-#endif
-
-#if (((DEBUG & PHASE_ETC) == PHASE_ETC) || (DEBUG & PRINT_COMMAND) || \
-     (DEBUG & PHASE_EXIT))
-  int i;
-
-#endif
-
-#if ((DEBUG & PHASE_ETC) == PHASE_ETC)
-  int phase = 0, newphase;
+  int clock, temp, nobuffs = 0, done = 0, len = 0;
+  unsigned long flags;
 
+#ifdef DEBUG
+  int transfered = 0, phase = 0, newphase;
 #endif
 
-  int done = 0;
-  unsigned char status = 0;
-  unsigned char message = 0;
   register unsigned char status_read;
+  unsigned char tmp_data, tmp_control, status = 0, message = 0;
 
-#ifndef OLDCNTDATASCEME
-  volatile unsigned char tmp_data;
-  volatile unsigned char tmp_control;
-#endif
   unsigned transfersize = 0, underflow = 0;
 
+#ifdef SLOW_RATE
+  int borken = (int) SCint->device->borken; /* Does the current target require
+					       Very Slow I/O ?  */
+#endif
+
   incommand = 0;
   st0x_aborted = 0;
 
-#ifdef SLOW_HANDSHAKE
-  borken = (int) SCint->device->borken;
-#endif
-
 #if (DEBUG & PRINT_COMMAND)
   printk ("scsi%d : target = %d, command = ", hostno, target);
   print_command ((unsigned char *) cmnd);
-  printk ("\n");
 #endif
 
 #if (DEBUG & PHASE_RESELECT)
@@ -864,9 +792,7 @@
   switch (reselect)
   {
     case RECONNECT_NOW:
-#if (DEBUG & PHASE_RESELECT)
-      printk ("scsi%d : phase RESELECT \n", hostno);
-#endif
+      DPRINTK ( PHASE_RESELECT, "scsi%d : phase RESELECT \n", hostno);
 
 /*
  *    At this point, we should find the logical or of our ID and the original
@@ -876,19 +802,14 @@
  *      target ID are asserted.  A valid initiator ID is not on the bus
  *      until IO is asserted, so we must wait for that.
  */
-      clock = jiffies + 10;
-      for (;;)
-      {
+      ULOOP( 100*1000 ) {
         temp = STATUS;
         if ((temp & STAT_IO) && !(temp & STAT_BSY))
           break;
 
-        if (jiffies > clock)
-        {
-#if (DEBUG & PHASE_RESELECT)
-          printk ("scsi%d : RESELECT timed out while waiting for IO .\n",
-                  hostno);
-#endif
+        if (TIMEOUT) {
+          DPRINTK (PHASE_RESELECT, 
+		   "scsi%d : RESELECT timed out while waiting for IO .\n", hostno);
           return (DID_BAD_INTR << 16);
         }
       }
@@ -900,10 +821,9 @@
 
       if (!((temp = DATA) & (controller_type == SEAGATE ? 0x80 : 0x40)))
       {
-#if (DEBUG & PHASE_RESELECT)
-        printk ("scsi%d : detected reconnect request to different target.\n"
-                "\tData bus = %d\n", hostno, temp);
-#endif
+        DPRINTK (PHASE_RESELECT,
+		 "scsi%d : detected reconnect request to different target.\n"
+		 "\tData bus = %d\n", hostno, temp);
         return (DID_BAD_INTR << 16);
       }
 
@@ -936,16 +856,14 @@
  *      BSY.
  */
 
-      for (clock = jiffies + 10; (jiffies < clock) && (STATUS & STAT_SEL);) ;
-
-      if (jiffies >= clock)
-      {
-        WRITE_CONTROL (BASE_CMD | CMD_INTR);
-#if (DEBUG & PHASE_RESELECT)
-        printk ("scsi%d : RESELECT timed out while waiting for SEL.\n", 
-                hostno);
-#endif
-        return (DID_BAD_INTR << 16);
+      ULOOP( 100*1000 ) {
+	if (!(STATUS & STAT_SEL)) break;
+	if (TIMEOUT) {
+	  WRITE_CONTROL (BASE_CMD | CMD_INTR);
+	  DPRINTK (PHASE_RESELECT,
+		   "scsi%d : RESELECT timed out while waiting for SEL.\n", hostno);
+	  return (DID_BAD_INTR << 16);
+	}
       }
 
       WRITE_CONTROL (BASE_CMD);
@@ -969,9 +887,7 @@
 
 #endif
 
-#if (DEBUG & PHASE_BUS_FREE)
-      printk ("scsi%d : phase = BUS FREE \n", hostno);
-#endif
+      DPRINTK (PHASE_BUS_FREE, "scsi%d : phase = BUS FREE \n", hostno);
 
 /*
  *    BUS FREE PHASE
@@ -982,12 +898,13 @@
  *      eliminate wire glitch.
  */
 
+#ifndef ARBITRATE
+#error FIXME: this is broken: we may not use jiffies here - we are under cli(). It will hardlock.
       clock = jiffies + ST0X_BUS_FREE_DELAY;
 
-#if !defined (ARBITRATE)
       while (((STATUS | STATUS | STATUS) &
               (STAT_BSY | STAT_SEL)) &&
-             (!st0x_aborted) && (jiffies < clock)) ;
+             (!st0x_aborted) && (jiffies < clock));
 
       if (jiffies > clock)
         return retcode (DID_BUS_BUSY);
@@ -995,9 +912,7 @@
         return retcode (st0x_aborted);
 #endif
 
-#if (DEBUG & PHASE_SELECTION)
-      printk ("scsi%d : phase = SELECTION\n", hostno);
-#endif
+      DPRINTK (PHASE_SELECTION, "scsi%d : phase = SELECTION\n", hostno);
 
       clock = jiffies + ST0X_SELECTION_DELAY;
 
@@ -1012,33 +927,27 @@
  * 6.  Enable SCSI drivers and asserted SEL and ATTN
  */
 
-#if defined(ARBITRATE)
-      { unsigned long flags;
+#ifdef ARBITRATE
       save_flags (flags);
       cli ();
       WRITE_CONTROL (0);
       WRITE_DATA ((controller_type == SEAGATE) ? 0x80 : 0x40);
       WRITE_CONTROL (CMD_START_ARB);
       restore_flags (flags);
-      }
-      while (!((status_read = STATUS) & (STAT_ARB_CMPL | STAT_SEL)) &&
-             (jiffies < clock) && !st0x_aborted) ;
 
-      if (!(status_read & STAT_ARB_CMPL))
-      {
-#if (DEBUG & PHASE_SELECTION)
-        if (status_read & STAT_SEL)
-          printk ("scsi%d : arbitration lost\n", hostno);
-        else
-          printk ("scsi%d : arbitration timeout.\n", hostno);
-#endif
-        WRITE_CONTROL (BASE_CMD);
-        return retcode (DID_NO_CONNECT);
-      };
+      ULOOP( ST0X_SELECTION_DELAY * 10000 ) {
+	status_read = STATUS;
+	if (status_read & STAT_ARB_CMPL) break;
+	if (st0x_aborted)	/* FIXME: What? We are going to do something even after abort? */
+	   break;
+	if (TIMEOUT || (status_read & STAT_SEL)) {
+	  printk( "scsi%d : arbitration lost or timeout.\n", hostno );
+	  WRITE_CONTROL (BASE_CMD);
+	  return retcode (DID_NO_CONNECT);
+	}
+      }
 
-#if (DEBUG & PHASE_SELECTION)
-      printk ("scsi%d : arbitration complete\n", hostno);
-#endif
+      DPRINTK (PHASE_SELECTION, "scsi%d : arbitration complete\n", hostno);
 #endif
 
 /*
@@ -1053,81 +962,53 @@
  *    try this with a SCSI protocol or logic analyzer to see what is
  *    going on.
  */
+       tmp_data = (unsigned char) ((1 << target) | (controller_type == SEAGATE ? 0x80 : 0x40));
+       tmp_control = BASE_CMD | CMD_DRVR_ENABLE | CMD_SEL | (reselect ? CMD_ATTN : 0);
+
+       save_flags(flags);
+       cli();
 #ifdef OLDCNTDATASCEME
 #ifdef SWAPCNTDATA
-      { unsigned long flags;
-        save_flags(flags);
-	cli();
-      WRITE_CONTROL (BASE_CMD | CMD_DRVR_ENABLE | CMD_SEL |
-                     (reselect ? CMD_ATTN : 0));
-      WRITE_DATA ((unsigned char) ((1 << target) |
-                               (controller_type == SEAGATE ? 0x80 : 0x40)));
-	restore_flags(flags);
-      }
+       WRITE_CONTROL (tmp_control);
+       WRITE_DATA (tmp_data);
 #else
-      { unsigned long flags;
-      save_flags(flags);
-      cli ();
-      WRITE_DATA ((unsigned char) ((1 << target) |
-                               (controller_type == SEAGATE ? 0x80 : 0x40)));
-      WRITE_CONTROL (BASE_CMD | CMD_DRVR_ENABLE | CMD_SEL |
-                     (reselect ? CMD_ATTN : 0));
-      restore_flags (flags);
-      }
+       WRITE_DATA (tmp_data);
+       WRITE_CONTROL (tmp_control);
 #endif
 #else
-       tmp_data = (unsigned char) ((1 << target) | (controller_type == SEAGATE 
-? 0x80 : 0x40));
-       tmp_control = BASE_CMD | CMD_DRVR_ENABLE | CMD_SEL |
-                (reselect ? CMD_ATTN : 0) | CMD_BSY;
-       WRITE_CONTROL(tmp_data);
-       WRITE_DATA(tmp_control);
-       tmp_control ^= CMD_BSY;
-       WRITE_CONTROL(tmp_control);
-#endif /* OLDCNTDATASCEME */
-      while (!((status_read = STATUS) & STAT_BSY) && (jiffies < clock)
-             && !st0x_aborted)
-#if 0 && (DEBUG & PHASE_SELECTION)
-      {
-        temp = clock - jiffies;
+       tmp_control ^= CMD_BSY;		/* This is guesswork. What used to be in driver	   */
+       WRITE_CONTROL (tmp_control);	/* could never work: it sent data into control	   */
+       WRITE_DATA (tmp_data);		/* register and control info into data. Hopefully  */
+       tmp_control ^= CMD_BSY;		/* fixed, but order of first two may be wrong.     */
+       WRITE_CONTROL (tmp_control);	                              /* -- pavel@ucw.cz   */
+#endif       
 
-        if (!(jiffies % 5))
-          printk ("seagate_st0x_timeout : %d            \r", temp);
-      }
-      printk ("Done.                                             \n");
-      printk ("scsi%d : status = %02x, seagate_st0x_timeout = %d, aborted = %02x \n",
-              hostno, status_read, temp, st0x_aborted);
-#else
-        ;
-#endif
 
-      if ((jiffies >= clock) && !(status_read & STAT_BSY))
-      {
-#if (DEBUG & PHASE_SELECTION)
-        printk ("scsi%d : NO CONNECT with target %d, status = %x \n",
-                hostno, target, STATUS);
-#endif
-        return retcode (DID_NO_CONNECT);
-      }
+       restore_flags (flags);
 
+       ULOOP( 250*1000 ) {
+	 if (st0x_aborted) {
 /*
  *    If we have been aborted, and we have a command in progress, IE the
  *      target still has BSY asserted, then we will reset the bus, and
  *      notify the midlevel driver to expect sense.
  */
 
-      if (st0x_aborted)
-      {
-        WRITE_CONTROL (BASE_CMD);
-        if (STATUS & STAT_BSY)
-        {
-          printk ("scsi%d : BST asserted after we've been aborted.\n",
-                  hostno);
-          seagate_st0x_reset (NULL, 0);
-          return retcode (DID_RESET);
-        }
-        return retcode (st0x_aborted);
-      }
+	   WRITE_CONTROL (BASE_CMD);
+	   if (STATUS & STAT_BSY) {
+	     printk ("scsi%d : BST asserted after we've been aborted.\n", hostno);
+	     seagate_st0x_reset (NULL, 0);
+	     return retcode (DID_RESET);
+	   }
+	   return retcode (st0x_aborted);
+	 }
+	 if (STATUS & STAT_BSY) break;
+	 if (TIMEOUT) {
+	   DPRINTK (PHASE_SELECTION, "scsi%d : NO CONNECT with target %d, stat = %x \n",
+		    hostno, target, STATUS);
+	   return retcode (DID_NO_CONNECT);
+	 }
+       }
 
 /* Establish current pointers.  Take into account scatter / gather */
 
@@ -1151,17 +1032,13 @@
       }
       else
       {
-#if (DEBUG & DEBUG_SG)
-        printk ("scsi%d : scatter gather not requested.\n", hostno);
-#endif
+        DPRINTK (DEBUG_SG, "scsi%d : scatter gather not requested.\n", hostno);
         buffer = NULL;
         len = SCint->request_bufflen;
         data = (unsigned char *) SCint->request_buffer;
       }
 
-#if (DEBUG & (PHASE_DATAIN | PHASE_DATAOUT))
-      printk ("scsi%d : len = %d\n", hostno, len);
-#endif
+      DPRINTK (PHASE_DATAIN | PHASE_DATAOUT, "scsi%d : len = %d\n", hostno, len);
 
       break;
 #ifdef LINKED
@@ -1205,9 +1082,7 @@
  *
  */
 
-#if ((DEBUG & PHASE_ETC) == PHASE_ETC)
-  printk ("scsi%d : phase = INFORMATION TRANSFER\n", hostno);
-#endif
+  DPRINTK (PHASE_ETC, "scsi%d : phase = INFORMATION TRANSFER\n", hostno);
 
   incommand = 1;
   transfersize = SCint->transfersize;
@@ -1271,12 +1146,10 @@
  * in word-sized chunks as fast as we can.
  */
 
-#ifdef FAST
           if (!len)
           {
 #if 0
-            printk ("scsi%d: underflow to target %d lun %d \n", hostno,
-                    target, lun);
+            printk ("scsi%d: underflow to target %d lun %d \n", hostno, target, lun);
             st0x_aborted = DID_ERROR;
             fast = 0;
 #endif
@@ -1290,11 +1163,10 @@
 #endif
             )
           {
-#if (DEBUG & DEBUG_FAST)
-            printk ("scsi%d : FAST transfer, underflow = %d, transfersize = %d\n"
+            DPRINTK (DEBUG_FAST,
+		     "scsi%d : FAST transfer, underflow = %d, transfersize = %d\n"
                     "         len = %d, data = %08x\n",
                   hostno, SCint->underflow, SCint->transfersize, len, data);
-#endif
 
 /* SJT: Start. Fast Write */
 #ifdef SEAGATE_USE_ASM
@@ -1332,13 +1204,11 @@
 /* SJT: End */
             len -= transfersize;
             data += transfersize;
-#if (DEBUG & DEBUG_FAST)
-            printk ("scsi%d : FAST transfer complete len = %d data = %08x\n",
+            DPRINTK (DEBUG_FAST,
+		     "scsi%d : FAST transfer complete len = %d data = %08x\n",
                     hostno, len, data);
-#endif
           }
           else
-#endif /* ifdef FAST */
           {
 /*
  *    We loop as long as we are in a data out phase, there is data to send,
@@ -1404,15 +1274,14 @@
             ++buffer;
             len = buffer->length;
             data = (unsigned char *) buffer->address;
-#if (DEBUG & DEBUG_SG)
-            printk ("scsi%d : next scatter-gather buffer len = %d address = %08x\n",
+            DPRINTK (DEBUG_SG,
+		    "scsi%d : next scatter-gather buffer len = %d address = %08x\n",
                     hostno, len, data);
-#endif
           }
           break;
 
         case REQ_DATAIN:
-#ifdef SLOW_HANDSHAKE
+#ifdef SLOW_RATE
           if (borken)
           {
 #if (DEBUG & (PHASE_DATAIN))
@@ -1432,7 +1301,7 @@
           }
           else
 #endif
-#ifdef FAST
+
             if (fast && transfersize && !(len % transfersize) &&
                 (len >= transfersize)
 #ifdef FAST32
@@ -1440,11 +1309,11 @@
 #endif
             )
           {
-#if (DEBUG & DEBUG_FAST)
-            printk ("scsi%d : FAST transfer, underflow = %d, transfersize = %d\n"
+            DPRINTK (DEBUG_FAST,
+		     "scsi%d : FAST transfer, underflow = %d, transfersize = %d\n"
                     "         len = %d, data = %08x\n",
                   hostno, SCint->underflow, SCint->transfersize, len, data);
-#endif
+
 /* SJT: Start. Fast Read */
 #ifdef SEAGATE_USE_ASM
             __asm__(
@@ -1486,13 +1355,11 @@
             transfered += transfersize;
 #endif
 
-#if (DEBUG & DEBUG_FAST)
-            printk ("scsi%d : FAST transfer complete len = %d data = %08x\n",
+            DPRINTK (DEBUG_FAST,
+		     "scsi%d : FAST transfer complete len = %d data = %08x\n",
                     hostno, len, data);
-#endif
           }
           else
-#endif
           {
 
 #if (DEBUG & PHASE_DATAIN)
@@ -1571,10 +1438,9 @@
             ++buffer;
             len = buffer->length;
             data = (unsigned char *) buffer->address;
-#if (DEBUG & DEBUG_SG)
-            printk ("scsi%d : next scatter-gather buffer len = %d address = %08x\n",
+            DPRINTK (DEBUG_SG, 
+		     "scsi%d : next scatter-gather buffer len = %d address = %08x\n",
                     hostno, len, data);
-#endif
           }
 
           break;
@@ -1586,7 +1452,7 @@
             {
               WRITE_DATA (*(const unsigned char *) cmnd);
               cmnd = 1 + (const unsigned char *) cmnd;
-#ifdef SLOW_HANDSHAKE
+#ifdef SLOW_RATE
               if (borken)
                 borken_wait ();
 #endif
@@ -1613,9 +1479,7 @@
             case CAN_RECONNECT:
               WRITE_DATA (IDENTIFY (1, lun));
 
-#if (DEBUG & (PHASE_RESELECT | PHASE_MSGOUT))
-              printk ("scsi%d : sent IDENTIFY message.\n", hostno);
-#endif
+              DPRINTK (PHASE_RESELECT | PHASE_MSGOUT, "scsi%d : sent IDENTIFY message.\n", hostno);
               break;
 #ifdef LINKED
             case LINKED_WRONG:
@@ -1623,13 +1487,10 @@
               linked_connected = 0;
               reselect = CAN_RECONNECT;
               goto connect_loop;
-#if (DEBUG & (PHASE_MSGOUT | DEBUG_LINKED))
-              printk ("scsi%d : sent ABORT message to cancel incorrect I_T_L nexus.\n", hostno);
-#endif
+              DPRINTK (PHASE_MSGOUT | DEBUG_LINKED, 
+		       "scsi%d : sent ABORT message to cancel incorrect I_T_L nexus.\n", hostno);
 #endif /* LINKED */
-#if (DEBUG & DEBUG_LINKED)
-              printk ("correct\n");
-#endif
+              DPRINTK (DEBUG_LINKED, "correct\n");
             default:
               WRITE_DATA (NOP);
               printk ("scsi%d : target %d requested MSGOUT, sent NOP message.\n", hostno, target);
@@ -1640,6 +1501,7 @@
           switch (message = DATA)
           {
             case DISCONNECT:
+	      DANY ("seagate: deciding to disconnect\n");
               should_reconnect = 1;
               current_data = data;      /* WDE add */
               current_buffer = buffer;
@@ -1649,9 +1511,7 @@
               linked_connected = 0;
 #endif
               done = 1;
-#if (DEBUG & (PHASE_RESELECT | PHASE_MSGIN))
-              printk ("scsi%d : disconnected.\n", hostno);
-#endif
+              DPRINTK ((PHASE_RESELECT | PHASE_MSGIN), "scsi%d : disconnected.\n", hostno);
               break;
 
 #ifdef LINKED
@@ -1662,15 +1522,11 @@
 /*
  * Note : we should check for underflow here.
  */
-#if (DEBUG & PHASE_MSGIN)
-              printk ("scsi%d : command complete.\n", hostno);
-#endif
+              DPRINTK (PHASE_MSGIN, "scsi%d : command complete.\n", hostno);
               done = 1;
               break;
             case ABORT:
-#if (DEBUG & PHASE_MSGIN)
-              printk ("scsi%d : abort message.\n", hostno);
-#endif
+              DPRINTK (PHASE_MSGIN, "scsi%d : abort message.\n", hostno);
               done = 1;
               break;
             case SAVE_POINTERS:
@@ -1678,9 +1534,7 @@
               current_bufflen = len;    /* WDE add */
               current_data = data;      /* WDE mod */
               current_nobuffs = nobuffs;
-#if (DEBUG & PHASE_MSGIN)
-              printk ("scsi%d : pointers saved.\n", hostno);
-#endif
+              DPRINTK (PHASE_MSGIN, "scsi%d : pointers saved.\n", hostno);
               break;
             case RESTORE_POINTERS:
               buffer = current_buffer;
@@ -1688,15 +1542,13 @@
               data = current_data;      /* WDE mod */
               len = current_bufflen;
               nobuffs = current_nobuffs;
-#if (DEBUG & PHASE_MSGIN)
-              printk ("scsi%d : pointers restored.\n", hostno);
-#endif
+              DPRINTK (PHASE_MSGIN, "scsi%d : pointers restored.\n", hostno);
               break;
             default:
 
 /*
  *    IDENTIFY distinguishes itself from the other messages by setting the
- *      high byte.
+ *      high byte. [FIXME: should not this read "the high bit"? - pavel@ucw.cz]
  *
  *      Note : we need to handle at least one outstanding command per LUN,
  *      and need to hash the SCSI command for that I_T_L nexus based on the
@@ -1705,10 +1557,8 @@
 
               if (message & 0x80)
               {
-#if (DEBUG & PHASE_MSGIN)
-                printk ("scsi%d : IDENTIFY message received from id %d, lun %d.\n",
+                DPRINTK (PHASE_MSGIN, "scsi%d : IDENTIFY message received from id %d, lun %d.\n",
                         hostno, target, message & 7);
-#endif
               }
               else
               {
@@ -1719,10 +1569,8 @@
  *      needs some serious restructuring first though.
  */
 
-#if (DEBUG & PHASE_MSGIN)
-                printk ("scsi%d : unknown message %d from target %d.\n",
-                        hostno, message, target);
-#endif
+                DPRINTK (PHASE_MSGIN, 
+			 "scsi%d : unknown message %d from target %d.\n", hostno, message, target);
               }
           }
           break;
@@ -1733,7 +1581,7 @@
       }                                 /* end of switch (status_read &
                                            REQ_MASK) */
 
-#ifdef SLOW_HANDSHAKE
+#ifdef SLOW_RATE
 /*
  * I really don't care to deal with borken devices in each single
  * byte transfer case (ie, message in, message out, status), so
@@ -1747,9 +1595,8 @@
   }                                     /* while(((status_read = STATUS)...)
                                            ends */
 
-#if (DEBUG & (PHASE_DATAIN | PHASE_DATAOUT | PHASE_EXIT))
-  printk ("scsi%d : Transfered %d bytes\n", hostno, transfered);
-#endif
+  DPRINTK (PHASE_DATAIN | PHASE_DATAOUT | PHASE_EXIT, 
+	   "scsi%d : Transfered %d bytes\n", hostno, transfered);
 
 #if (DEBUG & PHASE_EXIT)
 #if 0                                   /* Doesn't work for scatter/gather */
@@ -1764,17 +1611,6 @@
 #endif
 
 /* We shouldn't reach this until *after* BSY has been deasserted */
-#ifdef notyet
-  if (st0x_aborted)
-  {
-    if (STATUS & STAT_BSY)
-    {
-      seagate_st0x_reset (NULL);
-      st0x_aborted = DID_RESET;
-    }
-    abort_confirm = 1;
-  }
-#endif
 
 #ifdef LINKED
   else
@@ -1797,10 +1633,8 @@
         linked_target = current_target;
         linked_lun = current_lun;
         linked_connected = 1;
-#if (DEBUG & DEBUG_LINKED)
-        printk ("scsi%d : keeping I_T_L nexus established for linked command.\n",
-                hostno);
-#endif
+	DPRINTK (DEBUG_LINKED, "scsi%d : keeping I_T_L nexus established"
+		 "for linked command.\n", hostno);
     /* We also will need to adjust status to accommodate intermediate
        conditions. */
         if ((status == INTERMEDIATE_GOOD) ||
@@ -1814,9 +1648,7 @@
  * and flake if things aren't right.
  */
       default:
-#if (DEBUG & DEBUG_LINKED)
-        printk ("scsi%d : closing I_T_L nexus.\n", hostno);
-#endif
+        DPRINTK (DEBUG_LINKED, "scsi%d : closing I_T_L nexus.\n", hostno);
         linked_connected = 0;
     }
   }
@@ -1824,10 +1656,8 @@
 
   if (should_reconnect)
   {
-#if (DEBUG & PHASE_RESELECT)
-    printk ("scsi%d : exiting seagate_st0x_queue_command() with reconnect enabled.\n",
-            hostno);
-#endif
+    DPRINTK (PHASE_RESELECT, "scsi%d : exiting seagate_st0x_queue_command()"
+	     "with reconnect enabled.\n", hostno);
     WRITE_CONTROL (BASE_CMD | CMD_INTR);
   }
   else
@@ -1841,32 +1671,27 @@
   st0x_aborted = DID_ABORT;
   return SCSI_ABORT_PENDING;
 }
+#undef ULOOP
+#undef TIMEOUT
 
 /*
-   the seagate_st0x_reset function resets the SCSI bus */
+ * the seagate_st0x_reset function resets the SCSI bus 
+ */
 
 int seagate_st0x_reset (Scsi_Cmnd * SCpnt, unsigned int reset_flags)
 {
-  unsigned clock;
-
 /* No timeouts - this command is going to fail because it was reset. */
-#ifdef DEBUG
-  printk ("In seagate_st0x_reset()\n");
-#endif
+  DANY ("scsi%d: Reseting bus... ", hostno );
 
 /* assert  RESET signal on SCSI bus.  */
   WRITE_CONTROL (BASE_CMD | CMD_RST);
-  clock = jiffies + 2;
 
-/* Wait.  */
-  while (jiffies < clock) ;
+  udelay( 20*1000 );
 
   WRITE_CONTROL (BASE_CMD);
   st0x_aborted = DID_RESET;
 
-#ifdef DEBUG
-  printk ("SCSI bus reset.\n");
-#endif
+  DANY ("done.\n");
   return SCSI_RESET_WAKEUP;
 }
 
diff -u --recursive --new-file v2.1.117/linux/drivers/scsi/seagate.h linux/drivers/scsi/seagate.h
--- v2.1.117/linux/drivers/scsi/seagate.h	Sun Dec 21 17:04:49 1997
+++ linux/drivers/scsi/seagate.h	Sun Aug 23 13:42:08 1998
@@ -20,10 +20,6 @@
 const char *seagate_st0x_info(struct Scsi_Host *);
 int seagate_st0x_reset(Scsi_Cmnd *, unsigned int); 
 
-#ifndef NULL
-	#define NULL 0
-#endif
-
 #include <linux/kdev_t.h>
 int seagate_st0x_biosparam(Disk *, kdev_t, int*);
 
diff -u --recursive --new-file v2.1.117/linux/drivers/scsi/sg.c linux/drivers/scsi/sg.c
--- v2.1.117/linux/drivers/scsi/sg.c	Sat May  2 14:19:53 1998
+++ linux/drivers/scsi/sg.c	Mon Aug 24 13:14:10 1998
@@ -574,6 +574,7 @@
     sg_ioctl,        /* ioctl */
     NULL,            /* mmap */
     sg_open,         /* open */
+    NULL,	     /* flush */
     sg_close,        /* release */
     NULL             /* fsync */
 };
diff -u --recursive --new-file v2.1.117/linux/drivers/scsi/st.c linux/drivers/scsi/st.c
--- v2.1.117/linux/drivers/scsi/st.c	Thu May  7 22:51:51 1998
+++ linux/drivers/scsi/st.c	Mon Aug 24 13:14:10 1998
@@ -3162,6 +3162,7 @@
    st_ioctl,        /* ioctl */
    NULL,            /* mmap */
    scsi_tape_open,  /* open */
+   NULL,	    /* flush */
    scsi_tape_close, /* release */
    NULL		    /* fsync */
 };
diff -u --recursive --new-file v2.1.117/linux/drivers/sgi/char/graphics.c linux/drivers/sgi/char/graphics.c
--- v2.1.117/linux/drivers/sgi/char/graphics.c	Wed Dec 10 10:31:11 1997
+++ linux/drivers/sgi/char/graphics.c	Mon Aug 24 13:02:44 1998
@@ -274,6 +274,7 @@
 	sgi_graphics_ioctl,	/* ioctl */
 	sgi_graphics_mmap,	/* mmap */
 	sgi_graphics_open,	/* open */
+	NULL,			/* flush */
 	sgi_graphics_close,	/* release */
 	NULL,			/* fsync */
 	NULL,			/* check_media_change */
diff -u --recursive --new-file v2.1.117/linux/drivers/sgi/char/shmiq.c linux/drivers/sgi/char/shmiq.c
--- v2.1.117/linux/drivers/sgi/char/shmiq.c	Tue Jul 28 14:21:08 1998
+++ linux/drivers/sgi/char/shmiq.c	Mon Aug 24 13:14:10 1998
@@ -445,6 +445,7 @@
         shmiq_qcntl_ioctl,      /* ioctl */
         shmiq_qcntl_mmap,       /* mmap */
         shmiq_qcntl_open,       /* open */
+	NULL,			/* flush */
         shmiq_qcntl_close,      /* close */
         NULL,                   /* fsync */
         shmiq_qcntl_fasync,     /* fasync */
diff -u --recursive --new-file v2.1.117/linux/drivers/sgi/char/streamable.c linux/drivers/sgi/char/streamable.c
--- v2.1.117/linux/drivers/sgi/char/streamable.c	Wed Dec 10 10:31:11 1997
+++ linux/drivers/sgi/char/streamable.c	Mon Aug 24 13:14:10 1998
@@ -79,6 +79,7 @@
 	sgi_gfx_ioctl,		/* ioctl */
 	NULL,			/* mmap */
 	sgi_gfx_open,		/* open */
+	NULL,			/* flush */
 	sgi_gfx_close,		/* release */
 	NULL,			/* fsync */
 	NULL,			/* check_media_change */
@@ -199,6 +200,7 @@
 	sgi_keyb_ioctl,		/* ioctl */
 	NULL,			/* mmap */
 	sgi_keyb_open,		/* open */
+	NULL,			/* flush */
 	NULL,			/* release */
 	NULL,			/* fsync */
 	NULL,			/* check_media_change */
@@ -339,6 +341,7 @@
 	sgi_mouse_ioctl,	/* ioctl */
 	NULL,			/* mmap */
 	sgi_mouse_open,		/* open */
+	NULL,			/* flush */
 	sgi_mouse_close,	/* release */
 	NULL,			/* fsync */
 	NULL,			/* check_media_change */
diff -u --recursive --new-file v2.1.117/linux/drivers/sgi/char/usema.c linux/drivers/sgi/char/usema.c
--- v2.1.117/linux/drivers/sgi/char/usema.c	Tue Jul 28 14:21:08 1998
+++ linux/drivers/sgi/char/usema.c	Mon Aug 24 13:02:44 1998
@@ -172,6 +172,7 @@
 	sgi_usemaclone_ioctl,	/* ioctl */
 	NULL,			/* mmap */
 	sgi_usemaclone_open,	/* open */
+	NULL,			/* flush */
 	sgi_usemaclone_release,	/* release */
 	NULL,			/* fsync */
 	NULL,			/* check_media_change */
diff -u --recursive --new-file v2.1.117/linux/drivers/sound/Config.in linux/drivers/sound/Config.in
--- v2.1.117/linux/drivers/sound/Config.in	Thu Aug 20 17:05:16 1998
+++ linux/drivers/sound/Config.in	Thu Aug 20 14:30:25 1998
@@ -156,7 +156,7 @@
 
   dep_tristate 'Support for Crystal CS4232 based (PnP) cards' CONFIG_SOUND_CS4232 $CONFIG_SOUND_OSS
   if [ "$CONFIG_SOUND_CS4232" = "y" ]; then
-      hex 'CS4232 audio I/O base 530, 604, E80 or F40' CONFIG_CS4232_BASE 530
+      hex 'CS4232 audio I/O base (normally 530, 604, E80 or F40)' CONFIG_CS4232_BASE 530
       int 'CS4232 audio IRQ 5, 7, 9, 11, 12 or 15' CONFIG_CS4232_IRQ 11
       int 'CS4232 audio DMA 0, 1 or 3' CONFIG_CS4232_DMA 0
       int 'CS4232 second (duplex) DMA 0, 1 or 3' CONFIG_CS4232_DMA2 3
diff -u --recursive --new-file v2.1.117/linux/drivers/sound/dmasound.c linux/drivers/sound/dmasound.c
--- v2.1.117/linux/drivers/sound/dmasound.c	Thu Aug  6 14:06:33 1998
+++ linux/drivers/sound/dmasound.c	Mon Aug 24 13:02:44 1998
@@ -3808,6 +3808,7 @@
 	mixer_ioctl,
 	NULL,			/* mixer_mmap */
 	mixer_open,
+	NULL,			/* flush */
 	mixer_release,
 };
 
@@ -4169,6 +4170,7 @@
 	sq_ioctl,
 	NULL,			/* sq_mmap */
 	sq_open,
+	NULL,			/* flush */
 	sq_release,
 };
 
@@ -4363,6 +4365,7 @@
 	NULL,			/* state_ioctl */
 	NULL,			/* state_mmap */
 	state_open,
+	NULL,			/* flush */
 	state_release,
 };
 
diff -u --recursive --new-file v2.1.117/linux/drivers/sound/es1370.c linux/drivers/sound/es1370.c
--- v2.1.117/linux/drivers/sound/es1370.c	Thu Aug 20 17:05:16 1998
+++ linux/drivers/sound/es1370.c	Mon Aug 24 13:02:44 1998
@@ -977,6 +977,7 @@
 	&es1370_ioctl_mixdev,
 	NULL,  /* mmap */
 	&es1370_open_mixdev,
+	NULL,	/* flush */
 	&es1370_release_mixdev,
 	NULL,  /* fsync */
 	NULL,  /* fasync */
@@ -1626,6 +1627,7 @@
 	&es1370_ioctl,
 	&es1370_mmap,
 	&es1370_open,
+	NULL,	/* flush */
 	&es1370_release,
 	NULL,  /* fsync */
 	NULL,  /* fasync */
@@ -1992,6 +1994,7 @@
 	&es1370_ioctl_dac,
 	&es1370_mmap_dac,
 	&es1370_open_dac,
+	NULL,	/* flush */
 	&es1370_release_dac,
 	NULL,  /* fsync */
 	NULL,  /* fasync */
@@ -2228,6 +2231,7 @@
 	NULL,  /* ioctl */
 	NULL,  /* mmap */
 	&es1370_midi_open,
+	NULL,	/* flush */
 	&es1370_midi_release,
 	NULL,  /* fsync */
 	NULL,  /* fasync */
diff -u --recursive --new-file v2.1.117/linux/drivers/sound/es1371.c linux/drivers/sound/es1371.c
--- v2.1.117/linux/drivers/sound/es1371.c	Thu Aug 20 17:05:16 1998
+++ linux/drivers/sound/es1371.c	Mon Aug 24 13:02:44 1998
@@ -1425,6 +1425,7 @@
 	&es1371_ioctl_mixdev,
 	NULL,  /* mmap */
 	&es1371_open_mixdev,
+	NULL,	/* flush */
 	&es1371_release_mixdev,
 	NULL,  /* fsync */
 	NULL,  /* fasync */
@@ -2072,6 +2073,7 @@
 	&es1371_ioctl,
 	&es1371_mmap,
 	&es1371_open,
+	NULL,	/* flush */
 	&es1371_release,
 	NULL,  /* fsync */
 	NULL,  /* fasync */
@@ -2428,6 +2430,7 @@
 	&es1371_ioctl_dac,
 	&es1371_mmap_dac,
 	&es1371_open_dac,
+	NULL,	/* flush */
 	&es1371_release_dac,
 	NULL,  /* fsync */
 	NULL,  /* fasync */
@@ -2663,6 +2666,7 @@
 	NULL,  /* ioctl */
 	NULL,  /* mmap */
 	&es1371_midi_open,
+	NULL,	/* flush */
 	&es1371_midi_release,
 	NULL,  /* fsync */
 	NULL,  /* fasync */
diff -u --recursive --new-file v2.1.117/linux/drivers/sound/lowlevel/README linux/drivers/sound/lowlevel/README
--- v2.1.117/linux/drivers/sound/lowlevel/README	Tue Oct 28 02:10:48 1997
+++ linux/drivers/sound/lowlevel/README	Sun Aug 23 13:32:25 1998
@@ -11,7 +11,8 @@
 The following low level drivers are included:
 
 - ACI MIXER for miroPCM12 by Markus Kuhn
-(mskuhn@cip.informatik.uni-erlangen.de).
+  (mskuhn@cip.informatik.uni-erlangen.de).
+- Audio Excel DSP 16 initialization driver by Riccardo Facchetti
+  (fizban@tin.it)
 - SB32/AWE synthesizer driver (Emu8000) by Takashi Iwai
-(iwai@dragon.mm.t.u-tokyo.ac.jp). See README.awe for more
-info.
+  (iwai@dragon.mm.t.u-tokyo.ac.jp). See README.awe for more info.
diff -u --recursive --new-file v2.1.117/linux/drivers/sound/lowlevel/README.aedsp16 linux/drivers/sound/lowlevel/README.aedsp16
--- v2.1.117/linux/drivers/sound/lowlevel/README.aedsp16	Sun Jan  4 10:40:16 1998
+++ linux/drivers/sound/lowlevel/README.aedsp16	Wed Dec 31 16:00:00 1969
@@ -1,137 +0,0 @@
-Driver
-------
-
-Informations about Audio Excel DSP 16 driver can be found in the source
-file lowlevel/aedsp16.c
-Please, read the head of the source before using it. It contain useful
-informations.
-
-Configuration
--------------
-
-The Audio Excel configuration, is now done with the standard Linux setup.
-You have to configure the sound card (Sound Blaster or Microsoft Sound System)
-and, if you want it, the Roland MPU-401 (do not use the Sound Blaster MPU-401,
-SB-MPU401) in the main driver menu. Activate the lowlevel drivers then select
-the Audio Excel hardware that you want to initialize. Check the IRQ/DMA/MIRQ
-of the Audio Excel initialization: it must be the same as the SBPRO (or MSS)
-setup. If the parameters are different, correct it.
-I you own a Gallant's audio card based on SC-6600, activate the SC-6600 support.
-If you want to change the configuration of the sound board, be sure to
-check off all the configuration items before re-configure it.
-
-Module parameters
------------------
-To use this driver as a module, you must configure some module parameters, to
-set up I/O addresses, IRQ lines and DMA channels. Some parameters are
-mandatory while some others are optional. Here a list of parameters you can
-use with this module:
-
-Name		Description
-====		===========
-MANDATORY
-io		I/O base address (0x220 or 0x240)
-irq		irq line (5, 7, 9, 10 or 11)
-dma		dma channel (0, 1 or 3)
-
-OPTIONAL
-mss_base	I/O base address for activate MSS mode (default SBPRO)
-		(0x530 or 0xE80)
-mpu_base	I/O base address for activate MPU-401 mode
-		(0x300, 0x310, 0x320 or 0x330)
-mpu_irq		MPU-401 irq line (5, 7, 9, 10 or 0)
-
-The /etc/conf.modules will have a line like this:
-
-options aedsp16 io=0x220 irq=10 dma=3 mss_base=0x530
-
-Of course, you must write the 'options' for all other subsequent modules,
-opl3, ad1848, adlib_card, sb
-
-Then you must load the sound modules stack in this order:
-sound -> aedsp16 -> [ ad1848, opl3 ]
-
-Sound cards supported
----------------------
-This driver supports the SC-6000 and SC-6600 based Gallant's sound card.
-It don't support the Audio Excel DSP 16 III (try the SC-6600 code).
-I'm working on the III version of the card: if someone have useful
-informations about it, please let me know.
-For all the non-supported audio cards, you have to boot MS-DOS (or WIN95)
-activating the audio card with the MS-DOS device driver, then you have to
-<ctrl>-<alt>-<del> and boot Linux.
-Follow these steps:
-
-1) Compile Linux kernel with standard sound driver, using the emulation
-   you want, with the parameters of your audio card,
-   e.g. Microsoft Sound System irq10 dma3
-2) Install your new kernel as the default boot kernel.
-3) Boot MS-DOS and configure the audio card with the boot time device
-   driver, for MSS irq10 dma3 in our example.
-4) <ctrl>-<alt>-<del> and boot Linux. This will mantain the DOS configuration
-   and will boot the new kernel with sound driver. The sound driver will find
-   the audio card and will recognize and attach it.
-
-Reports on User successes
--------------------------
-
-[--------------------------------------------------------------------------]
-
-From POPmail Mon Jul 29 18:23:12 1996
-Received: from cdc8g5.cdc.polimi.it by mbox.vol.it with SMTP
-	(1.39.111.2/16.2) id AA257995686; Mon, 29 Jul 1996 09:34:46 +0200
-Return-Path: <sjg95@unixfe.rl.ac.uk>
-Received: from [130.246.12.16] by cdc8g5.cdc.polimi.it with SMTP
-	(1.38.193.4/15.6) id AA27426; Mon, 29 Jul 1996 09:42:49 +0200
-Posted-Date: Mon, 29 Jul 1996 08:35:40 +0100
-Received-Date: Mon, 29 Jul 1996 09:42:49 +0200
-Received: (from sjg95@localhost) by unixfe.rl.ac.uk (8.7.3/8.7.3) 
-          id IAA58788 for riccardo@cdc8g5.cdc.polimi.it; Mon, 29 Jul 1996 08:35:40 +0100
-Date: Mon, 29 Jul 1996 08:35:40 +0100
-From: Mr S J Greenaway <sjg95@unixfe.rl.ac.uk>
-Message-Id: <199607290735.IAA58788@unixfe.rl.ac.uk>
-To: riccardo@cdc8g5.cdc.polimi.it (Riccardo Facchetti)
-Subject: Re: Audio Excel DSP 16 initialization code
-Newsgroups: comp.os.linux.announce
-X-Newsreader: TIN [version 1.2 PL2]
-Status: RO
-X-Status: A
-
-Just to let you know got my Audio Excel (emulating a MSS) working
-with my original SB16, thanks for the driver!
-
-/dev/sndstat:
-
-Linux huey 2.0.9 #10 Sat Jul 27 11:41:42 BST 1996 i586)
-Kernel: Linux huey 2.0.9 #14 Sun Jul 28 12:50:43 BST 1996 i586
-Config options: c0202
-
-Installed drivers: 
-Type 10: MS Sound System
-Type 24: MS Sound System (AXP)
-Type 27: Compaq Deskpro XL
-Type 2: Sound Blaster
-
-Card config: 
-MS Sound System at 0x530 irq 11 drq 3
-Sound Blaster at 0x240 irq 5 drq 1,5
-
-Audio devices:
-0: MSS audio codec (CS4231A)
-1: Sound Blaster 16 (4.12)
-
-Synth devices:
-
-Midi devices: NOT ENABLED IN CONFIG
-
-Timers:
-0: System clock
-1: MSS audio codec (CS4231A)
-
-Mixers:
-0: MSS audio codec (CS4231A)
-1: Sound Blaster
-
-[--------------------------------------------------------------------------]
-
-    Riccardo
diff -u --recursive --new-file v2.1.117/linux/drivers/sound/lowlevel/aci.c linux/drivers/sound/lowlevel/aci.c
--- v2.1.117/linux/drivers/sound/lowlevel/aci.c	Thu Aug 20 17:05:16 1998
+++ linux/drivers/sound/lowlevel/aci.c	Sun Aug 23 13:32:25 1998
@@ -4,17 +4,21 @@
  * ACI is a protocol used to communicate with the microcontroller on
  * some sound cards produced by miro, e.g. the miroSOUND PCM12 and
  * PCM20. The ACI has been developed for miro by Norberto Pellicci
- * <pellicci@ix.netcom.com>. Special thanks to both him and miro for
+ * <pellicci@home.com>. Special thanks to both him and miro for
  * providing the ACI specification.
  *
  * The main function of the ACI is to control the mixer and to get a
  * product identification. On the PCM20, ACI also controls the radio
- * tuner on this card, however this is not yet supported in this
- * software.
+ * tuner on this card, this is supported in the Video for Linux 
+ * radio-miropcm20 driver.
  * 
  * This Voxware ACI driver currently only supports the ACI functions
- * on the miroSOUND PCM12 card. Support for miro sound cards with
- * additional ACI functions can easily be added later.
+ * on the miroSOUND PCM12 and PCM20 card. Support for miro sound cards 
+ * with additional ACI functions can easily be added later.
+ *
+ * / NOTE / When compiling as a module, make sure to load the module 
+ * after loading the mad16 module. The initialisation code expects the
+ * MAD16 default mixer to be already available.
  *
  * / NOTE / When compiling as a module, make sure to load the module 
  * after loading the mad16 module. The initialisation code expects the
@@ -31,8 +35,9 @@
  *   1996-05-28  Markus Kuhn
  *        Initialize CS4231A mixer, make ACI first mixer,
  *        use new private mixer API for solo mode.
- *   1998-08-04  Ruurd Reitsma <R.A.Reitsma@wbmt.tudelft.nl>
- *	  Small modification to complete modularisation.
+ *   1998-08-18  Ruurd Reitsma <R.A.Reitsma@wbmt.tudelft.nl>
+ *	  Small modification to export ACI functions and 
+ *	  complete modularisation.
  */
 
 /*
@@ -84,7 +89,7 @@
 #ifdef MODULE                  /* Whether the aci mixer is to be reset.    */
 int aci_reset = 0;             /* Default: don't reset if the driver is a  */
 MODULE_PARM(aci_reset,"i");
-#else                          /* module; use "insmod sound.o aci_reset=1" */
+#else                          /* module; use "insmod aci.o aci_reset=1" */
 int aci_reset = 1;             /* to override.                             */
 #endif
 
@@ -150,12 +155,12 @@
  * If a problem occurred, they return -1.
  */
 
-static int implied_cmd(unsigned char opcode)
+int aci_implied_cmd(unsigned char opcode)
 {
   unsigned long flags;
 
 #ifdef DEBUG
-  printk("ACI: implied_cmd(0x%02x)\n", opcode);
+  printk("ACI: aci_implied_cmd(0x%02x)\n", opcode);
 #endif
 
   save_flags(flags);
@@ -172,13 +177,13 @@
 }
 
 
-static int write_cmd(unsigned char opcode, unsigned char parameter)
+int aci_write_cmd(unsigned char opcode, unsigned char parameter)
 {
   unsigned long flags;
   int status;
 
 #ifdef DEBUG
-  printk("ACI: write_cmd(0x%02x, 0x%02x)\n", opcode, parameter);
+  printk("ACI: aci_write_cmd(0x%02x, 0x%02x)\n", opcode, parameter);
 #endif
 
   save_flags(flags);
@@ -209,8 +214,53 @@
   return 0;
 }
 
+/*
+ * This write command send 2 parameters instead of one.
+ * Only used in PCM20 radio frequency tuning control
+ */
+
+int aci_write_cmd_d(unsigned char opcode, unsigned char parameter, unsigned char parameter2)
+{
+  unsigned long flags;
+  int status;
+
+#ifdef DEBUG
+  printk("ACI: aci_write_cmd_d(0x%02x, 0x%02x)\n", opcode, parameter, parameter2);
+#endif
+
+  save_flags(flags);
+  cli();
+  
+  if (read_general_status() < 0 || busy_wait()) {
+    restore_flags(flags);
+    return -1;
+  }
+  outb_p(opcode, COMMAND_REGISTER);
+  if (busy_wait()) { restore_flags(flags); return -1; }
+  outb_p(parameter, COMMAND_REGISTER);
+  if (busy_wait()) { restore_flags(flags); return -1; }
+  outb_p(parameter2, COMMAND_REGISTER);
+
+  if ((status = read_general_status()) < 0) {
+    restore_flags(flags);
+    return -1;
+  }
+  /* polarity of the INVALID flag depends on ACI version */
+  if ((aci_version <  0xb0 && (status & 0x40) != 0) ||
+      (aci_version >= 0xb0 && (status & 0x40) == 0)) {
+    restore_flags(flags);
+#if 0	/* Frequency tuning works, but the INVALID flag is set ??? */
+    printk("ACI: invalid write (double) command 0x%02x, 0x%02x, 0x%02x.\n",
+	   opcode, parameter, parameter2);
+#endif
+    return -1;
+  }
+
+  restore_flags(flags);
+  return 0;
+}
 
-static int read_cmd(unsigned char opcode, int length, unsigned char *parameter)
+int aci_read_cmd(unsigned char opcode, int length, unsigned char *parameter)
 {
   unsigned long flags;
   int i = 0;
@@ -226,10 +276,10 @@
     parameter[i++] = inb_p(STATUS_REGISTER);
 #ifdef DEBUG
     if (i == 1)
-      printk("ACI: read_cmd(0x%02x, %d) = 0x%02x\n", opcode, length,
+      printk("ACI: aci_read_cmd(0x%02x, %d) = 0x%02x\n", opcode, length,
 	     parameter[i-1]);
     else
-      printk("ACI: read_cmd cont.: 0x%02x\n", parameter[i-1]);
+      printk("ACI: aci_read_cmd cont.: 0x%02x\n", parameter[i-1]);
 #endif
   }
 
@@ -238,7 +288,7 @@
 }
 
 
-static int indexed_cmd(unsigned char opcode, unsigned char index,
+int aci_indexed_cmd(unsigned char opcode, unsigned char index,
 		       unsigned char *parameter)
 {
   unsigned long flags;
@@ -256,7 +306,7 @@
   if (busy_wait()) { restore_flags(flags); return -1; }
   *parameter = inb_p(STATUS_REGISTER);
 #ifdef DEBUG
-  printk("ACI: indexed_cmd(0x%02x, 0x%02x) = 0x%02x\n", opcode, index,
+  printk("ACI: aci_indexed_cmd(0x%02x, 0x%02x) = 0x%02x\n", opcode, index,
 	 *parameter);
 #endif
 
@@ -292,10 +342,10 @@
   unsigned char buf;
 
   /* left channel */
-  if (indexed_cmd(0xf0, left_index, &buf)) return -EIO;
+  if (aci_indexed_cmd(0xf0, left_index, &buf)) return -EIO;
   vol = SCALE(0x20, 100, buf < 0x20 ? 0x20-buf : 0);
   /* right channel */
-  if (indexed_cmd(0xf0, right_index, &buf)) return -EIO;
+  if (aci_indexed_cmd(0xf0, right_index, &buf)) return -EIO;
   vol |= SCALE(0x20, 100, buf < 0x20 ? 0x20-buf : 0) << 8;
 
   return (*(int *) arg = vol);
@@ -311,13 +361,13 @@
   vol = *(int *)arg & 0xff;
   if (vol > 100) vol = 100;
   vol = SCALE(100, 0x20, vol);
-  if (write_cmd(left_index, 0x20 - vol)) return -EIO;
+  if (aci_write_cmd(left_index, 0x20 - vol)) return -EIO;
   ret = SCALE(0x20, 100, vol);
   /* right channel */
   vol = (*(int *)arg >> 8) & 0xff;
   if (vol > 100) vol = 100;
   vol = SCALE(100, 0x20, vol);
-  if (write_cmd(right_index, 0x20 - vol)) return -EIO;
+  if (aci_write_cmd(right_index, 0x20 - vol)) return -EIO;
   ret |= SCALE(0x20, 100, vol) << 8;
  
   return (*(int *) arg = ret);
@@ -334,7 +384,7 @@
   if (cmd == SOUND_MIXER_PRIVATE1) {
     if (*(int *) arg >= 0) {
       aci_solo = !!*(int *) arg;
-      if (write_cmd(0xd2, aci_solo)) return -EIO;
+      if (aci_write_cmd(0xd2, aci_solo)) return -EIO;
     } else if (aci_version >= 0xb0) {
       if ((status = read_general_status()) < 0) return -EIO;
       return (*(int *) arg = (status & 0x20) == 0);
@@ -366,7 +416,7 @@
 	vol = *(int *) arg & 0xff;
 	if (vol > 100) vol = 100;
 	vol = SCALE(100, 3, vol);
-	if (write_cmd(0x03, vol)) return -EIO;
+	if (aci_write_cmd(0x03, vol)) return -EIO;
 	vol = SCALE(3, 100, vol);
 	return (*(int *) arg = vol | (vol << 8));
       case SOUND_MIXER_RECSRC:
@@ -421,7 +471,7 @@
       case SOUND_MIXER_LINE2:  /* AUX2 */
 	return getvolume(arg, 0x13, 0x12);
       case SOUND_MIXER_IGAIN:  /* MIC pre-amp */
-	if (indexed_cmd(0xf0, 0x21, &buf)) return -EIO;
+	if (aci_indexed_cmd(0xf0, 0x21, &buf)) return -EIO;
 	vol = SCALE(3, 100, buf <= 3 ? buf : 3);
 	vol |= vol << 8;
 	return (*(int *) arg = vol);
@@ -485,13 +535,13 @@
     return 0;
   }
 
-  if (read_cmd(0xf2, 2, aci_idcode)) {
+  if (aci_read_cmd(0xf2, 2, aci_idcode)) {
 #ifdef DEBUG
     printk("ACI: Failed to read idcode.\n");
 #endif
     return 0;
   }
-  if (read_cmd(0xf1, 1, &aci_version)) {
+  if (aci_read_cmd(0xf1, 1, &aci_version)) {
 #ifdef DEBUG
     printk("ACI: Failed to read version.\n");
 #endif
@@ -523,7 +573,7 @@
 
   if (aci_reset) {
     /* initialize ACI mixer */
-    implied_cmd(0xff);
+    aci_implied_cmd(0xff);
     aci_solo = 0;
   }
 
diff -u --recursive --new-file v2.1.117/linux/drivers/sound/lowlevel/aedsp16.c linux/drivers/sound/lowlevel/aedsp16.c
--- v2.1.117/linux/drivers/sound/lowlevel/aedsp16.c	Tue Feb 17 13:12:47 1998
+++ linux/drivers/sound/lowlevel/aedsp16.c	Sun Aug 23 13:32:25 1998
@@ -26,6 +26,7 @@
 #include <linux/config.h>
 #include <linux/delay.h>
 #include <linux/module.h>
+#include <linux/init.h>
 #include "../sound_config.h"
 #include "../soundmodule.h"
 
@@ -248,6 +249,10 @@
      the flexibility of modular version, I have removed all the conditional
      compilation for SBPRO, MPU and MSS code. Now it is all managed with
      the ae_config structure.
+   v1.2
+   - Module informations added.
+   - Removed aedsp16_delay_10msec(), now using mdelay(10)
+   - All data and funcs moved to .*.init section.
 
    Known Problems:
    - Audio Excel DSP 16 III don't work with this driver.
@@ -259,7 +264,7 @@
  */
 
 
-#define VERSION "1.1"		/* Version of Audio Excel DSP 16 driver */
+#define VERSION "1.2"		/* Version of Audio Excel DSP 16 driver */
 
 #undef	AEDSP16_DEBUG 1		/* Define this to enable debug code     */
 #undef	AEDSP16_DEBUG_MORE 1	/* Define this to enable more debug     */
@@ -421,14 +426,14 @@
 #define INIT_MSS    (1<<1)
 #define INIT_MPU401 (1<<2)
 
-static int      soft_cfg = 0;	/* Will contain or'ed values of soft cf */
-static int      soft_cfg_1 = 0;	/* Will contain or'ed values of some cf */
-static int      gc = 0;		/* generic counter (utility counter)    */
-static int      ver[3];         /* DSP Version, hi<-ver[0], lo<-ver[1]  */
+static int      soft_cfg __initdata = 0;	/* bitmapped config */
+static int      soft_cfg_mss __initdata = 0;	/* bitmapped mss config */
+static int      ver[CARDVERLEN] __initdata = {0, 0};	/* DSP Ver:
+						   hi->ver[0] lo->ver[1] */
 
 #if defined(CONFIG_SC6600)
 static int	hard_cfg[2]     /* lo<-hard_cfg[0] hi<-hard_cfg[1]      */
-                     = { 0, 0};
+                     __initdata = { 0, 0};
 #endif /* CONFIG_SC6600 */
 
 #if defined(CONFIG_SC6600)
@@ -440,7 +445,10 @@
 	int wssbase;
 	int cdrom;
 	int cdrombase;
-} decoded_hcfg;
+};
+
+struct d_hcfg decoded_hcfg __initdata = {0, };
+
 #endif /* CONFIG_SC6600 */
 
 /* orVals contain the values to be or'ed       				*/
@@ -464,7 +472,7 @@
  * Magic values that the DSP will eat when configuring irq/mirq/dma
  */
 /* DSP IRQ conversion array             */
-static struct orVals orIRQ[] = {
+static struct orVals orIRQ[] __initdata = {
 	{0x05, 0x28},
 	{0x07, 0x08},
 	{0x09, 0x10},
@@ -474,7 +482,7 @@
 };
 
 /* MPU-401 IRQ conversion array         */
-static struct orVals orMIRQ[] = {
+static struct orVals orMIRQ[] __initdata = {
 	{0x05, 0x04},
 	{0x07, 0x44},
 	{0x09, 0x84},
@@ -483,14 +491,14 @@
 };
 
 /* DMA Channels conversion array        */
-static struct orVals orDMA[] = {
+static struct orVals orDMA[] __initdata = {
 	{0x00, 0x01},
 	{0x01, 0x02},
 	{0x03, 0x03},
 	{0x00, 0x00}
 };
 
-static struct aedsp16_info ae_config = {
+static struct aedsp16_info ae_config __initdata = {
 	DEF_AEDSP16_IOB,
 	DEF_AEDSP16_IRQ,
 	DEF_AEDSP16_MRQ,
@@ -503,16 +511,10 @@
 /*
  * Buffers to store audio card informations
  */
-static char     DSPCopyright[CARDNAMELEN + 1];
-static char     DSPVersion[CARDVERLEN + 1];
+static char     DSPCopyright[CARDNAMELEN + 1] __initdata = {0, };
+static char     DSPVersion[CARDVERLEN + 1] __initdata = {0, };
 
-static void aedsp16_delay_10msec(void)
-{
-	for (gc = 0; gc < 1000; gc++)
-		udelay(10);
-}
-
-static int aedsp16_wait_data(int port)
+static int __init aedsp16_wait_data(int port)
 {
 	int             loop = STATUSRETRY;
 	unsigned char   ret = 0;
@@ -535,7 +537,7 @@
 	return FALSE;
 }
 
-static int aedsp16_read(int port)
+static int __init aedsp16_read(int port)
 {
 	int inbyte;
 
@@ -553,12 +555,12 @@
 	return inbyte;
 }
 
-static int aedsp16_test_dsp(int port)
+static int __init aedsp16_test_dsp(int port)
 {
 	return ((aedsp16_read(port) == 0xaa) ? TRUE : FALSE);
 }
 
-static int aedsp16_dsp_reset(int port)
+static int __init aedsp16_dsp_reset(int port)
 {
 	/*
 	 * Reset DSP
@@ -579,7 +581,7 @@
 	return FALSE;
 }
 
-static int aedsp16_write(int port, int cmd)
+static int __init aedsp16_write(int port, int cmd)
 {
 	unsigned char   ret;
 	int             loop = HARDRETRY;
@@ -607,7 +609,7 @@
 #if defined(CONFIG_SC6600)
 
 #if defined(AEDSP16_INFO) || defined(AEDSP16_DEBUG)
-void aedsp16_pinfo(void) {
+void __init aedsp16_pinfo(void) {
 	DBG(("\n Base address:  %x\n", decoded_hcfg.iobase));
 	DBG((" Joystick    : %s present\n", decoded_hcfg.joystick?"":" not"));
 	DBG((" WSS addr    :  %x\n", decoded_hcfg.wssbase));
@@ -617,7 +619,7 @@
 }
 #endif
 
-void aedsp16_hard_decode(void) {
+void __init aedsp16_hard_decode(void) {
 
 	DBG((" aedsp16_hard_decode: 0x%x, 0x%x\n", hard_cfg[0], hard_cfg[1]));
 
@@ -661,7 +663,7 @@
 	DBG(("success.\n"));
 }
 
-void aedsp16_hard_encode(void) {
+void __init aedsp16_hard_encode(void) {
 
 	DBG((" aedsp16_hard_encode: 0x%x, 0x%x\n", hard_cfg[0], hard_cfg[1]));
 
@@ -686,7 +688,7 @@
 
 }
 
-static int aedsp16_hard_write(int port) {
+static int __init aedsp16_hard_write(int port) {
 
 	DBG(("aedsp16_hard_write:\n"));
 
@@ -721,7 +723,7 @@
 	return TRUE;
 }
 
-static int aedsp16_hard_read(int port) {
+static int __init aedsp16_hard_read(int port) {
 
 	DBG(("aedsp16_hard_read:\n"));
 
@@ -755,7 +757,7 @@
 	return TRUE;
 }
 
-static int aedsp16_ext_cfg_write(int port) {
+static int __init aedsp16_ext_cfg_write(int port) {
 
 	int extcfg, val;
 
@@ -809,7 +811,7 @@
 
 #endif /* CONFIG_SC6600 */
 
-static int aedsp16_cfg_write(int port) {
+static int __init aedsp16_cfg_write(int port) {
 	if (aedsp16_write(port, WRITE_MDIRQ_CFG)) {
 		printk("[AEDSP16] CMD 0x%x: failed!\n", WRITE_MDIRQ_CFG);
 		return FALSE;
@@ -821,11 +823,11 @@
 	return TRUE;
 }
 
-static int aedsp16_init_mss(int port)
+static int __init aedsp16_init_mss(int port)
 {
 	DBG(("aedsp16_init_mss:\n"));
 
-	aedsp16_delay_10msec();
+	mdelay(10);
 
 	if (aedsp16_write(port, DSP_INIT_MSS)) {
 		printk("[AEDSP16] aedsp16_init_mss [0x%x]: failed!\n",
@@ -833,19 +835,20 @@
 		DBG(("failure.\n"));
 		return FALSE;
 	}
-	aedsp16_delay_10msec();
+	
+	mdelay(10);
 
 	if (aedsp16_cfg_write(port) == FALSE)
 		return FALSE;
 
-	outb(soft_cfg_1, ae_config.mss_base);
+	outb(soft_cfg_mss, ae_config.mss_base);
 
 	DBG(("success.\n"));
 
 	return TRUE;
 }
 
-static int aedsp16_setup_board(int port) {
+static int __init aedsp16_setup_board(int port) {
 	int	loop = RETRY;
 
 #if defined(CONFIG_SC6600)
@@ -873,7 +876,7 @@
 			printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_88);
 			return FALSE;
 		}
-		aedsp16_delay_10msec();
+		mdelay(10);
 	} while ((aedsp16_wait_data(port) == FALSE) && loop--);
 
 	if (aedsp16_read(port) == -1) {
@@ -934,7 +937,7 @@
 	return TRUE;
 }
 
-static int aedsp16_stdcfg(int port) {
+static int __init aedsp16_stdcfg(int port) {
 	if (aedsp16_write(port, WRITE_MDIRQ_CFG)) {
 		printk("[AEDSP16] CMD 0x%x: failed!\n", WRITE_MDIRQ_CFG);
 		return FALSE;
@@ -949,7 +952,7 @@
 	return TRUE;
 }
 
-static int aedsp16_dsp_version(int port)
+static int __init aedsp16_dsp_version(int port)
 {
 	int             len = 0;
 	int             ret;
@@ -980,7 +983,7 @@
 	return TRUE;
 }
 
-static int aedsp16_dsp_copyright(int port)
+static int __init aedsp16_dsp_copyright(int port)
 {
 	int             len = 0;
 	int             ret;
@@ -1016,29 +1019,31 @@
 	return TRUE;
 }
 
-static void aedsp16_init_tables(void)
+static void __init aedsp16_init_tables(void)
 {
+	int i = 0;
+
 	memset(DSPCopyright, 0, CARDNAMELEN + 1);
 	memset(DSPVersion, 0, CARDVERLEN + 1);
 
-	for (gc = 0; orIRQ[gc].or; gc++)
-		if (orIRQ[gc].val == ae_config.irq) {
-			soft_cfg |= orIRQ[gc].or;
-			soft_cfg_1 |= orIRQ[gc].or;
+	for (i = 0; orIRQ[i].or; i++)
+		if (orIRQ[i].val == ae_config.irq) {
+			soft_cfg |= orIRQ[i].or;
+			soft_cfg_mss |= orIRQ[i].or;
 		}
 
-	for (gc = 0; orMIRQ[gc].or; gc++)
-		if (orMIRQ[gc].or == ae_config.mpu_irq)
-			soft_cfg |= orMIRQ[gc].or;
-
-	for (gc = 0; orDMA[gc].or; gc++)
-		if (orDMA[gc].val == ae_config.dma) {
-			soft_cfg |= orDMA[gc].or;
-			soft_cfg_1 |= orDMA[gc].or;
+	for (i = 0; orMIRQ[i].or; i++)
+		if (orMIRQ[i].or == ae_config.mpu_irq)
+			soft_cfg |= orMIRQ[i].or;
+
+	for (i = 0; orDMA[i].or; i++)
+		if (orDMA[i].val == ae_config.dma) {
+			soft_cfg |= orDMA[i].or;
+			soft_cfg_mss |= orDMA[i].or;
 		}
 }
 
-static int aedsp16_init_board(void)
+static int __init aedsp16_init_board(void)
 {
 	aedsp16_init_tables();
 
@@ -1134,12 +1139,12 @@
 	printk("]\n");
 #endif /* MODULE || AEDSP16_INFO || AEDSP16_DEBUG */
 
-	aedsp16_delay_10msec();
+	mdelay(10);
 
 	return TRUE;
 }
 
-static int init_aedsp16_sb(void)
+static int __init init_aedsp16_sb(void)
 {
 	DBG(("init_aedsp16_sb: "));
 
@@ -1159,7 +1164,7 @@
 	return TRUE;
 }
 
-static void uninit_aedsp16_sb(void)
+static void __init uninit_aedsp16_sb(void)
 {
 	DBG(("uninit_aedsp16_sb: "));
 
@@ -1168,7 +1173,7 @@
 	DBG(("done.\n"));
 }
 
-static int init_aedsp16_mss(void)
+static int __init init_aedsp16_mss(void)
 {
 	DBG(("init_aedsp16_mss: "));
 
@@ -1207,7 +1212,7 @@
 	return TRUE;
 }
 
-static void uninit_aedsp16_mss(void)
+static void __init uninit_aedsp16_mss(void)
 {
 	DBG(("uninit_aedsp16_mss: "));
 
@@ -1221,7 +1226,7 @@
 	DBG(("done.\n"));
 }
 
-static int init_aedsp16_mpu(void)
+static int __init init_aedsp16_mpu(void)
 {
 	DBG(("init_aedsp16_mpu: "));
 
@@ -1251,7 +1256,7 @@
 	return TRUE;
 }
 
-static void uninit_aedsp16_mpu(void)
+static void __init uninit_aedsp16_mpu(void)
 {
 	DBG(("uninit_aedsp16_mpu: "));
 
@@ -1266,7 +1271,7 @@
 	DBG(("done.\n"));
 }
 
-int init_aedsp16(void)
+int __init init_aedsp16(void)
 {
 	int initialized = FALSE;
 
@@ -1324,7 +1329,7 @@
 	return initialized;
 }
 
-void uninit_aedsp16(void)
+void __init uninit_aedsp16(void)
 {
 	if (ae_config.mss_base != -1)
 		uninit_aedsp16_mss();
@@ -1344,12 +1349,20 @@
 int mpu_base = -1;
 
 
-MODULE_PARM(io,"i");
-MODULE_PARM(irq,"i");
-MODULE_PARM(dma,"i");
-MODULE_PARM(mpu_irq,"i");
-MODULE_PARM(mss_base,"i");
-MODULE_PARM(mpu_base,"i");
+MODULE_PARM(io, "i");
+MODULE_PARM_DESC(io, "I/O base address (0x220 0x240)");
+MODULE_PARM(irq, "i");
+MODULE_PARM_DESC(irq, "IRQ line (5 7 9 10 11)");
+MODULE_PARM(dma, "i");
+MODULE_PARM_DESC(dma, "dma line (0 1 3)");
+MODULE_PARM(mpu_irq, "i");
+MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ line (5 7 9 10 0)");
+MODULE_PARM(mss_base, "i");
+MODULE_PARM_DESC(mss_base, "MSS emulation I/O base address (0x530 0xE80)");
+MODULE_PARM(mpu_base, "i");
+MODULE_PARM_DESC(mpu_base,"MPU-401 I/O base address (0x300 0x310 0x320 0x330)");
+MODULE_AUTHOR("Riccardo Facchetti <fizban@tin.it>");
+MODULE_DESCRIPTION("Audio Excel DSP 16 Driver Version " VERSION);
 
 int init_module(void) {
 	printk("Audio Excel DSP 16 init driver Copyright (C) Riccardo Facchetti 1995-98\n");
diff -u --recursive --new-file v2.1.117/linux/drivers/sound/lowlevel/miroaci.h linux/drivers/sound/lowlevel/miroaci.h
--- v2.1.117/linux/drivers/sound/lowlevel/miroaci.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/sound/lowlevel/miroaci.h	Sun Aug 23 13:32:25 1998
@@ -0,0 +1,6 @@
+extern int aci_implied_cmd(unsigned char opcode);
+extern int aci_write_cmd(unsigned char opcode, unsigned char parameter);
+extern int aci_write_cmd_d(unsigned char opcode, unsigned char parameter, unsigned char parameter2);
+extern int aci_read_cmd(unsigned char opcode, int length, unsigned char *parameter);
+extern int aci_indexed_cmd(unsigned char opcode, unsigned char index, unsigned char *parameter);
+
diff -u --recursive --new-file v2.1.117/linux/drivers/sound/lowlevel/soundlow.c linux/drivers/sound/lowlevel/soundlow.c
--- v2.1.117/linux/drivers/sound/lowlevel/soundlow.c	Tue Jun  9 11:57:30 1998
+++ linux/drivers/sound/lowlevel/soundlow.c	Sun Aug 23 13:32:25 1998
@@ -5,6 +5,7 @@
 #include "lowlevel.h"
 #include <linux/config.h>
 #include <linux/module.h>
+#include <linux/init.h>
 #include "../soundvers.h"
 
 #ifdef LOWLEVEL_MODULE
@@ -15,8 +16,8 @@
 extern void unload_aci(void);
 extern int attach_awe(void);
 extern void unload_awe(void);
-extern int init_aedsp16(void);
-extern void uninit_aedsp16(void);
+extern int init_aedsp16(void) __init;
+extern void uninit_aedsp16(void) __init;
 
 /*
  * There are two places where you can insert initialization calls of
diff -u --recursive --new-file v2.1.117/linux/drivers/sound/msnd_pinnacle.c linux/drivers/sound/msnd_pinnacle.c
--- v2.1.117/linux/drivers/sound/msnd_pinnacle.c	Thu Aug 20 17:05:16 1998
+++ linux/drivers/sound/msnd_pinnacle.c	Mon Aug 24 13:14:09 1998
@@ -944,6 +944,7 @@
 	dev_ioctl,
 	NULL,
 	dev_open,
+	NULL,		/* flush */
 	dev_close,
 };
 
diff -u --recursive --new-file v2.1.117/linux/drivers/sound/sb_common.c linux/drivers/sound/sb_common.c
--- v2.1.117/linux/drivers/sound/sb_common.c	Thu Aug 20 17:05:16 1998
+++ linux/drivers/sound/sb_common.c	Thu Aug 20 14:30:25 1998
@@ -694,7 +694,7 @@
 	return 1;
 }
 
-static int sb_dsp_init(struct address_info *hw_config)
+int sb_dsp_init(struct address_info *hw_config)
 {
 	sb_devc *devc;
 	char name[100];
diff -u --recursive --new-file v2.1.117/linux/drivers/sound/sonicvibes.c linux/drivers/sound/sonicvibes.c
--- v2.1.117/linux/drivers/sound/sonicvibes.c	Thu Aug 20 17:05:16 1998
+++ linux/drivers/sound/sonicvibes.c	Mon Aug 24 13:14:10 1998
@@ -1208,6 +1208,7 @@
 	&sv_ioctl_mixdev,
 	NULL,  /* mmap */
 	&sv_open_mixdev,
+	NULL,	/* flush */
 	&sv_release_mixdev,
 	NULL,  /* fsync */
 	NULL,  /* fasync */
@@ -1810,6 +1811,7 @@
 	&sv_ioctl,
 	&sv_mmap,
 	&sv_open,
+	NULL,	/* flush */
 	&sv_release,
 	NULL,  /* fsync */
 	NULL,  /* fasync */
@@ -2054,6 +2056,7 @@
 	NULL,  /* ioctl */
 	NULL,  /* mmap */
 	&sv_midi_open,
+	NULL,	/* flush */
 	&sv_midi_release,
 	NULL,  /* fsync */
 	NULL,  /* fasync */
@@ -2227,6 +2230,7 @@
 	&sv_dmfm_ioctl,
 	NULL,  /* mmap */
 	&sv_dmfm_open,
+	NULL,	/* flush */
 	&sv_dmfm_release,
 	NULL,  /* fsync */
 	NULL,  /* fasync */
diff -u --recursive --new-file v2.1.117/linux/drivers/sound/sound_core.c linux/drivers/sound/sound_core.c
--- v2.1.117/linux/drivers/sound/sound_core.c	Thu Jul 16 18:09:27 1998
+++ linux/drivers/sound/sound_core.c	Mon Aug 24 13:14:10 1998
@@ -262,6 +262,7 @@
 	NULL,
 	NULL,
 	NULL,
+	NULL,
 	NULL
 };
 
diff -u --recursive --new-file v2.1.117/linux/drivers/sound/soundcard.c linux/drivers/sound/soundcard.c
--- v2.1.117/linux/drivers/sound/soundcard.c	Thu Aug 20 17:05:16 1998
+++ linux/drivers/sound/soundcard.c	Mon Aug 24 13:14:10 1998
@@ -769,6 +769,7 @@
 	sound_ioctl,
 	sound_mmap,
 	sound_open,
+	NULL,			/* flush */
 	sound_release
 };
 
diff -u --recursive --new-file v2.1.117/linux/drivers/zorro/proc.c linux/drivers/zorro/proc.c
--- v2.1.117/linux/drivers/zorro/proc.c	Mon Aug  3 12:45:47 1998
+++ linux/drivers/zorro/proc.c	Mon Aug 24 13:14:10 1998
@@ -71,6 +71,7 @@
 	NULL,		/* ioctl */
 	NULL,		/* mmap */
 	NULL,		/* no special open code */
+	NULL,		/* flush */
 	NULL,		/* no special release code */
 	NULL		/* can't fsync */
 };
diff -u --recursive --new-file v2.1.117/linux/fs/adfs/dir.c linux/fs/adfs/dir.c
--- v2.1.117/linux/fs/adfs/dir.c	Tue Jan 20 16:44:58 1998
+++ linux/fs/adfs/dir.c	Mon Aug 24 13:02:44 1998
@@ -27,6 +27,7 @@
 	NULL,			/* ioctl */
 	NULL,			/* mmap */
 	NULL,			/* no special open code */
+	NULL,			/* flush */
 	NULL,			/* no special release code */
 	file_fsync,		/* fsync */
 	NULL,			/* fasync */
diff -u --recursive --new-file v2.1.117/linux/fs/adfs/file.c linux/fs/adfs/file.c
--- v2.1.117/linux/fs/adfs/file.c	Wed Jun 24 22:54:08 1998
+++ linux/fs/adfs/file.c	Mon Aug 24 13:02:44 1998
@@ -40,6 +40,7 @@
 	NULL,			/* ioctl		*/
 	generic_file_mmap,	/* mmap			*/
 	NULL,			/* open - not special	*/
+	NULL,			/* flush		*/
 	NULL,			/* release		*/
 	file_fsync,		/* fsync		*/
 	NULL,			/* fasync		*/
diff -u --recursive --new-file v2.1.117/linux/fs/affs/dir.c linux/fs/affs/dir.c
--- v2.1.117/linux/fs/affs/dir.c	Wed Jun 24 22:54:08 1998
+++ linux/fs/affs/dir.c	Mon Aug 24 13:02:44 1998
@@ -36,6 +36,7 @@
 	NULL,			/* ioctl - default */
 	NULL,			/* mmap */
 	NULL,			/* no special open code */
+	NULL,			/* flush */
 	NULL,			/* no special release code */
 	file_fsync		/* default fsync */
 };
diff -u --recursive --new-file v2.1.117/linux/fs/affs/file.c linux/fs/affs/file.c
--- v2.1.117/linux/fs/affs/file.c	Wed Jun 24 22:54:08 1998
+++ linux/fs/affs/file.c	Mon Aug 24 13:02:44 1998
@@ -52,6 +52,7 @@
 	NULL,			/* ioctl - default */
 	generic_file_mmap,	/* mmap */
 	NULL,			/* no special open */
+	NULL,			/* flush */
 	NULL,			/* release */
 	file_fsync,		/* brute force, but works */
 	NULL,			/* fasync */
@@ -92,6 +93,7 @@
 	NULL,			/* ioctl - default */
 	NULL,			/* mmap */
 	NULL,			/* no special open */
+	NULL,			/* flush */
 	NULL,			/* release */
 	file_fsync,		/* brute force, but works */
 	NULL,			/* fasync */
diff -u --recursive --new-file v2.1.117/linux/fs/autofs/dir.c linux/fs/autofs/dir.c
--- v2.1.117/linux/fs/autofs/dir.c	Sun Sep  7 14:00:19 1997
+++ linux/fs/autofs/dir.c	Mon Aug 24 13:02:44 1998
@@ -53,6 +53,7 @@
 	NULL,			/* ioctl */
 	NULL,			/* mmap */
 	NULL,			/* open */
+	NULL,			/* flush */
 	NULL,			/* release */
 	NULL,			/* fsync */
 	NULL,			/* fasync */
diff -u --recursive --new-file v2.1.117/linux/fs/autofs/root.c linux/fs/autofs/root.c
--- v2.1.117/linux/fs/autofs/root.c	Tue Aug 18 22:02:05 1998
+++ linux/fs/autofs/root.c	Mon Aug 24 13:14:10 1998
@@ -32,6 +32,7 @@
         autofs_root_ioctl,	/* ioctl */
         NULL,                   /* mmap */
         NULL,                   /* open */
+	NULL,			/* flush */
         NULL,                   /* release */
         NULL,			/* fsync */
 	NULL,			/* fasync */
diff -u --recursive --new-file v2.1.117/linux/fs/bad_inode.c linux/fs/bad_inode.c
--- v2.1.117/linux/fs/bad_inode.c	Fri Jan 30 11:28:08 1998
+++ linux/fs/bad_inode.c	Mon Aug 24 12:32:39 1998
@@ -38,6 +38,7 @@
 	EIO_ERROR,		/* ioctl */
 	EIO_ERROR,		/* mmap */
 	EIO_ERROR,		/* open */
+	EIO_ERROR,		/* flush */
 	EIO_ERROR,		/* release */
 	EIO_ERROR,		/* fsync */
 	EIO_ERROR,		/* fasync */
diff -u --recursive --new-file v2.1.117/linux/fs/binfmt_aout.c linux/fs/binfmt_aout.c
--- v2.1.117/linux/fs/binfmt_aout.c	Tue Aug 18 22:02:05 1998
+++ linux/fs/binfmt_aout.c	Thu Aug 20 15:13:00 1998
@@ -318,7 +318,6 @@
 		return -ENOEXEC;
 	}
 
-	current->personality = PER_LINUX;
 	fd_offset = N_TXTOFF(ex);
 
 #ifdef __i386__
@@ -350,6 +349,8 @@
 		return retval;
 
 	/* OK, This is the point of no return */
+	current->personality = PER_LINUX;
+
 #if defined(__sparc__) && !defined(__sparc_v9__)
 	memcpy(&current->tss.core_exec, &ex, sizeof(struct exec));
 #endif
@@ -563,7 +564,7 @@
 }
 
 
-__initfunc(int init_aout_binfmt(void))
+int __init init_aout_binfmt(void)
 {
 	return register_binfmt(&aout_format);
 }
diff -u --recursive --new-file v2.1.117/linux/fs/binfmt_elf.c linux/fs/binfmt_elf.c
--- v2.1.117/linux/fs/binfmt_elf.c	Thu Aug 20 17:05:17 1998
+++ linux/fs/binfmt_elf.c	Thu Aug 20 14:32:48 1998
@@ -1331,7 +1331,7 @@
 }
 #endif		/* USE_ELF_CORE_DUMP */
 
-__initfunc(int init_elf_binfmt(void))
+int __init init_elf_binfmt(void)
 {
 	return register_binfmt(&elf_format);
 }
diff -u --recursive --new-file v2.1.117/linux/fs/binfmt_em86.c linux/fs/binfmt_em86.c
--- v2.1.117/linux/fs/binfmt_em86.c	Sun Jul 13 21:20:10 1997
+++ linux/fs/binfmt_em86.c	Thu Aug 20 14:32:48 1998
@@ -110,7 +110,7 @@
 #endif
 };
 
-__initfunc(int init_em86_binfmt(void))
+int __init init_em86_binfmt(void)
 {
 	return register_binfmt(&em86_format);
 }
diff -u --recursive --new-file v2.1.117/linux/fs/binfmt_java.c linux/fs/binfmt_java.c
--- v2.1.117/linux/fs/binfmt_java.c	Mon Jul 14 10:28:48 1997
+++ linux/fs/binfmt_java.c	Thu Aug 20 14:32:48 1998
@@ -174,7 +174,7 @@
 #endif
 };
 
-__initfunc(int init_java_binfmt(void))
+int __init init_java_binfmt(void)
 {
 	register_binfmt(&java_format);
 	return register_binfmt(&applet_format);
diff -u --recursive --new-file v2.1.117/linux/fs/binfmt_misc.c linux/fs/binfmt_misc.c
--- v2.1.117/linux/fs/binfmt_misc.c	Tue Apr 14 14:29:24 1998
+++ linux/fs/binfmt_misc.c	Thu Aug 20 14:32:48 1998
@@ -488,7 +488,7 @@
 }
 #endif
 
-__initfunc(int init_misc_binfmt(void))
+int __init init_misc_binfmt(void)
 {
 	struct proc_dir_entry *status = NULL, *reg;
 	int error = -ENOMEM;
diff -u --recursive --new-file v2.1.117/linux/fs/binfmt_script.c linux/fs/binfmt_script.c
--- v2.1.117/linux/fs/binfmt_script.c	Sun Jul 13 21:20:10 1997
+++ linux/fs/binfmt_script.c	Thu Aug 20 14:32:48 1998
@@ -107,7 +107,7 @@
 #endif
 };
 
-__initfunc(int init_script_binfmt(void))
+int __init init_script_binfmt(void)
 {
 	return register_binfmt(&script_format);
 }
diff -u --recursive --new-file v2.1.117/linux/fs/buffer.c linux/fs/buffer.c
--- v2.1.117/linux/fs/buffer.c	Wed Jun 24 22:54:08 1998
+++ linux/fs/buffer.c	Thu Aug 20 14:33:11 1998
@@ -1736,7 +1736,7 @@
  * Use gfp() for the hash table to decrease TLB misses, use
  * SLAB cache for buffer heads.
  */
-__initfunc(void buffer_init(void))
+void __init buffer_init(void)
 {
 	int order = 5;		/* Currently maximum order.. */
 	unsigned int nr_hash;
diff -u --recursive --new-file v2.1.117/linux/fs/coda/dir.c linux/fs/coda/dir.c
--- v2.1.117/linux/fs/coda/dir.c	Mon Aug  3 12:45:47 1998
+++ linux/fs/coda/dir.c	Mon Aug 24 13:02:44 1998
@@ -96,6 +96,7 @@
         NULL,                   /* ioctl */
         NULL,                   /* mmap */
         coda_open,              /* open */
+	NULL,			/* flush */
         coda_release,           /* release */
 	coda_fsync,             /* fsync */
         NULL,                   
diff -u --recursive --new-file v2.1.117/linux/fs/coda/file.c linux/fs/coda/file.c
--- v2.1.117/linux/fs/coda/file.c	Sun Jun  7 11:16:36 1998
+++ linux/fs/coda/file.c	Mon Aug 24 13:02:44 1998
@@ -66,6 +66,7 @@
 	NULL,		        /* ioctl */
 	coda_file_mmap,         /* mmap */
 	coda_open,              /* open */
+	NULL,			/* flush */
 	coda_release,           /* release */
 	coda_fsync,		/* fsync */
 	NULL,                   /* fasync */
diff -u --recursive --new-file v2.1.117/linux/fs/coda/pioctl.c linux/fs/coda/pioctl.c
--- v2.1.117/linux/fs/coda/pioctl.c	Thu Jul 16 18:09:28 1998
+++ linux/fs/coda/pioctl.c	Mon Aug 24 13:14:10 1998
@@ -65,6 +65,7 @@
 	coda_pioctl,	        /* ioctl */
 	NULL,                   /* mmap */
 	coda_ioctl_open,        /* open */
+	NULL,			/* flush */
 	coda_ioctl_release,     /* release */
 	NULL,		        /* fsync */
 };
diff -u --recursive --new-file v2.1.117/linux/fs/coda/psdev.c linux/fs/coda/psdev.c
--- v2.1.117/linux/fs/coda/psdev.c	Tue Jul 21 00:15:32 1998
+++ linux/fs/coda/psdev.c	Mon Aug 24 13:14:10 1998
@@ -391,6 +391,7 @@
       NULL,                  /* ioctl */
       NULL,		     /* coda_psdev_mmap */
       coda_psdev_open,       /* open */
+      NULL,                  /* flush */
       coda_psdev_release,    /* release */
       NULL,                  /* fsync */
       NULL,                  /* fasync */
diff -u --recursive --new-file v2.1.117/linux/fs/dcache.c linux/fs/dcache.c
--- v2.1.117/linux/fs/dcache.c	Thu Aug 20 17:05:17 1998
+++ linux/fs/dcache.c	Thu Aug 20 14:33:11 1998
@@ -916,7 +916,7 @@
 	return ino;
 }
 
-__initfunc(void dcache_init(void))
+void __init dcache_init(void)
 {
 	int i;
 	struct list_head *d = dentry_hashtable;
diff -u --recursive --new-file v2.1.117/linux/fs/devices.c linux/fs/devices.c
--- v2.1.117/linux/fs/devices.c	Mon Aug  3 12:45:47 1998
+++ linux/fs/devices.c	Mon Aug 24 12:33:11 1998
@@ -261,6 +261,7 @@
 	NULL,		/* ioctl */
 	NULL,		/* mmap */
 	blkdev_open,	/* open */
+	NULL,		/* flush */
 	NULL,		/* release */
 };
 
@@ -313,6 +314,7 @@
 	NULL,		/* ioctl */
 	NULL,		/* mmap */
 	chrdev_open,	/* open */
+	NULL,		/* flush */
 	NULL,		/* release */
 };
 
diff -u --recursive --new-file v2.1.117/linux/fs/devpts/inode.c linux/fs/devpts/inode.c
--- v2.1.117/linux/fs/devpts/inode.c	Thu Aug  6 14:06:33 1998
+++ linux/fs/devpts/inode.c	Thu Aug 20 18:33:50 1998
@@ -77,13 +77,15 @@
 {
 	int setuid = 0;
 	int setgid = 0;
-	uid_t uid = 0;		/* To shut up gcc */
+	uid_t uid = 0;
 	gid_t gid = 0;
 	umode_t mode = 0600;
 	char *this_char, *value;
 
-	if ( !options ) return 1;
-	for (this_char = strtok(options,","); this_char; this_char = strtok(NULL,",")) {
+	this_char = NULL;
+	if ( options )
+		this_char = strtok(options,",");
+	for ( ; this_char; this_char = strtok(NULL,",")) {
 		if ((value = strchr(this_char,'=')) != NULL)
 			*value++ = 0;
 		if (!strcmp(this_char,"uid")) {
diff -u --recursive --new-file v2.1.117/linux/fs/devpts/root.c linux/fs/devpts/root.c
--- v2.1.117/linux/fs/devpts/root.c	Thu Aug  6 14:06:33 1998
+++ linux/fs/devpts/root.c	Mon Aug 24 13:14:10 1998
@@ -29,6 +29,7 @@
 	NULL,			/* ioctl */
 	NULL,                   /* mmap */
 	NULL,                   /* open */
+	NULL,			/* flush */
 	NULL,                   /* release */
 	NULL,			/* fsync */
 	NULL,			/* fasync */
diff -u --recursive --new-file v2.1.117/linux/fs/dquot.c linux/fs/dquot.c
--- v2.1.117/linux/fs/dquot.c	Thu Aug  6 14:06:33 1998
+++ linux/fs/dquot.c	Thu Aug 20 14:33:35 1998
@@ -1063,7 +1063,7 @@
 }
 
 
-__initfunc(void dquot_init_hash(void))
+void __init dquot_init_hash(void)
 {
 	printk(KERN_NOTICE "VFS: Diskquotas version %s initialized\n", __DQUOT_VERSION__);
 
diff -u --recursive --new-file v2.1.117/linux/fs/exec.c linux/fs/exec.c
--- v2.1.117/linux/fs/exec.c	Tue Aug 18 22:02:06 1998
+++ linux/fs/exec.c	Thu Aug 20 14:33:35 1998
@@ -67,7 +67,7 @@
 
 static struct linux_binfmt *formats = (struct linux_binfmt *) NULL;
 
-__initfunc(void binfmt_setup(void))
+void __init binfmt_setup(void)
 {
 #ifdef CONFIG_BINFMT_MISC
 	init_misc_binfmt();
diff -u --recursive --new-file v2.1.117/linux/fs/ext2/balloc.c linux/fs/ext2/balloc.c
--- v2.1.117/linux/fs/ext2/balloc.c	Thu May 14 19:47:43 1998
+++ linux/fs/ext2/balloc.c	Mon Aug 24 10:25:14 1998
@@ -213,7 +213,7 @@
 	if (sb->u.ext2_sb.s_loaded_block_bitmaps > 0 &&
 	    sb->u.ext2_sb.s_block_bitmap_number[0] == block_group &&
 	    sb->u.ext2_sb.s_block_bitmap[block_group]) {
-		slot = 0;
+		return 0;
 	}
 	/*
 	 * Or can we do a fast lookup based on a loaded group on a filesystem
diff -u --recursive --new-file v2.1.117/linux/fs/ext2/dir.c linux/fs/ext2/dir.c
--- v2.1.117/linux/fs/ext2/dir.c	Wed May 20 19:10:40 1998
+++ linux/fs/ext2/dir.c	Mon Aug 24 13:02:44 1998
@@ -43,6 +43,7 @@
 	ext2_ioctl,		/* ioctl */
 	NULL,			/* mmap */
 	NULL,			/* no special open code */
+	NULL,			/* flush */
 	NULL,			/* no special release code */
 	ext2_sync_file,		/* fsync */
 	NULL,			/* fasync */
diff -u --recursive --new-file v2.1.117/linux/fs/ext2/file.c linux/fs/ext2/file.c
--- v2.1.117/linux/fs/ext2/file.c	Thu May  7 22:51:53 1998
+++ linux/fs/ext2/file.c	Mon Aug 24 13:02:44 1998
@@ -74,6 +74,7 @@
 #else
 	ext2_open_file,
 #endif
+	NULL,			/* flush */
 	ext2_release_file,	/* release */
 	ext2_sync_file,		/* fsync */
 	NULL,			/* fasync */
diff -u --recursive --new-file v2.1.117/linux/fs/ext2/ialloc.c linux/fs/ext2/ialloc.c
--- v2.1.117/linux/fs/ext2/ialloc.c	Thu May 14 19:47:43 1998
+++ linux/fs/ext2/ialloc.c	Mon Aug 24 10:25:14 1998
@@ -101,7 +101,8 @@
 			    "block_group = %d, groups_count = %lu",
 			     block_group, sb->u.ext2_sb.s_groups_count);
 	if (sb->u.ext2_sb.s_loaded_inode_bitmaps > 0 &&
-	    sb->u.ext2_sb.s_inode_bitmap_number[0] == block_group)
+	    sb->u.ext2_sb.s_inode_bitmap_number[0] == block_group &&
+	    sb->u.ext2_sb.s_inode_bitmap[0] != NULL)
 		return 0;
 	if (sb->u.ext2_sb.s_groups_count <= EXT2_MAX_GROUP_LOADED) {
 		if (sb->u.ext2_sb.s_inode_bitmap[block_group]) {
diff -u --recursive --new-file v2.1.117/linux/fs/fat/dir.c linux/fs/fat/dir.c
--- v2.1.117/linux/fs/fat/dir.c	Wed Jun 24 22:54:08 1998
+++ linux/fs/fat/dir.c	Mon Aug 24 13:02:44 1998
@@ -46,6 +46,7 @@
 	fat_dir_ioctl,		/* ioctl - default */
 	NULL,			/* mmap */
 	NULL,			/* no special open code */
+	NULL,			/* flush */
 	NULL,			/* no special release code */
 	file_fsync		/* fsync */
 };
diff -u --recursive --new-file v2.1.117/linux/fs/fat/file.c linux/fs/fat/file.c
--- v2.1.117/linux/fs/fat/file.c	Wed Jun 24 22:54:08 1998
+++ linux/fs/fat/file.c	Mon Aug 24 13:02:44 1998
@@ -39,6 +39,7 @@
 	NULL,			/* ioctl - default */
 	generic_file_mmap,	/* mmap */
 	NULL,			/* no special open is needed */
+	NULL,			/* flush */
 	NULL,			/* release */
 	file_fsync		/* fsync */
 };
@@ -79,6 +80,7 @@
 	NULL,			/* ioctl - default */
 	fat_mmap,		/* mmap */
 	NULL,			/* no special open is needed */
+	NULL,			/* flush */
 	NULL,			/* release */
 	file_fsync		/* fsync */
 };
@@ -122,6 +124,7 @@
 	NULL,			/* ioctl - default */
 	generic_file_mmap,	/* mmap */
 	NULL,			/* no special open is needed */
+	NULL,			/* flush */
 	NULL,			/* release */
 	file_fsync		/* fsync */
 };
diff -u --recursive --new-file v2.1.117/linux/fs/fifo.c linux/fs/fifo.c
--- v2.1.117/linux/fs/fifo.c	Sat Sep 20 14:51:55 1997
+++ linux/fs/fifo.c	Mon Aug 24 13:02:44 1998
@@ -128,6 +128,8 @@
 	NULL,
 	fifo_open,		/* will set read or write pipe_fops */
 	NULL,
+	NULL,
+	NULL,
 	NULL
 };
 
diff -u --recursive --new-file v2.1.117/linux/fs/file_table.c linux/fs/file_table.c
--- v2.1.117/linux/fs/file_table.c	Fri May  8 23:14:53 1998
+++ linux/fs/file_table.c	Thu Aug 20 14:30:25 1998
@@ -12,6 +12,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
+#include <linux/init.h>
 
 /* SLAB cache for filp's. */
 static kmem_cache_t *filp_cache;
@@ -44,8 +45,7 @@
 	file->f_pprev = &inuse_filps;
 }
 
-/* N.B. This should be an __initfunc ... */
-void file_table_init(void)
+void __init file_table_init(void)
 {
 	filp_cache = kmem_cache_create("filp", sizeof(struct file),
 				       0,
diff -u --recursive --new-file v2.1.117/linux/fs/filesystems.c linux/fs/filesystems.c
--- v2.1.117/linux/fs/filesystems.c	Mon Aug  3 12:45:47 1998
+++ linux/fs/filesystems.c	Thu Aug 20 14:33:49 1998
@@ -50,7 +50,7 @@
 extern void binfmt_setup(void);
 extern void free_initmem(void);
 
-__initfunc(static void do_sys_setup(void))
+static void __init do_sys_setup(void)
 {
 	device_setup();
 
diff -u --recursive --new-file v2.1.117/linux/fs/hfs/dir_cap.c linux/fs/hfs/dir_cap.c
--- v2.1.117/linux/fs/hfs/dir_cap.c	Tue Mar 17 22:18:15 1998
+++ linux/fs/hfs/dir_cap.c	Mon Aug 24 13:02:44 1998
@@ -66,6 +66,7 @@
 	NULL,			/* ioctl - default */
 	NULL,			/* mmap - none */
 	NULL,			/* no special open code */
+	NULL,			/* flush */
 	NULL,			/* no special release code */
 	file_fsync,		/* fsync - default */
 	NULL,			/* fasync - default */
diff -u --recursive --new-file v2.1.117/linux/fs/hfs/dir_dbl.c linux/fs/hfs/dir_dbl.c
--- v2.1.117/linux/fs/hfs/dir_dbl.c	Tue Mar 17 22:18:15 1998
+++ linux/fs/hfs/dir_dbl.c	Mon Aug 24 13:02:44 1998
@@ -66,6 +66,7 @@
 	NULL,			/* ioctl - default */
 	NULL,			/* mmap - none */
 	NULL,			/* no special open code */
+	NULL,			/* flush */
 	NULL,			/* no special release code */
 	file_fsync,		/* fsync - default */
         NULL,			/* fasync - default */
diff -u --recursive --new-file v2.1.117/linux/fs/hfs/dir_nat.c linux/fs/hfs/dir_nat.c
--- v2.1.117/linux/fs/hfs/dir_nat.c	Tue Mar 17 22:18:15 1998
+++ linux/fs/hfs/dir_nat.c	Mon Aug 24 13:02:44 1998
@@ -69,6 +69,7 @@
 	NULL,			/* ioctl - default */
 	NULL,			/* mmap - none */
 	NULL,			/* no special open code */
+	NULL,			/* flush */
 	NULL,			/* no special release code */
 	file_fsync,		/* fsync - default */
         NULL,			/* fasync - default */
diff -u --recursive --new-file v2.1.117/linux/fs/hfs/file.c linux/fs/hfs/file.c
--- v2.1.117/linux/fs/hfs/file.c	Tue Mar 17 22:18:15 1998
+++ linux/fs/hfs/file.c	Mon Aug 24 13:02:44 1998
@@ -41,6 +41,7 @@
 	NULL,			/* ioctl - default */
 	generic_file_mmap,	/* mmap */
 	NULL,			/* open */
+	NULL,			/* flush */
 	NULL,			/* release */
 	file_fsync,		/* fsync - default */
         NULL,			/* fasync - default */
diff -u --recursive --new-file v2.1.117/linux/fs/hfs/file_cap.c linux/fs/hfs/file_cap.c
--- v2.1.117/linux/fs/hfs/file_cap.c	Tue Mar 17 22:18:15 1998
+++ linux/fs/hfs/file_cap.c	Mon Aug 24 13:02:44 1998
@@ -55,6 +55,7 @@
 	NULL,			/* ioctl - default */
 	NULL,			/* mmap - not yet */
 	NULL,			/* no special open code */
+	NULL,			/* flush */
 	NULL,			/* no special release code */
 	file_fsync,		/* fsync - default */
 	NULL,			/* fasync - default */
diff -u --recursive --new-file v2.1.117/linux/fs/hfs/file_hdr.c linux/fs/hfs/file_hdr.c
--- v2.1.117/linux/fs/hfs/file_hdr.c	Tue Mar 17 22:18:15 1998
+++ linux/fs/hfs/file_hdr.c	Mon Aug 24 13:02:44 1998
@@ -48,6 +48,7 @@
 	NULL,			/* ioctl - default */
 	NULL,			/* mmap - XXX: not yet */
 	NULL,			/* no special open code */
+	NULL,			/* flush */
 	NULL,			/* no special release code */
 	file_fsync,		/* fsync - default */
         NULL,			/* fasync - default */
diff -u --recursive --new-file v2.1.117/linux/fs/isofs/dir.c linux/fs/isofs/dir.c
--- v2.1.117/linux/fs/isofs/dir.c	Wed Jun 24 22:54:09 1998
+++ linux/fs/isofs/dir.c	Mon Aug 24 13:02:44 1998
@@ -35,6 +35,7 @@
 	NULL,			/* poll - default */
 	NULL,			/* ioctl - default */
 	NULL,			/* no special open code */
+	NULL,			/* flush */
 	NULL,			/* no special release code */
 	NULL			/* fsync */
 };
diff -u --recursive --new-file v2.1.117/linux/fs/isofs/file.c linux/fs/isofs/file.c
--- v2.1.117/linux/fs/isofs/file.c	Wed Jun 24 22:54:09 1998
+++ linux/fs/isofs/file.c	Mon Aug 24 13:02:44 1998
@@ -31,6 +31,7 @@
 	NULL,			/* ioctl - default */
 	generic_file_mmap,	/* mmap */
 	NULL,			/* no special open is needed */
+	NULL,			/* flush */
 	NULL,			/* release */
 	NULL			/* fsync */
 };
diff -u --recursive --new-file v2.1.117/linux/fs/lockd/clntproc.c linux/fs/lockd/clntproc.c
--- v2.1.117/linux/fs/lockd/clntproc.c	Sun Jan  4 00:53:43 1998
+++ linux/fs/lockd/clntproc.c	Tue Aug 25 11:33:00 1998
@@ -51,34 +51,39 @@
 }
 
 /*
- * Initialize arguments for GRANTED call
+ * Initialize arguments for GRANTED call. The nlm_rqst structure
+ * has been cleared already.
  */
 int
 nlmclnt_setgrantargs(struct nlm_rqst *call, struct nlm_lock *lock)
 {
-	struct nlm_args	*argp = &call->a_args;
-	struct nlm_lock	*alock = &argp->lock;
-	void		*data = NULL;
-
-	if (lock->oh.len > NLMCLNT_OHSIZE
-	 && !(data = kmalloc(lock->oh.len, GFP_KERNEL)))
-		return 0;
+	call->a_args.cookie  = nlm_cookie++;
+	call->a_args.lock    = *lock;
+	call->a_args.lock.caller = system_utsname.nodename;
+
+	/* set default data area */
+	call->a_args.lock.oh.data = call->a_owner;
+
+	if (lock->oh.len > NLMCLNT_OHSIZE) {
+		void *data = kmalloc(lock->oh.len, GFP_KERNEL);
+		if (!data)
+			return 0;
+		call->a_args.lock.oh.data = (u8 *) data;
+	}
 
-	argp->cookie  = nlm_cookie++;
-	argp->lock    = *lock;
-	alock->caller = system_utsname.nodename;
-	if (data)
-		alock->oh.data = (u8 *) data;
-	else
-		alock->oh.data = call->a_owner;
-	memcpy(alock->oh.data, lock->oh.data, lock->oh.len);
+	memcpy(call->a_args.lock.oh.data, lock->oh.data, lock->oh.len);
 	return 1;
 }
 
 void
 nlmclnt_freegrantargs(struct nlm_rqst *call)
 {
-	kfree(call->a_args.lock.caller);
+	/*
+	 * Check whether we allocated memory for the owner.
+	 */
+	if (call->a_args.lock.oh.data != (u8 *) call->a_owner) {
+		kfree(call->a_args.lock.oh.data);
+	}
 }
 
 /*
@@ -404,8 +409,14 @@
 static int
 nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl)
 {
+	struct nlm_host	*host = req->a_host;
 	struct nlm_res	*resp = &req->a_res;
 	int		status;
+
+	/* No monitor, no lock: see nlmclnt_lock().
+	 * Since this is an UNLOCK, don't try to setup monitoring here. */
+	if (!host->h_monitored)
+		return -ENOLCK;
 
 	/* Clean the GRANTED flag now so the lock doesn't get
 	 * reclaimed while we're stuck in the unlock call. */
diff -u --recursive --new-file v2.1.117/linux/fs/lockd/svclock.c linux/fs/lockd/svclock.c
--- v2.1.117/linux/fs/lockd/svclock.c	Sun Jul 13 21:20:10 1997
+++ linux/fs/lockd/svclock.c	Tue Aug 25 11:33:00 1998
@@ -158,10 +158,8 @@
 
 	/* Set notifier function for VFS, and init args */
 	lock->fl.fl_notify = nlmsvc_notify_blocked;
-	if (!nlmclnt_setgrantargs(&block->b_call, lock)) {
-		kfree(block);
-		goto failed;
-	}
+	if (!nlmclnt_setgrantargs(&block->b_call, lock))
+		goto failed_free;
 	block->b_call.a_args.cookie = cookie;	/* see above */
 
 	dprintk("lockd: created block %p...\n", block);
@@ -182,6 +180,8 @@
 
 	return block;
 
+failed_free:
+	kfree(block);
 failed:
 	nlm_release_host(host);
 	return NULL;
diff -u --recursive --new-file v2.1.117/linux/fs/minix/dir.c linux/fs/minix/dir.c
--- v2.1.117/linux/fs/minix/dir.c	Tue Oct 21 08:57:29 1997
+++ linux/fs/minix/dir.c	Mon Aug 24 13:02:44 1998
@@ -31,6 +31,7 @@
 	NULL,			/* ioctl - default */
 	NULL,			/* mmap */
 	NULL,			/* no special open code */
+	NULL,			/* flush */
 	NULL,			/* no special release code */
 	file_fsync		/* default fsync */
 };
diff -u --recursive --new-file v2.1.117/linux/fs/minix/file.c linux/fs/minix/file.c
--- v2.1.117/linux/fs/minix/file.c	Wed Jun 24 22:54:09 1998
+++ linux/fs/minix/file.c	Mon Aug 24 13:02:44 1998
@@ -42,6 +42,7 @@
 	NULL,			/* ioctl - default */
 	generic_file_mmap,	/* mmap */
 	NULL,			/* no special open is needed */
+	NULL,			/* flush */
 	NULL,			/* release */
 	minix_sync_file		/* fsync */
 };
diff -u --recursive --new-file v2.1.117/linux/fs/ncpfs/dir.c linux/fs/ncpfs/dir.c
--- v2.1.117/linux/fs/ncpfs/dir.c	Tue Mar 17 22:18:15 1998
+++ linux/fs/ncpfs/dir.c	Mon Aug 24 13:02:44 1998
@@ -70,6 +70,7 @@
 	ncp_ioctl,		/* ioctl */
 	NULL,			/* mmap */
 	NULL,			/* no special open code */
+	NULL,			/* flush */
 	NULL,			/* no special release code */
 	NULL			/* fsync */
 };
diff -u --recursive --new-file v2.1.117/linux/fs/ncpfs/file.c linux/fs/ncpfs/file.c
--- v2.1.117/linux/fs/ncpfs/file.c	Sun Jan  4 00:53:42 1998
+++ linux/fs/ncpfs/file.c	Mon Aug 24 13:02:44 1998
@@ -252,6 +252,7 @@
 	ncp_ioctl,		/* ioctl */
 	ncp_mmap,		/* mmap */
 	NULL,			/* open */
+	NULL,			/* flush */
 	NULL,			/* release */
 	ncp_fsync,		/* fsync */
 };
diff -u --recursive --new-file v2.1.117/linux/fs/nfs/dir.c linux/fs/nfs/dir.c
--- v2.1.117/linux/fs/nfs/dir.c	Thu Aug 20 17:05:17 1998
+++ linux/fs/nfs/dir.c	Mon Aug 24 13:02:44 1998
@@ -14,13 +14,6 @@
  *              Following Linus comments on my original hack, this version
  *              depends only on the dcache stuff and doesn't touch the inode
  *              layer (iput() and friends).
- * 04 Aug 1998  Ion Badulescu <ionut@cs.columbia.edu>     
- *	        FIFO's need special handling in NFSv2
- */
-
-/*
- * Fixes:
- *    Ion Badulescu <ionut@cs.columbia.edu>     : FIFO's need special handling in NFSv2
  */
 
 #include <linux/sched.h>
@@ -86,6 +79,7 @@
 	NULL,			/* ioctl - default */
 	NULL,			/* mmap */
 	nfs_dir_open,		/* open - revalidate */
+	NULL,			/* flush */
 	NULL,			/* no special release code */
 	NULL			/* fsync */
 };
@@ -652,10 +646,7 @@
 	if (dentry->d_name.len > NFS_MAXNAMLEN)
 		goto out;
 
- 	if (mode & S_IFIFO)
- 		sattr.mode = (mode & ~S_IFMT) | S_IFCHR;
- 	else
- 		sattr.mode = mode;
+	sattr.mode = mode;
 	sattr.uid = sattr.gid = sattr.size = (unsigned) -1;
 	sattr.atime.seconds = sattr.mtime.seconds = (unsigned) -1;
 
@@ -665,15 +656,6 @@
 	nfs_invalidate_dircache(dir);
 	error = nfs_proc_create(NFS_SERVER(dir), NFS_FH(dentry->d_parent),
 			dentry->d_name.name, &sattr, &fhandle, &fattr);
-	/*
-	 *	Retry invalid FIFO creates as the original object
-	 *	to cover for NFS servers that don't cope.
-	 */
-	if (error == -EINVAL && (mode & S_IFIFO)) {
-		sattr.mode = mode;
-		error = nfs_proc_create(NFS_SERVER(dir), NFS_FH(dentry->d_parent),
-					dentry->d_name.name, &sattr, &fhandle, &fattr);
-	}
 	if (!error)
 		error = nfs_instantiate(dentry, &fhandle, &fattr);
 	if (error)
@@ -703,10 +685,7 @@
 	if (dentry->d_name.len > NFS_MAXNAMLEN)
 		return -ENAMETOOLONG;
 
-	if (mode & S_IFIFO)
-		sattr.mode = (mode & ~S_IFMT) | S_IFCHR;
-	else
-		sattr.mode = mode;
+	sattr.mode = mode;
 	sattr.uid = sattr.gid = sattr.size = (unsigned) -1;
 	if (S_ISCHR(mode) || S_ISBLK(mode))
 		sattr.size = rdev; /* get out your barf bag */
@@ -715,11 +694,6 @@
 	nfs_invalidate_dircache(dir);
 	error = nfs_proc_create(NFS_SERVER(dir), NFS_FH(dentry->d_parent),
 				dentry->d_name.name, &sattr, &fhandle, &fattr);
-	if (error == -EINVAL && (mode & S_IFIFO)) {
-		sattr.mode = mode;
-		error = nfs_proc_create(NFS_SERVER(dir), NFS_FH(dentry->d_parent),
-					dentry->d_name.name, &sattr, &fhandle, &fattr);
-	}
 	if (!error)
 		error = nfs_instantiate(dentry, &fhandle, &fattr);
 	if (error)
diff -u --recursive --new-file v2.1.117/linux/fs/nfs/file.c linux/fs/nfs/file.c
--- v2.1.117/linux/fs/nfs/file.c	Tue Jul 21 00:15:32 1998
+++ linux/fs/nfs/file.c	Mon Aug 24 14:15:24 1998
@@ -35,6 +35,7 @@
 static int  nfs_file_mmap(struct file *, struct vm_area_struct *);
 static ssize_t nfs_file_read(struct file *, char *, size_t, loff_t *);
 static ssize_t nfs_file_write(struct file *, const char *, size_t, loff_t *);
+static int  nfs_file_flush(struct file *);
 static int  nfs_file_close(struct inode *, struct file *);
 static int  nfs_fsync(struct file *, struct dentry *dentry);
 
@@ -47,6 +48,7 @@
 	NULL,			/* ioctl - default */
 	nfs_file_mmap,		/* mmap */
 	NULL,			/* no special open is needed */
+	nfs_file_flush,		/* flush */
 	nfs_file_close,		/* release */
 	nfs_fsync,		/* fsync */
 	NULL,			/* fasync */
@@ -84,13 +86,7 @@
 #endif
 
 /*
- * Flush all dirty pages, and check for write errors.
- *
- * Note that since the file close operation is called only by the
- * _last_ process to close the file, we need to flush _all_ dirty 
- * pages. This also means that there is little sense in checking
- * for errors for this specific process -- we should probably just
- * clear all errors.
+ * Sync the file..
  */
 static int
 nfs_file_close(struct inode *inode, struct file *file)
@@ -104,6 +100,22 @@
 	if (!status)
 		status = error;
 	return status;
+}
+
+/*
+ * Flush all dirty pages, and check for write errors.
+ *
+ * We should probably do this better - this does get called at every
+ * close, so we should probably just flush the changes that "this"
+ * file has done and report on only those.
+ *
+ * Right now we use the "flush everything" approach. Overkill, but
+ * works.
+ */
+static int
+nfs_file_flush(struct file *file)
+{
+	return nfs_file_close(file->f_dentry->d_inode, file);
 }
 
 static ssize_t
diff -u --recursive --new-file v2.1.117/linux/fs/nfs/inode.c linux/fs/nfs/inode.c
--- v2.1.117/linux/fs/nfs/inode.c	Sun Jul 26 11:57:18 1998
+++ linux/fs/nfs/inode.c	Tue Aug 25 13:44:44 1998
@@ -652,6 +652,7 @@
 	int		 status = 0;
 	struct nfs_fattr fattr;
 
+	/* Don't bother revalidating if we've done it recently */
 	if (jiffies - NFS_READTIME(inode) < NFS_ATTRTIMEO(inode))
 		goto out;
 
@@ -744,6 +745,20 @@
 	 */
 	if ((inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT))
 		goto out_changed;
+
+	/*
+	 * If we have pending write-back entries, we don't want
+	 * to look at the size the server sends us too closely..
+	 * In particular, ignore the server if it tells us that
+	 * the file is smaller or older than we locally think it
+	 * is.. 
+	 */
+	if (NFS_WRITEBACK(inode)) {
+		if (inode->i_size > fattr->size)
+			fattr->size = inode->i_size;
+		if (inode->i_mtime > fattr->mtime.seconds)
+			fattr->mtime.seconds = inode->i_mtime;
+	}
 
 	/*
 	 * If the size or mtime changed from outside, we want
diff -u --recursive --new-file v2.1.117/linux/fs/nfs/mount_clnt.c linux/fs/nfs/mount_clnt.c
--- v2.1.117/linux/fs/nfs/mount_clnt.c	Thu Aug 20 17:05:17 1998
+++ linux/fs/nfs/mount_clnt.c	Fri Aug 21 12:01:22 1998
@@ -78,7 +78,6 @@
 		clnt->cl_softrtry = 1;
 		clnt->cl_chatty   = 1;
 		clnt->cl_oneshot  = 1;
-		clnt->cl_intr = 1;
 	}
 	return clnt;
 }
diff -u --recursive --new-file v2.1.117/linux/fs/nfs/nfs2xdr.c linux/fs/nfs/nfs2xdr.c
--- v2.1.117/linux/fs/nfs/nfs2xdr.c	Thu Aug 20 17:05:17 1998
+++ linux/fs/nfs/nfs2xdr.c	Fri Aug 21 12:01:23 1998
@@ -5,9 +5,6 @@
  *
  * Copyright (C) 1992, 1993, 1994  Rick Sladkey
  * Copyright (C) 1996 Olaf Kirch
- *
- * 04 Aug 1998  Ion Badulescu <ionut@cs.columbia.edu>     
- *	        FIFO's need special handling in NFSv2
  */
 
 #define NFS_NEED_XDR_TYPES
@@ -117,11 +114,6 @@
 	fattr->mtime.useconds = ntohl(*p++);
 	fattr->ctime.seconds = ntohl(*p++);
 	fattr->ctime.useconds = ntohl(*p++);
-	if (fattr->type == NFCHR && fattr->rdev == NFS_FIFO_DEV) {
-		fattr->type = NFFIFO;
-		fattr->mode = (fattr->mode & ~S_IFMT) | S_IFIFO;
-		fattr->rdev = 0;
-	}
 	return p;
 }
 
diff -u --recursive --new-file v2.1.117/linux/fs/nfs/write.c linux/fs/nfs/write.c
--- v2.1.117/linux/fs/nfs/write.c	Thu Aug 20 17:05:17 1998
+++ linux/fs/nfs/write.c	Tue Aug 25 13:32:49 1998
@@ -63,6 +63,8 @@
  *
  * Until we have a per-mount soft/hard mount policy that we can honour
  * we must default to hard mounting!
+ *
+ * And yes, this should be "interruptible", not soft.
  */
 #define IS_SOFT 0
 
@@ -442,11 +444,15 @@
 		sync = 1;
 
 	if (sync) {
+		sigset_t	oldmask;
+		struct rpc_clnt *clnt = NFS_CLIENT(inode);
 		dprintk("NFS: %4d schedule_write_request (sync)\n",
 					task->tk_pid);
 		/* Page is already locked */
 		req->wb_flags |= NFS_WRITE_LOCKED;
+		rpc_clnt_sigmask(clnt, &oldmask);
 		rpc_execute(task);
+		rpc_clnt_sigunmask(clnt, &oldmask);
 	} else {
 		dprintk("NFS: %4d schedule_write_request (async)\n",
 					task->tk_pid);
@@ -467,19 +473,19 @@
 {
 	struct wait_queue	wait = { current, NULL };
 	struct page		*page = req->wb_page;
-	int			retval;
+	int retval;
 	sigset_t		oldmask;
+	struct rpc_clnt		*clnt = NFS_CLIENT(req->wb_inode);
 
-	rpc_clnt_sigmask(NFS_CLIENT(req->wb_inode), &oldmask);
+	rpc_clnt_sigmask(clnt, &oldmask);
 	add_wait_queue(&page->wait, &wait);
 	atomic_inc(&page->count);
 	for (;;) {
-		current->state = IS_SOFT ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE;
+		current->state = TASK_INTERRUPTIBLE;
 		retval = 0;
 		if (!PageLocked(page))
 			break;
 		retval = -ERESTARTSYS;
-		/* IS_SOFT is a timeout item .. */
 		if (signalled())
 			break;
 		schedule();
@@ -488,7 +494,7 @@
 	current->state = TASK_RUNNING;
 	/* N.B. page may have been unused, so we must use free_page() */
 	free_page(page_address(page));
-	rpc_clnt_sigunmask(NFS_CLIENT(req->wb_inode), &oldmask);
+	rpc_clnt_sigunmask(clnt, &oldmask);
 	return retval;
 }
 
diff -u --recursive --new-file v2.1.117/linux/fs/ntfs/fs.c linux/fs/ntfs/fs.c
--- v2.1.117/linux/fs/ntfs/fs.c	Tue Jul 21 00:15:32 1998
+++ linux/fs/ntfs/fs.c	Mon Aug 24 13:02:44 1998
@@ -385,6 +385,7 @@
 	NULL, /* ioctl */
 	NULL, /* mmap */
 	NULL, /* open */
+	NULL, /* flush */
 	NULL, /* release */
 	NULL, /* fsync */
 	NULL, /* fasync */
@@ -506,6 +507,7 @@
 	NULL, /* ioctl */
 	generic_file_mmap,
 	NULL, /* open */
+	NULL, /* flush */
 	NULL, /* release */
 	NULL, /* fsync */
 	NULL, /* fasync */
@@ -546,6 +548,7 @@
 	NULL, /* ioctl */
 	NULL, /* mmap */
 	NULL, /* open */
+	NULL, /* flush */
 	NULL, /* release */
 	NULL, /* fsync */
 	NULL, /* fasync */
diff -u --recursive --new-file v2.1.117/linux/fs/open.c linux/fs/open.c
--- v2.1.117/linux/fs/open.c	Tue Jul 28 14:21:09 1998
+++ linux/fs/open.c	Mon Aug 24 13:55:03 1998
@@ -770,19 +770,17 @@
 /*
  * Called when retiring the last use of a file pointer.
  */
-int __fput(struct file *filp)
+void __fput(struct file *filp)
 {
 	struct dentry * dentry = filp->f_dentry;
 	struct inode * inode = dentry->d_inode;
-	int	error = 0;
 
 	if (filp->f_op && filp->f_op->release)
-		error = filp->f_op->release(inode, filp);
+		filp->f_op->release(inode, filp);
 	filp->f_dentry = NULL;
 	if (filp->f_mode & FMODE_WRITE)
 		put_write_access(inode);
 	dput(dentry);
-	return error;
 }
 
 /*
@@ -791,6 +789,7 @@
  */
 int close_fp(struct file *filp, fl_owner_t id)
 {
+	int retval;
 	struct dentry *dentry = filp->f_dentry;
 
 	if (filp->f_count == 0) {
@@ -799,7 +798,11 @@
 	}
 	if (dentry->d_inode)
 		locks_remove_posix(filp, id);
-	return fput(filp);
+	retval = 0;
+	if (filp->f_op && filp->f_op->flush)
+		retval = filp->f_op->flush(filp);
+	fput(filp);
+	return retval;
 }
 
 /*
diff -u --recursive --new-file v2.1.117/linux/fs/pipe.c linux/fs/pipe.c
--- v2.1.117/linux/fs/pipe.c	Wed Jun 24 22:54:10 1998
+++ linux/fs/pipe.c	Mon Aug 24 12:34:35 1998
@@ -304,6 +304,7 @@
 	pipe_ioctl,
 	NULL,		/* no mmap on pipes.. surprise */
 	pipe_read_open,
+	NULL,		/* flush */
 	pipe_read_release,
 	NULL
 };
@@ -317,6 +318,7 @@
 	pipe_ioctl,
 	NULL,		/* no mmap on pipes.. surprise */
 	pipe_read_open,
+	NULL,		/* flush */
 	pipe_read_release,
 	NULL
 };
@@ -330,6 +332,7 @@
 	pipe_ioctl,
 	NULL,		/* mmap */
 	pipe_write_open,
+	NULL,		/* flush */
 	pipe_write_release,
 	NULL
 };
@@ -343,6 +346,7 @@
 	pipe_ioctl,
 	NULL,		/* mmap */
 	pipe_rdwr_open,
+	NULL,		/* flush */
 	pipe_rdwr_release,
 	NULL
 };
@@ -356,6 +360,7 @@
 	pipe_ioctl,
 	NULL,		/* no mmap on pipes.. surprise */
 	pipe_read_open,
+	NULL,		/* flush */
 	pipe_read_release,
 	NULL
 };
@@ -369,6 +374,7 @@
 	pipe_ioctl,
 	NULL,		/* mmap */
 	pipe_write_open,
+	NULL,		/* flush */
 	pipe_write_release,
 	NULL
 };
@@ -382,6 +388,7 @@
 	pipe_ioctl,
 	NULL,		/* mmap */
 	pipe_rdwr_open,
+	NULL,		/* flush */
 	pipe_rdwr_release,
 	NULL
 };
diff -u --recursive --new-file v2.1.117/linux/fs/proc/array.c linux/fs/proc/array.c
--- v2.1.117/linux/fs/proc/array.c	Thu Aug 20 17:05:17 1998
+++ linux/fs/proc/array.c	Mon Aug 24 13:02:43 1998
@@ -1390,6 +1390,7 @@
 	NULL,		/* array_ioctl */
 	NULL,		/* mmap */
 	NULL,		/* no special open code */
+	NULL,		/* flush */
 	NULL,		/* no special release code */
 	NULL		/* can't fsync */
 };
@@ -1437,6 +1438,7 @@
 	NULL,		/* array_ioctl */
 	NULL,		/* mmap */
 	NULL,		/* no special open code */
+	NULL,		/* flush */
 	NULL,		/* no special release code */
 	NULL		/* can't fsync */
 };
diff -u --recursive --new-file v2.1.117/linux/fs/proc/base.c linux/fs/proc/base.c
--- v2.1.117/linux/fs/proc/base.c	Sun Jul 26 11:57:18 1998
+++ linux/fs/proc/base.c	Mon Aug 24 13:02:43 1998
@@ -24,6 +24,7 @@
 	NULL,			/* ioctl - default */
 	NULL,			/* mmap */
 	NULL,			/* no special open code */
+	NULL,			/* flush */
 	NULL,			/* no special release code */
 	NULL			/* can't fsync */
 };
diff -u --recursive --new-file v2.1.117/linux/fs/proc/fd.c linux/fs/proc/fd.c
--- v2.1.117/linux/fs/proc/fd.c	Fri May  8 23:14:53 1998
+++ linux/fs/proc/fd.c	Mon Aug 24 13:02:44 1998
@@ -30,6 +30,7 @@
 	NULL,			/* ioctl - default */
 	NULL,			/* mmap */
 	NULL,			/* no special open code */
+	NULL,			/* flush */
 	NULL,			/* no special release code */
 	NULL			/* can't fsync */
 };
diff -u --recursive --new-file v2.1.117/linux/fs/proc/generic.c linux/fs/proc/generic.c
--- v2.1.117/linux/fs/proc/generic.c	Tue Aug 18 22:02:06 1998
+++ linux/fs/proc/generic.c	Mon Aug 24 13:02:44 1998
@@ -42,6 +42,7 @@
     NULL,		/* ioctl   */
     NULL,		/* mmap	   */
     NULL,		/* no special open code	   */
+    NULL,		/* flush */
     NULL,		/* no special release code */
     NULL		/* can't fsync */
 };
diff -u --recursive --new-file v2.1.117/linux/fs/proc/kmsg.c linux/fs/proc/kmsg.c
--- v2.1.117/linux/fs/proc/kmsg.c	Tue Mar 10 10:03:34 1998
+++ linux/fs/proc/kmsg.c	Mon Aug 24 13:14:09 1998
@@ -54,6 +54,7 @@
 	NULL,		/* kmsg_ioctl */
 	NULL,		/* mmap */
 	kmsg_open,
+	NULL,		/* flush */
 	kmsg_release,
 	NULL		/* can't fsync */
 };
diff -u --recursive --new-file v2.1.117/linux/fs/proc/link.c linux/fs/proc/link.c
--- v2.1.117/linux/fs/proc/link.c	Fri May  8 23:14:53 1998
+++ linux/fs/proc/link.c	Mon Aug 24 13:14:09 1998
@@ -31,6 +31,7 @@
 	NULL,			/* ioctl - default */
 	NULL,			/* mmap */
 	NULL,			/* very special open code */
+	NULL,			/* flush */
 	NULL,			/* no special release code */
 	NULL			/* can't fsync */
 };
diff -u --recursive --new-file v2.1.117/linux/fs/proc/mem.c linux/fs/proc/mem.c
--- v2.1.117/linux/fs/proc/mem.c	Wed Apr  1 20:11:53 1998
+++ linux/fs/proc/mem.c	Mon Aug 24 13:14:09 1998
@@ -316,6 +316,7 @@
 	NULL,		/* mem_ioctl */
 	mem_mmap,	/* mmap */
 	NULL,		/* no special open code */
+	NULL,		/* flush */
 	NULL,		/* no special release code */
 	NULL		/* can't fsync */
 };
diff -u --recursive --new-file v2.1.117/linux/fs/proc/net.c linux/fs/proc/net.c
--- v2.1.117/linux/fs/proc/net.c	Wed Jun 24 22:54:10 1998
+++ linux/fs/proc/net.c	Mon Aug 24 13:14:09 1998
@@ -92,6 +92,7 @@
 	NULL,			/* ioctl - default */
 	NULL,			/* mmap */
 	NULL,			/* no special open code */
+	NULL,			/* flush */
 	NULL,			/* no special release code */
 	NULL			/* can't fsync */
 };
diff -u --recursive --new-file v2.1.117/linux/fs/proc/omirr.c linux/fs/proc/omirr.c
--- v2.1.117/linux/fs/proc/omirr.c	Thu Jul 10 14:53:00 1997
+++ linux/fs/proc/omirr.c	Mon Aug 24 13:14:09 1998
@@ -268,6 +268,7 @@
     NULL,	/* omirr_ioctl */
     NULL,	/* mmap */
     omirr_open,
+    NULL,	/* flush */
     omirr_release,
     NULL,	/* fsync */
     NULL,       /* fasync */
diff -u --recursive --new-file v2.1.117/linux/fs/proc/openpromfs.c linux/fs/proc/openpromfs.c
--- v2.1.117/linux/fs/proc/openpromfs.c	Thu Apr 23 20:21:37 1998
+++ linux/fs/proc/openpromfs.c	Mon Aug 24 13:14:10 1998
@@ -479,6 +479,7 @@
 	NULL,			/* ioctl - default */
 	NULL,			/* mmap */
 	NULL,			/* no special open code */
+	NULL,			/* flush */
 	property_release,	/* no special release code */
 	NULL			/* can't fsync */
 };
@@ -512,6 +513,7 @@
 	NULL,			/* ioctl - default */
 	NULL,			/* mmap */
 	NULL,			/* no special open code */
+	NULL,			/* flush */
 	NULL,			/* no special release code */
 	NULL			/* can't fsync */
 };
@@ -545,6 +547,7 @@
 	NULL,			/* ioctl - default */
 	NULL,			/* mmap */
 	NULL,			/* no special open code */
+	NULL,			/* flush */
 	NULL,			/* no special release code */
 	NULL			/* can't fsync */
 };
diff -u --recursive --new-file v2.1.117/linux/fs/proc/root.c linux/fs/proc/root.c
--- v2.1.117/linux/fs/proc/root.c	Tue Aug 18 22:02:06 1998
+++ linux/fs/proc/root.c	Mon Aug 24 13:14:10 1998
@@ -50,6 +50,7 @@
 	NULL,			/* ioctl - default */
 	NULL,			/* mmap */
 	NULL,			/* no special open code */
+	NULL,			/* flush */
 	NULL,			/* no special release code */
 	NULL			/* can't fsync */
 };
@@ -117,6 +118,7 @@
 	NULL,			/* ioctl - default */
 	NULL,			/* mmap */
 	NULL,			/* no special open code */
+	NULL,			/* flush */
 	NULL,			/* no special release code */
 	NULL			/* no fsync */
 };
@@ -276,6 +278,7 @@
 	NULL,			/* ioctl - default */
 	NULL,			/* mmap */
 	NULL,			/* no special open code */
+	NULL,			/* flush */
 	NULL,			/* no special release code */
 	NULL			/* can't fsync */
 };
@@ -901,19 +904,18 @@
  * tasklist lock while doing this, and we must release it before
  * we actually do the filldir itself, so we use a temp buffer..
  */
-static int get_pid_list(unsigned int index, unsigned int *pids)
+static int get_pid_list(int index, unsigned int *pids)
 {
 	struct task_struct *p;
-	int nr = FIRST_PROCESS_ENTRY;
 	int nr_pids = 0;
 
+	index -= FIRST_PROCESS_ENTRY;
 	read_lock(&tasklist_lock);
 	for_each_task(p) {
-		int pid;
-		if (nr++ < index)
-			continue;
-		pid = p->pid;
+		int pid = p->pid;
 		if (!pid)
+			continue;
+		if (--index >= 0)
 			continue;
 		pids[nr_pids] = pid;
 		nr_pids++;
diff -u --recursive --new-file v2.1.117/linux/fs/proc/scsi.c linux/fs/proc/scsi.c
--- v2.1.117/linux/fs/proc/scsi.c	Tue Oct 21 08:57:29 1997
+++ linux/fs/proc/scsi.c	Mon Aug 24 13:14:10 1998
@@ -50,6 +50,7 @@
     NULL,		/* ioctl   */
     NULL,		/* mmap	   */
     NULL,		/* no special open code	   */
+    NULL,		/* flush */
     NULL,		/* no special release code */
     NULL		/* can't fsync */
 };
diff -u --recursive --new-file v2.1.117/linux/fs/smbfs/dir.c linux/fs/smbfs/dir.c
--- v2.1.117/linux/fs/smbfs/dir.c	Fri Jan 23 18:10:32 1998
+++ linux/fs/smbfs/dir.c	Mon Aug 24 13:02:44 1998
@@ -40,6 +40,7 @@
 	smb_ioctl,		/* ioctl */
 	NULL,			/* mmap */
 	smb_dir_open,		/* open(struct inode *, struct file *) */
+	NULL,			/* flush */
 	NULL,			/* no special release code */
 	NULL			/* fsync */
 };
diff -u --recursive --new-file v2.1.117/linux/fs/smbfs/file.c linux/fs/smbfs/file.c
--- v2.1.117/linux/fs/smbfs/file.c	Tue Mar 10 10:03:34 1998
+++ linux/fs/smbfs/file.c	Mon Aug 24 13:02:44 1998
@@ -389,6 +389,7 @@
 	smb_ioctl,		/* ioctl */
 	smb_file_mmap,		/* mmap(struct file*, struct vm_area_struct*) */
 	smb_file_open,		/* open(struct inode*, struct file*) */
+	NULL,			/* flush */
 	smb_file_release,	/* release(struct inode*, struct file*) */
 	smb_fsync,		/* fsync(struct file*, struct dentry*) */
 	NULL,			/* fasync(struct file*, int) */
diff -u --recursive --new-file v2.1.117/linux/fs/super.c linux/fs/super.c
--- v2.1.117/linux/fs/super.c	Thu Aug 20 17:05:17 1998
+++ linux/fs/super.c	Thu Aug 20 14:34:12 1998
@@ -539,8 +539,8 @@
 	if (nr_super_blocks >= max_super_blocks)
 		return NULL;
 	s = kmalloc(sizeof(struct super_block),  GFP_USER);
-	nr_super_blocks++;
 	if (s) {
+		nr_super_blocks++;
 		memset(s, 0, sizeof(struct super_block));
 		INIT_LIST_HEAD(&s->s_dirty);
 		list_add (&s->s_list, super_blocks.prev);
@@ -1129,7 +1129,7 @@
 	goto dput_and_out;
 }
 
-__initfunc(void mount_root(void))
+void __init mount_root(void)
 {
 	struct file_system_type * fs_type;
 	struct super_block * sb;
@@ -1228,7 +1228,7 @@
 
 extern int initmem_freed;
 
-__initfunc(static int do_change_root(kdev_t new_root_dev,const char *put_old))
+static int __init do_change_root(kdev_t new_root_dev,const char *put_old)
 {
 	kdev_t old_root_dev;
 	struct vfsmount *vfsmnt;
diff -u --recursive --new-file v2.1.117/linux/fs/sysv/dir.c linux/fs/sysv/dir.c
--- v2.1.117/linux/fs/sysv/dir.c	Tue Oct 21 08:57:30 1997
+++ linux/fs/sysv/dir.c	Mon Aug 24 13:02:44 1998
@@ -38,6 +38,7 @@
 	NULL,			/* ioctl - default */
 	NULL,			/* mmap */
 	NULL,			/* no special open code */
+	NULL,			/* flush */
 	NULL,			/* no special release code */
 	file_fsync		/* default fsync */
 };
diff -u --recursive --new-file v2.1.117/linux/fs/sysv/file.c linux/fs/sysv/file.c
--- v2.1.117/linux/fs/sysv/file.c	Wed Jul  1 19:38:56 1998
+++ linux/fs/sysv/file.c	Mon Aug 24 13:02:44 1998
@@ -48,6 +48,7 @@
 	NULL,			/* ioctl - default */
 	generic_file_mmap,	/* mmap */
 	NULL,			/* no special open is needed */
+	NULL,			/* flush */
 	NULL,			/* release */
 	sysv_sync_file		/* fsync */
 };
diff -u --recursive --new-file v2.1.117/linux/fs/ufs/dir.c linux/fs/ufs/dir.c
--- v2.1.117/linux/fs/ufs/dir.c	Tue Jul 28 14:21:09 1998
+++ linux/fs/ufs/dir.c	Mon Aug 24 13:02:44 1998
@@ -199,6 +199,7 @@
 	NULL,			/* ioctl */
 	NULL,			/* mmap */
 	NULL,			/* open */
+	NULL,			/* flush */
 	NULL,			/* release */
 	file_fsync,		/* fsync */
 	NULL,			/* fasync */
diff -u --recursive --new-file v2.1.117/linux/fs/ufs/file.c linux/fs/ufs/file.c
--- v2.1.117/linux/fs/ufs/file.c	Tue Jul 28 14:21:09 1998
+++ linux/fs/ufs/file.c	Mon Aug 24 13:02:44 1998
@@ -61,6 +61,7 @@
 	NULL, 			/* ioctl */
 	generic_file_mmap,	/* mmap */
 	NULL,			/* no special open is needed */
+	NULL,			/* flush */
 	ufs_release_file,	/* release */
 	NULL, 			/* fsync */
 	NULL,			/* fasync */
diff -u --recursive --new-file v2.1.117/linux/fs/umsdos/dir.c linux/fs/umsdos/dir.c
--- v2.1.117/linux/fs/umsdos/dir.c	Wed May 20 19:10:41 1998
+++ linux/fs/umsdos/dir.c	Mon Aug 24 13:02:44 1998
@@ -1022,6 +1022,7 @@
 	UMSDOS_ioctl_dir,	/* ioctl - default */
 	NULL,			/* mmap */
 	NULL,			/* no special open code */
+	NULL,			/* flush */
 	NULL,			/* no special release code */
 	NULL			/* fsync *//* in original NULL. changed to file_fsync. FIXME? /mn/ */
 };
diff -u --recursive --new-file v2.1.117/linux/fs/umsdos/file.c linux/fs/umsdos/file.c
--- v2.1.117/linux/fs/umsdos/file.c	Wed May 20 19:10:41 1998
+++ linux/fs/umsdos/file.c	Mon Aug 24 13:02:44 1998
@@ -86,6 +86,7 @@
 	NULL,			/* ioctl - default */
 	generic_file_mmap,	/* mmap */
 	NULL,			/* no special open is needed */
+	NULL,			/* flush */
 	NULL,			/* release */
 	file_fsync		/* fsync */
 };
@@ -123,6 +124,7 @@
 	NULL,			/* ioctl - default */
 	fat_mmap,		/* mmap */
 	NULL,			/* no special open is needed */
+	NULL,			/* flush */
 	NULL,			/* release */
 	file_fsync		/* fsync */
 };
@@ -160,6 +162,7 @@
 	NULL,			/* ioctl - default */
 	generic_file_mmap,	/* mmap */
 	NULL,			/* no special open is needed */
+	NULL,			/* flush */
 	NULL,			/* release */
 	file_fsync		/* fsync */
 };
diff -u --recursive --new-file v2.1.117/linux/fs/umsdos/rdir.c linux/fs/umsdos/rdir.c
--- v2.1.117/linux/fs/umsdos/rdir.c	Wed May 20 19:10:41 1998
+++ linux/fs/umsdos/rdir.c	Mon Aug 24 13:14:10 1998
@@ -284,6 +284,7 @@
 	UMSDOS_ioctl_dir,	/* ioctl - default */
 	NULL,			/* mmap */
 	NULL,			/* no special open code */
+	NULL,			/* flush */
 	NULL,			/* no special release code */
 	NULL			/* fsync */
 };
diff -u --recursive --new-file v2.1.117/linux/fs/umsdos/symlink.c linux/fs/umsdos/symlink.c
--- v2.1.117/linux/fs/umsdos/symlink.c	Wed May 20 19:10:41 1998
+++ linux/fs/umsdos/symlink.c	Mon Aug 24 13:02:44 1998
@@ -149,6 +149,7 @@
 	NULL,			/* ioctl - default */
 	NULL,			/* mmap */
 	NULL,			/* no special open is needed */
+	NULL,			/* no flush code */
 	NULL,			/* release */
 	NULL			/* fsync */
 };
diff -u --recursive --new-file v2.1.117/linux/include/asm-alpha/fcntl.h linux/include/asm-alpha/fcntl.h
--- v2.1.117/linux/include/asm-alpha/fcntl.h	Thu Aug 20 17:05:18 1998
+++ linux/include/asm-alpha/fcntl.h	Fri Aug 21 08:47:33 1998
@@ -17,6 +17,7 @@
 #define O_NDELAY	O_NONBLOCK
 #define O_SYNC		040000
 #define FASYNC		020000	/* fcntl, for BSD compatibility */
+#define O_DIRECT	040000	/* direct disk access - should check with OSF/1 */
 
 #define F_DUPFD		0	/* dup */
 #define F_GETFD		1	/* get f_flags */
diff -u --recursive --new-file v2.1.117/linux/include/asm-alpha/posix_types.h linux/include/asm-alpha/posix_types.h
--- v2.1.117/linux/include/asm-alpha/posix_types.h	Tue Aug 18 22:02:07 1998
+++ linux/include/asm-alpha/posix_types.h	Fri Aug 21 06:33:36 1998
@@ -40,7 +40,7 @@
 
 #define	__FD_SET(d, set)	((set)->fds_bits[__FDELT(d)] |= __FDMASK(d))
 #define	__FD_CLR(d, set)	((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d))
-#define	__FD_ISSET(d, set)	((set)->fds_bits[__FDELT(d)] & __FDMASK(d))
+#define	__FD_ISSET(d, set)	(((set)->fds_bits[__FDELT(d)] & __FDMASK(d)) != 0)
 #define	__FD_ZERO(set)	\
   ((void) memset ((__ptr_t) (set), 0, sizeof (__kernel_fd_set)))
 
diff -u --recursive --new-file v2.1.117/linux/include/asm-arm/uaccess.h linux/include/asm-arm/uaccess.h
--- v2.1.117/linux/include/asm-arm/uaccess.h	Tue Jan 20 16:39:43 1998
+++ linux/include/asm-arm/uaccess.h	Mon Aug 24 12:29:35 1998
@@ -60,8 +60,11 @@
 
 static __inline__ unsigned long copy_from_user(void *to, const void *from, unsigned long n)
 {
-	if (access_ok(VERIFY_READ, from, n))
+	char *end = (char *)to + n;
+	if (access_ok(VERIFY_READ, from, n)) {
 		__do_copy_from_user(to, from, n);
+		if (n) memset(end - n, 0, n);
+	}
 	return n;
 }
 
diff -u --recursive --new-file v2.1.117/linux/include/asm-i386/fcntl.h linux/include/asm-i386/fcntl.h
--- v2.1.117/linux/include/asm-i386/fcntl.h	Thu Aug 20 17:05:18 1998
+++ linux/include/asm-i386/fcntl.h	Tue Aug 25 14:19:30 1998
@@ -3,19 +3,21 @@
 
 /* open/fcntl - O_SYNC is only implemented on blocks devices and on files
    located on an ext2 file system */
-#define O_ACCMODE	  0003
-#define O_RDONLY	    00
-#define O_WRONLY	    01
-#define O_RDWR		    02
-#define O_CREAT		  0100	/* not fcntl */
-#define O_EXCL		  0200	/* not fcntl */
-#define O_NOCTTY	  0400	/* not fcntl */
-#define O_TRUNC		 01000	/* not fcntl */
-#define O_APPEND	 02000
-#define O_NONBLOCK	 04000
+#define O_ACCMODE	   0003
+#define O_RDONLY	     00
+#define O_WRONLY	     01
+#define O_RDWR		     02
+#define O_CREAT		   0100	/* not fcntl */
+#define O_EXCL		   0200	/* not fcntl */
+#define O_NOCTTY	   0400	/* not fcntl */
+#define O_TRUNC		  01000	/* not fcntl */
+#define O_APPEND	  02000
+#define O_NONBLOCK	  04000
 #define O_NDELAY	O_NONBLOCK
-#define O_SYNC		010000
-#define FASYNC		020000	/* fcntl, for BSD compatibility */
+#define O_SYNC		 010000
+#define FASYNC		 020000	/* fcntl, for BSD compatibility */
+#define O_DIRECT	 040000	/* direct disk access hint - currently ignored */
+#define O_LARGEFILE	0100000
 
 #define F_DUPFD		0	/* dup */
 #define F_GETFD		1	/* get f_flags */
diff -u --recursive --new-file v2.1.117/linux/include/asm-i386/fixmap.h linux/include/asm-i386/fixmap.h
--- v2.1.117/linux/include/asm-i386/fixmap.h	Sun Jul 26 11:57:19 1998
+++ linux/include/asm-i386/fixmap.h	Thu Aug 20 16:13:44 1998
@@ -60,6 +60,10 @@
 #define FIXADDR_SIZE	(__end_of_fixed_addresses << PAGE_SHIFT)
 #define FIXADDR_START	(FIXADDR_TOP - FIXADDR_SIZE)
 
+#define __fix_to_virt(x)	(FIXADDR_TOP - ((x) << PAGE_SHIFT))
+
+extern void __this_fixmap_does_not_exist(void);
+
 /*
  * 'index to address' translation. If anyone tries to use the idx
  * directly without tranlation, we catch the bug with a NULL-deference
@@ -71,12 +75,15 @@
 	 * this branch gets completely eliminated after inlining,
 	 * except when someone tries to use fixaddr indices in an
 	 * illegal way. (such as mixing up address types or using
-	 * out-of-range indices)
+	 * out-of-range indices).
+	 *
+	 * If it doesn't get removed, the linker will complain
+	 * loudly with a reasonably clear error message..
 	 */
 	if (idx >= __end_of_fixed_addresses)
-		panic("illegal fixaddr index!");
+		__this_fixmap_does_not_exist();
 
-        return FIXADDR_TOP - (idx << PAGE_SHIFT);
+        return __fix_to_virt(idx);
 }
 
 #endif
diff -u --recursive --new-file v2.1.117/linux/include/asm-i386/uaccess.h linux/include/asm-i386/uaccess.h
--- v2.1.117/linux/include/asm-i386/uaccess.h	Fri Jul 31 17:05:53 1998
+++ linux/include/asm-i386/uaccess.h	Tue Aug 25 16:17:12 1998
@@ -268,13 +268,38 @@
 		: "r"(size & 3), "0"(size / 4), "D"(to), "S"(from)	\
 		: "di", "si", "memory")
 
+#define __copy_user_zeroing(to,from,size)				\
+	__asm__ __volatile__(						\
+		"0:	rep; movsl\n"					\
+		"	movl %1,%0\n"					\
+		"1:	rep; movsb\n"					\
+		"2:\n"							\
+		".section .fixup,\"ax\"\n"				\
+		"3:	lea 0(%1,%0,4),%0\n"				\
+		"4:	pushl %0\n"					\
+		"	pushl %%eax\n"					\
+		"	xorl %%eax,%%eax\n"				\
+		"	rep; stosb\n"					\
+		"	popl %%eax\n"					\
+		"	popl %0\n"					\
+		"	jmp 2b\n"					\
+		".previous\n"						\
+		".section __ex_table,\"a\"\n"				\
+		"	.align 4\n"					\
+		"	.long 0b,3b\n"					\
+		"	.long 1b,4b\n"					\
+		".previous"						\
+		: "=&c"(size)						\
+		: "r"(size & 3), "0"(size / 4), "D"(to), "S"(from)	\
+		: "di", "si", "memory");
+
 /* We let the __ versions of copy_from/to_user inline, because they're often
  * used in fast paths and have only a small space overhead.
  */
 static inline unsigned long
 __generic_copy_from_user_nocheck(void *to, const void *from, unsigned long n)
 {
-	__copy_user(to,from,n);
+	__copy_user_zeroing(to,from,n);
 	return n;
 }
 
@@ -369,6 +394,141 @@
 	}							\
 } while (0)
 
+/* Optimize just a little bit when we know the size of the move. */
+#define __constant_copy_user_zeroing(to, from, size)		\
+do {								\
+	switch (size & 3) {					\
+	default:						\
+		__asm__ __volatile__(				\
+			"0:	rep; movsl\n"			\
+			"1:\n"					\
+			".section .fixup,\"ax\"\n"		\
+			"2:	pushl %0\n"			\
+			"	pushl %%eax\n"			\
+			"	xorl %%eax,%%eax\n"		\
+			"	rep; stosl\n"			\
+			"	popl %%eax\n"			\
+			"	popl %0\n"			\
+			"	shl $2,%0\n"			\
+			"	jmp 1b\n"			\
+			".previous\n"				\
+			".section __ex_table,\"a\"\n"		\
+			"	.align 4\n"			\
+			"	.long 0b,2b\n"			\
+			".previous"				\
+			: "=c"(size)				\
+			: "S"(from), "D"(to), "0"(size/4)	\
+			: "di", "si", "memory");		\
+		break;						\
+	case 1:							\
+		__asm__ __volatile__(				\
+			"0:	rep; movsl\n"			\
+			"1:	movsb\n"			\
+			"2:\n"					\
+			".section .fixup,\"ax\"\n"		\
+			"3:	pushl %0\n"			\
+			"	pushl %%eax\n"			\
+			"	xorl %%eax,%%eax\n"		\
+			"	rep; stosl\n"			\
+			"	stosb\n"			\
+			"	popl %%eax\n"			\
+			"	popl %0\n"			\
+			"	shl $2,%0\n"			\
+			"	incl %0\n"			\
+			"	jmp 2b\n"			\
+			"4:	pushl %%eax\n"			\
+			"	xorl %%eax,%%eax\n"		\
+			"	stosb\n"			\
+			"	popl %%eax\n"			\
+			"	incl %0\n"			\
+			"	jmp 2b\n"			\
+			".previous\n"				\
+			".section __ex_table,\"a\"\n"		\
+			"	.align 4\n"			\
+			"	.long 0b,3b\n"			\
+			"	.long 1b,4b\n"			\
+			".previous"				\
+			: "=c"(size)				\
+			: "S"(from), "D"(to), "0"(size/4)	\
+			: "di", "si", "memory");		\
+		break;						\
+	case 2:							\
+		__asm__ __volatile__(				\
+			"0:	rep; movsl\n"			\
+			"1:	movsw\n"			\
+			"2:\n"					\
+			".section .fixup,\"ax\"\n"		\
+			"3:	pushl %0\n"			\
+			"	pushl %%eax\n"			\
+			"	xorl %%eax,%%eax\n"		\
+			"	rep; stosl\n"			\
+			"	stosw\n"			\
+			"	popl %%eax\n"			\
+			"	popl %0\n"			\
+			"	shl $2,%0\n"			\
+			"	addl $2,%0\n"			\
+			"	jmp 2b\n"			\
+			"4:	pushl %%eax\n"			\
+			"	xorl %%eax,%%eax\n"		\
+			"	stosw\n"			\
+			"	popl %%eax\n"			\
+			"	addl $2,%0\n"			\
+			"	jmp 2b\n"			\
+			".previous\n"				\
+			".section __ex_table,\"a\"\n"		\
+			"	.align 4\n"			\
+			"	.long 0b,3b\n"			\
+			"	.long 1b,4b\n"			\
+			".previous"				\
+			: "=c"(size)				\
+			: "S"(from), "D"(to), "0"(size/4)	\
+			: "di", "si", "memory");		\
+		break;						\
+	case 3:							\
+		__asm__ __volatile__(				\
+			"0:	rep; movsl\n"			\
+			"1:	movsw\n"			\
+			"2:	movsb\n"			\
+			"3:\n"					\
+			".section .fixup,\"ax\"\n"		\
+			"4:	pushl %0\n"			\
+			"	pushl %%eax\n"			\
+			"	xorl %%eax,%%eax\n"		\
+			"	rep; stosl\n"			\
+			"	stosw\n"			\
+			"	stosb\n"			\
+			"	popl %%eax\n"			\
+			"	popl %0\n"			\
+			"	shl $2,%0\n"			\
+			"	addl $3,%0\n"			\
+			"	jmp 2b\n"			\
+			"5:	pushl %%eax\n"			\
+			"	xorl %%eax,%%eax\n"		\
+			"	stosw\n"			\
+			"	stosb\n"			\
+			"	popl %%eax\n"			\
+			"	addl $3,%0\n"			\
+			"	jmp 2b\n"			\
+			"6:	pushl %%eax\n"			\
+			"	xorl %%eax,%%eax\n"		\
+			"	stosb\n"			\
+			"	popl %%eax\n"			\
+			"	incl %0\n"			\
+			"	jmp 2b\n"			\
+			".previous\n"				\
+			".section __ex_table,\"a\"\n"		\
+			"	.align 4\n"			\
+			"	.long 0b,4b\n"			\
+			"	.long 1b,5b\n"			\
+			"	.long 2b,6b\n"			\
+			".previous"				\
+			: "=c"(size)				\
+			: "S"(from), "D"(to), "0"(size/4)	\
+			: "di", "si", "memory");		\
+		break;						\
+	}							\
+} while (0)
+
 unsigned long __generic_copy_to_user(void *, const void *, unsigned long);
 unsigned long __generic_copy_from_user(void *, const void *, unsigned long);
 
@@ -384,7 +544,7 @@
 __constant_copy_from_user(void *to, const void *from, unsigned long n)
 {
 	if (access_ok(VERIFY_READ, from, n))
-		__constant_copy_user(to,from,n);
+		__constant_copy_user_zeroing(to,from,n);
 	return n;
 }
 
@@ -398,7 +558,7 @@
 static inline unsigned long
 __constant_copy_from_user_nocheck(void *to, const void *from, unsigned long n)
 {
-	__constant_copy_user(to,from,n);
+	__constant_copy_user_zeroing(to,from,n);
 	return n;
 }
 
diff -u --recursive --new-file v2.1.117/linux/include/asm-i386/unistd.h linux/include/asm-i386/unistd.h
--- v2.1.117/linux/include/asm-i386/unistd.h	Tue Aug 18 22:02:07 1998
+++ linux/include/asm-i386/unistd.h	Thu Aug 20 14:30:24 1998
@@ -27,7 +27,7 @@
 #define __NR_lseek		 19
 #define __NR_getpid		 20
 #define __NR_mount		 21
-#define __NR_oldumount		 22
+#define __NR_umount		 22
 #define __NR_setuid		 23
 #define __NR_getuid		 24
 #define __NR_stime		 25
@@ -57,7 +57,7 @@
 #define __NR_geteuid		 49
 #define __NR_getegid		 50
 #define __NR_acct		 51
-#define __NR_umount		 52
+#define __NR_umount2		 52
 #define __NR_lock		 53
 #define __NR_ioctl		 54
 #define __NR_fcntl		 55
diff -u --recursive --new-file v2.1.117/linux/include/asm-m68k/uaccess.h linux/include/asm-m68k/uaccess.h
--- v2.1.117/linux/include/asm-m68k/uaccess.h	Tue Aug 18 22:02:07 1998
+++ linux/include/asm-m68k/uaccess.h	Mon Aug 24 12:29:35 1998
@@ -712,9 +712,16 @@
 }
 
 #define copy_from_user(to, from, n)		\
+{ void *__to = (to);				\
+  void *__from = (from);			\
+  unsigned long __n = (n);			\
+  char *__end = (char *)__to + __n;		\
+  unsigned long __res =				\
 (__builtin_constant_p(n) ?			\
  __constant_copy_from_user(to, from, n) :	\
- __generic_copy_from_user(to, from, n))
+ __generic_copy_from_user(to, from, n));	\
+  if (__res) memset(__end - __res, 0, __res);	\
+  res; }
 
 #define copy_to_user(to, from, n)		\
 (__builtin_constant_p(n) ?			\
diff -u --recursive --new-file v2.1.117/linux/include/asm-ppc/uaccess.h linux/include/asm-ppc/uaccess.h
--- v2.1.117/linux/include/asm-ppc/uaccess.h	Mon Jan 12 15:18:13 1998
+++ linux/include/asm-ppc/uaccess.h	Mon Aug 24 12:29:35 1998
@@ -211,9 +211,12 @@
 extern inline unsigned long
 copy_from_user(void *to, const void *from, unsigned long n)
 {
-	if (access_ok(VERIFY_READ, from, n))
-		return __copy_tofrom_user(to, from, n);
-	return n? -EFAULT: 0;
+	unsigned long res = n;
+	if (access_ok(VERIFY_READ, from, n)) {
+		 res = __copy_tofrom_user(to, from, n);
+		 if (res) memset((char *)to + n - res, 0, res);
+	}
+	return res;
 }
 
 extern inline unsigned long
@@ -221,7 +224,7 @@
 {
 	if (access_ok(VERIFY_WRITE, to, n))
 		return __copy_tofrom_user(to, from, n);
-	return n? -EFAULT: 0;
+	return n;
 }
 
 #define __copy_from_user(to, from, size) \
diff -u --recursive --new-file v2.1.117/linux/include/asm-sparc/uaccess.h linux/include/asm-sparc/uaccess.h
--- v2.1.117/linux/include/asm-sparc/uaccess.h	Thu Apr 23 20:21:38 1998
+++ linux/include/asm-sparc/uaccess.h	Mon Aug 24 12:29:35 1998
@@ -318,11 +318,14 @@
 })
 
 #define copy_from_user(to,from,n) ({ \
+void *__copy_to = (void *) (to); \
 void *__copy_from = (void *) (from); \
 __kernel_size_t __copy_size = (__kernel_size_t) (n); \
 __kernel_size_t __copy_res; \
 if(__copy_size && __access_ok((unsigned long)__copy_from, __copy_size)) { \
-__copy_res = __copy_user((void *) (to), __copy_from, __copy_size); \
+__copy_res = __copy_user(__copy_to, __copy_from, __copy_size); \
+if(__copy_res) \
+memset((char *)__copy_to + __copy_size - __copy_res, 0, __copy_res); \
 } else __copy_res = __copy_size; \
 __copy_res; })
 
diff -u --recursive --new-file v2.1.117/linux/include/linux/file.h linux/include/linux/file.h
--- v2.1.117/linux/include/linux/file.h	Thu Mar 26 15:57:05 1998
+++ linux/include/linux/file.h	Mon Aug 24 13:56:09 1998
@@ -5,7 +5,7 @@
 #ifndef __LINUX_FILE_H
 #define __LINUX_FILE_H
 
-extern int __fput(struct file *);
+extern void __fput(struct file *);
 extern void insert_file_free(struct file *file);
 
 /*
@@ -58,20 +58,18 @@
 	*file->f_pprev = file->f_next;
 }
 
-extern inline int fput(struct file *file)
+extern inline void fput(struct file *file)
 {
 	int count = file->f_count-1;
-	int error = 0;
 
 	if (!count) {
 		locks_remove_flock(file);
-		error = __fput(file);
+		__fput(file);
 		file->f_count = 0;
 		remove_filp(file);
 		insert_file_free(file);
 	} else
 		file->f_count = count;
-	return error;
 }
 
 extern inline void put_filp(struct file *file)
diff -u --recursive --new-file v2.1.117/linux/include/linux/fs.h linux/include/linux/fs.h
--- v2.1.117/linux/include/linux/fs.h	Thu Aug 20 17:05:19 1998
+++ linux/include/linux/fs.h	Tue Aug 25 16:17:01 1998
@@ -596,6 +596,7 @@
 	int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
 	int (*mmap) (struct file *, struct vm_area_struct *);
 	int (*open) (struct inode *, struct file *);
+	int (*flush) (struct file *);
 	int (*release) (struct inode *, struct file *);
 	int (*fsync) (struct file *, struct dentry *);
 	int (*fasync) (int, struct file *, int);
@@ -670,7 +671,6 @@
 extern int do_truncate(struct dentry *, unsigned long);
 extern int get_unused_fd(void);
 extern void put_unused_fd(unsigned int);
-extern int __fput(struct file *);
 extern int close_fp(struct file *, fl_owner_t id);
 
 extern char * getname(const char * filename);
diff -u --recursive --new-file v2.1.117/linux/include/linux/pci.h linux/include/linux/pci.h
--- v2.1.117/linux/include/linux/pci.h	Fri Jul 31 17:05:53 1998
+++ linux/include/linux/pci.h	Tue Aug 25 16:13:38 1998
@@ -1,5 +1,5 @@
 /*
- *	$Id: pci.h,v 1.80 1998/07/21 10:06:40 mj Exp $
+ *	$Id: pci.h,v 1.84 1998/08/17 23:06:43 cort Exp $
  *
  *	PCI defines and function prototypes
  *	Copyright 1994, Drew Eckhardt
@@ -381,7 +381,9 @@
 #define PCI_DEVICE_ID_IBM_82351		0x0022
 #define PCI_DEVICE_ID_IBM_SERVERAID	0x002e
 #define PCI_DEVICE_ID_IBM_TR_WAKE	0x003e
+#define PCI_DEVICE_ID_IBM_MPIC		0x0046
 #define PCI_DEVICE_ID_IBM_3780IDSP	0x007d
+#define PCI_DEVICE_ID_IBM_MPIC_2	0xffff
 
 #define PCI_VENDOR_ID_WD		0x101c
 #define PCI_DEVICE_ID_WD_7197		0x3296
@@ -599,6 +601,9 @@
 #define PCI_DEVICE_ID_DATABOOK_87144	0xb106
 
 #define PCI_VENDOR_ID_PLX		0x10b5
+#define PCI_DEVICE_ID_PLX_9060		0x9060
+#define PCI_DEVICE_ID_PLX_9060ES	0x906E
+#define PCI_DEVICE_ID_PLX_9060SD	0x906D
 #define PCI_DEVICE_ID_PLX_9080		0x9080
 
 #define PCI_VENDOR_ID_MADGE		0x10b6
diff -u --recursive --new-file v2.1.117/linux/include/linux/shm.h linux/include/linux/shm.h
--- v2.1.117/linux/include/linux/shm.h	Fri Jul 31 17:08:33 1998
+++ linux/include/linux/shm.h	Tue Aug 25 13:47:38 1998
@@ -64,6 +64,7 @@
 asmlinkage int sys_shmat (int shmid, char *shmaddr, int shmflg, unsigned long *addr);
 asmlinkage int sys_shmdt (char *shmaddr);
 asmlinkage int sys_shmctl (int shmid, int cmd, struct shmid_ds *buf);
+extern void shm_unuse(unsigned long entry, unsigned long page);
 
 #endif /* __KERNEL__ */
 
diff -u --recursive --new-file v2.1.117/linux/include/linux/videodev.h linux/include/linux/videodev.h
--- v2.1.117/linux/include/linux/videodev.h	Thu Aug 20 17:05:19 1998
+++ linux/include/linux/videodev.h	Sun Aug 23 13:32:25 1998
@@ -216,7 +216,7 @@
 
 #define VIDIOCGCAP		_IOR('v',1,struct video_capability)	/* Get capabilities */
 #define VIDIOCGCHAN		_IOWR('v',2,struct video_channel)	/* Get channel info (sources) */
-#define VIDIOCSCHAN		_IOW('v',3,int)				/* Set channel 	*/
+#define VIDIOCSCHAN		_IOW('v',3,struct video_channel)	/* Set channel 	*/
 #define VIDIOCGTUNER		_IOWR('v',4,struct video_tuner)		/* Get tuner abilities */
 #define VIDIOCSTUNER		_IOW('v',5,struct video_tuner)		/* Tune the tuner for the current channel */
 #define VIDIOCGPICT		_IOR('v',6,struct video_picture)	/* Get picture properties */
diff -u --recursive --new-file v2.1.117/linux/init/main.c linux/init/main.c
--- v2.1.117/linux/init/main.c	Thu Aug  6 14:06:34 1998
+++ linux/init/main.c	Thu Aug 20 14:31:48 1998
@@ -469,7 +469,7 @@
 	{ NULL, 0 }
 };
 
-__initfunc(kdev_t name_to_kdev_t(char *line))
+kdev_t __init name_to_kdev_t(char *line)
 {
 	int base = 0;
 	if (strncmp(line,"/dev/",5) == 0) {
@@ -488,7 +488,7 @@
 	return to_kdev_t(base + simple_strtoul(line,NULL,base?10:16));
 }
 
-__initfunc(static void root_dev_setup(char *line, int *num))
+static void __init root_dev_setup(char *line, int *num)
 {
 	ROOT_DEV = name_to_kdev_t(line);
 }
@@ -816,32 +816,32 @@
 };
 
 #ifdef CONFIG_BLK_DEV_RAM
-__initfunc(static void ramdisk_start_setup(char *str, int *ints))
+static void __init ramdisk_start_setup(char *str, int *ints)
 {
    if (ints[0] > 0 && ints[1] >= 0)
       rd_image_start = ints[1];
 }
 
-__initfunc(static void load_ramdisk(char *str, int *ints))
+static void __init load_ramdisk(char *str, int *ints)
 {
    if (ints[0] > 0 && ints[1] >= 0)
       rd_doload = ints[1] & 1;
 }
 
-__initfunc(static void prompt_ramdisk(char *str, int *ints))
+static void __init prompt_ramdisk(char *str, int *ints)
 {
    if (ints[0] > 0 && ints[1] >= 0)
       rd_prompt = ints[1] & 1;
 }
 
-__initfunc(static void ramdisk_size(char *str, int *ints))
+static void __init ramdisk_size(char *str, int *ints)
 {
 	if (ints[0] > 0 && ints[1] >= 0)
 		rd_size = ints[1];
 }
 #endif
 
-__initfunc(static int checksetup(char *line))
+static int __init checksetup(char *line)
 {
 	int i, ints[11];
 
@@ -878,7 +878,7 @@
    better than 1% */
 #define LPS_PREC 8
 
-__initfunc(void calibrate_delay(void))
+void __init calibrate_delay(void)
 {
 	unsigned long ticks, loopbit;
 	int lps_precision = LPS_PREC;
@@ -930,7 +930,7 @@
  * This routine also checks for options meant for the kernel.
  * These options are not given to init - they are for internal kernel use only.
  */
-__initfunc(static void parse_options(char *line))
+static void __init parse_options(char *line)
 {
 	char *next;
 	int args, envs;
@@ -1014,7 +1014,7 @@
 extern int cpu_idle(void * unused);
 
 /* Called by boot processor to activate the rest. */
-__initfunc(static void smp_init(void))
+static void __init smp_init(void)
 {
 	/* Get other processors into their bootup holding patterns. */
 	smp_boot_cpus();
@@ -1026,7 +1026,7 @@
  *	they are finished.
  */
  
-__initfunc(static void smp_begin(void))
+static void __init smp_begin(void)
 {
 	smp_threads_ready=1;
 	smp_commence();
@@ -1040,7 +1040,7 @@
  *	Activate the first processor.
  */
  
-__initfunc(asmlinkage void start_kernel(void))
+asmlinkage void __init start_kernel(void)
 {
 	char * command_line;
 
@@ -1188,7 +1188,7 @@
 	return execve(shell, argv, envp_init);
 }
 
-__initfunc(static void no_initrd(char *s,int *ints))
+static void __init no_initrd(char *s,int *ints)
 {
 	mount_initrd = 0;
 }
diff -u --recursive --new-file v2.1.117/linux/ipc/sem.c linux/ipc/sem.c
--- v2.1.117/linux/ipc/sem.c	Thu May  7 22:51:55 1998
+++ linux/ipc/sem.c	Thu Aug 20 14:47:56 1998
@@ -56,7 +56,7 @@
 
 static unsigned short sem_seq = 0;
 
-__initfunc(void sem_init (void))
+void __init sem_init (void)
 {
 	int i;
 
diff -u --recursive --new-file v2.1.117/linux/ipc/shm.c linux/ipc/shm.c
--- v2.1.117/linux/ipc/shm.c	Thu Aug  6 14:06:34 1998
+++ linux/ipc/shm.c	Tue Aug 25 13:47:38 1998
@@ -3,6 +3,7 @@
  * Copyright (C) 1992, 1993 Krishna Balasubramanian
  *         Many improvements/fixes by Bruno Haible.
  * Replaced `struct shm_desc' by `struct vm_area_struct', July 1994.
+ * Fixed the shm swap deallocation (shm_unuse()), August 1998 Andrea Arcangeli.
  */
 
 #include <linux/errno.h>
@@ -45,7 +46,7 @@
 static ulong swap_successes = 0;
 static ulong used_segs = 0;
 
-__initfunc(void shm_init (void))
+void __init shm_init (void)
 {
 	int id;
 
@@ -836,4 +837,39 @@
 	shm_swp++;
 	shm_rss--;
 	return 1;
+}
+
+/*
+ * Free the swap entry and set the new pte for the shm page.
+ */
+static void shm_unuse_page(struct shmid_ds *shp, unsigned long idx,
+			   unsigned long page, unsigned long entry)
+{
+	pte_t pte;
+
+	pte = pte_mkdirty(mk_pte(page, PAGE_SHARED));
+	shp->shm_pages[idx] = pte_val(pte);
+	atomic_inc(&mem_map[MAP_NR(page)].count);
+	shm_rss++;
+
+	swap_free(entry);
+	shm_swp--;
+}
+
+/*
+ * unuse_shm() search for an eventually swapped out shm page.
+ */
+void shm_unuse(unsigned long entry, unsigned long page)
+{
+	int i, n;
+
+	for (i = 0; i < SHMMNI; i++)
+		if (shm_segs[i] != IPC_UNUSED && shm_segs[i] != IPC_NOID)
+			for (n = 0; n < shm_segs[i]->shm_npages; n++)
+				if (shm_segs[i]->shm_pages[n] == entry)
+				{
+					shm_unuse_page(shm_segs[i], n,
+						       page, entry);
+					return;
+				}
 }
diff -u --recursive --new-file v2.1.117/linux/ipc/util.c linux/ipc/util.c
--- v2.1.117/linux/ipc/util.c	Thu Aug  6 14:06:34 1998
+++ linux/ipc/util.c	Thu Aug 20 14:48:34 1998
@@ -24,7 +24,7 @@
 
 extern void sem_init (void), msg_init (void), shm_init (void);
 
-__initfunc(void ipc_init (void))
+void __init ipc_init (void)
 {
 	sem_init();
 	msg_init();
diff -u --recursive --new-file v2.1.117/linux/kernel/capability.c linux/kernel/capability.c
--- v2.1.117/linux/kernel/capability.c	Tue Aug 18 22:02:08 1998
+++ linux/kernel/capability.c	Sun Aug 23 11:45:57 1998
@@ -147,7 +147,6 @@
              return -EINVAL;
      }
 
-     /* may want to set other processes at some point -- for now demand 0 */
      if (get_user(pid, &header->pid))
 	     return -EFAULT; 
 
diff -u --recursive --new-file v2.1.117/linux/kernel/fork.c linux/kernel/fork.c
--- v2.1.117/linux/kernel/fork.c	Thu Aug 20 17:05:19 1998
+++ linux/kernel/fork.c	Thu Aug 20 14:47:10 1998
@@ -125,7 +125,7 @@
 	return 0;
 }
 
-__initfunc(void uidcache_init(void))
+void __init uidcache_init(void)
 {
 	int i;
 
@@ -641,7 +641,7 @@
 	goto bad_fork;
 }
 
-__initfunc(void filescache_init(void))
+void __init filescache_init(void)
 {
 	files_cachep = kmem_cache_create("files_cache", 
 					 sizeof(struct files_struct),
diff -u --recursive --new-file v2.1.117/linux/kernel/kmod.c linux/kernel/kmod.c
--- v2.1.117/linux/kernel/kmod.c	Tue Aug 18 22:02:08 1998
+++ linux/kernel/kmod.c	Fri Aug 21 15:35:20 1998
@@ -116,7 +116,7 @@
 	/* Block everything but SIGKILL/SIGSTOP */
 	spin_lock_irq(&current->sigmask_lock);
 	tmpsig = current->blocked;
-	siginitset(&current->blocked, ~(sigmask(SIGKILL)|sigmask(SIGSTOP)));
+	siginitsetinv(&current->blocked, sigmask(SIGKILL) | sigmask(SIGSTOP));
 	recalc_sigpending(current);
 	spin_unlock_irq(&current->sigmask_lock);
 
diff -u --recursive --new-file v2.1.117/linux/kernel/panic.c linux/kernel/panic.c
--- v2.1.117/linux/kernel/panic.c	Sun Jun  7 11:16:39 1998
+++ linux/kernel/panic.c	Thu Aug 20 14:47:20 1998
@@ -25,7 +25,7 @@
 
 int panic_timeout = 0;
 
-__initfunc(void panic_setup(char *str, int *ints))
+void __init panic_setup(char *str, int *ints)
 {
 	if (ints[0] == 1)
 		panic_timeout = ints[1];
diff -u --recursive --new-file v2.1.117/linux/kernel/printk.c linux/kernel/printk.c
--- v2.1.117/linux/kernel/printk.c	Mon Aug  3 12:45:48 1998
+++ linux/kernel/printk.c	Thu Aug 20 14:47:30 1998
@@ -58,7 +58,7 @@
 /*
  *	Setup a list of consoles. Called from init/main.c
  */
-__initfunc(void console_setup(char *str, int *ints))
+void __init console_setup(char *str, int *ints)
 {
 	struct console_cmdline *c;
 	char name[sizeof(c->name)];
diff -u --recursive --new-file v2.1.117/linux/kernel/resource.c linux/kernel/resource.c
--- v2.1.117/linux/kernel/resource.c	Wed Jun 24 22:54:12 1998
+++ linux/kernel/resource.c	Thu Aug 20 14:49:27 1998
@@ -182,7 +182,7 @@
 #endif
 
 /* Called from init/main.c to reserve IO ports. */
-__initfunc(void reserve_setup(char *str, int *ints))
+void __init reserve_setup(char *str, int *ints)
 {
 	int i;
 
diff -u --recursive --new-file v2.1.117/linux/kernel/sched.c linux/kernel/sched.c
--- v2.1.117/linux/kernel/sched.c	Thu Aug 20 17:05:19 1998
+++ linux/kernel/sched.c	Thu Aug 20 14:49:37 1998
@@ -1675,7 +1675,7 @@
 	read_unlock(&tasklist_lock);
 }
 
-__initfunc(void sched_init(void))
+void __init sched_init(void)
 {
 	/*
 	 *	We have to do a little magic to get the first
diff -u --recursive --new-file v2.1.117/linux/kernel/signal.c linux/kernel/signal.c
--- v2.1.117/linux/kernel/signal.c	Thu Aug 20 17:05:19 1998
+++ linux/kernel/signal.c	Thu Aug 20 14:30:25 1998
@@ -18,6 +18,7 @@
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
 #include <linux/slab.h>
+#include <linux/init.h>
 
 #include <asm/uaccess.h>
 
@@ -38,8 +39,7 @@
 static int nr_queued_signals;
 static int max_queued_signals = 1024;
 
-void
-signals_init(void)
+void __init signals_init(void)
 {
 	signal_queue_cachep =
 		kmem_cache_create("signal_queue",
diff -u --recursive --new-file v2.1.117/linux/kernel/sysctl.c linux/kernel/sysctl.c
--- v2.1.117/linux/kernel/sysctl.c	Thu Aug 20 17:05:19 1998
+++ linux/kernel/sysctl.c	Mon Aug 24 12:35:14 1998
@@ -95,6 +95,7 @@
 	NULL,		/* ioctl   */
 	NULL,		/* mmap	   */
 	NULL,		/* no special open code	   */
+	NULL,		/* no special flush code */
 	NULL,		/* no special release code */
 	NULL		/* can't fsync */
 };
@@ -251,7 +252,7 @@
 };  
 
 
-__initfunc(void sysctl_init(void))
+void __init sysctl_init(void)
 {
 #ifdef CONFIG_PROC_FS
 	register_proc_table(root_table, &proc_sys_root);
diff -u --recursive --new-file v2.1.117/linux/mm/mmap.c linux/mm/mmap.c
--- v2.1.117/linux/mm/mmap.c	Tue Jul 28 14:21:10 1998
+++ linux/mm/mmap.c	Thu Aug 20 14:47:43 1998
@@ -688,7 +688,7 @@
 	mm->mmap_cache = NULL;		/* Kill the cache. */
 }
 
-__initfunc(void vma_init(void))
+void __init vma_init(void)
 {
 	vm_area_cachep = kmem_cache_create("vm_area_struct",
 					   sizeof(struct vm_area_struct),
diff -u --recursive --new-file v2.1.117/linux/mm/page_alloc.c linux/mm/page_alloc.c
--- v2.1.117/linux/mm/page_alloc.c	Tue Aug 18 22:02:08 1998
+++ linux/mm/page_alloc.c	Thu Aug 20 14:48:54 1998
@@ -318,7 +318,7 @@
  *   - mark all memory queues empty
  *   - clear the memory bitmaps
  */
-__initfunc(unsigned long free_area_init(unsigned long start_mem, unsigned long end_mem))
+unsigned long __init free_area_init(unsigned long start_mem, unsigned long end_mem)
 {
 	mem_map_t * p;
 	unsigned long mask = PAGE_MASK;
diff -u --recursive --new-file v2.1.117/linux/mm/slab.c linux/mm/slab.c
--- v2.1.117/linux/mm/slab.c	Tue Jul 28 14:21:10 1998
+++ linux/mm/slab.c	Thu Aug 20 14:49:11 1998
@@ -406,7 +406,7 @@
 static unsigned long bufctl_limit = 0;
 
 /* Initialisation - setup the `cache' cache. */
-__initfunc(long kmem_cache_init(long start, long end))
+long __init kmem_cache_init(long start, long end)
 {
 	size_t size, i;
 
@@ -460,7 +460,7 @@
 /* Initialisation - setup remaining internal and general caches.
  * Called after the gfp() functions have been enabled, and before smp_init().
  */
-__initfunc(void kmem_cache_sizes_init(void))
+void __init kmem_cache_sizes_init(void)
 {
 	unsigned int	found = 0;
 
diff -u --recursive --new-file v2.1.117/linux/mm/swapfile.c linux/mm/swapfile.c
--- v2.1.117/linux/mm/swapfile.c	Thu Aug 20 17:05:19 1998
+++ linux/mm/swapfile.c	Tue Aug 25 13:47:38 1998
@@ -22,6 +22,7 @@
 #include <linux/blkdev.h> /* for blk_size */
 #include <linux/vmalloc.h>
 #include <linux/pagemap.h>
+#include <linux/shm.h>
 
 #include <asm/bitops.h>
 #include <asm/pgtable.h>
@@ -325,6 +326,7 @@
 		for_each_task(p)
 			unuse_process(p->mm, entry, page);
 		read_unlock(&tasklist_lock);
+		shm_unuse(entry, page);
 		/* Now get rid of the extra reference to the temporary
                    page we've been using. */
 		if (PageSwapCache(page_map))
diff -u --recursive --new-file v2.1.117/linux/mm/vmscan.c linux/mm/vmscan.c
--- v2.1.117/linux/mm/vmscan.c	Thu Aug 20 17:05:19 1998
+++ linux/mm/vmscan.c	Thu Aug 20 14:30:25 1998
@@ -24,6 +24,7 @@
 #include <linux/dcache.h>
 #include <linux/fs.h>
 #include <linux/pagemap.h>
+#include <linux/init.h>
 
 #include <asm/bitops.h>
 #include <asm/pgtable.h>
@@ -491,7 +492,7 @@
  * may be printed in the middle of another driver's init 
  * message).  It looks very bad when that happens.
  */
-void kswapd_setup(void)
+void __init kswapd_setup(void)
 {
        int i;
        char *revision="$Revision: 1.5 $", *s, *e;
diff -u --recursive --new-file v2.1.117/linux/net/netlink/netlink_dev.c linux/net/netlink/netlink_dev.c
--- v2.1.117/linux/net/netlink/netlink_dev.c	Fri May  8 23:14:57 1998
+++ linux/net/netlink/netlink_dev.c	Mon Aug 24 13:14:09 1998
@@ -185,6 +185,7 @@
 	netlink_ioctl,
 	NULL,		/* netlink_mmap */
 	netlink_open,
+	NULL,		/* flush */
 	netlink_release
 };
 
diff -u --recursive --new-file v2.1.117/linux/net/socket.c linux/net/socket.c
--- v2.1.117/linux/net/socket.c	Thu Aug 20 17:05:19 1998
+++ linux/net/socket.c	Mon Aug 24 12:35:57 1998
@@ -122,6 +122,7 @@
 	sock_ioctl,
 	NULL,			/* mmap */
 	NULL,			/* no special open code... */
+	NULL,			/* flush */
 	sock_close,
 	NULL,			/* no fsync */
 	sock_fasync
@@ -1441,7 +1442,7 @@
 	return 0;
 }
 
-__initfunc(void proto_init(void))
+void __init proto_init(void)
 {
 	extern struct net_proto protocols[];	/* Network protocols */
 	struct net_proto *pro;
@@ -1461,7 +1462,7 @@
 extern void wanrouter_init(void);
 #endif
 
-__initfunc(void sock_init(void))
+void __init sock_init(void)
 {
 	int i;
 
diff -u --recursive --new-file v2.1.117/linux/net/sunrpc/clnt.c linux/net/sunrpc/clnt.c
--- v2.1.117/linux/net/sunrpc/clnt.c	Thu Aug 20 17:05:19 1998
+++ linux/net/sunrpc/clnt.c	Fri Aug 21 15:42:26 1998
@@ -413,7 +413,7 @@
 		return;
 	printk("RPC: buffer allocation failed for task %p\n", task); 
 
-	if (1 || !signalled()) {
+	if (!signalled()) {
 		xprt_release(task);
 		task->tk_action = call_reserve;
 		rpc_delay(task, HZ);
diff -u --recursive --new-file v2.1.117/linux/net/sunrpc/sched.c linux/net/sunrpc/sched.c
--- v2.1.117/linux/net/sunrpc/sched.c	Thu Aug 20 17:05:19 1998
+++ linux/net/sunrpc/sched.c	Tue Aug 25 13:32:49 1998
@@ -128,7 +128,7 @@
 	if (!timer)
 		timer = __rpc_default_timer;
 	if (expires < jiffies) {
-		printk("RPC: bad timeout value %ld - setting to 10 sec!\n",
+		printk(KERN_ERR "RPC: bad timeout value %ld - setting to 10 sec!\n",
 					task->tk_timeout);
 		expires = jiffies + 10 * HZ;
 	}
@@ -164,7 +164,7 @@
 rpc_make_runnable(struct rpc_task *task)
 {
 	if (task->tk_timeout) {
-		printk("RPC: task w/ running timer in rpc_make_runnable!!\n");
+		printk(KERN_ERR "RPC: task w/ running timer in rpc_make_runnable!!\n");
 		return;
 	}
 	if (RPC_IS_ASYNC(task)) {
@@ -242,7 +242,7 @@
 
 #ifdef RPC_DEBUG
 	if (task->tk_magic != 0xf00baa) {
-		printk("RPC: attempt to wake up non-existing task!\n");
+		printk(KERN_ERR "RPC: attempt to wake up non-existing task!\n");
 		rpc_debug = ~0;
 		return;
 	}
@@ -352,7 +352,6 @@
 /*
  * This is the RPC `scheduler' (or rather, the finite state machine).
  */
-
 static int
 __rpc_execute(struct rpc_task *task)
 {
@@ -363,7 +362,7 @@
 				task->tk_pid, task->tk_flags);
 
 	if (!RPC_IS_RUNNING(task)) {
-		printk("RPC: rpc_execute called for sleeping task!!\n");
+		printk(KERN_WARNING "RPC: rpc_execute called for sleeping task!!\n");
 		return 0;
 	}
 
@@ -413,18 +412,12 @@
 			dprintk("RPC: %4d sync task going to sleep\n",
 							task->tk_pid);
 			if (current->pid == rpciod_pid)
-				printk("RPC: rpciod waiting on sync task!\n");
+				printk(KERN_ERR "RPC: rpciod waiting on sync task!\n");
 			current->timeout = 0;
 			sleep_on(&task->tk_wait);
-			
+
 			/* When the task received a signal, remove from
-			 * any queues etc, and make runnable again.
-			 *
-			 * The "intr" property isnt handled here. rpc_do_call
-			 * has changed the signal mask of the process for
-			 * a synchronous rpc call. If a signal gets through
-			 * this then its real.
-			 */
+			 * any queues etc, and make runnable again. */
 			if (signalled())
 				__rpc_wake_up(task);
 
@@ -467,11 +460,11 @@
 
 	if (incr) {
 		if (rpc_inhibit) {
-			printk("RPC: execution inhibited!\n");
+			printk(KERN_INFO "RPC: execution inhibited!\n");
 			return;
 		}
 		if (executing)
-			printk("RPC: %d tasks executed\n", executing);
+			printk(KERN_WARNING "RPC: %d tasks executed\n", executing);
 	}
 	
 	executing += incr;
@@ -770,6 +763,8 @@
 	rpc_inhibit--;
 }
 
+static struct semaphore rpciod_running = MUTEX_LOCKED;
+
 /*
  * This is the rpciod kernel thread
  */
@@ -786,11 +781,16 @@
 	 * Let our maker know we're running ...
 	 */
 	rpciod_pid = current->pid;
-	wake_up(&rpciod_idle);
+	up(&rpciod_running);
 
 	exit_files(current);
 	exit_mm(current);
+
+	spin_lock_irq(&current->sigmask_lock);
 	siginitsetinv(&current->blocked, sigmask(SIGKILL));
+	recalc_sigpending(current);
+	spin_unlock_irq(&current->sigmask_lock);
+
 	current->session = 1;
 	current->pgrp = 1;
 	sprintf(current->comm, "rpciod");
@@ -798,12 +798,7 @@
 	dprintk("RPC: rpciod starting (pid %d)\n", rpciod_pid);
 	while (rpciod_users) {
 		if (signalled()) {
-			if (sigismember(&current->signal, SIGKILL)) {
-				rpciod_killall();
-			} else {
-				printk("rpciod: ignoring signal (%d users)\n",
-					rpciod_users);
-			}
+			rpciod_killall();
 			flush_signals(current);
 		}
 		__rpc_schedule();
@@ -825,7 +820,7 @@
 
 	dprintk("RPC: rpciod shutdown commences\n");
 	if (all_tasks) {
-		printk("rpciod: active tasks at shutdown?!\n");
+		printk(KERN_ERR "rpciod: active tasks at shutdown?!\n");
 		rpciod_killall();
 	}
 
@@ -847,7 +842,7 @@
 		rpc_killall_tasks(NULL);
 		__rpc_schedule();
 		if (all_tasks) {
-printk("rpciod_killall: waiting for tasks to exit\n");
+			dprintk("rpciod_killall: waiting for tasks to exit\n");
 			current->state = TASK_INTERRUPTIBLE;
 			current->timeout = jiffies + 1;
 			schedule();
@@ -878,16 +873,17 @@
 	 * If there's no pid, we should be the first user.
 	 */
 	if (rpciod_users > 1)
-		printk("rpciod_up: no pid, %d users??\n", rpciod_users);
+		printk(KERN_WARNING "rpciod_up: no pid, %d users??\n", rpciod_users);
 	/*
 	 * Create the rpciod thread and wait for it to start.
 	 */
 	error = kernel_thread(rpciod, &rpciod_killer, 0);
 	if (error < 0) {
-		printk("rpciod_up: create thread failed, error=%d\n", error);
+		printk(KERN_WARNING "rpciod_up: create thread failed, error=%d\n", error);
+		rpciod_users--;
 		goto out;
 	}
-	sleep_on(&rpciod_idle);
+	down(&rpciod_running);
 	error = 0;
 out:
 	up(&rpciod_sema);
@@ -907,10 +903,10 @@
 		if (--rpciod_users)
 			goto out;
 	} else
-		printk("rpciod_down: pid=%d, no users??\n", rpciod_pid);
+		printk(KERN_WARNING "rpciod_down: pid=%d, no users??\n", rpciod_pid);
 
 	if (!rpciod_pid) {
-		printk("rpciod_down: Nothing to do!\n");
+		dprintk("rpciod_down: Nothing to do!\n");
 		goto out;
 	}
 
@@ -928,9 +924,9 @@
 	 * Display a message if we're going to wait longer.
 	 */
 	while (rpciod_pid) {
-		printk("rpciod_down: waiting for pid %d to exit\n", rpciod_pid);
+		dprintk("rpciod_down: waiting for pid %d to exit\n", rpciod_pid);
 		if (signalled()) {
-			printk("rpciod_down: caught signal\n");
+			dprintk("rpciod_down: caught signal\n");
 			break;
 		}
 		interruptible_sleep_on(&rpciod_killer);
diff -u --recursive --new-file v2.1.117/linux/net/sunrpc/xprt.c linux/net/sunrpc/xprt.c
--- v2.1.117/linux/net/sunrpc/xprt.c	Thu Aug 20 17:05:19 1998
+++ linux/net/sunrpc/xprt.c	Tue Aug 25 16:09:49 1998
@@ -140,9 +140,8 @@
  *	Adjust the iovec to move on 'n' bytes
  */
  
-extern inline void xprt_move_iov(struct msghdr *msg, int amount)
+extern inline void xprt_move_iov(struct msghdr *msg, struct iovec *niv, int amount)
 {
-	struct iovec niv[MAX_IOVEC];
 	struct iovec *iv=msg->msg_iov;
 	
 	/*
@@ -187,6 +186,7 @@
 	struct msghdr	msg;
 	mm_segment_t	oldfs;
 	int		result;
+	struct iovec	niv[MAX_IOVEC];
 
 	xprt_pktdump("packet data:",
 				xprt->snd_buf.io_vec->iov_base,
@@ -202,7 +202,7 @@
 	/* Dont repeat bytes */
 	
 	if(xprt->snd_sent)
-		xprt_move_iov(&msg, xprt->snd_sent);
+		xprt_move_iov(&msg, niv, xprt->snd_sent);
 		
 	oldfs = get_fs(); set_fs(get_ds());
 	result = sock_sendmsg(sock, &msg, xprt->snd_buf.io_len);
diff -u --recursive --new-file v2.1.117/linux/net/wanrouter/wanproc.c linux/net/wanrouter/wanproc.c
--- v2.1.117/linux/net/wanrouter/wanproc.c	Fri Jan 30 11:28:10 1998
+++ linux/net/wanrouter/wanproc.c	Mon Aug 24 13:02:44 1998
@@ -102,6 +102,7 @@
 	NULL,			/* ioctl   */
 	NULL,			/* mmap	   */
 	NULL,			/* no special open code	   */
+	NULL,			/* flush */
 	NULL,			/* no special release code */
 	NULL			/* can't fsync */
 };
@@ -141,6 +142,7 @@
 	wanrouter_ioctl,	/* ioctl   */
 	NULL,			/* mmap	   */
 	NULL,			/* no special open code	   */
+	NULL,			/* flush */
 	NULL,			/* no special release code */
 	NULL			/* can't fsync */
 };
