## Automatically generated incremental diff
## From:   linux-2.4.7-pre6
## To:     linux-2.4.7-pre7
## Robot:  $Id: make-incremental-diff,v 1.8 2001/12/04 06:05:04 hpa Exp $

diff -urN linux-2.4.7-pre6/Documentation/Configure.help linux/Documentation/Configure.help
--- linux-2.4.7-pre6/Documentation/Configure.help	Mon Dec  3 22:55:40 2001
+++ linux/Documentation/Configure.help	Mon Dec  3 22:55:49 2001
@@ -12204,34 +12204,38 @@
   The module is called freevxfs.o. If you want to compile it as a module,
   say M here and read Documentation/modules.txt. If unsure, say N.
 
-NTFS support (read only)
+NTFS file system support (read-only)
 CONFIG_NTFS_FS
   NTFS is the file system of Microsoft Windows NT. Say Y if you want
   to get read access to files on NTFS partitions of your hard drive.
   The Linux NTFS driver supports most of the mount options of the VFAT
-  driver, see Documentation/filesystems/ntfs.txt. Saying Y here will
-  give you read-only access to NTFS partitions.
+  driver, see <file:Documentation/filesystems/ntfs.txt>. Saying Y here
+  will give you read-only access to NTFS partitions.
 
   This code is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
   The module will be called ntfs.o. If you want to compile it as a
-  module, say M here and read Documentation/modules.txt.
+  module, say M here and read <file:Documentation/modules.txt>.
 
 NTFS write support (DANGEROUS)
 CONFIG_NTFS_RW
   If you say Y here, you will (maybe) be able to write to NTFS file
-  systems as well as read from them. The read-write support in
-  NTFS is far from being complete and is not well tested. If you
-  say Y here, back up your NTFS volume first since it may get
-  damaged. Also, make sure to run chkdsk from within Microsoft
-  Windows NT after having performed any writes to a NTFS partition
-  from Linux to detect any problems as early as possible.
+  systems as well as read from them. The read-write support in NTFS
+  is far from being complete and is not well tested. If you say Y
+  here, back up your NTFS volume first, since it will probably get
+  damaged. Also, download the Linux-NTFS project distribution from
+  Sourceforge at <http://linux-ntfs.sf.net/> and always run the
+  included ntfsfix utility after writing to an NTFS partition from
+  Linux to fix some of the damage done by the driver. You should run
+  ntfsfix _after_ unmounting the partition in Linux but _before_
+  rebooting into Windows. When Windows next boots, chkdsk will be
+  run automatically to fix the remaining damage.
   Please note that write support is limited to Windows NT4 and
   earlier versions.
 
   If unsure, say N.
 
-System V, Version 7, Xenix and Coherent filesystem support (read only)
+System V, Version 7, Xenix and Coherent filesystem support
 CONFIG_SYSV_FS
   SCO, Xenix and Coherent are commercial Unix systems for Intel
   machines, and Version 7 was used on the DEC PDP-11. Saying Y
@@ -12241,14 +12245,12 @@
 
   If you have floppies or hard disk partitions like that, it is likely
   that they contain binaries from those other Unix systems; in order
-  to run these binaries, you will want to install iBCS2 (Intel Binary
-  Compatibility Standard is a kernel module which lets you run SCO,
-  Xenix, Wyse, UnixWare, Dell Unix and System V programs under Linux
-  and is often needed to run commercial software that's only available
-  for those systems. It's available via FTP (user: anonymous) from
-  ftp://tsx-11.mit.edu/pub/linux/BETA ). NOTE: that will work only for
-  binaries from Intel-based systems; PDP ones will have to wait until
-  somebody ports Linux to -11 ;-)
+  to run these binaries, you will want to install linux-abi which is a
+  a set of kernel modules that lets you run SCO, Xenix, Wyse, UnixWare,
+  Dell Unix and System V programs under Linux.  It's available via FTP
+  (user: ftp) from ftp://ftp.openlinux.org/pub/people/hch/linux-abi).
+  NOTE: that will work only for binaries from Intel-based systems;
+  PDP ones will have to wait until somebody ports Linux to -11 ;-)
 
   If you only intend to mount files from some other Unix over the
   network using NFS, you don't need the System V file system support
@@ -12269,15 +12271,6 @@
 
   If you haven't heard about all of this before, it's safe to say N.
 
-SYSV file system write support (DANGEROUS)
-CONFIG_SYSV_FS_WRITE
-  If you say Y here, you will be able to write to hard drive
-  partitions and floppy disks which carry a SYSV file system used the
-  commercial Unixes SCO, Xenix and Coherent. 
-
-  This support is experimental and you may destroy your data. If
-  unsure, say N.
-
 Amiga FFS file system support
 CONFIG_AFFS_FS
   The Fast File System (FFS) is the common file system used on hard
@@ -15631,9 +15624,18 @@
 VIA 82Cxxx Audio Codec
 CONFIG_SOUND_VIA82CXXX
   Say Y here to include support for the audio codec found on VIA
-  82Cxxx-based chips. Typically these are built into a motherboard. DO
-  NOT select Sound Blaster or Adlib with this driver, unless you have
-  a Sound Blaster or Adlib card in addition to your VIA audio chip.
+  82Cxxx-based chips. Typically these are built into a motherboard.
+
+  DO NOT select Sound Blaster or Adlib with this driver, unless
+  you have a Sound Blaster or Adlib card in addition to your VIA
+  audio chip.
+
+VIA 82C686 MIDI
+CONFIG_MIDI_VIA82CXXX
+   Answer Y to use the MIDI interface of the Via686. You may need to
+   enable this in the BIOS before it will work. This is for connection
+   to external MIDI hardware, and is not required for software playback
+   of MIDI files.
 
 NeoMagic 256AV/256ZX sound chipsets
 CONFIG_SOUND_NM256
diff -urN linux-2.4.7-pre6/Documentation/DocBook/videobook.tmpl linux/Documentation/DocBook/videobook.tmpl
--- linux-2.4.7-pre6/Documentation/DocBook/videobook.tmpl	Thu Jan  4 12:50:12 2001
+++ linux/Documentation/DocBook/videobook.tmpl	Mon Dec  3 22:55:49 2001
@@ -179,23 +179,23 @@
    <tgroup cols=3 align=left>
    <tbody>
    <row>
-        <entry>VFL_TYPE_RADIO</><>/dev/radio{n}</><>
+        <entry>VFL_TYPE_RADIO</><entry>/dev/radio{n}</><entry>
 
         Radio devices are assigned in this block. As with all of these
         selections the actual number assignment is done by the video layer
         accordijng to what is free.</entry>
 	</row><row>
-        <entry>VFL_TYPE_GRABBER</><>/dev/video{n}</><>
+        <entry>VFL_TYPE_GRABBER</><entry>/dev/video{n}</><entry>
         Video capture devices and also -- counter-intuitively for the name --
         hardware video playback devices such as MPEG2 cards.</entry>
 	</row><row>
-        <entry>VFL_TYPE_VBI</><>/dev/vbi{n}</><>
+        <entry>VFL_TYPE_VBI</><entry>/dev/vbi{n}</><entry>
         The VBI devices capture the hidden lines on a television picture
         that carry further information like closed caption data, teletext
         (primarily in Europe) and now Intercast and the ATVEC internet
         television encodings.</entry>
 	</row><row>
-        <entry>VFL_TYPE_VTX</><>/dev/vtx[n}</><>
+        <entry>VFL_TYPE_VTX</><entry>/dev/vtx[n}</><entry>
         VTX is 'Videotext' also known as 'Teletext'. This is a system for
         sending numbered, 40x25, mostly textual page images over the hidden
         lines. Unlike the /dev/vbi interfaces, this is for 'smart' decoder 
@@ -302,25 +302,25 @@
    <tgroup cols=2 align=left>
    <tbody>
    <row>
-        <entry>name</><>The device text name. This is intended for the user.</>
+        <entry>name</><entry>The device text name. This is intended for the user.</>
 	</row><row>
-        <entry>channels</><>The number of different channels you can tune on
+        <entry>channels</><entry>The number of different channels you can tune on
                         this card. It could even by zero for a card that has
                         no tuning capability. For our simple FM radio it is 1. 
                         An AM/FM radio would report 2.</entry>
 	</row><row>
-        <entry>audios</><>The number of audio inputs on this device. For our
+        <entry>audios</><entry>The number of audio inputs on this device. For our
                         radio there is only one audio input.</entry>
 	</row><row>
-        <entry>minwidth,minheight</><>The smallest size the card is capable of capturing
+        <entry>minwidth,minheight</><entry>The smallest size the card is capable of capturing
 		        images in. We set these to zero. Radios do not
                         capture pictures</entry>
 	</row><row>
-        <entry>maxwidth,maxheight</><>The largest image size the card is capable of
+        <entry>maxwidth,maxheight</><entry>The largest image size the card is capable of
                                       capturing. For our radio we report 0.
 				</entry>
 	</row><row>
-        <entry>type</><>This reports the capabilities of the device, and
+        <entry>type</><entry>This reports the capabilities of the device, and
                         matches the field we filled in in the struct
                         video_device when registering.</entry>
     </row>
@@ -415,7 +415,7 @@
 	</row><row>
         <entry>VIDEO_TUNER_SECAM</><entry>A SECAM (French) TV tuner</entry>
 	</row><row>
-        <entry>VIDEO_TUNER_LOW</><>
+        <entry>VIDEO_TUNER_LOW</><entry>
              The tuner frequency is scaled in 1/16th of a KHz
              steps. If not it is in 1/16th of a MHz steps
 	</entry>
@@ -432,13 +432,13 @@
    <tgroup cols=2 align=left>
    <tbody>
    <row>
-                <entry>VIDEO_MODE_PAL</><>PAL Format</entry>
+                <entry>VIDEO_MODE_PAL</><entry>PAL Format</entry>
    </row><row>
-                <entry>VIDEO_MODE_NTSC</><>NTSC Format (USA)</entry>
+                <entry>VIDEO_MODE_NTSC</><entry>NTSC Format (USA)</entry>
    </row><row>
-                <entry>VIDEO_MODE_SECAM</><>French Format</entry>
+                <entry>VIDEO_MODE_SECAM</><entry>French Format</entry>
    </row><row>
-                <entry>VIDEO_MODE_AUTO</><>A device that does not need to do
+                <entry>VIDEO_MODE_AUTO</><entry>A device that does not need to do
                                         TV format switching</entry>
    </row>
     </tbody>
@@ -583,30 +583,30 @@
    <tgroup cols=2 align=left>
    <tbody>
    <row>
-   <entry>audio</><>The input the user wishes to query</>
+   <entry>audio</><entry>The input the user wishes to query</>
    </row><row>
-   <entry>volume</><>The volume setting on a scale of 0-65535</>
+   <entry>volume</><entry>The volume setting on a scale of 0-65535</>
    </row><row>
-   <entry>base</><>The base level on a scale of 0-65535</>
+   <entry>base</><entry>The base level on a scale of 0-65535</>
    </row><row>
-   <entry>treble</><>The treble level on a scale of 0-65535</>
+   <entry>treble</><entry>The treble level on a scale of 0-65535</>
    </row><row>
-   <entry>flags</><>The features this audio device supports
+   <entry>flags</><entry>The features this audio device supports
    </entry>
    </row><row>
-   <entry>name</><>A text name to display to the user. We picked 
+   <entry>name</><entry>A text name to display to the user. We picked 
                         "Radio" as it explains things quite nicely.</>
    </row><row>
-   <entry>mode</><>The current reception mode for the audio
+   <entry>mode</><entry>The current reception mode for the audio
 
                 We report MONO because our card is too stupid to know if it is in
                 mono or stereo. 
    </entry>
    </row><row>
-   <entry>balance</><>The stereo balance on a scale of 0-65535, 32768 is
+   <entry>balance</><entry>The stereo balance on a scale of 0-65535, 32768 is
                         middle.</>
    </row><row>
-   <entry>step</><>The step by which the volume control jumps. This is
+   <entry>step</><entry>The step by which the volume control jumps. This is
                         used to help make it easy for applications to set 
                         slider behaviour.</>   
    </row>
@@ -618,15 +618,15 @@
    <tgroup cols=2 align=left>
    <tbody>
    <row>
-                <entry>VIDEO_AUDIO_MUTE</><>The audio is currently muted. We
+                <entry>VIDEO_AUDIO_MUTE</><entry>The audio is currently muted. We
                                         could fake this in our driver but we
                                         choose not to bother.</entry>
    </row><row>
-                <entry>VIDEO_AUDIO_MUTABLE</><>The input has a mute option</entry>
+                <entry>VIDEO_AUDIO_MUTABLE</><entry>The input has a mute option</entry>
    </row><row>
-                <entry>VIDEO_AUDIO_TREBLE</><>The  input has a treble control</entry>
+                <entry>VIDEO_AUDIO_TREBLE</><entry>The  input has a treble control</entry>
    </row><row>
-                <entry>VIDEO_AUDIO_BASS</><>The input has a base control</entry>
+                <entry>VIDEO_AUDIO_BASS</><entry>The input has a base control</entry>
    </row>
    </tbody>
    </tgroup>
@@ -636,13 +636,13 @@
    <tgroup cols=2 align=left>
    <tbody>
    <row>
-                <entry>VIDEO_SOUND_MONO</><>Mono sound</entry>
+                <entry>VIDEO_SOUND_MONO</><entry>Mono sound</entry>
    </row><row>
-                <entry>VIDEO_SOUND_STEREO</><>Stereo sound</entry>
+                <entry>VIDEO_SOUND_STEREO</><entry>Stereo sound</entry>
    </row><row>
-                <entry>VIDEO_SOUND_LANG1</><>Alternative language 1 (TV specific)</entry>
+                <entry>VIDEO_SOUND_LANG1</><entry>Alternative language 1 (TV specific)</entry>
    </row><row>
-                <entry>VIDEO_SOUND_LANG2</><>Alternative language 2 (TV specific)</entry>
+                <entry>VIDEO_SOUND_LANG2</><entry>Alternative language 2 (TV specific)</entry>
    </row>
    </tbody>
    </tgroup>
@@ -867,33 +867,33 @@
    <tgroup cols=2 align=left>
    <tbody>
    <row>
-<entry>VID_TYPE_CAPTURE</><>We support image capture</>
+<entry>VID_TYPE_CAPTURE</><entry>We support image capture</>
 </row><row>
-<entry>VID_TYPE_TELETEXT</><>A teletext capture device (vbi{n])</>
+<entry>VID_TYPE_TELETEXT</><entry>A teletext capture device (vbi{n])</>
 </row><row>
-<entry>VID_TYPE_OVERLAY</><>The image can be directly overlaid onto the
+<entry>VID_TYPE_OVERLAY</><entry>The image can be directly overlaid onto the
                                 frame buffer</>
 </row><row>
-<entry>VID_TYPE_CHROMAKEY</><>Chromakey can be used to select which parts
+<entry>VID_TYPE_CHROMAKEY</><entry>Chromakey can be used to select which parts
                                 of the image to display</>
 </row><row>
-<entry>VID_TYPE_CLIPPING</><>It is possible to give the board a list of
+<entry>VID_TYPE_CLIPPING</><entry>It is possible to give the board a list of
                                 rectangles to draw around. </>
 </row><row>
-<entry>VID_TYPE_FRAMERAM</><>The video capture goes into the video memory
+<entry>VID_TYPE_FRAMERAM</><entry>The video capture goes into the video memory
                                 and actually changes it. Applications need
                                 to know this so they can clean up after the
                                 card</>
 </row><row>
-<entry>VID_TYPE_SCALES</><>The image can be scaled to various sizes,
+<entry>VID_TYPE_SCALES</><entry>The image can be scaled to various sizes,
                                 rather than being a single fixed size.</>
 </row><row>
-<entry>VID_TYPE_MONOCHROME</><>The capture will be monochrome. This isn't a 
+<entry>VID_TYPE_MONOCHROME</><entry>The capture will be monochrome. This isn't a 
                                 complete answer to the question since a mono
                                 camera on a colour capture card will still
                                 produce mono output.</>
 </row><row>
-<entry>VID_TYPE_SUBCAPTURE</><>The card allows only part of its field of
+<entry>VID_TYPE_SUBCAPTURE</><entry>The card allows only part of its field of
                                 view to be captured. This enables
                                 applications to avoid copying all of a large
                                 image into memory when only some section is
@@ -1209,18 +1209,18 @@
    <tbody>
    <row>
 
-   <entry>channel</><>The channel number we are selecting</entry>
+   <entry>channel</><entry>The channel number we are selecting</entry>
    </row><row>
-   <entry>name</><>The name for this channel. This is intended
+   <entry>name</><entry>The name for this channel. This is intended
                    to describe the port to the user.
                    Appropriate names are therefore things like
                    "Camera" "SCART input"</entry>
    </row><row>
-   <entry>flags</><>Channel properties</entry>
+   <entry>flags</><entry>Channel properties</entry>
    </row><row>
-   <entry>type</><>Input type</entry>
+   <entry>type</><entry>Input type</entry>
    </row><row>
-   <entry>norm</><>The current television encoding being used
+   <entry>norm</><entry>The current television encoding being used
                    if relevant for this channel.
     </entry>
     </row>
@@ -1231,9 +1231,9 @@
     <tgroup cols=2 align=left>
     <tbody>
     <row>
-        <entry>VIDEO_VC_TUNER</><>Channel has a tuner.</entry>
+        <entry>VIDEO_VC_TUNER</><entry>Channel has a tuner.</entry>
    </row><row>
-        <entry>VIDEO_VC_AUDIO</><>Channel has audio.</entry>
+        <entry>VIDEO_VC_AUDIO</><entry>Channel has audio.</entry>
     </row>
     </tbody>
     </tgroup>
@@ -1242,11 +1242,11 @@
     <tgroup cols=2 align=left>
     <tbody>
     <row>
-        <entry>VIDEO_TYPE_TV</><>Television input.</entry>
+        <entry>VIDEO_TYPE_TV</><entry>Television input.</entry>
    </row><row>
-        <entry>VIDEO_TYPE_CAMERA</><>Fixed camera input.</entry>
+        <entry>VIDEO_TYPE_CAMERA</><entry>Fixed camera input.</entry>
    </row><row>
-	<entry>0</><>Type is unknown.</entry>
+	<entry>0</><entry>Type is unknown.</entry>
     </row>
     </tbody>
     </tgroup>
@@ -1255,13 +1255,13 @@
     <tgroup cols=2 align=left>
     <tbody>
     <row>
-        <entry>VIDEO_MODE_PAL</><>PAL encoded Television</entry>
+        <entry>VIDEO_MODE_PAL</><entry>PAL encoded Television</entry>
    </row><row>
-        <entry>VIDEO_MODE_NTSC</><>NTSC (US) encoded Television</entry>
+        <entry>VIDEO_MODE_NTSC</><entry>NTSC (US) encoded Television</entry>
    </row><row>
-        <entry>VIDEO_MODE_SECAM</><>SECAM (French) Television </entry>
+        <entry>VIDEO_MODE_SECAM</><entry>SECAM (French) Television </entry>
    </row><row>
-        <entry>VIDEO_MODE_AUTO</><>Automatic switching, or format does not
+        <entry>VIDEO_MODE_AUTO</><entry>Automatic switching, or format does not
                                 matter</entry>
     </row>
     </tbody>
@@ -1341,13 +1341,13 @@
    <tgroup cols=2 align=left>
    <tbody>
    <row>
-   <entry>GREY</><>Linear greyscale. This is for simple cameras and the
+   <entry>GREY</><entry>Linear greyscale. This is for simple cameras and the
                         like</>
    </row><row>
-   <entry>RGB565</><>The top 5 bits hold 32 red levels, the next six bits 
+   <entry>RGB565</><entry>The top 5 bits hold 32 red levels, the next six bits 
                         hold green and the low 5 bits hold blue. </>
    </row><row>
-   <entry>RGB555</><>The top bit is clear. The red green and blue levels
+   <entry>RGB555</><entry>The top bit is clear. The red green and blue levels
                         each occupy five bits.</>
     </row>
     </tbody>
@@ -1479,32 +1479,32 @@
    <tgroup cols=2 align=left>
    <tbody>
    <row>
-        <entry>width</><>The width in pixels of the desired image. The card
+        <entry>width</><entry>The width in pixels of the desired image. The card
                         may use a smaller size if this size is not available</>
 	</row><row>
-        <entry>height</><>The height of the image. The card may use a smaller
+        <entry>height</><entry>The height of the image. The card may use a smaller
                         size if this size is not available.</>
 	</row><row>
-        <entry>x</><>   The X position of the top left of the window. This
+        <entry>x</><entry>   The X position of the top left of the window. This
                         is in pixels relative to the left hand edge of the
                         picture. Not all cards can display images aligned on
                         any pixel boundary. If the position is unsuitable
                         the card adjusts the image right and reduces the
                         width.</>
 	</row><row>
-        <entry>y</><>   The Y position of the top left of the window. This
+        <entry>y</><entry>   The Y position of the top left of the window. This
                         is counted in pixels relative to the top edge of the
                         picture. As with the width if the card cannot
                         display  starting on this line it will adjust the
                         values.</>
 	</row><row>
-        <entry>chromakey</><>The colour (expressed in RGB32 format) for the
+        <entry>chromakey</><entry>The colour (expressed in RGB32 format) for the
                         chromakey colour if chroma keying is being used. </>
 	</row><row>
-        <entry>clips</><>An array of rectangles that must not be drawn
+        <entry>clips</><entry>An array of rectangles that must not be drawn
 			over.</>
 	</row><row>
-        <entry>clipcount</><>The number of clips in this array.</>
+        <entry>clipcount</><entry>The number of clips in this array.</>
     </row>
     </tbody>
     </tgroup>
@@ -1516,11 +1516,11 @@
    <tgroup cols=2 align=left>
    <tbody>
    <row>
-        <entry>x, y</><>Co-ordinates relative to the display</>
+        <entry>x, y</><entry>Co-ordinates relative to the display</>
 	</row><row>
-        <entry>width, height</><>Width and height in pixels</>
+        <entry>width, height</><entry>Width and height in pixels</>
 	</row><row>
-        <entry>next</><>A spare field for the application to use</>
+        <entry>next</><entry>A spare field for the application to use</>
     </row>
     </tbody>
     </tgroup>
diff -urN linux-2.4.7-pre6/Documentation/filesystems/devfs/ChangeLog linux/Documentation/filesystems/devfs/ChangeLog
--- linux-2.4.7-pre6/Documentation/filesystems/devfs/ChangeLog	Wed Jun 20 10:54:31 2001
+++ linux/Documentation/filesystems/devfs/ChangeLog	Mon Dec  3 22:55:49 2001
@@ -1661,3 +1661,17 @@
 - Replaced <devfsd_read> stack usage with <devfsd_ioctl> kmalloc
 
 - Simplified locking in <devfsd_ioctl> and fixed memory leak
+===============================================================================
+Changes for patch v182
+
+- Created <devfs_*alloc_major> and <devfs_*alloc_devnum>
+
+- Removed broken devnum allocation and use <devfs_alloc_devnum>
+
+- Fixed old devnum leak by calling new <devfs_dealloc_devnum>
+
+- Created <devfs_*alloc_unique_number>
+
+- Fixed number leak for /dev/cdroms/cdrom%d
+
+- Fixed number leak for /dev/discs/disc%d
diff -urN linux-2.4.7-pre6/Documentation/filesystems/ext2.txt linux/Documentation/filesystems/ext2.txt
--- linux-2.4.7-pre6/Documentation/filesystems/ext2.txt	Fri Apr 20 16:18:35 2001
+++ linux/Documentation/filesystems/ext2.txt	Mon Dec  3 22:55:49 2001
@@ -299,6 +299,8 @@
 so 8kB blocks are only allowed on Alpha systems (and other architectures
 which support larger pages).
 
+There is an upper limit of 32768 subdirectories in a single directory.
+
 There is a "soft" upper limit of about 10-15k files in a single directory
 with the current linear linked-list directory implementation.  This limit
 stems from performance problems when creating and deleting (and also
diff -urN linux-2.4.7-pre6/Documentation/filesystems/ntfs.txt linux/Documentation/filesystems/ntfs.txt
--- linux-2.4.7-pre6/Documentation/filesystems/ntfs.txt	Fri Feb 16 15:53:08 2001
+++ linux/Documentation/filesystems/ntfs.txt	Mon Dec  3 22:55:49 2001
@@ -1,6 +1,9 @@
 NTFS Overview
 =============
 
+Driver development has as of recently (since June '01) been sponsored
+by Legato Systems, Inc. (http://www.legato.com)
+
 To mount an NTFS volume, use the filesystem type 'ntfs'. The driver
 currently works only in read-only mode, with no fault-tolerance supported.
 
@@ -9,9 +12,18 @@
 distribution from Sourceforge at http://sourceforge.net/projects/linux-ntfs/
 and always run the included ntfsfix utility after performing a write to an
 NTFS partition from Linux to fix some of the damage done by the Linux NTFS
-driver. You should run ntfsfix _after_ unmounting the partition in Linux but
-_before_ rebooting into Windows. During the next reboot into Windows, chkdsk
-will be run automatically to fix the remaining damage.
+driver and to schedule an automatic chkdsk when Windows reboots. You should
+run ntfsfix _after_ unmounting the partition in Linux but _before_ rebooting
+into Windows. During the next reboot into Windows, chkdsk will be run
+automatically fixing the remaining damage. If no errors are found it is a
+good indication that the driver + ntfsfix together worked to full
+satisfaction. (-;
+
+Please note that the experimental write support is limited to Windows NT4 and
+earlier versions at the moment.
+
+If you think you have discovered a bug please have look at the "Known bugs"
+section below to see whether it isn't known already.
 
 For ftdisk support, limited success was reported with volume sets on top of
 the md driver, although mirror and stripe sets should work as well - if the
@@ -19,25 +31,78 @@
 using the md driver will fail if any of your NTFS partitions have an odd
 number of sectors.
 
-Please note that the experimental write support is limited to
-Windows NT4 and earlier versions at the moment.
+Supported mount options
+=======================
+
+iocharset=name		Character set to use when returning file names.
+			Unlike VFAT, NTFS suppresses names that contain
+			unconvertible characters
+
+utf8=<bool>		Use UTF-8 for converting file names
+
+uni_xlate=<bool>,2	Use the VFAT-style encoding for file names outside
+			the current character set. A boolean value will
+			enable the feature, a value of 2 will enable the
+			encoding as documented in vfat.txt:
+				':', (u & 0x3f), ((u>>6) & 0x3f), (u>>12),
 
-The ntfs driver supports the following mount options:
-iocharset=name      Character set to use when returning file names.
-                    Unlike VFAT, NTFS suppresses names that contain
-		    unconvertible characters
-utf8=<bool>	    Use UTF-8 for converting file names
-uni_xlate=<bool>,2  Use the VFAT-style encoding for file names outside
-		    the current character set. A boolean value will
-		    enable the feature, a value of 2 will enable the
-		    encoding as documented in vfat.txt:
-		    ':', (u & 0x3f), ((u>>6) & 0x3f), (u>>12),
 uid=
 gid=
-umask=              These options work as documented in mount(8).
-		    By default, the files are owned by root and
-		    not readable by somebody else.
-posix=<bool>	    If enabled, the file system distinguishes between
-		    upper and lower case. The 8.3 alias names are presented
-		    as hard links instead of being suppressed.
+umask=			These options work as documented in mount(8).
+			By default, the files are owned by root and
+			not readable by anyone else.
+
+posix=<bool>		If enabled, the file system distinguishes between
+			upper and lower case. The 8.3 alias names are presented
+			as hard links instead of being suppressed.
+
+show_sys_files=<bool>	If enabled, show all system files as normal files. Note
+			that $MFT does not appear unless specifically
+			requested. For example in bash, use: "ls -l \$MFT".
+			Be careful not to write anything to them or you could
+			crash the kernel and/or corrupt your file system!
+
+Known bugs and (mis-)features
+=============================
+
+- Do not use the driver for writing as it corrupts the file system. If you do
+  use it, get the Linux-NTFS tools and use the ntfsfix utility after
+  dismounting a partition you wrote to.
+
+- Use the show_sys_files mount option which should make things work generally
+  better. (It results in both the short and long file names being shown as well
+  as the sytem files.)
+
+- Writing of extension records is not supported properly.
+
+Please send bug reports/comments/feed back/abuse to the Linux-NTFS development
+list at sourceforge: linux-ntfs-dev@lists.sourceforge.net
+
+ChangeLog
+=========
+
+NTFS 1.1.15 (changes since kernel 2.4.4's NTFS driver):
+
+	- New mount option show_sys_files=<bool> to show all system files as
+	  normal files.
+	- Support for files and in general any attributes up to the full 2TiB
+	  size supported by the NTFS filesystem. Note we only support up to
+	  32-bits worth of inodes/clusters at this point.
+	- Support for more than 128kiB sized runlists (using vmalloc_32()
+	  instead of kmalloc()).
+	- Fixed races in allocation of clusters and mft records.
+	- Fixed major bugs in attribute handling / searching / collation.
+	- Fixed major bugs in compressing a run list into a mapping pairs array.
+	- Fixed major bugs in inode allocation. Especially file create and
+	  mkdir.
+	- Fixed memory leaks.
+	- Fixed major bug in inode layout assignment of sequence numbers.
+	- Lots of other bug fixes I can't think of right now...
+	- Fixed NULL bug found by the Stanford checker in ntfs_dupuni2map().
+	- Convert large stack variable to dynamically allocated one in
+	  ntfs_get_free_cluster_count() (found by Stanford checker).
+
+Kernel 2.4.4:
+
+	- Started ChangeLog.
 
diff -urN linux-2.4.7-pre6/Documentation/ioctl-number.txt linux/Documentation/ioctl-number.txt
--- linux-2.4.7-pre6/Documentation/ioctl-number.txt	Sat May 19 17:54:14 2001
+++ linux/Documentation/ioctl-number.txt	Mon Dec  3 22:55:49 2001
@@ -187,3 +187,5 @@
 0xB1	00-1F	PPPoX			<mailto:mostrows@styx.uwaterloo.ca>
 0xCB	00-1F	CBM serial IEC bus	in development:
 					<mailto:michael.klein@puffin.lb.shuttle.de>
+
+0xFE	00-9F	Logical Volume Manager	<mailto:linux-lvm@sistina.com>
diff -urN linux-2.4.7-pre6/Documentation/networking/dl2k.txt linux/Documentation/networking/dl2k.txt
--- linux-2.4.7-pre6/Documentation/networking/dl2k.txt	Mon Dec  3 22:55:40 2001
+++ linux/Documentation/networking/dl2k.txt	Mon Dec  3 22:55:49 2001
@@ -1,5 +1,5 @@
 
-    D-Link DL2000-based Gigabit Ethernet Adapter Installation 
+    D-Link DL2000-based Gigabit Ethernet Adapter Installation
     for Linux
     July 5, 2001
 
@@ -22,7 +22,7 @@
 D-Link DL2000-based Gigabit Ethernet Adapter.
 
 
-The driver support Linux kernal 2.4.x later. We had tested it 
+The driver support Linux kernal 2.4.x later. We had tested it
 on the environments below.
 
  . Red Hat v6.2 (update to kernel 2.4.4)
@@ -35,17 +35,17 @@
 Install linux driver as following command:
 
 1. make all
-2. insmod dl2x.o 
+2. insmod dl2x.o
 3. ifconfig eth0 up 10.xxx.xxx.xxx netmask 255.0.0.0
-                    ^^^^^^^^^^^^^^^\        ^^^^^^^^\
-		    		    IP	             NETMASK 
-Now eth0 bring up, you can test it by "ping" or get more information by 
+		    ^^^^^^^^^^^^^^^\	    ^^^^^^^^\
+				    IP		     NETMASK
+Now eth0 bring up, you can test it by "ping" or get more information by
 "ifconfig". If test ok, then continue next step.
 
 4. cp dl2x.o /lib/modules/`uname -r`/kernel/drivers/net
 5. Add the following lines to /etc/modules.conf:
 	alias eth0 dl2x
-6. Run "netconfig" or "netconf" to create configuration script ifcfg-eth0 
+6. Run "netconfig" or "netconf" to create configuration script ifcfg-eth0
    located at /etc/sysconfig/network-scripts or create it manually.
    [see - Configuration Script Sample]
 7. Driver will automatically load and configure at next boot time.
@@ -64,7 +64,7 @@
 The 3 files necessary to build Linux device driver are dl2x.c, dl2x.h and
 Makefile. To compile, the Linux installation must include the gcc compiler,
 the kernel source, and the kernel headers. The Linux driver supports Linux
-Kernels 2.4.x. Copy the files to a directory and enter the following command 
+Kernels 2.4.x. Copy the files to a directory and enter the following command
 to compile and link the driver:
 
 CD-ROM drive
@@ -76,7 +76,7 @@
 [root@XXX /root] mkdir dl2x
 [root@XXX /root] cd dl2x
 [root@XXX dl2x] cp /cdrom/linux/dl2x.tgz /root/dl2x
-[root@XXX dl2x] tar xfvz dl2x.tgz 
+[root@XXX dl2x] tar xfvz dl2x.tgz
 [root@XXX dl2x] make all
 
 Floppy disc drive
@@ -86,7 +86,7 @@
 [root@XXX /root] mkdir dl2x
 [root@XXX /root] cd dl2x
 [root@XXX dl2x] mcopy a:/linux/dl2x.tgz /root/dl2x
-[root@XXX dl2x] tar xfvz dl2x.tgz 
+[root@XXX dl2x] tar xfvz dl2x.tgz
 [root@XXX dl2x] make all
 
 Installing the Driver
@@ -99,15 +99,15 @@
   module enter the command:
 
   insmod dl2x.o
- 
+
 
   or
 
-  insmod dl2x.o <optional parameter>    ; add parameter
-  
+  insmod dl2x.o <optional parameter>	; add parameter
+
   ===============================================================
    example: insmod dl2x.o media=100mbps_hd
-   or       insmod dl2x.o media=3
+   or	    insmod dl2x.o media=3
    or	    insmod dl2x.o media=3 2	; for 2 cards
   ===============================================================
 
@@ -172,37 +172,37 @@
 
 Parameter Description
 =====================
-You can install this driver without any addtional parameter. However, if you 
-are going to have extensive functions then it is necessary to set extra 
-parameter. Below is a list of the command line parameters supported by the 
+You can install this driver without any addtional parameter. However, if you
+are going to have extensive functions then it is necessary to set extra
+parameter. Below is a list of the command line parameters supported by the
 Linux device
 driver.
 
-mtu=packet_size                 - Specifies the maximum packet size. default
-                                  is 1500.
+mtu=packet_size			- Specifies the maximum packet size. default
+				  is 1500.
 
 media=xxxxxxxxx			- Specifies the media type the NIC operates at.
 				  autosense	Autosensing active media.
-				  10mbps_hd 	10Mbps half duplex.
-				  10mbps_fd 	10Mbps full duplex.
-				  100mbps_hd 	100Mbps half duplex.
-				  100mbps_fd 	100Mbps full duplex.
+				  10mbps_hd	10Mbps half duplex.
+				  10mbps_fd	10Mbps full duplex.
+				  100mbps_hd	100Mbps half duplex.
+				  100mbps_fd	100Mbps full duplex.
 				  1000mbps_fd	1000Mbps full duplex.
 				  1000mbps_hd	1000Mbps half duplex.
 				  0		Autosensing active media.
-				  1	 	10Mbps half duplex.
-				  2	 	10Mbps full duplex.
-				  3	 	100Mbps half duplex.
-				  4	 	100Mbps full duplex.
+				  1		10Mbps half duplex.
+				  2		10Mbps full duplex.
+				  3		100Mbps half duplex.
+				  4		100Mbps full duplex.
 				  5		1000Mbps full duplex.
 				  6		1000Mbps half duplex.
 				  By default, the NIC operates at autosense.
-				  
-vlan=x				- Specifies the VLAN ID. If vlan=0, the  
+
+vlan=x				- Specifies the VLAN ID. If vlan=0, the
 				  Virtual Local Area Network (VLAN) function is
-				  disable. 
-				  
-jumbo=x				- Specifies the jumbo frame support. If jumbo=1, 
+				  disable.
+
+jumbo=x				- Specifies the jumbo frame support. If jumbo=1,
 				  the NIC accept jumbo frames. By default, this
 				  function is disabled.
 
@@ -222,15 +222,25 @@
 
 Troubleshooting
 ===============
-Q: Couldn't compiler the driver ?
-A1: Copy all necessary files on same current directory. Make sure all files 
-   are Unix file format (no LF). You can use some convertible program conver 
-   it from DOS to UNIX. (Like dos2unix,  UltraEdit-32 ...).
-      
-A2: The default include directory configured in Makefile is 
-    /usr/src/linux/include. If kernel source was not installed, you could 
-    not compile driver. Try to install kernel source, and make sure kernel 
-    source in /usr/src/linux. If there is a copy of header files in 
-    /usr/include, you can try to change the variable "INCLUDEDIR" in Makefile from 
-    /usr/src/linux/include to /usr/include.
-    
+Q1. Source files contain behind every line.
+	Make sure all files are Unix file format (no LF). Try the following
+    shell command to convert files.
+
+	cat dl2k.c | col -b > dl2k.tmp
+	mv dl2k.tmp dl2k.c
+
+	OR
+
+	cat dl2k.c | tr -d "\r" > dl2k.tmp
+	mv dl2k.tmp dl2k.c
+
+Q2: Could not find header files (*.h) ?
+	To compile the driver, you need kernel header files. After
+    installing the kernel source, the header files are usually located in
+    /usr/src/linux/include, which is the default include directory configured
+    in Makefile. For some distributions, there is a copy of header files in
+    /usr/src/include/linux and /usr/src/include/asm, that you can change the
+    INCLUDEDIR in Makefile to /usr/include without installing kernel source.
+	Note that RH 7.0 didn't provide correct header files in /usr/include,
+    including those files will make a wrong version driver.
+
diff -urN linux-2.4.7-pre6/MAINTAINERS linux/MAINTAINERS
--- linux-2.4.7-pre6/MAINTAINERS	Mon Dec  3 22:55:40 2001
+++ linux/MAINTAINERS	Mon Dec  3 22:55:49 2001
@@ -841,6 +841,12 @@
 M:	zab@zabbo.net
 S:	Odd Fixes
 
+MATROX FRAMEBUFFER DRIVER
+P:	Petr Vandrovec
+M:	vandrove@vc.cvut.cz
+L:	linux-fbdev-devel@lists.sourceforge.net
+S:	Maintained
+
 MEMORY TECHNOLOGY DEVICES
 P:	David Woodhouse
 M:	dwmw2@redhat.com
@@ -1304,10 +1310,11 @@
 S:	Maintained
 
 TOKEN-RING NETWORK DRIVER
-P:	Paul Norton
-M:	pnorton@ieee.org
+P:	Mike Phillips
+M:	mikep@linuxtr.net
 L:	linux-net@vger.kernel.org
 L:	linux-tr@linuxtr.net
+W:	http://www.linuxtr.net
 S:	Maintained
 
 TRIDENT 4DWAVE/SIS 7018 PCI AUDIO CORE
diff -urN linux-2.4.7-pre6/Makefile linux/Makefile
--- linux-2.4.7-pre6/Makefile	Mon Dec  3 22:55:40 2001
+++ linux/Makefile	Mon Dec  3 22:55:49 2001
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 7
-EXTRAVERSION =-pre6
+EXTRAVERSION =-pre7
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
@@ -88,7 +88,7 @@
 CPPFLAGS := -D__KERNEL__ -I$(HPATH)
 
 CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes -Wno-trigraphs -O2 \
-          -fomit-frame-pointer -fno-strict-aliasing
+	  -fomit-frame-pointer -fno-strict-aliasing -fno-common
 AFLAGS := -D__ASSEMBLY__ $(CPPFLAGS)
 
 #
@@ -147,6 +147,7 @@
 DRIVERS-$(CONFIG_ATM) += drivers/atm/atm.o
 DRIVERS-$(CONFIG_IDE) += drivers/ide/idedriver.o
 DRIVERS-$(CONFIG_SCSI) += drivers/scsi/scsidrv.o
+DRIVERS-$(CONFIG_FUSION_BOOT) += drivers/message/fusion/fusion.o
 DRIVERS-$(CONFIG_IEEE1394) += drivers/ieee1394/ieee1394drv.o
 
 ifneq ($(CONFIG_CD_NO_IDESCSI)$(CONFIG_BLK_DEV_IDECD)$(CONFIG_BLK_DEV_SR)$(CONFIG_PARIDE_PCD),)
@@ -333,14 +334,14 @@
 TAGS: dummy
 	etags `find include/asm-$(ARCH) -name '*.h'`
 	find include -type d \( -name "asm-*" -o -name config \) -prune -o -name '*.h' -print | xargs etags -a
-	find $(SUBDIRS) init -name '*.c' | xargs etags -a
+	find $(SUBDIRS) init -name '*.[ch]' | xargs etags -a
 
 # Exuberant ctags works better with -I
 tags: dummy
 	CTAGSF=`ctags --version | grep -i exuberant >/dev/null && echo "-I __initdata,__exitdata,EXPORT_SYMBOL,EXPORT_SYMBOL_NOVERS"`; \
 	ctags $$CTAGSF `find include/asm-$(ARCH) -name '*.h'` && \
 	find include -type d \( -name "asm-*" -o -name config \) -prune -o -name '*.h' -print | xargs ctags $$CTAGSF -a && \
-	find $(SUBDIRS) init -name '*.c' | xargs ctags $$CTAGSF -a
+	find $(SUBDIRS) init -name '*.[ch]' | xargs ctags $$CTAGSF -a
 
 ifdef CONFIG_MODULES
 ifdef CONFIG_MODVERSIONS
diff -urN linux-2.4.7-pre6/arch/i386/config.in linux/arch/i386/config.in
--- linux-2.4.7-pre6/arch/i386/config.in	Wed Jun 20 17:47:39 2001
+++ linux/arch/i386/config.in	Mon Dec  3 22:55:49 2001
@@ -303,6 +303,8 @@
 fi
 endmenu
 
+source drivers/message/fusion/Config.in
+
 source drivers/ieee1394/Config.in
 
 source drivers/i2o/Config.in
diff -urN linux-2.4.7-pre6/arch/i386/defconfig linux/arch/i386/defconfig
--- linux-2.4.7-pre6/arch/i386/defconfig	Mon Dec  3 22:55:40 2001
+++ linux/arch/i386/defconfig	Mon Dec  3 22:55:49 2001
@@ -335,6 +335,15 @@
 # CONFIG_SCSI_PCMCIA is not set
 
 #
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+# CONFIG_FUSION_BOOT is not set
+# CONFIG_FUSION_ISENSE is not set
+# CONFIG_FUSION_CTL is not set
+# CONFIG_FUSION_LAN is not set
+
+#
 # I2O device support
 #
 # CONFIG_I2O is not set
diff -urN linux-2.4.7-pre6/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c
--- linux-2.4.7-pre6/arch/i386/kernel/setup.c	Mon Dec  3 22:55:40 2001
+++ linux/arch/i386/kernel/setup.c	Mon Dec  3 22:55:49 2001
@@ -1994,6 +1994,9 @@
 		wrmsr(0x119,lo,hi);
 		printk(KERN_NOTICE "CPU serial number disabled.\n");
 		clear_bit(X86_FEATURE_PN, &c->x86_capability);
+
+		/* Disabling the serial number may affect the cpuid level */
+		c->cpuid_level = cpuid_eax(0);
 	}
 }
 
diff -urN linux-2.4.7-pre6/drivers/Makefile linux/drivers/Makefile
--- linux-2.4.7-pre6/drivers/Makefile	Mon Jun 11 19:15:27 2001
+++ linux/drivers/Makefile	Mon Dec  3 22:55:49 2001
@@ -6,9 +6,9 @@
 #
 
 
-mod-subdirs :=	dio mtd sbus video macintosh usb input telephony sgi i2o ide \
-		scsi md ieee1394 pnp isdn atm fc4 net/hamradio i2c acpi \
-		bluetooth
+mod-subdirs :=	dio mtd sbus video macintosh usb input telephony sgi ide \
+		i2o message/fusion scsi md ieee1394 pnp isdn atm \
+		fc4 net/hamradio i2c acpi bluetooth
 
 subdir-y :=	parport char block net sound misc media cdrom
 subdir-m :=	$(subdir-y)
@@ -32,6 +32,7 @@
 subdir-$(CONFIG_IDE)		+= ide
 subdir-$(CONFIG_SCSI)		+= scsi
 subdir-$(CONFIG_I2O)		+= i2o
+subdir-$(CONFIG_FUSION)		+= message/fusion
 subdir-$(CONFIG_MD)		+= md
 subdir-$(CONFIG_IEEE1394)	+= ieee1394
 subdir-$(CONFIG_PNP)		+= pnp
diff -urN linux-2.4.7-pre6/drivers/atm/nicstar.c linux/drivers/atm/nicstar.c
--- linux-2.4.7-pre6/drivers/atm/nicstar.c	Wed Jun 27 14:13:01 2001
+++ linux/drivers/atm/nicstar.c	Mon Dec  3 22:55:49 2001
@@ -214,8 +214,8 @@
 
 static u32 ns_read_sram(ns_dev *card, u32 sram_address);
 static void ns_write_sram(ns_dev *card, u32 sram_address, u32 *value, int count);
-static int ns_init_card(int i, struct pci_dev *pcidev);
-static void ns_init_card_error(ns_dev *card, int error);
+static int __init ns_init_card(int i, struct pci_dev *pcidev);
+static void __init ns_init_card_error(ns_dev *card, int error);
 static scq_info *get_scq(int size, u32 scd);
 static void free_scq(scq_info *scq, struct atm_vcc *vcc);
 static void push_rxbufs(ns_dev *card, u32 type, u32 handle1, u32 addr1,
@@ -277,7 +277,7 @@
 
 #ifdef MODULE
 
-int init_module(void)
+int __init init_module(void)
 {
    int i;
    unsigned error = 0;	/* Initialized to remove compile warning */
@@ -511,7 +511,7 @@
 }
 
 
-static int ns_init_card(int i, struct pci_dev *pcidev)
+static int __init ns_init_card(int i, struct pci_dev *pcidev)
 {
    int j;
    struct ns_dev *card = NULL;
@@ -1007,7 +1007,7 @@
 
 
 
-static void ns_init_card_error(ns_dev *card, int error)
+static void __init ns_init_card_error(ns_dev *card, int error)
 {
    if (error >= 17)
    {
diff -urN linux-2.4.7-pre6/drivers/block/genhd.c linux/drivers/block/genhd.c
--- linux-2.4.7-pre6/drivers/block/genhd.c	Wed May 16 14:01:32 2001
+++ linux/drivers/block/genhd.c	Mon Dec  3 22:55:49 2001
@@ -21,6 +21,9 @@
 #ifdef CONFIG_BLK_DEV_DAC960
 extern void DAC960_Initialize(void);
 #endif
+#ifdef CONFIG_FUSION_BOOT
+extern int fusion_init(void);
+#endif
 extern int net_dev_init(void);
 extern void console_map_init(void);
 extern int soc_probe(void);
@@ -38,6 +41,9 @@
 #endif
 #ifdef CONFIG_BLK_DEV_DAC960
 	DAC960_Initialize();
+#endif
+#ifdef CONFIG_FUSION_BOOT
+	fusion_init();
 #endif
 #ifdef CONFIG_FC4_SOC
 	/* This has to be done before scsi_dev_init */
diff -urN linux-2.4.7-pre6/drivers/block/rd.c linux/drivers/block/rd.c
--- linux-2.4.7-pre6/drivers/block/rd.c	Mon Dec  3 22:55:40 2001
+++ linux/drivers/block/rd.c	Mon Dec  3 22:55:49 2001
@@ -570,8 +570,9 @@
 	char *buf;
 	unsigned short rotate = 0;
 	unsigned short devblocks = 0;
+#if !defined(CONFIG_ARCH_S390) && !defined(CONFIG_PPC_ISERIES)
 	char rotator[4] = { '|' , '/' , '-' , '\\' };
-
+#endif
 	ram_device = MKDEV(MAJOR_NR, unit);
 
 	if ((inode = get_empty_inode()) == NULL)
@@ -672,7 +673,7 @@
 		}
 		infile.f_op->read(&infile, buf, BLOCK_SIZE, &infile.f_pos);
 		outfile.f_op->write(&outfile, buf, BLOCK_SIZE, &outfile.f_pos);
-#if !defined(CONFIG_ARCH_S390)
+#if !defined(CONFIG_ARCH_S390) && !defined(CONFIG_PPC_ISERIES)
 		if (!(i % 16)) {
 			printk("%c\b", rotator[rotate & 0x3]);
 			rotate++;
diff -urN linux-2.4.7-pre6/drivers/cdrom/cdrom.c linux/drivers/cdrom/cdrom.c
--- linux-2.4.7-pre6/drivers/cdrom/cdrom.c	Fri May  4 15:09:23 2001
+++ linux/drivers/cdrom/cdrom.c	Mon Dec  3 22:55:49 2001
@@ -331,6 +331,7 @@
 #endif /* CONFIG_SYSCTL */ 
 static struct cdrom_device_info *topCdromPtr;
 static devfs_handle_t devfs_handle;
+static struct unique_numspace cdrom_numspace = UNIQUE_NUMBERSPACE_INITIALISER;
 
 struct block_device_operations cdrom_fops =
 {
@@ -354,7 +355,6 @@
         struct cdrom_device_ops *cdo = cdi->ops;
         int *change_capability = (int *)&cdo->capability; /* hack */
 	char vname[16];
-	static unsigned int cdrom_counter;
 
 	cdinfo(CD_OPEN, "entering register_cdrom\n"); 
 
@@ -395,7 +395,8 @@
 
 	if (!devfs_handle)
 		devfs_handle = devfs_mk_dir (NULL, "cdroms", NULL);
-	sprintf (vname, "cdrom%u", cdrom_counter++);
+	cdi->number = devfs_alloc_unique_number (&cdrom_numspace);
+	sprintf (vname, "cdrom%d", cdi->number);
 	if (cdi->de) {
 		int pos;
 		devfs_handle_t slave;
@@ -450,6 +451,7 @@
 		topCdromPtr = cdi->next;
 	cdi->ops->n_minors--;
 	devfs_unregister (cdi->de);
+	devfs_dealloc_unique_number (&cdrom_numspace, cdi->number);
 	cdinfo(CD_REG_UNREG, "drive \"/dev/%s\" unregistered\n", cdi->name);
 	return 0;
 }
diff -urN linux-2.4.7-pre6/drivers/cdrom/sbpcd.c linux/drivers/cdrom/sbpcd.c
--- linux-2.4.7-pre6/drivers/cdrom/sbpcd.c	Thu May 24 15:14:08 2001
+++ linux/drivers/cdrom/sbpcd.c	Mon Dec  3 22:55:49 2001
@@ -4308,7 +4308,7 @@
 		i=verify_area(VERIFY_READ, (void *) arg, sizeof(struct cdrom_read_audio));
 		if (i) RETURN_UP(i);
 		copy_from_user(&read_audio, (void *) arg, sizeof(struct cdrom_read_audio));
-		if (read_audio.nframes>D_S[d].sbp_audsiz) RETURN_UP(-EINVAL);
+		if (read_audio.nframes < 0 || read_audio.nframes>D_S[d].sbp_audsiz) RETURN_UP(-EINVAL);
 		i=verify_area(VERIFY_WRITE, read_audio.buf,
 			      read_audio.nframes*CD_FRAMESIZE_RAW);
 		if (i) RETURN_UP(i);
diff -urN linux-2.4.7-pre6/drivers/char/drm/bufs.c linux/drivers/char/drm/bufs.c
--- linux-2.4.7-pre6/drivers/char/drm/bufs.c	Mon Mar 19 12:35:08 2001
+++ linux/drivers/char/drm/bufs.c	Mon Dec  3 22:55:49 2001
@@ -202,6 +202,12 @@
 		return -ENOMEM;	/* May only call once for each order */
 	}
 	
+	if(count < 0 || count > 4096)
+	{
+		up(&dev->struct_sem);
+		return -EINVAL;
+	}
+	
 	entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
 				   DRM_MEM_BUFS);
 	if (!entry->buflist) {
diff -urN linux-2.4.7-pre6/drivers/char/drm/i810_bufs.c linux/drivers/char/drm/i810_bufs.c
--- linux-2.4.7-pre6/drivers/char/drm/i810_bufs.c	Tue Aug 29 14:09:15 2000
+++ linux/drivers/char/drm/i810_bufs.c	Mon Dec  3 22:55:49 2001
@@ -87,7 +87,14 @@
 		atomic_dec(&dev->buf_alloc);
 		return -ENOMEM; /* May only call once for each order */
 	}
-   
+
+	if(count < 0 || count > 4096)
+	{
+		up(&dev->struct_sem);
+		atomic_dec(&dev->buf_alloc);
+		return -EINVAL;
+	}
+	   
 	entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
 				   DRM_MEM_BUFS);
 	if (!entry->buflist) {
diff -urN linux-2.4.7-pre6/drivers/char/drm/i810_dma.c linux/drivers/char/drm/i810_dma.c
--- linux-2.4.7-pre6/drivers/char/drm/i810_dma.c	Wed Jun 27 17:10:55 2001
+++ linux/drivers/char/drm/i810_dma.c	Mon Dec  3 22:55:49 2001
@@ -1416,6 +1416,11 @@
    	buf_priv = buf->dev_private;
 	if (buf_priv->currently_mapped != I810_BUF_MAPPED) return -EPERM;
 
+	/* Stopping end users copying their data to the entire kernel
+	   is good.. */
+	if (d.used < 0 || d.used > buf->total)
+		return -EINVAL;
+		
    	if (copy_from_user(buf_priv->virtual, d.address, d.used))
 		return -EFAULT;
 
diff -urN linux-2.4.7-pre6/drivers/char/drm/ioctl.c linux/drivers/char/drm/ioctl.c
--- linux-2.4.7-pre6/drivers/char/drm/ioctl.c	Tue Aug 29 14:09:15 2000
+++ linux/drivers/char/drm/ioctl.c	Mon Dec  3 22:55:49 2001
@@ -82,7 +82,7 @@
 	if (copy_from_user(&u, (drm_unique_t *)arg, sizeof(u)))
 		return -EFAULT;
 
-	if (!u.unique_len)
+	if (!u.unique_len || u.unique_len > 1024)
 		return -EINVAL;
 	
 	dev->unique_len = u.unique_len;
diff -urN linux-2.4.7-pre6/drivers/char/drm/mga_bufs.c linux/drivers/char/drm/mga_bufs.c
--- linux-2.4.7-pre6/drivers/char/drm/mga_bufs.c	Mon Mar 19 12:35:08 2001
+++ linux/drivers/char/drm/mga_bufs.c	Mon Dec  3 22:55:49 2001
@@ -97,7 +97,17 @@
 		atomic_dec(&dev->buf_alloc);
 		return -ENOMEM; /* May only call once for each order */
 	}
-   
+
+	/* This isnt neccessarily a good limit, but we have to stop a dumb
+	   32 bit overflow problem below */
+	   
+	if ( count < 0 || count > 4096)
+	{
+		up(&dev->struct_sem);
+		atomic_dec(&dev->buf_alloc);
+		return -EINVAL;
+	}
+		   
 	entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
 				   DRM_MEM_BUFS);
 	if (!entry->buflist) {
@@ -248,6 +258,13 @@
 		up(&dev->struct_sem);
 		atomic_dec(&dev->buf_alloc);
 		return -ENOMEM;	/* May only call once for each order */
+	}
+	
+	if(count < 0 || count > 4096)
+	{
+		up(&dev->struct_sem);
+		atomic_dec(&dev->buf_alloc);
+		return -EINVAL;
 	}
 	
 	entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
diff -urN linux-2.4.7-pre6/drivers/char/drm/r128_bufs.c linux/drivers/char/drm/r128_bufs.c
--- linux-2.4.7-pre6/drivers/char/drm/r128_bufs.c	Mon Mar 19 12:35:08 2001
+++ linux/drivers/char/drm/r128_bufs.c	Mon Dec  3 22:55:49 2001
@@ -103,6 +103,16 @@
 		return -ENOMEM; /* May only call once for each order */
 	}
 
+	/* Might be a poor limit, but take that up with XFree86 
+	   if its a problem */
+	   
+	if(count < 0 || count > 4096)
+	{
+		up(&dev->struct_sem);
+		atomic_dec(&dev->buf_alloc);
+		return -EINVAL;
+	}
+		
 	entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
 				   DRM_MEM_BUFS);
 	if (!entry->buflist) {
diff -urN linux-2.4.7-pre6/drivers/char/drm/radeon_bufs.c linux/drivers/char/drm/radeon_bufs.c
--- linux-2.4.7-pre6/drivers/char/drm/radeon_bufs.c	Wed Jun 27 17:10:55 2001
+++ linux/drivers/char/drm/radeon_bufs.c	Mon Dec  3 22:55:49 2001
@@ -100,6 +100,15 @@
 		return -ENOMEM; /* May only call once for each order */
 	}
 
+	/* Might be too low a limit. XFree folks need to fix this properly */
+	
+	if(count < 0 || count > 4096)
+	{
+		up(&dev->struct_sem);
+		atomic_dec(&dev->buf_alloc);
+		return -EINVAL;
+	}
+		
 	entry->buflist = drm_alloc(count * sizeof(*entry->buflist),
 				   DRM_MEM_BUFS);
 	if (!entry->buflist) {
diff -urN linux-2.4.7-pre6/drivers/char/dsp56k.c linux/drivers/char/dsp56k.c
--- linux-2.4.7-pre6/drivers/char/dsp56k.c	Fri Mar  2 18:38:37 2001
+++ linux/drivers/char/dsp56k.c	Mon Dec  3 22:55:49 2001
@@ -64,7 +64,7 @@
 
 #define wait_some(n) \
 { \
-	current->state = TASK_INTERRUPTIBLE; \
+	set_current_state(TASK_INTERRUPTIBLE); \
 	schedule_timeout(n); \
 }
 
@@ -149,7 +149,7 @@
 
 
 static struct dsp56k_device {
-	int in_use;
+	long in_use;
 	long maxio, timeout;
 	int tx_wsize, rx_wsize;
 } dsp56k;
@@ -451,10 +451,9 @@
 	{
 	case DSP56K_DEV_56001:
 
-		if (dsp56k.in_use)
+		if (test_and_set_bit(0, &dsp56k.in_use))
 			return -EBUSY;
 
-		dsp56k.in_use = 1;
 		dsp56k.timeout = TIMEOUT;
 		dsp56k.maxio = MAXIO;
 		dsp56k.rx_wsize = dsp56k.tx_wsize = 4; 
@@ -469,8 +468,7 @@
 		break;
 
 	default:
-		printk(KERN_ERR "DSP56k driver: Unknown minor device: %d\n", dev);
-		return -ENXIO;
+		return -ENODEV;
 	}
 
 	return 0;
@@ -483,11 +481,7 @@
 	switch(dev)
 	{
 	case DSP56K_DEV_56001:
-
-		lock_kernel();
-		dsp56k.in_use = 0;
-		unlock_kernel();
-
+		clear_bit(0, &dsp56k.in_use);
 		break;
 	default:
 		printk(KERN_ERR "DSP56k driver: Unknown minor device: %d\n", dev);
diff -urN linux-2.4.7-pre6/drivers/char/esp.c linux/drivers/char/esp.c
--- linux-2.4.7-pre6/drivers/char/esp.c	Wed Jun 27 14:13:01 2001
+++ linux/drivers/char/esp.c	Mon Dec  3 22:55:49 2001
@@ -32,6 +32,9 @@
  *   Support for PIO mode.  This allows the driver to work properly with
  *     multiport cards.
  *
+ * Arnaldo Carvalho de Melo <acme@conectiva.com.br> -
+ * several cleanups, use module_init/module_exit, etc
+ *
  * This module exports the following rs232 io functions:
  *
  *	int espserial_init(void);
@@ -100,8 +103,8 @@
 
 #define WAKEUP_CHARS 1024
 
-static char *serial_name = "ESP serial driver";
-static char *serial_version = "2.2";
+static char serial_name[] __initdata = "ESP serial driver";
+static char serial_version[] __initdata = "2.2";
 
 static DECLARE_TASK_QUEUE(tq_esp);
 
@@ -174,9 +177,9 @@
 					kdev_t device, const char *routine)
 {
 #ifdef SERIAL_PARANOIA_CHECK
-	static const char *badmagic =
+	static const char badmagic[] = KERN_WARNING
 		"Warning: bad magic number for serial struct (%s) in %s\n";
-	static const char *badinfo =
+	static const char badinfo[] = KERN_WARNING
 		"Warning: null esp_struct for (%s) in %s\n";
 
 	if (!info) {
@@ -285,8 +288,7 @@
 		buf = free_pio_buf;
 		free_pio_buf = buf->next;
 	} else {
-		buf = (struct esp_pio_buffer *)
-			kmalloc(sizeof(struct esp_pio_buffer), GFP_ATOMIC);
+		buf = kmalloc(sizeof(struct esp_pio_buffer), GFP_ATOMIC);
 	}
 
 	return buf;
@@ -887,17 +889,14 @@
 
 	save_flags(flags); cli();
 
-	if (info->flags & ASYNC_INITIALIZED) {
-		restore_flags(flags);
-		return retval;
-	}
+	if (info->flags & ASYNC_INITIALIZED)
+		goto out;
 
 	if (!info->xmit_buf) {
 		info->xmit_buf = (unsigned char *)get_free_page(GFP_KERNEL);
-		if (!info->xmit_buf) {
-			restore_flags(flags);
-			return -ENOMEM;
-		}
+		retval = -ENOMEM;
+		if (!info->xmit_buf)
+			goto out;
 	}
 
 #ifdef SERIAL_DEBUG_OPEN
@@ -944,9 +943,7 @@
 					&info->tty->flags);
 			retval = 0;
 		}
-		
-		restore_flags(flags);
-		return retval;
+		goto out;
 	}
 
 	if (!(info->stat_flags & ESP_STAT_USE_PIO) && !dma_buffer) {
@@ -1003,8 +1000,9 @@
 	change_speed(info);
 
 	info->flags |= ASYNC_INITIALIZED;
-	restore_flags(flags);
-	return 0;
+	retval = 0;
+out:	restore_flags(flags);
+	return retval;
 }
 
 /*
@@ -1500,10 +1498,7 @@
 	tmp.pio_threshold = info->config.pio_threshold;
 	tmp.dma_channel = (info->stat_flags & ESP_STAT_NEVER_DMA ? 0 : dma);
 
-	if (copy_to_user(retinfo,&tmp,sizeof(*retinfo)))
-		return -EFAULT;
-
-	return 0;
+	return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0;
 }
 
 static int set_serial_info(struct esp_struct * info,
@@ -1803,12 +1798,10 @@
 static int set_modem_info(struct esp_struct * info, unsigned int cmd,
 			  unsigned int *value)
 {
-	int error;
 	unsigned int arg;
 
-	error = get_user(arg, value);
-	if (error)
-		return error;
+	if (get_user(arg, value))
+		return -EFAULT;
 
 	switch (cmd) {
 	case TIOCMBIS: 
@@ -1866,7 +1859,6 @@
 static int rs_ioctl(struct tty_struct *tty, struct file * file,
 		    unsigned int cmd, unsigned long arg)
 {
-	int error;
 	struct esp_struct * info = (struct esp_struct *)tty->driver_data;
 	struct async_icount cprev, cnow;	/* kernel counter temps */
 	struct serial_icounter_struct *p_cuser;	/* user space */
@@ -1929,13 +1921,19 @@
 				cli();
 				cnow = info->icount;	/* atomic copy */
 				sti();
-				if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && 
-				    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
+				if (cnow.rng == cprev.rng &&
+				    cnow.dsr == cprev.dsr && 
+				    cnow.dcd == cprev.dcd &&
+				    cnow.cts == cprev.cts)
 					return -EIO; /* no change => error */
-				if ( ((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
-				     ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
-				     ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) ||
-				     ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) {
+				if (((arg & TIOCM_RNG) &&
+				     (cnow.rng != cprev.rng)) ||
+				     ((arg & TIOCM_DSR) &&
+				      (cnow.dsr != cprev.dsr)) ||
+				     ((arg & TIOCM_CD) &&
+				      (cnow.dcd != cprev.dcd)) ||
+				     ((arg & TIOCM_CTS) &&
+				      (cnow.cts != cprev.cts)) ) {
 					return 0;
 				}
 				cprev = cnow;
@@ -1953,22 +1951,17 @@
 			cnow = info->icount;
 			sti();
 			p_cuser = (struct serial_icounter_struct *) arg;
-			if ((error = put_user(cnow.cts, &p_cuser->cts)))
-				return error;
-			if ((error = put_user(cnow.dsr, &p_cuser->dsr)))
-				return error;
-			if ((error = put_user(cnow.rng, &p_cuser->rng)))
-				return error;
-			if ((error = put_user(cnow.dcd, &p_cuser->dcd)))
-				return error;
+			if (put_user(cnow.cts, &p_cuser->cts) ||
+			    put_user(cnow.dsr, &p_cuser->dsr) ||
+			    put_user(cnow.rng, &p_cuser->rng) ||
+			    put_user(cnow.dcd, &p_cuser->dcd))
+				return -EFAULT;
 
 			return 0;
 	case TIOCGHAYESESP:
-		return (get_esp_config(info,
-				       (struct hayes_esp_config *)arg));
+		return (get_esp_config(info, (struct hayes_esp_config *)arg));
 	case TIOCSHAYESESP:
-		return (set_esp_config(info,
-				       (struct hayes_esp_config *)arg));
+		return (set_esp_config(info, (struct hayes_esp_config *)arg));
 
 		default:
 			return -ENOIOCTLCMD;
@@ -2050,9 +2043,7 @@
 	
 	if (tty_hung_up_p(filp)) {
 		DBG_CNT("before DEC-hung");
-		MOD_DEC_USE_COUNT;
-		restore_flags(flags);
-		return;
+		goto out;
 	}
 	
 #ifdef SERIAL_DEBUG_OPEN
@@ -2077,9 +2068,7 @@
 	}
 	if (info->count) {
 		DBG_CNT("before DEC-2");
-		MOD_DEC_USE_COUNT;
-		restore_flags(flags);
-		return;
+		goto out;
 	}
 	info->flags |= ASYNC_CLOSING;
 	/*
@@ -2140,7 +2129,7 @@
 	info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE|
 			 ASYNC_CLOSING);
 	wake_up_interruptible(&info->close_wait);
-	MOD_DEC_USE_COUNT;
+out:	MOD_DEC_USE_COUNT;
 	restore_flags(flags);
 }
 
@@ -2360,7 +2349,6 @@
 {
 	struct esp_struct	*info;
 	int 			retval, line;
-	unsigned long		page;
 
 	line = MINOR(tty->device) - tty->driver.minor_start;
 	if ((line < 0) || (line >= NR_PORTS))
@@ -2388,13 +2376,9 @@
 	info->tty = tty;
 
 	if (!tmp_buf) {
-		page = get_free_page(GFP_KERNEL);
-		if (!page)
+		tmp_buf = (unsigned char *) get_free_page(GFP_KERNEL);
+		if (!tmp_buf)
 			return -ENOMEM;
-		if (tmp_buf)
-			free_page(page);
-		else
-			tmp_buf = (unsigned char *) page;
 	}
 	
 	/*
@@ -2613,8 +2597,7 @@
 		return 1;
 	}
 	
-	info = (struct esp_struct *)kmalloc(sizeof(struct esp_struct),
-		GFP_KERNEL);
+	info = kmalloc(sizeof(struct esp_struct), GFP_KERNEL);
 
 	if (!info)
 	{
@@ -2685,8 +2668,7 @@
 		if (!dma)
 			info->stat_flags |= ESP_STAT_NEVER_DMA;
 
-		info = (struct esp_struct *)kmalloc(sizeof(struct esp_struct),
-			GFP_KERNEL);
+		info = kmalloc(sizeof(struct esp_struct), GFP_KERNEL);
 		if (!info)
 		{
 			printk(KERN_ERR "Couldn't allocate memory for esp serial device information\n"); 
@@ -2714,14 +2696,7 @@
 	return 0;
 }
 
-#ifdef MODULE
-
-int init_module(void)
-{
-	return espserial_init();
-}
-
-void cleanup_module(void) 
+static void __exit espserial_exit(void) 
 {
 	unsigned long flags;
 	int e1, e2;
@@ -2782,4 +2757,6 @@
 		free_pio_buf = pio_buf;
 	}
 }
-#endif /* MODULE */
+
+module_init(espserial_init);
+module_exit(espserial_exit);
diff -urN linux-2.4.7-pre6/drivers/char/i810-tco.c linux/drivers/char/i810-tco.c
--- linux-2.4.7-pre6/drivers/char/i810-tco.c	Mon Jul  2 13:56:41 2001
+++ linux/drivers/char/i810-tco.c	Mon Dec  3 22:55:49 2001
@@ -261,11 +261,13 @@
 	 */
 
 	pci_for_each_dev(dev) {
-		if (pci_match_device(i810tco_pci_tbl, dev))
+		if (pci_match_device(i810tco_pci_tbl, dev)) {
+			i810tco_pci = dev;
 			break;
+		}
 	}
 
-	if ((i810tco_pci = dev)) {
+	if (i810tco_pci) {
 		/*
 		 *      Find the ACPI base I/O address which is the base
 		 *      for the TCO registers (TCOBASE=ACPIBASE + 0x60)
diff -urN linux-2.4.7-pre6/drivers/char/istallion.c linux/drivers/char/istallion.c
--- linux-2.4.7-pre6/drivers/char/istallion.c	Fri Mar  2 11:12:07 2001
+++ linux/drivers/char/istallion.c	Mon Dec  3 22:55:49 2001
@@ -2075,13 +2075,10 @@
 			(unsigned int *) arg);
 		break;
 	case TIOCSSOFTCAR:
-		if ((rc = verify_area(VERIFY_READ, (void *) arg,
-		    sizeof(unsigned int))) == 0) {
-			get_user(ival, (unsigned int *) arg);
+		if ((rc = get_user(ival, (unsigned int *) arg)) == 0)
 			tty->termios->c_cflag =
 				(tty->termios->c_cflag & ~CLOCAL) |
 				(ival ? CLOCAL : 0);
-		}
 		break;
 	case TIOCMGET:
 		if ((rc = verify_area(VERIFY_WRITE, (void *) arg,
@@ -2094,9 +2091,7 @@
 		}
 		break;
 	case TIOCMBIS:
-		if ((rc = verify_area(VERIFY_READ, (void *) arg,
-		    sizeof(unsigned int))) == 0) {
-			get_user(ival, (unsigned int *) arg);
+		if ((rc = get_user(ival, (unsigned int *) arg)) == 0) {
 			stli_mkasysigs(&portp->asig,
 				((ival & TIOCM_DTR) ? 1 : -1),
 				((ival & TIOCM_RTS) ? 1 : -1));
@@ -2105,9 +2100,7 @@
 		}
 		break;
 	case TIOCMBIC:
-		if ((rc = verify_area(VERIFY_READ, (void *) arg,
-		    sizeof(unsigned int))) == 0) {
-			get_user(ival, (unsigned int *) arg);
+		if ((rc = get_user(ival, (unsigned int *) arg)) == 0) {
 			stli_mkasysigs(&portp->asig,
 				((ival & TIOCM_DTR) ? 0 : -1),
 				((ival & TIOCM_RTS) ? 0 : -1));
@@ -2116,9 +2109,7 @@
 		}
 		break;
 	case TIOCMSET:
-		if ((rc = verify_area(VERIFY_READ, (void *) arg,
-		    sizeof(unsigned int))) == 0) {
-			get_user(ival, (unsigned int *) arg);
+		if ((rc = get_user(ival, (unsigned int *) arg)) == 0) {
 			stli_mkasysigs(&portp->asig,
 				((ival & TIOCM_DTR) ? 1 : 0),
 				((ival & TIOCM_RTS) ? 1 : 0));
@@ -2137,16 +2128,11 @@
 			rc = stli_setserial(portp, (struct serial_struct *)arg);
 		break;
 	case STL_GETPFLAG:
-		if ((rc = verify_area(VERIFY_WRITE, (void *) arg,
-		    sizeof(unsigned long))) == 0)
-			put_user(portp->pflag, (unsigned int *) arg);
+		rc = put_user(portp->pflag, (unsigned int *) arg);
 		break;
 	case STL_SETPFLAG:
-		if ((rc = verify_area(VERIFY_READ, (void *) arg,
-		    sizeof(unsigned long))) == 0) {
-			get_user(portp->pflag, (unsigned int *) arg);
+		if ((rc = get_user(portp->pflag, (unsigned int *) arg)) == 0)
 			stli_setport(portp);
-		}
 		break;
 	case COM_GETPORTSTATS:
 		if ((rc = verify_area(VERIFY_WRITE, (void *) arg,
@@ -2357,7 +2343,7 @@
 	stliport_t	*portp;
 
 #if DEBUG
-	printk("stli_dohangup(portp=%x)\n", (int) arg);
+	printk(KERN_DEBUG "stli_dohangup(portp=%x)\n", (int) arg);
 #endif
 
 	/*
@@ -2390,7 +2376,7 @@
 	unsigned long	flags;
 
 #if DEBUG
-	printk("stli_hangup(tty=%x)\n", (int) tty);
+	printk(KERN_DEBUG "stli_hangup(tty=%x)\n", (int) tty);
 #endif
 
 	if (tty == (struct tty_struct *) NULL)
@@ -2448,7 +2434,7 @@
 	unsigned long	ftype, flags;
 
 #if DEBUG
-	printk("stli_flushbuffer(tty=%x)\n", (int) tty);
+	printk(KERN_DEBUG "stli_flushbuffer(tty=%x)\n", (int) tty);
 #endif
 
 	if (tty == (struct tty_struct *) NULL)
@@ -2498,7 +2484,7 @@
 	/* long savestate, savetime; */
 
 #if DEBUG
-	printk("stli_breakctl(tty=%x,state=%d)\n", (int) tty, state);
+	printk(KERN_DEBUG "stli_breakctl(tty=%x,state=%d)\n", (int) tty, state);
 #endif
 
 	if (tty == (struct tty_struct *) NULL)
@@ -2537,7 +2523,7 @@
 	unsigned long	tend;
 
 #if DEBUG
-	printk("stli_waituntilsent(tty=%x,timeout=%x)\n", (int) tty, timeout);
+	printk(KERN_DEBUG "stli_waituntilsent(tty=%x,timeout=%x)\n", (int) tty, timeout);
 #endif
 
 	if (tty == (struct tty_struct *) NULL)
@@ -2568,7 +2554,7 @@
 	asyctrl_t	actrl;
 
 #if DEBUG
-	printk("stli_sendxchar(tty=%x,ch=%x)\n", (int) tty, ch);
+	printk(KERN_DEBUG "stli_sendxchar(tty=%x,ch=%x)\n", (int) tty, ch);
 #endif
 
 	if (tty == (struct tty_struct *) NULL)
@@ -2675,7 +2661,7 @@
 	char		*pos;
 
 #if DEBUG
-	printk("stli_readproc(page=%x,start=%x,off=%x,count=%d,eof=%x,"
+	printk(KERN_DEBUG "stli_readproc(page=%x,start=%x,off=%x,count=%d,eof=%x,"
 		"data=%x\n", (int) page, (int) start, (int) off, count,
 		(int) eof, (int) data);
 #endif
@@ -2751,7 +2737,7 @@
 	unsigned long		flags;
 
 #if DEBUG
-	printk("stli_sendcmd(brdp=%x,portp=%x,cmd=%x,arg=%x,size=%d,"
+	printk(KERN_DEBUG "stli_sendcmd(brdp=%x,portp=%x,cmd=%x,arg=%x,size=%d,"
 		"copyback=%d)\n", (int) brdp, (int) portp, (int) cmd,
 		(int) arg, size, copyback);
 #endif
@@ -2760,7 +2746,8 @@
 	cli();
 
 	if (test_bit(ST_CMDING, &portp->state)) {
-		printk("STALLION: command already busy, cmd=%x!\n", (int) cmd);
+		printk(KERN_ERR "STALLION: command already busy, cmd=%x!\n",
+				(int) cmd);
 		restore_flags(flags);
 		return;
 	}
@@ -2804,7 +2791,8 @@
 	unsigned int		len, stlen;
 
 #if DEBUG
-	printk("stli_read(brdp=%x,portp=%d)\n", (int) brdp, (int) portp);
+	printk(KERN_DEBUG "stli_read(brdp=%x,portp=%d)\n",
+			(int) brdp, (int) portp);
 #endif
 
 	if (test_bit(ST_RXSTOP, &portp->state))
@@ -2920,7 +2908,8 @@
 	int			rc, donerx;
 
 #if DEBUG
-	printk("stli_hostcmd(brdp=%x,channr=%d)\n", (int) brdp, channr);
+	printk(KERN_DEBUG "stli_hostcmd(brdp=%x,channr=%d)\n",
+			(int) brdp, channr);
 #endif
 
 	ap = (volatile cdkasy_t *) EBRDGETMEMPTR(brdp, portp->addr);
@@ -3177,7 +3166,7 @@
 static void stli_mkasyport(stliport_t *portp, asyport_t *pp, struct termios *tiosp)
 {
 #if DEBUG
-	printk("stli_mkasyport(portp=%x,pp=%x,tiosp=%d)\n",
+	printk(KERN_DEBUG "stli_mkasyport(portp=%x,pp=%x,tiosp=%d)\n",
 		(int) portp, (int) pp, (int) tiosp);
 #endif
 
@@ -3300,7 +3289,8 @@
 static void stli_mkasysigs(asysigs_t *sp, int dtr, int rts)
 {
 #if DEBUG
-	printk("stli_mkasysigs(sp=%x,dtr=%d,rts=%d)\n", (int) sp, dtr, rts);
+	printk(KERN_DEBUG "stli_mkasysigs(sp=%x,dtr=%d,rts=%d)\n",
+			(int) sp, dtr, rts);
 #endif
 
 	memset(sp, 0, sizeof(asysigs_t));
@@ -3326,7 +3316,7 @@
 	long	tiocm;
 
 #if DEBUG
-	printk("stli_mktiocm(sigvalue=%x)\n", (int) sigvalue);
+	printk(KERN_DEBUG "stli_mktiocm(sigvalue=%x)\n", (int) sigvalue);
 #endif
 
 	tiocm = 0;
@@ -3352,7 +3342,7 @@
 	int		i, panelnr, panelport;
 
 #if DEBUG
-	printk("stli_initports(brdp=%x)\n", (int) brdp);
+	printk(KERN_DEBUG "stli_initports(brdp=%x)\n", (int) brdp);
 #endif
 
 	for (i = 0, panelnr = 0, panelport = 0; (i < brdp->nrports); i++) {
@@ -3399,7 +3389,7 @@
 	unsigned long	memconf;
 
 #if DEBUG
-	printk("stli_ecpinit(brdp=%d)\n", (int) brdp);
+	printk(KERN_DEBUG "stli_ecpinit(brdp=%d)\n", (int) brdp);
 #endif
 
 	outb(ECP_ATSTOP, (brdp->iobase + ECP_ATCONFR));
@@ -3416,7 +3406,7 @@
 static void stli_ecpenable(stlibrd_t *brdp)
 {	
 #if DEBUG
-	printk("stli_ecpenable(brdp=%x)\n", (int) brdp);
+	printk(KERN_DEBUG "stli_ecpenable(brdp=%x)\n", (int) brdp);
 #endif
 	outb(ECP_ATENABLE, (brdp->iobase + ECP_ATCONFR));
 }
@@ -3426,7 +3416,7 @@
 static void stli_ecpdisable(stlibrd_t *brdp)
 {	
 #if DEBUG
-	printk("stli_ecpdisable(brdp=%x)\n", (int) brdp);
+	printk(KERN_DEBUG "stli_ecpdisable(brdp=%x)\n", (int) brdp);
 #endif
 	outb(ECP_ATDISABLE, (brdp->iobase + ECP_ATCONFR));
 }
@@ -3439,14 +3429,14 @@
 	unsigned char	val;
 
 #if DEBUG
-	printk("stli_ecpgetmemptr(brdp=%x,offset=%x)\n", (int) brdp,
+	printk(KERN_DEBUG "stli_ecpgetmemptr(brdp=%x,offset=%x)\n", (int) brdp,
 		(int) offset);
 #endif
 
 	if (offset > brdp->memsize) {
-		printk("STALLION: shared memory pointer=%x out of range at "
-			"line=%d(%d), brd=%d\n", (int) offset, line,
-			__LINE__, brdp->brdnr);
+		printk(KERN_ERR "STALLION: shared memory pointer=%x out of "
+				"range at line=%d(%d), brd=%d\n",
+			(int) offset, line, __LINE__, brdp->brdnr);
 		ptr = 0;
 		val = 0;
 	} else {
@@ -3462,7 +3452,7 @@
 static void stli_ecpreset(stlibrd_t *brdp)
 {	
 #if DEBUG
-	printk("stli_ecpreset(brdp=%x)\n", (int) brdp);
+	printk(KERN_DEBUG "stli_ecpreset(brdp=%x)\n", (int) brdp);
 #endif
 
 	outb(ECP_ATSTOP, (brdp->iobase + ECP_ATCONFR));
@@ -3476,7 +3466,7 @@
 static void stli_ecpintr(stlibrd_t *brdp)
 {	
 #if DEBUG
-	printk("stli_ecpintr(brdp=%x)\n", (int) brdp);
+	printk(KERN_DEBUG "stli_ecpintr(brdp=%x)\n", (int) brdp);
 #endif
 	outb(0x1, brdp->iobase);
 }
@@ -3492,7 +3482,7 @@
 	unsigned long	memconf;
 
 #if DEBUG
-	printk("stli_ecpeiinit(brdp=%x)\n", (int) brdp);
+	printk(KERN_DEBUG "stli_ecpeiinit(brdp=%x)\n", (int) brdp);
 #endif
 
 	outb(0x1, (brdp->iobase + ECP_EIBRDENAB));
@@ -3529,14 +3519,14 @@
 	unsigned char	val;
 
 #if DEBUG
-	printk("stli_ecpeigetmemptr(brdp=%x,offset=%x,line=%d)\n",
+	printk(KERN_DEBUG "stli_ecpeigetmemptr(brdp=%x,offset=%x,line=%d)\n",
 		(int) brdp, (int) offset, line);
 #endif
 
 	if (offset > brdp->memsize) {
-		printk("STALLION: shared memory pointer=%x out of range at "
-			"line=%d(%d), brd=%d\n", (int) offset, line,
-			__LINE__, brdp->brdnr);
+		printk(KERN_ERR "STALLION: shared memory pointer=%x out of "
+				"range at line=%d(%d), brd=%d\n",
+			(int) offset, line, __LINE__, brdp->brdnr);
 		ptr = 0;
 		val = 0;
 	} else {
@@ -3586,9 +3576,9 @@
 	unsigned char	val;
 
 	if (offset > brdp->memsize) {
-		printk("STALLION: shared memory pointer=%x out of range at "
-			"line=%d(%d), brd=%d\n", (int) offset, line,
-			__LINE__, brdp->brdnr);
+		printk(KERN_ERR "STALLION: shared memory pointer=%x out of "
+				"range at line=%d(%d), brd=%d\n",
+			(int) offset, line, __LINE__, brdp->brdnr);
 		ptr = 0;
 		val = 0;
 	} else {
@@ -3618,7 +3608,7 @@
 static void stli_ecppciinit(stlibrd_t *brdp)
 {
 #if DEBUG
-	printk("stli_ecppciinit(brdp=%x)\n", (int) brdp);
+	printk(KERN_DEBUG "stli_ecppciinit(brdp=%x)\n", (int) brdp);
 #endif
 
 	outb(ECP_PCISTOP, (brdp->iobase + ECP_PCICONFR));
@@ -3635,14 +3625,14 @@
 	unsigned char	val;
 
 #if DEBUG
-	printk("stli_ecppcigetmemptr(brdp=%x,offset=%x,line=%d)\n",
+	printk(KERN_DEBUG "stli_ecppcigetmemptr(brdp=%x,offset=%x,line=%d)\n",
 		(int) brdp, (int) offset, line);
 #endif
 
 	if (offset > brdp->memsize) {
-		printk("STALLION: shared memory pointer=%x out of range at "
-			"line=%d(%d), board=%d\n", (int) offset, line,
-			__LINE__, brdp->brdnr);
+		printk(KERN_ERR "STALLION: shared memory pointer=%x out of "
+				"range at line=%d(%d), board=%d\n",
+				(int) offset, line, __LINE__, brdp->brdnr);
 		ptr = 0;
 		val = 0;
 	} else {
@@ -3674,7 +3664,7 @@
 	unsigned long	memconf;
 
 #if DEBUG
-	printk("stli_onbinit(brdp=%d)\n", (int) brdp);
+	printk(KERN_DEBUG "stli_onbinit(brdp=%d)\n", (int) brdp);
 #endif
 
 	outb(ONB_ATSTOP, (brdp->iobase + ONB_ATCONFR));
@@ -3693,7 +3683,7 @@
 static void stli_onbenable(stlibrd_t *brdp)
 {	
 #if DEBUG
-	printk("stli_onbenable(brdp=%x)\n", (int) brdp);
+	printk(KERN_DEBUG "stli_onbenable(brdp=%x)\n", (int) brdp);
 #endif
 	outb((brdp->enabval | ONB_ATENABLE), (brdp->iobase + ONB_ATCONFR));
 }
@@ -3703,7 +3693,7 @@
 static void stli_onbdisable(stlibrd_t *brdp)
 {	
 #if DEBUG
-	printk("stli_onbdisable(brdp=%x)\n", (int) brdp);
+	printk(KERN_DEBUG "stli_onbdisable(brdp=%x)\n", (int) brdp);
 #endif
 	outb((brdp->enabval | ONB_ATDISABLE), (brdp->iobase + ONB_ATCONFR));
 }
@@ -3715,14 +3705,14 @@
 	void	*ptr;
 
 #if DEBUG
-	printk("stli_onbgetmemptr(brdp=%x,offset=%x)\n", (int) brdp,
+	printk(KERN_DEBUG "stli_onbgetmemptr(brdp=%x,offset=%x)\n", (int) brdp,
 		(int) offset);
 #endif
 
 	if (offset > brdp->memsize) {
-		printk("STALLION: shared memory pointer=%x out of range at "
-			"line=%d(%d), brd=%d\n", (int) offset, line,
-			__LINE__, brdp->brdnr);
+		printk(KERN_ERR "STALLION: shared memory pointer=%x out of "
+				"range at line=%d(%d), brd=%d\n",
+				(int) offset, line, __LINE__, brdp->brdnr);
 		ptr = 0;
 	} else {
 		ptr = brdp->membase + (offset % ONB_ATPAGESIZE);
@@ -3736,7 +3726,7 @@
 {	
 
 #if DEBUG
-	printk("stli_onbreset(brdp=%x)\n", (int) brdp);
+	printk(KERN_DEBUG "stli_onbreset(brdp=%x)\n", (int) brdp);
 #endif
 
 	outb(ONB_ATSTOP, (brdp->iobase + ONB_ATCONFR));
@@ -3756,7 +3746,7 @@
 	unsigned long	memconf;
 
 #if DEBUG
-	printk("stli_onbeinit(brdp=%d)\n", (int) brdp);
+	printk(KERN_DEBUG "stli_onbeinit(brdp=%d)\n", (int) brdp);
 #endif
 
 	outb(0x1, (brdp->iobase + ONB_EIBRDENAB));
@@ -3778,7 +3768,7 @@
 static void stli_onbeenable(stlibrd_t *brdp)
 {	
 #if DEBUG
-	printk("stli_onbeenable(brdp=%x)\n", (int) brdp);
+	printk(KERN_DEBUG "stli_onbeenable(brdp=%x)\n", (int) brdp);
 #endif
 	outb(ONB_EIENABLE, (brdp->iobase + ONB_EICONFR));
 }
@@ -3788,7 +3778,7 @@
 static void stli_onbedisable(stlibrd_t *brdp)
 {	
 #if DEBUG
-	printk("stli_onbedisable(brdp=%x)\n", (int) brdp);
+	printk(KERN_DEBUG "stli_onbedisable(brdp=%x)\n", (int) brdp);
 #endif
 	outb(ONB_EIDISABLE, (brdp->iobase + ONB_EICONFR));
 }
@@ -3801,14 +3791,14 @@
 	unsigned char	val;
 
 #if DEBUG
-	printk("stli_onbegetmemptr(brdp=%x,offset=%x,line=%d)\n",
+	printk(KERN_DEBUG "stli_onbegetmemptr(brdp=%x,offset=%x,line=%d)\n",
 		(int) brdp, (int) offset, line);
 #endif
 
 	if (offset > brdp->memsize) {
-		printk("STALLION: shared memory pointer=%x out of range at "
-			"line=%d(%d), brd=%d\n", (int) offset, line,
-			__LINE__, brdp->brdnr);
+		printk(KERN_ERR "STALLION: shared memory pointer=%x out of "
+				"range at line=%d(%d), brd=%d\n",
+			(int) offset, line, __LINE__, brdp->brdnr);
 		ptr = 0;
 		val = 0;
 	} else {
@@ -3828,7 +3818,7 @@
 {	
 
 #if DEBUG
-	printk("stli_onbereset(brdp=%x)\n", (int) brdp);
+	printk(KERN_ERR "stli_onbereset(brdp=%x)\n", (int) brdp);
 #endif
 
 	outb(ONB_EISTOP, (brdp->iobase + ONB_EICONFR));
@@ -3847,7 +3837,7 @@
 {
 
 #if DEBUG
-	printk("stli_bbyinit(brdp=%d)\n", (int) brdp);
+	printk(KERN_ERR "stli_bbyinit(brdp=%d)\n", (int) brdp);
 #endif
 
 	outb(BBY_ATSTOP, (brdp->iobase + BBY_ATCONFR));
@@ -3866,14 +3856,14 @@
 	unsigned char	val;
 
 #if DEBUG
-	printk("stli_bbygetmemptr(brdp=%x,offset=%x)\n", (int) brdp,
+	printk(KERN_ERR "stli_bbygetmemptr(brdp=%x,offset=%x)\n", (int) brdp,
 		(int) offset);
 #endif
 
 	if (offset > brdp->memsize) {
-		printk("STALLION: shared memory pointer=%x out of range at "
-			"line=%d(%d), brd=%d\n", (int) offset, line,
-			__LINE__, brdp->brdnr);
+		printk(KERN_ERR "STALLION: shared memory pointer=%x out of "
+				"range at line=%d(%d), brd=%d\n",
+				(int) offset, line, __LINE__, brdp->brdnr);
 		ptr = 0;
 		val = 0;
 	} else {
@@ -3890,7 +3880,7 @@
 {	
 
 #if DEBUG
-	printk("stli_bbyreset(brdp=%x)\n", (int) brdp);
+	printk(KERN_DEBUG "stli_bbyreset(brdp=%x)\n", (int) brdp);
 #endif
 
 	outb(BBY_ATSTOP, (brdp->iobase + BBY_ATCONFR));
@@ -3909,7 +3899,7 @@
 {
 
 #if DEBUG
-	printk("stli_stalinit(brdp=%d)\n", (int) brdp);
+	printk(KERN_DEBUG "stli_stalinit(brdp=%d)\n", (int) brdp);
 #endif
 
 	outb(0x1, brdp->iobase);
@@ -3923,14 +3913,14 @@
 	void	*ptr;
 
 #if DEBUG
-	printk("stli_stalgetmemptr(brdp=%x,offset=%x)\n", (int) brdp,
+	printk(KERN_DEBUG "stli_stalgetmemptr(brdp=%x,offset=%x)\n", (int) brdp,
 		(int) offset);
 #endif
 
 	if (offset > brdp->memsize) {
-		printk("STALLION: shared memory pointer=%x out of range at "
-			"line=%d(%d), brd=%d\n", (int) offset, line,
-			__LINE__, brdp->brdnr);
+		printk(KERN_ERR "STALLION: shared memory pointer=%x out of "
+				"range at line=%d(%d), brd=%d\n",
+				(int) offset, line, __LINE__, brdp->brdnr);
 		ptr = 0;
 	} else {
 		ptr = brdp->membase + (offset % STAL_PAGESIZE);
@@ -3945,7 +3935,7 @@
 	volatile unsigned long	*vecp;
 
 #if DEBUG
-	printk("stli_stalreset(brdp=%x)\n", (int) brdp);
+	printk(KERN_DEBUG "stli_stalreset(brdp=%x)\n", (int) brdp);
 #endif
 
 	vecp = (volatile unsigned long *) (brdp->membase + 0x30);
@@ -3970,7 +3960,7 @@
 	int		panelnr, nrports;
 
 #if DEBUG
-	printk("stli_initecp(brdp=%x)\n", (int) brdp);
+	printk(KERN_DEBUG "stli_initecp(brdp=%x)\n", (int) brdp);
 #endif
 
 /*
@@ -3981,8 +3971,9 @@
 
 	brdp->iosize = ECP_IOSIZE;
 	if (check_region(brdp->iobase, brdp->iosize))
-		printk("STALLION: Warning, board %d I/O address %x conflicts "
-			"with another device\n", brdp->brdnr, brdp->iobase);
+		printk(KERN_ERR "STALLION: Warning, board %d I/O address %x "
+				"conflicts with another device\n",
+				brdp->brdnr, brdp->iobase);
 
 /*
  *	Based on the specific board type setup the common vars to access
@@ -4123,7 +4114,7 @@
 	int		i;
 
 #if DEBUG
-	printk("stli_initonb(brdp=%x)\n", (int) brdp);
+	printk(KERN_DEBUG "stli_initonb(brdp=%x)\n", (int) brdp);
 #endif
 
 /*
@@ -4134,8 +4125,9 @@
 
 	brdp->iosize = ONB_IOSIZE;
 	if (check_region(brdp->iobase, brdp->iosize))
-		printk("STALLION: Warning, board %d I/O address %x conflicts "
-			"with another device\n", brdp->brdnr, brdp->iobase);
+		printk(KERN_ERR "STALLION: Warning, board %d I/O address %x "
+				"conflicts with another device\n",
+				brdp->brdnr, brdp->iobase);
 
 /*
  *	Based on the specific board type setup the common vars to access
@@ -4284,7 +4276,7 @@
 	int			portnr, nrdevs, i, rc;
 
 #if DEBUG
-	printk("stli_startbrd(brdp=%x)\n", (int) brdp);
+	printk(KERN_DEBUG "stli_startbrd(brdp=%x)\n", (int) brdp);
 #endif
 
 	rc = 0;
@@ -4304,8 +4296,8 @@
 #endif
 
 	if (nrdevs < (brdp->nrports + 1)) {
-		printk("STALLION: slave failed to allocate memory for all "
-			"devices, devices=%d\n", nrdevs);
+		printk(KERN_ERR "STALLION: slave failed to allocate memory for "
+				"all devices, devices=%d\n", nrdevs);
 		brdp->nrports = nrdevs - 1;
 	}
 	brdp->nrdevs = nrdevs;
@@ -4314,13 +4306,13 @@
 	brdp->bitsize = (nrdevs + 7) / 8;
 	memp = (volatile cdkmem_t *) hdrp->memp;
 	if (((unsigned long) memp) > brdp->memsize) {
-		printk("STALLION: corrupted shared memory region?\n");
+		printk(KERN_ERR "STALLION: corrupted shared memory region?\n");
 		rc = -EIO;
 		goto stli_donestartup;
 	}
 	memp = (volatile cdkmem_t *) EBRDGETMEMPTR(brdp, (unsigned long) memp);
 	if (memp->dtype != TYP_ASYNCTRL) {
-		printk("STALLION: no slave control device found\n");
+		printk(KERN_ERR "STALLION: no slave control device found\n");
 		goto stli_donestartup;
 	}
 	memp++;
@@ -4390,7 +4382,7 @@
 static int __init stli_brdinit(stlibrd_t *brdp)
 {
 #if DEBUG
-	printk("stli_brdinit(brdp=%x)\n", (int) brdp);
+	printk(KERN_DEBUG "stli_brdinit(brdp=%x)\n", (int) brdp);
 #endif
 
 	stli_brds[brdp->brdnr] = brdp;
@@ -4418,24 +4410,25 @@
 	case BRD_ECH:
 	case BRD_ECHMC:
 	case BRD_ECHPCI:
-		printk("STALLION: %s board type not supported in this driver\n",
-			stli_brdnames[brdp->brdtype]);
+		printk(KERN_ERR "STALLION: %s board type not supported in "
+				"this driver\n", stli_brdnames[brdp->brdtype]);
 		return(ENODEV);
 	default:
-		printk("STALLION: board=%d is unknown board type=%d\n",
-			brdp->brdnr, brdp->brdtype);
+		printk(KERN_ERR "STALLION: board=%d is unknown board "
+				"type=%d\n", brdp->brdnr, brdp->brdtype);
 		return(ENODEV);
 	}
 
 	if ((brdp->state & BST_FOUND) == 0) {
-		printk("STALLION: %s board not found, board=%d io=%x mem=%x\n",
+		printk(KERN_ERR "STALLION: %s board not found, board=%d "
+				"io=%x mem=%x\n",
 			stli_brdnames[brdp->brdtype], brdp->brdnr,
 			brdp->iobase, (int) brdp->memaddr);
 		return(ENODEV);
 	}
 
 	stli_initports(brdp);
-	printk("STALLION: %s found, board=%d io=%x mem=%x "
+	printk(KERN_INFO "STALLION: %s found, board=%d io=%x mem=%x "
 		"nrpanels=%d nrports=%d\n", stli_brdnames[brdp->brdtype],
 		brdp->brdnr, brdp->iobase, (int) brdp->memaddr,
 		brdp->nrpanels, brdp->nrports);
@@ -4456,7 +4449,7 @@
 	int		i, foundit;
 
 #if DEBUG
-	printk("stli_eisamemprobe(brdp=%x)\n", (int) brdp);
+	printk(KERN_DEBUG "stli_eisamemprobe(brdp=%x)\n", (int) brdp);
 #endif
 
 /*
@@ -4533,9 +4526,9 @@
 	if (! foundit) {
 		brdp->memaddr = 0;
 		brdp->membase = 0;
-		printk("STALLION: failed to probe shared memory region for "
-			"%s in EISA slot=%d\n", stli_brdnames[brdp->brdtype],
-			(brdp->iobase >> 12));
+		printk(KERN_ERR "STALLION: failed to probe shared memory "
+				"region for %s in EISA slot=%d\n",
+			stli_brdnames[brdp->brdtype], (brdp->iobase >> 12));
 		return(-ENODEV);
 	}
 	return(0);
@@ -4560,7 +4553,7 @@
 	int		i;
 
 #if DEBUG
-	printk("stli_findeisabrds()\n");
+	printk(KERN_DEBUG "stli_findeisabrds()\n");
 #endif
 
 /*
@@ -4656,8 +4649,8 @@
 	stlibrd_t	*brdp;
 
 #if DEBUG
-	printk("stli_initpcibrd(brdtype=%d,busnr=%x,devnr=%x)\n", brdtype,
-		dev->bus->number, dev->devfn);
+	printk(KERN_DEBUG "stli_initpcibrd(brdtype=%d,busnr=%x,devnr=%x)\n",
+		brdtype, dev->bus->number, dev->devfn);
 #endif
 
 	if (pci_enable_device(devp))
@@ -4665,14 +4658,14 @@
 	if ((brdp = stli_allocbrd()) == (stlibrd_t *) NULL)
 		return(-ENOMEM);
 	if ((brdp->brdnr = stli_getbrdnr()) < 0) {
-		printk("STALLION: too many boards found, "
+		printk(KERN_INFO "STALLION: too many boards found, "
 			"maximum supported %d\n", STL_MAXBRDS);
 		return(0);
 	}
 	brdp->brdtype = brdtype;
 
 #if DEBUG
-	printk("%s(%d): BAR[]=%lx,%lx,%lx,%lx\n", __FILE__, __LINE__,
+	printk(KERN_DEBUG "%s(%d): BAR[]=%lx,%lx,%lx,%lx\n", __FILE__, __LINE__,
 		pci_resource_start(devp, 0),
 		pci_resource_start(devp, 1),
 		pci_resource_start(devp, 2),
@@ -4732,8 +4725,8 @@
 
 	brdp = (stlibrd_t *) stli_memalloc(sizeof(stlibrd_t));
 	if (brdp == (stlibrd_t *) NULL) {
-		printk("STALLION: failed to allocate memory (size=%d)\n",
-			sizeof(stlibrd_t));
+		printk(KERN_ERR "STALLION: failed to allocate memory "
+				"(size=%d)\n", sizeof(stlibrd_t));
 		return((stlibrd_t *) NULL);
 	}
 
@@ -4756,12 +4749,12 @@
 	int		i, j;
 
 #if DEBUG
-	printk("stli_initbrds()\n");
+	printk(KERN_DEBUG "stli_initbrds()\n");
 #endif
 
 	if (stli_nrbrds > STL_MAXBRDS) {
-		printk("STALLION: too many boards in configuration table, "
-			"truncating to %d\n", STL_MAXBRDS);
+		printk(KERN_INFO "STALLION: too many boards in configuration "
+			"table, truncating to %d\n", STL_MAXBRDS);
 		stli_nrbrds = STL_MAXBRDS;
 	}
 
@@ -4854,8 +4847,8 @@
 	int		brdnr, size, n;
 
 #if DEBUG
-	printk("stli_memread(fp=%x,buf=%x,count=%x,offp=%x)\n", (int) fp,
-		(int) buf, count, (int) offp);
+	printk(KERN_DEBUG "stli_memread(fp=%x,buf=%x,count=%x,offp=%x)\n",
+			(int) fp, (int) buf, count, (int) offp);
 #endif
 
 	brdnr = MINOR(fp->f_dentry->d_inode->i_rdev);
@@ -4905,8 +4898,8 @@
 	int		brdnr, size, n;
 
 #if DEBUG
-	printk("stli_memwrite(fp=%x,buf=%x,count=%x,offp=%x)\n", (int) fp,
-		(int) buf, count, (int) offp);
+	printk(KERN_DEBUG "stli_memwrite(fp=%x,buf=%x,count=%x,offp=%x)\n",
+			(int) fp, (int) buf, count, (int) offp);
 #endif
 
 	brdnr = MINOR(fp->f_dentry->d_inode->i_rdev);
@@ -4951,7 +4944,8 @@
 	stlibrd_t	*brdp;
 	int		i;
 
-	copy_from_user(&stli_brdstats, bp, sizeof(combrd_t));
+	if (copy_from_user(&stli_brdstats, bp, sizeof(combrd_t)))
+		return -EFAULT;
 	if (stli_brdstats.brd >= STL_MAXBRDS)
 		return(-ENODEV);
 	brdp = stli_brds[stli_brdstats.brd];
@@ -4973,7 +4967,8 @@
 		stli_brdstats.panels[i].nrports = brdp->panels[i];
 	}
 
-	copy_to_user(bp, &stli_brdstats, sizeof(combrd_t));
+	if (copy_to_user(bp, &stli_brdstats, sizeof(combrd_t)))
+		return -EFAULT;
 	return(0);
 }
 
@@ -5089,7 +5084,8 @@
 	int		rc;
 
 	if (portp == (stliport_t *) NULL) {
-		copy_from_user(&stli_comstats, cp, sizeof(comstats_t));
+		if (copy_from_user(&stli_comstats, cp, sizeof(comstats_t)))
+			return -EFAULT;
 		portp = stli_getport(stli_comstats.brd, stli_comstats.panel,
 			stli_comstats.port);
 		if (portp == (stliport_t *) NULL)
@@ -5103,8 +5099,8 @@
 	if ((rc = stli_portcmdstats(portp)) < 0)
 		return(rc);
 
-	copy_to_user(cp, &stli_comstats, sizeof(comstats_t));
-	return(0);
+	return copy_to_user(cp, &stli_comstats, sizeof(comstats_t)) ?
+			-EFAULT : 0;
 }
 
 /*****************************************************************************/
@@ -5119,7 +5115,8 @@
 	int		rc;
 
 	if (portp == (stliport_t *) NULL) {
-		copy_from_user(&stli_comstats, cp, sizeof(comstats_t));
+		if (copy_from_user(&stli_comstats, cp, sizeof(comstats_t)))
+			return -EFAULT;
 		portp = stli_getport(stli_comstats.brd, stli_comstats.panel,
 			stli_comstats.port);
 		if (portp == (stliport_t *) NULL)
@@ -5140,7 +5137,8 @@
 	stli_comstats.panel = portp->panelnr;
 	stli_comstats.port = portp->portnr;
 
-	copy_to_user(cp, &stli_comstats, sizeof(comstats_t));
+	if (copy_to_user(cp, &stli_comstats, sizeof(comstats_t)))
+		return -EFAULT;
 	return(0);
 }
 
@@ -5154,12 +5152,14 @@
 {
 	stliport_t	*portp;
 
-	copy_from_user(&stli_dummyport, (void *) arg, sizeof(stliport_t));
+	if (copy_from_user(&stli_dummyport, (void *)arg, sizeof(stliport_t)))
+		return -EFAULT;
 	portp = stli_getport(stli_dummyport.brdnr, stli_dummyport.panelnr,
 		 stli_dummyport.portnr);
 	if (portp == (stliport_t *) NULL)
 		return(-ENODEV);
-	copy_to_user((void *) arg, portp, sizeof(stliport_t));
+	if (copy_to_user((void *) arg, portp, sizeof(stliport_t)))
+		return -EFAULT;
 	return(0);
 }
 
@@ -5173,13 +5173,15 @@
 {
 	stlibrd_t	*brdp;
 
-	copy_from_user(&stli_dummybrd, (void *) arg, sizeof(stlibrd_t));
+	if (copy_from_user(&stli_dummybrd, (void *)arg, sizeof(stlibrd_t)))
+		return -EFAULT;
 	if ((stli_dummybrd.brdnr < 0) || (stli_dummybrd.brdnr >= STL_MAXBRDS))
 		return(-ENODEV);
 	brdp = stli_brds[stli_dummybrd.brdnr];
 	if (brdp == (stlibrd_t *) NULL)
 		return(-ENODEV);
-	copy_to_user((void *) arg, brdp, sizeof(stlibrd_t));
+	if (copy_to_user((void *) arg, brdp, sizeof(stlibrd_t)))
+		return -EFAULT;
 	return(0);
 }
 
@@ -5197,8 +5199,8 @@
 	int		brdnr, rc, done;
 
 #if DEBUG
-	printk("stli_memioctl(ip=%x,fp=%x,cmd=%x,arg=%x)\n", (int) ip,
-		(int) fp, cmd, (int) arg);
+	printk(KERN_DEBUG "stli_memioctl(ip=%x,fp=%x,cmd=%x,arg=%x)\n",
+			(int) ip, (int) fp, cmd, (int) arg);
 #endif
 
 /*
@@ -5209,39 +5211,25 @@
 
 	switch (cmd) {
 	case COM_GETPORTSTATS:
-		if ((rc = verify_area(VERIFY_WRITE, (void *) arg,
-		    sizeof(comstats_t))) == 0)
-			rc = stli_getportstats((stliport_t *) NULL,
-				(comstats_t *) arg);
+		rc = stli_getportstats((stliport_t *)NULL, (comstats_t *)arg);
 		done++;
 		break;
 	case COM_CLRPORTSTATS:
-		if ((rc = verify_area(VERIFY_WRITE, (void *) arg,
-		    sizeof(comstats_t))) == 0)
-			rc = stli_clrportstats((stliport_t *) NULL,
-				(comstats_t *) arg);
+		rc = stli_clrportstats((stliport_t *)NULL, (comstats_t *)arg);
 		done++;
 		break;
 	case COM_GETBRDSTATS:
-		if ((rc = verify_area(VERIFY_WRITE, (void *) arg,
-		    sizeof(combrd_t))) == 0)
-			rc = stli_getbrdstats((combrd_t *) arg);
+		rc = stli_getbrdstats((combrd_t *) arg);
 		done++;
 		break;
 	case COM_READPORT:
-		if ((rc = verify_area(VERIFY_WRITE, (void *) arg,
-		    sizeof(stliport_t))) == 0)
-			rc = stli_getportstruct(arg);
+		rc = stli_getportstruct(arg);
 		done++;
 		break;
 	case COM_READBOARD:
-		if ((rc = verify_area(VERIFY_WRITE, (void *) arg,
-		    sizeof(stlibrd_t))) == 0)
-			rc = stli_getbrdstruct(arg);
+		rc = stli_getbrdstruct(arg);
 		done++;
 		break;
-	default:
-		break;
 	}
 
 	if (done)
@@ -5299,19 +5287,20 @@
  */
 	stli_tmpwritebuf = (char *) stli_memalloc(STLI_TXBUFSIZE);
 	if (stli_tmpwritebuf == (char *) NULL)
-		printk("STALLION: failed to allocate memory (size=%d)\n",
-			STLI_TXBUFSIZE);
-	stli_txcookbuf = (char *) stli_memalloc(STLI_TXBUFSIZE);
+		printk(KERN_ERR "STALLION: failed to allocate memory "
+				"(size=%d)\n", STLI_TXBUFSIZE);
+	stli_txcookbuf = stli_memalloc(STLI_TXBUFSIZE);
 	if (stli_txcookbuf == (char *) NULL)
-		printk("STALLION: failed to allocate memory (size=%d)\n",
-			STLI_TXBUFSIZE);
+		printk(KERN_ERR "STALLION: failed to allocate memory "
+				"(size=%d)\n", STLI_TXBUFSIZE);
 
 /*
  *	Set up a character driver for the shared memory region. We need this
  *	to down load the slave code image. Also it is a useful debugging tool.
  */
 	if (devfs_register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stli_fsiomem))
-		printk("STALLION: failed to register serial memory device\n");
+		printk(KERN_ERR "STALLION: failed to register serial memory "
+				"device\n");
 
 	devfs_handle = devfs_mk_dir (NULL, "staliomem", NULL);
 	devfs_register_series (devfs_handle, "%u", 4, DEVFS_FL_DEFAULT,
@@ -5366,9 +5355,9 @@
 	stli_callout.read_proc = 0;
 
 	if (tty_register_driver(&stli_serial))
-		printk("STALLION: failed to register serial driver\n");
+		printk(KERN_ERR "STALLION: failed to register serial driver\n");
 	if (tty_register_driver(&stli_callout))
-		printk("STALLION: failed to register callout driver\n");
+		printk(KERN_ERR "STALLION: failed to register callout driver\n");
 
 	return(0);
 }
diff -urN linux-2.4.7-pre6/drivers/char/tty_io.c linux/drivers/char/tty_io.c
--- linux-2.4.7-pre6/drivers/char/tty_io.c	Mon Jul  2 14:16:31 2001
+++ linux/drivers/char/tty_io.c	Mon Dec  3 22:55:49 2001
@@ -211,9 +211,9 @@
 			      const char *routine)
 {
 #ifdef TTY_PARANOIA_CHECK
-	static const char *badmagic =
+	static const char badmagic[] = KERN_WARNING
 		"Warning: bad magic number for tty struct (%s) in %s\n";
-	static const char *badtty =
+	static const char badtty[] = KERN_WARNING
 		"Warning: null TTY for (%s) in %s\n";
 
 	if (!tty) {
@@ -245,7 +245,8 @@
 	    tty->link && tty->link->count)
 		count++;
 	if (tty->count != count) {
-		printk("Warning: dev (%s) tty->count(%d) != #fd's(%d) in %s\n",
+		printk(KERN_WARNING "Warning: dev (%s) tty->count(%d) "
+				    "!= #fd's(%d) in %s\n",
 		       kdevname(tty->device), tty->count, count, routine);
 		return count;
        }	
@@ -356,7 +357,7 @@
 	if (current->tty != tty)
 		return 0;
 	if (tty->pgrp <= 0) {
-		printk("tty_check_change: tty->pgrp <= 0!\n");
+		printk(KERN_WARNING "tty_check_change: tty->pgrp <= 0!\n");
 		return 0;
 	}
 	if (current->pgrp == tty->pgrp)
@@ -494,8 +495,8 @@
 		if (tty->ldisc.open) {
 			int i = (tty->ldisc.open)(tty);
 			if (i < 0)
-				printk("do_tty_hangup: N_TTY open: error %d\n",
-				       -i);
+				printk(KERN_ERR "do_tty_hangup: N_TTY open: "
+						"error %d\n", -i);
 		}
 	}
 	
@@ -537,7 +538,7 @@
 #ifdef TTY_DEBUG_HANGUP
 	char	buf[64];
 	
-	printk("%s hangup...\n", tty_name(tty, buf));
+	printk(KERN_DEBUG "%s hangup...\n", tty_name(tty, buf));
 #endif
 	schedule_task(&tty->tq_hangup);
 }
@@ -547,7 +548,7 @@
 #ifdef TTY_DEBUG_HANGUP
 	char	buf[64];
 
-	printk("%s vhangup...\n", tty_name(tty, buf));
+	printk(KERN_DEBUG "%s vhangup...\n", tty_name(tty, buf));
 #endif
 	do_tty_hangup((void *) tty);
 }
@@ -999,7 +1000,8 @@
 
 	/* call the tty release_mem routine to clean out this slot */
 release_mem_out:
-	printk("init_dev: ldisc open failed, clearing slot %d\n", idx);
+	printk(KERN_INFO "init_dev: ldisc open failed, "
+			 "clearing slot %d\n", idx);
 	release_mem(tty, idx);
 	goto end_init;
 }
@@ -1022,6 +1024,7 @@
 		}
 		o_tty->magic = 0;
 		(*o_tty->driver.refcount)--;
+		list_del(&o_tty->tty_files);
 		free_tty_struct(o_tty);
 	}
 
@@ -1033,6 +1036,7 @@
 	}
 	tty->magic = 0;
 	(*tty->driver.refcount)--;
+	list_del(&tty->tty_files);
 	free_tty_struct(tty);
 }
 
@@ -1066,23 +1070,23 @@
 
 #ifdef TTY_PARANOIA_CHECK
 	if (idx < 0 || idx >= tty->driver.num) {
-		printk("release_dev: bad idx when trying to free (%s)\n",
-		       kdevname(tty->device));
+		printk(KERN_DEBUG "release_dev: bad idx when trying to "
+				  "free (%s)\n", kdevname(tty->device));
 		return;
 	}
 	if (tty != tty->driver.table[idx]) {
-		printk("release_dev: driver.table[%d] not tty for (%s)\n",
-		       idx, kdevname(tty->device));
+		printk(KERN_DEBUG "release_dev: driver.table[%d] not tty "
+				  "for (%s)\n", idx, kdevname(tty->device));
 		return;
 	}
 	if (tty->termios != tty->driver.termios[idx]) {
-		printk("release_dev: driver.termios[%d] not termios "
+		printk(KERN_DEBUG "release_dev: driver.termios[%d] not termios "
 		       "for (%s)\n",
 		       idx, kdevname(tty->device));
 		return;
 	}
 	if (tty->termios_locked != tty->driver.termios_locked[idx]) {
-		printk("release_dev: driver.termios_locked[%d] not "
+		printk(KERN_DEBUG "release_dev: driver.termios_locked[%d] not "
 		       "termios_locked for (%s)\n",
 		       idx, kdevname(tty->device));
 		return;
@@ -1090,33 +1094,33 @@
 #endif
 
 #ifdef TTY_DEBUG_HANGUP
-	printk("release_dev of %s (tty count=%d)...", tty_name(tty, buf),
-	       tty->count);
+	printk(KERN_DEBUG "release_dev of %s (tty count=%d)...",
+	       tty_name(tty, buf), tty->count);
 #endif
 
 #ifdef TTY_PARANOIA_CHECK
 	if (tty->driver.other) {
 		if (o_tty != tty->driver.other->table[idx]) {
-			printk("release_dev: other->table[%d] not o_tty for ("
-			       "%s)\n",
+			printk(KERN_DEBUG "release_dev: other->table[%d] "
+					  "not o_tty for (%s)\n",
 			       idx, kdevname(tty->device));
 			return;
 		}
 		if (o_tty->termios != tty->driver.other->termios[idx]) {
-			printk("release_dev: other->termios[%d] not o_termios "
-			       "for (%s)\n",
+			printk(KERN_DEBUG "release_dev: other->termios[%d] "
+					  "not o_termios for (%s)\n",
 			       idx, kdevname(tty->device));
 			return;
 		}
 		if (o_tty->termios_locked != 
 		      tty->driver.other->termios_locked[idx]) {
-			printk("release_dev: other->termios_locked[%d] not "
-			       "o_termios_locked for (%s)\n",
+			printk(KERN_DEBUG "release_dev: other->termios_locked["
+					  "%d] not o_termios_locked for (%s)\n",
 			       idx, kdevname(tty->device));
 			return;
 		}
 		if (o_tty->link != tty) {
-			printk("release_dev: bad pty pointers\n");
+			printk(KERN_DEBUG "release_dev: bad pty pointers\n");
 			return;
 		}
 	}
@@ -1171,8 +1175,8 @@
 		if (!do_sleep)
 			break;
 
-		printk("release_dev: %s: read/write wait queue active!\n",
-		       tty_name(tty, buf));
+		printk(KERN_WARNING "release_dev: %s: read/write wait queue "
+				    "active!\n", tty_name(tty, buf));
 		schedule();
 	}	
 
@@ -1183,13 +1187,14 @@
 	 */
 	if (pty_master) {
 		if (--o_tty->count < 0) {
-			printk("release_dev: bad pty slave count (%d) for %s\n",
+			printk(KERN_WARNING "release_dev: bad pty slave count "
+					    "(%d) for %s\n",
 			       o_tty->count, tty_name(o_tty, buf));
 			o_tty->count = 0;
 		}
 	}
 	if (--tty->count < 0) {
-		printk("release_dev: bad tty->count (%d) for %s\n",
+		printk(KERN_WARNING "release_dev: bad tty->count (%d) for %s\n",
 		       tty->count, tty_name(tty, buf));
 		tty->count = 0;
 	}
@@ -1198,7 +1203,7 @@
 	 * We've decremented tty->count, so we should zero out
 	 * filp->private_data, to break the link between the tty and
 	 * the file descriptor.  Otherwise if filp_close() blocks before
-	 * the the file descriptor is removed from the inuse_filp
+	 * the file descriptor is removed from the inuse_filp
 	 * list, check_tty_count() could observe a discrepancy and
 	 * printk a warning message to the user.
 	 */
@@ -1240,7 +1245,7 @@
 		return;
 	
 #ifdef TTY_DEBUG_HANGUP
-	printk("freeing tty structure...");
+	printk(KERN_DEBUG "freeing tty structure...");
 #endif
 
 	/*
@@ -1368,7 +1373,7 @@
 	    tty->driver.subtype == PTY_TYPE_MASTER)
 		noctty = 1;
 #ifdef TTY_DEBUG_HANGUP
-	printk("opening %s...", tty_name(tty, buf));
+	printk(KERN_DEBUG "opening %s...", tty_name(tty, buf));
 #endif
 	if (tty->driver.open)
 		retval = tty->driver.open(tty, filp);
@@ -1381,7 +1386,7 @@
 
 	if (retval) {
 #ifdef TTY_DEBUG_HANGUP
-		printk("error %d in opening %s...", retval,
+		printk(KERN_DEBUG "error %d in opening %s...", retval,
 		       tty_name(tty, buf));
 #endif
 
@@ -1605,7 +1610,8 @@
 	    (current->tty != real_tty) ||
 	    (real_tty->session != current->session))
 		return -ENOTTY;
-	get_user(pgrp, (pid_t *) arg);
+	if (get_user(pgrp, (pid_t *) arg))
+		return -EFAULT;
 	if (pgrp < 0)
 		return -EINVAL;
 	if (session_of_pgrp(pgrp) != current->session)
@@ -1636,11 +1642,10 @@
 
 static int tiocsetd(struct tty_struct *tty, int *arg)
 {
-	int retval, ldisc;
+	int ldisc;
 
-	retval = get_user(ldisc, arg);
-	if (retval)
-		return retval;
+	if (get_user(ldisc, arg))
+		return -EFAULT;
 	return tty_set_ldisc(tty, ldisc);
 }
 
@@ -1953,7 +1958,8 @@
 	}
 	if (i==15 && tty->alt_speed) {
 		if (!tty->warned) {
-			printk("Use of setserial/setrocket to set SPD_* flags is deprecated\n");
+			printk(KERN_WARNING "Use of setserial/setrocket to "
+					    "set SPD_* flags is deprecated\n");
 			tty->warned = 1;
 		}
 		return(tty->alt_speed);
@@ -2360,5 +2366,8 @@
 #endif
 #ifdef CONFIG_HWC
 	hwc_tty_init();
+#endif
+#ifdef CONFIG_A2232
+	a2232board_init();
 #endif
 }
diff -urN linux-2.4.7-pre6/drivers/i2c/i2c-dev.c linux/drivers/i2c/i2c-dev.c
--- linux-2.4.7-pre6/drivers/i2c/i2c-dev.c	Fri Feb  9 11:30:23 2001
+++ linux/drivers/i2c/i2c-dev.c	Mon Dec  3 22:55:49 2001
@@ -241,6 +241,9 @@
 				   sizeof(rdwr_arg)))
 			return -EFAULT;
 
+		if(rdwr_arg.nmsgs > 2048)
+			return -EINVAL;
+			
 		rdwr_pa = (struct i2c_msg *)
 			kmalloc(rdwr_arg.nmsgs * sizeof(struct i2c_msg), 
 			GFP_KERNEL);
diff -urN linux-2.4.7-pre6/drivers/ide/ali14xx.c linux/drivers/ide/ali14xx.c
--- linux-2.4.7-pre6/drivers/ide/ali14xx.c	Thu Apr 13 22:54:26 2000
+++ linux/drivers/ide/ali14xx.c	Mon Dec  3 22:55:49 2001
@@ -81,9 +81,9 @@
 	{0x2d, 0x32, 0x2e, 0x33},     /* drive 3 */
 };
 
-static int basePort = 0;	/* base port address */
-static int regPort = 0;		/* port for register number */
-static int dataPort = 0;	/* port for register data */
+static int basePort;	/* base port address */
+static int regPort;	/* port for register number */
+static int dataPort;	/* port for register data */
 static byte regOn;	/* output to base port to access registers */
 static byte regOff;	/* output to base port to close registers */
 
diff -urN linux-2.4.7-pre6/drivers/ide/alim15x3.c linux/drivers/ide/alim15x3.c
--- linux-2.4.7-pre6/drivers/ide/alim15x3.c	Sat May 19 17:43:06 2001
+++ linux/drivers/ide/alim15x3.c	Mon Dec  3 22:55:49 2001
@@ -679,19 +679,21 @@
 	hwif->drives[0].autotune = 1;
 	hwif->drives[1].autotune = 1;
 	hwif->speedproc = &ali15x3_tune_chipset;
-#ifndef CONFIG_BLK_DEV_IDEDMA
-	hwif->autodma = 0;
-	return;
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 
+#ifdef CONFIG_BLK_DEV_IDEDMA
 	if ((hwif->dma_base) && (m5229_revision >= 0x20)) {
 		/*
 		 * M1543C or newer for DMAing
 		 */
 		hwif->dmaproc = &ali15x3_dmaproc;
-		if (!noautodma)
-			hwif->autodma = 1;
+		hwif->autodma = 1;
 	}
+
+	if (noautodma)
+		hwif->autodma = 0;
+#else
+	hwif->autodma = 0;
+#endif /* CONFIG_BLK_DEV_IDEDMA */
 }
 
 void __init ide_dmacapable_ali15x3 (ide_hwif_t *hwif, unsigned long dmabase)
diff -urN linux-2.4.7-pre6/drivers/ide/buddha.c linux/drivers/ide/buddha.c
--- linux-2.4.7-pre6/drivers/ide/buddha.c	Mon Nov 27 17:57:34 2000
+++ linux/drivers/ide/buddha.c	Mon Dec  3 22:55:49 2001
@@ -87,7 +87,7 @@
      *  Board information
      */
 
-static u_long buddha_board = 0;
+static u_long buddha_board;
 static int buddha_num_hwifs = -1;
 
 
diff -urN linux-2.4.7-pre6/drivers/ide/ide-cd.c linux/drivers/ide/ide-cd.c
--- linux-2.4.7-pre6/drivers/ide/ide-cd.c	Fri May 25 12:44:11 2001
+++ linux/drivers/ide/ide-cd.c	Mon Dec  3 22:55:49 2001
@@ -254,7 +254,7 @@
  *			  They will disappear later when I get the time to
  *			  do it cleanly.
  *			- Minimize the TOC reading - only do it when we
- *			  know a media change has occured.
+ *			  know a media change has occurred.
  *			- Moved all the CDROMREADx ioctls to the Uniform layer.
  *			- Heiko Eissfeldt <heiko@colossus.escape.de> supplied
  *			  some fixes for CDI.
diff -urN linux-2.4.7-pre6/drivers/ide/ide-pmac.c linux/drivers/ide/ide-pmac.c
--- linux-2.4.7-pre6/drivers/ide/ide-pmac.c	Thu Feb 15 17:22:08 2001
+++ linux/drivers/ide/ide-pmac.c	Mon Dec  3 22:55:49 2001
@@ -176,7 +176,8 @@
 	if (pmac_ide[ix].dma_regs && pmac_ide[ix].dma_table) {
 		ide_hwifs[ix].dmaproc = &pmac_ide_dmaproc;
 #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC_AUTO
-		ide_hwifs[ix].autodma = 1;
+		if (!noautodma)
+			ide_hwifs[ix].autodma = 1;
 #endif
 	}
 }
@@ -676,7 +677,8 @@
 
 	ide_hwifs[ix].dmaproc = &pmac_ide_dmaproc;
 #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC_AUTO
-	ide_hwifs[ix].autodma = 1;
+	if (!noautodma)
+		ide_hwifs[ix].autodma = 1;
 #endif
 }
 
diff -urN linux-2.4.7-pre6/drivers/ide/pdc4030.c linux/drivers/ide/pdc4030.c
--- linux-2.4.7-pre6/drivers/ide/pdc4030.c	Tue Mar  6 19:44:34 2001
+++ linux/drivers/ide/pdc4030.c	Mon Dec  3 22:55:49 2001
@@ -367,7 +367,7 @@
 #ifdef DEBUG_READ
 			printk(KERN_DEBUG "%s: promise_read: waiting for"
 			       "interrupt\n", drive->name);
-#endif 
+#endif
 			return ide_started;
 		}
 		printk(KERN_ERR "%s: Eeek! promise_read_intr: sectors left "
@@ -457,8 +457,8 @@
 
 #ifdef DEBUG_WRITE
 	printk(KERN_DEBUG "%s: promise_write: sectors(%ld-%ld), "
-	       "buffer=0x%08x\n", drive->name, rq->sector,
-	       rq->sector + rq->nr_sectors - 1, (unsigned int)rq->buffer);
+	       "buffer=%p\n", drive->name, rq->sector,
+	       rq->sector + rq->nr_sectors - 1, rq->buffer);
 #endif
 
 	/*
diff -urN linux-2.4.7-pre6/drivers/ide/pdc4030.h linux/drivers/ide/pdc4030.h
--- linux-2.4.7-pre6/drivers/ide/pdc4030.h	Sat Feb 26 20:32:14 2000
+++ linux/drivers/ide/pdc4030.h	Mon Dec  3 22:55:49 2001
@@ -41,4 +41,4 @@
 	u8	pad[SECTOR_WORDS*4 - 32];
 };
 
-#endif IDE_PROMISE_H
+#endif /* IDE_PROMISE_H */
diff -urN linux-2.4.7-pre6/drivers/ide/piix.c linux/drivers/ide/piix.c
--- linux-2.4.7-pre6/drivers/ide/piix.c	Wed Jun 20 11:16:01 2001
+++ linux/drivers/ide/piix.c	Mon Dec  3 22:55:49 2001
@@ -516,7 +516,8 @@
 	hwif->autodma = 0;
 #else /* CONFIG_BLK_DEV_IDEDMA */
 #ifdef CONFIG_PIIX_TUNING
-	hwif->autodma = 1;
+	if (!noautodma)
+		hwif->autodma = 1;
 	hwif->dmaproc = &piix_dmaproc;
 	hwif->speedproc = &piix_tune_chipset;
 #endif /* CONFIG_PIIX_TUNING */
diff -urN linux-2.4.7-pre6/drivers/ide/slc90e66.c linux/drivers/ide/slc90e66.c
--- linux-2.4.7-pre6/drivers/ide/slc90e66.c	Sat May 19 17:43:06 2001
+++ linux/drivers/ide/slc90e66.c	Mon Dec  3 22:55:49 2001
@@ -349,11 +349,11 @@
 {
 #if 1
 	byte reg47 = 0, ata66 = 0;
-	byte mask = hwif->channel ? 0x02 : 0x01;
+	byte mask = hwif->channel ? 0x01 : 0x02;	/* bit0:Primary */
 
 	pci_read_config_byte(hwif->pci_dev, 0x47, &reg47);
 
-	ata66 = (reg47 & mask) ? 1 : 0;
+	ata66 = (reg47 & mask) ? 0 : 1;	/* bit[0(1)]: 0:80, 1:40 */
 #else
 	byte ata66 = 0;
 #endif
diff -urN linux-2.4.7-pre6/drivers/isdn/avmb1/b1dma.c linux/drivers/isdn/avmb1/b1dma.c
--- linux-2.4.7-pre6/drivers/isdn/avmb1/b1dma.c	Tue Jun 12 13:03:18 2001
+++ linux/drivers/isdn/avmb1/b1dma.c	Mon Dec  3 22:55:49 2001
@@ -26,6 +26,10 @@
 #include "capicmd.h"
 #include "capiutil.h"
 
+#if BITS_PER_LONG != 32
+#error FIXME: driver requires 32-bit platform
+#endif
+
 static char *revision = "$Revision: 1.11.6.6 $";
 
 /* ------------------------------------------------------------- */
diff -urN linux-2.4.7-pre6/drivers/isdn/hisax/bkm_a4t.c linux/drivers/isdn/hisax/bkm_a4t.c
--- linux-2.4.7-pre6/drivers/isdn/hisax/bkm_a4t.c	Fri Mar  2 11:12:08 2001
+++ linux/drivers/isdn/hisax/bkm_a4t.c	Mon Dec  3 22:55:49 2001
@@ -28,7 +28,7 @@
 
 
 static inline u_char
-readreg(unsigned int ale, unsigned int adr, u_char off)
+readreg(unsigned int ale, unsigned long adr, u_char off)
 {
 	register u_int ret;
 	long flags;
@@ -46,7 +46,7 @@
 
 
 static inline void
-readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
+readfifo(unsigned int ale, unsigned long adr, u_char off, u_char * data, int size)
 {
 	/* fifo read without cli because it's allready done  */
 	int i;
@@ -56,7 +56,7 @@
 
 
 static inline void
-writereg(unsigned int ale, unsigned int adr, u_char off, u_char data)
+writereg(unsigned int ale, unsigned long adr, u_char off, u_char data)
 {
 	long flags;
 	unsigned int *po = (unsigned int *) adr;	/* Postoffice */
@@ -71,7 +71,7 @@
 
 
 static inline void
-writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size)
+writefifo(unsigned int ale, unsigned long adr, u_char off, u_char * data, int size)
 {
 	/* fifo write without cli because it's allready done  */
 	int i;
@@ -316,11 +316,11 @@
 		printk(KERN_WARNING "HiSax: %s: No Memory base address\n", CardType[card->typ]);
 		return (0);
 	}
-	cs->hw.ax.base = (u_int) ioremap(pci_memaddr, 4096);
+	cs->hw.ax.base = (long) ioremap(pci_memaddr, 4096);
 	/* Check suspecious address */
 	pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base);
 	if ((pI20_Regs->i20IntStatus & 0x8EFFFFFF) != 0) {
-		printk(KERN_WARNING "HiSax: %s address %x-%x suspecious\n",
+		printk(KERN_WARNING "HiSax: %s address %lx-%lx suspecious\n",
 		       CardType[card->typ], cs->hw.ax.base, cs->hw.ax.base + 4096);
 		iounmap((void *) cs->hw.ax.base);
 		cs->hw.ax.base = 0;
@@ -335,7 +335,7 @@
 	printk(KERN_WARNING "HiSax: %s: unable to configure\n", CardType[card->typ]);
 	return (0);
 #endif				/* CONFIG_PCI */
-	printk(KERN_INFO "HiSax: %s: Card configured at 0x%X IRQ %d\n",
+	printk(KERN_INFO "HiSax: %s: Card configured at 0x%lX IRQ %d\n",
 	       CardType[card->typ], cs->hw.ax.base, cs->irq);
 
 	reset_bkm(cs);
diff -urN linux-2.4.7-pre6/drivers/isdn/hisax/bkm_a8.c linux/drivers/isdn/hisax/bkm_a8.c
--- linux-2.4.7-pre6/drivers/isdn/hisax/bkm_a8.c	Wed Apr 18 11:49:13 2001
+++ linux/drivers/isdn/hisax/bkm_a8.c	Mon Dec  3 22:55:49 2001
@@ -436,7 +436,7 @@
 	/* For isac and hscx data path */
 	cs->hw.ax.data_adr = cs->hw.ax.base + 4;
 
-	printk(KERN_INFO "HiSax: %s (%s) configured at 0x%.4X, 0x%.4X, 0x%.4X and IRQ %d\n",
+	printk(KERN_INFO "HiSax: %s (%s) configured at 0x%.4lX, 0x%.4lX, 0x%.4lX and IRQ %d\n",
 	       CardType[card->typ],
 	       sct_quadro_subtypes[cs->subtyp],
 	       cs->hw.ax.plx_adr,
diff -urN linux-2.4.7-pre6/drivers/isdn/hisax/elsa.c linux/drivers/isdn/hisax/elsa.c
--- linux-2.4.7-pre6/drivers/isdn/hisax/elsa.c	Fri Mar  2 11:12:08 2001
+++ linux/drivers/isdn/hisax/elsa.c	Mon Dec  3 22:55:49 2001
@@ -590,13 +590,13 @@
 		if (cs->subtyp==ELSA_QS1000) {
 			cs->subtyp = ELSA_QS3000;
 			printk(KERN_INFO
-				"Elsa: %s detected modem at 0x%x\n",
+				"Elsa: %s detected modem at 0x%lx\n",
 				Elsa_Types[cs->subtyp],
 				cs->hw.elsa.base+8);
 			release_region(cs->hw.elsa.base, 8);
 			if (check_region(cs->hw.elsa.base, 16)) {
 				printk(KERN_WARNING
-				"HiSax: %s config port %x-%x already in use\n",
+				"HiSax: %s config port %lx-%lx already in use\n",
 				Elsa_Types[cs->subtyp],
 				cs->hw.elsa.base + 8,
 				cs->hw.elsa.base + 16);
@@ -606,13 +606,13 @@
 		} else if (cs->subtyp==ELSA_PCC16) {
 			cs->subtyp = ELSA_PCF;
 			printk(KERN_INFO
-				"Elsa: %s detected modem at 0x%x\n",
+				"Elsa: %s detected modem at 0x%lx\n",
 				Elsa_Types[cs->subtyp],
 				cs->hw.elsa.base+8);
 			release_region(cs->hw.elsa.base, 8);
 			if (check_region(cs->hw.elsa.base, 16)) {
 				printk(KERN_WARNING
-				"HiSax: %s config port %x-%x already in use\n",
+				"HiSax: %s config port %lx-%lx already in use\n",
 				Elsa_Types[cs->subtyp],
 				cs->hw.elsa.base + 8,
 				cs->hw.elsa.base + 16);
@@ -621,7 +621,7 @@
 					"elsa isdn modem");
 		} else
 			printk(KERN_INFO
-				"Elsa: %s detected modem at 0x%x\n",
+				"Elsa: %s detected modem at 0x%lx\n",
 				Elsa_Types[cs->subtyp],
 				cs->hw.elsa.base+8);
 		arcofi_fsm(cs, ARCOFI_START, &ARCOFI_XOP_0);
diff -urN linux-2.4.7-pre6/drivers/isdn/hisax/hisax.h linux/drivers/isdn/hisax/hisax.h
--- linux-2.4.7-pre6/drivers/isdn/hisax/hisax.h	Mon Jul  2 14:07:55 2001
+++ linux/drivers/isdn/hisax/hisax.h	Mon Dec  3 22:55:49 2001
@@ -535,7 +535,7 @@
 };
 
 struct elsa_hw {
-	unsigned int base;
+	unsigned long base;
 	unsigned int cfg;
 	unsigned int ctrl;
 	unsigned int ale;
@@ -597,9 +597,9 @@
 	unsigned long cfg_reg;
 	unsigned long pci_cfg;
 	unsigned int ctrl;
-	unsigned int isac_adr;
+	unsigned long isac_adr;
 	unsigned int isac;
-	unsigned int hscx_adr;
+	unsigned long hscx_adr;
 	unsigned int hscx;
 	unsigned int status;
 	struct timer_list tl;
@@ -653,7 +653,7 @@
 };
 
 struct njet_hw {
-	unsigned int base;
+	unsigned long base;
 	unsigned int isac;
 	unsigned int auxa;
 	unsigned char auxd;
@@ -692,7 +692,7 @@
 };
 
 struct hfcSX_hw {
-        unsigned int  base;
+        unsigned long base;
 	unsigned char cirm;
 	unsigned char ctmt;
 	unsigned char conn;
@@ -754,15 +754,15 @@
 };
 
 struct bkm_hw {
-	unsigned int base;
+	unsigned long base;
 	/* A4T stuff */
-	unsigned int isac_adr;
+	unsigned long isac_adr;
 	unsigned int isac_ale;
-	unsigned int jade_adr;
+	unsigned long jade_adr;
 	unsigned int jade_ale;
 	/* Scitel Quadro stuff */
-	unsigned int plx_adr;
-	unsigned int data_adr;
+	unsigned long plx_adr;
+	unsigned long data_adr;
 };	
 
 struct gazel_hw {
@@ -1275,7 +1275,7 @@
 struct IsdnCard {
 	int typ;
 	int protocol;		/* EDSS1, 1TR6 or NI1 */
-	unsigned int para[4];
+	unsigned long para[4];
 	struct IsdnCardState *cs;
 };
 
diff -urN linux-2.4.7-pre6/drivers/isdn/hysdn/boardergo.c linux/drivers/isdn/hysdn/boardergo.c
--- linux-2.4.7-pre6/drivers/isdn/hysdn/boardergo.c	Sat May 19 17:54:14 2001
+++ linux/drivers/isdn/hysdn/boardergo.c	Mon Dec  3 22:55:49 2001
@@ -35,6 +35,7 @@
 #include <linux/kernel.h>
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
+#include <linux/vmalloc.h>
 
 #include "hysdn_defs.h"
 #include "boardergo.h"
diff -urN linux-2.4.7-pre6/drivers/isdn/isdn_bsdcomp.c linux/drivers/isdn/isdn_bsdcomp.c
--- linux-2.4.7-pre6/drivers/isdn/isdn_bsdcomp.c	Fri Mar  2 11:12:09 2001
+++ linux/drivers/isdn/isdn_bsdcomp.c	Mon Dec  3 22:55:49 2001
@@ -76,6 +76,7 @@
 #include <linux/skbuff.h>
 #include <linux/inet.h>
 #include <linux/ioctl.h>
+#include <linux/vmalloc.h>
 
 #include <linux/ppp_defs.h>
 
diff -urN linux-2.4.7-pre6/drivers/md/lvm.c linux/drivers/md/lvm.c
--- linux-2.4.7-pre6/drivers/md/lvm.c	Sat Apr 21 10:37:16 2001
+++ linux/drivers/md/lvm.c	Mon Dec  3 22:55:49 2001
@@ -988,6 +988,10 @@
 
 	case LV_BMAP:
 		/* turn logical block into (dev_t, block). non privileged. */
+		/* don't bmap a snapshot, since the mapping can change */
+		if (lv_ptr->lv_access & LV_SNAPSHOT)
+			return -EPERM;
+
 		return lvm_user_bmap(inode, (struct lv_bmap *) arg);
 		break;
 
@@ -1075,8 +1079,8 @@
 		return -EFAULT;
 
 	memset(&bh,0,sizeof bh);
-	bh.b_rsector = block;
-	bh.b_dev = bh.b_rdev = inode->i_dev;
+	bh.b_blocknr = block;
+	bh.b_dev = bh.b_rdev = inode->i_rdev;
 	bh.b_size = lvm_get_blksize(bh.b_dev);
 	if ((err=lvm_map(&bh, READ)) < 0)  {
 		printk("lvm map failed: %d\n", err);
@@ -1084,7 +1088,8 @@
 	}
 
 	return put_user(kdev_t_to_nr(bh.b_rdev), &user_result->lv_dev) ||
-	put_user(bh.b_rsector, &user_result->lv_block) ? -EFAULT : 0;
+	       put_user(bh.b_rsector/(bh.b_size>>9), &user_result->lv_block) ?
+	       -EFAULT : 0;
 }
 
 
diff -urN linux-2.4.7-pre6/drivers/media/video/bttv-driver.c linux/drivers/media/video/bttv-driver.c
--- linux-2.4.7-pre6/drivers/media/video/bttv-driver.c	Wed Jun 20 11:10:27 2001
+++ linux/drivers/media/video/bttv-driver.c	Mon Dec  3 22:55:49 2001
@@ -1688,6 +1688,9 @@
 				vfree(vcp);
 				return -EFAULT;
 			}
+		} else if (vw.clipcount > 2048) {
+			up(&btv->lock);
+			return -EINVAL;
 		} else if (vw.clipcount) {
 			if((vcp=vmalloc(sizeof(struct video_clip)*
 					(vw.clipcount))) == NULL) {
diff -urN linux-2.4.7-pre6/drivers/media/video/zr36120.c linux/drivers/media/video/zr36120.c
--- linux-2.4.7-pre6/drivers/media/video/zr36120.c	Wed Jun 27 17:10:55 2001
+++ linux/drivers/media/video/zr36120.c	Mon Dec  3 22:55:49 2001
@@ -1189,7 +1189,7 @@
 		if (vw.flags)
 			return -EINVAL;
 
-		if (vw.clipcount>256)
+		if (vw.clipcount <0 || vw.clipcount>256)
 			return -EDOM;   /* Too many! */
 
 		/*
diff -urN linux-2.4.7-pre6/drivers/net/3c501.c linux/drivers/net/3c501.c
--- linux-2.4.7-pre6/drivers/net/3c501.c	Wed Jun 20 11:10:53 2001
+++ linux/drivers/net/3c501.c	Mon Dec  3 22:55:49 2001
@@ -11,9 +11,11 @@
     Do not purchase this card, even as a joke.  It's performance is horrible,
     and it breaks in many ways.
 
-    The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
-    Center of Excellence in Space Data and Information Sciences
-       Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
+    The author may be reached as becker@scyld.com, or C/O
+	Scyld Computing Corporation
+	410 Severn Ave., Suite 210
+	Annapolis MD 21403
+
 
     Fixed (again!) the missing interrupt locking on TX/RX shifting.
     		Alan Cox <Alan.Cox@linux.org>
diff -urN linux-2.4.7-pre6/drivers/net/3c503.c linux/drivers/net/3c503.c
--- linux-2.4.7-pre6/drivers/net/3c503.c	Wed Jun 20 11:10:53 2001
+++ linux/drivers/net/3c503.c	Mon Dec  3 22:55:49 2001
@@ -7,9 +7,11 @@
     distributed according to the terms of the GNU General Public License,
     incorporated herein by reference.
 
-    The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
-    Center of Excellence in Space Data and Information Sciences
-       Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
+    The author may be reached as becker@scyld.com, or C/O
+	Scyld Computing Corporation
+	410 Severn Ave., Suite 210
+	Annapolis MD 21403
+
 
     This driver should work with the 3c503 and 3c503/16.  It should be used
     in shared memory mode for best performance, although it may also work
diff -urN linux-2.4.7-pre6/drivers/net/3c505.c linux/drivers/net/3c505.c
--- linux-2.4.7-pre6/drivers/net/3c505.c	Wed Jun 20 11:10:53 2001
+++ linux/drivers/net/3c505.c	Mon Dec  3 22:55:49 2001
@@ -20,6 +20,7 @@
  *                      Juha Laiho, <jlaiho@ichaos.nullnet.fi>
  *              Linux 3C509 driver by
  *                      Donald Becker, <becker@super.org>
+ *			(Now at <becker@scyld.com>)
  *              Crynwr packet driver by
  *                      Krishnan Gopalan and Gregg Stefancik,
  *                      Clemson University Engineering Computer Operations.
diff -urN linux-2.4.7-pre6/drivers/net/3c507.c linux/drivers/net/3c507.c
--- linux-2.4.7-pre6/drivers/net/3c507.c	Wed Jun 20 11:10:53 2001
+++ linux/drivers/net/3c507.c	Mon Dec  3 22:55:49 2001
@@ -8,9 +8,11 @@
 	This software may be used and distributed according to the terms
 	of the GNU General Public License, incorporated herein by reference.
 
-	The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
-	Center of Excellence in Space Data and Information Sciences
-	   Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
+	The author may be reached as becker@scyld.com, or C/O
+	Scyld Computing Corporation
+	410 Severn Ave., Suite 210
+	Annapolis MD 21403
+
 
 	Thanks go to jennings@Montrouge.SMR.slb.com ( Patrick Jennings)
 	and jrs@world.std.com (Rick Sladkey) for testing and bugfixes.
diff -urN linux-2.4.7-pre6/drivers/net/3c509.c linux/drivers/net/3c509.c
--- linux-2.4.7-pre6/drivers/net/3c509.c	Mon Dec  3 22:55:41 2001
+++ linux/drivers/net/3c509.c	Mon Dec  3 22:55:49 2001
@@ -10,9 +10,10 @@
 
 	This driver is for the 3Com EtherLinkIII series.
 
-	The author may be reached as becker@cesdis.gsfc.nasa.gov or
-	C/O Center of Excellence in Space Data and Information Sciences
-		Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
+	The author may be reached as becker@scyld.com, or C/O
+	Scyld Computing Corporation
+	410 Severn Ave., Suite 210
+	Annapolis MD 21403
 
 	Known limitations:
 	Because of the way 3c509 ISA detection works it's difficult to predict
diff -urN linux-2.4.7-pre6/drivers/net/3c515.c linux/drivers/net/3c515.c
--- linux-2.4.7-pre6/drivers/net/3c515.c	Wed Jun 20 11:10:53 2001
+++ linux/drivers/net/3c515.c	Mon Dec  3 22:55:49 2001
@@ -7,9 +7,11 @@
 
 	This driver is for the 3Com ISA EtherLink XL "Corkscrew" 3c515 ethercard.
 
-	The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
-	Center of Excellence in Space Data and Information Sciences
-	   Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
+	The author may be reached as becker@scyld.com, or C/O
+	Scyld Computing Corporation
+	410 Severn Ave., Suite 210
+	Annapolis MD 21403
+
 
 	2/2/00- Added support for kernel-level ISAPnP 
 		by Stephen Frost <sfrost@snowman.net> and Alessandro Zummo
@@ -78,7 +80,7 @@
 #define REQUEST_IRQ(i,h,f,n, instance) request_irq(i,h,f,n, instance)
 #define IRQ(irq, dev_id, pt_regs) (irq, dev_id, pt_regs)
 
-MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
+MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
 MODULE_DESCRIPTION("3Com 3c515 Corkscrew driver");
 MODULE_PARM(debug, "i");
 MODULE_PARM(options, "1-" __MODULE_STRING(8) "i");
diff -urN linux-2.4.7-pre6/drivers/net/8139too.c linux/drivers/net/8139too.c
--- linux-2.4.7-pre6/drivers/net/8139too.c	Mon Dec  3 22:55:41 2001
+++ linux/drivers/net/8139too.c	Mon Dec  3 22:55:49 2001
@@ -294,6 +294,7 @@
 	 * so we simply don't match on the main vendor id.
 	 */
 	{PCI_ANY_ID, 0x8139, 0x10ec, 0x8139, 0, 0, RTL8139 },
+	{PCI_ANY_ID, 0x8139, 0x1186, 0x1300, 0, 0, DFE538TX },
 
 	{0,}
 };
@@ -1168,6 +1169,7 @@
 };
 
 
+#ifdef CONFIG_8139TOO_8129
 /* Syncronize the MII management interface by shifting 32 one bits out. */
 static void mdio_sync (void *mdio_addr)
 {
@@ -1184,15 +1186,17 @@
 
 	DPRINTK ("EXIT\n");
 }
-
+#endif
 
 static int mdio_read (struct net_device *dev, int phy_id, int location)
 {
 	struct rtl8139_private *tp = dev->priv;
+	int retval = 0;
+#ifdef CONFIG_8139TOO_8129
 	void *mdio_addr = tp->mmio_addr + Config4;
 	int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location;
-	int retval = 0;
 	int i;
+#endif
 
 	DPRINTK ("ENTER\n");
 
@@ -1233,9 +1237,11 @@
 			int value)
 {
 	struct rtl8139_private *tp = dev->priv;
+#ifdef CONFIG_8139TOO_8129
 	void *mdio_addr = tp->mmio_addr + Config4;
 	int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value;
 	int i;
+#endif
 
 	DPRINTK ("ENTER\n");
 
@@ -1732,7 +1738,6 @@
 	RTL_W32_F (TxAddr0 + (entry * 4), dma_addr);
 	RTL_W32_F (TxStatus0 + (entry * sizeof (u32)),
 		   tp->tx_flag | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN));
-	spin_unlock_irq(&tp->lock);
 
 	dev->trans_start = jiffies;
 
@@ -1740,6 +1745,7 @@
 	mb();
 	if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx)
 		netif_stop_queue (dev);
+	spin_unlock_irq(&tp->lock);
 
 	DPRINTK ("%s: Queued Tx packet at %p size %u to slot %d.\n",
 		 dev->name, skb->data, skb->len, entry);
diff -urN linux-2.4.7-pre6/drivers/net/82596.c linux/drivers/net/82596.c
--- linux-2.4.7-pre6/drivers/net/82596.c	Wed Jun 20 11:10:53 2001
+++ linux/drivers/net/82596.c	Mon Dec  3 22:55:49 2001
@@ -35,8 +35,8 @@
    according to the terms of the GNU General Public License as modified by SRC,
    incorporated herein by reference.
 
-   The author may be reached as becker@super.org or
-   C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
+   The author may be reached as becker@scyld.com, or C/O
+   Scyld Computing Corporation, 410 Severn Ave., Suite 210, Annapolis MD 21403
 
  */
 
diff -urN linux-2.4.7-pre6/drivers/net/8390.c linux/drivers/net/8390.c
--- linux-2.4.7-pre6/drivers/net/8390.c	Wed May 16 10:25:38 2001
+++ linux/drivers/net/8390.c	Mon Dec  3 22:55:49 2001
@@ -8,9 +8,11 @@
 	This software may be used and distributed according to the terms
 	of the GNU General Public License, incorporated herein by reference.
 
-	The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
-	Center of Excellence in Space Data and Information Sciences
-	   Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
+	The author may be reached as becker@scyld.com, or C/O
+	Scyld Computing Corporation
+	410 Severn Ave., Suite 210
+	Annapolis MD 21403
+
   
   This is the chip-specific code for many 8390-based ethernet adaptors.
   This is not a complete driver, it must be combined with board-specific
diff -urN linux-2.4.7-pre6/drivers/net/Config.in linux/drivers/net/Config.in
--- linux-2.4.7-pre6/drivers/net/Config.in	Mon Dec  3 22:55:41 2001
+++ linux/drivers/net/Config.in	Mon Dec  3 22:55:49 2001
@@ -207,7 +207,7 @@
 
 dep_tristate 'Alteon AceNIC/3Com 3C985/NetGear GA620 Gigabit support' CONFIG_ACENIC $CONFIG_PCI
 dep_mbool '  Omit support for old Tigon I based AceNICs' CONFIG_ACENIC_OMIT_TIGON_I $CONFIG_ACENIC
-dep_tristate 'D-Link 2000-based Gigabit Ethernet support' CONFIG_DL2K $CONFIG_PCI
+dep_tristate 'D-Link DL2000-based Gigabit Ethernet support' CONFIG_DL2K $CONFIG_PCI
 dep_tristate 'MyriCOM Gigabit Ethernet support' CONFIG_MYRI_SBUS $CONFIG_SBUS
 dep_tristate 'Packet Engines Hamachi GNIC-II support' CONFIG_HAMACHI $CONFIG_PCI
 dep_tristate 'Packet Engines Yellowfin Gigabit-NIC support (EXPERIMENTAL)' CONFIG_YELLOWFIN $CONFIG_PCI $CONFIG_EXPERIMENTAL
diff -urN linux-2.4.7-pre6/drivers/net/Space.c linux/drivers/net/Space.c
--- linux-2.4.7-pre6/drivers/net/Space.c	Wed Apr 18 11:39:21 2001
+++ linux/drivers/net/Space.c	Mon Dec  3 22:55:49 2001
@@ -9,7 +9,7 @@
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
- *		Donald J. Becker, <becker@super.org>
+ *		Donald J. Becker, <becker@scyld.com>
  *
  * Changelog:
  *		Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 09/1999
diff -urN linux-2.4.7-pre6/drivers/net/ac3200.c linux/drivers/net/ac3200.c
--- linux-2.4.7-pre6/drivers/net/ac3200.c	Wed Jun 20 11:10:53 2001
+++ linux/drivers/net/ac3200.c	Mon Dec  3 22:55:49 2001
@@ -6,8 +6,10 @@
 	according to the terms of the GNU General Public License as modified by SRC,
 	incorporated herein by reference.
 
-	The author may be reached as becker@cesdis.gsfc.nasa.gov, or
-	C/O Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
+	The author may be reached as becker@scyld.com, or C/O
+	Scyld Computing Corporation
+	410 Severn Ave., Suite 210
+	Annapolis MD 21403
 
 	This is driver for the Ansel Communications Model 3200 EISA Ethernet LAN
 	Adapter.  The programming information is from the users manual, as related
diff -urN linux-2.4.7-pre6/drivers/net/aironet4500.h linux/drivers/net/aironet4500.h
--- linux-2.4.7-pre6/drivers/net/aironet4500.h	Mon Dec 11 13:00:51 2000
+++ linux/drivers/net/aironet4500.h	Mon Dec  3 22:55:49 2001
@@ -47,10 +47,6 @@
 
 
 #include <linux/spinlock.h>
-typedef spinlock_t 			my_spinlock_t	;
-#define my_spin_lock_init(a)		spin_lock_init(a)
-#define my_spin_lock_irqsave(a,b) 	spin_lock_irqsave(a,b)
-#define my_spin_unlock_irqrestore(a,b) 	spin_unlock_irqrestore(a,b)
 
 
 #define AWC_ERROR	-1
@@ -111,7 +107,7 @@
 	volatile int lock;
 	volatile int	status;
 	struct semaphore sem;
-	my_spinlock_t spinlock;
+	spinlock_t spinlock;
 	unsigned long flags;
 };
 
@@ -157,8 +153,8 @@
 	printk("bap lock under cli but not in int\n");\
 */
 
-#define AWC_LOCK_COMMAND_ISSUING(a) my_spin_lock_irqsave(&a->command_issuing_spinlock,a->command_issuing_spinlock_flags);
-#define AWC_UNLOCK_COMMAND_ISSUING(a) my_spin_unlock_irqrestore(&a->command_issuing_spinlock,a->command_issuing_spinlock_flags);
+#define AWC_LOCK_COMMAND_ISSUING(a) spin_lock_irqsave(&a->command_issuing_spinlock,a->command_issuing_spinlock_flags);
+#define AWC_UNLOCK_COMMAND_ISSUING(a) spin_unlock_irqrestore(&a->command_issuing_spinlock,a->command_issuing_spinlock_flags);
 
 #define AWC_BAP_LOCK_UNDER_CLI_REAL(cmd) \
  	if (!cmd.priv) {\
@@ -166,9 +162,9 @@
 	}\
 	cmd.bap = &(cmd.priv->bap1);\
 	if (both_bap_lock)\
-	my_spin_lock_irqsave(&cmd.priv->both_bap_spinlock,cmd.priv->both_bap_spinlock_flags);\
+	spin_lock_irqsave(&cmd.priv->both_bap_spinlock,cmd.priv->both_bap_spinlock_flags);\
 	if (cmd.bap){\
-		my_spin_lock_irqsave(&(cmd.bap->spinlock),cmd.bap->flags);\
+		spin_lock_irqsave(&(cmd.bap->spinlock),cmd.bap->flags);\
 		cmd.bap->lock++;\
 		if (cmd.bap->lock > 1)\
 			printk("Bap 1 lock high\n");\
@@ -183,8 +179,8 @@
 	}\
 	cmd.bap = &(cmd.priv->bap0);\
 	if (both_bap_lock)\
-		my_spin_lock_irqsave(&cmd.priv->both_bap_spinlock,cmd.priv->both_bap_spinlock_flags);\
-	my_spin_lock_irqsave(&(cmd.bap->spinlock),cmd.bap->flags);\
+		spin_lock_irqsave(&cmd.priv->both_bap_spinlock,cmd.priv->both_bap_spinlock_flags);\
+	spin_lock_irqsave(&(cmd.bap->spinlock),cmd.bap->flags);\
 	DOWN(&(cmd.priv->bap0.sem));\
 	cmd.bap->lock++;\
 	if (cmd.bap->lock > 1)\
@@ -195,8 +191,8 @@
 #define AWC_BAP_LOCK_NOT_CLI_CLI_REAL(cmd) {\
 	cmd.bap = &(cmd.priv->bap0);\
 	if (both_bap_lock)\
-		my_spin_lock_irqsave(&cmd.priv->both_bap_spinlock,cmd.priv->both_bap_spinlock_flags);\
-	my_spin_lock_irqsave(&(cmd.bap->spinlock),cmd.bap->flags);\
+		spin_lock_irqsave(&cmd.priv->both_bap_spinlock,cmd.priv->both_bap_spinlock_flags);\
+	spin_lock_irqsave(&(cmd.bap->spinlock),cmd.bap->flags);\
 	cmd.bap->lock++;\
 	if (cmd.bap->lock > 1)\
 		printk("Bap 0 lock high\n");\
@@ -258,15 +254,15 @@
 			 com.bap->lock--; \
 			 com.lock_state &= ~AWC_BAP_SEMALOCKED;\
 			 UP(&(com.bap->sem)); \
-			 my_spin_unlock_irqrestore(&(cmd.bap->spinlock),cmd.bap->flags);\
+			 spin_unlock_irqrestore(&(cmd.bap->spinlock),cmd.bap->flags);\
 		} else if (com.lock_state & AWC_BAP_LOCKED){\
 			 com.bap->lock--; \
 			 com.lock_state &= ~AWC_BAP_LOCKED;\
-			 my_spin_unlock_irqrestore(&(cmd.bap->spinlock),cmd.bap->flags);\
+			 spin_unlock_irqrestore(&(cmd.bap->spinlock),cmd.bap->flags);\
 		}\
 	}\
 	if (both_bap_lock)\
-		my_spin_unlock_irqrestore(&cmd.priv->both_bap_spinlock,cmd.priv->both_bap_spinlock_flags);\
+		spin_unlock_irqrestore(&cmd.priv->both_bap_spinlock,cmd.priv->both_bap_spinlock_flags);\
 }
 
 #define AWC_RELEASE_COMMAND(com) {\
@@ -450,7 +446,7 @@
 	struct awc_fid * head;
 	struct awc_fid * tail;
 	int	size;
-	my_spinlock_t spinlock;
+	spinlock_t spinlock;
 };
 
 
@@ -459,12 +455,12 @@
 
 	unsigned long flags;
 	memset(queue,0, sizeof(struct awc_fid_queue));	
-	my_spin_lock_init(&queue->spinlock);
-	my_spin_lock_irqsave(&queue->spinlock,flags);
+	spin_lock_init(&queue->spinlock);
+	spin_lock_irqsave(&queue->spinlock,flags);
 	queue->head = NULL;
 	queue->tail = NULL;
 	queue->size = 0;
-	my_spin_unlock_irqrestore(&queue->spinlock,flags);	
+	spin_unlock_irqrestore(&queue->spinlock,flags);	
 };
 
 extern inline void
@@ -473,7 +469,7 @@
 
 	unsigned long flags;
 
-	my_spin_lock_irqsave(&queue->spinlock,flags);	
+	spin_lock_irqsave(&queue->spinlock,flags);	
 	
 	fid->prev = queue->tail;
 	fid->next = NULL;
@@ -487,7 +483,7 @@
 		queue->head = fid;
 	queue->size++;
 
-	my_spin_unlock_irqrestore(&queue->spinlock,flags);
+	spin_unlock_irqrestore(&queue->spinlock,flags);
 		
 };
 
@@ -498,7 +494,7 @@
 
 	unsigned long flags;
 
-	my_spin_lock_irqsave(&queue->spinlock,flags);	
+	spin_lock_irqsave(&queue->spinlock,flags);	
 	
 	fid->prev = NULL;
 	fid->next = queue->head;
@@ -512,9 +508,7 @@
 		queue->tail = fid;
 	queue->size++;
 	
-	
-	my_spin_unlock_irqrestore(&queue->spinlock,flags);
-	
+	spin_unlock_irqrestore(&queue->spinlock,flags);
 };
 
 
@@ -551,11 +545,11 @@
 awc_fid_queue_remove(		struct awc_fid_queue * 	queue,
 				struct awc_fid *	fid){
 	unsigned long flags;
-	my_spin_lock_irqsave(&queue->spinlock,flags);	
+	spin_lock_irqsave(&queue->spinlock,flags);	
 	
 	awc_fid_queue_rm(queue,fid);
 	
-	my_spin_unlock_irqrestore(&queue->spinlock,flags);
+	spin_unlock_irqrestore(&queue->spinlock,flags);
 	
 };
 
@@ -567,14 +561,13 @@
 	unsigned long flags;
 	struct awc_fid * fid;
 	
-	my_spin_lock_irqsave(&queue->spinlock,flags);	
+	spin_lock_irqsave(&queue->spinlock,flags);	
 
 	fid = queue->head;
 	if (fid)
 		awc_fid_queue_rm(queue,fid);
 		
-	
-	my_spin_unlock_irqrestore(&queue->spinlock,flags);
+	spin_unlock_irqrestore(&queue->spinlock,flags);
 	
 	return fid;
 };
@@ -588,13 +581,13 @@
 	unsigned long flags;
 	struct awc_fid * fid;
 	
-	my_spin_lock_irqsave(&queue->spinlock,flags);	
+	spin_lock_irqsave(&queue->spinlock,flags);	
 
 	fid = queue->tail;
 	if (fid)
 			awc_fid_queue_rm(queue,fid);
 	
-	my_spin_unlock_irqrestore(&queue->spinlock,flags);
+	spin_unlock_irqrestore(&queue->spinlock,flags);
 	
 	return fid;
 };
@@ -1465,7 +1458,7 @@
 	struct awc_fid_queue    tx_large_ready;
 	struct awc_fid_queue    tx_post_process;
 	struct awc_fid_queue    tx_in_transmit;
-	my_spinlock_t		queues_lock;
+	spinlock_t		queues_lock;
 
 	struct awc_fid_queue    rx_ready;
 	struct awc_fid_queue    rx_post_process;
@@ -1494,13 +1487,13 @@
 	
 	// Command serialize stuff
 //changed to spinlock        struct semaphore 	command_semaphore;
-	my_spinlock_t		both_bap_spinlock; // on SMP, card should theorethically live without that
+	spinlock_t		both_bap_spinlock; // on SMP, card should theorethically live without that
 	unsigned long		both_bap_spinlock_flags;
-	my_spinlock_t		bap_setup_spinlock; // on SMP, card should theoretically live without that
+	spinlock_t		bap_setup_spinlock; // on SMP, card should theoretically live without that
 	unsigned long		bap_setup_spinlock_flags;
-	my_spinlock_t		command_issuing_spinlock;
+	spinlock_t		command_issuing_spinlock;
 	unsigned long		command_issuing_spinlock_flags;
-	my_spinlock_t		interrupt_spinlock;
+	spinlock_t		interrupt_spinlock;
 
         volatile int		unlock_command_postponed;
         struct awc_command	cmd;
diff -urN linux-2.4.7-pre6/drivers/net/aironet4500_core.c linux/drivers/net/aironet4500_core.c
--- linux-2.4.7-pre6/drivers/net/aironet4500_core.c	Wed Jun 20 11:10:53 2001
+++ linux/drivers/net/aironet4500_core.c	Mon Dec  3 22:55:49 2001
@@ -394,7 +394,7 @@
      	DEBUG(1,"no bap or bap not locked cmd %d !!", cmd->command);
 
 	if (bap_setup_spinlock)
-		my_spin_lock_irqsave(&cmd->priv->bap_setup_spinlock,cmd->priv->bap_setup_spinlock_flags);	  
+		spin_lock_irqsave(&cmd->priv->bap_setup_spinlock,cmd->priv->bap_setup_spinlock_flags);	  
 	  status = AWC_IN(cmd->bap->offset);
 	  
 	  if (status & ~0x2000 ){
@@ -526,19 +526,19 @@
 
 ejected_unlock:
      if (bap_setup_spinlock)
-	my_spin_unlock_irqrestore(&cmd->priv->bap_setup_spinlock,cmd->priv->bap_setup_spinlock_flags);	  
+	spin_unlock_irqrestore(&cmd->priv->bap_setup_spinlock,cmd->priv->bap_setup_spinlock_flags);	  
      AWC_ENTRY_EXIT_DEBUG(" ejected_unlock_exit \n");	
      return -1;
 
 return_AWC_ERROR:
      if (bap_setup_spinlock)
-	my_spin_unlock_irqrestore(&cmd->priv->bap_setup_spinlock,cmd->priv->bap_setup_spinlock_flags);	  
+	spin_unlock_irqrestore(&cmd->priv->bap_setup_spinlock,cmd->priv->bap_setup_spinlock_flags);	  
      AWC_ENTRY_EXIT_DEBUG(" AWC_ERROR_exit \n");
      return AWC_ERROR;          
 
 return_AWC_SUCCESS:
      if (bap_setup_spinlock)
-	my_spin_unlock_irqrestore(&cmd->priv->bap_setup_spinlock,cmd->priv->bap_setup_spinlock_flags);	  
+	spin_unlock_irqrestore(&cmd->priv->bap_setup_spinlock,cmd->priv->bap_setup_spinlock_flags);	  
      AWC_ENTRY_EXIT_DEBUG(" exit \n");
      return AWC_SUCCESS;          
 }
@@ -1190,7 +1190,7 @@
 	
      AWC_ENTRY_EXIT_DEBUG(" entry awc_tx_fid_lookup ");
 
-	my_spin_lock_irqsave(&(priv->queues_lock),flags);
+	spin_lock_irqsave(&(priv->queues_lock),flags);
 
 
 	fid = priv->tx_in_transmit.head;
@@ -1198,14 +1198,14 @@
 	while (fid){
 	  	if (fid->u.tx.fid == fid_handle){
 	  		awc_fid_queue_remove(&priv->tx_in_transmit, fid);
-	  		my_spin_unlock_irqrestore(&(priv->queues_lock),flags);
+	  		spin_unlock_irqrestore(&(priv->queues_lock),flags);
 	  		return fid;
 	  	}
 	  	fid = fid->next;
 	//	printk("iT\n");
 		if (cnt++ > 200) {
 	//		printk("bbb in awc_fid_queue\n");
-			my_spin_unlock_irqrestore(&(priv->queues_lock),flags);
+			spin_unlock_irqrestore(&(priv->queues_lock),flags);
 	  		return 0;
 		};
 	};
@@ -1215,14 +1215,14 @@
 	while (fid){
 	  	if (fid->u.tx.fid == fid_handle){
 	  		awc_fid_queue_remove(&priv->tx_post_process, fid);
-	  		my_spin_unlock_irqrestore(&(priv->queues_lock),flags);
+	  		spin_unlock_irqrestore(&(priv->queues_lock),flags);
 	  		return fid;
 	  	}
 	  	fid = fid->next;
 	//	printk("pp\n");
 		if (cnt++ > 200) {
 	//		printk("bbb in awc_fid_queue\n");
-			my_spin_unlock_irqrestore(&(priv->queues_lock),flags);
+			spin_unlock_irqrestore(&(priv->queues_lock),flags);
 	  		return 0;
 		};
 
@@ -1233,14 +1233,14 @@
 	while (fid){
 	  	if (fid->u.tx.fid == fid_handle){
 	  		awc_fid_queue_remove(&priv->tx_large_ready, fid);
-	  		my_spin_unlock_irqrestore(&(priv->queues_lock),flags);
+	  		spin_unlock_irqrestore(&(priv->queues_lock),flags);
 	  		return fid;
 	  	}
 	  	fid = fid->next;
 	//	printk("lr\n");
 		if (cnt++ > 200) {
 	//		printk("bbb in awc_fid_queue\n");
-			my_spin_unlock_irqrestore(&(priv->queues_lock),flags);
+			spin_unlock_irqrestore(&(priv->queues_lock),flags);
 	  		return 0;
 		};
 
@@ -1250,20 +1250,20 @@
 	while (fid){
 	  	if (fid->u.tx.fid == fid_handle){
 	  		awc_fid_queue_remove(&priv->tx_small_ready, fid);
-	  		my_spin_unlock_irqrestore(&(priv->queues_lock),flags);
+	  		spin_unlock_irqrestore(&(priv->queues_lock),flags);
 	  		return fid;
 	  	}
 	  	fid = fid->next;
 	//	printk("sr\n");
 		if (cnt++ > 200) {
 	//		printk("bbb in awc_fid_queue\n");
-			my_spin_unlock_irqrestore(&(priv->queues_lock),flags);
+			spin_unlock_irqrestore(&(priv->queues_lock),flags);
 	  		return 0;
 		};
 
 	};
 
-	my_spin_unlock_irqrestore(&(priv->queues_lock),flags);
+	spin_unlock_irqrestore(&(priv->queues_lock),flags);
 	
 	printk(KERN_ERR "%s tx fid %x not found \n",dev->name, fid_handle);  
         AWC_ENTRY_EXIT_DEBUG(" BAD exit \n");   	  
@@ -2792,7 +2792,7 @@
 	// here we go, bad aironet
 	memset(&priv->SSIDs,0,sizeof(priv->SSIDs));
 
-	my_spin_lock_init(&priv->queues_lock);
+	spin_lock_init(&priv->queues_lock);
         priv->SSIDs.ridLen		=0;
         if (!SSID) {
 	        priv->SSIDs.SSID[0].SSID[0] 	='a';
@@ -2849,29 +2849,29 @@
 	
 	memset(priv, 0, sizeof(struct awc_private)); 
 	
-	my_spin_lock_init(&priv->queues_lock);
+	spin_lock_init(&priv->queues_lock);
 	
 	priv->bap0.select 	= dev->base_addr + awc_Select0_register;
 	priv->bap0.offset 	= dev->base_addr + awc_Offset0_register;
 	priv->bap0.data		= dev->base_addr + awc_Data0_register;
 	priv->bap0.lock 	= 0;
 	priv->bap0.status	= 0;
-	my_spin_lock_init(&priv->bap0.spinlock);
+	spin_lock_init(&priv->bap0.spinlock);
 	init_MUTEX(&priv->bap0.sem);
 	priv->bap1.select 	= dev->base_addr + awc_Select1_register;
 	priv->bap1.offset 	= dev->base_addr + awc_Offset1_register;
 	priv->bap1.data		= dev->base_addr + awc_Data1_register;
 	priv->bap1.lock 	= 0;
 	priv->bap1.status	= 0;
-	my_spin_lock_init(&priv->bap1.spinlock);
+	spin_lock_init(&priv->bap1.spinlock);
 	init_MUTEX(&priv->bap1.sem);
 	priv->sleeping_bap	= 1;
 	
 //spinlock now	init_MUTEX(&priv->command_semaphore);
-	my_spin_lock_init(&priv->command_issuing_spinlock);
-	my_spin_lock_init(&priv->both_bap_spinlock);
-	my_spin_lock_init(&priv->bap_setup_spinlock);
-	my_spin_lock_init(&priv->interrupt_spinlock);
+	spin_lock_init(&priv->command_issuing_spinlock);
+	spin_lock_init(&priv->both_bap_spinlock);
+	spin_lock_init(&priv->bap_setup_spinlock);
+	spin_lock_init(&priv->interrupt_spinlock);
 	
 	priv->command_semaphore_on = 0;
 	priv->unlock_command_postponed = 0;
@@ -3098,7 +3098,7 @@
 
  void awc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	struct net_device *dev = (struct net_device *)dev_id;
+	struct net_device *dev = dev_id;
 	struct awc_private *priv;
 	unsigned long flags;
 
@@ -3110,11 +3110,11 @@
 	
 
 	DEBUG(2, "%s: awc_interrupt \n",  dev->name);
-	my_spin_lock_irqsave(&priv->interrupt_spinlock, flags);	  
+	spin_lock_irqsave(&priv->interrupt_spinlock, flags);	  
 
 	awc_interrupt_process(dev);
 
-	my_spin_unlock_irqrestore(&priv->interrupt_spinlock, flags);	  
+	spin_unlock_irqrestore(&priv->interrupt_spinlock, flags);	  
 
 	return;
 }
diff -urN linux-2.4.7-pre6/drivers/net/at1700.c linux/drivers/net/at1700.c
--- linux-2.4.7-pre6/drivers/net/at1700.c	Wed Jun 20 11:13:18 2001
+++ linux/drivers/net/at1700.c	Mon Dec  3 22:55:49 2001
@@ -8,9 +8,10 @@
 	This software may be used and distributed according to the terms
 	of the GNU General Public License, incorporated herein by reference.
 
-	The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
-	Center of Excellence in Space Data and Information Sciences
-	   Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
+	The author may be reached as becker@scyld.com, or C/O
+	Scyld Computing Corporation
+	410 Severn Ave., Suite 210
+	Annapolis MD 21403
 
 	This is a device driver for the Allied Telesis AT1700, and
         Fujitsu FMV-181/182/181A/182A/183/184/183A/184A, which are
diff -urN linux-2.4.7-pre6/drivers/net/auto_irq.c linux/drivers/net/auto_irq.c
--- linux-2.4.7-pre6/drivers/net/auto_irq.c	Sun Sep 17 09:45:05 2000
+++ linux/drivers/net/auto_irq.c	Mon Dec  3 22:55:49 2001
@@ -2,9 +2,7 @@
 /*
     Written 1994 by Donald Becker.
 
-    The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
-    Center of Excellence in Space Data and Information Sciences
-      Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
+    The author may be reached as becker@scyld.com
 
     This code is a general-purpose IRQ line detector for devices with
     jumpered IRQ lines.  If you can make the device raise an IRQ (and
@@ -29,7 +27,7 @@
 
 #ifdef version
 static const char *version=
-"auto_irq.c:v1.11 Donald Becker (becker@cesdis.gsfc.nasa.gov)";
+"auto_irq.c:v1.11 Donald Becker (becker@scyld.com)";
 #endif
 
 #include <linux/module.h>
diff -urN linux-2.4.7-pre6/drivers/net/bsd_comp.c linux/drivers/net/bsd_comp.c
--- linux-2.4.7-pre6/drivers/net/bsd_comp.c	Tue Feb 13 13:15:04 2001
+++ linux/drivers/net/bsd_comp.c	Mon Dec  3 22:55:49 2001
@@ -185,7 +185,7 @@
 static int	bsd_decompress (void *state, unsigned char *ibuf, int isize,
 				unsigned char *obuf, int osize);
 
-/* These are in ppp.c */
+/* These are in ppp_generic.c */
 extern int  ppp_register_compressor   (struct compressor *cp);
 extern void ppp_unregister_compressor (struct compressor *cp);
 
@@ -1158,7 +1158,7 @@
  * Module support routines
  *************************************************************/
 
-int bsdcomp_init(void)
+int __init bsdcomp_init(void)
 {
 	int answer = ppp_register_compressor(&ppp_bsd_compress);
 	if (answer == 0)
@@ -1166,7 +1166,7 @@
 	return answer;
 }
 
-void bsdcomp_cleanup(void)
+void __exit bsdcomp_cleanup(void)
 {
 	ppp_unregister_compressor(&ppp_bsd_compress);
 }
diff -urN linux-2.4.7-pre6/drivers/net/de600.c linux/drivers/net/de600.c
--- linux-2.4.7-pre6/drivers/net/de600.c	Wed Jun 20 11:10:53 2001
+++ linux/drivers/net/de600.c	Mon Dec  3 22:55:49 2001
@@ -16,7 +16,7 @@
  *
  *	Adapted to the sample network driver core for linux,
  *	written by: Donald Becker <becker@super.org>
- *	C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
+ *		(Now at <becker@scyld.com>)
  *
  *	compile-command:
  *	"gcc -D__KERNEL__  -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer \
diff -urN linux-2.4.7-pre6/drivers/net/de620.c linux/drivers/net/de620.c
--- linux-2.4.7-pre6/drivers/net/de620.c	Wed Jun 20 11:10:53 2001
+++ linux/drivers/net/de620.c	Mon Dec  3 22:55:49 2001
@@ -13,7 +13,7 @@
  *
  *	Adapted to the sample network driver core for linux,
  *	written by: Donald Becker <becker@super.org>
- *		(Now at <becker@cesdis.gsfc.nasa.gov>
+ *		(Now at <becker@scyld.com>)
  *
  *	Valuable assistance from:
  *		J. Joshua Kopper <kopper@rtsg.mot.com>
diff -urN linux-2.4.7-pre6/drivers/net/dl2k.c linux/drivers/net/dl2k.c
--- linux-2.4.7-pre6/drivers/net/dl2k.c	Mon Dec  3 22:55:41 2001
+++ linux/drivers/net/dl2k.c	Mon Dec  3 22:55:49 2001
@@ -84,6 +84,8 @@
 	int err, irq = pdev->irq;
 	long ioaddr;
 	static int version_printed;
+	void *ring_space;
+	dma_addr_t ring_dma;
 
 	if (!version_printed++)
 		printk ("%s", version);
@@ -119,6 +121,7 @@
 	dev->irq = irq;
 	np = dev->priv;
 	np->chip_id = chip_idx;
+	np->pdev = pdev;
 	spin_lock_init (&np->lock);
 
 	/* Parse manual configuration */
@@ -181,13 +184,25 @@
 #endif
 	pci_set_drvdata (pdev, dev);
 
+	ring_space = pci_alloc_consistent(pdev, TX_TOTAL_SIZE, &ring_dma);
+	if (!ring_space)
+		goto err_out_iounmap;
+	np->tx_ring = (struct netdev_desc *)ring_space;
+	np->tx_ring_dma = ring_dma;
+
+	ring_space = pci_alloc_consistent(pdev, RX_TOTAL_SIZE, &ring_dma);
+	if (!ring_space)
+		goto err_out_unmap_tx;
+	np->rx_ring = (struct netdev_desc *)ring_space;
+	np->rx_ring_dma = ring_dma;
+
 	/* Parse eeprom data */
 	parse_eeprom (dev);
 
 	/* Find PHY address */
 	err = find_miiphy (dev);
 	if (err)
-		goto err_out_unmap;
+		goto err_out_unmap_rx;
 
 	/* Set media and reset PHY */
 	mii_set_media (dev);
@@ -198,7 +213,7 @@
 
 	err = register_netdev (dev);
 	if (err)
-		goto err_out_unmap;
+		goto err_out_unmap_rx;
 
 	card_idx++;
 
@@ -209,7 +224,11 @@
 		irq);
 	return 0;
 
-err_out_unmap:
+err_out_unmap_rx:
+        pci_free_consistent(pdev, RX_TOTAL_SIZE, np->rx_ring, np->rx_ring_dma);
+err_out_unmap_tx:
+        pci_free_consistent(pdev, TX_TOTAL_SIZE, np->tx_ring, np->tx_ring_dma);
+err_out_iounmap:
 #ifndef USE_IO_OPS
 	iounmap ((void *) ioaddr);
 
@@ -253,7 +272,7 @@
 parse_eeprom (struct net_device *dev)
 {
 	int i, j;
-	int ioaddr = dev->base_addr;
+	long ioaddr = dev->base_addr;
 	u8 sromdata[256];
 	u8 *psib;
 	u32 crc;
@@ -335,7 +354,7 @@
 	writel (readl (ioaddr + DebugCtrl) | 0x0230, ioaddr + DebugCtrl);
 
 	/* Jumbo frame */
-	if (jumbo != 0)
+	if (np->jumbo != 0)
 		writew (9014, ioaddr + MaxFrameSize);
 
 	alloc_list (dev);
@@ -400,7 +419,6 @@
 	np->cur_rx = np->cur_tx = 0;
 	np->old_rx = np->old_tx = 0;
 	np->rx_buf_sz = (dev->mtu <= 1500 ? PACKET_SIZE : dev->mtu + 32);
-	np->rx_head_desc = &np->rx_ring[0];
 
 	/* Initialize Tx descriptors, TFDListPtr leaves in start_xmit(). */
 	for (i = 0; i < TX_RING_SIZE; i++) {
@@ -410,16 +428,13 @@
 
 	/* Initialize Rx descriptors */
 	for (i = 0; i < RX_RING_SIZE; i++) {
-		np->rx_ring[i].next_desc =
-		    virt_to_le64desc (&np->rx_ring[i + 1]);
+		np->rx_ring[i].next_desc = cpu_to_le64(np->rx_ring_dma +
+			((i+1)%RX_RING_SIZE)*sizeof(struct netdev_desc));
 		np->rx_ring[i].status = 0;
 		np->rx_ring[i].fraginfo = 0;
 		np->rx_skbuff[i] = 0;
 	}
 
-	/* Chain the next pointer to the top */
-	np->rx_ring[i - 1].next_desc = virt_to_le64desc (&np->rx_ring[0]);
-
 	/* Allocate the rx buffers */
 	for (i = 0; i < RX_RING_SIZE; i++) {
 		/* Allocated fixed size of skbuff */
@@ -434,13 +449,14 @@
 		skb->dev = dev;	/* Mark as being used by this device. */
 		skb_reserve (skb, 2);	/* 16 byte align the IP header. */
 		/* Rubicon now supports 40 bits of addressing space. */
-		np->rx_ring[i].fraginfo = virt_to_le64desc (skb->tail);
+		np->rx_ring[i].fraginfo = cpu_to_le64(pci_map_single(
+			np->pdev, skb->tail, np->rx_buf_sz, 
+			PCI_DMA_FROMDEVICE));
 		np->rx_ring[i].fraginfo |= cpu_to_le64 (np->rx_buf_sz) << 48;
 	}
 
 	/* Set RFDListPtr */
-	writel (cpu_to_le32 (virt_to_bus (&np->rx_ring[0])),
-		dev->base_addr + RFDListPtr0);
+	writel (cpu_to_le32 (np->rx_ring_dma), dev->base_addr + RFDListPtr0);
 	writel (0, dev->base_addr + RFDListPtr1);
 
 	return;
@@ -453,6 +469,8 @@
 	struct netdev_desc *txdesc;
 	unsigned entry;
 	u32 ioaddr;
+	int tx_shift;
+	unsigned flags;
 
 	ioaddr = dev->base_addr;
 	entry = np->cur_tx % TX_RING_SIZE;
@@ -472,21 +490,23 @@
 	}
 #endif
 	if (np->vlan) {
-		txdesc->status |= cpu_to_le64 (VLANTagInsert |
-					       cpu_to_le64 (vlan) << 32 |
-					       cpu_to_le64 (skb->
-							    priority) << 45);
+		txdesc->status |=
+			cpu_to_le64 (VLANTagInsert) |
+			(cpu_to_le64 (np->vlan) << 32) |
+			(cpu_to_le64 (skb->priority) << 45);
 	}
 
 	/* Send one packet each time at 10Mbps mode */
 	if (entry % 0x08 == 0 || np->speed == 10)
 		txdesc->status |= cpu_to_le64 (TxIndicate);
-	txdesc->fraginfo = virt_to_le64desc (skb->data);
+	txdesc->fraginfo = cpu_to_le64 (pci_map_single(np->pdev, skb->data, 
+		skb->len, PCI_DMA_TODEVICE));
 	txdesc->fraginfo |= cpu_to_le64 (skb->len) << 48;
 
 	/* Chain the last descriptor's pointer to this one */
 	if (np->last_tx)
-		np->last_tx->next_desc = virt_to_le64desc (txdesc);
+		np->last_tx->next_desc = cpu_to_le64 (np->tx_ring_dma +
+			entry*sizeof(struct netdev_desc));
 	np->last_tx = txdesc;
 
 	/* Clear TFDDone, then TxDMA start to send this descriptor */
@@ -507,11 +527,19 @@
 
 	/* The first TFDListPtr */
 	if (readl (dev->base_addr + TFDListPtr0) == 0) {
-		writel (virt_to_bus (&np->tx_ring[entry]),
+		writel (np->tx_ring_dma + entry*sizeof(struct netdev_desc),
 			dev->base_addr + TFDListPtr0);
 		writel (0, dev->base_addr + TFDListPtr1);
 	}
-
+	
+	spin_lock_irqsave (&np->lock, flags);
+	if (np->old_tx > TX_RING_SIZE) {
+		tx_shift = TX_RING_SIZE;
+		np->old_tx -= tx_shift;
+		np->cur_tx -= tx_shift;
+	}
+	spin_unlock_irqrestore (&np->lock, flags);	
+	
 	/* NETDEV WATCHDOG timer */
 	dev->trans_start = jiffies;
 	return 0;
@@ -561,9 +589,14 @@
 		/* Free used tx skbuffs */
 		for (; np->cur_tx - np->old_tx > 0; np->old_tx++) {
 			int entry = np->old_tx % TX_RING_SIZE;
+			struct sk_buff *skb;
+
 			if (!(np->tx_ring[entry].status & TFDDone))
 				break;
-			dev_kfree_skb_irq (np->tx_skbuff[entry]);
+			skb = np->tx_skbuff[entry];
+                	pci_unmap_single(np->pdev, np->tx_ring[entry].fraginfo,
+				skb->len, PCI_DMA_TODEVICE);
+			dev_kfree_skb_irq (skb);
 			np->tx_skbuff[entry] = 0;
 		}
 		/* If the ring is no longer full, clear tx_full and 
@@ -617,7 +650,7 @@
 			mdelay (1);
 		}
 		/* Reset TFDListPtr */
-		writel (virt_to_bus (&np->tx_ring[frame_id]),
+		writel (np->tx_ring_dma + frame_id*sizeof(struct netdev_desc),
 			dev->base_addr + TFDListPtr0);
 		writel (0, dev->base_addr + TFDListPtr1);
 
@@ -657,19 +690,33 @@
 	struct netdev_private *np = (struct netdev_private *) dev->priv;
 	int entry = np->cur_rx % RX_RING_SIZE;
 	int cnt = np->old_rx + RX_RING_SIZE - np->cur_rx;
+	int rx_shift;
 
+	if (np->old_rx > RX_RING_SIZE) {
+		rx_shift = RX_RING_SIZE;
+		np->old_rx -= rx_shift;
+		np->cur_rx -= rx_shift;
+	}
 	DEBUG_RFD_DUMP (np, 1);
 	/* If RFDDone, FrameStart and FrameEnd set, there is a new packet in. */
-	while (np->rx_head_desc->status & RFDDone &&
-	       np->rx_head_desc->status & FrameStart &&
-	       np->rx_head_desc->status & FrameEnd) {
-		struct netdev_desc *desc = np->rx_head_desc;
-		u64 frame_status = le64_to_cpu (desc->status);
-		int pkt_len = le64_to_cpu (desc->status & 0xffff);	/* Chip omits the CRC. */
+	while (1) {
+		struct netdev_desc *desc = &np->rx_ring[entry];
+		int pkt_len;
+		u64 frame_status; 
+
+		if (!(desc->status & RFDDone) || 
+			!(desc->status & FrameStart) ||
+			!(desc->status & FrameEnd))
+			break;
 
+		/* Chip omits the CRC. */
+		pkt_len = le64_to_cpu (desc->status & 0xffff);	
+		frame_status = le64_to_cpu (desc->status);
 		if (--cnt < 0)
 			break;
 		DEBUG_PKT_DUMP (np, pkt_len);
+                pci_dma_sync_single(np->pdev, desc->fraginfo, np->rx_buf_sz,
+			PCI_DMA_FROMDEVICE);
 		/* Update rx error statistics, drop packet. */
 		if (frame_status & 0x003f0000) {
 			np->stats.rx_errors++;
@@ -683,13 +730,17 @@
 				np->stats.rx_crc_errors++;
 		} else {
 			struct sk_buff *skb;
+
 			/* Small skbuffs for short packets */
 			if (pkt_len > copy_thresh) {
+                		pci_unmap_single(np->pdev, desc->fraginfo,
+					np->rx_buf_sz, PCI_DMA_FROMDEVICE);
 				skb_put (skb = np->rx_skbuff[entry], pkt_len);
 				np->rx_skbuff[entry] = NULL;
 			} else if ((skb = dev_alloc_skb (pkt_len + 2)) != NULL) {
 				skb->dev = dev;
-				skb_reserve (skb, 2);	/* 16 byte align the IP header */
+				/* 16 byte align the IP header */
+				skb_reserve (skb, 2);
 				eth_copy_and_sum (skb,
 						  np->rx_skbuff[entry]->tail,
 						  pkt_len, 0);
@@ -706,7 +757,6 @@
 			dev->last_rx = jiffies;
 		}
 		entry = (++np->cur_rx) % RX_RING_SIZE;
-		np->rx_head_desc = &np->rx_ring[entry];
 	}
 
 	/* Re-allocate skbuffs to fill the descriptor ring */
@@ -725,9 +775,11 @@
 			}
 			np->rx_skbuff[entry] = skb;
 			skb->dev = dev;
-			skb_reserve (skb, 2);	/* 16 byte align the IP header */
-			np->rx_ring[entry].fraginfo =
-			    virt_to_le64desc (skb->tail);
+			/* 16 byte align the IP header */
+			skb_reserve (skb, 2);
+			np->rx_ring[entry].fraginfo = cpu_to_le64(pci_map_single(
+				np->pdev, skb->tail, np->rx_buf_sz, 
+				PCI_DMA_FROMDEVICE));
 		}
 		np->rx_ring[entry].fraginfo |=
 		    cpu_to_le64 (np->rx_buf_sz) << 48;
@@ -843,7 +895,8 @@
 int
 change_mtu (struct net_device *dev, int new_mtu)
 {
-	int max = (jumbo) ? 9000 : 1536;
+	struct netdev_private *np = dev->priv;
+	int max = (np->jumbo) ? 9000 : 1536;
 
 	if ((new_mtu < 68) || (new_mtu > max)) {
 		return -EINVAL;
@@ -960,18 +1013,19 @@
 		netif_wake_queue (dev);
 		break;
 	case SIOCDEVPRIVATE + 7:
-		printk ("tx_full=%x cur_tx=%x old_tx=%x cur_rx=%x old_rx=%x\n",
-			(u32) np->tx_full, (u32) np->cur_tx, (u32) np->old_tx,
-			(u32) np->cur_rx, (u32) np->old_rx);
+		printk ("tx_full=%x cur_tx=%lx old_tx=%lx cur_rx=%lx old_rx=%lx\n",
+			np->tx_full, np->cur_tx, np->old_tx,
+			np->cur_rx, np->old_rx);
 		break;
 	case SIOCDEVPRIVATE + 8:
 		for (i = 0; i < TX_RING_SIZE; i++) {
 			desc = &np->tx_ring[i];
 			printk
-			    ("cur:%08x next:%08x status:%08x frag1:%08x frag0:%08x",
-			     (u32) virt_to_bus (desc), (u32) desc->next_desc,
-			     (u32) desc->status, (u32) (desc->fraginfo >> 32),
-			     (u32) desc->fraginfo);
+				("cur:%08x next:%08x status:%08x frag1:%08x frag0:%08x",
+				(u32) (np->tx_ring_dma + i*sizeof(*desc)),
+				(u32) desc->next_desc,
+				(u32) desc->status, (u32) (desc->fraginfo >> 32),
+				(u32) desc->fraginfo);
 			printk ("\n");
 		}
 		printk ("\n");
@@ -1101,7 +1155,7 @@
 static void
 mii_sendbit (struct net_device *dev, u32 data)
 {
-	int ioaddr = dev->base_addr + PhyCtrl;
+	long ioaddr = dev->base_addr + PhyCtrl;
 	data = (data) ? MII_DATA1 : 0;
 	data |= MII_WRITE;
 	data |= (readb (ioaddr) & 0xf8) | MII_WRITE;
@@ -1114,7 +1168,7 @@
 static int
 mii_getbit (struct net_device *dev)
 {
-	int ioaddr = dev->base_addr + PhyCtrl;
+	long ioaddr = dev->base_addr + PhyCtrl;
 	u8 data;
 
 	data = (readb (ioaddr) & 0xf8) | MII_READ;
@@ -1363,6 +1417,7 @@
 {
 	long ioaddr = dev->base_addr;
 	struct netdev_private *np = dev->priv;
+	struct sk_buff *skb;
 	int i;
 
 	netif_stop_queue (dev);
@@ -1379,15 +1434,22 @@
 	for (i = 0; i < RX_RING_SIZE; i++) {
 		np->rx_ring[i].status = 0;
 		np->rx_ring[i].fraginfo = 0;
-		if (np->rx_skbuff[i]) {
-			dev_kfree_skb (np->rx_skbuff[i]);
+		skb = np->rx_skbuff[i];
+		if (skb) {
+                	pci_unmap_single(np->pdev, np->rx_ring[i].fraginfo, 
+				skb->len, PCI_DMA_FROMDEVICE);
+			dev_kfree_skb (skb);
+			np->rx_skbuff[i] = 0;
 		}
-		np->rx_skbuff[i] = 0;
 	}
 	for (i = 0; i < TX_RING_SIZE; i++) {
-		if (np->tx_skbuff[i])
-			dev_kfree_skb (np->tx_skbuff[i]);
-		np->tx_skbuff[i] = 0;
+		skb = np->tx_skbuff[i];
+		if (skb) {
+                	pci_unmap_single(np->pdev, np->tx_ring[i].fraginfo, 
+				skb->len, PCI_DMA_TODEVICE);
+			dev_kfree_skb (skb);
+			np->tx_skbuff[i] = 0;
+		}
 	}
 	return 0;
 }
@@ -1396,8 +1458,15 @@
 rio_remove1 (struct pci_dev *pdev)
 {
 	struct net_device *dev = pci_get_drvdata (pdev);
+
 	if (dev) {
+		struct netdev_private *np = dev->priv;
+
 		unregister_netdev (dev);
+        	pci_free_consistent(pdev, RX_TOTAL_SIZE, np->rx_ring, 
+			np->rx_ring_dma);
+        	pci_free_consistent(pdev, TX_TOTAL_SIZE, np->tx_ring, 
+			np->tx_ring_dma);
 #ifndef USE_IO_OPS
 		iounmap ((char *) (dev->base_addr));
 #endif
diff -urN linux-2.4.7-pre6/drivers/net/dl2k.h linux/drivers/net/dl2k.h
--- linux-2.4.7-pre6/drivers/net/dl2k.h	Mon Dec  3 22:55:41 2001
+++ linux/drivers/net/dl2k.h	Mon Dec  3 22:55:49 2001
@@ -35,9 +35,9 @@
 #define TX_RING_SIZE	16
 #define TX_QUEUE_LEN	10	/* Limit ring entries actually used.  */
 #define RX_RING_SIZE	16
+#define TX_TOTAL_SIZE	TX_RING_SIZE*sizeof(struct netdev_desc)
+#define RX_TOTAL_SIZE	RX_RING_SIZE*sizeof(struct netdev_desc)
 
-#define virt_to_le64desc(addr)  cpu_to_le64(virt_to_bus(addr))
-#define le64desc_to_virt(addr)  bus_to_virt(le64_to_cpu(addr))
 /* This driver was written to use PCI memory space, however x86-oriented
    hardware often uses I/O space accesses. */
 #ifdef USE_IO_OPS
@@ -570,15 +570,15 @@
    within the structure. */
 struct netdev_private {
 	/* Descriptor rings first for alignment. */
-	struct netdev_desc rx_ring[RX_RING_SIZE];
-	struct netdev_desc tx_ring[TX_RING_SIZE];
-	/* The addresses of receive-in-place skbuffs. */
+	struct netdev_desc *rx_ring;
+	struct netdev_desc *tx_ring;
 	struct sk_buff *rx_skbuff[RX_RING_SIZE];
-	/* The saved address of a sent-in-place packet/buffer, for later free(). */
 	struct sk_buff *tx_skbuff[TX_RING_SIZE];
-	struct net_device_stats stats;
+	dma_addr_t tx_ring_dma;
+	dma_addr_t rx_ring_dma;
+	struct pci_dev * pdev;
 	spinlock_t lock;
-	struct netdev_desc *rx_head_desc;
+	struct net_device_stats stats;
 	unsigned int rx_buf_sz;	/* Based on MTU+slack. */
 	unsigned int tx_full:1;	/* The Tx queue is full. */
 	unsigned int full_duplex:1;	/* Full-duplex operation requested. */
@@ -588,8 +588,8 @@
 	unsigned int chip_id;	/* PCI table chip id */
 	unsigned int jumbo;
 	struct netdev_desc *last_tx;	/* Last Tx descriptor used. */
-	u64 cur_rx, old_rx;	/* Producer/consumer ring indices */
-	u64 cur_tx, old_tx;
+	unsigned long cur_rx, old_rx;	/* Producer/consumer ring indices */
+	unsigned long cur_tx, old_tx;
 	int wake_polarity;
 	char name[256];		/* net device description */
 	u8 duplex_polarity;
@@ -649,10 +649,11 @@
 		for (i = 0; i < TX_RING_SIZE; i++) {
 			desc = &np->tx_ring[i];
 			printk
-			    ("cur:%08x next:%08x status:%08x frag1:%08x frag0:%08x",
-			     (u32) virt_to_bus (desc), (u32) desc->next_desc,
-			     (u32) desc->status, (u32) (desc->fraginfo >> 32),
-			     (u32) desc->fraginfo);
+				("cur:%08x next:%08x status:%08x frag1:%08x frag0:%08x",
+				(u32) np->tx_ring_dma + i*sizeof(*desc),
+				(u32) desc->next_desc, (u32) desc->status, 
+				(u32) (desc->fraginfo >> 32),
+				(u32) desc->fraginfo);
 			printk ("\n");
 		}
 		printk ("\n");
@@ -669,10 +670,11 @@
 		for (i = 0; i < RX_RING_SIZE; i++) {
 			desc = &np->rx_ring[i];
 			printk
-			    ("cur:%08x next:%08x status:%08x frag1:%08x frag0:%08x",
-			     (u32) virt_to_bus (desc), (u32) desc->next_desc,
-			     (u32) desc->status, (u32) (desc->fraginfo >> 32),
-			     (u32) desc->fraginfo);
+				("cur:%08x next:%08x status:%08x frag1:%08x frag0:%08x",
+				(u32) np->rx_ring_dma + i*sizeof(*desc),
+				(u32) desc->next_desc, (u32) desc->status, 
+				(u32) (desc->fraginfo >> 32),
+				(u32) desc->fraginfo);
 			printk ("\n");
 		}
 		printk ("\n");
@@ -700,18 +702,20 @@
 static inline void
 debug_pkt_dump (struct netdev_private *np, int pkt_len)
 {
-	int i;
-	struct netdev_desc *desc = np->rx_head_desc;
+	int entry = np->cur_rx % RX_RING_SIZE;
+	struct netdev_desc *desc = &np->rx_ring[entry];
+	u64 frame_status = le64_to_cpu (desc->status);
 	unsigned char *pchar;
 	unsigned char *phead;
-	u64 frame_status = le64_to_cpu (desc->status);
+	int i;
 
 	if (np->rx_debug == 4) {
 		printk ("  rcv_pkt: status was %4.4x %4.4x.\n",
 			(u32) (frame_status >> 32), (u32) frame_status);
 	}
 	if (np->rx_debug == 7) {
-		phead = le64desc_to_virt ((desc->fraginfo & 0xffffffffff));
+		
+		phead = bus_to_virt(le64_to_cpu(desc->fraginfo & 0xffffffffff));
 		for (pchar = phead, i = 0; i < pkt_len; i++, pchar++) {
 			printk ("%02x ", *pchar);
 			if ((i + 1) % 20 == 0)
diff -urN linux-2.4.7-pre6/drivers/net/e2100.c linux/drivers/net/e2100.c
--- linux-2.4.7-pre6/drivers/net/e2100.c	Wed Jun 20 11:10:53 2001
+++ linux/drivers/net/e2100.c	Mon Dec  3 22:55:49 2001
@@ -10,8 +10,10 @@
 
 	This is a driver for the Cabletron E2100 series ethercards.
 
-	The Author may be reached as becker@cesdis.gsfc.nasa.gov, or
-	C/O Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
+	The Author may be reached as becker@scyld.com, or C/O
+	Scyld Computing Corporation
+	410 Severn Ave., Suite 210
+	Annapolis MD 21403
 
 	The E2100 series ethercard is a fairly generic shared memory 8390
 	implementation.  The only unusual aspect is the way the shared memory
diff -urN linux-2.4.7-pre6/drivers/net/epic100.c linux/drivers/net/epic100.c
--- linux-2.4.7-pre6/drivers/net/epic100.c	Mon Dec  3 22:55:41 2001
+++ linux/drivers/net/epic100.c	Mon Dec  3 22:55:49 2001
@@ -48,13 +48,16 @@
 	* ethtool driver info support (jgarzik)
 
 	LK1.1.9:
-	* MII ioctl support (jgarzik)
+	* ethtool media get/set support (jgarzik)
+
+	LK1.1.10:
+	* revert MII transceiver init change (jgarzik)
 
 */
 
 #define DRV_NAME	"epic100"
-#define DRV_VERSION	"1.11+LK1.1.9"
-#define DRV_RELDATE	"July 2, 2001"
+#define DRV_VERSION	"1.11+LK1.1.10"
+#define DRV_RELDATE	"July 6, 2001"
 
 
 /* The user-configurable values.
@@ -448,7 +451,7 @@
 	outl(0x0008, ioaddr + TEST1);
 
 	/* Turn on the MII transceiver. */
-	outl(dev->if_port == 1 ? 0x13 : 0x12, ioaddr + MIICfg);
+	outl(0x12, ioaddr + MIICfg);
 	if (chip_idx == 1)
 		outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
 	outl(0x0200, ioaddr + GENCTL);
@@ -670,7 +673,9 @@
 	   required by the details of which bits are reset and the transceiver
 	   wiring on the Ositech CardBus card.
 	*/
+#if 0
 	outl(dev->if_port == 1 ? 0x13 : 0x12, ioaddr + MIICfg);
+#endif
 	if (ep->chip_flags & MII_PWRDWN)
 		outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
 
diff -urN linux-2.4.7-pre6/drivers/net/eth16i.c linux/drivers/net/eth16i.c
--- linux-2.4.7-pre6/drivers/net/eth16i.c	Mon Dec  3 22:55:41 2001
+++ linux/drivers/net/eth16i.c	Mon Dec  3 22:55:49 2001
@@ -28,7 +28,7 @@
    
    Sources:
      - skeleton.c  a sample network driver core for linux,
-       written by Donald Becker <becker@CESDIS.gsfc.nasa.gov>
+       written by Donald Becker <becker@scyld.com>
      - at1700.c a driver for Allied Telesis AT1700, written 
        by Donald Becker.
      - e16iSRV.asm a Netware 3.X Server Driver for ICL EtherTeam16i
diff -urN linux-2.4.7-pre6/drivers/net/fmv18x.c linux/drivers/net/fmv18x.c
--- linux-2.4.7-pre6/drivers/net/fmv18x.c	Wed Jun 20 11:10:53 2001
+++ linux/drivers/net/fmv18x.c	Mon Dec  3 22:55:49 2001
@@ -3,9 +3,10 @@
 	Original: at1700.c (1993-94 by Donald Becker).
 		Copyright 1993 United States Government as represented by the
 		Director, National Security Agency.
-		The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
-		Center of Excellence in Space Data and Information Sciences
-		   Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
+		The author may be reached as becker@scyld.com, or C/O
+			Scyld Computing Corporation
+			410 Severn Ave., Suite 210
+			Annapolis MD 21403
 
 	Modified by Yutaka TAMIYA (tamy@flab.fujitsu.co.jp)
 		Copyright 1994 Fujitsu Laboratories Ltd.
diff -urN linux-2.4.7-pre6/drivers/net/hamachi.c linux/drivers/net/hamachi.c
--- linux-2.4.7-pre6/drivers/net/hamachi.c	Mon Jul  2 14:03:04 2001
+++ linux/drivers/net/hamachi.c	Mon Dec  3 22:55:49 2001
@@ -125,6 +125,8 @@
 */
 #define TX_RING_SIZE	64
 #define RX_RING_SIZE	512
+#define TX_TOTAL_SIZE	TX_RING_SIZE*sizeof(struct hamachi_desc)
+#define RX_TOTAL_SIZE	RX_RING_SIZE*sizeof(struct hamachi_desc)
 
 /*
  * Enable netdev_ioctl.  Added interrupt coalescing parameter adjustment.
@@ -207,10 +209,9 @@
 
 /* Condensed bus+endian portability operations. */
 #if ADDRLEN == 64
-#define virt_to_desc(addr)  cpu_to_le64(virt_to_bus(addr))
+#define cpu_to_leXX(addr)	cpu_to_le64(addr)
 #else 
-#define virt_to_desc(addr)  cpu_to_le32(virt_to_bus(addr))
-#define le32desc_to_virt(addr)  bus_to_virt(le32_to_cpu(addr))
+#define cpu_to_leXX(addr)	cpu_to_le32(addr)
 #endif   
 
 
@@ -485,31 +486,30 @@
 	DescIntr=0x10000000,
 };
 
-#define PRIV_ALIGN   15    				/* Required alignment mask */
+#define PRIV_ALIGN	15  			/* Required alignment mask */
 #define MII_CNT		4
 struct hamachi_private {
 	/* Descriptor rings first for alignment.  Tx requires a second descriptor
 	   for status. */
-	struct hamachi_desc rx_ring[RX_RING_SIZE];
-	struct hamachi_desc tx_ring[TX_RING_SIZE];
-	/* The addresses of receive-in-place skbuffs. */
+	struct hamachi_desc *rx_ring;
+	struct hamachi_desc *tx_ring;
 	struct sk_buff* rx_skbuff[RX_RING_SIZE];
-	/* The saved address of a sent-in-place packet/buffer, for skfree(). */
 	struct sk_buff* tx_skbuff[TX_RING_SIZE];
+	dma_addr_t tx_ring_dma;
+	dma_addr_t rx_ring_dma;
 	struct net_device_stats stats;
-	struct timer_list timer;				/* Media selection timer. */
+	struct timer_list timer;		/* Media selection timer. */
 	/* Frequently used and paired value: keep adjacent for cache effect. */
 	spinlock_t lock;
 	int chip_id;
-	struct hamachi_desc *rx_head_desc;
 	unsigned int cur_rx, dirty_rx;		/* Producer/consumer ring indices */
 	unsigned int cur_tx, dirty_tx;
-	unsigned int rx_buf_sz;					/* Based on MTU+slack. */
-	unsigned int tx_full:1;					/* The Tx queue is full. */
-	unsigned int full_duplex:1;			/* Full-duplex operation requested. */
+	unsigned int rx_buf_sz;			/* Based on MTU+slack. */
+	unsigned int tx_full:1;			/* The Tx queue is full. */
+	unsigned int full_duplex:1;		/* Full-duplex operation requested. */
 	unsigned int duplex_lock:1;
-	unsigned int medialock:1;				/* Do not sense media. */
-	unsigned int default_port:4;			/* Last dev->if_port value. */
+	unsigned int medialock:1;		/* Do not sense media. */
+	unsigned int default_port:4;		/* Last dev->if_port value. */
 	/* MII transceiver section. */
 	int mii_cnt;								/* MII device addresses. */
 	u16 advertising;							/* NWay media advertisement */
@@ -580,6 +580,9 @@
 	long ioaddr;
 	static int card_idx;
 	struct net_device *dev;
+	void *ring_space;
+	dma_addr_t ring_dma;
+	int ret = -ENOMEM;
 
 /* when built into the kernel, we only print version if device is found */
 #ifndef MODULE
@@ -588,8 +591,10 @@
 		printk(version);
 #endif
 
-	if (pci_enable_device(pdev))
-		return -EIO;
+	if (pci_enable_device(pdev)) {
+		ret = -EIO;
+		goto err_out;
+	}
 
 	ioaddr = pci_resource_start(pdev, 0);
 #ifdef __alpha__				/* Really "64 bit addrs" */
@@ -603,17 +608,13 @@
 
 	irq = pdev->irq;
 	ioaddr = (long) ioremap(ioaddr, 0x400);
-	if (!ioaddr) {
-		pci_release_regions(pdev);
-		return -ENOMEM;
-	}
+	if (!ioaddr)
+		goto err_out_release;
 
 	dev = alloc_etherdev(sizeof(struct hamachi_private));
-	if (!dev) {
-		pci_release_regions(pdev);
-		iounmap((char *)ioaddr);
-		return -ENOMEM;
-	}
+	if (!dev)
+		goto err_out_iounmap;
+
 	SET_MODULE_OWNER(dev);
 
 #ifdef TX_CHECKSUM
@@ -635,6 +636,18 @@
 	hmp = dev->priv;
 	spin_lock_init(&hmp->lock);
 
+	ring_space = pci_alloc_consistent(pdev, TX_TOTAL_SIZE, &ring_dma);
+	if (!ring_space)
+		goto err_out_cleardev;
+	hmp->tx_ring = (struct hamachi_desc *)ring_space;
+	hmp->tx_ring_dma = ring_dma;
+
+	ring_space = pci_alloc_consistent(pdev, RX_TOTAL_SIZE, &ring_dma);
+	if (!ring_space)
+		goto err_out_unmap_tx;
+	hmp->rx_ring = (struct hamachi_desc *)ring_space;
+	hmp->rx_ring_dma = ring_dma;
+
 	/* Check for options being passed in */
 	option = card_idx < MAX_UNITS ? options[card_idx] : 0;
 	if (dev->mem_start)
@@ -715,11 +728,8 @@
 
 	i = register_netdev(dev);
 	if (i) {
-		kfree(dev);
-		iounmap((char *)ioaddr);
-		pci_release_regions(pdev);
-		pci_set_drvdata(pdev, NULL);
-		return i;
+		ret = i;
+		goto err_out_unmap_rx;
 	}
 
 	printk(KERN_INFO "%s: %s type %x at 0x%lx, ",
@@ -757,6 +767,21 @@
 
 	card_idx++;
 	return 0;
+
+err_out_unmap_rx:
+	pci_free_consistent(pdev, RX_TOTAL_SIZE, hmp->rx_ring, 
+		hmp->rx_ring_dma);
+err_out_unmap_tx:
+	pci_free_consistent(pdev, TX_TOTAL_SIZE, hmp->tx_ring, 
+		hmp->tx_ring_dma);
+err_out_cleardev:
+	kfree (dev);
+err_out_iounmap:
+	iounmap((char *)ioaddr);
+err_out_release:
+	pci_release_regions(pdev);
+err_out:
+	return ret;
 }
 
 static int read_eeprom(long ioaddr, int location)
@@ -833,13 +858,14 @@
 	hamachi_init_ring(dev);
 
 #if ADDRLEN == 64
-	writel(virt_to_bus(hmp->rx_ring), ioaddr + RxPtr);
-	writel(virt_to_bus(hmp->rx_ring) >> 32, ioaddr + RxPtr + 4);
-	writel(virt_to_bus(hmp->tx_ring), ioaddr + TxPtr);
-	writel(virt_to_bus(hmp->tx_ring) >> 32, ioaddr + TxPtr + 4);
+	/* writellll anyone ? */
+	writel(cpu_to_le64(hmp->rx_ring_dma), ioaddr + RxPtr);
+	writel(cpu_to_le64(hmp->rx_ring_dma) >> 32, ioaddr + RxPtr + 4);
+	writel(cpu_to_le64(hmp->tx_ring_dma), ioaddr + TxPtr);
+	writel(cpu_to_le64(hmp->tx_ring_dma) >> 32, ioaddr + TxPtr + 4);
 #else
-	writel(virt_to_bus(hmp->rx_ring), ioaddr + RxPtr);
-	writel(virt_to_bus(hmp->tx_ring), ioaddr + TxPtr);
+	writel(cpu_to_le32(hmp->rx_ring_dma), ioaddr + RxPtr);
+	writel(cpu_to_le32(hmp->tx_ring_dma), ioaddr + TxPtr);
 #endif
 
 	/* TODO:  It would make sense to organize this as words since the card 
@@ -970,11 +996,17 @@
 		still owned by the card */
 	for (; hmp->cur_tx - hmp->dirty_tx > 0; hmp->dirty_tx++) {
 		int entry = hmp->dirty_tx % TX_RING_SIZE;
+		struct sk_buff *skb;
+
 		if (hmp->tx_ring[entry].status_n_length & cpu_to_le32(DescOwn)) 
 			break;
 		/* Free the original skb. */
-		if (hmp->tx_skbuff[entry] != 0) {
-			dev_kfree_skb(hmp->tx_skbuff[entry]);
+		skb = hmp->tx_skbuff[entry];
+		if (skb != 0) {
+			pci_unmap_single(hmp->pci_dev, 
+				hmp->tx_ring[entry].addr, skb->len, 
+				PCI_DMA_TODEVICE);
+			dev_kfree_skb(skb);
 			hmp->tx_skbuff[entry] = 0;
 		}
 		hmp->tx_ring[entry].status_n_length = 0;
@@ -1021,18 +1053,16 @@
 	printk(KERN_WARNING "%s: Hamachi transmit timed out, status %8.8x,"
 		   " resetting...\n", dev->name, (int)readw(ioaddr + TxStatus));
 
-#ifndef __alpha__
 	{
 		int i;
-		printk(KERN_DEBUG "  Rx ring %8.8x: ", (int)hmp->rx_ring);
+		printk(KERN_DEBUG "  Rx ring %p: ", hmp->rx_ring);
 		for (i = 0; i < RX_RING_SIZE; i++)
 			printk(" %8.8x", (unsigned int)hmp->rx_ring[i].status_n_length);
-		printk("\n"KERN_DEBUG"  Tx ring %8.8x: ", (int)hmp->tx_ring);
+		printk("\n"KERN_DEBUG"  Tx ring %p: ", hmp->tx_ring);
 		for (i = 0; i < TX_RING_SIZE; i++)
 			printk(" %4.4x", hmp->tx_ring[i].status_n_length);
 		printk("\n");
 	}
-#endif
 
 	/* Reinit the hardware and make sure the Rx and Tx processes 
 		are up and running.
@@ -1046,19 +1076,25 @@
 	 */
 	
 	for (i = 0; i < RX_RING_SIZE; i++)
-		hmp->rx_ring[i].status_n_length &= ~DescOwn;
+		hmp->rx_ring[i].status_n_length &= cpu_to_le32(~DescOwn);
 
 	/* Presume that all packets in the Tx queue are gone if we have to
 	 * re-init the hardware.
 	 */
 	for (i = 0; i < TX_RING_SIZE; i++){
+		struct sk_buff *skb;
+
 		if (i >= TX_RING_SIZE - 1)
-			hmp->tx_ring[i].status_n_length = DescEndRing |
-				(hmp->tx_ring[i].status_n_length & 0x0000FFFF);
+			hmp->tx_ring[i].status_n_length = cpu_to_le32(
+				DescEndRing |
+				(hmp->tx_ring[i].status_n_length & 0x0000FFFF));
 		else	
 			hmp->tx_ring[i].status_n_length &= 0x0000ffff;
-		if (hmp->tx_skbuff[i]){
-			dev_kfree_skb(hmp->tx_skbuff[i]);
+		skb = hmp->tx_skbuff[i];
+		if (skb){
+			pci_unmap_single(hmp->pci_dev, hmp->tx_ring[i].addr, 
+				skb->len, PCI_DMA_TODEVICE);
+			dev_kfree_skb(skb);
 			hmp->tx_skbuff[i] = 0;
 		}
 	}
@@ -1071,13 +1107,16 @@
 	hmp->tx_full = 0;
 	hmp->cur_rx = hmp->cur_tx = 0;
 	hmp->dirty_rx = hmp->dirty_tx = 0;
-	hmp->rx_head_desc = &hmp->rx_ring[0];
 	/* Rx packets are also presumed lost; however, we need to make sure a
 	 * ring of buffers is in tact. -KDU
 	 */ 
 	for (i = 0; i < RX_RING_SIZE; i++){
-		if (hmp->rx_skbuff[i]){
-			dev_kfree_skb(hmp->rx_skbuff[i]);
+		struct sk_buff *skb = hmp->rx_skbuff[i];
+
+		if (skb){
+			pci_unmap_single(hmp->pci_dev, hmp->rx_ring[i].addr, 
+				hmp->rx_buf_sz, PCI_DMA_FROMDEVICE);
+			dev_kfree_skb(skb);
 			hmp->rx_skbuff[i] = 0;
 		}
 	}
@@ -1089,9 +1128,10 @@
 			break;
 		skb->dev = dev;         /* Mark as being used by this device. */
 		skb_reserve(skb, 2); /* 16 byte align the IP header. */
-		hmp->rx_ring[i].addr = virt_to_desc(skb->tail);
-		hmp->rx_ring[i].status_n_length =
-			cpu_to_le32(DescOwn | DescEndPacket | DescIntr | (hmp->rx_buf_sz - 2));
+                hmp->rx_ring[i].addr = cpu_to_leXX(pci_map_single(hmp->pci_dev, 
+			skb->tail, hmp->rx_buf_sz, PCI_DMA_FROMDEVICE));
+		hmp->rx_ring[i].status_n_length = cpu_to_le32(DescOwn | 
+			DescEndPacket | DescIntr | (hmp->rx_buf_sz - 2));
 	}
 	hmp->dirty_rx = (unsigned int)(i - RX_RING_SIZE);
 	/* Mark the last entry as wrapping the ring. */
@@ -1136,8 +1176,6 @@
 	hmp->rx_buf_sz = (dev->mtu <= 1492 ? PKT_BUF_SZ : 
 		(((dev->mtu+26+7) & ~7) + 2 + 16));
 
-	hmp->rx_head_desc = &hmp->rx_ring[0];
-
 	/* Initialize all Rx descriptors. */
 	for (i = 0; i < RX_RING_SIZE; i++) {
 		hmp->rx_ring[i].status_n_length = 0;
@@ -1151,24 +1189,20 @@
 			break;
 		skb->dev = dev;         /* Mark as being used by this device. */
 		skb_reserve(skb, 2); /* 16 byte align the IP header. */
-		hmp->rx_ring[i].addr = virt_to_desc(skb->tail);
+                hmp->rx_ring[i].addr = cpu_to_leXX(pci_map_single(hmp->pci_dev, 
+			skb->tail, hmp->rx_buf_sz, PCI_DMA_FROMDEVICE));
 		/* -2 because it doesn't REALLY have that first 2 bytes -KDU */
-		hmp->rx_ring[i].status_n_length =
-			cpu_to_le32(DescOwn | DescEndPacket | DescIntr | (hmp->rx_buf_sz -2));
+		hmp->rx_ring[i].status_n_length = cpu_to_le32(DescOwn | 
+			DescEndPacket | DescIntr | (hmp->rx_buf_sz -2));
 	}
 	hmp->dirty_rx = (unsigned int)(i - RX_RING_SIZE);
-	/* Mark the last entry as wrapping the ring. */
 	hmp->rx_ring[RX_RING_SIZE-1].status_n_length |= cpu_to_le32(DescEndRing);
 
-
-	/* Mark the last entry as wrapping the ring. */
-	hmp->rx_ring[RX_RING_SIZE-1].status_n_length |= DescEndRing;
-
 	for (i = 0; i < TX_RING_SIZE; i++) {
 		hmp->tx_skbuff[i] = 0;
 		hmp->tx_ring[i].status_n_length = 0;
 	}
-	/* Mark the last entry as wrapping the ring. */
+	/* Mark the last entry of the ring */
 	hmp->tx_ring[TX_RING_SIZE-1].status_n_length |= cpu_to_le32(DescEndRing);
 
 	return;
@@ -1270,7 +1304,8 @@
 	}
 #endif
 
-	hmp->tx_ring[entry].addr = virt_to_desc(skb->data);
+        hmp->tx_ring[entry].addr = cpu_to_leXX(pci_map_single(hmp->pci_dev, 
+		skb->data, skb->len, PCI_DMA_TODEVICE));
     
 	/* Hmmmm, could probably put a DescIntr on these, but the way
 		the driver is currently coded makes Tx interrupts unnecessary
@@ -1282,11 +1317,11 @@
 		mitigating interrupt frequency with the tx_min_pkt parameter. -KDU
 	*/
 	if (entry >= TX_RING_SIZE-1)		 /* Wrap ring */
-		hmp->tx_ring[entry].status_n_length = 
-			cpu_to_le32(DescOwn|DescEndPacket|DescEndRing|DescIntr | skb->len);
+		hmp->tx_ring[entry].status_n_length = cpu_to_le32(DescOwn |
+			DescEndPacket | DescEndRing | DescIntr | skb->len);
 	else
-		hmp->tx_ring[entry].status_n_length = 
-			cpu_to_le32(DescOwn|DescEndPacket|DescIntr | skb->len);
+		hmp->tx_ring[entry].status_n_length = cpu_to_le32(DescOwn |
+			DescEndPacket | DescIntr | skb->len);
 	hmp->cur_tx++;
 
 	/* Non-x86 Todo: explicitly flush cache lines here. */
@@ -1361,11 +1396,18 @@
 			if (hmp->tx_full){
 				for (; hmp->cur_tx - hmp->dirty_tx > 0; hmp->dirty_tx++){
 					int entry = hmp->dirty_tx % TX_RING_SIZE;
+					struct sk_buff *skb;
+
 					if (hmp->tx_ring[entry].status_n_length & cpu_to_le32(DescOwn)) 
 						break;
+					skb = hmp->tx_skbuff[entry];
 					/* Free the original skb. */
-					if (hmp->tx_skbuff[entry]){
-						dev_kfree_skb_irq(hmp->tx_skbuff[entry]);
+					if (skb){
+						pci_unmap_single(hmp->pci_dev, 
+							hmp->tx_ring[entry].addr, 
+							skb->len,
+							PCI_DMA_TODEVICE);
+						dev_kfree_skb_irq(skb);
 						hmp->tx_skbuff[entry] = 0;
 					}
 					hmp->tx_ring[entry].status_n_length = 0;
@@ -1489,14 +1531,19 @@
 	}
 
 	/* If EOP is set on the next entry, it's a new packet. Send it up. */
-	while ( ! (hmp->rx_head_desc->status_n_length & cpu_to_le32(DescOwn))) {
-		struct hamachi_desc *desc = hmp->rx_head_desc;
+	while (1) {
+		struct hamachi_desc *desc = &(hmp->rx_ring[entry]);
 		u32 desc_status = le32_to_cpu(desc->status_n_length);
-		u16 data_size = desc_status;			/* Implicit truncate */
-		u8 *buf_addr = le32desc_to_virt(desc->addr);
-		s32 frame_status = 
-			le32_to_cpu(get_unaligned((s32*)&(buf_addr[data_size - 12])));
+		u16 data_size = desc_status;	/* Implicit truncate */
+		u8 *buf_addr; 
+		s32 frame_status;
 		
+		if (desc_status & DescOwn)
+			break;
+		pci_dma_sync_single(hmp->pci_dev, desc->addr, hmp->rx_buf_sz, 
+			PCI_DMA_FROMDEVICE);
+		buf_addr = (u8 *)hmp->rx_ring + entry*sizeof(*desc);
+		frame_status = le32_to_cpu(get_unaligned((s32*)&(buf_addr[data_size - 12])));
 		if (hamachi_debug > 4)
 			printk(KERN_DEBUG "  hamachi_rx() status was %8.8x.\n",
 				frame_status);
@@ -1560,23 +1607,19 @@
 				skb_reserve(skb, 2);	/* 16 byte align the IP header */
 				/* Call copy + cksum if available. */
 #if 1 || USE_IP_COPYSUM
-				eth_copy_and_sum(skb, bus_to_virt(desc->addr), pkt_len, 0);
+				eth_copy_and_sum(skb, 
+					hmp->rx_skbuff[entry]->data, pkt_len, 0);
 				skb_put(skb, pkt_len);
 #else
-				memcpy(skb_put(skb, pkt_len), bus_to_virt(desc->addr),pkt_len);
+				memcpy(skb_put(skb, pkt_len), hmp->rx_ring_dma
+					+ entry*sizeof(*desc), pkt_len);
 #endif
 			} else {
-				char *temp = skb_put(skb = hmp->rx_skbuff[entry], pkt_len);
+				pci_unmap_single(hmp->pci_dev, 
+					hmp->rx_ring[entry].addr, 
+					hmp->rx_buf_sz, PCI_DMA_FROMDEVICE);
+				skb_put(skb = hmp->rx_skbuff[entry], pkt_len);
 				hmp->rx_skbuff[entry] = NULL;
-#ifndef final_version				/* Remove after testing. */
-				if (bus_to_virt(desc->addr) != temp)
-					printk(KERN_ERR "%s: Internal fault: The skbuff addresses "
-						   "do not match in hamachi_rx: %p vs. %p / %p.\n",
-						   dev->name, bus_to_virt(desc->addr),
-						   skb->head, temp);
-#else
-				(void) temp;
-#endif
 			}
 #ifdef TX_CHECKSUM
 			/* account for extra TX hard_header bytes */
@@ -1609,18 +1652,18 @@
 						p_r1 = *(p-1);
 						switch (inv) {
 							case 0:	
-										crc = (p_r & 0xffff) + (p_r >> 16);
-										break;
+								crc = (p_r & 0xffff) + (p_r >> 16);
+								break;
 							case 1:	
-										crc = (p_r >> 16) + (p_r & 0xffff)
-											+ (p_r1 >> 16 & 0xff00); 
-										break;
+								crc = (p_r >> 16) + (p_r & 0xffff)
+									+ (p_r1 >> 16 & 0xff00); 
+								break;
 							case 2:	
-										crc = p_r + (p_r1 >> 16); 
-										break;
+								crc = p_r + (p_r1 >> 16); 
+								break;
 							case 3:	
-										crc = p_r + (p_r1 & 0xff00) + (p_r1 >> 16); 
-										break;
+								crc = p_r + (p_r1 & 0xff00) + (p_r1 >> 16); 
+								break;
 							default:	/*NOTREACHED*/ crc = 0;
 						}
 						if (crc & 0xffff0000) {
@@ -1648,29 +1691,32 @@
 			hmp->stats.rx_packets++;
 		}
 		entry = (++hmp->cur_rx) % RX_RING_SIZE;
-		hmp->rx_head_desc = &hmp->rx_ring[entry];
 	}
 
 	/* Refill the Rx ring buffers. */
 	for (; hmp->cur_rx - hmp->dirty_rx > 0; hmp->dirty_rx++) {
-		struct sk_buff *skb;
+		struct hamachi_desc *desc;
+
 		entry = hmp->dirty_rx % RX_RING_SIZE;
+		desc = &(hmp->rx_ring[entry]);
 		if (hmp->rx_skbuff[entry] == NULL) {
-			skb = dev_alloc_skb(hmp->rx_buf_sz);
+			struct sk_buff *skb = dev_alloc_skb(hmp->rx_buf_sz);
+
 			hmp->rx_skbuff[entry] = skb;
 			if (skb == NULL)
-				break;					/* Better luck next round. */
-			skb->dev = dev;			/* Mark as being used by this device. */
-			skb_reserve(skb, 2);		/* Align IP on 16 byte boundaries */
-			hmp->rx_ring[entry].addr = virt_to_desc(skb->tail);
+				break;		/* Better luck next round. */
+			skb->dev = dev;		/* Mark as being used by this device. */
+			skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */
+                	desc->addr = cpu_to_leXX(pci_map_single(hmp->pci_dev, 
+				skb->tail, hmp->rx_buf_sz, PCI_DMA_FROMDEVICE));
 		}
-		hmp->rx_ring[entry].status_n_length = cpu_to_le32(hmp->rx_buf_sz);
+		desc->status_n_length = cpu_to_le32(hmp->rx_buf_sz);
 		if (entry >= RX_RING_SIZE-1)
-			hmp->rx_ring[entry].status_n_length |=
-				cpu_to_le32(DescOwn | DescEndPacket | DescEndRing | DescIntr);
+			desc->status_n_length |= cpu_to_le32(DescOwn | 
+				DescEndPacket | DescEndRing | DescIntr);
 		else
-			hmp->rx_ring[entry].status_n_length |= 
-				cpu_to_le32(DescOwn | DescEndPacket | DescIntr);
+			desc->status_n_length |= cpu_to_le32(DescOwn | 
+				DescEndPacket | DescIntr);
 	}
 
 	/* Restart Rx engine if stopped. */
@@ -1721,6 +1767,7 @@
 {
 	long ioaddr = dev->base_addr;
 	struct hamachi_private *hmp = dev->priv;
+	struct sk_buff *skb;
 	int i;
 
 	netif_stop_queue(dev);
@@ -1743,22 +1790,25 @@
 #ifdef __i386__
 	if (hamachi_debug > 2) {
 		printk("\n"KERN_DEBUG"  Tx ring at %8.8x:\n",
-			   (int)virt_to_bus(hmp->tx_ring));
+			   (int)hmp->tx_ring_dma);
 		for (i = 0; i < TX_RING_SIZE; i++)
 			printk(" %c #%d desc. %8.8x %8.8x.\n",
 				   readl(ioaddr + TxCurPtr) == (long)&hmp->tx_ring[i] ? '>' : ' ',
 				   i, hmp->tx_ring[i].status_n_length, hmp->tx_ring[i].addr);
 		printk("\n"KERN_DEBUG "  Rx ring %8.8x:\n",
-			   (int)virt_to_bus(hmp->rx_ring));
+			   (int)hmp->rx_ring_dma);
 		for (i = 0; i < RX_RING_SIZE; i++) {
 			printk(KERN_DEBUG " %c #%d desc. %4.4x %8.8x\n",
 				   readl(ioaddr + RxCurPtr) == (long)&hmp->rx_ring[i] ? '>' : ' ',
 				   i, hmp->rx_ring[i].status_n_length, hmp->rx_ring[i].addr);
 			if (hamachi_debug > 6) {
-				if (*(u8*)bus_to_virt(hmp->rx_ring[i].addr) != 0x69) {
+				if (*(u8*)hmp->rx_skbuff[i]->tail != 0x69) {
+					u16 *addr = (u16 *)
+						hmp->rx_skbuff[i]->tail;
 					int j;
+
 					for (j = 0; j < 0x50; j++)
-						printk(" %4.4x",((u16*)le32desc_to_virt(hmp->rx_ring[i].addr))[j]);
+						printk(" %4.4x", addr[j]);
 					printk("\n");
 				}
 			}
@@ -1772,17 +1822,26 @@
 
 	/* Free all the skbuffs in the Rx queue. */
 	for (i = 0; i < RX_RING_SIZE; i++) {
+		skb = hmp->rx_skbuff[i];
 		hmp->rx_ring[i].status_n_length = 0;
 		hmp->rx_ring[i].addr = 0xBADF00D0; /* An invalid address. */
-		if (hmp->rx_skbuff[i]) {
-			dev_kfree_skb(hmp->rx_skbuff[i]);
+		if (skb) {
+			pci_unmap_single(hmp->pci_dev, 
+				hmp->rx_ring[i].addr, hmp->rx_buf_sz, 
+				PCI_DMA_FROMDEVICE);
+			dev_kfree_skb(skb);
+			hmp->rx_skbuff[i] = 0;
 		}
-		hmp->rx_skbuff[i] = 0;
 	}
 	for (i = 0; i < TX_RING_SIZE; i++) {
-		if (hmp->tx_skbuff[i])
-			dev_kfree_skb(hmp->tx_skbuff[i]);
-		hmp->tx_skbuff[i] = 0;
+		skb = hmp->tx_skbuff[i];
+		if (skb) {
+			pci_unmap_single(hmp->pci_dev, 
+				hmp->tx_ring[i].addr, skb->len, 
+				PCI_DMA_TODEVICE);
+			dev_kfree_skb(skb);
+			hmp->tx_skbuff[i] = 0;
+		}
 	}
 
 	writeb(0x00, ioaddr + LEDCtrl);
@@ -1849,7 +1908,7 @@
 
 static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr)
 {
-	struct hamachi_private *np = dev->priv;
+	struct hamachi_private *hmp = dev->priv;
 	u32 ethcmd;
 		
 	if (copy_from_user(&ethcmd, useraddr, sizeof(ethcmd)))
@@ -1860,7 +1919,7 @@
 		struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO};
 		strcpy(info.driver, DRV_NAME);
 		strcpy(info.version, DRV_VERSION);
-		strcpy(info.bus_info, np->pci_dev->slot_name);
+		strcpy(info.bus_info, hmp->pci_dev->slot_name);
 		if (copy_to_user(useraddr, &info, sizeof(info)))
 			return -EFAULT;
 		return 0;
@@ -1926,6 +1985,12 @@
 
 	/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
 	if (dev) {
+		struct hamachi_private *hmp = dev->priv;
+
+		pci_free_consistent(pdev, RX_TOTAL_SIZE, hmp->rx_ring, 
+			hmp->rx_ring_dma);
+		pci_free_consistent(pdev, TX_TOTAL_SIZE, hmp->tx_ring, 
+			hmp->tx_ring_dma);
 		unregister_netdev(dev);
 		iounmap((char *)dev->base_addr);
 		kfree(dev);
diff -urN linux-2.4.7-pre6/drivers/net/hp-plus.c linux/drivers/net/hp-plus.c
--- linux-2.4.7-pre6/drivers/net/hp-plus.c	Wed Jun 20 11:10:53 2001
+++ linux/drivers/net/hp-plus.c	Mon Dec  3 22:55:49 2001
@@ -8,10 +8,10 @@
 	This software may be used and distributed according to the terms
 	of the GNU General Public License, incorporated herein by reference.
 
-	The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
-
-	Center of Excellence in Space Data and Information Sciences
-		Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
+	The author may be reached as becker@scyld.com, or C/O
+	Scyld Computing Corporation
+	410 Severn Ave., Suite 210
+	Annapolis MD 21403
 
 	As is often the case, a great deal of credit is owed to Russ Nelson.
 	The Crynwr packet driver was my primary source of HP-specific
diff -urN linux-2.4.7-pre6/drivers/net/hp.c linux/drivers/net/hp.c
--- linux-2.4.7-pre6/drivers/net/hp.c	Wed Jun 20 11:10:53 2001
+++ linux/drivers/net/hp.c	Mon Dec  3 22:55:49 2001
@@ -8,9 +8,10 @@
 	This software may be used and distributed according to the terms
 	of the GNU General Public License, incorporated herein by reference.
 
-	The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
-	Center of Excellence in Space Data and Information Sciences
-	   Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
+	The author may be reached as becker@scyld.com, or C/O
+	Scyld Computing Corporation
+	410 Severn Ave., Suite 210
+	Annapolis MD 21403
 
 	This is a driver for the HP PC-LAN adaptors.
 
diff -urN linux-2.4.7-pre6/drivers/net/ioc3-eth.c linux/drivers/net/ioc3-eth.c
--- linux-2.4.7-pre6/drivers/net/ioc3-eth.c	Mon Dec  3 22:55:41 2001
+++ linux/drivers/net/ioc3-eth.c	Mon Dec  3 22:55:49 2001
@@ -66,18 +66,6 @@
  */
 #define RX_BUFFS 64
 
-/*
- * Private ioctls that de facto are well known and used for example
- * by mii-tool.  These are deprecated and will go away in 2.5.0.
- */
-#define SIOCGMIIPHY (SIOCDEVPRIVATE)	/* Read from current PHY */
-#define SIOCGMIIREG (SIOCDEVPRIVATE+1)	/* Read any PHY register */
-#define SIOCSMIIREG (SIOCDEVPRIVATE+2)	/* Write any PHY register */
-
-/* These exist in other drivers; we don't use them at this time.  */
-#define SIOCGPARAMS (SIOCDEVPRIVATE+3)	/* Read operational parameters */
-#define SIOCSPARAMS (SIOCDEVPRIVATE+4)	/* Set operational parameters */
-
 /* Timer state engine. */
 enum ioc3_timer_state {
 	arbwait  = 0,	/* Waiting for auto negotiation to complete.          */
@@ -1513,7 +1501,7 @@
 	struct ioc3 *ioc3 = ip->regs;
 
 	iounmap(ioc3);
-	/* pci_release_regions(pdev);  Will be used in 2.4.3 */
+	pci_release_regions(pdev);
 	kfree(dev);
 }
 
diff -urN linux-2.4.7-pre6/drivers/net/isa-skeleton.c linux/drivers/net/isa-skeleton.c
--- linux-2.4.7-pre6/drivers/net/isa-skeleton.c	Thu Apr 12 12:15:25 2001
+++ linux/drivers/net/isa-skeleton.c	Mon Dec  3 22:55:49 2001
@@ -8,9 +8,10 @@
  *	This software may be used and distributed according to the terms
  *	of the GNU General Public License, incorporated herein by reference.
  *
- *	The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
- *	Center of Excellence in Space Data and Information Sciences
- *	   Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
+ *	The author may be reached as becker@scyld.com, or C/O
+ *	Scyld Computing Corporation
+ *	410 Severn Ave., Suite 210
+ *	Annapolis MD 21403
  *
  *	This file is an outline for writing a network device driver for the
  *	the Linux operating system.
diff -urN linux-2.4.7-pre6/drivers/net/lance.c linux/drivers/net/lance.c
--- linux-2.4.7-pre6/drivers/net/lance.c	Wed Jun 20 11:10:53 2001
+++ linux/drivers/net/lance.c	Mon Dec  3 22:55:49 2001
@@ -10,9 +10,10 @@
 	This driver is for the Allied Telesis AT1500 and HP J2405A, and should work
 	with most other LANCE-based bus-master (NE2100/NE2500) ethercards.
 
-	The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
-	Center of Excellence in Space Data and Information Sciences
-	   Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
+	The author may be reached as becker@scyld.com, or C/O
+	Scyld Computing Corporation
+	410 Severn Ave., Suite 210
+	Annapolis MD 21403
 
 	Andrey V. Savochkin:
 	- alignment problem with 1.3.* kernel and some minor changes.
diff -urN linux-2.4.7-pre6/drivers/net/lasi_82596.c linux/drivers/net/lasi_82596.c
--- linux-2.4.7-pre6/drivers/net/lasi_82596.c	Mon Jul  2 14:03:04 2001
+++ linux/drivers/net/lasi_82596.c	Mon Dec  3 22:55:49 2001
@@ -63,8 +63,8 @@
    according to the terms of the GNU General Public License as modified by SRC,
    incorporated herein by reference.
 
-   The author may be reached as becker@super.org or
-   C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
+   The author may be reached as becker@scyld.com, or C/O
+   Scyld Computing Corporation, 410 Severn Ave., Suite 210, Annapolis MD 21403
 
  */
 
diff -urN linux-2.4.7-pre6/drivers/net/loopback.c linux/drivers/net/loopback.c
--- linux-2.4.7-pre6/drivers/net/loopback.c	Wed Apr 18 14:40:06 2001
+++ linux/drivers/net/loopback.c	Mon Dec  3 22:55:49 2001
@@ -9,7 +9,7 @@
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
- *		Donald Becker, <becker@cesdis.gsfc.nasa.gov>
+ *		Donald Becker, <becker@scyld.com>
  *
  *		Alan Cox	:	Fixed oddments for NET3.014
  *		Alan Cox	:	Rejig for NET3.029 snap #3
diff -urN linux-2.4.7-pre6/drivers/net/lp486e.c linux/drivers/net/lp486e.c
--- linux-2.4.7-pre6/drivers/net/lp486e.c	Mon Dec  3 22:55:41 2001
+++ linux/drivers/net/lp486e.c	Mon Dec  3 22:55:49 2001
@@ -10,8 +10,10 @@
 	distributed according to the terms of the GNU Public License
 	as modified by SRC, incorporated herein by reference.
 
-        The author may be reached as becker@super.org or
-        C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
+        The author may be reached as becker@scyld.com, or C/O
+	Scyld Computing Corporation
+	410 Severn Ave., Suite 210
+	Annapolis MD 21403
 
     Apricot
         Written 1994 by Mark Evans.
diff -urN linux-2.4.7-pre6/drivers/net/natsemi.c linux/drivers/net/natsemi.c
--- linux-2.4.7-pre6/drivers/net/natsemi.c	Thu Jun 21 14:28:39 2001
+++ linux/drivers/net/natsemi.c	Mon Dec  3 22:55:49 2001
@@ -153,6 +153,7 @@
 #include <linux/ethtool.h>
 #include <linux/delay.h>
 #include <linux/rtnetlink.h>
+#include <linux/mii.h>
 #include <asm/processor.h>		/* Processor type for cache alignment. */
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -737,11 +738,12 @@
 	   of the 100Mbit autodetection circuitry.  Also, we only want to do
 	   this for rev C of the chip.
 
-	   There seems to be a typo on page 78: the fixup should be performed
-	   for "DP83815CVNG (SRR = 203h)", but the description of the
-	   SiliconRev regsiters says "DP83815CVNG: 00000302h"
+	   There seems to be a typo on page 78, but there isn't.  The fixup 
+	   should be performed for "DP83815CVNG (SRR = 203h)", which is a 
+	   pretty old rev.  This is not to be confused with 302h, which is 
+	   current.  Confirmed with engineers at NSC.
 	*/
-	if (readl(ioaddr + SiliconRev) == 0x302) {
+	if (readl(ioaddr + SiliconRev) == 0x203) {
 		writew(0x0001, ioaddr + PGSEL);
 		writew(0x189C, ioaddr + PMDCSR);
 		writew(0x0000, ioaddr + TSTDAT);
@@ -1035,14 +1037,13 @@
 		/* The ring is no longer full, wake queue. */
 		netif_wake_queue(dev);
 	}
-	spin_unlock(&np->lock);
-
 }
+
 /* The interrupt handler does all of the Rx thread work and cleans up
    after the Tx thread. */
 static void intr_handler(int irq, void *dev_instance, struct pt_regs *rgs)
 {
-	struct net_device *dev = (struct net_device *)dev_instance;
+	struct net_device *dev = dev_instance;
 	struct netdev_private *np;
 	long ioaddr;
 	int boguscnt = max_interrupt_work;
@@ -1335,8 +1336,8 @@
 	}
 	writel(rx_mode, ioaddr + RxFilterAddr);
 	np->cur_rx_mode = rx_mode;
-	spin_unlock_irq(&np->lock);
 }
+
 static void set_rx_mode(struct net_device *dev)
 {
 	struct netdev_private *np = dev->priv;
@@ -1372,23 +1373,28 @@
 static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
 	struct netdev_private *np = dev->priv;
-	u16 *data = (u16 *)&rq->ifr_data;
+	struct mii_ioctl_data *data = (struct mii_ioctl_data *)&rq->ifr_data;
 
 	switch(cmd) {
 	case SIOCETHTOOL:
 		return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
-	case SIOCDEVPRIVATE:		/* Get the address of the PHY in use. */
-		data[0] = 1;
+	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
+	case SIOCDEVPRIVATE:		/* for binary compat, remove in 2.5 */
+		data->phy_id = 1;
 		/* Fall Through */
-	case SIOCDEVPRIVATE+1:		/* Read the specified MII register. */
-		data[3] = mdio_read(dev, data[0] & 0x1f, data[1] & 0x1f);
+
+	case SIOCGMIIREG:		/* Read MII PHY register. */
+	case SIOCDEVPRIVATE+1:		/* for binary compat, remove in 2.5 */
+		data->val_out = mdio_read(dev, data->phy_id & 0x1f, data->reg_num & 0x1f);
 		return 0;
-	case SIOCDEVPRIVATE+2:		/* Write the specified MII register */
+
+	case SIOCSMIIREG:		/* Write MII PHY register. */
+	case SIOCDEVPRIVATE+2:		/* for binary compat, remove in 2.5 */
 		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
-		if (data[0] == 1) {
-			u16 miireg = data[1] & 0x1f;
-			u16 value = data[2];
+		if (data->phy_id == 1) {
+			u16 miireg = data->reg_num & 0x1f;
+			u16 value = data->val_in;
 			writew(value, dev->base_addr + 0x80 + (miireg << 2));
 			switch (miireg) {
 			case 4: np->advertising = value; break;
diff -urN linux-2.4.7-pre6/drivers/net/ne.c linux/drivers/net/ne.c
--- linux-2.4.7-pre6/drivers/net/ne.c	Wed Jun 20 11:10:53 2001
+++ linux/drivers/net/ne.c	Mon Dec  3 22:55:49 2001
@@ -8,9 +8,8 @@
     This software may be used and distributed according to the terms
     of the GNU General Public License, incorporated herein by reference.
 
-    The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
-    Center of Excellence in Space Data and Information Sciences
-        Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
+    The author may be reached as becker@scyld.com, or C/O
+    Scyld Computing Corporation, 410 Severn Ave., Suite 210, Annapolis MD 21403
 
     This driver should work with many programmed-I/O 8390-based ethernet
     boards.  Currently it supports the NE1000, NE2000, many clones,
diff -urN linux-2.4.7-pre6/drivers/net/net_init.c linux/drivers/net/net_init.c
--- linux-2.4.7-pre6/drivers/net/net_init.c	Wed May 16 10:25:39 2001
+++ linux/drivers/net/net_init.c	Mon Dec  3 22:55:49 2001
@@ -2,9 +2,10 @@
 /*
 	Written 1993,1994,1995 by Donald Becker.
 
-	The author may be reached as becker@cesdis.gsfc.nasa.gov or
-	C/O Center of Excellence in Space Data and Information Sciences
-		Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
+	The author may be reached as becker@scyld.com, or C/O
+	Scyld Computing Corporation
+	410 Severn Ave., Suite 210
+	Annapolis MD 21403
 
 	This file contains the initialization for the "pl14+" style ethernet
 	drivers.  It should eventually replace most of drivers/net/Space.c.
diff -urN linux-2.4.7-pre6/drivers/net/pcmcia/3c574_cs.c linux/drivers/net/pcmcia/3c574_cs.c
--- linux-2.4.7-pre6/drivers/net/pcmcia/3c574_cs.c	Wed Apr 18 14:40:05 2001
+++ linux/drivers/net/pcmcia/3c574_cs.c	Mon Dec  3 22:55:49 2001
@@ -1,7 +1,7 @@
 /* 3c574.c: A PCMCIA ethernet driver for the 3com 3c574 "RoadRunner".
 
 	Written 1993-1998 by
-	Donald Becker, becker@cesdis.gsfc.nasa.gov, (driver core) and
+	Donald Becker, becker@scyld.com, (driver core) and
 	David Hinds, dahinds@users.sourceforge.net (from his PC card code).
 
 	This software may be used and distributed according to the terms of
@@ -16,7 +16,7 @@
 
 /* Driver author info must always be in the binary.  Version too.. */
 static const char *tc574_version =
-"3c574_cs.c v1.08 9/24/98 Donald Becker/David Hinds, becker@cesdis.gsfc.nasa.gov.\n";
+"3c574_cs.c v1.08 9/24/98 Donald Becker/David Hinds, becker@scyld.com.\n";
 
 /*
 				Theory of Operation
@@ -217,7 +217,7 @@
 MODULE_PARM(pc_debug, "i");
 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
 static char *version =
-"3c574_cs.c 1.000 1998/1/8 Donald Becker, becker@cesdis.gsfc.nasa.gov.\n";
+"3c574_cs.c 1.000 1998/1/8 Donald Becker, becker@scyld.com.\n";
 #else
 #define DEBUG(n, args...)
 #endif
diff -urN linux-2.4.7-pre6/drivers/net/pcmcia/3c589_cs.c linux/drivers/net/pcmcia/3c589_cs.c
--- linux-2.4.7-pre6/drivers/net/pcmcia/3c589_cs.c	Wed Apr 18 14:40:05 2001
+++ linux/drivers/net/pcmcia/3c589_cs.c	Mon Dec  3 22:55:49 2001
@@ -13,7 +13,7 @@
     Director, National Security Agency.  This software may be used and
     distributed according to the terms of the GNU General Public License,
     incorporated herein by reference.
-    Donald Becker may be reached at becker@cesdis1.gsfc.nasa.gov
+    Donald Becker may be reached at becker@scyld.com
 
 ======================================================================*/
 
diff -urN linux-2.4.7-pre6/drivers/net/pcmcia/fmvj18x_cs.c linux/drivers/net/pcmcia/fmvj18x_cs.c
--- linux-2.4.7-pre6/drivers/net/pcmcia/fmvj18x_cs.c	Wed Apr 18 14:40:05 2001
+++ linux/drivers/net/pcmcia/fmvj18x_cs.c	Mon Dec  3 22:55:49 2001
@@ -21,9 +21,9 @@
     This software may be used and distributed according to the terms
     of the GNU General Public License, incorporated herein by reference.
     
-    The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
-    Center of Excellence in Space Data and Information Sciences
-    Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
+    The author may be reached as becker@scyld.com, or C/O
+    Scyld Computing Corporation
+    410 Severn Ave., Suite 210, Annapolis MD 21403
     
 ======================================================================*/
 
diff -urN linux-2.4.7-pre6/drivers/net/pcmcia/nmclan_cs.c linux/drivers/net/pcmcia/nmclan_cs.c
--- linux-2.4.7-pre6/drivers/net/pcmcia/nmclan_cs.c	Wed Apr 18 14:40:05 2001
+++ linux/drivers/net/pcmcia/nmclan_cs.c	Mon Dec  3 22:55:49 2001
@@ -27,7 +27,7 @@
   Tom Pollard, New Media Corporation
   Dean Siasoyco, New Media Corporation
   Ken Lesniak, Silicon Graphics, Inc. <lesniak@boston.sgi.com>
-  Donald Becker <becker@cesdis1.gsfc.nasa.gov>
+  Donald Becker <becker@scyld.com>
   David Hinds <dahinds@users.sourceforge.net>
 
   The Linux client driver is based on the 3c589_cs.c client driver by
diff -urN linux-2.4.7-pre6/drivers/net/pcmcia/pcnet_cs.c linux/drivers/net/pcmcia/pcnet_cs.c
--- linux-2.4.7-pre6/drivers/net/pcmcia/pcnet_cs.c	Fri Apr 20 11:54:22 2001
+++ linux/drivers/net/pcmcia/pcnet_cs.c	Mon Dec  3 22:55:49 2001
@@ -20,7 +20,7 @@
     Director, National Security Agency.  This software may be used and
     distributed according to the terms of the GNU General Public License,
     incorporated herein by reference.
-    Donald Becker may be reached at becker@cesdis1.gsfc.nasa.gov
+    Donald Becker may be reached at becker@scyld.com.
 
     Based also on Keith Moore's changes to Don Becker's code, for IBM
     CCAE support.  Drivers merged back together, and shared-memory
diff -urN linux-2.4.7-pre6/drivers/net/pcmcia/smc91c92_cs.c linux/drivers/net/pcmcia/smc91c92_cs.c
--- linux-2.4.7-pre6/drivers/net/pcmcia/smc91c92_cs.c	Wed Apr 18 14:40:05 2001
+++ linux/drivers/net/pcmcia/smc91c92_cs.c	Mon Dec  3 22:55:49 2001
@@ -11,7 +11,7 @@
     smc91c92_cs.c 1.106 2001/02/07 00:19:58
     
     This driver contains code written by Donald Becker
-    (becker@cesdis.gsfc.nasa.gov), Rowan Hughes (x-csrdh@jcu.edu.au),
+    (becker@scyld.com), Rowan Hughes (x-csrdh@jcu.edu.au),
     David Hinds (dahinds@users.sourceforge.net), and Erik Stahlman
     (erik@vt.edu).  Donald wrote the SMC 91c92 code using parts of
     Erik's SMC 91c94 driver.  Rowan wrote a similar driver, and I've
@@ -60,7 +60,7 @@
 static int pc_debug = PCMCIA_DEBUG;
 MODULE_PARM(pc_debug, "i");
 static const char *version =
-"smc91c92_cs.c 0.09 1996/8/4 Donald Becker, becker@cesdis.gsfc.nasa.gov.\n";
+"smc91c92_cs.c 0.09 1996/8/4 Donald Becker, becker@scyld.com.\n";
 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
 #else
 #define DEBUG(n, args...)
diff -urN linux-2.4.7-pre6/drivers/net/pcmcia/xircom_tulip_cb.c linux/drivers/net/pcmcia/xircom_tulip_cb.c
--- linux-2.4.7-pre6/drivers/net/pcmcia/xircom_tulip_cb.c	Wed Jun 20 11:16:01 2001
+++ linux/drivers/net/pcmcia/xircom_tulip_cb.c	Mon Dec  3 22:55:49 2001
@@ -9,17 +9,17 @@
 	It should work with most DEC 21*4*-based chips/ethercards, as well as
 	with work-alike chips from Lite-On (PNIC) and Macronix (MXIC) and ASIX.
 
-	The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
-	Center of Excellence in Space Data and Information Sciences
-	   Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
+	The author may be reached as becker@scyld.com, or C/O
+	Scyld Computing Corporation
+	410 Severn Ave., Suite 210
+	Annapolis MD 21403
 
 	Support and updates available at
 	http://cesdis.gsfc.nasa.gov/linux/drivers/tulip.html
 */
 
-#define SMP_CHECK
 #define CARDBUS 1
-static const char version[] = "xircom_tulip_cb.c:v0.91 4/14/99 becker@cesdis.gsfc.nasa.gov (modified by danilo@cs.uni-magdeburg.de for XIRCOM CBE, fixed by Doug Ledford)\n";
+static const char version[] = "xircom_tulip_cb.c:v0.91 4/14/99 becker@scyld.com (modified by danilo@cs.uni-magdeburg.de for XIRCOM CBE, fixed by Doug Ledford)\n";
 
 /* A few user-configurable values. */
 
@@ -84,11 +84,6 @@
 /* Time in jiffies before concluding the transmitter is hung. */
 #define TX_TIMEOUT  (4*HZ)
 #define PKT_BUF_SZ		1536			/* Size of each temporary Rx buffer.*/
-/* This is a mysterious value that can be written to CSR11 in the 21040 (only)
-   to support a pre-NWay full-duplex signaling mechanism using short frames.
-   No one knows what it should be, but if left at its default value some
-   10base2(!) packets trigger a full-duplex-request interrupt. */
-#define FULL_DUPLEX_MAGIC	0x6969
 
 #if !defined(__OPTIMIZE__)  ||  !defined(__KERNEL__)
 #warning  You must compile this file with the correct options!
@@ -99,32 +94,20 @@
 #include <linux/version.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
-#include <linux/skbuff.h>
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <asm/processor.h>		/* Processor type for cache alignment. */
-#include <asm/bitops.h>
-#include <asm/io.h>
-#include <asm/unaligned.h>
 
 /* Kernel compatibility defines, some common to David Hinds' PCMCIA package.
    This is only in the support-all-kernels source code. */
 
-MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
+MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
 MODULE_DESCRIPTION("Digital 21*4* Tulip ethernet driver");
 MODULE_PARM(debug, "i");
 MODULE_PARM(max_interrupt_work, "i");
-MODULE_PARM(reverse_probe, "i");
 MODULE_PARM(rx_copybreak, "i");
 MODULE_PARM(csr0, "i");
 MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
@@ -162,12 +145,6 @@
 need to be set on the board.  The system BIOS preferably should assign the
 PCI INTA signal to an otherwise unused system IRQ line.
 
-Some boards have EEPROMs tables with default media entry.  The factory default
-is usually "autoselect".  This should only be overridden when using
-transceiver connections without link beat e.g. 10base2 or AUI, or (rarely!)
-for forcing full-duplex when used with old link partners that do not do
-autonegotiation. 
-
 III. Driver operation
 
 IIIa. Ring buffers
@@ -214,42 +191,23 @@
 
 IV. Notes
 
-Thanks to Duke Kamstra of SMC for long ago providing an EtherPower board.
-Greg LaPolla at Linksys provided PNIC and other Linksys boards.
-Znyx provided a four-port card for testing.
-
 IVb. References
 
 http://cesdis.gsfc.nasa.gov/linux/misc/NWay.html
 http://www.digital.com  (search for current 21*4* datasheets and "21X4 SROM")
 http://www.national.com/pf/DP/DP83840A.html
-http://www.asix.com.tw/pmac.htm
-http://www.admtek.com.tw/
 
 IVc. Errata
 
-The old DEC databooks were light on details.
-The 21040 databook claims that CSR13, CSR14, and CSR15 should each be the last
-register of the set CSR12-15 written.  Hmmm, now how is that possible?
-
-The DEC SROM format is very badly designed not precisely defined, leading to
-part of the media selection junkheap below.  Some boards do not have EEPROM
-media tables and need to be patched up.  Worse, other boards use the DEC
-design kit media table when it isn't correct for their board.
-
 We cannot use MII interrupts because there is no defined GPIO pin to attach
 them.  The MII transceiver status is polled using an kernel timer.
 
 */
 
-/* This table use during operation for capabilities and media timer. */
-
 static void tulip_timer(unsigned long data);
 
 enum tbl_flag {
-	HAS_MII=1, HAS_MEDIA_TABLE=2, CSR12_IN_SROM=4, ALWAYS_CHECK_MII=8,
-	HAS_ACPI=0x10, MC_HASH_ONLY=0x20, /* Hash-only multicast filter. */
-	HAS_NWAY143=0x40,			/* Uses 21143-like internal NWay. */
+	HAS_MII=1, HAS_ACPI=2,
 };
 static struct tulip_chip_table {
 	char *chip_name;
@@ -262,11 +220,9 @@
        HAS_MII | HAS_ACPI, tulip_timer }, 
   {0},
 };
-/* This matches the table above.  Note 21142 == 21143. */
+/* This matches the table above. */
 enum chips {
 	X3201_3,
-	DC21040, DC21041, DC21140, DC21142=4, DC21143=4,
-	LC82C168, MX98713, MX98715, MX98725, AX88140, PNIC2, COMET, COMPEX9881,
 };
 
 /* A full-duplex map for media types. */
@@ -275,13 +231,6 @@
 	MediaIs100=16};
 static const char media_cap[] =
 {0,0,0,16,  3,19,16,24,  27,4,7,5, 0,20,23,20 };
-static u8 t21040_csr13[] = {2,0x0C,8,4,  4,0,0,0, 0,0,0,0, 4,0,0,0};
-/* 21041 transceiver register settings: 10-T, 10-2, AUI, 10-T, 10T-FD*/
-static u16 t21041_csr13[] = { 0xEF05, 0xEF09, 0xEF09, 0xEF01, 0xEF09, };
-static u16 t21041_csr14[] = { 0x7F3F, 0xF7FD, 0xF7FD, 0x7F3F, 0x7F3D, };
-static u16 t21041_csr15[] = { 0x0008, 0x0006, 0x000E, 0x0008, 0x0008, };
-
-static u16 t21142_csr14[] = { 0xFFFF, 0x0705, 0x0705, 0x0000, 0x7F3D, };
 
 /* Offsets to the Command and Status Registers, "CSRs".  All accesses
    must be longword instructions and quadword aligned. */
@@ -325,34 +274,6 @@
 */
 #define DESC_RING_WRAP 0x02000000
 
-#ifdef CARDBUS
-#define EEPROM_ADDRLEN (chip_rev == 65 ? 8 : 6)
-#else
-#define EEPROM_ADDRLEN 6
-#endif
-#define EEPROM_SIZE 128 	/* 2 << EEPROM_ADDRLEN */
-
-struct medialeaf {
-	u8 type;
-	u8 media;
-	unsigned char *leafdata;
-};
-
-struct mediatable {
-	u16 defaultmedia;
-	u8 leafcount, csr12dir;				/* General purpose pin directions. */
-	unsigned has_mii:1, has_nonmii:1, has_reset:6;
-	u32 csr15dir, csr15val;				/* 21143 NWay setting. */
-	struct medialeaf mleaf[0];
-};
-
-struct mediainfo {
-	struct mediainfo *next;
-	int info_type;
-	int index;
-	unsigned char *info;
-};
-
 struct tulip_private {
 	char devname[8];			/* Used only for kernel debugging. */
 	const char *product_name;
@@ -379,38 +300,26 @@
 	unsigned int tx_full:1;				/* The Tx queue is full. */
 	unsigned int full_duplex:1;			/* Full-duplex operation requested. */
 	unsigned int full_duplex_lock:1;
-	unsigned int fake_addr:1;			/* Multiport board faked address. */
 	unsigned int default_port:4;		/* Last dev->if_port value. */
-	unsigned int media2:4;				/* Secondary monitored media port. */
 	unsigned int medialock:1;			/* Don't sense media type. */
 	unsigned int mediasense:1;			/* Media sensing in progress. */
-	unsigned int nway:1, nwayset:1;		/* 21143 internal NWay. */
 	unsigned int open:1;
 	unsigned int csr0;					/* CSR0 setting. */
 	unsigned int csr6;					/* Current CSR6 control settings. */
-	unsigned char eeprom[EEPROM_SIZE];	/* Serial EEPROM contents. */
 	u16 to_advertise;					/* NWay capabilities advertised.  */
-	u16 lpar;							/* 21143 Link partner ability. */
 	u16 advertising[4];
 	signed char phys[4], mii_cnt;		/* MII device addresses. */
-	struct mediatable *mtable;
-	int cur_index;						/* Current media index. */
 	int saved_if_port;
 	struct pci_dev *pdev;
 	spinlock_t lock;
-	int pad0, pad1;						/* Used for 8-byte alignment */
 };
 
-static void parse_eeprom(struct net_device *dev);
-static int read_eeprom(long ioaddr, int location, int addr_len);
 static int mdio_read(struct net_device *dev, int phy_id, int location);
 static void mdio_write(struct net_device *dev, int phy_id, int location, int value);
-static void select_media(struct net_device *dev, int startup);
 static void tulip_up(struct net_device *dev);
 static void tulip_down(struct net_device *dev);
 static int tulip_open(struct net_device *dev);
 static void tulip_timer(unsigned long data);
-static void t21142_start_nway(struct net_device *dev);
 static void tulip_tx_timeout(struct net_device *dev);
 static void tulip_init_ring(struct net_device *dev);
 static int tulip_start_xmit(struct sk_buff *skb, struct net_device *dev);
@@ -433,11 +342,6 @@
     long flags;
     save_flags(flags);
     cli();
-    if (chip_idx != X3201_3) {
-		outl(newcsr6, ioaddr + CSR6);
-		restore_flags(flags);
-		return;
-    }
     newcsr6 &= 0x726cfecb; /* mask out the reserved CSR6 bits that always */
 			   /* read 0 on the Xircom cards */
     newcsr6 |= 0x320c0000; /* or in the reserved bits that always read 1 */
@@ -481,13 +385,8 @@
 	static int did_version;			/* Already printed version info. */
 	struct net_device *dev;
 	struct tulip_private *tp;
-	/* See note below on the multiport cards. */
-	static unsigned char last_phys_addr[6] = {0x00, 'L', 'i', 'n', 'u', 'x'};
-	static int last_irq;
-	static int multiport_cnt;		/* For four-port boards w/one EEPROM */
 	u8 chip_rev;
 	int i;
-	unsigned short sum;
 
 	if (tulip_debug > 0  &&  did_version++ == 0)
 		printk(KERN_INFO "%s", version);
@@ -511,34 +410,7 @@
 	   be polled, waiting for the value to be read bit serially from the
 	   EEPROM.
 	   */
-	sum = 0;
-	if (chip_idx == DC21040) {
-		outl(0, ioaddr + CSR9);		/* Reset the pointer with a dummy write. */
-		for (i = 0; i < 6; i++) {
-			int value, boguscnt = 100000;
-			do
-				value = inl(ioaddr + CSR9);
-			while (value < 0  && --boguscnt > 0);
-			dev->dev_addr[i] = value;
-			sum += value & 0xff;
-		}
-	} else if (chip_idx == LC82C168) {
-		for (i = 0; i < 3; i++) {
-			int value, boguscnt = 100000;
-			outl(0x600 | i, ioaddr + 0x98);
-			do
-				value = inl(ioaddr + CSR9);
-			while (value < 0  && --boguscnt > 0);
-			put_unaligned(le16_to_cpu(value), ((u16*)dev->dev_addr) + i);
-			sum += value & 0xffff;
-		}
-	} else if (chip_idx == COMET) {
-		/* No need to read the EEPROM. */
-		put_unaligned(inl(ioaddr + 0xA4), (u32 *)dev->dev_addr);
-		put_unaligned(inl(ioaddr + 0xA8), (u16 *)(dev->dev_addr + 4));
-		for (i = 0; i < 6; i ++)
-			sum += dev->dev_addr[i];
-	} else if (chip_idx == X3201_3) {
+	if (chip_idx == X3201_3) {
 		/* Xircom has its address stored in the CIS
 		 * we access it through the boot rom interface for now
 		 * this might not work, as the CIS is not parsed but I
@@ -574,58 +446,8 @@
 				break;
 			}
 		}
-		sum = 1; // to make check below fail!
-	} else {	/* Must be a new chip, with a serial EEPROM interface. */
-		/* We read the whole EEPROM, and sort it out later.  DEC has a
-		   specification _Digital Semiconductor 21X4 Serial ROM Format_
-		   but early vendor boards just put the address in the first six
-		   EEPROM locations. */
-		unsigned char ee_data[EEPROM_SIZE];
-		int sa_offset = 0;
-
-		for (i = 0; i < sizeof(ee_data)/2; i++)
-			((u16 *)ee_data)[i] =
-				le16_to_cpu(read_eeprom(ioaddr, i, EEPROM_ADDRLEN));
-
-		/* Detect the simple EEPROM format by the duplicated station addr. */
-		for (i = 0; i < 8; i ++)
-			if (ee_data[i] != ee_data[16+i])
-				sa_offset = 20;
-		if (ee_data[0] == 0xff  &&  ee_data[1] == 0xff &&  ee_data[2] == 0) {
-			sa_offset = 2;		/* Grrr, damn Matrox boards. */
-			multiport_cnt = 4;
-		}
-		for (i = 0; i < 6; i ++) {
-			dev->dev_addr[i] = ee_data[i + sa_offset];
-			sum += ee_data[i + sa_offset];
-		}
-	}
-	/* Lite-On boards have the address byte-swapped. */
-	if ((dev->dev_addr[0] == 0xA0  ||  dev->dev_addr[0] == 0xC0)
-		&&  dev->dev_addr[1] == 0x00)
-		for (i = 0; i < 6; i+=2) {
-			char tmp = dev->dev_addr[i];
-			dev->dev_addr[i] = dev->dev_addr[i+1];
-			dev->dev_addr[i+1] = tmp;
-		}
-	/* On the Zynx 315 Etherarray and other multiport boards only the
-	   first Tulip has an EEPROM.
-	   The addresses of the subsequent ports are derived from the first.
-	   Many PCI BIOSes also incorrectly report the IRQ line, so we correct
-	   that here as well. */
-	if (sum == 0  || sum == 6*0xff) {
-		printk(" EEPROM not present,");
-		for (i = 0; i < 5; i++)
-			dev->dev_addr[i] = last_phys_addr[i];
-		dev->dev_addr[i] = last_phys_addr[i] + 1;
-#if defined(__i386__)		/* Patch up x86 BIOS bug. */
-		if (last_irq)
-			irq = last_irq;
-#endif
 	}
 
-	last_irq = irq;
-
 	/* We do a request_region() only to register /proc/ioports info. */
 	request_region(ioaddr, tulip_tbl[chip_idx].io_size, "xircom_tulip_cb");
 
@@ -646,11 +468,8 @@
 
 	/* BugFixes: The 21143-TD hangs with PCI Write-and-Invalidate cycles.
 	   And the ASIX must have a burst limit or horrible things happen. */
-	if ( (chip_idx == DC21143  &&  chip_rev == 65) ||
-	     (chip_idx == X3201_3) )
+	if (chip_idx == X3201_3)
 		tp->csr0 &= ~0x01000000;
-	else if (chip_idx == AX88140)
-		tp->csr0 |= 0x2000;
 
 	/* The lower four bits are the media type. */
 	if (board_idx >= 0  &&  board_idx < MAX_UNITS) {
@@ -670,30 +489,14 @@
 	if (tp->full_duplex)
 		tp->full_duplex_lock = 1;
 
-	/* This is logically part of probe1(), but too complex to write inline. */
-	if (tulip_tbl[chip_idx].flags & HAS_MEDIA_TABLE)
-		parse_eeprom(dev);
-
 	if (media_cap[tp->default_port] & MediaIsMII) {
 		u16 media2advert[] = { 0x20, 0x40, 0x03e0, 0x60, 0x80, 0x100, 0x200 };
 		tp->to_advertise = media2advert[tp->default_port - 9];
 	} else
 		tp->to_advertise = 0x03e1;
 
-	if ((tulip_tbl[chip_idx].flags & ALWAYS_CHECK_MII) ||
-		(tp->mtable  &&  tp->mtable->has_mii) ||
-		( ! tp->mtable  &&  (tulip_tbl[chip_idx].flags & HAS_MII))) {
+	if (tulip_tbl[chip_idx].flags & HAS_MII) {
 		int phy, phy_idx;
-		if (tp->mtable  &&  tp->mtable->has_mii) {
-			for (i = 0; i < tp->mtable->leafcount; i++)
-				if (tp->mtable->mleaf[i].media == 11) {
-					tp->cur_index = i;
-					tp->saved_if_port = dev->if_port;
-					select_media(dev, 1);
-					dev->if_port = tp->saved_if_port;
-					break;
-				}
-		}
 		/* Find the connected MII xcvrs.
 		   Doing this in open() would allow detecting external xcvrs later,
 		   but takes much time. */
@@ -724,7 +527,7 @@
 			}
 		}
 		tp->mii_cnt = phy_idx;
-		if (tp->mtable  &&  tp->mtable->has_mii  &&  phy_idx == 0) {
+		if (phy_idx == 0) {
 			printk(KERN_INFO "xircom(%s): ***WARNING***: No MII transceiver found!\n",
 			       pdev->slot_name);
 			tp->phys[0] = 1;
@@ -747,10 +550,6 @@
 
 	/* Reset the xcvr interface and turn on heartbeat. */
 	switch (chip_idx) {
-	case DC21140: default:
-		if (tp->mtable)
-			outl(tp->mtable->csr12dir | 0x100, ioaddr + CSR12);
-		break;
 	case X3201_3:
 		outl(0x0008, ioaddr + CSR15);
 		udelay(5);  /* The delays are Xircom recommended to give the
@@ -767,8 +566,6 @@
 
 	if (register_netdev(dev)) {
 		request_region(ioaddr, tulip_tbl[chip_idx].io_size, "xircom_tulip_cb");
-		if (tp->mtable)
-			kfree(tp->mtable);
 		kfree(dev->priv);
 		kfree(dev);
 		return NULL;
@@ -777,282 +574,11 @@
 	printk(KERN_INFO "%s: %s rev %d at %#3lx,",
 	       dev->name, tulip_tbl[chip_idx].chip_name, chip_rev, ioaddr);
 	for (i = 0; i < 6; i++)
-		printk("%c%2.2X", i ? ':' : ' ',
-		       last_phys_addr[i] = dev->dev_addr[i]);
+		printk("%c%2.2X", i ? ':' : ' ', dev->dev_addr[i]);
 	printk(", IRQ %d.\n", irq);
 
 	return dev;
 }
-
-/* Serial EEPROM section. */
-/* The main routine to parse the very complicated SROM structure.
-   Search www.digital.com for "21X4 SROM" to get details.
-   This code is very complex, and will require changes to support
-   additional cards, so I'll be verbose about what is going on.
-   */
-
-/* Known cards that have old-style EEPROMs. */
-static struct fixups {
-  char *name;
-  unsigned char addr0, addr1, addr2;
-  u16 newtable[32];				/* Max length below. */
-} eeprom_fixups[] = {
-  {"Asante", 0, 0, 0x94, {0x1e00, 0x0000, 0x0800, 0x0100, 0x018c,
-						  0x0000, 0x0000, 0xe078, 0x0001, 0x0050, 0x0018 }},
-  {"SMC9332DST", 0, 0, 0xC0, { 0x1e00, 0x0000, 0x0800, 0x021f,
-							   0x0000, 0x009E, /* 10baseT */
-							   0x0903, 0x006D, /* 100baseTx */ }},
-  {"Cogent EM100", 0, 0, 0x92, { 0x1e00, 0x0000, 0x0800, 0x033f,
-								 0x0107, 0x8021, /* 100baseFx */
-								 0x0108, 0x8021, /* 100baseFx-FD */
-								 0x0103, 0x006D, /* 100baseTx */ }},
-  {"Maxtech NX-110", 0, 0, 0xE8, { 0x1e00, 0x0000, 0x0800, 0x0313,
-							   0x1001, 0x009E, /* 10base2, CSR12 0x10*/
-							   0x0000, 0x009E, /* 10baseT */
-							   0x0303, 0x006D, /* 100baseTx, CSR12 0x03 */ }},
-  {"Accton EN1207", 0, 0, 0xE8, { 0x1e00, 0x0000, 0x0800, 0x031F,
-							0x1B01, 0x0000, /* 10base2,   CSR12 0x1B */
-							0x1B03, 0x006D, /* 100baseTx, CSR12 0x1B */
-							0x0B00, 0x009E, /* 10baseT,   CSR12 0x0B */
-   }},
-  {0, 0, 0, 0, {}}};
-
-static const char * block_name[] = {"21140 non-MII", "21140 MII PHY",
- "21142 Serial PHY", "21142 MII PHY", "21143 SYM PHY", "21143 reset method"};
-
-#if defined(__i386__)			/* AKA get_unaligned() */
-#define get_u16(ptr) (*(u16 *)(ptr))
-#else
-#define get_u16(ptr) (((u8*)(ptr))[0] + (((u8*)(ptr))[1]<<8))
-#endif
-
-static void parse_eeprom(struct net_device *dev)
-{
-	/* The last media info list parsed, for multiport boards.  */
-	static struct mediatable *last_mediatable;
-	static unsigned char *last_ee_data;
-	static int controller_index;
-	struct tulip_private *tp = (struct tulip_private *)dev->priv;
-	long ioaddr = dev->base_addr;
-	unsigned char *ee_data = tp->eeprom;
-	int i;
-#ifdef CARDBUS
-	int chip_rev = tp->revision;
-#endif
-
-	tp->mtable = 0;
-	for (i = 0; i < EEPROM_SIZE/2; i++)
-		((u16 *)ee_data)[i] =
-			le16_to_cpu(read_eeprom(ioaddr, i, EEPROM_ADDRLEN));
-
-	/* Detect an old-style (SA only) EEPROM layout:
-	   memcmp(eedata, eedata+16, 8). */
-	for (i = 0; i < 8; i ++)
-		if (ee_data[i] != ee_data[16+i])
-			break;
-	if (i >= 8) {
-		if (ee_data[0] == 0xff) {
-			if (last_mediatable) {
-				controller_index++;
-				printk(KERN_INFO "%s:  Controller %d of multiport board.\n",
-					   dev->name, controller_index);
-				tp->mtable = last_mediatable;
-				ee_data = last_ee_data;
-				goto subsequent_board;
-			} else
-				printk(KERN_INFO "%s:  Missing EEPROM, this interface may "
-					   "not work correctly!\n",
-			   dev->name);
-			return;
-		}
-	  /* Do a fix-up based on the vendor half of the station address prefix. */
-	  for (i = 0; eeprom_fixups[i].name; i++) {
-		if (dev->dev_addr[0] == eeprom_fixups[i].addr0
-			&&  dev->dev_addr[1] == eeprom_fixups[i].addr1
-			&&  dev->dev_addr[2] == eeprom_fixups[i].addr2) {
-		  if (dev->dev_addr[2] == 0xE8  &&  ee_data[0x1a] == 0x55)
-			  i++;			/* An Accton EN1207, not an outlaw Maxtech. */
-		  memcpy(ee_data + 26, eeprom_fixups[i].newtable,
-				 sizeof(eeprom_fixups[i].newtable));
-		  printk(KERN_INFO "%s: Old format EEPROM on '%s' board.  Using"
-				 " substitute media control info.\n",
-				 dev->name, eeprom_fixups[i].name);
-		  break;
-		}
-	  }
-	  if (eeprom_fixups[i].name == NULL) { /* No fixup found. */
-		  printk(KERN_INFO "%s: Old style EEPROM with no media selection "
-				 "information.\n",
-			   dev->name);
-		return;
-	  }
-	}
-
-	controller_index = 0;
-	if (ee_data[19] > 1) {		/* Multiport board. */
-		last_ee_data = ee_data;
-	}
-subsequent_board:
-
-	if (ee_data[27] == 0) {		/* No valid media table. */
-	} else if (tp->chip_id == DC21041) {
-		unsigned char *p = (void *)ee_data + ee_data[27 + controller_index*3];
-		short media;
-		int count;
-
-		media = get_u16(p);
-		p += 2;
-		count = *p++;
-
-		printk(KERN_INFO "%s:21041 Media information at %d, default media "
-			   "%4.4x (%s).\n", dev->name, ee_data[27], media,
-			   media & 0x0800 ? "Autosense" : medianame[media & 15]);
-		for (i = 0; i < count; i++) {
-			unsigned char media_code = *p++;
-			u16 csrvals[3];
-			int idx;
-			for (idx = 0; idx < 3; idx++) {
-				csrvals[idx] = get_u16(p);
-				p += 2;
-			}
-			if (media_code & 0x40) {
-				printk(KERN_INFO "%s:  21041 media %2.2x (%s),"
-					   " csr13 %4.4x csr14 %4.4x csr15 %4.4x.\n",
-					   dev->name, media_code & 15, medianame[media_code & 15],
-					   csrvals[0], csrvals[1], csrvals[2]);
-			} else
-				printk(KERN_INFO "%s:  21041 media #%d, %s.\n",
-					   dev->name, media_code & 15, medianame[media_code & 15]);
-		}
-	} else {
-		unsigned char *p = (void *)ee_data + ee_data[27];
-		unsigned char csr12dir = 0;
-		int count;
-		struct mediatable *mtable;
-		u16 media = get_u16(p);
-
-		p += 2;
-		if (tulip_tbl[tp->chip_id].flags & CSR12_IN_SROM)
-			csr12dir = *p++;
-		count = *p++;
-		mtable = (struct mediatable *)
-			kmalloc(sizeof(struct mediatable) + count*sizeof(struct medialeaf),
-					GFP_KERNEL);
-		if (mtable == NULL)
-			return;				/* Horrible, impossible failure. */
-		last_mediatable = tp->mtable = mtable;
-		mtable->defaultmedia = media;
-		mtable->leafcount = count;
-		mtable->csr12dir = csr12dir;
-		mtable->has_nonmii = mtable->has_mii = mtable->has_reset = 0;
-		mtable->csr15dir = mtable->csr15val = 0;
-
-		printk(KERN_INFO "%s:  EEPROM default media type %s.\n", dev->name,
-			   media & 0x0800 ? "Autosense" : medianame[media & 15]);
-		for (i = 0; i < count; i++) {
-			struct medialeaf *leaf = &mtable->mleaf[i];
-
-			if ((p[0] & 0x80) == 0) { /* 21140 Compact block. */
-				leaf->type = 0;
-				leaf->media = p[0] & 0x3f;
-				leaf->leafdata = p;
-				if ((p[2] & 0x61) == 0x01)	/* Bogus, but Znyx boards do it. */
-					mtable->has_mii = 1;
-				p += 4;
-			} else {
-				leaf->type = p[1];
-				if (p[1] == 0x05) {
-					mtable->has_reset = i;
-					leaf->media = p[2] & 0x0f;
-				} else if (p[1] & 1) {
-					mtable->has_mii = 1;
-					leaf->media = 11;
-				} else {
-					mtable->has_nonmii = 1;
-					leaf->media = p[2] & 0x0f;
-					if (p[1] == 2) {
-						if (leaf->media == 0) {
-							mtable->csr15dir = get_unaligned((u16*)&p[3])<<16;
-							mtable->csr15val = get_unaligned((u16*)&p[5])<<16;
-						} else if (leaf->media == 0x40) {
-							u32 base15 = get_unaligned((u16*)&p[7]);
-							mtable->csr15dir =
-								(get_unaligned((u16*)&p[9])<<16) + base15;
-							mtable->csr15val =
-								(get_unaligned((u16*)&p[11])<<16) + base15;
-						}
-					}
-				}
-				leaf->leafdata = p + 2;
-				p += (p[0] & 0x3f) + 1;
-			}
-			if (tulip_debug > 1  &&  leaf->media == 11) {
-				unsigned char *bp = leaf->leafdata;
-				printk(KERN_INFO "%s:  MII interface PHY %d, setup/reset "
-					   "sequences %d/%d long, capabilities %2.2x %2.2x.\n",
-					   dev->name, bp[0], bp[1], bp[1 + bp[1]*2],
-					   bp[5 + bp[2 + bp[1]*2]*2], bp[4 + bp[2 + bp[1]*2]*2]);
-			}
-			printk(KERN_INFO "%s:  Index #%d - Media %s (#%d) described "
-				   "by a %s (%d) block.\n",
-				   dev->name, i, medianame[leaf->media], leaf->media,
-				   block_name[leaf->type], leaf->type);
-		}
-	}
-}
-/* Reading a serial EEPROM is a "bit" grungy, but we work our way through:->.*/
-
-/*  EEPROM_Ctrl bits. */
-#define EE_SHIFT_CLK	0x02	/* EEPROM shift clock. */
-#define EE_CS			0x01	/* EEPROM chip select. */
-#define EE_DATA_WRITE	0x04	/* EEPROM chip data in. */
-#define EE_WRITE_0		0x01
-#define EE_WRITE_1		0x05
-#define EE_DATA_READ	0x08	/* EEPROM chip data out. */
-#define EE_ENB			(0x4800 | EE_CS)
-
-/* Delay between EEPROM clock transitions.
-   Even at 33Mhz current PCI implementations don't overrun the EEPROM clock.
-   We add a bus turn-around to insure that this remains true. */
-#define eeprom_delay()	inl(ee_addr)
-
-/* The EEPROM commands include the alway-set leading bit. */
-#define EE_WRITE_CMD	(5 << addr_len)
-#define EE_READ_CMD		(6 << addr_len)
-#define EE_ERASE_CMD	(7 << addr_len)
-
-static int read_eeprom(long ioaddr, int location, int addr_len)
-{
-	int i;
-	unsigned short retval = 0;
-	long ee_addr = ioaddr + CSR9;
-	int read_cmd = location | EE_READ_CMD;
-
-	outl(EE_ENB & ~EE_CS, ee_addr);
-	outl(EE_ENB, ee_addr);
-
-	/* Shift the read command bits out. */
-	for (i = 4 + addr_len; i >= 0; i--) {
-		short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
-		outl(EE_ENB | dataval, ee_addr);
-		eeprom_delay();
-		outl(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
-		eeprom_delay();
-	}
-	outl(EE_ENB, ee_addr);
-
-	for (i = 16; i > 0; i--) {
-		outl(EE_ENB | EE_SHIFT_CLK, ee_addr);
-		eeprom_delay();
-		retval = (retval << 1) | ((inl(ee_addr) & EE_DATA_READ) ? 1 : 0);
-		outl(EE_ENB, ee_addr);
-		eeprom_delay();
-	}
-
-	/* Terminate the EEPROM access. */
-	outl(EE_ENB & ~EE_CS, ee_addr);
-	return retval;
-}
 
 /* MII transceiver control section.
    Read and write the MII registers using software-generated serial
@@ -1076,36 +602,12 @@
 
 static int mdio_read(struct net_device *dev, int phy_id, int location)
 {
-	struct tulip_private *tp = (struct tulip_private *)dev->priv;
 	int i;
 	int read_cmd = (0xf6 << 10) | (phy_id << 5) | location;
 	int retval = 0;
 	long ioaddr = dev->base_addr;
 	long mdio_addr = ioaddr + CSR9;
 
-	if (tp->chip_id == LC82C168) {
-		int i = 1000;
-		outl(0x60020000 + (phy_id<<23) + (location<<18), ioaddr + 0xA0);
-		inl(ioaddr + 0xA0);
-		inl(ioaddr + 0xA0);
-		while (--i > 0)
-			if ( ! ((retval = inl(ioaddr + 0xA0)) & 0x80000000))
-				return retval & 0xffff;
-		return 0xffff;
-	}
-
-	if (tp->chip_id == COMET) {
-		if (phy_id == 1) {
-			if (location < 7)
-				return inl(ioaddr + 0xB4 + (location<<2));
-			else if (location == 17)
-				return inl(ioaddr + 0xD0);
-			else if (location >= 29 && location <= 31)
-				return inl(ioaddr + 0xD4 + ((location-29)<<2));
-		}
-		return 0xffff;
-	}
-
 	/* Establish sync by sending at least 32 logic ones. */
 	for (i = 32; i >= 0; i--) {
 		outl(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr);
@@ -1135,34 +637,11 @@
 
 static void mdio_write(struct net_device *dev, int phy_id, int location, int value)
 {
-	struct tulip_private *tp = (struct tulip_private *)dev->priv;
 	int i;
 	int cmd = (0x5002 << 16) | (phy_id << 23) | (location<<18) | value;
 	long ioaddr = dev->base_addr;
 	long mdio_addr = ioaddr + CSR9;
 
-	if (tp->chip_id == LC82C168) {
-		int i = 1000;
-		outl(cmd, ioaddr + 0xA0);
-		do
-			if ( ! (inl(ioaddr + 0xA0) & 0x80000000))
-				break;
-		while (--i > 0);
-		return;
-	}
-
-	if (tp->chip_id == COMET) {
-		if (phy_id != 1)
-			return;
-		if (location < 7)
-			outl(value, ioaddr + 0xB4 + (location<<2));
-		else if (location == 17)
-			outl(value, ioaddr + 0xD0);
-		else if (location >= 29 && location <= 31)
-			outl(value, ioaddr + 0xD4 + ((location-29)<<2));
-		return;
-	}
-
 	/* Establish sync by sending 32 logic ones. */
 	for (i = 32; i >= 0; i--) {
 		outl(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr);
@@ -1196,7 +675,7 @@
 	int i;
 
 	/* On some chip revs we must set the MII/SYM port before the reset!? */
-	if (tp->mii_cnt  ||  (tp->mtable  &&  tp->mtable->has_mii))
+	if (tp->mii_cnt)
 		outl_CSR6(0x00040000, ioaddr, tp->chip_id);
 
 	/* Reset the chip, holding bit 0 set at least 50 PCI cycles. */
@@ -1218,38 +697,7 @@
 	if (tulip_debug > 1)
 		printk(KERN_DEBUG "%s: tulip_open() irq %d.\n", dev->name, dev->irq);
 
-	if (tulip_tbl[tp->chip_id].flags & MC_HASH_ONLY) {
-		u32 addr_low = cpu_to_le32(get_unaligned((u32 *)dev->dev_addr));
-		u32 addr_high = cpu_to_le32(get_unaligned((u16 *)(dev->dev_addr+4)));
-		if (tp->chip_id == AX88140) {
-			outl(0, ioaddr + CSR13);
-			outl(addr_low,  ioaddr + CSR14);
-			outl(1, ioaddr + CSR13);
-			outl(addr_high, ioaddr + CSR14);
-		} else if (tp->chip_id == COMET) {
-			outl(addr_low,  ioaddr + 0xA4);
-			outl(addr_high, ioaddr + 0xA8);
-			outl(0, ioaddr + 0xAC);
-			outl(0, ioaddr + 0xB0);
-		}
-	} else if (tp->chip_id != X3201_3) {
-		/* This is set_rx_mode(), but without starting the transmitter. */
-		u16 *eaddrs = (u16 *)dev->dev_addr;
-		u16 *setup_frm = &tp->setup_frame[15*6];
-
-		/* 21140 bug: you must add the broadcast address. */
-		memset(tp->setup_frame, 0xff, 96*sizeof(u16));
-		/* Fill the final entry of the table with our physical address. */
-		*setup_frm++ = eaddrs[0]; *setup_frm++ = eaddrs[0];
-		*setup_frm++ = eaddrs[1]; *setup_frm++ = eaddrs[1];
-		*setup_frm++ = eaddrs[2]; *setup_frm++ = eaddrs[2];
-		/* Put the setup frame on the Tx list. */
-		tp->tx_ring[0].length = 0x68000000 | 192;
-		tp->tx_ring[0].buffer1 = virt_to_bus(tp->setup_frame);
-		tp->tx_ring[0].status = DescOwned;
-
-		tp->cur_tx++;
-	} else { /* X3201_3 */
+	{ /* X3201_3 */
 		u16 *eaddrs = (u16 *)dev->dev_addr;
 		u16 *setup_frm = &tp->setup_frame[0*6];
 		
@@ -1277,78 +725,10 @@
 	tp->saved_if_port = dev->if_port;
 	if (dev->if_port == 0)
 		dev->if_port = tp->default_port;
-	if (tp->chip_id == DC21041  &&  dev->if_port > 4)
-		/* Invalid: Select initial TP, autosense, autonegotiate.  */
-		dev->if_port = 4;
 
 	/* Allow selecting a default media. */
-	i = 0;
-	if (tp->mtable == NULL)
-		goto media_picked;
-	if (dev->if_port) {
-		int looking_for = media_cap[dev->if_port] & MediaIsMII ? 11 :
-			(dev->if_port == 12 ? 0 : dev->if_port);
-		for (i = 0; i < tp->mtable->leafcount; i++)
-			if (tp->mtable->mleaf[i].media == looking_for) {
-				printk(KERN_INFO "%s: Using user-specified media %s.\n",
-					   dev->name, medianame[dev->if_port]);
-				goto media_picked;
-			}
-	}
-	if ((tp->mtable->defaultmedia & 0x0800) == 0) {
-		int looking_for = tp->mtable->defaultmedia & 15;
-		for (i = 0; i < tp->mtable->leafcount; i++)
-			if (tp->mtable->mleaf[i].media == looking_for) {
-				printk(KERN_INFO "%s: Using EEPROM-set media %s.\n",
-					   dev->name, medianame[looking_for]);
-				goto media_picked;
-			}
-	}
-	/* Start sensing first non-full-duplex media. */
-	for (i = tp->mtable->leafcount - 1;
-		 (media_cap[tp->mtable->mleaf[i].media] & MediaAlwaysFD) && i > 0; i--)
-		;
-media_picked:
-
 	tp->csr6 = 0;
-	tp->cur_index = i;
-	if (dev->if_port == 0  &&  tp->chip_id == DC21142) {
-		if (tp->mii_cnt) {
-			select_media(dev, 1);
-			if (tulip_debug > 1)
-				printk(KERN_INFO "%s: Using MII transceiver %d, status "
-					   "%4.4x.\n",
-					   dev->name, tp->phys[0], mdio_read(dev, tp->phys[0], 1));
-			outl_CSR6(0x82020000, ioaddr, tp->chip_id);
-			tp->csr6 = 0x820E0000;
-			dev->if_port = 11;
-			outl(0x0000, ioaddr + CSR13);
-			outl(0x0000, ioaddr + CSR14);
-		} else
-			t21142_start_nway(dev);
-	} else if ((tp->chip_id == LC82C168  || tp->chip_id == PNIC2)
-			   &&  tp->mii_cnt && ! tp->medialock) {
-		dev->if_port = 11;
-		tp->csr6 = 0x814C0000 | (tp->full_duplex ? 0x0200 : 0);
-		outl(0x0001, ioaddr + CSR15);
-	} else if ((tp->chip_id == MX98713 || tp->chip_id == COMPEX9881)
-			   && ! tp->medialock) {
-		dev->if_port = 0;
-		tp->csr6 = 0x01880000 | (tp->full_duplex ? 0x0200 : 0);
-		outl(0x0f370000 | inw(ioaddr + 0x80), ioaddr + 0x80);
-	} else if (tp->chip_id == MX98715 || tp->chip_id == MX98725) {
-		/* Provided by BOLO, Macronix - 12/10/1998. */
-		dev->if_port = 0;
-		tp->csr6 = 0x01880200;
-		outl(0x0f370000 | inw(ioaddr + 0x80), ioaddr + 0x80);
-		outl(0x11000 | inw(ioaddr + 0xa0), ioaddr + 0xa0);
-	} else if (tp->chip_id == DC21143  &&
-			   media_cap[dev->if_port] & MediaIsMII) {
-		/* We must reset the media CSRs when we force-select MII mode. */
-		outl(0x0000, ioaddr + CSR13);
-		outl(0x0000, ioaddr + CSR14);
-		outl(0x0008, ioaddr + CSR15);
-	} else if (tp->chip_id == X3201_3) {
+	if (tp->chip_id == X3201_3) {
 		outl(0x0008, ioaddr + CSR15);
 		udelay(5);
 		outl(0xa8050000, ioaddr + CSR15);
@@ -1356,12 +736,7 @@
 		outl(0xa00f0000, ioaddr + CSR15); 
 		udelay(5);
 		tp->csr6  = 0x32400000;
-	} else if (tp->chip_id == COMET) {
-		dev->if_port = 0;
-		tp->csr6 = 0x00040000;
-	} else
-		select_media(dev, 1);
-
+	}
 	/* Start the chip's Tx to process setup frame. */
 	outl_CSR6(tp->csr6, ioaddr, tp->chip_id);
 	outl_CSR6(tp->csr6 | 0x2000, ioaddr, tp->chip_id);
@@ -1405,238 +780,13 @@
 	return 0;
 }
 
-/* Set up the transceiver control registers for the selected media type. */
-static void select_media(struct net_device *dev, int startup)
-{
-	long ioaddr = dev->base_addr;
-	struct tulip_private *tp = (struct tulip_private *)dev->priv;
-	struct mediatable *mtable = tp->mtable;
-	u32 new_csr6;
-	int i;
-
-	if (mtable) {
-		struct medialeaf *mleaf = &mtable->mleaf[tp->cur_index];
-		unsigned char *p = mleaf->leafdata;
-		switch (mleaf->type) {
-		case 0:					/* 21140 non-MII xcvr. */
-			if (tulip_debug > 1)
-				printk(KERN_DEBUG "%s: Using a 21140 non-MII transceiver"
-					   " with control setting %2.2x.\n",
-					   dev->name, p[1]);
-			dev->if_port = p[0];
-			if (startup)
-				outl(mtable->csr12dir | 0x100, ioaddr + CSR12);
-			outl(p[1], ioaddr + CSR12);
-			new_csr6 = 0x02000000 | ((p[2] & 0x71) << 18);
-			break;
-		case 2: case 4: {
-			u16 setup[5];
-			u32 csr13val, csr14val, csr15dir, csr15val;
-			for (i = 0; i < 5; i++)
-				setup[i] = get_u16(&p[i*2 + 1]);
-
-			dev->if_port = p[0] & 15;
-			if (media_cap[dev->if_port] & MediaAlwaysFD)
-				tp->full_duplex = 1;
-
-			if (startup && mtable->has_reset) {
-				struct medialeaf *rleaf = &mtable->mleaf[mtable->has_reset];
-				unsigned char *rst = rleaf->leafdata;
-				if (tulip_debug > 1)
-					printk(KERN_DEBUG "%s: Resetting the transceiver.\n",
-						   dev->name);
-				for (i = 0; i < rst[0]; i++)
-					outl(get_u16(rst + 1 + (i<<1)) << 16, ioaddr + CSR15);
-			}
-			if (tulip_debug > 1)
-				printk(KERN_DEBUG "%s: 21143 non-MII %s transceiver control "
-					   "%4.4x/%4.4x.\n",
-					   dev->name, medianame[dev->if_port], setup[0], setup[1]);
-			if (p[0] & 0x40) {	/* SIA (CSR13-15) setup values are provided. */
-				csr13val = setup[0];
-				csr14val = setup[1];
-				csr15dir = (setup[3]<<16) | setup[2];
-				csr15val = (setup[4]<<16) | setup[2];
-				outl(0, ioaddr + CSR13);
-				outl(csr14val, ioaddr + CSR14);
-				outl(csr15dir, ioaddr + CSR15);	/* Direction */
-				outl(csr15val, ioaddr + CSR15);	/* Data */
-				outl(csr13val, ioaddr + CSR13);
-			} else {
-				csr13val = 1;
-				csr14val = 0x0003FF7F;
-				csr15dir = (setup[0]<<16) | 0x0008;
-				csr15val = (setup[1]<<16) | 0x0008;
-				if (dev->if_port <= 4)
-					csr14val = t21142_csr14[dev->if_port];
-				if (startup) {
-					outl(0, ioaddr + CSR13);
-					outl(csr14val, ioaddr + CSR14);
-				}
-				outl(csr15dir, ioaddr + CSR15);	/* Direction */
-				outl(csr15val, ioaddr + CSR15);	/* Data */
-				if (startup) outl(csr13val, ioaddr + CSR13);
-			}
-			if (tulip_debug > 1)
-				printk(KERN_DEBUG "%s:  Setting CSR15 to %8.8x/%8.8x.\n",
-					   dev->name, csr15dir, csr15val);
-			if (mleaf->type == 4)
-				new_csr6 = 0x82020000 | ((setup[2] & 0x71) << 18);
-			else
-				new_csr6 = 0x82420000;
-			break;
-		}
-		case 1: case 3: {
-			int phy_num = p[0];
-			int init_length = p[1];
-			u16 *misc_info;
-			u16 to_advertise;
-
-			dev->if_port = 11;
-			new_csr6 = 0x020E0000;
-			if (mleaf->type == 3) {	/* 21142 */
-				u16 *init_sequence = (u16*)(p+2);
-				u16 *reset_sequence = &((u16*)(p+3))[init_length];
-				int reset_length = p[2 + init_length*2];
-				misc_info = reset_sequence + reset_length;
-				if (startup)
-					for (i = 0; i < reset_length; i++)
-						outl(get_u16(&reset_sequence[i]) << 16, ioaddr + CSR15);
-				for (i = 0; i < init_length; i++)
-					outl(get_u16(&init_sequence[i]) << 16, ioaddr + CSR15);
-			} else {
-				u8 *init_sequence = p + 2;
-				u8 *reset_sequence = p + 3 + init_length;
-				int reset_length = p[2 + init_length];
-				misc_info = (u16*)(reset_sequence + reset_length);
-				if (startup) {
-					outl(mtable->csr12dir | 0x100, ioaddr + CSR12);
-					for (i = 0; i < reset_length; i++)
-						outl(reset_sequence[i], ioaddr + CSR12);
-				}
-				for (i = 0; i < init_length; i++)
-					outl(init_sequence[i], ioaddr + CSR12);
-			}
-			to_advertise = (get_u16(&misc_info[1]) & tp->to_advertise) | 1;
-			tp->advertising[phy_num] = to_advertise;
-			if (tulip_debug > 1)
-				printk(KERN_DEBUG "%s:  Advertising %4.4x on PHY %d (%d).\n",
-					   dev->name, to_advertise, phy_num, tp->phys[phy_num]);
-			/* Bogus: put in by a committee?  */
-			mdio_write(dev, tp->phys[phy_num], 4, to_advertise);
-			break;
-		}
-		default:
-			printk(KERN_DEBUG "%s:  Invalid media table selection %d.\n",
-					   dev->name, mleaf->type);
-			new_csr6 = 0x020E0000;
-		}
-		if (tulip_debug > 1)
-			printk(KERN_DEBUG "%s: Using media type %s, CSR12 is %2.2x.\n",
-				   dev->name, medianame[dev->if_port],
-				   inl(ioaddr + CSR12) & 0xff);
-	} else if (tp->chip_id == DC21041) {
-		if (tulip_debug > 1)
-			printk(KERN_DEBUG "%s: 21041 using media %s, CSR12 is %4.4x.\n",
-				   dev->name, medianame[dev->if_port & 15],
-				   inl(ioaddr + CSR12) & 0xffff);
-		outl(0x00000000, ioaddr + CSR13); /* Reset the serial interface */
-		outl(t21041_csr14[dev->if_port], ioaddr + CSR14);
-		outl(t21041_csr15[dev->if_port], ioaddr + CSR15);
-		outl(t21041_csr13[dev->if_port], ioaddr + CSR13);
-		new_csr6 = 0x80020000;
-	} else if (tp->chip_id == LC82C168 || tp->chip_id == PNIC2) {
-		if (startup && ! tp->medialock)
-			dev->if_port = tp->mii_cnt ? 11 : 0;
-		if (tulip_debug > 1)
-			printk(KERN_DEBUG "%s: PNIC PHY status is %3.3x, CSR12 %4.4x,"
-				   " media %s.\n",
-				   dev->name, inl(ioaddr + 0xB8), inl(ioaddr + CSR12),
-				   medianame[dev->if_port]);
-		if (tp->mii_cnt) {
-			new_csr6 = 0x810C0000;
-			outl(0x0001, ioaddr + CSR15);
-			outl(0x0201B07A, ioaddr + 0xB8);
-		} else if (startup) {
-			/* Start with 10mbps to do autonegotiation. */
-			outl(0x32, ioaddr + CSR12);
-			new_csr6 = 0x00420000;
-			outl(0x0001B078, ioaddr + 0xB8);
-			outl(0x0201B078, ioaddr + 0xB8);
-		} else if (dev->if_port == 3  ||  dev->if_port == 5) {
-			outl(0x33, ioaddr + CSR12);
-			new_csr6 = 0x01860000;
-			if (startup)
-				outl(0x0201F868, ioaddr + 0xB8); /* Trigger autonegotiation. */
-			else
-				outl(0x1F868, ioaddr + 0xB8);
-		} else {
-			outl(0x32, ioaddr + CSR12);
-			new_csr6 = 0x00420000;
-			outl(0x1F078, ioaddr + 0xB8);
-		}
-	} else if (tp->chip_id == DC21040) {					/* 21040 */
-		/* Turn on the xcvr interface. */
-		int csr12 = inl(ioaddr + CSR12);
-		if (tulip_debug > 1)
-			printk(KERN_DEBUG "%s: 21040 media type is %s, CSR12 is %2.2x.\n",
-				   dev->name, medianame[dev->if_port], csr12);
-		if (media_cap[dev->if_port] & MediaAlwaysFD)
-			tp->full_duplex = 1;
-		new_csr6 = 0x20000;
-		/* Set the full duplux match frame. */
-		outl(FULL_DUPLEX_MAGIC, ioaddr + CSR11);
-		outl(0x00000000, ioaddr + CSR13); /* Reset the serial interface */
-		if (t21040_csr13[dev->if_port] & 8) {
-			outl(0x0705, ioaddr + CSR14);
-			outl(0x0006, ioaddr + CSR15);
-		} else {
-			outl(0xffff, ioaddr + CSR14);
-			outl(0x0000, ioaddr + CSR15);
-		}
-		outl(0x8f01 | t21040_csr13[dev->if_port], ioaddr + CSR13);
-	} else if (tp->chip_id == X3201_3) {					/* Xircom */
-		if (tp->default_port == 0)
-			dev->if_port = tp->mii_cnt ? 11 : 3;
-/* Someone is on crack, the Xircom only does MII, no Fx */
-/*		if (media_cap[dev->if_port] & MediaIsMII) {
-			new_csr6 = 0x020E0000;
-		} else if (media_cap[dev->if_port] & MediaIsFx) {
-			new_csr6 = 0x028600000;
-		} else
-			new_csr6 = 0x038600000;*/
-		new_csr6 = 0x324c0000;
-		if (tulip_debug > 1)
-			printk(KERN_DEBUG "%s: Xircom CardBus Adapter: "
-				   "%s transceiver, CSR12 %2.2x.\n",
-				   dev->name, medianame[dev->if_port],
-				   inl(ioaddr + CSR12));
-	} else {					/* Unknown chip type with no media table. */
-		if (tp->default_port == 0)
-			dev->if_port = tp->mii_cnt ? 11 : 3;
-		if (media_cap[dev->if_port] & MediaIsMII) {
-			new_csr6 = 0x020E0000;
-		} else if (media_cap[dev->if_port] & MediaIsFx) {
-			new_csr6 = 0x028600000;
-		} else
-			new_csr6 = 0x038600000;
-		if (tulip_debug > 1)
-			printk(KERN_DEBUG "%s: No media description table, assuming "
-				   "%s transceiver, CSR12 %2.2x.\n",
-				   dev->name, medianame[dev->if_port],
-				   inl(ioaddr + CSR12));
-	}
-
-	tp->csr6 = new_csr6 | (tp->csr6 & 0xfdff) | (tp->full_duplex ? 0x0200 : 0);
-	return;
-}
-
 /*
   Check the MII negotiated duplex, and change the CSR6 setting if
   required.
   Return 0 if everything is OK.
   Return < 0 if the transceiver is missing or has no link beat.
   */
+#if 0
 static int check_duplex(struct net_device *dev)
 {
 	long ioaddr = dev->base_addr;
@@ -1679,6 +829,7 @@
 	}
 	return 0;
 }
+#endif
 
 static void tulip_timer(unsigned long data)
 {
@@ -1695,273 +846,17 @@
 			   csr12, inl(ioaddr + CSR13),
 			   inl(ioaddr + CSR14), inl(ioaddr + CSR15));
 	}
-	switch (tp->chip_id) {
-	case DC21040:
-		if (!tp->medialock  &&  csr12 & 0x0002) { /* Network error */
-			printk(KERN_INFO "%s: No link beat found.\n",
-				   dev->name);
-			dev->if_port = (dev->if_port == 2 ? 0 : 2);
-			select_media(dev, 0);
-			dev->trans_start = jiffies;
-		}
-		break;
-	case DC21041:
-		if (tulip_debug > 2)
-			printk(KERN_DEBUG "%s: 21041 media tick  CSR12 %8.8x.\n",
-				   dev->name, csr12);
-		switch (dev->if_port) {
-		case 0: case 3: case 4:
-		  if (csr12 & 0x0004) { /*LnkFail */
-			/* 10baseT is dead.  Check for activity on alternate port. */
-			tp->mediasense = 1;
-			if (csr12 & 0x0200)
-				dev->if_port = 2;
-			else
-				dev->if_port = 1;
-			printk(KERN_INFO "%s: No 21041 10baseT link beat, Media switched to %s.\n",
-				   dev->name, medianame[dev->if_port]);
-			outl(0, ioaddr + CSR13); /* Reset */
-			outl(t21041_csr14[dev->if_port], ioaddr + CSR14);
-			outl(t21041_csr15[dev->if_port], ioaddr + CSR15);
-			outl(t21041_csr13[dev->if_port], ioaddr + CSR13);
-			next_tick = 10*HZ;			/* 2.4 sec. */
-		  } else
-			next_tick = 30*HZ;
-		  break;
-		case 1:					/* 10base2 */
-		case 2:					/* AUI */
-			if (csr12 & 0x0100) {
-				next_tick = (30*HZ);			/* 30 sec. */
-				tp->mediasense = 0;
-			} else if ((csr12 & 0x0004) == 0) {
-				printk(KERN_INFO "%s: 21041 media switched to 10baseT.\n",
-					   dev->name);
-				dev->if_port = 0;
-				select_media(dev, 0);
-				next_tick = (24*HZ)/10;				/* 2.4 sec. */
-			} else if (tp->mediasense || (csr12 & 0x0002)) {
-				dev->if_port = 3 - dev->if_port; /* Swap ports. */
-				select_media(dev, 0);
-				next_tick = 20*HZ;
-			} else {
-				next_tick = 20*HZ;
-			}
-			break;
-		}
-		break;
-	case DC21140:  case DC21142: case MX98713: case COMPEX9881: default: {
-		struct medialeaf *mleaf;
-		unsigned char *p;
-		if (tp->mtable == NULL) {	/* No EEPROM info, use generic code. */
-			/* Not much that can be done.
-			   Assume this a generic MII or SYM transceiver. */
-			next_tick = 60*HZ;
-			if (tulip_debug > 2)
-				printk(KERN_DEBUG "%s: network media monitor CSR6 %8.8x "
-					   "CSR12 0x%2.2x.\n",
-					   dev->name, inl(ioaddr + CSR6), csr12 & 0xff);
-			break;
-		}
-		mleaf = &tp->mtable->mleaf[tp->cur_index];
-		p = mleaf->leafdata;
-		switch (mleaf->type) {
-		case 0: case 4: {
-			/* Type 0 serial or 4 SYM transceiver.  Check the link beat bit. */
-			int offset = mleaf->type == 4 ? 5 : 2;
-			s8 bitnum = p[offset];
-			if (p[offset+1] & 0x80) {
-				if (tulip_debug > 1)
-					printk(KERN_DEBUG"%s: Transceiver monitor tick "
-						   "CSR12=%#2.2x, no media sense.\n",
-						   dev->name, csr12);
-				if (mleaf->type == 4) {
-					if (mleaf->media == 3 && (csr12 & 0x02))
-						goto select_next_media;
-				}
-				break;
-			}
-			if (tulip_debug > 2)
-				printk(KERN_DEBUG "%s: Transceiver monitor tick: CSR12=%#2.2x"
-					   " bit %d is %d, expecting %d.\n",
-					   dev->name, csr12, (bitnum >> 1) & 7,
-					   (csr12 & (1 << ((bitnum >> 1) & 7))) != 0,
-					   (bitnum >= 0));
-			/* Check that the specified bit has the proper value. */
-			if ((bitnum < 0) !=
-				((csr12 & (1 << ((bitnum >> 1) & 7))) != 0)) {
-				if (tulip_debug > 1)
-					printk(KERN_DEBUG "%s: Link beat detected for %s.\n", dev->name,
-						   medianame[mleaf->media]);
-				if ((p[2] & 0x61) == 0x01)	/* Bogus Znyx board. */
-					goto actually_mii;
-				break;
-			}
-			if (tp->medialock)
-				break;
-	  select_next_media:
-			if (--tp->cur_index < 0) {
-				/* We start again, but should instead look for default. */
-				tp->cur_index = tp->mtable->leafcount - 1;
-			}
-			dev->if_port = tp->mtable->mleaf[tp->cur_index].media;
-			if (media_cap[dev->if_port] & MediaIsFD)
-				goto select_next_media; /* Skip FD entries. */
-			if (tulip_debug > 1)
-				printk(KERN_DEBUG "%s: No link beat on media %s,"
-					   " trying transceiver type %s.\n",
-					   dev->name, medianame[mleaf->media & 15],
-					   medianame[tp->mtable->mleaf[tp->cur_index].media]);
-			select_media(dev, 0);
-			/* Restart the transmit process. */
-			outl_CSR6(tp->csr6 | 0x0002, ioaddr, tp->chip_id);
-			outl_CSR6(tp->csr6 | 0x2002, ioaddr, tp->chip_id);
-			next_tick = (24*HZ)/10;
-			break;
-		}
-		case 1:  case 3:		/* 21140, 21142 MII */
-		actually_mii:
-			check_duplex(dev);
-			next_tick = 60*HZ;
-			break;
-		case 2:					/* 21142 serial block has no link beat. */
-		default:
-			break;
-		}
-	}
-	break;
-	}
-	tp->timer.expires = RUN_AT(next_tick);
-	add_timer(&tp->timer);
-}
-
-static void t21142_start_nway(struct net_device *dev)
-{
-	struct tulip_private *tp = (struct tulip_private *)dev->priv;
-	long ioaddr = dev->base_addr;
-	int csr14 = ((tp->to_advertise & 0x0180) << 9)  |
-		((tp->to_advertise&0x0020)<<1) | 0xffbf;
 
-	dev->if_port = 0;
-	tp->nway = tp->mediasense = 1;
-	tp->nwayset = tp->lpar = 0;
-	if (debug > 1)
-		printk(KERN_DEBUG "%s: Restarting 21143 autonegotiation, %8.8x.\n",
-			   dev->name, csr14);
-	outl(0x0001, ioaddr + CSR13);
-	outl(csr14, ioaddr + CSR14);
-	tp->csr6 = 0x82420000 | (tp->to_advertise & 0x0040 ? 0x0200 : 0);
-	outl_CSR6(tp->csr6, ioaddr, tp->chip_id);
-	if (tp->mtable  &&  tp->mtable->csr15dir) {
-		outl(tp->mtable->csr15dir, ioaddr + CSR15);
-		outl(tp->mtable->csr15val, ioaddr + CSR15);
-	} else
-		outw(0x0008, ioaddr + CSR15);
-	outl(0x1301, ioaddr + CSR12); 		/* Trigger NWAY. */
-}
-
-static void t21142_lnk_change(struct net_device *dev, int csr5)
-{
-	struct tulip_private *tp = (struct tulip_private *)dev->priv;
-	long ioaddr = dev->base_addr;
-	int csr12 = inl(ioaddr + CSR12);
+	/* Not much that can be done.
+	   Assume this a generic MII or SYM transceiver. */
+	next_tick = 60*HZ;
+	if (tulip_debug > 2)
+		printk(KERN_DEBUG "%s: network media monitor CSR6 %8.8x "
+		       "CSR12 0x%2.2x.\n",
+		       dev->name, inl(ioaddr + CSR6), csr12 & 0xff);
 
-	if (tulip_debug > 1)
-		printk(KERN_INFO"%s: 21143 link status interrupt %8.8x, CSR5 %x, "
-			   "%8.8x.\n", dev->name, csr12, csr5, inl(ioaddr + CSR14));
-
-	/* If NWay finished and we have a negotiated partner capability. */
-	if (tp->nway  &&  !tp->nwayset  &&  (csr12 & 0x7000) == 0x5000) {
-		int setup_done = 0;
-		tp->lpar = csr12 >> 16;
-		tp->nwayset = 1;
-		if (csr12 & 0x01000000)			dev->if_port = 5;
-		else if (csr12 & 0x00800000)	dev->if_port = 3;
-		else if (csr12 & 0x00400000)	dev->if_port = 4;
-		else if (csr12 & 0x00200000)	dev->if_port = 0;
-		else {
-			tp->nwayset = 0;
-			if ( ! (csr12 & 2))			dev->if_port = 3;
-			else if ( ! (csr12 & 4))	dev->if_port = 0;
-		}
-		tp->full_duplex = (media_cap[tp->default_port] & MediaAlwaysFD) ? 1:0;
-
-		if (tulip_debug > 1) {
-			if (tp->nwayset)
-				printk(KERN_INFO "%s: Switching to %s based on link partner "
-					   "advertisement %4.4x.\n",
-					   dev->name, medianame[dev->if_port], tp->lpar);
-			else
-				printk(KERN_INFO "%s: Switching to %s based on link beat "
-					   "status of %4.4x.\n",
-					   dev->name, medianame[dev->if_port], csr12);
-		}
-
-		if (tp->mtable) {
-			int i;
-			for (i = 0; i < tp->mtable->leafcount; i++)
-				if (tp->mtable->mleaf[i].media == dev->if_port) {
-					tp->cur_index = i;
-					select_media(dev, 0);
-					setup_done = 1;
-					break;
-				}
-		}
-		if ( ! setup_done) {
-			tp->csr6 = dev->if_port & 1 ? 0x83860000 : 0x82420000;
-			if (tp->full_duplex)
-				tp->csr6 |= 0x0200;
-			outw(0x0000, ioaddr + CSR13);
-			outw(0x0000, ioaddr + CSR14);
-		}
-		outl_CSR6(tp->csr6 | 0x0000, ioaddr, tp->chip_id);
-		if (debug > 2)
-			printk(KERN_DEBUG "%s:  Restarting Tx and Rx, CSR5 is %8.8x.\n",
-				   dev->name, inl(ioaddr + CSR5));
-		outl_CSR6(tp->csr6 | 0x2002, ioaddr, tp->chip_id);
-	} else if ((tp->nwayset  &&  (csr5 & 0x08000000)
-				&& (dev->if_port == 3  ||  dev->if_port == 5)
-				&& (csr12 & 2) == 2) ||
-			   (tp->nway && (csr5 & (TPLnkFail)))) {
-		/* Link blew? Maybe restart NWay. */
-		del_timer(&tp->timer);
-		t21142_start_nway(dev);
-		tp->timer.expires = RUN_AT(3*HZ);
-		add_timer(&tp->timer);
-	} else if (dev->if_port == 3  ||  dev->if_port == 5) {
-		if (tulip_debug > 1)
-			printk(KERN_INFO"%s: 21143 %s link beat %s.\n",
-				   dev->name, medianame[dev->if_port],
-				   (csr12 & 2) ? "failed" : "good");
-		if ((csr12 & 2)  &&  ! tp->medialock) {
-			del_timer(&tp->timer);
-			t21142_start_nway(dev);
-			tp->timer.expires = RUN_AT(3*HZ);
-			add_timer(&tp->timer);
-		}
-	} else if (dev->if_port == 0  ||  dev->if_port == 4) {
-		if ((csr12 & 4) == 0)
-			printk(KERN_INFO"%s: 21143 10baseT link beat good.\n",
-				   dev->name);
-	} else if (!(csr12 & 4)) {		/* 10mbps link beat good. */
-		if (tulip_debug)
-			printk(KERN_INFO"%s: 21143 10mbps sensed media.\n",
-				   dev->name);
-		dev->if_port = 0;
-	} else if (tp->nwayset) {
-		if (tulip_debug)
-			printk(KERN_INFO"%s: 21143 using NWay-set %s, csr6 %8.8x.\n",
-				   dev->name, medianame[dev->if_port], tp->csr6);
-	} else {		/* 100mbps link beat good. */
-		if (tulip_debug)
-			printk(KERN_INFO"%s: 21143 100baseTx sensed media.\n",
-				   dev->name);
-		dev->if_port = 3;
-		tp->csr6 = 0x83860000;
-		outl(0x0003FF7F, ioaddr + CSR14);
-		outl(0x0301, ioaddr + CSR12);
-		outl_CSR6(tp->csr6 | 0x0002, ioaddr, tp->chip_id);
-		outl_CSR6(tp->csr6 | 0x2002, ioaddr, tp->chip_id);
-	}
+	tp->timer.expires = RUN_AT(next_tick);
+	add_timer(&tp->timer);
 }
 
 static void tulip_tx_timeout(struct net_device *dev)
@@ -1974,59 +869,6 @@
 		if (tulip_debug > 1)
 			printk(KERN_WARNING "%s: Transmit timeout using MII device.\n",
 				   dev->name);
-	} else if (tp->chip_id == DC21040) {
-		if ( !tp->medialock  &&  inl(ioaddr + CSR12) & 0x0002) {
-			dev->if_port = (dev->if_port == 2 ? 0 : 2);
-			printk(KERN_INFO "%s: transmit timed out, switching to "
-				   "%s.\n",
-				   dev->name, medianame[dev->if_port]);
-			select_media(dev, 0);
-		}
-		dev->trans_start = jiffies;
-		return;
-	} else if (tp->chip_id == DC21041) {
-		int csr12 = inl(ioaddr + CSR12);
-
-		printk(KERN_WARNING "%s: 21041 transmit timed out, status %8.8x, "
-			   "CSR12 %8.8x, CSR13 %8.8x, CSR14 %8.8x, resetting...\n",
-			   dev->name, inl(ioaddr + CSR5), csr12,
-			   inl(ioaddr + CSR13), inl(ioaddr + CSR14));
-		tp->mediasense = 1;
-		if ( ! tp->medialock) {
-			if (dev->if_port == 1 || dev->if_port == 2)
-				if (csr12 & 0x0004) {
-					dev->if_port = 2 - dev->if_port;
-				} else
-					dev->if_port = 0;
-			else
-				dev->if_port = 1;
-			select_media(dev, 0);
-		}
-	} else if (tp->chip_id == DC21140 || tp->chip_id == DC21142
-			   || tp->chip_id == MX98713 || tp->chip_id == COMPEX9881) {
-		printk(KERN_WARNING "%s: 21140 transmit timed out, status %8.8x, "
-			   "SIA %8.8x %8.8x %8.8x %8.8x, resetting...\n",
-			   dev->name, inl(ioaddr + CSR5), inl(ioaddr + CSR12),
-			   inl(ioaddr + CSR13), inl(ioaddr + CSR14), inl(ioaddr + CSR15));
-		if ( ! tp->medialock  &&  tp->mtable) {
-			do
-				--tp->cur_index;
-			while (tp->cur_index >= 0
-				   && (media_cap[tp->mtable->mleaf[tp->cur_index].media]
-					   & MediaIsFD));
-			if (--tp->cur_index < 0) {
-				/* We start again, but should instead look for default. */
-				tp->cur_index = tp->mtable->leafcount - 1;
-			}
-			select_media(dev, 0);
-			printk(KERN_WARNING "%s: transmit timed out, switching to %s "
-				   "media.\n", dev->name, medianame[dev->if_port]);
-		}
-	} else {
-		printk(KERN_WARNING "%s: Transmit timed out, status %8.8x, CSR12 "
-			   "%8.8x, resetting...\n",
-			   dev->name, inl(ioaddr + CSR5), inl(ioaddr + CSR12));
-		dev->if_port = 0;
 	}
 
 #if defined(way_too_many_messages)
@@ -2295,10 +1137,6 @@
 						   dev->name, csr5);
 				outl(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7);
 			}
-			if (csr5 & (TPLnkPass | TPLnkFail | 0x08000000)) {
-				if ( tp->chip_id == DC21142)
-					t21142_lnk_change(dev, csr5);
-			}
 			/* Clear all error sources, included undocumented ones! */
 			outl(0x0800f7ba, ioaddr + CSR5);
 		}
@@ -2442,9 +1280,6 @@
 	outl(0x00000000, ioaddr + CSR7);
 	/* Stop the chip's Tx and Rx processes. */
 	outl_CSR6(inl(ioaddr + CSR6) & ~0x2002, ioaddr, tp->chip_id);
-	/* 21040 -- Leave the card in 10baseT state. */
-	if (tp->chip_id == DC21040)
-		outl(0x00000004, ioaddr + CSR13);
 
 	if (inl(ioaddr + CSR6) != 0xffffffff)
 		tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff;
@@ -2510,7 +1345,6 @@
 static int private_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
 	struct tulip_private *tp = (struct tulip_private *)dev->priv;
-	long ioaddr = dev->base_addr;
 	u16 *data = (u16 *)&rq->ifr_data;
 	int phy = tp->phys[0] & 0x1f;
 	long flags;
@@ -2523,27 +1357,7 @@
 			return -ENODEV;
 		return 0;
 	case SIOCDEVPRIVATE+1:		/* Read the specified MII register. */
-		if (data[0] == 32  &&
-			(tp->chip_id == DC21142 || tp->chip_id == PNIC2)) {
-			int csr12 = inl(ioaddr + CSR12);
-			int csr14 = inl(ioaddr + CSR14);
-			switch (data[1]) {
-			case 0: {
-				data[3] = (csr14<<5) & 0x1000;
-				break; }
-			case 1:
-				data[3] = 0x7848 + ((csr12&0x7000) == 0x5000 ? 0x20 : 0)
-					+ (csr12&0x06 ? 0x04 : 0);
-				break;
-			case 4: {
-				data[3] = ((csr14>>9)&0x0380) +
-					((inl(ioaddr + CSR6)>>3)&0x0040) +((csr14>>1)&0x20) + 1;
-				break;
-			}
-			case 5: data[3] = csr12 >> 16; break;
-			default: data[3] = 0; break;
-			}
-		} else {
+		{
 			save_flags(flags);
 			cli();
 			data[3] = mdio_read(dev, data[0] & 0x1f, data[1] & 0x1f);
@@ -2558,10 +1372,7 @@
 		if (!suser())
 			return -EPERM;
 #endif
-		if (data[0] == 32  &&  tp->chip_id == DC21142) {
-			if (data[1] == 5)
-				tp->to_advertise = data[2];
-		} else {
+		{
 			save_flags(flags);
 			cli();
 			mdio_write(dev, data[0] & 0x1f, data[1] & 0x1f, data[2]);
@@ -2632,21 +1443,6 @@
 		/* Too many to filter well -- accept all multicasts. */
 		tp->csr6 |= 0x0080;
 		csr6 |= 0x0080;
-	} else	if (tulip_tbl[tp->chip_id].flags & MC_HASH_ONLY) {
-		/* Some work-alikes have only a 64-entry hash filter table. */
-		/* Should verify correctness on big-endian/__powerpc__ */
-		struct dev_mc_list *mclist;
-		int i;
-		u32 mc_filter[2];		 /* Multicast hash filter */
-		if (dev->mc_count > 64) {		/* Arbitrary non-effective limit. */
-			tp->csr6 |= 0x0080;
-			csr6 |= 0x0080;
-		} else {
-			mc_filter[1] = mc_filter[0] = 0;
-			for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
-				 i++, mclist = mclist->next)
-				set_bit(ether_crc(ETH_ALEN, mclist->dmi_addr)>>26, mc_filter);
-		}
 	} else {
 		u16 *eaddrs, *setup_frm = tp->setup_frame;
 		struct dev_mc_list *mclist;
diff -urN linux-2.4.7-pre6/drivers/net/plip.c linux/drivers/net/plip.c
--- linux-2.4.7-pre6/drivers/net/plip.c	Wed Jun 20 11:10:53 2001
+++ linux/drivers/net/plip.c	Mon Dec  3 22:55:49 2001
@@ -2,7 +2,7 @@
 /* PLIP: A parallel port "network" driver for Linux. */
 /* This driver is for parallel port with 5-bit cable (LapLink (R) cable). */
 /*
- * Authors:	Donald Becker <becker@super.org>
+ * Authors:	Donald Becker <becker@scyld.com>
  *		Tommy Thorn <thorn@daimi.aau.dk>
  *		Tanabe Hiroyasu <hiro@sanpo.t.u-tokyo.ac.jp>
  *		Alan Cox <gw4pts@gw4pts.ampr.org>
@@ -37,7 +37,7 @@
  */
 
 /*
- * Original version and the name 'PLIP' from Donald Becker <becker@super.org>
+ * Original version and the name 'PLIP' from Donald Becker <becker@scyld.com>
  * inspired by Russ Nelson's parallel port packet driver.
  *
  * NOTE:
diff -urN linux-2.4.7-pre6/drivers/net/sis900.c linux/drivers/net/sis900.c
--- linux-2.4.7-pre6/drivers/net/sis900.c	Mon Jul  2 14:03:04 2001
+++ linux/drivers/net/sis900.c	Mon Dec  3 22:55:49 2001
@@ -150,8 +150,11 @@
 	/* The saved address of a sent/receive-in-place packet buffer */
 	struct sk_buff *tx_skbuff[NUM_TX_DESC];
 	struct sk_buff *rx_skbuff[NUM_RX_DESC];
-	BufferDesc tx_ring[NUM_TX_DESC];
-	BufferDesc rx_ring[NUM_RX_DESC];
+	BufferDesc *tx_ring;
+	BufferDesc *rx_ring;
+
+	dma_addr_t tx_ring_dma;
+	dma_addr_t rx_ring_dma;
 
 	unsigned int tx_full;			/* The Tx queue is full.    */
 };
@@ -309,6 +312,8 @@
 {
 	struct sis900_private *sis_priv;
 	struct net_device *net_dev;
+	dma_addr_t ring_dma;
+	void *ring_space;
 	long ioaddr;
 	int i, ret;
 	u8 revision;
@@ -353,6 +358,22 @@
 
 	pci_set_drvdata(pci_dev, net_dev);
 
+	ring_space = pci_alloc_consistent(pci_dev, TX_TOTAL_SIZE, &ring_dma);
+	if (!ring_space) {
+		ret = -ENOMEM;
+		goto err_out_cleardev;
+	}
+	sis_priv->tx_ring = (BufferDesc *)ring_space;
+	sis_priv->tx_ring_dma = ring_dma;
+
+	ring_space = pci_alloc_consistent(pci_dev, RX_TOTAL_SIZE, &ring_dma);
+	if (!ring_space) {
+		ret = -ENOMEM;
+		goto err_unmap_tx;
+	}
+	sis_priv->rx_ring = (BufferDesc *)ring_space;
+	sis_priv->rx_ring_dma = ring_dma;
+		
 	/* The SiS900-specific entries in the device structure. */
 	net_dev->open = &sis900_open;
 	net_dev->hard_start_xmit = &sis900_start_xmit;
@@ -366,7 +387,7 @@
 	
 	ret = register_netdev(net_dev);
 	if (ret)
-		goto err_out_cleardev;
+		goto err_unmap_rx;
 		
 	/* Get Mac address according to the chip revision */
 	pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &revision);
@@ -401,6 +422,12 @@
 
  err_out_unregister:
  	unregister_netdev(net_dev);
+ err_unmap_rx:
+	pci_free_consistent(pci_dev, RX_TOTAL_SIZE, sis_priv->rx_ring,
+		sis_priv->rx_ring_dma);
+ err_unmap_tx:
+	pci_free_consistent(pci_dev, TX_TOTAL_SIZE, sis_priv->tx_ring,
+		sis_priv->tx_ring_dma);
  err_out_cleardev:
  	pci_set_drvdata(pci_dev, NULL);
 	pci_release_regions(pci_dev);
@@ -808,7 +835,7 @@
 {
 	struct sis900_private *sis_priv = net_dev->priv;
 	long ioaddr = net_dev->base_addr;
-	u8  revision;
+	u8 revision;
 	int ret;
 
 	/* Soft reset the chip. */
@@ -907,14 +934,14 @@
 	for (i = 0; i < NUM_TX_DESC; i++) {
 		sis_priv->tx_skbuff[i] = NULL;
 
-		sis_priv->tx_ring[i].link = (u32) virt_to_bus(&sis_priv->tx_ring[i+1]);
+		sis_priv->tx_ring[i].link = sis_priv->tx_ring_dma +
+			((i+1)%NUM_TX_DESC)*sizeof(BufferDesc);
 		sis_priv->tx_ring[i].cmdsts = 0;
 		sis_priv->tx_ring[i].bufptr = 0;
 	}
-	sis_priv->tx_ring[i-1].link = (u32) virt_to_bus(&sis_priv->tx_ring[0]);
 
 	/* load Transmit Descriptor Register */
-	outl(virt_to_bus(&sis_priv->tx_ring[0]), ioaddr + txdp);
+	outl(sis_priv->tx_ring_dma, ioaddr + txdp);
 	if (sis900_debug > 2)
 		printk(KERN_INFO "%s: TX descriptor register loaded with: %8.8x\n",
 		       net_dev->name, inl(ioaddr + txdp));
@@ -942,11 +969,11 @@
 	for (i = 0; i < NUM_RX_DESC; i++) {
 		sis_priv->rx_skbuff[i] = NULL;
 
-		sis_priv->rx_ring[i].link = (u32) virt_to_bus(&sis_priv->rx_ring[i+1]);
+		sis_priv->rx_ring[i].link = sis_priv->rx_ring_dma +
+			((i+1)%NUM_RX_DESC)*sizeof(BufferDesc);
 		sis_priv->rx_ring[i].cmdsts = 0;
 		sis_priv->rx_ring[i].bufptr = 0;
 	}
-	sis_priv->rx_ring[i-1].link = (u32) virt_to_bus(&sis_priv->rx_ring[0]);
 
 	/* allocate sock buffers */
 	for (i = 0; i < NUM_RX_DESC; i++) {
@@ -962,12 +989,13 @@
 		skb->dev = net_dev;
 		sis_priv->rx_skbuff[i] = skb;
 		sis_priv->rx_ring[i].cmdsts = RX_BUF_SIZE;
-		sis_priv->rx_ring[i].bufptr = virt_to_bus(skb->tail);
+                sis_priv->rx_ring[i].bufptr = pci_map_single(sis_priv->pci_dev,
+                        skb->tail, RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
 	}
 	sis_priv->dirty_rx = (unsigned int) (i - NUM_RX_DESC);
 
 	/* load Receive Descriptor Register */
-	outl(virt_to_bus(&sis_priv->rx_ring[0]), ioaddr + rxdp);
+	outl(sis_priv->rx_ring_dma, ioaddr + rxdp);
 	if (sis900_debug > 2)
 		printk(KERN_INFO "%s: RX descriptor register loaded with: %8.8x\n",
 		       net_dev->name, inl(ioaddr + rxdp));
@@ -1012,7 +1040,8 @@
 	       revision == SIS630A_900_REV) )
 		return;
 
-	if ((dev = pci_find_device(SIS630_VENDOR_ID, SIS630_DEVICE_ID, dev)))
+	dev = pci_find_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_630, dev);
+	if (dev)
 		pci_read_config_byte(dev, PCI_CLASS_REVISION, &host_bridge_rev);
 
 	if (netif_carrier_ok(net_dev)) {
@@ -1320,8 +1349,13 @@
 	/* discard unsent packets */
 	sis_priv->dirty_tx = sis_priv->cur_tx = 0;
 	for (i = 0; i < NUM_TX_DESC; i++) {
-		if (sis_priv->tx_skbuff[i] != NULL) {
-			dev_kfree_skb(sis_priv->tx_skbuff[i]);
+		struct sk_buff *skb = sis_priv->tx_skbuff[i];
+
+		if (skb) {
+			pci_unmap_single(sis_priv->pci_dev, 
+				sis_priv->tx_ring[i].bufptr, skb->len,
+				PCI_DMA_TODEVICE);
+			dev_kfree_skb(skb);
 			sis_priv->tx_skbuff[i] = 0;
 			sis_priv->tx_ring[i].cmdsts = 0;
 			sis_priv->tx_ring[i].bufptr = 0;
@@ -1368,7 +1402,8 @@
 	sis_priv->tx_skbuff[entry] = skb;
 
 	/* set the transmit buffer descriptor and enable Transmit State Machine */
-	sis_priv->tx_ring[entry].bufptr = virt_to_bus(skb->data);
+	sis_priv->tx_ring[entry].bufptr = pci_map_single(sis_priv->pci_dev,
+		skb->data, skb->len, PCI_DMA_TODEVICE);
 	sis_priv->tx_ring[entry].cmdsts = (OWN | skb->len);
 	outl(TxENA, ioaddr + cr);
 
@@ -1509,7 +1544,13 @@
 				break;
 			}
 
-			/* gvie the socket buffer to upper layers */
+			pci_dma_sync_single(sis_priv->pci_dev, 
+				sis_priv->rx_ring[entry].bufptr, RX_BUF_SIZE, 
+				PCI_DMA_FROMDEVICE);
+			pci_unmap_single(sis_priv->pci_dev, 
+				sis_priv->rx_ring[entry].bufptr, RX_BUF_SIZE, 
+				PCI_DMA_FROMDEVICE);
+			/* give the socket buffer to upper layers */
 			skb = sis_priv->rx_skbuff[entry];
 			skb_put(skb, rx_size);
 			skb->protocol = eth_type_trans(skb, net_dev);
@@ -1542,7 +1583,9 @@
 			skb->dev = net_dev;
 			sis_priv->rx_skbuff[entry] = skb;
 			sis_priv->rx_ring[entry].cmdsts = RX_BUF_SIZE;
-			sis_priv->rx_ring[entry].bufptr = virt_to_bus(skb->tail);
+                	sis_priv->rx_ring[entry].bufptr = 
+				pci_map_single(sis_priv->pci_dev, skb->tail, 
+					RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
 			sis_priv->dirty_rx++;
 		}
 		sis_priv->cur_rx++;
@@ -1572,7 +1615,9 @@
 			skb->dev = net_dev;
 			sis_priv->rx_skbuff[entry] = skb;
 			sis_priv->rx_ring[entry].cmdsts = RX_BUF_SIZE;
-			sis_priv->rx_ring[entry].bufptr = virt_to_bus(skb->tail);
+                	sis_priv->rx_ring[entry].bufptr =
+				pci_map_single(sis_priv->pci_dev, skb->tail,
+					RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
 		}
 	}
 	/* re-enable the potentially idle receive state matchine */
@@ -1596,6 +1641,7 @@
 	struct sis900_private *sis_priv = net_dev->priv;
 
 	for (; sis_priv->dirty_tx < sis_priv->cur_tx; sis_priv->dirty_tx++) {
+		struct sk_buff *skb;
 		unsigned int entry;
 		u32 tx_status;
 
@@ -1631,7 +1677,11 @@
 			sis_priv->stats.tx_packets++;
 		}
 		/* Free the original skb. */
-		dev_kfree_skb_irq(sis_priv->tx_skbuff[entry]);
+		skb = sis_priv->tx_skbuff[entry];
+		pci_unmap_single(sis_priv->pci_dev, 
+			sis_priv->tx_ring[entry].bufptr, skb->len,
+			PCI_DMA_TODEVICE);
+		dev_kfree_skb_irq(skb);
 		sis_priv->tx_skbuff[entry] = NULL;
 		sis_priv->tx_ring[entry].bufptr = 0;
 		sis_priv->tx_ring[entry].cmdsts = 0;
@@ -1659,6 +1709,7 @@
 {
 	long ioaddr = net_dev->base_addr;
 	struct sis900_private *sis_priv = net_dev->priv;
+	struct sk_buff *skb;
 	int i;
 
 	netif_stop_queue(net_dev);
@@ -1676,14 +1727,24 @@
 
 	/* Free Tx and RX skbuff */
 	for (i = 0; i < NUM_RX_DESC; i++) {
-		if (sis_priv->rx_skbuff[i] != NULL)
-			dev_kfree_skb(sis_priv->rx_skbuff[i]);
-		sis_priv->rx_skbuff[i] = 0;
+		skb = sis_priv->rx_skbuff[i];
+		if (skb) {
+			pci_unmap_single(sis_priv->pci_dev, 
+				sis_priv->rx_ring[i].bufptr,
+				RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
+			dev_kfree_skb(skb);
+			sis_priv->rx_skbuff[i] = 0;
+		}
 	}
 	for (i = 0; i < NUM_TX_DESC; i++) {
-		if (sis_priv->tx_skbuff[i] != NULL)
-			dev_kfree_skb(sis_priv->tx_skbuff[i]);
-		sis_priv->tx_skbuff[i] = 0;
+		skb = sis_priv->tx_skbuff[i];
+		if (skb) {
+			pci_unmap_single(sis_priv->pci_dev, 
+				sis_priv->tx_ring[i].bufptr, skb->len,
+				PCI_DMA_TODEVICE);
+			dev_kfree_skb(skb);
+			sis_priv->tx_skbuff[i] = 0;
+		}
 	}
 
 	/* Green! Put the chip in low-power mode. */
@@ -2007,6 +2068,10 @@
 		kfree(phy);
 	}
 
+	pci_free_consistent(pci_dev, RX_TOTAL_SIZE, sis_priv->rx_ring,
+		sis_priv->rx_ring_dma);
+	pci_free_consistent(pci_dev, TX_TOTAL_SIZE, sis_priv->tx_ring,
+		sis_priv->tx_ring_dma);
 	unregister_netdev(net_dev);
 	kfree(net_dev);
 	pci_release_regions(pci_dev);
diff -urN linux-2.4.7-pre6/drivers/net/sis900.h linux/drivers/net/sis900.h
--- linux-2.4.7-pre6/drivers/net/sis900.h	Mon Jul  2 14:03:04 2001
+++ linux/drivers/net/sis900.h	Mon Dec  3 22:55:49 2001
@@ -265,6 +265,9 @@
 
 #define NUM_TX_DESC     16      	/* Number of Tx descriptor registers. */
 #define NUM_RX_DESC     16       	/* Number of Rx descriptor registers. */
+#define TX_TOTAL_SIZE	NUM_TX_DESC*sizeof(BufferDesc)
+#define RX_TOTAL_SIZE	NUM_RX_DESC*sizeof(BufferDesc)
 
+/* PCI stuff, should be move to pci.h */
 #define SIS630_VENDOR_ID        0x1039
 #define SIS630_DEVICE_ID        0x0630
diff -urN linux-2.4.7-pre6/drivers/net/smc-ultra.c linux/drivers/net/smc-ultra.c
--- linux-2.4.7-pre6/drivers/net/smc-ultra.c	Wed Jun 20 11:10:53 2001
+++ linux/drivers/net/smc-ultra.c	Mon Dec  3 22:55:50 2001
@@ -10,9 +10,10 @@
 	This software may be used and distributed according to the terms
 	of the GNU General Public License, incorporated herein by reference.
 
-	The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
-	Center of Excellence in Space Data and Information Sciences
-		Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
+	The author may be reached as becker@scyld.com, or C/O
+	Scyld Computing Corporation
+	410 Severn Ave., Suite 210
+	Annapolis MD 21403
 
 	This driver uses the cards in the 8390-compatible mode.
 	Most of the run-time complexity is handled by the generic code in
diff -urN linux-2.4.7-pre6/drivers/net/smc9194.c linux/drivers/net/smc9194.c
--- linux-2.4.7-pre6/drivers/net/smc9194.c	Wed Jun 20 11:10:53 2001
+++ linux/drivers/net/smc9194.c	Mon Dec  3 22:55:50 2001
@@ -25,7 +25,7 @@
  .
  . Sources:
  .    o   SMC databook
- .    o   skeleton.c by Donald Becker ( becker@cesdis.gsfc.nasa.gov )
+ .    o   skeleton.c by Donald Becker ( becker@scyld.com )
  .    o   ( a LOT of advice from Becker as well )
  .
  . History:
diff -urN linux-2.4.7-pre6/drivers/net/sundance.c linux/drivers/net/sundance.c
--- linux-2.4.7-pre6/drivers/net/sundance.c	Mon Jul  2 14:03:04 2001
+++ linux/drivers/net/sundance.c	Mon Dec  3 22:55:50 2001
@@ -60,6 +60,8 @@
 #define TX_RING_SIZE	16
 #define TX_QUEUE_LEN	10		/* Limit ring entries actually used.  */
 #define RX_RING_SIZE	32
+#define TX_TOTAL_SIZE	TX_RING_SIZE*sizeof(struct netdev_desc)
+#define RX_TOTAL_SIZE	RX_RING_SIZE*sizeof(struct netdev_desc)
 
 /* Operational parameters that usually are not changed. */
 /* Time in jiffies before concluding the transmitter is hung. */
@@ -104,11 +106,6 @@
 KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE "  Written by Donald Becker\n"
 KERN_INFO "  http://www.scyld.com/network/sundance.html\n";
 
-/* Condensed operations for readability. */
-#define virt_to_le32desc(addr)  cpu_to_le32(virt_to_bus(addr))
-#define le32desc_to_virt(addr)  bus_to_virt(le32_to_cpu(addr))
-
-
 MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
 MODULE_DESCRIPTION("Sundance Alta Ethernet driver");
 MODULE_PARM(max_interrupt_work, "i");
@@ -265,22 +262,54 @@
    multiple times should be defined symbolically.
 */
 enum alta_offsets {
-	DMACtrl=0x00,     TxListPtr=0x04, TxDMACtrl=0x08, TxDescPoll=0x0a,
-	RxDMAStatus=0x0c, RxListPtr=0x10, RxDMACtrl=0x14, RxDescPoll=0x16,
-	LEDCtrl=0x1a, ASICCtrl=0x30,
-	EEData=0x34, EECtrl=0x36, TxThreshold=0x3c,
-	FlashAddr=0x40, FlashData=0x44, TxStatus=0x46, DownCounter=0x48,
-	IntrClear=0x4a, IntrEnable=0x4c, IntrStatus=0x4e,
-	MACCtrl0=0x50, MACCtrl1=0x52, StationAddr=0x54,
-	MaxTxSize=0x5A, RxMode=0x5c, MIICtrl=0x5e,
-	MulticastFilter0=0x60, MulticastFilter1=0x64,
-	RxOctetsLow=0x68, RxOctetsHigh=0x6a, TxOctetsLow=0x6c, TxOctetsHigh=0x6e,
-	TxFramesOK=0x70, RxFramesOK=0x72, StatsCarrierError=0x74,
-	StatsLateColl=0x75, StatsMultiColl=0x76, StatsOneColl=0x77,
-	StatsTxDefer=0x78, RxMissed=0x79, StatsTxXSDefer=0x7a, StatsTxAbort=0x7b,
-	StatsBcastTx=0x7c, StatsBcastRx=0x7d, StatsMcastTx=0x7e, StatsMcastRx=0x7f,
+	DMACtrl = 0x00,
+	TxListPtr = 0x04,
+	TxDMACtrl = 0x08,
+	TxDescPoll = 0x0a,
+	RxDMAStatus = 0x0c,
+	RxListPtr = 0x10,
+	RxDMACtrl = 0x14,
+	RxDescPoll = 0x16,
+	LEDCtrl = 0x1a,
+	ASICCtrl = 0x30,
+	EEData = 0x34,
+	EECtrl = 0x36,
+	TxThreshold = 0x3c,
+	FlashAddr = 0x40,
+	FlashData = 0x44,
+	TxStatus = 0x46,
+	DownCounter = 0x18,
+	IntrClear = 0x4a,
+	IntrEnable = 0x4c,
+	IntrStatus = 0x4e,
+	MACCtrl0 = 0x50,
+	MACCtrl1 = 0x52,
+	StationAddr = 0x54,
+	MaxTxSize = 0x5A,
+	RxMode = 0x5c,
+	MIICtrl = 0x5e,
+	MulticastFilter0 = 0x60,
+	MulticastFilter1 = 0x64,
+	RxOctetsLow = 0x68,
+	RxOctetsHigh = 0x6a,
+	TxOctetsLow = 0x6c,
+	TxOctetsHigh = 0x6e,
+	TxFramesOK = 0x70,
+	RxFramesOK = 0x72,
+	StatsCarrierError = 0x74,
+	StatsLateColl = 0x75,
+	StatsMultiColl = 0x76,
+	StatsOneColl = 0x77,
+	StatsTxDefer = 0x78,
+	RxMissed = 0x79,
+	StatsTxXSDefer = 0x7a,
+	StatsTxAbort = 0x7b,
+	StatsBcastTx = 0x7c,
+	StatsBcastRx = 0x7d,
+	StatsMcastTx = 0x7e,
+	StatsMcastRx = 0x7f,
 	/* Aliased and bogus values! */
-	RxStatus=0x0c,
+	RxStatus = 0x0c,
 };
 
 /* Bits in the interrupt status/mask registers. */
@@ -319,8 +348,13 @@
 
 /* Bits in netdev_desc.status */
 enum desc_status_bits {
-	DescOwn=0x8000, DescEndPacket=0x4000, DescEndRing=0x2000,
-	LastFrag=0x80000000, DescIntrOnTx=0x8000, DescIntrOnDMADone=0x80000000,
+	DescOwn=0x8000,
+	DescEndPacket=0x4000,
+	DescEndRing=0x2000,
+	LastFrag=0x80000000,
+	DescIntrOnTx=0x8000,
+	DescIntrOnDMADone=0x80000000,
+	DisableAlign = 0x00000001,
 };
 
 #define PRIV_ALIGN	15 	/* Required alignment mask */
@@ -329,19 +363,17 @@
 #define MII_CNT		4
 struct netdev_private {
 	/* Descriptor rings first for alignment. */
-	struct netdev_desc rx_ring[RX_RING_SIZE];
-	struct netdev_desc tx_ring[TX_RING_SIZE];
-	/* The addresses of receive-in-place skbuffs. */
+	struct netdev_desc *rx_ring;
+	struct netdev_desc *tx_ring;
 	struct sk_buff* rx_skbuff[RX_RING_SIZE];
-	/* The saved address of a sent-in-place packet/buffer, for later free(). */
 	struct sk_buff* tx_skbuff[TX_RING_SIZE];
+        dma_addr_t tx_ring_dma;
+        dma_addr_t rx_ring_dma;
 	struct net_device_stats stats;
 	struct timer_list timer;	/* Media monitoring timer. */
 	/* Frequently used values: keep some adjacent for cache effect. */
 	spinlock_t lock;
 	int chip_id, drv_flags;
-	/* Note: Cache paragraph grouped variables. */
-	struct netdev_desc *rx_head_desc;
 	unsigned int cur_rx, dirty_rx;		/* Producer/consumer ring indices */
 	unsigned int rx_buf_sz;				/* Based on MTU+slack. */
 	spinlock_t txlock;					/* Group with Tx control cache line. */
@@ -396,6 +428,9 @@
 	int irq;
 	int i, option = card_idx < MAX_UNITS ? options[card_idx] : 0;
 	long ioaddr;
+	void *ring_space;
+	dma_addr_t ring_dma;
+
 
 /* when built into the kernel, we only print version if device is found */
 #ifndef MODULE
@@ -440,6 +475,18 @@
 	np->pci_dev = pdev;
 	spin_lock_init(&np->lock);
 
+	ring_space = pci_alloc_consistent(pdev, TX_TOTAL_SIZE, &ring_dma);
+	if (!ring_space)
+		goto err_out_cleardev;
+	np->tx_ring = (struct netdev_desc *)ring_space;
+	np->tx_ring_dma = ring_dma;
+
+	ring_space = pci_alloc_consistent(pdev, RX_TOTAL_SIZE, &ring_dma);
+	if (!ring_space)
+		goto err_out_unmap_tx;
+	np->rx_ring = (struct netdev_desc *)ring_space;
+	np->rx_ring_dma = ring_dma;
+
 	if (dev->mem_start)
 		option = dev->mem_start;
 
@@ -473,7 +520,7 @@
 
 	i = register_netdev(dev);
 	if (i)
-		goto err_out_cleardev;
+		goto err_out_unmap_rx;
 
 	printk(KERN_INFO "%s: %s at 0x%lx, ",
 		   dev->name, pci_id_tbl[chip_idx].name, ioaddr);
@@ -511,6 +558,10 @@
 	card_idx++;
 	return 0;
 
+err_out_unmap_rx:
+        pci_free_consistent(pdev, RX_TOTAL_SIZE, np->rx_ring, np->rx_ring_dma);
+err_out_unmap_tx:
+        pci_free_consistent(pdev, TX_TOTAL_SIZE, np->tx_ring, np->tx_ring_dma);
 err_out_cleardev:
 	pci_set_drvdata(pdev, NULL);
 #ifndef USE_IO_OPS
@@ -549,7 +600,7 @@
 /* Set iff a MII transceiver on any interface requires mdio preamble.
    This only set with older tranceivers, so the extra
    code size of a per-interface flag is not worthwhile. */
-static char mii_preamble_required;
+static const char mii_preamble_required = 1;
 
 enum mii_reg_bits {
 	MDIO_ShiftClk=0x0001, MDIO_Data=0x0002, MDIO_EnbOutput=0x0004,
@@ -649,7 +700,7 @@
 
 	init_ring(dev);
 
-	writel(virt_to_bus(np->rx_ring), ioaddr + RxListPtr);
+	writel(np->rx_ring_dma, ioaddr + RxListPtr);
 	/* The Tx list pointer is written as packets are queued. */
 
 	for (i = 0; i < 6; i++)
@@ -665,6 +716,7 @@
 	np->mcastlock = (spinlock_t) SPIN_LOCK_UNLOCKED;
 
 	set_rx_mode(dev);
+	writew(0, ioaddr + IntrEnable);
 	writew(0, ioaddr + DownCounter);
 	/* Set the chip to poll every N*320nsec. */
 	writeb(100, ioaddr + RxDescPoll);
@@ -779,17 +831,15 @@
 	np->dirty_rx = np->dirty_tx = 0;
 
 	np->rx_buf_sz = (dev->mtu <= 1500 ? PKT_BUF_SZ : dev->mtu + 32);
-	np->rx_head_desc = &np->rx_ring[0];
 
 	/* Initialize all Rx descriptors. */
 	for (i = 0; i < RX_RING_SIZE; i++) {
-		np->rx_ring[i].next_desc = virt_to_le32desc(&np->rx_ring[i+1]);
+		np->rx_ring[i].next_desc = cpu_to_le32(np->rx_ring_dma + 
+			((i+1)%RX_RING_SIZE)*sizeof(*np->rx_ring));
 		np->rx_ring[i].status = 0;
 		np->rx_ring[i].frag[0].length = 0;
 		np->rx_skbuff[i] = 0;
 	}
-	/* Wrap the ring. */
-	np->rx_ring[i-1].next_desc = virt_to_le32desc(&np->rx_ring[0]);
 
 	/* Fill in the Rx buffers.  Handle allocation failure gracefully. */
 	for (i = 0; i < RX_RING_SIZE; i++) {
@@ -797,9 +847,11 @@
 		np->rx_skbuff[i] = skb;
 		if (skb == NULL)
 			break;
-		skb->dev = dev;			/* Mark as being used by this device. */
+		skb->dev = dev;		/* Mark as being used by this device. */
 		skb_reserve(skb, 2);	/* 16 byte align the IP header. */
-		np->rx_ring[i].frag[0].addr = virt_to_le32desc(skb->tail);
+		np->rx_ring[i].frag[0].addr = cpu_to_le32(
+			pci_map_single(np->pci_dev, skb->tail, np->rx_buf_sz, 
+				PCI_DMA_FROMDEVICE));
 		np->rx_ring[i].frag[0].length = cpu_to_le32(np->rx_buf_sz | LastFrag);
 	}
 	np->dirty_rx = (unsigned int)(i - RX_RING_SIZE);
@@ -828,11 +880,13 @@
 	txdesc->next_desc = 0;
 	/* Note: disable the interrupt generation here before releasing. */
 	txdesc->status =
-		cpu_to_le32((entry<<2) | DescIntrOnDMADone | DescIntrOnTx);
-	txdesc->frag[0].addr = virt_to_le32desc(skb->data);
+		cpu_to_le32((entry<<2) | DescIntrOnDMADone | DescIntrOnTx | DisableAlign);
+	txdesc->frag[0].addr = cpu_to_le32(pci_map_single(np->pci_dev, 
+		skb->data, skb->len, PCI_DMA_TODEVICE));
 	txdesc->frag[0].length = cpu_to_le32(skb->len | LastFrag);
 	if (np->last_tx)
-		np->last_tx->next_desc = virt_to_le32desc(txdesc);
+		np->last_tx->next_desc = cpu_to_le32(np->tx_ring_dma +
+			entry*sizeof(struct netdev_desc));
 	np->last_tx = txdesc;
 	np->cur_tx++;
 
@@ -846,7 +900,8 @@
 	}
 	/* Side effect: The read wakes the potentially-idle transmit channel. */
 	if (readl(dev->base_addr + TxListPtr) == 0)
-		writel(virt_to_bus(&np->tx_ring[entry]), dev->base_addr + TxListPtr);
+		writel(np->tx_ring_dma + entry*sizeof(*np->tx_ring),
+			dev->base_addr + TxListPtr);
 
 	dev->trans_start = jiffies;
 
@@ -873,9 +928,8 @@
 	do {
 		int intr_status = readw(ioaddr + IntrStatus);
 		writew(intr_status & (IntrRxDone | IntrRxDMADone | IntrPCIErr |
-							  IntrDrvRqst |IntrTxDone|IntrTxDMADone |
-							  StatsMax | LinkChange),
-							  ioaddr + IntrStatus);
+			IntrDrvRqst | IntrTxDone | IntrTxDMADone | StatsMax | 
+			LinkChange), ioaddr + IntrStatus);
 
 		if (debug > 4)
 			printk(KERN_DEBUG "%s: Interrupt, status %4.4x.\n",
@@ -908,8 +962,9 @@
 					if (tx_status & 0x10) {			/* Reset the Tx. */
 						writew(0x001c, ioaddr + ASICCtrl + 2);
 #if 0					/* Do we need to reset the Tx pointer here? */
-						writel(virt_to_bus(&np->tx_ring[np->dirty_tx]),
-							   dev->base_addr + TxListPtr);
+						writel(np->tx_ring_dma
+							+ np->dirty_tx*sizeof(*np->tx_ring),
+							dev->base_addr + TxListPtr);
 #endif
 					}
 					if (tx_status & 0x1e) 		/* Restart the Tx. */
@@ -924,10 +979,16 @@
 		}
 		for (; np->cur_tx - np->dirty_tx > 0; np->dirty_tx++) {
 			int entry = np->dirty_tx % TX_RING_SIZE;
+			struct sk_buff *skb;
+
 			if ( ! (np->tx_ring[entry].status & 0x00010000))
 				break;
+			skb = np->tx_skbuff[entry];
 			/* Free the original skb. */
-			dev_kfree_skb_irq(np->tx_skbuff[entry]);
+			pci_unmap_single(np->pci_dev, 
+				np->tx_ring[entry].frag[0].addr, 
+				skb->len, PCI_DMA_TODEVICE);
+			dev_kfree_skb_irq(skb);
 			np->tx_skbuff[entry] = 0;
 		}
 		if (np->tx_full
@@ -947,6 +1008,7 @@
 				   "status=0x%4.4x / 0x%4.4x.\n",
 				   dev->name, intr_status, readw(ioaddr + IntrClear));
 			/* Re-enable us in 3.2msec. */
+			writew(0, ioaddr + IntrEnable);
 			writew(1000, ioaddr + DownCounter);
 			writew(IntrDrvRqst, ioaddr + IntrEnable);
 			break;
@@ -974,16 +1036,23 @@
 	}
 
 	/* If EOP is set on the next entry, it's a new packet. Send it up. */
-	while (np->rx_head_desc->status & DescOwn) {
-		struct netdev_desc *desc = np->rx_head_desc;
-		u32 frame_status = le32_to_cpu(desc->status);
-		int pkt_len = frame_status & 0x1fff;		/* Chip omits the CRC. */
+	while (1) {
+		struct netdev_desc *desc = &(np->rx_ring[entry]);
+		u32 frame_status;
+		int pkt_len;
 
+		if (!(desc->status & DescOwn))
+			break;
+		frame_status = le32_to_cpu(desc->status);
+		pkt_len = frame_status & 0x1fff;	/* Chip omits the CRC. */
 		if (debug > 4)
 			printk(KERN_DEBUG "  netdev_rx() status was %8.8x.\n",
 				   frame_status);
 		if (--boguscnt < 0)
 			break;
+		pci_dma_sync_single(np->pci_dev, desc->frag[0].addr,
+			np->rx_buf_sz, PCI_DMA_FROMDEVICE);
+		
 		if (frame_status & 0x001f4000) {
 			/* There was a error. */
 			if (debug > 2)
@@ -1017,6 +1086,10 @@
 				eth_copy_and_sum(skb, np->rx_skbuff[entry]->tail, pkt_len, 0);
 				skb_put(skb, pkt_len);
 			} else {
+				pci_unmap_single(np->pci_dev, 
+					desc->frag[0].addr,
+					np->rx_buf_sz, 
+					PCI_DMA_FROMDEVICE);
 				skb_put(skb = np->rx_skbuff[entry], pkt_len);
 				np->rx_skbuff[entry] = NULL;
 			}
@@ -1026,7 +1099,6 @@
 			dev->last_rx = jiffies;
 		}
 		entry = (++np->cur_rx) % RX_RING_SIZE;
-		np->rx_head_desc = &np->rx_ring[entry];
 	}
 
 	/* Refill the Rx ring buffers. */
@@ -1037,10 +1109,12 @@
 			skb = dev_alloc_skb(np->rx_buf_sz);
 			np->rx_skbuff[entry] = skb;
 			if (skb == NULL)
-				break;				/* Better luck next round. */
-			skb->dev = dev;			/* Mark as being used by this device. */
+				break;		/* Better luck next round. */
+			skb->dev = dev;		/* Mark as being used by this device. */
 			skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */
-			np->rx_ring[entry].frag[0].addr = virt_to_le32desc(skb->tail);
+			np->rx_ring[entry].frag[0].addr = cpu_to_le32(
+				pci_map_single(np->pci_dev, skb->tail, 
+					np->rx_buf_sz, PCI_DMA_FROMDEVICE));
 		}
 		/* Perhaps we need not reset this field. */
 		np->rx_ring[entry].frag[0].length =
@@ -1060,6 +1134,7 @@
 	if (intr_status & IntrDrvRqst) {
 		/* Stop the down counter and turn interrupts back on. */
 		printk("%s: Turning interrupts back on.\n", dev->name);
+		writew(0, ioaddr + IntrEnable);
 		writew(0, ioaddr + DownCounter);
 		writew(IntrRxDone | IntrRxDMADone | IntrPCIErr | IntrDrvRqst |
 			   IntrTxDone | StatsMax | LinkChange, ioaddr + IntrEnable);
@@ -1226,6 +1301,7 @@
 {
 	long ioaddr = dev->base_addr;
 	struct netdev_private *np = dev->priv;
+	struct sk_buff *skb;
 	int i;
 
 	netif_stop_queue(dev);
@@ -1248,13 +1324,13 @@
 #ifdef __i386__
 	if (debug > 2) {
 		printk("\n"KERN_DEBUG"  Tx ring at %8.8x:\n",
-			   (int)virt_to_bus(np->tx_ring));
+			   (int)(np->tx_ring_dma));
 		for (i = 0; i < TX_RING_SIZE; i++)
 			printk(" #%d desc. %4.4x %8.8x %8.8x.\n",
 				   i, np->tx_ring[i].status, np->tx_ring[i].frag[0].addr,
 				   np->tx_ring[i].frag[0].length);
 		printk("\n"KERN_DEBUG "  Rx ring %8.8x:\n",
-			   (int)virt_to_bus(np->rx_ring));
+			   (int)(np->rx_ring_dma));
 		for (i = 0; i < /*RX_RING_SIZE*/4 ; i++) {
 			printk(KERN_DEBUG " #%d desc. %4.4x %4.4x %8.8x\n",
 				   i, np->rx_ring[i].status, np->rx_ring[i].frag[0].addr,
@@ -1271,15 +1347,24 @@
 	for (i = 0; i < RX_RING_SIZE; i++) {
 		np->rx_ring[i].status = 0;
 		np->rx_ring[i].frag[0].addr = 0xBADF00D0; /* An invalid address. */
-		if (np->rx_skbuff[i]) {
-			dev_kfree_skb(np->rx_skbuff[i]);
+		skb = np->rx_skbuff[i];
+		if (skb) {
+			pci_unmap_single(np->pci_dev, 
+				np->rx_ring[i].frag[0].addr, np->rx_buf_sz, 
+				PCI_DMA_FROMDEVICE);
+			dev_kfree_skb(skb);
+			np->rx_skbuff[i] = 0;
 		}
-		np->rx_skbuff[i] = 0;
 	}
 	for (i = 0; i < TX_RING_SIZE; i++) {
-		if (np->tx_skbuff[i])
-			dev_kfree_skb(np->tx_skbuff[i]);
-		np->tx_skbuff[i] = 0;
+		skb = np->tx_skbuff[i];
+		if (skb) {
+			pci_unmap_single(np->pci_dev, 
+				np->tx_ring[i].frag[0].addr, skb->len,
+				PCI_DMA_TODEVICE);
+			dev_kfree_skb(skb);
+			np->tx_skbuff[i] = 0;
+		}
 	}
 
 	return 0;
@@ -1291,15 +1376,20 @@
 	
 	/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
 	if (dev) {
+		struct netdev_private *np = dev->priv;
+
 		unregister_netdev(dev);
+        	pci_free_consistent(pdev, RX_TOTAL_SIZE, np->rx_ring, 
+			np->rx_ring_dma);
+	        pci_free_consistent(pdev, TX_TOTAL_SIZE, np->tx_ring, 
+			np->tx_ring_dma);
 		pci_release_regions(pdev);
 #ifndef USE_IO_OPS
 		iounmap((char *)(dev->base_addr));
 #endif
 		kfree(dev);
+		pci_set_drvdata(pdev, NULL);
 	}
-
-	pci_set_drvdata(pdev, NULL);
 }
 
 static struct pci_driver sundance_driver = {
diff -urN linux-2.4.7-pre6/drivers/net/tokenring/ibmtr.c linux/drivers/net/tokenring/ibmtr.c
--- linux-2.4.7-pre6/drivers/net/tokenring/ibmtr.c	Mon Dec  3 22:55:41 2001
+++ linux/drivers/net/tokenring/ibmtr.c	Mon Dec  3 22:55:50 2001
@@ -7,7 +7,7 @@
  *	This device driver should work with Any IBM Token Ring Card that does
  *	not use DMA.
  *
- *	I used Donald Becker's (becker@cesdis.gsfc.nasa.gov) device driver work
+ *	I used Donald Becker's (becker@scyld.com) device driver work
  *	as a base for most of my initial work.
  *
  *	Changes by Peter De Schrijver
diff -urN linux-2.4.7-pre6/drivers/net/tulip/21142.c linux/drivers/net/tulip/21142.c
--- linux-2.4.7-pre6/drivers/net/tulip/21142.c	Wed Jun 20 11:15:44 2001
+++ linux/drivers/net/tulip/21142.c	Mon Dec  3 22:55:50 2001
@@ -195,7 +195,7 @@
 				}
 		}
 		if ( ! setup_done) {
-			tp->csr6 = dev->if_port & 1 ? 0x83860000 : 0x82420000;
+			tp->csr6 = (dev->if_port & 1 ? 0x838E0000 : 0x82420000) | (tp->csr6 & 0x20ff);
 			if (tp->full_duplex)
 				tp->csr6 |= 0x0200;
 			outl(1, ioaddr + CSR13);
@@ -230,7 +230,8 @@
 			t21142_start_nway(dev);
 			tp->timer.expires = RUN_AT(3*HZ);
 			add_timer(&tp->timer);
-		}
+		} else if (dev->if_port == 5)
+			outl(inl(ioaddr + CSR14) & ~0x080, ioaddr + CSR14);
 	} else if (dev->if_port == 0  ||  dev->if_port == 4) {
 		if ((csr12 & 4) == 0)
 			printk(KERN_INFO"%s: 21143 10baseT link beat good.\n",
@@ -249,7 +250,7 @@
 			printk(KERN_INFO"%s: 21143 100baseTx sensed media.\n",
 				   dev->name);
 		dev->if_port = 3;
-		tp->csr6 = 0x83860000;
+		tp->csr6 = 0x838E0000 | (tp->csr6 & 0x20ff);
 		outl(0x0003FF7F, ioaddr + CSR14);
 		outl(0x0301, ioaddr + CSR12);
 		tulip_restart_rxtx(tp);
diff -urN linux-2.4.7-pre6/drivers/net/tulip/ChangeLog linux/drivers/net/tulip/ChangeLog
--- linux-2.4.7-pre6/drivers/net/tulip/ChangeLog	Wed Jun 20 11:19:02 2001
+++ linux/drivers/net/tulip/ChangeLog	Mon Dec  3 22:55:50 2001
@@ -1,3 +1,35 @@
+2001-07-17  Erik A. Hendriks  <hendriks@lanl.gov>
+
+	* 21142.c: Merge fix from tulip.c 0.92w which prevents the
+	overwriting of csr6 bits we want to preserve.
+
+2001-07-10  Jeff Golds  <jgolds@resilience.com>
+
+	* tulip_core.c: Fix two comments
+
+2001-07-06  Stephen Degler  <sdegler@degler.net>
+
+	* media.c:
+	The media selection process at the end of NWAY is busted
+	because for the case of MII/SYM it needs to be:
+
+        csr13 <- 0
+        csr14 <- 0
+        csr6 <-  the value calculated is okay.
+
+	In the other media cases csr14 is computed by
+	t21142_csr14val[dev->if_port], which seems ok.  The value of
+	zero as opposed to 3FFFFF comes straight from appendix D of the
+	21143 data book, and it makes logical sense because you're
+	bypassing all the SIA interface when you usa MII or SYM (see
+	figure 1-1 in the data book if your're visually oriented)
+
+2001-07-03  Jeff Golds  <jgolds@resilience.com>
+
+	* tulip_core.c (tulip_clean_tx_ring):
+	Clear status for in-progress Tx's, and count
+	Tx errors for all packets being released.
+
 2001-06-16  Jeff Garzik  <jgarzik@mandrakesoft.com>
 
 	* tulip.h, tulip_core.c:
diff -urN linux-2.4.7-pre6/drivers/net/tulip/media.c linux/drivers/net/tulip/media.c
--- linux-2.4.7-pre6/drivers/net/tulip/media.c	Wed Jun 20 11:15:44 2001
+++ linux/drivers/net/tulip/media.c	Mon Dec  3 22:55:50 2001
@@ -232,7 +232,7 @@
 				outl(csr13val, ioaddr + CSR13);
 			} else {
 				csr13val = 1;
-				csr14val = 0x0003FFFF;
+				csr14val = 0;
 				csr15dir = (setup[0]<<16) | 0x0008;
 				csr15val = (setup[1]<<16) | 0x0008;
 				if (dev->if_port <= 4)
diff -urN linux-2.4.7-pre6/drivers/net/tulip/tulip_core.c linux/drivers/net/tulip/tulip_core.c
--- linux-2.4.7-pre6/drivers/net/tulip/tulip_core.c	Mon Jul  2 14:03:04 2001
+++ linux/drivers/net/tulip/tulip_core.c	Mon Dec  3 22:55:50 2001
@@ -742,7 +742,7 @@
 	return 0;
 }
 
-static void tulip_release_unconsumed_tx_buffers(struct tulip_private *tp)
+static void tulip_clean_tx_ring(struct tulip_private *tp)
 {
 	unsigned int dirty_tx;
 
@@ -751,10 +751,12 @@
 		int entry = dirty_tx % TX_RING_SIZE;
 		int status = le32_to_cpu(tp->tx_ring[entry].status);
 
-		if (status > 0)
-			break;		/* It has been Txed */
+		if (status < 0) {
+			tp->stats.tx_errors++;	/* It wasn't Txed */
+			tp->tx_ring[entry].status = 0;
+		}
 
-		/* Check for Rx filter setup frames. */
+		/* Check for Tx filter setup frames. */
 		if (tp->tx_buffers[entry].skb == NULL) {
 			/* test because dummy frames not mapped */
 			if (tp->tx_buffers[entry].mapping)
@@ -764,7 +766,6 @@
 					PCI_DMA_TODEVICE);
 			continue;
 		}
-		tp->stats.tx_errors++;
 
 		pci_unmap_single(tp->pdev, tp->tx_buffers[entry].mapping,
 				tp->tx_buffers[entry].skb->len,
@@ -797,7 +798,7 @@
 	tulip_refill_rx(dev);
 
 	/* release any unconsumed transmit buffers */
-	tulip_release_unconsumed_tx_buffers(tp);
+	tulip_clean_tx_ring(tp);
 
 	/* 21040 -- Leave the card in 10baseT state. */
 	if (tp->chip_id == DC21040)
@@ -1434,7 +1435,7 @@
 	ioaddr = pci_resource_start (pdev, 0);
 	irq = pdev->irq;
 
-	/* init_etherdev ensures aligned and zeroed private structures */
+	/* alloc_etherdev ensures aligned and zeroed private structures */
 	dev = alloc_etherdev (sizeof (*tp));
 	if (!dev) {
 		printk (KERN_ERR PFX "ether device alloc failed, aborting\n");
@@ -1467,7 +1468,7 @@
 
 	/*
 	 * initialize private data structure 'tp'
-	 * it is zeroed and aligned in init_etherdev
+	 * it is zeroed and aligned in alloc_etherdev
 	 */
 	tp = dev->priv;
 
diff -urN linux-2.4.7-pre6/drivers/net/via-rhine.c linux/drivers/net/via-rhine.c
--- linux-2.4.7-pre6/drivers/net/via-rhine.c	Mon Jul  2 14:03:04 2001
+++ linux/drivers/net/via-rhine.c	Mon Dec  3 22:55:50 2001
@@ -64,6 +64,11 @@
 	                 (media selection + eeprom reload)
 	- David Vrabel:  merges from D-Link "1.11" version
 	                 (disable WOL and PME on startup)
+
+	LK1.1.10:
+	- Manfred Spraul: use "singlecopy" for unaligned buffers
+	                  don't allocate bounce buffers for !ReqTxAlign cards
+
 */
 
 
@@ -118,7 +123,6 @@
 /* max time out delay time */
 #define W_MAX_TIMEOUT	0x0FFFU
 
-
 #if !defined(__OPTIMIZE__)  ||  !defined(__KERNEL__)
 #warning  You must compile this file with the correct options!
 #warning  See the last lines of the source file.
@@ -147,7 +151,7 @@
 
 /* These identify the driver base version and may not be removed. */
 static char version[] __devinitdata =
-KERN_INFO "via-rhine.c:v1.10-LK1.1.9  05/31/2001  Written by Donald Becker\n"
+KERN_INFO "via-rhine.c:v1.10-LK1.1.10  07/12/2001  Written by Donald Becker\n"
 KERN_INFO "  http://www.scyld.com/network/via-rhine.html\n";
 
 static char shortname[] __devinitdata = "via-rhine";
@@ -641,6 +645,8 @@
 	dev->do_ioctl = mii_ioctl;
 	dev->tx_timeout = via_rhine_tx_timeout;
 	dev->watchdog_timeo = TX_TIMEOUT;
+	if (np->drv_flags & ReqTxAlign)
+		dev->features |= NETIF_F_SG|NETIF_F_HW_CSUM;
 	
 	i = register_netdev(dev);
 	if (i)
@@ -723,14 +729,16 @@
 		printk(KERN_ERR "Could not allocate DMA memory.\n");
 		return -ENOMEM;
 	}
-	np->tx_bufs = pci_alloc_consistent(np->pdev, PKT_BUF_SZ * TX_RING_SIZE,
+	if (np->drv_flags & ReqTxAlign) {
+		np->tx_bufs = pci_alloc_consistent(np->pdev, PKT_BUF_SZ * TX_RING_SIZE,
 								   &np->tx_bufs_dma);
-	if (np->tx_bufs == NULL) {
-		pci_free_consistent(np->pdev, 
-			    RX_RING_SIZE * sizeof(struct rx_desc) +
-			    TX_RING_SIZE * sizeof(struct tx_desc),
-			    ring, ring_dma);
-		return -ENOMEM;
+		if (np->tx_bufs == NULL) {
+			pci_free_consistent(np->pdev, 
+				    RX_RING_SIZE * sizeof(struct rx_desc) +
+				    TX_RING_SIZE * sizeof(struct tx_desc),
+				    ring, ring_dma);
+			return -ENOMEM;
+		}
 	}
 
 	np->rx_ring = ring;
@@ -738,7 +746,6 @@
 	np->rx_ring_dma = ring_dma;
 	np->tx_ring_dma = ring_dma + RX_RING_SIZE * sizeof(struct rx_desc);
 
-
 	return 0;
 }
 
@@ -1100,17 +1107,23 @@
 	/* Caution: the write order is important here, set the field
 	   with the "ownership" bits last. */
 
-	/* lock eth irq */
-	spin_lock_irq (&np->lock);
-
 	/* Calculate the next Tx descriptor entry. */
 	entry = np->cur_tx % TX_RING_SIZE;
 
 	np->tx_skbuff[entry] = skb;
 
-	if ((np->drv_flags & ReqTxAlign) && ((long)skb->data & 3)) {
+	if ((np->drv_flags & ReqTxAlign) &&
+		(((long)skb->data & 3) || skb_shinfo(skb)->nr_frags != 0 || skb->ip_summed == CHECKSUM_HW)
+		) {
 		/* Must use alignment buffer. */
-		memcpy(np->tx_buf[entry], skb->data, skb->len);
+		if (skb->len > PKT_BUF_SZ) {
+			/* packet too long, drop it */
+			dev_kfree_skb(skb);
+			np->tx_skbuff[entry] = NULL;
+			np->stats.tx_dropped++;
+			return 0;
+		}
+		skb_copy_and_csum_dev(skb, np->tx_buf[entry]);
 		np->tx_skbuff_dma[entry] = 0;
 		np->tx_ring[entry].addr = cpu_to_le32(np->tx_bufs_dma +
 										  (np->tx_buf[entry] - np->tx_bufs));
@@ -1122,7 +1135,12 @@
 
 	np->tx_ring[entry].desc_length = 
 		cpu_to_le32(0x00E08000 | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN));
+
+	/* lock eth irq */
+	spin_lock_irq (&np->lock);
+	wmb();
 	np->tx_ring[entry].tx_status = cpu_to_le32(DescOwn);
+	wmb();
 
 	np->cur_tx++;
 
diff -urN linux-2.4.7-pre6/drivers/net/wan/sbni.c linux/drivers/net/wan/sbni.c
--- linux-2.4.7-pre6/drivers/net/wan/sbni.c	Tue Mar 20 12:05:01 2001
+++ linux/drivers/net/wan/sbni.c	Mon Dec  3 22:55:50 2001
@@ -22,7 +22,7 @@
  *   //      - for bug hunting and many ideas
  *   //   Alan Cox (Alan.Cox@linux.org)
  *   //	     - for consulting in some hardcore questions
- *   //   Donald Becker (becker@cesdis.gsfc.nasa.gov)
+ *   //   Donald Becker (becker@scyld.com)
  *   //      - for pretty nice skeleton 
  * 
  *   More info and useful utilities to work w/ SBNI you can find at 
diff -urN linux-2.4.7-pre6/drivers/net/wavelan.c linux/drivers/net/wavelan.c
--- linux-2.4.7-pre6/drivers/net/wavelan.c	Wed Apr 25 14:36:23 2001
+++ linux/drivers/net/wavelan.c	Mon Dec  3 22:55:50 2001
@@ -4302,7 +4302,7 @@
  * It is based on other device drivers and information
  * either written or supplied by:
  *	Ajay Bakre (bakre@paul.rutgers.edu),
- *	Donald Becker (becker@cesdis.gsfc.nasa.gov),
+ *	Donald Becker (becker@scyld.com),
  *	Loeke Brederveld (Loeke.Brederveld@Utrecht.NCR.com),
  *	Anders Klemets (klemets@it.kth.se),
  *	Vladimir V. Kolpakov (w@stier.koenig.ru),
diff -urN linux-2.4.7-pre6/drivers/net/wd.c linux/drivers/net/wd.c
--- linux-2.4.7-pre6/drivers/net/wd.c	Wed Jun 20 11:10:53 2001
+++ linux/drivers/net/wd.c	Mon Dec  3 22:55:50 2001
@@ -8,9 +8,10 @@
 	This software may be used and distributed according to the terms
 	of the GNU General Public License, incorporated herein by reference.
 
-	The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
-	Center of Excellence in Space Data and Information Sciences
-	   Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
+	The author may be reached as becker@scyld.com, or C/O
+	Scyld Computing Corporation
+	410 Severn Ave., Suite 210
+	Annapolis MD 21403
 
 	This is a driver for WD8003 and WD8013 "compatible" ethercards.
 
diff -urN linux-2.4.7-pre6/drivers/net/winbond-840.c linux/drivers/net/winbond-840.c
--- linux-2.4.7-pre6/drivers/net/winbond-840.c	Mon Jul  2 14:03:04 2001
+++ linux/drivers/net/winbond-840.c	Mon Dec  3 22:55:50 2001
@@ -32,15 +32,19 @@
 		synchronize tx_q_bytes
 		software reset in tx_timeout
 			Copyright (C) 2000 Manfred Spraul
-
+	* further cleanups
+		power management.
+		support for big endian descriptors
+			Copyright (C) 2001 Manfred Spraul
+  
 	TODO:
-	* according to the documentation, the chip supports big endian
-		descriptors. Remove cpu_to_le32, enable BE descriptors.
+	* enable pci_power_off
+	* Wake-On-LAN
 */
-
+  
 #define DRV_NAME	"winbond-840"
-#define DRV_VERSION	"1.01"
-#define DRV_RELDATE	"5/15/2000"
+#define DRV_VERSION	"1.01-c"
+#define DRV_RELDATE	"6/30/2000"
 
 
 /* Automatically extracted configuration info:
@@ -86,8 +90,11 @@
    There are no ill effects from too-large receive rings. */
 #define TX_RING_SIZE	16
 #define TX_QUEUE_LEN	10		/* Limit ring entries actually used.  */
+#define TX_QUEUE_LEN_RESTART	5
 #define RX_RING_SIZE	32
 
+#define TX_BUFLIMIT	(1024-128)
+
 /* The presumed FIFO size for working around the Tx-FIFO-overflow bug.
    To avoid overflowing we don't queue again until we have room for a
    full-size packet.
@@ -95,7 +102,6 @@
 #define TX_FIFO_SIZE (2048)
 #define TX_BUG_FIFO_LIMIT (TX_FIFO_SIZE-1514-16)
 
-#define TX_BUFLIMIT	(1024-128)
 
 /* Operational parameters that usually are not changed. */
 /* Time in jiffies before concluding the transmitter is hung. */
@@ -129,10 +135,12 @@
 #include <linux/delay.h>
 #include <linux/ethtool.h>
 #include <linux/mii.h>
+#include <linux/rtnetlink.h>
 #include <asm/uaccess.h>
 #include <asm/processor.h>		/* Processor type for cache alignment. */
 #include <asm/bitops.h>
 #include <asm/io.h>
+#include <asm/irq.h>
 
 /* These identify the driver base version and may not be removed. */
 static char version[] __devinitdata =
@@ -197,6 +205,8 @@
 correctly detect a full FIFO, and queuing more than 2048 bytes may result in
 silent data corruption.
 
+Test with 'ping -s 10000' on a fast computer.
+
 */
 
 
@@ -316,7 +326,7 @@
 struct w840_tx_desc {
 	s32 status;
 	s32 length;
-	u32 buffer1, buffer2;				/* We use only buffer 1.  */
+	u32 buffer1, buffer2;
 };
 
 /* Bits in network_desc.status */
@@ -349,35 +359,36 @@
 	unsigned int cur_rx, dirty_rx;		/* Producer/consumer ring indices */
 	unsigned int rx_buf_sz;				/* Based on MTU+slack. */
 	unsigned int cur_tx, dirty_tx;
-	int tx_q_bytes;
-	unsigned int tx_full:1;				/* The Tx queue is full. */
+	unsigned int tx_q_bytes;
+	unsigned int tx_full;				/* The Tx queue is full. */
 	/* These values are keep track of the transceiver/media in use. */
 	unsigned int full_duplex:1;			/* Full-duplex operation requested. */
 	unsigned int duplex_lock:1;
-	unsigned int medialock:1;			/* Do not sense media. */
-	unsigned int default_port:4;		/* Last dev->if_port value. */
 	/* MII transceiver section. */
 	int mii_cnt;						/* MII device addresses. */
 	u16 advertising;					/* NWay media advertisement */
 	unsigned char phys[MII_CNT];		/* MII device addresses, but only the first is used */
+	u32 mii;
 };
 
 static int  eeprom_read(long ioaddr, int location);
 static int  mdio_read(struct net_device *dev, int phy_id, int location);
 static void mdio_write(struct net_device *dev, int phy_id, int location, int value);
 static int  netdev_open(struct net_device *dev);
-static void check_duplex(struct net_device *dev);
+static int  update_link(struct net_device *dev);
 static void netdev_timer(unsigned long data);
 static void init_rxtx_rings(struct net_device *dev);
 static void free_rxtx_rings(struct netdev_private *np);
 static void init_registers(struct net_device *dev);
 static void tx_timeout(struct net_device *dev);
-static int alloc_ring(struct net_device *dev);
+static int alloc_ringdesc(struct net_device *dev);
+static void free_ringdesc(struct netdev_private *np);
 static int  start_tx(struct sk_buff *skb, struct net_device *dev);
 static void intr_handler(int irq, void *dev_instance, struct pt_regs *regs);
 static void netdev_error(struct net_device *dev, int intr_status);
 static int  netdev_rx(struct net_device *dev);
 static inline unsigned ether_crc(int length, unsigned char *data);
+static u32 __set_rx_mode(struct net_device *dev);
 static void set_rx_mode(struct net_device *dev);
 static struct net_device_stats *get_stats(struct net_device *dev);
 static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
@@ -425,7 +436,6 @@
 		goto err_out_free_res;
 #endif
 
-	/* Warning: broken for big-endian machines. */
 	for (i = 0; i < 3; i++)
 		((u16 *)dev->dev_addr)[i] = le16_to_cpu(eeprom_read(ioaddr, i));
 
@@ -451,9 +461,9 @@
 	if (option > 0) {
 		if (option & 0x200)
 			np->full_duplex = 1;
-		np->default_port = option & 15;
-		if (np->default_port)
-			np->medialock = 1;
+		if (option & 15)
+			printk(KERN_INFO "%s: ignoring user supplied media type %d",
+				dev->name, option & 15);
 	}
 	if (find_cnt < MAX_UNITS  &&  full_duplex[find_cnt] > 0)
 		np->full_duplex = 1;
@@ -488,9 +498,11 @@
 			if (mii_status != 0xffff  &&  mii_status != 0x0000) {
 				np->phys[phy_idx++] = phy;
 				np->advertising = mdio_read(dev, phy, 4);
-				printk(KERN_INFO "%s: MII PHY found at address %d, status "
+				np->mii = (mdio_read(dev, phy, 2) << 16)+
+						mdio_read(dev, phy, 3);
+				printk(KERN_INFO "%s: MII PHY %8.8xh found at address %d, status "
 					   "0x%4.4x advertising %4.4x.\n",
-					   dev->name, phy, mii_status, np->advertising);
+					   dev->name, np->mii, phy, mii_status, np->advertising);
 			}
 		}
 		np->mii_cnt = phy_idx;
@@ -673,18 +685,22 @@
 
 	writel(0x00000001, ioaddr + PCIBusCfg);		/* Reset */
 
+	netif_device_detach(dev);
 	i = request_irq(dev->irq, &intr_handler, SA_SHIRQ, dev->name, dev);
 	if (i)
-		return i;
+		goto out_err;
 
 	if (debug > 1)
 		printk(KERN_DEBUG "%s: w89c840_open() irq %d.\n",
 			   dev->name, dev->irq);
 
-	if((i=alloc_ring(dev)))
-		return i;
+	if((i=alloc_ringdesc(dev)))
+		goto out_err;
 
+	spin_lock_irq(&np->lock);
+	netif_device_attach(dev);
 	init_registers(dev);
+	spin_unlock_irq(&np->lock);
 
 	netif_start_queue(dev);
 	if (debug > 2)
@@ -692,33 +708,119 @@
 
 	/* Set the timer to check for link beat. */
 	init_timer(&np->timer);
-	np->timer.expires = jiffies + 3*HZ;
+	np->timer.expires = jiffies + 1*HZ;
 	np->timer.data = (unsigned long)dev;
 	np->timer.function = &netdev_timer;				/* timer handler */
 	add_timer(&np->timer);
-
 	return 0;
+out_err:
+	netif_device_attach(dev);
+	return i;
 }
 
-static void check_duplex(struct net_device *dev)
+#define MII_DAVICOM_DM9101	0x0181b800
+
+static int update_link(struct net_device *dev)
 {
 	struct netdev_private *np = dev->priv;
-	int mii_reg5 = mdio_read(dev, np->phys[0], 5);
-	int negotiated =  mii_reg5 & np->advertising;
-	int duplex;
+	int duplex, fasteth, result, mii_reg;
 
-	if (np->duplex_lock  ||  mii_reg5 == 0xffff)
-		return;
-	duplex = (negotiated & 0x0100) || (negotiated & 0x01C0) == 0x0040;
-	if (np->full_duplex != duplex) {
-		np->full_duplex = duplex;
+	/* BSMR */
+	mii_reg = mdio_read(dev, np->phys[0], 1);
+
+	if (mii_reg == 0xffff)
+		return np->csr6;
+	/* reread: the link status bit is sticky */
+	mii_reg = mdio_read(dev, np->phys[0], 1);
+	if (!(mii_reg & 0x4)) {
+		if (netif_carrier_ok(dev)) {
+			if (debug)
+				printk(KERN_INFO "%s: MII #%d reports no link. Disabling watchdog.\n",
+					dev->name, np->phys[0]);
+			netif_carrier_off(dev);
+		}
+		return np->csr6;
+	}
+	if (!netif_carrier_ok(dev)) {
 		if (debug)
-			printk(KERN_INFO "%s: Setting %s-duplex based on MII #%d "
-				   "negotiated capability %4.4x.\n", dev->name,
-				   duplex ? "full" : "half", np->phys[0], negotiated);
-		np->csr6 &= ~0x200;
-		np->csr6 |= duplex ? 0x200 : 0;
+			printk(KERN_INFO "%s: MII #%d link is back. Enabling watchdog.\n",
+				dev->name, np->phys[0]);
+		netif_carrier_on(dev);
 	}
+	
+	if ((np->mii & ~0xf) == MII_DAVICOM_DM9101) {
+		/* If the link partner doesn't support autonegotiation
+		 * the MII detects it's abilities with the "parallel detection".
+		 * Some MIIs update the LPA register to the result of the parallel
+		 * detection, some don't.
+		 * The Davicom PHY [at least 0181b800] doesn't.
+		 * Instead bit 9 and 13 of the BMCR are updated to the result
+		 * of the negotiation..
+		 */
+		mii_reg = mdio_read(dev, np->phys[0], 0);
+		duplex = mii_reg & 0x100;
+		fasteth = mii_reg & 0x2000;
+	} else {
+		int negotiated;
+		mii_reg	= mdio_read(dev, np->phys[0], 5);
+		negotiated = mii_reg & np->advertising;
+
+		duplex = (negotiated & 0x0100) || ((negotiated & 0x02C0) == 0x0040);
+		fasteth = negotiated & 0x380;
+	}
+	duplex |= np->duplex_lock;
+	/* remove fastether and fullduplex */
+	result = np->csr6 & ~0x20000200;
+	if (duplex)
+		result |= 0x200;
+	if (fasteth)
+		result |= 0x20000000;
+	if (result != np->csr6 && debug)
+		printk(KERN_INFO "%s: Setting %dMBit-%s-duplex based on MII#%d\n",
+				 dev->name, fasteth ? 100 : 10, 
+			   	duplex ? "full" : "half", np->phys[0]);
+	return result;
+}
+
+#define RXTX_TIMEOUT	2000
+static inline void update_csr6(struct net_device *dev, int new)
+{
+	struct netdev_private *np = dev->priv;
+	long ioaddr = dev->base_addr;
+	int limit = RXTX_TIMEOUT;
+
+	if (!netif_device_present(dev))
+		new = 0;
+	if (new==np->csr6)
+		return;
+	/* stop both Tx and Rx processes */
+	writel(np->csr6 & ~0x2002, ioaddr + NetworkConfig);
+	/* wait until they have really stopped */
+	for (;;) {
+		int csr5 = readl(ioaddr + IntrStatus);
+		int t;
+
+		t = (csr5 >> 17) & 0x07;
+		if (t==0||t==1) {
+			/* rx stopped */
+			t = (csr5 >> 20) & 0x07;
+			if (t==0||t==1)
+				break;
+		}
+
+		limit--;
+		if(!limit) {
+			printk(KERN_INFO "%s: couldn't stop rxtx, IntrStatus %xh.\n",
+					dev->name, csr5);
+			break;
+		}
+		udelay(1);
+	}
+	np->csr6 = new;
+	/* and restart them with the new configuration */
+	writel(np->csr6, ioaddr + NetworkConfig);
+	if (new & 0x200)
+		np->full_duplex = 1;
 }
 
 static void netdev_timer(unsigned long data)
@@ -726,8 +828,6 @@
 	struct net_device *dev = (struct net_device *)data;
 	struct netdev_private *np = dev->priv;
 	long ioaddr = dev->base_addr;
-	int next_tick = 10*HZ;
-	int old_csr6 = np->csr6;
 
 	if (debug > 2)
 		printk(KERN_DEBUG "%s: Media selection timer tick, status %8.8x "
@@ -735,13 +835,9 @@
 			   dev->name, (int)readl(ioaddr + IntrStatus),
 			   (int)readl(ioaddr + NetworkConfig));
 	spin_lock_irq(&np->lock);
-	check_duplex(dev);
-	if (np->csr6 != old_csr6) {
-		writel(np->csr6 & ~0x0002, ioaddr + NetworkConfig);
-		writel(np->csr6 | 0x2002, ioaddr + NetworkConfig);
-	}
+	update_csr6(dev, update_link(dev));
 	spin_unlock_irq(&np->lock);
-	np->timer.expires = jiffies + next_tick;
+	np->timer.expires = jiffies + 10*HZ;
 	add_timer(&np->timer);
 }
 
@@ -755,12 +851,12 @@
 
 	/* Initial all Rx descriptors. */
 	for (i = 0; i < RX_RING_SIZE; i++) {
-		np->rx_ring[i].length = cpu_to_le32(np->rx_buf_sz);
+		np->rx_ring[i].length = np->rx_buf_sz;
 		np->rx_ring[i].status = 0;
 		np->rx_skbuff[i] = 0;
 	}
 	/* Mark the last entry as wrapping the ring. */
-	np->rx_ring[i-1].length |= cpu_to_le32(DescEndRing);
+	np->rx_ring[i-1].length |= DescEndRing;
 
 	/* Fill in the Rx buffers.  Handle allocation failure gracefully. */
 	for (i = 0; i < RX_RING_SIZE; i++) {
@@ -772,8 +868,8 @@
 		np->rx_addr[i] = pci_map_single(np->pci_dev,skb->tail,
 					skb->len,PCI_DMA_FROMDEVICE);
 
-		np->rx_ring[i].buffer1 = cpu_to_le32(np->rx_addr[i]);
-		np->rx_ring[i].status = cpu_to_le32(DescOwn);
+		np->rx_ring[i].buffer1 = np->rx_addr[i];
+		np->rx_ring[i].status = DescOwn;
 	}
 
 	np->cur_rx = 0;
@@ -830,6 +926,14 @@
 		writeb(dev->dev_addr[i], ioaddr + StationAddr + i);
 
 	/* Initialize other registers. */
+#ifdef __BIG_ENDIAN
+	i = (1<<20);	/* Big-endian descriptors */
+#else
+	i = 0;
+#endif
+	i |= (0x04<<2);		/* skip length 4 u32 */
+	i |= 0x02;		/* give Rx priority */
+
 	/* Configure the PCI bus bursts and FIFO thresholds.
 	   486: Set 8 longword cache alignment, 8 longword burst.
 	   586: Set 16 longword cache alignment, no burst limit.
@@ -837,44 +941,37 @@
 		0000	<not allowed> 		0000 align to cache	0800 8 longwords
 		4000	8  longwords		0100 1 longword		1000 16 longwords
 		8000	16 longwords		0200 2 longwords	2000 32 longwords
-		C000	32  longwords		0400 4 longwords
-	   Wait the specified 50 PCI cycles after a reset by initializing
-	   Tx and Rx queues and the address filter list. */
-#if defined(__powerpc__) || defined(__sparc__)		/* Big-endian */
-	writel(0x00100080 | 0xE010, ioaddr + PCIBusCfg);
-#elif defined(__alpha__)
-	writel(0xE010, ioaddr + PCIBusCfg);
-#elif defined(__i386__)
-#if defined(MODULE)
-	writel(0xE010, ioaddr + PCIBusCfg);
-#else
+		C000	32  longwords		0400 4 longwords */
+
+#if defined (__i386__) && !defined(MODULE)
 	/* When not a module we can work around broken '486 PCI boards. */
-#define x86 boot_cpu_data.x86
-	writel((x86 <= 4 ? 0x4810 : 0xE010), ioaddr + PCIBusCfg);
-	if (x86 <= 4)
+	if (boot_cpu_data.x86 <= 4) {
+		i |= 0x4800;
 		printk(KERN_INFO "%s: This is a 386/486 PCI system, setting cache "
-			   "alignment to %x.\n", dev->name,
-			   (x86 <= 4 ? 0x4810 : 0xE010));
-#endif
+			   "alignment to 8 longwords.\n", dev->name);
+	} else {
+		i |= 0xE000;
+	}
+#elif defined(__powerpc__) || defined(__i386__) || defined(__alpha) || defined(__ia64__)
+	i |= 0xE000;
+#elif defined(__sparc__)
+	i |= 0x4800;
 #else
-	writel(0xE010, ioaddr + PCIBusCfg);
-#warning Processor architecture undefined!
+#warning Processor architecture undefined
+	i |= 0x4800;
 #endif
+	writel(i, ioaddr + PCIBusCfg);
 
-	if (dev->if_port == 0)
-		dev->if_port = np->default_port;
-
-	/* Fast Ethernet; 128 byte Tx threshold; 
+	np->csr6 = 0;
+	/* 128 byte Tx threshold; 
 		Transmit on; Receive on; */
-	np->csr6 = 0x20022002;
-	check_duplex(dev);
-	set_rx_mode(dev);
-	writel(0, ioaddr + RxStartDemand);
+	update_csr6(dev, 0x00022002 | update_link(dev) | __set_rx_mode(dev));
 
 	/* Clear and Enable interrupts by setting the interrupt mask. */
 	writel(0x1A0F5, ioaddr + IntrStatus);
 	writel(0x1A0F5, ioaddr + IntrEnable);
 
+	writel(0, ioaddr + RxStartDemand);
 }
 
 static void tx_timeout(struct net_device *dev)
@@ -896,9 +993,10 @@
 		printk("\n");
 	}
 	printk(KERN_DEBUG "Tx cur %d Tx dirty %d Tx Full %d, q bytes %d.\n",
-				np->cur_tx, np->dirty_tx, np->tx_full,np->tx_q_bytes);
+				np->cur_tx, np->dirty_tx, np->tx_full, np->tx_q_bytes);
 	printk(KERN_DEBUG "Tx Descriptor addr %xh.\n",readl(ioaddr+0x4C));
 
+	disable_irq(dev->irq);
 	spin_lock_irq(&np->lock);
 	/*
 	 * Under high load dirty_tx and the internal tx descriptor pointer
@@ -912,9 +1010,8 @@
 	free_rxtx_rings(np);
 	init_rxtx_rings(dev);
 	init_registers(dev);
-	set_rx_mode(dev);
-
 	spin_unlock_irq(&np->lock);
+	enable_irq(dev->irq);
 
 	netif_wake_queue(dev);
 	dev->trans_start = jiffies;
@@ -923,7 +1020,7 @@
 }
 
 /* Initialize the Rx and Tx rings, along with various 'dev' bits. */
-static int alloc_ring(struct net_device *dev)
+static int alloc_ringdesc(struct net_device *dev)
 {
 	struct netdev_private *np = dev->priv;
 
@@ -939,12 +1036,19 @@
 	return 0;
 }
 
+static void free_ringdesc(struct netdev_private *np)
+{
+	pci_free_consistent(np->pci_dev,
+			sizeof(struct w840_rx_desc)*RX_RING_SIZE +
+			sizeof(struct w840_tx_desc)*TX_RING_SIZE,
+			np->rx_ring, np->ring_dma_addr);
+
+}
 
 static int start_tx(struct sk_buff *skb, struct net_device *dev)
 {
 	struct netdev_private *np = dev->priv;
 	unsigned entry;
-	int len1, len2;
 
 	/* Caution: the write order is important here, set the field
 	   with the "ownership" bits last. */
@@ -952,48 +1056,51 @@
 	/* Calculate the next Tx descriptor entry. */
 	entry = np->cur_tx % TX_RING_SIZE;
 
-	np->tx_skbuff[entry] = skb;
 	np->tx_addr[entry] = pci_map_single(np->pci_dev,
 				skb->data,skb->len, PCI_DMA_TODEVICE);
-	np->tx_ring[entry].buffer1 = cpu_to_le32(np->tx_addr[entry]);
-	len2 = 0;
-	len1 = skb->len;
-	if(len1 > TX_BUFLIMIT) {
-		len1 = TX_BUFLIMIT;
-		len2 = skb->len-len1;
-		np->tx_ring[entry].buffer2 = cpu_to_le32(np->tx_addr[entry]+TX_BUFLIMIT);
-	}
-	np->tx_ring[entry].length = cpu_to_le32(DescWholePkt | (len2 << 11) | len1);
-	if (entry >= TX_RING_SIZE-1)		 /* Wrap ring */
-		np->tx_ring[entry].length |= cpu_to_le32(DescIntr | DescEndRing);
-	np->cur_tx++;
+	np->tx_skbuff[entry] = skb;
+
+	np->tx_ring[entry].buffer1 = np->tx_addr[entry];
+	if (skb->len < TX_BUFLIMIT) {
+		np->tx_ring[entry].length = DescWholePkt | skb->len;
+	} else {
+		int len = skb->len - TX_BUFLIMIT;
+
+		np->tx_ring[entry].buffer2 = np->tx_addr[entry]+TX_BUFLIMIT;
+		np->tx_ring[entry].length = DescWholePkt | (len << 11) | TX_BUFLIMIT;
+	}
+	if(entry == TX_RING_SIZE-1)
+		np->tx_ring[entry].length |= DescEndRing;
 
-	/* The spinlock protects against 2 races:
-	 * - tx_q_bytes is updated by this function and intr_handler
-	 * - our hardware is extremely fast and finishes the packet between
-	 *	our check for "queue full" and netif_stop_queue.
-	 *	Thus setting DescOwn and netif_stop_queue must be atomic.
+	/* Now acquire the irq spinlock.
+	 * The difficult race is the the ordering between
+	 * increasing np->cur_tx and setting DescOwn:
+	 * - if np->cur_tx is increased first the interrupt
+	 *   handler could consider the packet as transmitted
+	 *   since DescOwn is cleared.
+	 * - If DescOwn is set first the NIC could report the
+	 *   packet as sent, but the interrupt handler would ignore it
+	 *   since the np->cur_tx was not yet increased.
 	 */
 	spin_lock_irq(&np->lock);
+	np->cur_tx++;
 
 	wmb(); /* flush length, buffer1, buffer2 */
-	np->tx_ring[entry].status = cpu_to_le32(DescOwn);
+	np->tx_ring[entry].status = DescOwn;
 	wmb(); /* flush status and kick the hardware */
 	writel(0, dev->base_addr + TxStartDemand);
-
 	np->tx_q_bytes += skb->len;
 	/* Work around horrible bug in the chip by marking the queue as full
 	   when we do not have FIFO room for a maximum sized packet. */
-	if (np->cur_tx - np->dirty_tx > TX_QUEUE_LEN)
-		np->tx_full = 1;
-	else if ((np->drv_flags & HasBrokenTx)
-			 && np->tx_q_bytes > TX_BUG_FIFO_LIMIT)
-		np->tx_full = 1;
-	if (np->tx_full)
+	if (np->cur_tx - np->dirty_tx > TX_QUEUE_LEN ||
+		((np->drv_flags & HasBrokenTx) && np->tx_q_bytes > TX_BUG_FIFO_LIMIT)) {
 		netif_stop_queue(dev);
+		wmb();
+		np->tx_full = 1;
+	}
+	spin_unlock_irq(&np->lock);
 
 	dev->trans_start = jiffies;
-	spin_unlock_irq(&np->lock);
 
 	if (debug > 4) {
 		printk(KERN_DEBUG "%s: Transmit frame #%d queued in slot %d.\n",
@@ -1002,6 +1109,62 @@
 	return 0;
 }
 
+static void netdev_tx_done(struct net_device *dev)
+{
+	struct netdev_private *np = dev->priv;
+	for (; np->cur_tx - np->dirty_tx > 0; np->dirty_tx++) {
+		int entry = np->dirty_tx % TX_RING_SIZE;
+		int tx_status = np->tx_ring[entry].status;
+
+		if (tx_status < 0)
+			break;
+		if (tx_status & 0x8000) { 	/* There was an error, log it. */
+#ifndef final_version
+			if (debug > 1)
+				printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n",
+					   dev->name, tx_status);
+#endif
+			np->stats.tx_errors++;
+			if (tx_status & 0x0104) np->stats.tx_aborted_errors++;
+			if (tx_status & 0x0C80) np->stats.tx_carrier_errors++;
+			if (tx_status & 0x0200) np->stats.tx_window_errors++;
+			if (tx_status & 0x0002) np->stats.tx_fifo_errors++;
+			if ((tx_status & 0x0080) && np->full_duplex == 0)
+				np->stats.tx_heartbeat_errors++;
+#ifdef ETHER_STATS
+			if (tx_status & 0x0100) np->stats.collisions16++;
+#endif
+		} else {
+#ifdef ETHER_STATS
+			if (tx_status & 0x0001) np->stats.tx_deferred++;
+#endif
+#ifndef final_version
+			if (debug > 3)
+				printk(KERN_DEBUG "%s: Transmit slot %d ok, Tx status %8.8x.\n",
+					   dev->name, entry, tx_status);
+#endif
+			np->stats.tx_bytes += np->tx_skbuff[entry]->len;
+			np->stats.collisions += (tx_status >> 3) & 15;
+			np->stats.tx_packets++;
+		}
+		/* Free the original skb. */
+		pci_unmap_single(np->pci_dev,np->tx_addr[entry],
+					np->tx_skbuff[entry]->len,
+					PCI_DMA_TODEVICE);
+		np->tx_q_bytes -= np->tx_skbuff[entry]->len;
+		dev_kfree_skb_irq(np->tx_skbuff[entry]);
+		np->tx_skbuff[entry] = 0;
+	}
+	if (np->tx_full &&
+		np->cur_tx - np->dirty_tx < TX_QUEUE_LEN_RESTART &&
+		np->tx_q_bytes < TX_BUG_FIFO_LIMIT) {
+		/* The ring is no longer full, clear tbusy. */
+		np->tx_full = 0;
+		wmb();
+		netif_wake_queue(dev);
+	}
+}
+
 /* The interrupt handler does all of the Rx thread work and cleans up
    after the Tx thread. */
 static void intr_handler(int irq, void *dev_instance, struct pt_regs *rgs)
@@ -1011,8 +1174,8 @@
 	long ioaddr = dev->base_addr;
 	int work_limit = max_interrupt_work;
 
-	spin_lock(&np->lock);
-
+	if (!netif_device_present(dev))
+		return;
 	do {
 		u32 intr_status = readl(ioaddr + IntrStatus);
 
@@ -1028,51 +1191,14 @@
 
 		if (intr_status & (IntrRxDone | RxNoBuf))
 			netdev_rx(dev);
+		if (intr_status & RxNoBuf)
+			writel(0, ioaddr + RxStartDemand);
 
-		for (; np->cur_tx - np->dirty_tx > 0; np->dirty_tx++) {
-			int entry = np->dirty_tx % TX_RING_SIZE;
-			int tx_status = le32_to_cpu(np->tx_ring[entry].status);
-
-			if (tx_status < 0)
-				break;
-			if (tx_status & 0x8000) { 		/* There was an error, log it. */
-#ifndef final_version
-				if (debug > 1)
-					printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n",
-						   dev->name, tx_status);
-#endif
-				np->stats.tx_errors++;
-				if (tx_status & 0x0104) np->stats.tx_aborted_errors++;
-				if (tx_status & 0x0C80) np->stats.tx_carrier_errors++;
-				if (tx_status & 0x0200) np->stats.tx_window_errors++;
-				if (tx_status & 0x0002) np->stats.tx_fifo_errors++;
-				if ((tx_status & 0x0080) && np->full_duplex == 0)
-					np->stats.tx_heartbeat_errors++;
-#ifdef ETHER_STATS
-				if (tx_status & 0x0100) np->stats.collisions16++;
-#endif
-			} else {
-#ifdef ETHER_STATS
-				if (tx_status & 0x0001) np->stats.tx_deferred++;
-#endif
-				np->stats.tx_bytes += np->tx_skbuff[entry]->len;
-				np->stats.collisions += (tx_status >> 3) & 15;
-				np->stats.tx_packets++;
-			}
-			/* Free the original skb. */
-			pci_unmap_single(np->pci_dev,np->tx_addr[entry],
-						np->tx_skbuff[entry]->len,
-						PCI_DMA_TODEVICE);
-			np->tx_q_bytes -= np->tx_skbuff[entry]->len;
-			dev_kfree_skb_irq(np->tx_skbuff[entry]);
-			np->tx_skbuff[entry] = 0;
-		}
-		if (np->tx_full &&
-			np->cur_tx - np->dirty_tx < TX_QUEUE_LEN - 4
-			&&  np->tx_q_bytes < TX_BUG_FIFO_LIMIT) {
-			/* The ring is no longer full, clear tbusy. */
-			np->tx_full = 0;
-			netif_wake_queue(dev);
+		if (intr_status & (TxIdle | IntrTxDone) &&
+			np->cur_tx != np->dirty_tx) {
+			spin_lock(&np->lock);
+			netdev_tx_done(dev);
+			spin_unlock(&np->lock);
 		}
 
 		/* Abnormal error summary/uncommon events handlers. */
@@ -1085,8 +1211,12 @@
 				   "status=0x%4.4x.\n", dev->name, intr_status);
 			/* Set the timer to re-enable the other interrupts after
 			   10*82usec ticks. */
-			writel(AbnormalIntr | TimerInt, ioaddr + IntrEnable);
-			writel(10, ioaddr + GPTimer);
+			spin_lock(&np->lock);
+			if (netif_device_present(dev)) {
+				writel(AbnormalIntr | TimerInt, ioaddr + IntrEnable);
+				writel(10, ioaddr + GPTimer);
+			}
+			spin_unlock(&np->lock);
 			break;
 		}
 	} while (1);
@@ -1094,8 +1224,6 @@
 	if (debug > 3)
 		printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n",
 			   dev->name, (int)readl(ioaddr + IntrStatus));
-
-	spin_unlock(&np->lock);
 }
 
 /* This routine is logically part of the interrupt handler, but separated
@@ -1114,7 +1242,7 @@
 	/* If EOP is set on the next entry, it's a new packet. Send it up. */
 	while (--work_limit >= 0) {
 		struct w840_rx_desc *desc = np->rx_head_desc;
-		s32 status = le32_to_cpu(desc->status);
+		s32 status = desc->status;
 
 		if (debug > 4)
 			printk(KERN_DEBUG "  netdev_rx() status was %8.8x.\n",
@@ -1210,10 +1338,10 @@
 			np->rx_addr[entry] = pci_map_single(np->pci_dev,
 							skb->tail,
 							skb->len, PCI_DMA_FROMDEVICE);
-			np->rx_ring[entry].buffer1 = cpu_to_le32(np->rx_addr[entry]);
+			np->rx_ring[entry].buffer1 = np->rx_addr[entry];
 		}
 		wmb();
-		np->rx_ring[entry].status = cpu_to_le32(DescOwn);
+		np->rx_ring[entry].status = DescOwn;
 	}
 
 	return 0;
@@ -1229,35 +1357,38 @@
 			   dev->name, intr_status);
 	if (intr_status == 0xffffffff)
 		return;
+	spin_lock(&np->lock);
 	if (intr_status & TxFIFOUnderflow) {
+		int new;
 		/* Bump up the Tx threshold */
 #if 0
 		/* This causes lots of dropped packets,
 		 * and under high load even tx_timeouts
 		 */
-		np->csr6 += 0x4000;
+		new = np->csr6 + 0x4000;
 #else
-		int cur = (np->csr6 >> 14)&0x7f;
-		if (cur < 64)
-			cur *= 2;
+		new = (np->csr6 >> 14)&0x7f;
+		if (new < 64)
+			new *= 2;
 		 else
-		 	cur = 0; /* load full packet before starting */
-		np->csr6 &= ~(0x7F << 14);
-		np->csr6 |= cur<<14;
+		 	new = 127; /* load full packet before starting */
+		new = (np->csr6 & ~(0x7F << 14)) | (new<<14);
 #endif
-		printk(KERN_DEBUG "%s: Tx underflow, increasing threshold to %8.8x.\n",
-			   dev->name, np->csr6);
-		writel(np->csr6, ioaddr + NetworkConfig);
+		printk(KERN_DEBUG "%s: Tx underflow, new csr6 %8.8x.\n",
+			   dev->name, new);
+		update_csr6(dev, new);
 	}
 	if (intr_status & IntrRxDied) {		/* Missed a Rx frame. */
 		np->stats.rx_errors++;
 	}
 	if (intr_status & TimerInt) {
 		/* Re-enable other interrupts. */
-		writel(0x1A0F5, ioaddr + IntrEnable);
+		if (netif_device_present(dev))
+			writel(0x1A0F5, ioaddr + IntrEnable);
 	}
 	np->stats.rx_missed_errors += readl(ioaddr + RxMissed) & 0xffff;
 	writel(0, ioaddr + RxStartDemand);
+	spin_unlock(&np->lock);
 }
 
 static struct net_device_stats *get_stats(struct net_device *dev)
@@ -1266,8 +1397,10 @@
 	struct netdev_private *np = dev->priv;
 
 	/* The chip only need report frame silently dropped. */
-	if (netif_running(dev))
+	spin_lock_irq(&np->lock);
+	if (netif_running(dev) && netif_device_present(dev))
 		np->stats.rx_missed_errors += readl(ioaddr + RxMissed) & 0xffff;
+	spin_unlock_irq(&np->lock);
 
 	return &np->stats;
 }
@@ -1288,9 +1421,8 @@
     return crc;
 }
 
-static void set_rx_mode(struct net_device *dev)
+static u32 __set_rx_mode(struct net_device *dev)
 {
-	struct netdev_private *np = dev->priv;
 	long ioaddr = dev->base_addr;
 	u32 mc_filter[2];			/* Multicast hash filter */
 	u32 rx_mode;
@@ -1319,9 +1451,16 @@
 	}
 	writel(mc_filter[0], ioaddr + MulticastFilter0);
 	writel(mc_filter[1], ioaddr + MulticastFilter1);
-	np->csr6 &= ~0x00F8;
-	np->csr6 |= rx_mode;
-	writel(np->csr6, ioaddr + NetworkConfig);
+	return rx_mode;
+}
+
+static void set_rx_mode(struct net_device *dev)
+{
+	struct netdev_private *np = dev->priv;
+	u32 rx_mode = __set_rx_mode(dev);
+	spin_lock_irq(&np->lock);
+	update_csr6(dev, (np->csr6 & ~0x00F8) | rx_mode);
+	spin_unlock_irq(&np->lock);
 }
 
 static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr)
@@ -1351,6 +1490,7 @@
 static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
 	struct mii_ioctl_data *data = (struct mii_ioctl_data *)&rq->ifr_data;
+	struct netdev_private *np = dev->priv;
 
 	switch(cmd) {
 	case SIOCETHTOOL:
@@ -1362,14 +1502,18 @@
 
 	case SIOCGMIIREG:		/* Read MII PHY register. */
 	case SIOCDEVPRIVATE+1:		/* for binary compat, remove in 2.5 */
+		spin_lock_irq(&np->lock);
 		data->val_out = mdio_read(dev, data->phy_id & 0x1f, data->reg_num & 0x1f);
+		spin_unlock_irq(&np->lock);
 		return 0;
 
 	case SIOCSMIIREG:		/* Write MII PHY register. */
 	case SIOCDEVPRIVATE+2:		/* for binary compat, remove in 2.5 */
 		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
+		spin_lock_irq(&np->lock);
 		mdio_write(dev, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in);
+		spin_unlock_irq(&np->lock);
 		return 0;
 	default:
 		return -EOPNOTSUPP;
@@ -1391,11 +1535,16 @@
 			   dev->name, np->cur_tx, np->dirty_tx, np->cur_rx, np->dirty_rx);
 	}
 
-	/* Disable interrupts by clearing the interrupt mask. */
+ 	/* Stop the chip's Tx and Rx processes. */
+	spin_lock_irq(&np->lock);
+	netif_device_detach(dev);
+	update_csr6(dev, 0);
 	writel(0x0000, ioaddr + IntrEnable);
+	spin_unlock_irq(&np->lock);
 
-	/* Stop the chip's Tx and Rx processes. */
-	writel(np->csr6 &= ~0x20FA, ioaddr + NetworkConfig);
+	free_irq(dev->irq, dev);
+	wmb();
+	netif_device_attach(dev);
 
 	if (readl(ioaddr + NetworkConfig) != 0xffffffff)
 		np->stats.rx_missed_errors += readl(ioaddr + RxMissed) & 0xffff;
@@ -1420,11 +1569,10 @@
 	}
 #endif /* __i386__ debugging only */
 
-	free_irq(dev->irq, dev);
-
 	del_timer_sync(&np->timer);
 
 	free_rxtx_rings(np);
+	free_ringdesc(np);
 
 	return 0;
 }
@@ -1446,11 +1594,112 @@
 	pci_set_drvdata(pdev, NULL);
 }
 
+#ifdef CONFIG_PM
+
+/*
+ * suspend/resume synchronization:
+ * - open, close, do_ioctl:
+ * 	rtnl_lock, & netif_device_detach after the rtnl_unlock.
+ * - get_stats:
+ * 	spin_lock_irq(np->lock), doesn't touch hw if not present
+ * - hard_start_xmit:
+ * 	netif_stop_queue + spin_unlock_wait(&dev->xmit_lock);
+ * - tx_timeout:
+ * 	netif_device_detach + spin_unlock_wait(&dev->xmit_lock);
+ * - set_multicast_list
+ * 	netif_device_detach + spin_unlock_wait(&dev->xmit_lock);
+ * - interrupt handler
+ * 	doesn't touch hw if not present, synchronize_irq waits for
+ * 	running instances of the interrupt handler.
+ *
+ * Disabling hw requires clearing csr6 & IntrEnable.
+ * update_csr6 & all function that write IntrEnable check netif_device_present
+ * before settings any bits.
+ *
+ * Detach must occur under spin_unlock_irq(), interrupts from a detached
+ * device would cause an irq storm.
+ */
+static int w840_suspend (struct pci_dev *pdev, u32 state)
+{
+	struct net_device *dev = pci_get_drvdata (pdev);
+	struct netdev_private *np = dev->priv;
+	long ioaddr = dev->base_addr;
+
+	rtnl_lock();
+	if (netif_running (dev)) {
+		del_timer_sync(&np->timer);
+
+		spin_lock_irq(&np->lock);
+		netif_device_detach(dev);
+		update_csr6(dev, 0);
+		writel(0, ioaddr + IntrEnable);
+		netif_stop_queue(dev);
+		spin_unlock_irq(&np->lock);
+
+		spin_unlock_wait(&dev->xmit_lock);
+		synchronize_irq();
+	
+		np->stats.rx_missed_errors += readl(ioaddr + RxMissed) & 0xffff;
+
+		/* no more hardware accesses behind this line. */
+
+		if (np->csr6) BUG();
+		if (readl(ioaddr + IntrEnable)) BUG();
+
+		/* pci_power_off(pdev, -1); */
+
+		free_rxtx_rings(np);
+	} else {
+		netif_device_detach(dev);
+	}
+	rtnl_unlock();
+	return 0;
+}
+
+
+static int w840_resume (struct pci_dev *pdev)
+{
+	struct net_device *dev = pci_get_drvdata (pdev);
+	struct netdev_private *np = dev->priv;
+
+	rtnl_lock();
+	if (netif_device_present(dev))
+		goto out; /* device not suspended */
+	if (netif_running(dev)) {
+		pci_enable_device(pdev);
+	/*	pci_power_on(pdev); */
+
+		spin_lock_irq(&np->lock);
+		writel(1, dev->base_addr+PCIBusCfg);
+		readl(dev->base_addr+PCIBusCfg);
+		udelay(1);
+		netif_device_attach(dev);
+		init_rxtx_rings(dev);
+		init_registers(dev);
+		spin_unlock_irq(&np->lock);
+
+		netif_wake_queue(dev);
+
+		np->timer.expires = jiffies + 1*HZ;
+		add_timer(&np->timer);
+	} else {
+		netif_device_attach(dev);
+	}
+out:
+	rtnl_unlock();
+	return 0;
+}
+#endif
+
 static struct pci_driver w840_driver = {
 	name:		DRV_NAME,
 	id_table:	w840_pci_tbl,
 	probe:		w840_probe1,
 	remove:		w840_remove1,
+#ifdef CONFIG_PM
+	suspend:	w840_suspend,
+	resume:		w840_resume,
+#endif
 };
 
 static int __init w840_init(void)
diff -urN linux-2.4.7-pre6/drivers/net/wireless/airo.c linux/drivers/net/wireless/airo.c
--- linux-2.4.7-pre6/drivers/net/wireless/airo.c	Mon Jul  2 14:03:04 2001
+++ linux/drivers/net/wireless/airo.c	Mon Dec  3 22:55:50 2001
@@ -333,7 +333,8 @@
 #define EV_LINK 0x80
 #define EV_AWAKE 0x100
 #define EV_UNKNOWN 0x800
-#define STATUS_INTS ( EV_AWAKE | EV_LINK | EV_TXEXC | EV_TX | EV_RX | EV_UNKNOWN)
+#define STATUS_INTS ( EV_AWAKE | EV_LINK | EV_TXEXC | EV_TX | EV_RX)
+#define IGNORE_INTS ( EV_CMD | EV_UNKNOWN)
 
 /* The RIDs */
 #define RID_CAPABILITIES 0xFF00
@@ -656,7 +657,6 @@
 // A few details needed for WEP (Wireless Equivalent Privacy)
 #define MAX_KEY_SIZE 13			// 128 (?) bits
 #define MIN_KEY_SIZE  5			// 40 bits RC4 - WEP
-#define MAX_KEYS      4			// 4 different keys
 typedef struct wep_key_t {
 	u16	len;
 	u8	key[16];	/* 40-bit and 104-bit keys */
@@ -724,11 +724,12 @@
         spinlock_t aux_lock;
         spinlock_t cmd_lock;
         int flags;
-#define FLAG_PROMISC   0x01
+#define FLAG_PROMISC   IFF_PROMISC
 #define FLAG_RADIO_OFF 0x02
 	int (*bap_read)(struct airo_info*, u16 *pu16Dst, int bytelen, 
 			int whichbap);
 	int (*header_parse)(struct sk_buff*, unsigned char *);
+	unsigned short *flash;
 #ifdef WIRELESS_EXT
 	int			need_commit;	// Need to set config
 	struct iw_statistics	wstats;		// wireless stats
@@ -949,10 +950,17 @@
 	Cmd cmd;
 	Resp rsp;
 	  
-	memset(&cmd, 0, sizeof(cmd));
-	cmd.cmd=CMD_SETMODE;
-	cmd.parm0=(dev->flags&IFF_PROMISC) ? PROMISC : NOPROMISC;
-	issuecommand(ai, &cmd, &rsp);
+	/* For some reason this command takes a lot of time (~20 ms) and it's
+	 * run in an interrupt handler, so we'd better be sure we needed it
+	 * before executing it.
+	 */
+	if ((dev->flags ^ ai->flags) & IFF_PROMISC) {
+		memset(&cmd, 0, sizeof(cmd));
+		cmd.cmd=CMD_SETMODE;
+		cmd.parm0=(dev->flags&IFF_PROMISC) ? PROMISC : NOPROMISC;
+		issuecommand(ai, &cmd, &rsp);
+		ai->flags^=IFF_PROMISC;
+	}
 
 	if ((dev->flags&IFF_ALLMULTI)||dev->mc_count>0) {
 		/* Turn on multicast.  (Should be already setup...) */
@@ -994,6 +1002,8 @@
 void stop_airo_card( struct net_device *dev, int freeres ) 
 {
 	struct airo_info *ai = (struct airo_info*)dev->priv;
+	if (ai->flash)
+		kfree(ai->flash);
 	takedown_proc_entry( dev, ai );
 	if (ai->registered) {
 		unregister_netdev( dev );
@@ -1113,11 +1123,10 @@
 }
 
 int reset_airo_card( struct net_device *dev ) {
-	int i, flags;
+	int i;
 	struct airo_info *ai = (struct airo_info*)dev->priv;
 
 	disable_MAC(ai);
-	spin_lock_irqsave(&ai->cmd_lock, flags);
 	waitbusy (ai);
 	OUT4500(ai,COMMAND,CMD_SOFTRESET);
 	set_current_state (TASK_UNINTERRUPTIBLE);
@@ -1125,7 +1134,6 @@
 	waitbusy (ai);
 	set_current_state (TASK_UNINTERRUPTIBLE);
 	schedule_timeout (HZ/5);
-	spin_unlock_irqrestore(&ai->cmd_lock, flags);
 	if ( setup_card(ai, dev->dev_addr, &(ai)->config) != SUCCESS ) {
 		printk( KERN_ERR "airo: MAC could not be enabled\n" );
 		return -1;
@@ -1359,10 +1367,10 @@
 			apriv->stats.tx_errors++;
 		}
 	}
-	if ( status & ~STATUS_INTS ) 
+	if ( status & ~STATUS_INTS & ~IGNORE_INTS ) 
 		printk( KERN_WARNING 
 			"airo: Got weird status %x\n", 
-			status & ~STATUS_INTS );
+			status & ~STATUS_INTS & ~IGNORE_INTS );
 	OUT4500( apriv, EVACK, status & STATUS_INTS );
 	OUT4500( apriv, EVINTEN, savedInterrupts );
 	
@@ -1446,6 +1454,10 @@
 	int rc;
 
 	memset( &mySsid, 0, sizeof( mySsid ) );
+	if (ai->flash) {
+		kfree (ai->flash);
+		ai->flash = NULL;
+	}
 
 	/* The NOP is the first step in getting the card going */
 	cmd.cmd = NOP;
@@ -1562,6 +1574,10 @@
 			// PC4500 didn't notice command, try again
 			OUT4500(ai, COMMAND, pCmd->cmd);
 		}
+		if (!(max_tries & 255) && !in_interrupt()) {
+			set_current_state(TASK_RUNNING);
+			schedule();
+		}
 	}
 	if ( max_tries == -1 ) {
 		printk( KERN_ERR 
@@ -3134,9 +3150,12 @@
 
 				/* Set the SSID */
 				memset(essid, 0, sizeof(essid));
-				copy_from_user(essid,
+				if (copy_from_user(essid,
 					       wrq->u.data.pointer,
-					       wrq->u.data.length);
+					       wrq->u.data.length)) {
+					rc = -EFAULT;
+					break;
+				}
 				memcpy(SSID_rid.ssids[index].ssid, essid,
 				       sizeof(essid) - 1);
 				SSID_rid.ssids[index].len = wrq->u.data.length - 1;
@@ -3199,7 +3218,11 @@
 				break;
 			}
 			memset(name, 0, sizeof(name));
-			copy_from_user(name, wrq->u.data.pointer, wrq->u.data.length);
+			if (copy_from_user(name, wrq->u.data.pointer,
+					   wrq->u.data.length)) {
+				rc = -EFAULT;
+				break;
+			}
 			memcpy(config.nodeName, name, 16);
 			local->need_commit = 1;
 		}
@@ -3395,7 +3418,7 @@
 				break;
 			}
 			/* Check the index (none -> use current) */
-			if ((index < 0) || (index >= MAX_KEYS))
+			if ((index < 0) || (index>=(cap_rid.softCap&0x80)?4:1))
 				index = current_index;
 			/* Set the length */
 			if (wrq->u.encoding.length > MIN_KEY_SIZE)
@@ -3433,7 +3456,7 @@
 		} else {
 			/* Do we want to just set the transmit key index ? */
 			int index = (wrq->u.encoding.flags & IW_ENCODE_INDEX) - 1;
-			if ((index >= 0) && (index < MAX_KEYS)) {
+			if ((index>=0) && (index<(cap_rid.softCap&0x80)?4:1)) {
 				set_wep_key(local, index, 0, 0, 1);
 			} else
 				/* Don't complain if only change the mode */
@@ -3490,7 +3513,7 @@
 			}
 
 			/* Which key do we want ? -1 -> tx index */
-			if((index < 0) || (index >= MAX_KEYS))
+			if((index < 0) || (index >= (cap_rid.softCap&0x80)?4:1))
 				index = get_wep_key(local, 0xffff);
 			wrq->u.encoding.flags |= index + 1;
 			/* Copy the key to the user buffer */
@@ -3614,7 +3637,7 @@
 					range.num_encoding_sizes = 2;
 				} else
 					range.num_encoding_sizes = 1;
-				range.max_encoding_tokens = 4;	// 4 keys
+				range.max_encoding_tokens = (cap_rid.softCap & 0x80) ? 4 : 1;
 			} else {
 				range.num_encoding_sizes = 0;
 				range.max_encoding_tokens = 0;
@@ -3785,8 +3808,14 @@
 				memcpy(address[i].sa_data, local->spy_address[i], 6);
 				address[i].sa_family = AF_UNIX;
 			}
-			copy_to_user(wrq->u.data.pointer, address, sizeof(struct sockaddr) * local->spy_number);
-			copy_to_user(wrq->u.data.pointer + (sizeof(struct sockaddr)*local->spy_number), local->spy_stat, sizeof(struct iw_quality) * local->spy_number);
+			if (copy_to_user(wrq->u.data.pointer, address, sizeof(struct sockaddr) * local->spy_number)) {
+				rc = -EFAULT;
+				break;
+			}
+			if (copy_to_user(wrq->u.data.pointer + (sizeof(struct sockaddr)*local->spy_number), local->spy_stat, sizeof(struct iw_quality) * local->spy_number)) {
+				rc = -EFAULT;
+				break;
+			}
 			for (i=0; i<local->spy_number; i++)
 				local->spy_stat[i].updated = 0;
 		}
@@ -3833,7 +3862,10 @@
 		 */
 	{
 		aironet_ioctl com;
-		copy_from_user(&com,rq->ifr_data,sizeof(com));
+		if (copy_from_user(&com,rq->ifr_data,sizeof(com))) {
+			rc = -EFAULT;
+			break;
+		}
 
 		/* Seperate R/W functions bracket legality here
 		 */
@@ -4035,7 +4067,8 @@
 	if(comp->len > sizeof(iobuf))
 		return -EINVAL;
 
-	copy_from_user(iobuf,comp->data,comp->len);
+	if (copy_from_user(iobuf,comp->data,comp->len))
+		return -EFAULT;
 	if((*writer)((struct airo_info *)dev->priv, ridcode, iobuf,comp->len))
 		return -EIO;
 	return 0;
@@ -4056,9 +4089,8 @@
 	int setflashmode(struct airo_info *);
 	int flashgchar(struct airo_info *,int,int);
 	int flashpchar(struct airo_info *,int,int);
-	int flashputbuf(struct airo_info *, unsigned short *);
+	int flashputbuf(struct airo_info *);
 	int flashrestart(struct airo_info *,struct net_device *);
-	unsigned short * flashbuffer;
 
 	/* Only super-user can modify flash */
 	if (!capable(CAP_NET_ADMIN))
@@ -4070,32 +4102,34 @@
 		return cmdreset((struct airo_info *)dev->priv);
 
 	case AIROFLSHSTFL:
+		if (!((struct airo_info *)dev->priv)->flash &&
+			(((struct airo_info *)dev->priv)->flash = kmalloc (FLASHSIZE, GFP_KERNEL)) == NULL)
+			return -ENOMEM;
 		return setflashmode((struct airo_info *)dev->priv);
 
 	case AIROFLSHGCHR: /* Get char from aux */
 		if(comp->len != sizeof(int))
 			return -EINVAL;
-		copy_from_user(&z,comp->data,comp->len);
+		if (copy_from_user(&z,comp->data,comp->len))
+			return -EFAULT;
 		return flashgchar((struct airo_info *)dev->priv,z,8000);
 
 	case AIROFLSHPCHR: /* Send char to card. */
 		if(comp->len != sizeof(int))
 			return -EINVAL;
-		copy_from_user(&z,comp->data,comp->len);
+		if (copy_from_user(&z,comp->data,comp->len))
+			return -EFAULT;
 		return flashpchar((struct airo_info *)dev->priv,z,8000);
 
 	case AIROFLPUTBUF: /* Send 32k to card */
-		if(comp->len > FLASHSIZE)
-			return -EINVAL;
-		if ((flashbuffer = kmalloc (FLASHSIZE, GFP_KERNEL)) == NULL)
+		if (!((struct airo_info *)dev->priv)->flash)
 			return -ENOMEM;
-		if(copy_from_user(flashbuffer,comp->data,comp->len)) {
-			kfree (flashbuffer);
+		if(comp->len > FLASHSIZE)
 			return -EINVAL;
-		}
+		if(copy_from_user(((struct airo_info *)dev->priv)->flash,comp->data,comp->len))
+			return -EFAULT;
 
-		flashputbuf((struct airo_info *)dev->priv,flashbuffer);
-		kfree (flashbuffer);
+		flashputbuf((struct airo_info *)dev->priv);
 		return 0;
 
 	case AIRORESTART:
@@ -4115,11 +4149,8 @@
  */
 
 int cmdreset(struct airo_info *ai) {
-	int flags;
-
 	disable_MAC(ai);
 
-	spin_lock_irqsave(&ai->cmd_lock, flags);
 	if(!waitbusy (ai)){
 		printk(KERN_INFO "Waitbusy hang before RESET\n");
 		return -EBUSY;
@@ -4134,7 +4165,6 @@
 		printk(KERN_INFO "Waitbusy hang AFTER RESET\n");
 		return -EBUSY;
 	}
-	spin_unlock_irqrestore(&ai->cmd_lock, flags);
 	return 0;
 }
 
@@ -4144,16 +4174,12 @@
  */
 
 int setflashmode (struct airo_info *ai) {
-	int flags;
-
-	spin_lock_irqsave(&ai->cmd_lock, flags);
 	OUT4500(ai, SWS0, FLASH_COMMAND);
 	OUT4500(ai, SWS1, FLASH_COMMAND);
 	OUT4500(ai, SWS0, FLASH_COMMAND);
 	OUT4500(ai, COMMAND,0x10);
 	set_current_state (TASK_UNINTERRUPTIBLE);
 	schedule_timeout (HZ/2); /* 500ms delay */
-	spin_unlock_irqrestore(&ai->cmd_lock, flags);
   
 	if(!waitbusy(ai)) {
 		printk(KERN_INFO "Waitbusy hang after setflash mode\n");
@@ -4237,7 +4263,7 @@
  * send to the card 
  */
 
-int flashputbuf(struct airo_info *ai, unsigned short *bufp){
+int flashputbuf(struct airo_info *ai){
 	int            nwords;
 
 	/* Write stuff */
@@ -4245,7 +4271,7 @@
 	OUT4500(ai,AUXOFF,0);
 
 	for(nwords=0;nwords != FLASHSIZE / 2;nwords++){
-		OUT4500(ai,AUXDATA,bufp[nwords] & 0xffff);
+		OUT4500(ai,AUXDATA,ai->flash[nwords] & 0xffff);
 	}
   
 	OUT4500(ai,SWS0,0x8000);
diff -urN linux-2.4.7-pre6/drivers/net/yellowfin.c linux/drivers/net/yellowfin.c
--- linux-2.4.7-pre6/drivers/net/yellowfin.c	Mon Jul  2 14:03:04 2001
+++ linux/drivers/net/yellowfin.c	Mon Dec  3 22:55:50 2001
@@ -86,6 +86,9 @@
 #define TX_RING_SIZE	16
 #define TX_QUEUE_SIZE	12		/* Must be > 4 && <= TX_RING_SIZE */
 #define RX_RING_SIZE	64
+#define STATUS_TOTAL_SIZE	TX_RING_SIZE*sizeof(struct tx_status_words)
+#define TX_TOTAL_SIZE		2*TX_RING_SIZE*sizeof(struct yellowfin_desc)
+#define RX_TOTAL_SIZE		RX_RING_SIZE*sizeof(struct yellowfin_desc)
 
 /* Operational parameters that usually are not changed. */
 /* Time in jiffies before concluding the transmitter is hung. */
@@ -127,10 +130,6 @@
 KERN_INFO "  http://www.scyld.com/network/yellowfin.html\n"
 KERN_INFO "  (unofficial 2.4.x port, " DRV_VERSION ", " DRV_RELDATE ")\n";
 
-/* Condensed operations for readability. */
-#define virt_to_le32desc(addr)  cpu_to_le32(virt_to_bus(addr))
-#define le32desc_to_virt(addr)  bus_to_virt(le32_to_cpu(addr))
-
 #ifndef USE_IO_OPS
 #undef inb
 #undef inw
@@ -351,19 +350,21 @@
 struct yellowfin_private {
 	/* Descriptor rings first for alignment.
 	   Tx requires a second descriptor for status. */
-	struct yellowfin_desc rx_ring[RX_RING_SIZE];
-	struct yellowfin_desc tx_ring[TX_RING_SIZE*2];
-	/* The addresses of receive-in-place skbuffs. */
+	struct yellowfin_desc *rx_ring;
+	struct yellowfin_desc *tx_ring;
 	struct sk_buff* rx_skbuff[RX_RING_SIZE];
-	/* The saved address of a sent-in-place packet/buffer, for later free(). */
 	struct sk_buff* tx_skbuff[TX_RING_SIZE];
-	struct tx_status_words tx_status[TX_RING_SIZE];
+	dma_addr_t rx_ring_dma;
+	dma_addr_t tx_ring_dma;
+
+	struct tx_status_words *tx_status;
+	dma_addr_t tx_status_dma;
+
 	struct timer_list timer;	/* Media selection timer. */
 	struct net_device_stats stats;
 	/* Frequently used and paired value: keep adjacent for cache effect. */
 	int chip_id, drv_flags;
 	struct pci_dev *pci_dev;
-	struct yellowfin_desc *rx_head_desc;
 	unsigned int cur_rx, dirty_rx;		/* Producer/consumer ring indices */
 	unsigned int rx_buf_sz;				/* Based on MTU+slack. */
 	struct tx_status_words *tx_tail_desc;
@@ -409,6 +410,8 @@
 	long ioaddr, real_ioaddr;
 	int i, option = find_cnt < MAX_UNITS ? options[find_cnt] : 0;
 	int drv_flags = pci_id_tbl[chip_idx].drv_flags;
+        void *ring_space;
+        dma_addr_t ring_dma;
 	
 /* when built into the kernel, we only print version if device is found */
 #ifndef MODULE
@@ -460,12 +463,30 @@
 	dev->irq = irq;
 
 	pci_set_drvdata(pdev, dev);
-	np->lock = SPIN_LOCK_UNLOCKED;
+	spin_lock_init(&np->lock);
 
 	np->pci_dev = pdev;
 	np->chip_id = chip_idx;
 	np->drv_flags = drv_flags;
 
+	ring_space = pci_alloc_consistent(pdev, TX_TOTAL_SIZE, &ring_dma);
+	if (!ring_space)
+		goto err_out_cleardev;
+	np->tx_ring = (struct yellowfin_desc *)ring_space;
+	np->tx_ring_dma = ring_dma;
+
+	ring_space = pci_alloc_consistent(pdev, RX_TOTAL_SIZE, &ring_dma);
+	if (!ring_space)
+		goto err_out_unmap_tx;
+	np->rx_ring = (struct yellowfin_desc *)ring_space;
+	np->rx_ring_dma = ring_dma;
+
+	ring_space = pci_alloc_consistent(pdev, STATUS_TOTAL_SIZE, &ring_dma);
+	if (!ring_space)
+		goto err_out_unmap_rx;
+	np->tx_status = (struct tx_status_words *)ring_space;
+	np->tx_status_dma = ring_dma;
+
 	if (dev->mem_start)
 		option = dev->mem_start;
 
@@ -498,7 +519,7 @@
 
 	i = register_netdev(dev);
 	if (i)
-		goto err_out_cleardev;
+		goto err_out_unmap_status;
 
 	printk(KERN_INFO "%s: %s type %8x at 0x%lx, ",
 		   dev->name, pci_id_tbl[chip_idx].name, inl(ioaddr + ChipRev), ioaddr);
@@ -525,6 +546,13 @@
 	
 	return 0;
 
+err_out_unmap_status:
+        pci_free_consistent(pdev, STATUS_TOTAL_SIZE, np->tx_status, 
+		np->tx_status_dma);
+err_out_unmap_rx:
+        pci_free_consistent(pdev, RX_TOTAL_SIZE, np->rx_ring, np->rx_ring_dma);
+err_out_unmap_tx:
+        pci_free_consistent(pdev, TX_TOTAL_SIZE, np->tx_ring, np->tx_ring_dma);
 err_out_cleardev:
 	pci_set_drvdata(pdev, NULL);
 #ifndef USE_IO_OPS
@@ -597,8 +625,8 @@
 
 	yellowfin_init_ring(dev);
 
-	outl(virt_to_bus(yp->rx_ring), ioaddr + RxPtr);
-	outl(virt_to_bus(yp->tx_ring), ioaddr + TxPtr);
+	outl(yp->rx_ring_dma, ioaddr + RxPtr);
+	outl(yp->tx_ring_dma, ioaddr + TxPtr);
 
 	for (i = 0; i < 6; i++)
 		outb(dev->dev_addr[i], ioaddr + StnAddr + i);
@@ -742,24 +770,23 @@
 	yp->dirty_tx = 0;
 
 	yp->rx_buf_sz = (dev->mtu <= 1500 ? PKT_BUF_SZ : dev->mtu + 32);
-	yp->rx_head_desc = &yp->rx_ring[0];
 
 	for (i = 0; i < RX_RING_SIZE; i++) {
 		yp->rx_ring[i].dbdma_cmd =
 			cpu_to_le32(CMD_RX_BUF | INTR_ALWAYS | yp->rx_buf_sz);
-		yp->rx_ring[i].branch_addr = virt_to_le32desc(&yp->rx_ring[i+1]);
+		yp->rx_ring[i].branch_addr = cpu_to_le32(yp->rx_ring_dma +
+			((i+1)%RX_RING_SIZE)*sizeof(struct yellowfin_desc));
 	}
-	/* Mark the last entry as wrapping the ring. */
-	yp->rx_ring[i-1].branch_addr = virt_to_le32desc(&yp->rx_ring[0]);
 
 	for (i = 0; i < RX_RING_SIZE; i++) {
 		struct sk_buff *skb = dev_alloc_skb(yp->rx_buf_sz);
 		yp->rx_skbuff[i] = skb;
 		if (skb == NULL)
 			break;
-		skb->dev = dev;			/* Mark as being used by this device. */
+		skb->dev = dev;		/* Mark as being used by this device. */
 		skb_reserve(skb, 2);	/* 16 byte align the IP header. */
-		yp->rx_ring[i].addr = virt_to_le32desc(skb->tail);
+		yp->rx_ring[i].addr = pci_map_single(yp->pci_dev, skb->tail,
+			yp->rx_buf_sz, PCI_DMA_FROMDEVICE);
 	}
 	yp->rx_ring[i-1].dbdma_cmd = cpu_to_le32(CMD_STOP);
 	yp->dirty_rx = (unsigned int)(i - RX_RING_SIZE);
@@ -770,35 +797,47 @@
 	for (i = 0; i < TX_RING_SIZE; i++) {
 		yp->tx_skbuff[i] = 0;
 		yp->tx_ring[i].dbdma_cmd = cpu_to_le32(CMD_STOP);
-		yp->tx_ring[i].branch_addr = virt_to_le32desc(&yp->tx_ring[i+1]);
+		yp->tx_ring[i].branch_addr = cpu_to_le32(yp->tx_ring_dma +
+			((i+1)%TX_RING_SIZE)*sizeof(struct yellowfin_desc));
 	}
 	/* Wrap ring */
 	yp->tx_ring[--i].dbdma_cmd = cpu_to_le32(CMD_STOP | BRANCH_ALWAYS);
-	yp->tx_ring[i].branch_addr = virt_to_le32desc(&yp->tx_ring[0]);
 #else
+{
+	int j;
+
 	/* Tx ring needs a pair of descriptors, the second for the status. */
-	for (i = 0; i < TX_RING_SIZE*2; i++) {
-		yp->tx_skbuff[i/2] = 0;
+	for (i = 0; i < TX_RING_SIZE; i++) {
+		j = 2*i;
+		yp->tx_skbuff[i] = 0;
 		/* Branch on Tx error. */
-		yp->tx_ring[i].dbdma_cmd = cpu_to_le32(CMD_STOP);
-		yp->tx_ring[i].branch_addr = virt_to_le32desc(&yp->tx_ring[i+1]);
-		i++;
+		yp->tx_ring[j].dbdma_cmd = cpu_to_le32(CMD_STOP);
+		yp->tx_ring[j].branch_addr = cpu_to_le32(yp->tx_ring_dma +
+			(j+1)*sizeof(struct yellowfin_desc);
+		j++;
 		if (yp->flags & FullTxStatus) {
-			yp->tx_ring[i].dbdma_cmd =
-				cpu_to_le32(CMD_TXSTATUS | sizeof(yp->tx_status[i]));
-			yp->tx_ring[i].request_cnt = sizeof(yp->tx_status[i]);
-			yp->tx_ring[i].addr = virt_to_le32desc(&yp->tx_status[i/2]);
-		} else {				/* Symbios chips write only tx_errs word. */
-			yp->tx_ring[i].dbdma_cmd =
+			yp->tx_ring[j].dbdma_cmd =
+				cpu_to_le32(CMD_TXSTATUS | sizeof(*yp->tx_status));
+			yp->tx_ring[j].request_cnt = sizeof(*yp->tx_status);
+			yp->tx_ring[j].addr = cpu_to_le32(yp->tx_status_dma +
+				i*sizeof(struct tx_status_words);
+		} else {
+			/* Symbios chips write only tx_errs word. */
+			yp->tx_ring[j].dbdma_cmd =
 				cpu_to_le32(CMD_TXSTATUS | INTR_ALWAYS | 2);
-			yp->tx_ring[i].request_cnt = 2;
-			yp->tx_ring[i].addr = virt_to_le32desc(&yp->tx_status[i/2].tx_errs);
+			yp->tx_ring[j].request_cnt = 2;
+			/* Om pade ummmmm... */
+			yp->tx_ring[j].addr = cpu_to_le32(yp->tx_status_dma +
+				i*sizeof(struct tx_status_words) +
+				&(yp->tx_status[0].tx_errs) - 
+				&(yp->tx_status[0]));
 		}
-		yp->tx_ring[i].branch_addr = virt_to_le32desc(&yp->tx_ring[i+1]);
+		yp->tx_ring[j].branch_addr = cpu_to_le32(yp->tx_ring_dma + 
+			((j+1)%(2*TX_RING_SIZE))*sizeof(struct yellowfin_desc));
 	}
 	/* Wrap ring */
-	yp->tx_ring[--i].dbdma_cmd |= cpu_to_le32(BRANCH_ALWAYS | INTR_ALWAYS);
-	yp->tx_ring[i].branch_addr = virt_to_le32desc(&yp->tx_ring[0]);
+	yp->tx_ring[++j].dbdma_cmd |= cpu_to_le32(BRANCH_ALWAYS | INTR_ALWAYS);
+}
 #endif
 	yp->tx_tail_desc = &yp->tx_status[0];
 	return;
@@ -819,14 +858,15 @@
 
 	yp->tx_skbuff[entry] = skb;
 
-	if (gx_fix) {		/* Note: only works for paddable protocols e.g. IP. */
-		int cacheline_end = (virt_to_bus(skb->data) + skb->len) % 32;
+	if (gx_fix) {	/* Note: only works for paddable protocols e.g.  IP. */
+		int cacheline_end = ((unsigned long)skb->data + skb->len) % 32;
 		/* Fix GX chipset errata. */
 		if (cacheline_end > 24  || cacheline_end == 0)
 			skb->len += 32 - cacheline_end + 1;
 	}
 #ifdef NO_TXSTATS
-	yp->tx_ring[entry].addr = virt_to_le32desc(skb->data);
+	yp->tx_ring[entry].addr = cpu_to_le32(pci_map_single(yp->pci_dev, 
+		skb->data, skb->len, PCI_DMA_TODEVICE));
 	yp->tx_ring[entry].result_status = 0;
 	if (entry >= TX_RING_SIZE-1) {
 		/* New stop command. */
@@ -841,9 +881,10 @@
 	yp->cur_tx++;
 #else
 	yp->tx_ring[entry<<1].request_cnt = skb->len;
-	yp->tx_ring[entry<<1].addr = virt_to_le32desc(skb->data);
-	/* The input_last (status-write) command is constant, but we must rewrite
-	   the subsequent 'stop' command. */
+	yp->tx_ring[entry<<1].addr = cpu_to_le32(pci_map_single(yp->pci_dev, 
+		skb->data, skb->len, PCI_DMA_TODEVICE));
+	/* The input_last (status-write) command is constant, but we must 
+	   rewrite the subsequent 'stop' command. */
 
 	yp->cur_tx++;
 	{
@@ -914,12 +955,17 @@
 #ifdef NO_TXSTATS
 		for (; yp->cur_tx - yp->dirty_tx > 0; yp->dirty_tx++) {
 			int entry = yp->dirty_tx % TX_RING_SIZE;
+			struct sk_buff *skb;
+
 			if (yp->tx_ring[entry].result_status == 0)
 				break;
+			skb = yp->tx_skbuff[entry];
 			yp->stats.tx_packets++;
-			yp->stats.tx_bytes += yp->tx_skbuff[entry]->len;
+			yp->stats.tx_bytes += skb->len;
 			/* Free the original skb. */
-			dev_kfree_skb_irq(yp->tx_skbuff[entry]);
+			pci_unmap_single(yp->pci_dev, yp->tx_ring[entry].addr,
+				skb->len, PCI_DMA_TODEVICE);
+			dev_kfree_skb_irq(skb);
 			yp->tx_skbuff[entry] = 0;
 		}
 		if (yp->tx_full
@@ -929,8 +975,7 @@
 			netif_wake_queue(dev);
 		}
 #else
-		if (intr_status & IntrTxDone
-			|| yp->tx_tail_desc->tx_errs) {
+		if ((intr_status & IntrTxDone) || (yp->tx_tail_desc->tx_errs)) {
 			unsigned dirty_tx = yp->dirty_tx;
 
 			for (dirty_tx = yp->dirty_tx; yp->cur_tx - dirty_tx > 0;
@@ -938,6 +983,7 @@
 				/* Todo: optimize this. */
 				int entry = dirty_tx % TX_RING_SIZE;
 				u16 tx_errs = yp->tx_status[entry].tx_errs;
+				struct sk_buff *skb;
 
 #ifndef final_version
 				if (yellowfin_debug > 5)
@@ -950,7 +996,8 @@
 						   yp->tx_status[entry].paused);
 #endif
 				if (tx_errs == 0)
-					break;			/* It still hasn't been Txed */
+					break;	/* It still hasn't been Txed */
+				skb = yp->tx_skbuff[entry];
 				if (tx_errs & 0xF810) {
 					/* There was an major error, log it. */
 #ifndef final_version
@@ -975,12 +1022,15 @@
 #ifdef ETHER_STATS
 					if (tx_errs & 0x0400) yp->stats.tx_deferred++;
 #endif
-					yp->stats.tx_bytes += yp->tx_skbuff[entry]->len;
+					yp->stats.tx_bytes += skb->len;
 					yp->stats.collisions += tx_errs & 15;
 					yp->stats.tx_packets++;
 				}
 				/* Free the original skb. */
-				dev_kfree_skb_irq(yp->tx_skbuff[entry]);
+				pci_unmap_single(yp->pci_dev, 
+					yp->tx_ring[entry<<1].addr, skb->len, 
+					PCI_DMA_TODEVICE);
+				dev_kfree_skb_irq(skb);
 				yp->tx_skbuff[entry] = 0;
 				/* Mark status as empty. */
 				yp->tx_status[entry].tx_errs = 0;
@@ -1043,15 +1093,23 @@
 	}
 
 	/* If EOP is set on the next entry, it's a new packet. Send it up. */
-	while (yp->rx_head_desc->result_status) {
-		struct yellowfin_desc *desc = yp->rx_head_desc;
-		u16 desc_status = le32_to_cpu(desc->result_status) >> 16;
-		int data_size =
-			(le32_to_cpu(desc->dbdma_cmd) - le32_to_cpu(desc->result_status))
-			& 0xffff;
-		u8 *buf_addr = le32desc_to_virt(desc->addr);
-		s16 frame_status = get_unaligned((s16*)&(buf_addr[data_size - 2]));
+	while (1) {
+		struct yellowfin_desc *desc = &yp->rx_ring[entry];
+		struct sk_buff *rx_skb = yp->rx_skbuff[entry];
+		s16 frame_status;
+		u16 desc_status;
+		int data_size;
+		u8 *buf_addr;
 
+		if(!desc->result_status)
+			break;
+		pci_dma_sync_single(yp->pci_dev, desc->addr, 
+			yp->rx_buf_sz, PCI_DMA_FROMDEVICE);
+		desc_status = le32_to_cpu(desc->result_status) >> 16;
+		buf_addr = rx_skb->tail;
+		data_size = (le32_to_cpu(desc->dbdma_cmd) - 
+			le32_to_cpu(desc->result_status)) & 0xffff;
+		frame_status = get_unaligned((s16*)&(buf_addr[data_size - 2]));
 		if (yellowfin_debug > 4)
 			printk(KERN_DEBUG "  yellowfin_rx() status was %4.4x.\n",
 				   frame_status);
@@ -1080,12 +1138,14 @@
 			if (status2 & 0x03) yp->stats.rx_frame_errors++;
 			if (status2 & 0x04) yp->stats.rx_crc_errors++;
 			if (status2 & 0x80) yp->stats.rx_dropped++;
-#ifdef YF_PROTOTYPE			/* Support for prototype hardware errata. */
+#ifdef YF_PROTOTYPE		/* Support for prototype hardware errata. */
 		} else if ((yp->flags & HasMACAddrBug)  &&
-				   memcmp(le32desc_to_virt(yp->rx_ring[entry].addr),
-						  dev->dev_addr, 6) != 0
-				   && memcmp(le32desc_to_virt(yp->rx_ring[entry].addr),
-							 "\377\377\377\377\377\377", 6) != 0) {
+			memcmp(le32_to_cpu(yp->rx_ring_dma +
+				entry*sizeof(struct yellowfin_desc)),
+				dev->dev_addr, 6) != 0 && 
+			memcmp(le32_to_cpu(yp->rx_ring_dma +
+				entry*sizeof(struct yellowfin_desc)),
+				"\377\377\377\377\377\377", 6) != 0) {
 			if (bogus_rx++ == 0)
 				printk(KERN_WARNING "%s: Bad frame to %2.2x:%2.2x:%2.2x:%2.2x:"
 					   "%2.2x:%2.2x.\n",
@@ -1107,16 +1167,12 @@
 			/* Check if the packet is long enough to just pass up the skbuff
 			   without copying to a properly sized skbuff. */
 			if (pkt_len > rx_copybreak) {
-				char *temp = skb_put(skb = yp->rx_skbuff[entry], pkt_len);
+				skb_put(skb = rx_skb, pkt_len);
+				pci_unmap_single(yp->pci_dev, 
+					yp->rx_ring[entry].addr, 
+					yp->rx_buf_sz, 
+					PCI_DMA_FROMDEVICE);
 				yp->rx_skbuff[entry] = NULL;
-#ifndef final_version				/* Remove after testing. */
-				if (le32desc_to_virt(yp->rx_ring[entry].addr) != temp)
-					printk(KERN_ERR "%s: Internal fault: The skbuff addresses "
-						   "do not match in yellowfin_rx: %p vs. %p / %p.\n",
-						   dev->name,
-						   le32desc_to_virt(yp->rx_ring[entry].addr),
-						   skb->head, temp);
-#endif
 			} else {
 				skb = dev_alloc_skb(pkt_len + 2);
 				if (skb == NULL)
@@ -1124,11 +1180,11 @@
 				skb->dev = dev;
 				skb_reserve(skb, 2);	/* 16 byte align the IP header */
 #if HAS_IP_COPYSUM
-				eth_copy_and_sum(skb, yp->rx_skbuff[entry]->tail, pkt_len, 0);
+				eth_copy_and_sum(skb, rx_skb->tail, pkt_len, 0);
 				skb_put(skb, pkt_len);
 #else
-				memcpy(skb_put(skb, pkt_len), yp->rx_skbuff[entry]->tail,
-					   pkt_len);
+				memcpy(skb_put(skb, pkt_len), 
+					rx_skb->tail, pkt_len);
 #endif
 			}
 			skb->protocol = eth_type_trans(skb, dev);
@@ -1138,7 +1194,6 @@
 			yp->stats.rx_bytes += pkt_len;
 		}
 		entry = (++yp->cur_rx) % RX_RING_SIZE;
-		yp->rx_head_desc = &yp->rx_ring[entry];
 	}
 
 	/* Refill the Rx ring buffers. */
@@ -1146,12 +1201,13 @@
 		entry = yp->dirty_rx % RX_RING_SIZE;
 		if (yp->rx_skbuff[entry] == NULL) {
 			struct sk_buff *skb = dev_alloc_skb(yp->rx_buf_sz);
-			yp->rx_skbuff[entry] = skb;
 			if (skb == NULL)
 				break;				/* Better luck next round. */
-			skb->dev = dev;			/* Mark as being used by this device. */
+			yp->rx_skbuff[entry] = skb;
+			skb->dev = dev;	/* Mark as being used by this device. */
 			skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */
-			yp->rx_ring[entry].addr = virt_to_le32desc(skb->tail);
+			yp->rx_ring[entry].addr = pci_map_single(yp->pci_dev,
+				skb->tail, yp->rx_buf_sz, PCI_DMA_FROMDEVICE);
 		}
 		yp->rx_ring[entry].dbdma_cmd = cpu_to_le32(CMD_STOP);
 		yp->rx_ring[entry].result_status = 0;	/* Clear complete bit. */
@@ -1208,8 +1264,7 @@
 
 #if defined(__i386__)
 	if (yellowfin_debug > 2) {
-		printk("\n"KERN_DEBUG"  Tx ring at %8.8x:\n",
-			   (int)virt_to_bus(yp->tx_ring));
+		printk("\n"KERN_DEBUG"  Tx ring at %8.8x:\n", yp->tx_ring_dma);
 		for (i = 0; i < TX_RING_SIZE*2; i++)
 			printk(" %c #%d desc. %8.8x %8.8x %8.8x %8.8x.\n",
 				   inl(ioaddr + TxPtr) == (long)&yp->tx_ring[i] ? '>' : ' ',
@@ -1221,8 +1276,7 @@
 				   i, yp->tx_status[i].tx_cnt, yp->tx_status[i].tx_errs,
 				   yp->tx_status[i].total_tx_cnt, yp->tx_status[i].paused);
 
-		printk("\n"KERN_DEBUG "  Rx ring %8.8x:\n",
-			   (int)virt_to_bus(yp->rx_ring));
+		printk("\n"KERN_DEBUG "  Rx ring %8.8x:\n", yp->rx_ring_dma);
 		for (i = 0; i < RX_RING_SIZE; i++) {
 			printk(KERN_DEBUG " %c #%d desc. %8.8x %8.8x %8.8x\n",
 				   inl(ioaddr + RxPtr) == (long)&yp->rx_ring[i] ? '>' : ' ',
@@ -1422,6 +1476,10 @@
 		BUG();
 	np = dev->priv;
 
+        pci_free_consistent(pdev, STATUS_TOTAL_SIZE, np->tx_status, 
+		np->tx_status_dma);
+	pci_free_consistent(pdev, RX_TOTAL_SIZE, np->rx_ring, np->rx_ring_dma);
+	pci_free_consistent(pdev, TX_TOTAL_SIZE, np->tx_ring, np->tx_ring_dma);
 	unregister_netdev (dev);
 
 	pci_release_regions (pdev);
diff -urN linux-2.4.7-pre6/drivers/net/znet.c linux/drivers/net/znet.c
--- linux-2.4.7-pre6/drivers/net/znet.c	Thu Apr 19 09:34:52 2001
+++ linux/drivers/net/znet.c	Mon Dec  3 22:55:50 2001
@@ -5,7 +5,7 @@
 /*
 	Written by Donald Becker.
 
-	The author may be reached as becker@cesdis.gsfc.nasa.gov.
+	The author may be reached as becker@scyld.com.
 	This driver is based on the Linux skeleton driver.  The copyright of the
 	skeleton driver is held by the United States Government, as represented
 	by DIRNSA, and it is released under the GPL.
diff -urN linux-2.4.7-pre6/drivers/pcmcia/rsrc_mgr.c linux/drivers/pcmcia/rsrc_mgr.c
--- linux-2.4.7-pre6/drivers/pcmcia/rsrc_mgr.c	Tue Mar  6 19:28:32 2001
+++ linux/drivers/pcmcia/rsrc_mgr.c	Mon Dec  3 22:55:50 2001
@@ -189,6 +189,10 @@
     
     /* First, what does a floating port look like? */
     b = kmalloc(256, GFP_KERNEL);
+    if (!b) {
+            printk(KERN_ERR "do_io_probe: unable to kmalloc 256 bytes");
+            return;
+    }   
     memset(b, 0, 256);
     for (i = base, most = 0; i < base+num; i += 8) {
 	if (check_io_resource(i, 8))
diff -urN linux-2.4.7-pre6/drivers/scsi/aha152x.c linux/drivers/scsi/aha152x.c
--- linux-2.4.7-pre6/drivers/scsi/aha152x.c	Wed Jun 27 17:10:55 2001
+++ linux/drivers/scsi/aha152x.c	Mon Dec  3 22:55:50 2001
@@ -238,6 +238,7 @@
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/isapnp.h>
 #include <asm/semaphore.h>
 #include <linux/spinlock.h>
 
@@ -385,6 +386,16 @@
 MODULE_PARM_DESC(aha152x1, "parameters for second controller");
 static int aha152x1[]  = {0, 11, 7, 1, 1, 1, DELAY_DEFAULT, 0, DEBUG_DEFAULT};
 #endif /* !defined(AHA152X_DEBUG) */
+
+#ifdef __ISAPNP__
+
+static struct isapnp_device_id id_table[] __devinitdata = {
+	{ ISAPNP_DEVICE_SINGLE('A','D','P',0x1505, 'A','D','P',0x1505), },
+	{ ISAPNP_DEVICE_SINGLE_END, }
+};
+MODULE_DEVICE_TABLE(isapnp, id_table);
+
+#endif /* ISAPNP */
 #endif /* MODULE */
 
 /* set by aha152x_setup according to the command line */
@@ -940,12 +951,18 @@
 	SETPORT(DMACNTRL0, INTEN);
 }
 
-
+#ifdef __ISAPNP__
+static struct pci_dev *pnpdev[2];
+static int num_pnpdevs;
+#endif
 int aha152x_detect(Scsi_Host_Template * tpnt)
 {
 	int i, j, ok;
 #if defined(AUTOCONF)
 	aha152x_config conf;
+#ifdef __ISAPNP__
+	struct pci_dev *dev = NULL;
+#endif
 #endif
 	tpnt->proc_name = "aha152x"; 
 
@@ -962,6 +979,29 @@
 			}
 		printk("ok\n");
 	}
+#ifdef __ISAPNP__
+	while (setup_count <= 2 &&
+	       (dev = isapnp_find_dev (NULL, ISAPNP_VENDOR('A','D','P'),
+				       ISAPNP_FUNCTION(0x1505), dev))) {
+		if (dev->prepare(dev) < 0)
+			continue;
+		if (dev->active)
+			continue;
+		if (!(dev->resource[0].flags & IORESOURCE_IO))
+			continue;
+		dev->resource[0].flags |= IORESOURCE_AUTO;
+		if (dev->activate(dev) < 0)
+			continue;
+		setup[setup_count].io_port = dev->resource[0].start;
+		setup[setup_count].irq = dev->irq_resource[0].start;
+		pnpdev[num_pnpdevs++] = dev;
+		printk (KERN_INFO
+			"aha152x: found ISAPnP AVA-1505A at address 0x%03X, IRQ %d\n",
+			setup[setup_count].io_port, setup[setup_count].irq);
+		setup_count++;
+	}
+#endif
+
 #if defined(SETUP0)
 	if (setup_count < 2) {
 		struct aha152x_setup override = SETUP0;
@@ -1349,6 +1389,10 @@
 	if (shpnt->io_port)
 		release_region(shpnt->io_port, IO_RANGE);
 
+#ifdef __ISAPNP__
+	while (num_pnpdevs--)
+		pnpdev[num_pnpdevs]->deactivate(pnpdev[num_pnpdevs]);
+#endif
 	scsi_unregister(shpnt);
 
 	return 0;
diff -urN linux-2.4.7-pre6/drivers/scsi/atp870u.c linux/drivers/scsi/atp870u.c
--- linux-2.4.7-pre6/drivers/scsi/atp870u.c	Fri Apr 27 13:59:18 2001
+++ linux/drivers/scsi/atp870u.c	Mon Dec  3 22:55:50 2001
@@ -10,6 +10,8 @@
  *		   support atp876 chip
  *		   enable 32 bit fifo transfer
  *		   support cdrom & remove device run ultra speed
+ *		   fix disconnect bug  2000/12/21
+ *		   support atp880 chip lvd u160 2001/05/15
  */
 
 #include <linux/module.h>
@@ -63,6 +65,7 @@
 	unsigned short wide_idu;
 	unsigned short active_idu;
 	unsigned short ultra_map;
+	unsigned short deviceid;
 	unsigned char ata_cdbu[16];
 	Scsi_Cmnd *querequ[qcnt];
 	struct atp_id
@@ -137,14 +140,6 @@
 		tmport -= 0x08;
 
 		i = inb(tmport);
-		if ((j & 0x40) == 0)
-		{
-			if ((dev->last_cmd & 0x40) == 0)
-			{
-				dev->last_cmd = 0xff;
-			}
-		}
-		else dev->last_cmd |= 0x40;
 
 		tmport -= 0x02;
 		target_id = inb(tmport);
@@ -160,8 +155,21 @@
 			target_id &= 0x07;
 		}
 
+		if ((j & 0x40) != 0)
+		{
+		     if (dev->last_cmd == 0xff)
+		     {
+			dev->last_cmd = target_id;
+		     }
+		     dev->last_cmd |= 0x40;
+		}
+
 		if (i == 0x85)
 		{
+			if ((dev->last_cmd & 0xf0) != 0x40)
+			{
+			   dev->last_cmd = 0xff;
+			}
 			/*
 			 *	Flip wide
 			 */
@@ -188,8 +196,20 @@
 			dev->in_int = 0;
 			return;
 		}
+
+		if (i == 0x40)
+		{
+		     dev->last_cmd |= 0x40;
+		     dev->in_int = 0;
+		     return;
+		}
+
 		if (i == 0x21)
 		{
+			if ((dev->last_cmd & 0xf0) != 0x40)
+			{
+			   dev->last_cmd = 0xff;
+			}
 			tmport -= 0x05;
 			adrcntu = 0;
 			((unsigned char *) &adrcntu)[2] = inb(tmport++);
@@ -215,6 +235,10 @@
 				tmport += 0x0d;
 				lun = inb(tmport) & 0x07;
 			} else {
+				if ((dev->last_cmd & 0xf0) != 0x40)
+				{
+				   dev->last_cmd = 0xff;
+				}
 				if (j == 0x41)
 				{
 					tmport += 0x02;
@@ -245,6 +269,10 @@
 					return;
 				}
 			}
+			if (dev->last_cmd != 0xff)
+			{
+			   dev->last_cmd |= 0x40;
+			}
 			tmport = workportu + 0x10;
 			outb(0x45, tmport);
 			tmport += 0x06;
@@ -279,15 +307,31 @@
 			outb(0x80, tmport);
 
 			/* enable 32 bit fifo transfer */
-			tmport = workportu + 0x3a;
-			if ((dev->ata_cdbu[0] == 0x08) || (dev->ata_cdbu[0] == 0x28) ||
-			    (dev->ata_cdbu[0] == 0x0a) || (dev->ata_cdbu[0] == 0x2a))
+			if (dev->deviceid != 0x8081)
 			{
-				outb((unsigned char)((inb(tmport) & 0xf3) | 0x08),tmport);
+			   tmport = workportu + 0x3a;
+			   if ((dev->ata_cdbu[0] == 0x08) || (dev->ata_cdbu[0] == 0x28) ||
+			       (dev->ata_cdbu[0] == 0x0a) || (dev->ata_cdbu[0] == 0x2a))
+			   {
+			      outb((unsigned char)((inb(tmport) & 0xf3) | 0x08),tmport);
+			   }
+			   else
+			   {
+			      outb((unsigned char)(inb(tmport) & 0xf3),tmport);
+			   }
 			}
 			else
 			{
-				outb((unsigned char)(inb(tmport) & 0xf3),tmport);
+			   tmport = workportu - 0x05;
+			   if ((dev->ata_cdbu[0] == 0x08) || (dev->ata_cdbu[0] == 0x28) ||
+			       (dev->ata_cdbu[0] == 0x0a) || (dev->ata_cdbu[0] == 0x2a))
+			   {
+			      outb((unsigned char)((inb(tmport) & 0x3f) | 0xc0),tmport);
+			   }
+			   else
+			   {
+			      outb((unsigned char)(inb(tmport) & 0x3f),tmport);
+			   }
 			}
 
 			tmport = workportu + 0x1b;
@@ -303,7 +347,7 @@
 			outb(j, tmport);
 			while ((inb(tmport) & 0x01) != j)
 			{
-				outb(j,tmport);
+			   outb(j,tmport);
 			}
 
 			if (dev->id[target_id].last_lenu == 0) {
@@ -365,12 +409,20 @@
 		workrequ = dev->id[target_id].curr_req;
 
 		if (i == 0x42) {
+			if ((dev->last_cmd & 0xf0) != 0x40)
+			{
+			   dev->last_cmd = 0xff;
+			}
 			errstus = 0x02;
 			workrequ->result = errstus;
 			goto go_42;
 		}
 		if (i == 0x16)
 		{
+			if ((dev->last_cmd & 0xf0) != 0x40)
+			{
+			   dev->last_cmd = 0xff;
+			}
 			errstus = 0;
 			tmport -= 0x08;
 			errstus = inb(tmport);
@@ -381,13 +433,13 @@
 			 */
 			spin_lock_irqsave(&io_request_lock, flags);
 			(*workrequ->scsi_done) (workrequ);
-			spin_unlock_irqrestore(&io_request_lock, flags);
 
 			/*
 			 *	Clear it off the queue
 			 */
 			dev->id[target_id].curr_req = 0;
 			dev->working--;
+			spin_unlock_irqrestore(&io_request_lock, flags);
 			/*
 			 *	Take it back wide
 			 */
@@ -396,7 +448,7 @@
 				outb(0x01,tmport);
 				while ((inb(tmport) & 0x01) != 0x01)
 				{
-					outb(0x01,tmport);
+				   outb(0x01,tmport);
 				}
 			}
 			/*
@@ -405,11 +457,15 @@
 			if (((dev->last_cmd != 0xff) || (dev->quhdu != dev->quendu)) &&
 			    (dev->in_snd == 0))
 			{
-				send_s870(h);
+			   send_s870(h);
 			}
 			dev->in_int = 0;
 			return;
 		}
+		if ((dev->last_cmd & 0xf0) != 0x40)
+		{
+		   dev->last_cmd = 0xff;
+		}
 		if (i == 0x4f) {
 			i = 0x89;
 		}
@@ -474,7 +530,7 @@
 
 int atp870u_queuecommand(Scsi_Cmnd * req_p, void (*done) (Scsi_Cmnd *))
 {
-	unsigned char i, h;
+	unsigned char h;
 	unsigned long flags;
 	unsigned short int m;
 	unsigned int tmport;
@@ -516,6 +572,8 @@
 	/*
 	 *	Count new command
 	 */
+	save_flags(flags);
+	cli();
 	dev->quendu++;
 	if (dev->quendu >= qcnt) {
 		dev->quendu = 0;
@@ -523,18 +581,17 @@
 	/*
 	 *	Check queue state
 	 */
-wait_que_empty:
 	if (dev->quhdu == dev->quendu) {
-		goto wait_que_empty;
+		if (dev->quendu == 0) {
+			dev->quendu = qcnt;
+		}
+		dev->quendu--;
+		req_p->result = 0x00020000;
+		done(req_p);
+		restore_flags(flags);
+		return 0;
 	}
-	save_flags(flags);
-	cli();
 	dev->querequ[dev->quendu] = req_p;
-	if (dev->quendu == 0) {
-		i = qcnt - 1;
-	} else {
-		i = dev->quendu - 1;
-	}
 	tmport = dev->ioport + 0x1c;
 	restore_flags(flags);
 	if ((inb(tmport) == 0) && (dev->in_int == 0) && (dev->in_snd == 0)) {
@@ -582,11 +639,17 @@
 		dev->last_cmd = 0xff;
 		if (dev->quhdu == dev->quendu)
 		{
-			dev->in_snd = 0;
-			restore_flags(flags);
-			return ;
+		   dev->in_snd = 0;
+		   restore_flags(flags);
+		   return ;
 		}
 	}
+	if ((dev->last_cmd != 0xff) && (dev->working != 0))
+	{
+	     dev->in_snd = 0;
+	     restore_flags(flags);
+	     return ;
+	}
 	dev->working++;
 	j = dev->quhdu;
 	dev->quhdu++;
@@ -629,15 +692,6 @@
 	if (dev->ata_cdbu[0] == 0x00) {
 		workrequ->request_bufflen = 0;
 	}
-	/*
-	 *	Why limit this ????
-	 */
-	if (dev->ata_cdbu[0] == INQUIRY) {
-		if (workrequ->request_bufflen > 0x24) {
-			workrequ->request_bufflen = 0x24;
-			dev->ata_cdbu[4] = 0x24;
-		}
-	}
 
 	tmport = workportu + 0x1b;
 	j = 0;
@@ -654,7 +708,7 @@
 	outb(j, tmport);
 	while ((inb(tmport) & 0x01) != j)
 	{
-		outb(j,tmport);
+	   outb(j,tmport);
 	}
 
 	/*
@@ -780,15 +834,31 @@
 	outb(0x00, tmpcip);
 	tmpcip = tmpcip - 2;
 
-	tmport = workportu + 0x3a;
-	if ((dev->ata_cdbu[0] == 0x08) || (dev->ata_cdbu[0] == 0x28) ||
-	    (dev->ata_cdbu[0] == 0x0a) || (dev->ata_cdbu[0] == 0x2a))
+	if (dev->deviceid != 0x8081)
 	{
-		outb((unsigned char)((inb(tmport) & 0xf3) | 0x08),tmport);
+	   tmport = workportu + 0x3a;
+	   if ((dev->ata_cdbu[0] == 0x08) || (dev->ata_cdbu[0] == 0x28) ||
+	       (dev->ata_cdbu[0] == 0x0a) || (dev->ata_cdbu[0] == 0x2a))
+	   {
+	      outb((unsigned char)((inb(tmport) & 0xf3) | 0x08),tmport);
+	   }
+	   else
+	   {
+	      outb((unsigned char)(inb(tmport) & 0xf3),tmport);
+	   }
 	}
 	else
 	{
-		outb((unsigned char)(inb(tmport) & 0xf3),tmport);
+	   tmport = workportu - 0x05;
+	   if ((dev->ata_cdbu[0] == 0x08) || (dev->ata_cdbu[0] == 0x28) ||
+	       (dev->ata_cdbu[0] == 0x0a) || (dev->ata_cdbu[0] == 0x2a))
+	   {
+	      outb((unsigned char)((inb(tmport) & 0x3f) | 0xc0),tmport);
+	   }
+	   else
+	   {
+	      outb((unsigned char)(inb(tmport) & 0x3f),tmport);
+	   }
 	}
 	tmport = workportu + 0x1c;
 
@@ -1152,11 +1222,11 @@
 		}
 		tmport = wkport + 0x1b;
 		if (dev->chip_veru == 4) {
-			outb(0x01, tmport);
+		   outb(0x01, tmport);
 		}
 		else
 		{
-			outb(0x00, tmport);
+		   outb(0x00, tmport);
 		}
 		tmport = wkport + 1;
 		outb(0x08, tmport++);
@@ -1615,182 +1685,909 @@
 	outb((unsigned char) (inb(tmport) & 0xef), tmport);
 }
 
-/* return non-zero on detection */
-int atp870u_detect(Scsi_Host_Template * tpnt)
+void is880(unsigned long host, unsigned int wkport)
 {
-	unsigned char irq, h, k;
-	unsigned long flags;
-	unsigned int base_io, error, tmport;
-	unsigned short index = 0;
-	struct pci_dev *pdev[3];
-	unsigned char chip_ver[3], host_id;
-	struct Scsi_Host *shpnt = NULL;
-	int tmpcnt = 0;
-	int count = 0;
-
-	static unsigned short devid[8] = {
-		0x8002, 0x8010, 0x8020, 0x8030, 0x8040, 0x8050, 0x8060, 0
-	};
+	unsigned int tmport;
+	unsigned char i, j, k, rmb, n, lvdmode;
+	unsigned short int m;
+	static unsigned char mbuf[512];
+	static unsigned char satn[9] =	{0, 0, 0, 0, 0, 0, 0, 6, 6};
+	static unsigned char inqd[9] =	{0x12, 0, 0, 0, 0x24, 0, 0, 0x24, 6};
+	static unsigned char synn[6] =	{0x80, 1, 3, 1, 0x19, 0x0e};
+	static unsigned char synu[6] =	{0x80, 1, 3, 1, 0x0a, 0x0e};
+	static unsigned char synw[6] =	{0x80, 1, 3, 1, 0x0a, 0x0e};
+	static unsigned char wide[6] =	{0x80, 1, 2, 3, 1, 0};
+	static unsigned char u3[9] = { 0x80,1,6,4,0x09,00,0x0e,0x01,0x02 };
+	struct atp_unit *dev = &atp_unit[host];
 
-	printk(KERN_INFO "aec671x_detect: \n");
-	if (!pci_present()) {
-		printk(KERN_INFO"   NO PCI SUPPORT.\n");
-		return count;
-	}
-	tpnt->proc_name = "atp870u";
+	sync_idu = 0;
+	lvdmode=inb(wkport + 0x3f) & 0x40;
 
-	for (h = 0; h < 2; h++) {
-		struct atp_unit *dev = &atp_unit[h];
-		for(k=0;k<16;k++)
-		{
-			dev->id[k].prd_tableu = kmalloc(1024, GFP_KERNEL);
-			dev->id[k].devspu=0x20;
-			dev->id[k].devtypeu = 0;
-			dev->id[k].curr_req = NULL;
-		}
-		dev->active_idu = 0;
-		dev->wide_idu = 0;
-		dev->host_idu = 0x07;
-		dev->quhdu = 0;
-		dev->quendu = 0;
-		pdev[h]=NULL;
-		pdev[2]=NULL;
-		dev->chip_veru = 0;
-		dev->last_cmd = 0xff;
-		dev->in_snd = 0;
-		dev->in_int = 0;
-		for (k = 0; k < qcnt; k++) {
-			dev->querequ[k] = 0;
-		}
-		for (k = 0; k < 16; k++) {
-			dev->id[k].curr_req = 0;
-		}
-	}
-	h = 0;
-	while (devid[h] != 0) {
-		pdev[2] = pci_find_device(0x1191, devid[h], pdev[2]);
-		if (pdev[2] == NULL || pci_enable_device(pdev[2])) {
-			h++;
-			index = 0;
+	for (i = 0; i < 16; i++) {
+		m = 1;
+		m = m << i;
+		if ((m & dev->active_idu) != 0) {
 			continue;
 		}
-		chip_ver[2] = 0;
-
-		if (devid[h] == 0x8002) {
-			error = pci_read_config_byte(pdev[2], 0x08, &chip_ver[2]);
-			if (chip_ver[2] < 2) {
-				goto nxt_devfn;
-			}
-		}
-		if (devid[h] == 0x8010 || devid[h] == 0x8050) {
-			chip_ver[2] = 0x04;
-		}
-		pdev[tmpcnt] = pdev[2];
-		chip_ver[tmpcnt] = chip_ver[2];
-		tmpcnt++;
-	      nxt_devfn:
-		index++;
-		if (index > 3) {
-			index = 0;
-			h++;
+		if (i == dev->host_idu) {
+			printk(KERN_INFO "         ID: %2d  Host Adapter\n", dev->host_idu);
+			continue;
 		}
-		if(tmpcnt>1)
-			break;
-	}
-	for (h = 0; h < 2; h++) {
-		struct atp_unit *dev=&atp_unit[h];
-		if (pdev[h]==NULL) {
-			return count;
+		tmport = wkport + 0x5b;
+		outb(0x01, tmport);
+		tmport = wkport + 0x41;
+		outb(0x08, tmport++);
+		outb(0x7f, tmport++);
+		outb(satn[0], tmport++);
+		outb(satn[1], tmport++);
+		outb(satn[2], tmport++);
+		outb(satn[3], tmport++);
+		outb(satn[4], tmport++);
+		outb(satn[5], tmport++);
+		tmport += 0x06;
+		outb(0, tmport);
+		tmport += 0x02;
+		outb(dev->id[i].devspu, tmport++);
+		outb(0, tmport++);
+		outb(satn[6], tmport++);
+		outb(satn[7], tmport++);
+		j = i;
+		if ((j & 0x08) != 0) {
+			j = (j & 0x07) | 0x40;
 		}
+		outb(j, tmport);
+		tmport += 0x03;
+		outb(satn[8], tmport);
+		tmport += 0x07;
 
-		/* Found an atp870u/w. */
-		base_io = pci_resource_start(pdev[h], 0);
-		irq = pdev[h]->irq;
-		error = pci_read_config_byte(pdev[h],0x49,&host_id);
+		while ((inb(tmport) & 0x80) == 0x00);
+		tmport -= 0x08;
+		if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
+			continue;
+		}
+		while (inb(tmport) != 0x8e);
+		dev->active_idu |= m;
 
-		base_io &= 0xfffffff8;
+		tmport = wkport + 0x50;
+		outb(0x30, tmport);
+		tmport = wkport + 0x54;
+		outb(0x00, tmport);
 
-		if (check_region(base_io,0x40) != 0)
-		{  
-			return 0;
+phase_cmd:
+		tmport = wkport + 0x58;
+		outb(0x08, tmport);
+		tmport += 0x07;
+		while ((inb(tmport) & 0x80) == 0x00);
+		tmport -= 0x08;
+		j = inb(tmport);
+		if (j != 0x16) {
+			tmport = wkport + 0x50;
+			outb(0x41, tmport);
+			goto phase_cmd;
+		}
+sel_ok:
+		tmport = wkport + 0x43;
+		outb(inqd[0], tmport++);
+		outb(inqd[1], tmport++);
+		outb(inqd[2], tmport++);
+		outb(inqd[3], tmport++);
+		outb(inqd[4], tmport++);
+		outb(inqd[5], tmport);
+		tmport += 0x07;
+		outb(0, tmport);
+		tmport += 0x02;
+		outb(dev->id[i].devspu, tmport++);
+		outb(0, tmport++);
+		outb(inqd[6], tmport++);
+		outb(inqd[7], tmport++);
+		tmport += 0x03;
+		outb(inqd[8], tmport);
+		tmport += 0x07;
+		while ((inb(tmport) & 0x80) == 0x00);
+		tmport -= 0x08;
+		if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
+			continue;
 		}
-		printk(KERN_INFO "   ACARD AEC-671X PCI Ultra/W SCSI-3 Host Adapter: %d    IO:%x, IRQ:%d.\n"
-		       ,h, base_io, irq);
-		dev->ioport = base_io;
-		dev->pciport = base_io + 0x20;
-		irqnumu[h] = irq;
-		host_id &= 0x07;
-		dev->host_idu = host_id;
-		dev->chip_veru = chip_ver[h];
-
-		tmport = base_io + 0x22;
-		dev->scam_on = inb(tmport);
-		tmport += 0x0b;
-		dev->global_map = inb(tmport++);
-		dev->ultra_map = inw(tmport);
-		if (dev->ultra_map == 0) {
-			dev->scam_on = 0x00;
-			dev->global_map = 0x20;
-			dev->ultra_map = 0xffff;
+		while (inb(tmport) != 0x8e);
+		tmport = wkport + 0x5b;
+		outb(0x00, tmport);
+		tmport = wkport + 0x58;
+		outb(0x08, tmport);
+		tmport += 0x07;
+		j = 0;
+rd_inq_data:
+		k = inb(tmport);
+		if ((k & 0x01) != 0) {
+			tmport -= 0x06;
+			mbuf[j++] = inb(tmport);
+			tmport += 0x06;
+			goto rd_inq_data;
 		}
-		shpnt = scsi_register(tpnt, 4);
-		if(shpnt==NULL)
-			return count;
-
-		save_flags(flags);
-		cli();
-		if (request_irq(irq, atp870u_intr_handle, SA_SHIRQ, "atp870u", dev)) {
-			printk(KERN_ERR "Unable to allocate IRQ for Acard controller.\n");
-			goto unregister;
+		if ((k & 0x80) == 0) {
+			goto rd_inq_data;
 		}
-
-		if (chip_ver[h] > 0x07) 	  /* check if atp876 chip   */
-		{				  /* then enable terminator */
-			tmport = base_io + 0x3e;
-			outb(0x30, tmport);
+		tmport -= 0x08;
+		j = inb(tmport);
+		if (j == 0x16) {
+			goto inq_ok;
 		}
-
-		tmport = base_io + 0x3a;
-		k = (inb(tmport) & 0xf3) | 0x10;
-		outb(k, tmport);
-		outb((k & 0xdf), tmport);
-		mydlyu(0x8000);
-		outb(k, tmport);
-		mydlyu(0x8000);
-		tmport = base_io;
-		outb((host_id | 0x08), tmport);
-		tmport += 0x18;
-		outb(0, tmport);
+		tmport = wkport + 0x50;
+		outb(0x46, tmport);
+		tmport += 0x02;
+		outb(0, tmport++);
+		outb(0, tmport++);
+		outb(0, tmport++);
+		tmport += 0x03;
+		outb(0x08, tmport);
 		tmport += 0x07;
-		while ((inb(tmport) & 0x80) == 0);
+		while ((inb(tmport) & 0x80) == 0x00);
 		tmport -= 0x08;
-		inb(tmport);
-		tmport = base_io + 1;
-		outb(8, tmport++);
-		outb(0x7f, tmport);
-		tmport = base_io + 0x11;
-		outb(0x20, tmport);
-
-		tscam(h);
-		is870(h, base_io);
-		tmport = base_io + 0x3a;
-		outb((inb(tmport) & 0xef), tmport);
-		tmport++;
-		outb((inb(tmport) | 0x20),tmport);
-
-		atp_host[h] = shpnt;
-		if (dev->chip_veru == 4) {
-			shpnt->max_id = 16;
+		if (inb(tmport) != 0x16) {
+			goto sel_ok;
 		}
-		shpnt->this_id = host_id;
-		shpnt->unique_id = base_io;
-		shpnt->io_port = base_io;
-		shpnt->n_io_port = 0x40;	/* Number of bytes of I/O space used */
-		shpnt->irq = irq;
-		scsi_set_pci_device(shpnt, pdev[h]);
-		restore_flags(flags);
-		request_region(base_io, 0x40, "atp870u");       /* Register the IO ports that we use */
-		count++;
+inq_ok:
+		mbuf[36] = 0;
+		printk(KERN_INFO "         ID: %2d  %s\n", i, &mbuf[8]);
+		dev->id[i].devtypeu = mbuf[0];
+		rmb = mbuf[1];
+		n = mbuf[7];
+		if ((mbuf[7] & 0x60) == 0) {
+			goto not_wide;
+		}
+		if ((dev->global_map & 0x20) == 0) {
+			goto not_wide;
+		}
+		if (lvdmode == 0)
+		{
+		   goto chg_wide;
+		}
+		if ((mbuf[2] & 0x07) < 0x03)	      // force u2
+		{
+		   goto chg_wide;
+		}
+		tmport = wkport + 0x5b;
+		outb(0x01, tmport);
+		tmport = wkport + 0x43;
+		outb(satn[0], tmport++);
+		outb(satn[1], tmport++);
+		outb(satn[2], tmport++);
+		outb(satn[3], tmport++);
+		outb(satn[4], tmport++);
+		outb(satn[5], tmport++);
+		tmport += 0x06;
+		outb(0, tmport);
+		tmport += 0x02;
+		outb(dev->id[i].devspu, tmport++);
+		outb(0, tmport++);
+		outb(satn[6], tmport++);
+		outb(satn[7], tmport++);
+		tmport += 0x03;
+		outb(satn[8], tmport);
+		tmport += 0x07;
+
+		while ((inb(tmport) & 0x80) == 0x00);
+		tmport -= 0x08;
+		if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
+			continue;
+		}
+		while (inb(tmport) != 0x8e);
+try_u3:
+		j = 0;
+		tmport = wkport + 0x54;
+		outb(0x09, tmport);
+		tmport += 0x04;
+		outb(0x20, tmport);
+		tmport += 0x07;
+
+		while ((inb(tmport) & 0x80) == 0) {
+			if ((inb(tmport) & 0x01) != 0) {
+				tmport -= 0x06;
+				outb(u3[j++], tmport);
+				tmport += 0x06;
+			}
+		}
+		tmport -= 0x08;
+		while ((inb(tmport) & 0x80) == 0x00);
+		j = inb(tmport) & 0x0f;
+		if (j == 0x0f) {
+			goto u3p_in;
+		}
+		if (j == 0x0a) {
+			goto u3p_cmd;
+		}
+		if (j == 0x0e) {
+			goto try_u3;
+		}
+		continue;
+u3p_out:
+		tmport = wkport + 0x58;
+		outb(0x20, tmport);
+		tmport += 0x07;
+		while ((inb(tmport) & 0x80) == 0) {
+			if ((inb(tmport) & 0x01) != 0) {
+				tmport -= 0x06;
+				outb(0, tmport);
+				tmport += 0x06;
+			}
+		}
+		tmport -= 0x08;
+		j = inb(tmport) & 0x0f;
+		if (j == 0x0f) {
+			goto u3p_in;
+		}
+		if (j == 0x0a) {
+			goto u3p_cmd;
+		}
+		if (j == 0x0e) {
+			goto u3p_out;
+		}
+		continue;
+u3p_in:
+		tmport = wkport + 0x54;
+		outb(0x09, tmport);
+		tmport += 0x04;
+		outb(0x20, tmport);
+		tmport += 0x07;
+		k = 0;
+u3p_in1:
+		j = inb(tmport);
+		if ((j & 0x01) != 0) {
+			tmport -= 0x06;
+			mbuf[k++] = inb(tmport);
+			tmport += 0x06;
+			goto u3p_in1;
+		}
+		if ((j & 0x80) == 0x00) {
+			goto u3p_in1;
+		}
+		tmport -= 0x08;
+		j = inb(tmport) & 0x0f;
+		if (j == 0x0f) {
+			goto u3p_in;
+		}
+		if (j == 0x0a) {
+			goto u3p_cmd;
+		}
+		if (j == 0x0e) {
+			goto u3p_out;
+		}
+		continue;
+u3p_cmd:
+		tmport = wkport + 0x50;
+		outb(0x30, tmport);
+		tmport = wkport + 0x54;
+		outb(0x00, tmport);
+		tmport += 0x04;
+		outb(0x08, tmport);
+		tmport += 0x07;
+		while ((inb(tmport) & 0x80) == 0x00);
+		tmport -= 0x08;
+		j = inb(tmport);
+		if (j != 0x16) {
+			if (j == 0x4e) {
+				goto u3p_out;
+			}
+			continue;
+		}
+		if (mbuf[0] != 0x01) {
+			goto chg_wide;
+		}
+		if (mbuf[1] != 0x06) {
+			goto chg_wide;
+		}
+		if (mbuf[2] != 0x04) {
+			goto chg_wide;
+		}
+		if (mbuf[3] == 0x09) {
+		   m = 1;
+		   m = m << i;
+		   dev->wide_idu |= m;
+		   dev->id[i].devspu = 0xce;
+		   continue;
+		}
+chg_wide:
+		tmport = wkport + 0x5b;
+		outb(0x01, tmport);
+		tmport = wkport + 0x43;
+		outb(satn[0], tmport++);
+		outb(satn[1], tmport++);
+		outb(satn[2], tmport++);
+		outb(satn[3], tmport++);
+		outb(satn[4], tmport++);
+		outb(satn[5], tmport++);
+		tmport += 0x06;
+		outb(0, tmport);
+		tmport += 0x02;
+		outb(dev->id[i].devspu, tmport++);
+		outb(0, tmport++);
+		outb(satn[6], tmport++);
+		outb(satn[7], tmport++);
+		tmport += 0x03;
+		outb(satn[8], tmport);
+		tmport += 0x07;
+
+		while ((inb(tmport) & 0x80) == 0x00);
+		tmport -= 0x08;
+		if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
+			continue;
+		}
+		while (inb(tmport) != 0x8e);
+try_wide:
+		j = 0;
+		tmport = wkport + 0x54;
+		outb(0x05, tmport);
+		tmport += 0x04;
+		outb(0x20, tmport);
+		tmport += 0x07;
+
+		while ((inb(tmport) & 0x80) == 0) {
+			if ((inb(tmport) & 0x01) != 0) {
+				tmport -= 0x06;
+				outb(wide[j++], tmport);
+				tmport += 0x06;
+			}
+		}
+		tmport -= 0x08;
+		while ((inb(tmport) & 0x80) == 0x00);
+		j = inb(tmport) & 0x0f;
+		if (j == 0x0f) {
+			goto widep_in;
+		}
+		if (j == 0x0a) {
+			goto widep_cmd;
+		}
+		if (j == 0x0e) {
+			goto try_wide;
+		}
+		continue;
+widep_out:
+		tmport = wkport + 0x58;
+		outb(0x20, tmport);
+		tmport += 0x07;
+		while ((inb(tmport) & 0x80) == 0) {
+			if ((inb(tmport) & 0x01) != 0) {
+				tmport -= 0x06;
+				outb(0, tmport);
+				tmport += 0x06;
+			}
+		}
+		tmport -= 0x08;
+		j = inb(tmport) & 0x0f;
+		if (j == 0x0f) {
+			goto widep_in;
+		}
+		if (j == 0x0a) {
+			goto widep_cmd;
+		}
+		if (j == 0x0e) {
+			goto widep_out;
+		}
+		continue;
+widep_in:
+		tmport = wkport + 0x54;
+		outb(0xff, tmport);
+		tmport += 0x04;
+		outb(0x20, tmport);
+		tmport += 0x07;
+		k = 0;
+widep_in1:
+		j = inb(tmport);
+		if ((j & 0x01) != 0) {
+			tmport -= 0x06;
+			mbuf[k++] = inb(tmport);
+			tmport += 0x06;
+			goto widep_in1;
+		}
+		if ((j & 0x80) == 0x00) {
+			goto widep_in1;
+		}
+		tmport -= 0x08;
+		j = inb(tmport) & 0x0f;
+		if (j == 0x0f) {
+			goto widep_in;
+		}
+		if (j == 0x0a) {
+			goto widep_cmd;
+		}
+		if (j == 0x0e) {
+			goto widep_out;
+		}
+		continue;
+widep_cmd:
+		tmport = wkport + 0x50;
+		outb(0x30, tmport);
+		tmport = wkport + 0x54;
+		outb(0x00, tmport);
+		tmport += 0x04;
+		outb(0x08, tmport);
+		tmport += 0x07;
+		while ((inb(tmport) & 0x80) == 0x00);
+		tmport -= 0x08;
+		j = inb(tmport);
+		if (j != 0x16) {
+			if (j == 0x4e) {
+				goto widep_out;
+			}
+			continue;
+		}
+		if (mbuf[0] != 0x01) {
+			goto not_wide;
+		}
+		if (mbuf[1] != 0x02) {
+			goto not_wide;
+		}
+		if (mbuf[2] != 0x03) {
+			goto not_wide;
+		}
+		if (mbuf[3] != 0x01) {
+			goto not_wide;
+		}
+		m = 1;
+		m = m << i;
+		dev->wide_idu |= m;
+not_wide:
+		if ((dev->id[i].devtypeu == 0x00) || (dev->id[i].devtypeu == 0x07) ||
+		    ((dev->id[i].devtypeu == 0x05) && ((n & 0x10) != 0)))
+		{
+			goto set_sync;
+		}
+		continue;
+set_sync:
+		tmport = wkport + 0x5b;
+		j = 0;
+		if ((m & dev->wide_idu) != 0) {
+			j |= 0x01;
+		}
+		outb(j, tmport);
+		tmport = wkport + 0x43;
+		outb(satn[0], tmport++);
+		outb(satn[1], tmport++);
+		outb(satn[2], tmport++);
+		outb(satn[3], tmport++);
+		outb(satn[4], tmport++);
+		outb(satn[5], tmport++);
+		tmport += 0x06;
+		outb(0, tmport);
+		tmport += 0x02;
+		outb(dev->id[i].devspu, tmport++);
+		outb(0, tmport++);
+		outb(satn[6], tmport++);
+		outb(satn[7], tmport++);
+		tmport += 0x03;
+		outb(satn[8], tmport);
+		tmport += 0x07;
+
+		while ((inb(tmport) & 0x80) == 0x00);
+		tmport -= 0x08;
+		if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
+			continue;
+		}
+		while (inb(tmport) != 0x8e);
+try_sync:
+		j = 0;
+		tmport = wkport + 0x54;
+		outb(0x06, tmport);
+		tmport += 0x04;
+		outb(0x20, tmport);
+		tmport += 0x07;
+
+		while ((inb(tmport) & 0x80) == 0) {
+			if ((inb(tmport) & 0x01) != 0) {
+				tmport -= 0x06;
+				if ((m & dev->wide_idu) != 0) {
+					outb(synw[j++], tmport);
+				} else {
+					if ((m & dev->ultra_map) != 0) {
+						outb(synu[j++], tmport);
+					} else {
+						outb(synn[j++], tmport);
+					}
+				}
+				tmport += 0x06;
+			}
+		}
+		tmport -= 0x08;
+		while ((inb(tmport) & 0x80) == 0x00);
+		j = inb(tmport) & 0x0f;
+		if (j == 0x0f) {
+			goto phase_ins;
+		}
+		if (j == 0x0a) {
+			goto phase_cmds;
+		}
+		if (j == 0x0e) {
+			goto try_sync;
+		}
+		continue;
+phase_outs:
+		tmport = wkport + 0x58;
+		outb(0x20, tmport);
+		tmport += 0x07;
+		while ((inb(tmport) & 0x80) == 0x00) {
+			if ((inb(tmport) & 0x01) != 0x00) {
+				tmport -= 0x06;
+				outb(0x00, tmport);
+				tmport += 0x06;
+			}
+		}
+		tmport -= 0x08;
+		j = inb(tmport);
+		if (j == 0x85) {
+			goto tar_dcons;
+		}
+		j &= 0x0f;
+		if (j == 0x0f) {
+			goto phase_ins;
+		}
+		if (j == 0x0a) {
+			goto phase_cmds;
+		}
+		if (j == 0x0e) {
+			goto phase_outs;
+		}
+		continue;
+phase_ins:
+		tmport = wkport + 0x54;
+		outb(0x06, tmport);
+		tmport += 0x04;
+		outb(0x20, tmport);
+		tmport += 0x07;
+		k = 0;
+phase_ins1:
+		j = inb(tmport);
+		if ((j & 0x01) != 0x00) {
+			tmport -= 0x06;
+			mbuf[k++] = inb(tmport);
+			tmport += 0x06;
+			goto phase_ins1;
+		}
+		if ((j & 0x80) == 0x00) {
+			goto phase_ins1;
+		}
+		tmport -= 0x08;
+		while ((inb(tmport) & 0x80) == 0x00);
+		j = inb(tmport);
+		if (j == 0x85) {
+			goto tar_dcons;
+		}
+		j &= 0x0f;
+		if (j == 0x0f) {
+			goto phase_ins;
+		}
+		if (j == 0x0a) {
+			goto phase_cmds;
+		}
+		if (j == 0x0e) {
+			goto phase_outs;
+		}
+		continue;
+phase_cmds:
+		tmport = wkport + 0x50;
+		outb(0x30, tmport);
+tar_dcons:
+		tmport = wkport + 0x54;
+		outb(0x00, tmport);
+		tmport += 0x04;
+		outb(0x08, tmport);
+		tmport += 0x07;
+		while ((inb(tmport) & 0x80) == 0x00);
+		tmport -= 0x08;
+		j = inb(tmport);
+		if (j != 0x16) {
+			continue;
+		}
+		if (mbuf[0] != 0x01) {
+			continue;
+		}
+		if (mbuf[1] != 0x03) {
+			continue;
+		}
+		if (mbuf[4] == 0x00) {
+			continue;
+		}
+		if (mbuf[3] > 0x64) {
+			continue;
+		}
+		if (mbuf[4] > 0x0e) {
+			mbuf[4] = 0x0e;
+		}
+		dev->id[i].devspu = mbuf[4];
+		if (mbuf[3] < 0x0c){
+			j = 0xb0;
+			goto set_syn_ok;
+		}
+		if ((mbuf[3] < 0x0d) && (rmb == 0)) {
+			j = 0xa0;
+			goto set_syn_ok;
+		}
+		if (mbuf[3] < 0x1a) {
+			j = 0x20;
+			goto set_syn_ok;
+		}
+		if (mbuf[3] < 0x33) {
+			j = 0x40;
+			goto set_syn_ok;
+		}
+		if (mbuf[3] < 0x4c) {
+			j = 0x50;
+			goto set_syn_ok;
+		}
+		j = 0x60;
+	      set_syn_ok:
+		dev->id[i].devspu = (dev->id[i].devspu & 0x0f) | j;
+	}
+}
+
+/* return non-zero on detection */
+int atp870u_detect(Scsi_Host_Template * tpnt)
+{
+	unsigned char irq, h, k;
+	unsigned long flags;
+	unsigned int base_io, error, tmport;
+	unsigned short index = 0;
+	struct pci_dev *pdev[3];
+	unsigned char chip_ver[3], host_id;
+	unsigned short dev_id[3];
+	struct Scsi_Host *shpnt = NULL;
+	int tmpcnt = 0;
+	int count = 0;
+
+	static unsigned short devid[9] = {
+	  0x8081, 0x8002, 0x8010, 0x8020, 0x8030, 0x8040, 0x8050, 0x8060, 0
+	};
+
+	printk(KERN_INFO "aec671x_detect: \n");
+	if (!pci_present()) {
+		printk(KERN_INFO"   NO PCI SUPPORT.\n");
+		return count;
+	}
+	tpnt->proc_name = "atp870u";
+
+	for (h = 0; h < 2; h++) {
+		struct atp_unit *dev = &atp_unit[h];
+		for(k=0;k<16;k++)
+		{
+			dev->id[k].prd_tableu = kmalloc(1024, GFP_KERNEL);
+			dev->id[k].devspu=0x20;
+			dev->id[k].devtypeu = 0;
+			dev->id[k].curr_req = NULL;
+		}
+		dev->active_idu = 0;
+		dev->wide_idu = 0;
+		dev->host_idu = 0x07;
+		dev->quhdu = 0;
+		dev->quendu = 0;
+		pdev[h]=NULL;
+		pdev[2]=NULL;
+		dev->chip_veru = 0;
+		dev->last_cmd = 0xff;
+		dev->in_snd = 0;
+		dev->in_int = 0;
+		for (k = 0; k < qcnt; k++) {
+			dev->querequ[k] = 0;
+		}
+		for (k = 0; k < 16; k++) {
+			dev->id[k].curr_req = 0;
+		}
+	}
+	h = 0;
+	while (devid[h] != 0) {
+		pdev[2] = pci_find_device(0x1191, devid[h], pdev[2]);
+		if (pdev[2] == NULL || pci_enable_device(pdev[2])) {
+			h++;
+			index = 0;
+			continue;
+		}
+		chip_ver[2] = 0;
+		dev_id[2] = devid[h];
+
+		if (devid[h] == 0x8002) {
+			error = pci_read_config_byte(pdev[2], 0x08, &chip_ver[2]);
+			if (chip_ver[2] < 2) {
+				goto nxt_devfn;
+			}
+		}
+		if (devid[h] == 0x8010 || devid[h] == 0x8081 || devid[h] == 0x8050)
+		{
+			chip_ver[2] = 0x04;
+		}
+		pdev[tmpcnt] = pdev[2];
+		chip_ver[tmpcnt] = chip_ver[2];
+		dev_id[tmpcnt] = dev_id[2];
+		tmpcnt++;
+	      nxt_devfn:
+		index++;
+		if (index > 3) {
+			index = 0;
+			h++;
+		}
+		if(tmpcnt>1)
+			break;
+	}
+	for (h = 0; h < 2; h++) {
+		struct atp_unit *dev=&atp_unit[h];
+		if (pdev[h]==NULL) {
+			return count;
+		}
+
+		/* Found an atp870u/w. */
+		base_io = pci_resource_start(pdev[h], 0);
+		irq = pdev[h]->irq;
+
+		if (dev_id[h] != 0x8081)
+		{
+		   error = pci_read_config_byte(pdev[h],0x49,&host_id);
+
+		   base_io &= 0xfffffff8;
+
+		   if (check_region(base_io,0x40) != 0)
+		   {
+			   return 0;
+		   }
+		   printk(KERN_INFO "   ACARD AEC-671X PCI Ultra/W SCSI-3 Host Adapter: %d    IO:%x, IRQ:%d.\n"
+			  ,h, base_io, irq);
+		   dev->ioport = base_io;
+		   dev->pciport = base_io + 0x20;
+		   dev->deviceid = dev_id[h];
+		   irqnumu[h] = irq;
+		   host_id &= 0x07;
+		   dev->host_idu = host_id;
+		   dev->chip_veru = chip_ver[h];
+
+		   tmport = base_io + 0x22;
+		   dev->scam_on = inb(tmport);
+		   tmport += 0x0b;
+		   dev->global_map = inb(tmport++);
+		   dev->ultra_map = inw(tmport);
+		   if (dev->ultra_map == 0) {
+			   dev->scam_on = 0x00;
+			   dev->global_map = 0x20;
+			   dev->ultra_map = 0xffff;
+		   }
+		   shpnt = scsi_register(tpnt, 4);
+		   if(shpnt==NULL)
+			   return count;
+
+		   save_flags(flags);
+		   cli();
+		   if (request_irq(irq, atp870u_intr_handle, SA_SHIRQ, "atp870u", dev)) {
+			   printk(KERN_ERR "Unable to allocate IRQ for Acard controller.\n");
+			   goto unregister;
+		   }
+
+		   if (chip_ver[h] > 0x07)	     /* check if atp876 chip   */
+		   {				     /* then enable terminator */
+		      tmport = base_io + 0x3e;
+		      outb(0x00, tmport);
+		   }
+
+		   tmport = base_io + 0x3a;
+		   k = (inb(tmport) & 0xf3) | 0x10;
+		   outb(k, tmport);
+		   outb((k & 0xdf), tmport);
+		   mydlyu(0x8000);
+		   outb(k, tmport);
+		   mydlyu(0x8000);
+		   tmport = base_io;
+		   outb((host_id | 0x08), tmport);
+		   tmport += 0x18;
+		   outb(0, tmport);
+		   tmport += 0x07;
+		   while ((inb(tmport) & 0x80) == 0);
+		   tmport -= 0x08;
+		   inb(tmport);
+		   tmport = base_io + 1;
+		   outb(8, tmport++);
+		   outb(0x7f, tmport);
+		   tmport = base_io + 0x11;
+		   outb(0x20, tmport);
+
+		   tscam(h);
+		   is870(h, base_io);
+		   tmport = base_io + 0x3a;
+		   outb((inb(tmport) & 0xef), tmport);
+		   tmport++;
+		   outb((inb(tmport) | 0x20),tmport);
+		}
+		else
+		{
+		   base_io &= 0xfffffff8;
+
+		   if (check_region(base_io,0x60) != 0)
+		   {
+			   return 0;
+		   }
+		   host_id = inb(base_io + 0x39);
+		   host_id >>= 0x04;
+
+		   printk(KERN_INFO "   ACARD AEC-67160 PCI Ultra3 LVD Host Adapter: %d    IO:%x, IRQ:%d.\n"
+			  ,h, base_io, irq);
+		   dev->ioport = base_io + 0x40;
+		   dev->pciport = base_io + 0x28;
+		   dev->deviceid = dev_id[h];
+		   irqnumu[h] = irq;
+		   dev->host_idu = host_id;
+		   dev->chip_veru = chip_ver[h];
+
+		   tmport = base_io + 0x22;
+		   dev->scam_on = inb(tmport);
+		   tmport += 0x13;
+		   dev->global_map = inb(tmport);
+		   tmport += 0x07;
+		   dev->ultra_map = inw(tmport);
+		   if (dev->ultra_map == 0) {
+			   dev->scam_on = 0x00;
+			   dev->global_map = 0x20;
+			   dev->ultra_map = 0xffff;
+		   }
+		   shpnt = scsi_register(tpnt, 4);
+		   if(shpnt==NULL)
+			   return count;
+
+		   save_flags(flags);
+		   cli();
+		   if (request_irq(irq, atp870u_intr_handle, SA_SHIRQ, "atp870u", dev)) {
+			   printk(KERN_ERR "Unable to allocate IRQ for Acard controller.\n");
+			   goto unregister;
+		   }
+
+		   tmport = base_io + 0x38;
+		   k = inb(tmport) & 0x80;
+		   outb(k, tmport);
+		   tmport += 0x03;
+		   outb(0x20, tmport);
+		   mydlyu(0x8000);
+		   outb(0, tmport);
+		   mydlyu(0x8000);
+		   tmport = base_io + 0x5b;
+		   inb(tmport);
+		   tmport -= 0x04;
+		   inb(tmport);
+		   tmport = base_io + 0x40;
+		   outb((host_id | 0x08), tmport);
+		   tmport += 0x18;
+		   outb(0, tmport);
+		   tmport += 0x07;
+		   while ((inb(tmport) & 0x80) == 0);
+		   tmport -= 0x08;
+		   inb(tmport);
+		   tmport = base_io + 0x41;
+		   outb(8, tmport++);
+		   outb(0x7f, tmport);
+		   tmport = base_io + 0x51;
+		   outb(0x20, tmport);
+
+		   is880(h, base_io);
+		   tmport = base_io + 0x38;
+		   outb(0xb0, tmport);
+		}
+
+		atp_host[h] = shpnt;
+		if (dev->chip_veru == 4) {
+			shpnt->max_id = 16;
+		}
+		shpnt->this_id = host_id;
+		shpnt->unique_id = base_io;
+		shpnt->io_port = base_io;
+		if (dev_id[h] == 0x8081)
+		{
+		   shpnt->n_io_port = 0x60;	   /* Number of bytes of I/O space used */
+		}
+		else
+		{
+		   shpnt->n_io_port = 0x40;	   /* Number of bytes of I/O space used */
+		}
+		shpnt->irq = irq;
+		restore_flags(flags);
+		if (dev_id[h] == 0x8081)
+		{
+		   request_region(base_io, 0x60, "atp870u");       /* Register the IO ports that we use */
+		}
+		else
+		{
+		   request_region(base_io, 0x40, "atp870u");       /* Register the IO ports that we use */
+		}
+		count++;
 		index++;
 		continue;
 unregister:
@@ -1809,7 +2606,8 @@
 
 int atp870u_abort(Scsi_Cmnd * SCpnt)
 {
-	unsigned char h, j;
+	unsigned char h, j, k;
+	Scsi_Cmnd *workrequ;
 	unsigned int tmport;
 	struct atp_unit *dev;
 	for (h = 0; h <= admaxu; h++) {
@@ -1830,18 +2628,34 @@
 	printk(" r1c=%2x", inb(tmport));
 	tmport += 0x03;
 	printk(" r1f=%2x in_snd=%2x ", inb(tmport), dev->in_snd);
-	tmport++;
+	tmport= dev->pciport;
 	printk(" r20=%2x", inb(tmport));
 	tmport += 0x02;
 	printk(" r22=%2x", inb(tmport));
-	tmport += 0x18;
+	tmport = dev->ioport + 0x3a;
 	printk(" r3a=%2x \n",inb(tmport));
+	tmport = dev->ioport + 0x3b;
+	printk(" r3b=%2x \n",inb(tmport));
+	for(j=0;j<16;j++)
+	{
+	   if (dev->id[j].curr_req != NULL)
+	   {
+		workrequ = dev->id[j].curr_req;
+		printk("\n que cdb= ");
+		for (k=0; k < workrequ->cmd_len; k++)
+		{
+		    printk(" %2x ",workrequ->cmnd[k]);
+		}
+		printk(" last_lenu= %x ",dev->id[j].last_lenu);
+	   }
+	}
 	return (SCSI_ABORT_SNOOZE);
 }
 
 int atp870u_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags)
 {
 	unsigned char h;
+	struct atp_unit *dev;
 	/*
 	 * See if a bus reset was suggested.
 	 */
@@ -1852,6 +2666,7 @@
 	}
 	panic("Reset bus host not found !");
 find_host:
+	dev=&atp_unit[h];
 /*	SCpnt->result = 0x00080000;
 	SCpnt->scsi_done(SCpnt);
 	dev->working=0;
@@ -1865,7 +2680,7 @@
 {
 	static char buffer[128];
 
-	strcpy(buffer, "ACARD AEC-6710/6712 PCI Ultra/W SCSI-3 Adapter Driver V2.1+ac ");
+	strcpy(buffer, "ACARD AEC-6710/6712/67160 PCI Ultra/W/LVD SCSI-3 Adapter Driver V2.4+ac ");
 
 	return buffer;
 }
@@ -1910,7 +2725,7 @@
 	if (offset == 0) {
 		memset(buff, 0, sizeof(buff));
 	}
-	size += sprintf(BLS, "ACARD AEC-671X Driver Version: 2.1+ac\n");
+	size += sprintf(BLS, "ACARD AEC-671X Driver Version: 2.4+ac\n");
 	len += size;
 	pos = begin + len;
 	size = 0;
@@ -1976,3 +2791,4 @@
 
 static Scsi_Host_Template driver_template = ATP870U;
 #include "scsi_module.c"
+
diff -urN linux-2.4.7-pre6/drivers/scsi/fdomain.c linux/drivers/scsi/fdomain.c
--- linux-2.4.7-pre6/drivers/scsi/fdomain.c	Fri May  4 15:11:42 2001
+++ linux/drivers/scsi/fdomain.c	Mon Dec  3 22:55:50 2001
@@ -3,6 +3,7 @@
  * Revised: Mon Dec 28 21:59:02 1998 by faith@acm.org
  * Author: Rickard E. Faith, faith@cs.unc.edu
  * Copyright 1992-1996, 1998 Rickard E. Faith (faith@acm.org)
+ * Shared IRQ supported added 7/7/2001  Alan Cox <alan@redhat.com>
 
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
@@ -982,7 +983,7 @@
       /* Register the IRQ with the kernel */
 
       retcode = request_irq( interrupt_level,
-			     do_fdomain_16x0_intr, 0, "fdomain", NULL);
+			     do_fdomain_16x0_intr, pdev?SA_SHIRQ:0, "fdomain", NULL);
 
       if (retcode < 0) {
 	 if (retcode == -EINVAL) {
@@ -1229,8 +1230,11 @@
 				   interruptions while this routine is
 				   running. */
 
-   /* sti();			 Yes, we really want sti() here if we want to lock up our machine */
-   
+   /* Check for other IRQ sources */
+   if((inb(TMC_Status_port)&0x01)==0)   
+   	return;
+
+   /* It is our IRQ */   	
    outb( 0x00, Interrupt_Cntl_port );
 
    /* We usually have one spurious interrupt after each command.  Ignore it. */
diff -urN linux-2.4.7-pre6/drivers/sound/ac97.c linux/drivers/sound/ac97.c
--- linux-2.4.7-pre6/drivers/sound/ac97.c	Thu Jan  6 15:01:56 2000
+++ linux/drivers/sound/ac97.c	Mon Dec  3 22:55:50 2001
@@ -407,19 +407,19 @@
 	/* Read or write request. */
 	ret = -EINVAL;
 	if (_IOC_TYPE (cmd) == 'M') {
-	    int dir = _IOC_DIR (cmd);
+	    int dir = _SIOC_DIR (cmd);
 	    int channel = _IOC_NR (cmd);
 
 	    if (channel >= 0 && channel < SOUND_MIXER_NRDEVICES) {
 		ret = 0;
-		if (dir & _IOC_WRITE) {
+		if (dir & _SIOC_WRITE) {
 		    int val;
 		    if (get_user (val, (int *) arg) == 0)
 			ret = ac97_set_mixer (dev, channel, val);
 		    else
 			ret = -EFAULT;
 		}
-		if (ret >= 0 && (dir & _IOC_READ)) {
+		if (ret >= 0 && (dir & _SIOC_READ)) {
 		    if (dev->last_written_OSS_values[channel]
 			== AC97_REGVAL_UNKNOWN)
 			dev->last_written_OSS_values[channel]
diff -urN linux-2.4.7-pre6/drivers/sound/esssolo1.c linux/drivers/sound/esssolo1.c
--- linux-2.4.7-pre6/drivers/sound/esssolo1.c	Tue May 22 10:23:16 2001
+++ linux/drivers/sound/esssolo1.c	Mon Dec  3 22:55:50 2001
@@ -1,4 +1,4 @@
-/*****************************************************************************/
+/****************************************************************************/
 
 /*
  *      esssolo1.c  --  ESS Technology Solo1 (ES1946) audio driver.
@@ -79,6 +79,9 @@
  *                       for abs. Bug report by Andrew Morton <andrewm@uow.edu.au>
  *    15.05.2001         pci_enable_device moved, return values in probe cleaned
  *                       up. Marcus Meissner <mm@caldera.de>
+ *    22.05.2001   0.19  more cleanups, changed PM to PCI 2.4 style, got rid
+ *                       of global list of devices, using pci device data.
+ *                       Marcus Meissner <mm@caldera.de>
  */
 
 /*****************************************************************************/
@@ -94,7 +97,6 @@
 #include <linux/soundcard.h>
 #include <linux/pci.h>
 #include <linux/bitops.h>
-#include <linux/pm.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <linux/init.h>
@@ -104,25 +106,9 @@
 #include <linux/wrapper.h>
 #include <asm/uaccess.h>
 #include <asm/hardirq.h>
-
-#include "dm.h"
-
-#if defined(CONFIG_INPUT_ANALOG) || defined(CONFIG_INPUT_ANALOG_MODULE)
 #include <linux/gameport.h>
-#else
-struct gameport {
-	int io;
-	int size;
-};
 
-extern inline void gameport_register_port(struct gameport *gameport)
-{
-}
-
-extern inline void gameport_unregister_port(struct gameport *gameport)
-{
-}
-#endif
+#include "dm.h"
 
 /* --------------------------------------------------------------------- */
 
@@ -147,6 +133,7 @@
 #define VCBASE_EXTENT             (DDMABASE_EXTENT+DDMABASE_OFFSET)
 #define MPUBASE_EXTENT            4
 #define GPBASE_EXTENT             4
+#define GAMEPORT_EXTENT		  4
 
 #define FMSYNTH_EXTENT            4
 
@@ -161,15 +148,14 @@
 
 #define FMODE_DMFM 0x10
 
+static struct pci_driver solo1_driver;
+
 /* --------------------------------------------------------------------- */
 
 struct solo1_state {
 	/* magic */
 	unsigned int magic;
 
-	/* list of esssolo1 devices */
-	struct list_head devs;
-	
 	/* the corresponding pci_dev structure */
 	struct pci_dev *dev;
 
@@ -244,10 +230,6 @@
 
 /* --------------------------------------------------------------------- */
 
-static LIST_HEAD(devs);
-
-/* --------------------------------------------------------------------- */
-
 extern inline void write_seq(struct solo1_state *s, unsigned char data)
 {
         int i;
@@ -939,16 +921,22 @@
 static int solo1_open_mixdev(struct inode *inode, struct file *file)
 {
 	int minor = MINOR(inode->i_rdev);
-	struct list_head *list;
-	struct solo1_state *s;
+	struct solo1_state *s = NULL;
+	struct pci_dev *pci_dev;
 
-	for (list = devs.next; ; list = list->next) {
-		if (list == &devs)
-			return -ENODEV;
-		s = list_entry(list, struct solo1_state, devs);
+	pci_for_each_dev(pci_dev) {
+		struct pci_driver *drvr;
+		drvr = pci_dev_driver (pci_dev);
+		if (drvr != &solo1_driver)
+			continue;
+		s = (struct solo1_state*)pci_get_drvdata(pci_dev);
+		if (!s)
+			continue;
 		if (s->dev_mixer == minor)
 			break;
 	}
+	if (!s)
+		return -ENODEV;
        	VALIDATE_STATE(s);
 	file->private_data = s;
 	return 0;
@@ -1611,16 +1599,23 @@
 {
 	int minor = MINOR(inode->i_rdev);
 	DECLARE_WAITQUEUE(wait, current);
-	struct list_head *list;
-	struct solo1_state *s;
+	struct solo1_state *s = NULL;
+	struct pci_dev *pci_dev;
 	
-	for (list = devs.next; ; list = list->next) {
-		if (list == &devs)
-			return -ENODEV;
-		s = list_entry(list, struct solo1_state, devs);
+	pci_for_each_dev(pci_dev) {
+		struct pci_driver *drvr;
+
+		drvr = pci_dev_driver(pci_dev);
+		if (drvr != &solo1_driver)
+			continue;
+		s = (struct solo1_state*)pci_get_drvdata(pci_dev);
+		if (!s)
+			continue;
 		if (!((s->dev_audio ^ minor) & ~0xf))
 			break;
 	}
+	if (!s)
+		return -ENODEV;
        	VALIDATE_STATE(s);
 	file->private_data = s;
 	/* wait for device to become free */
@@ -1894,16 +1889,23 @@
 	int minor = MINOR(inode->i_rdev);
 	DECLARE_WAITQUEUE(wait, current);
 	unsigned long flags;
-	struct list_head *list;
-	struct solo1_state *s;
+	struct solo1_state *s = NULL;
+	struct pci_dev *pci_dev;
+
+	pci_for_each_dev(pci_dev) {
+		struct pci_driver *drvr;
 
-	for (list = devs.next; ; list = list->next) {
-		if (list == &devs)
-			return -ENODEV;
-		s = list_entry(list, struct solo1_state, devs);
+		drvr = pci_dev_driver(pci_dev);
+		if (drvr != &solo1_driver)
+			continue;
+		s = (struct solo1_state*)pci_get_drvdata(pci_dev);
+		if (!s)
+			continue;
 		if (s->dev_midi == minor)
 			break;
 	}
+	if (!s)
+		return -ENODEV;
        	VALIDATE_STATE(s);
 	file->private_data = s;
 	/* wait for device to become free */
@@ -2112,16 +2114,23 @@
 {
 	int minor = MINOR(inode->i_rdev);
 	DECLARE_WAITQUEUE(wait, current);
-	struct list_head *list;
-	struct solo1_state *s;
+	struct solo1_state *s = NULL;
+	struct pci_dev *pci_dev;
 
-	for (list = devs.next; ; list = list->next) {
-		if (list == &devs)
-			return -ENODEV;
-		s = list_entry(list, struct solo1_state, devs);
+	pci_for_each_dev(pci_dev) {
+		struct pci_driver *drvr;
+
+		drvr = pci_dev_driver(pci_dev);
+		if (drvr != &solo1_driver)
+			continue;
+		s = (struct solo1_state*)pci_get_drvdata(pci_dev);
+		if (!s)
+			continue;
 		if (s->dev_dmfm == minor)
 			break;
 	}
+	if (!s)
+		return -ENODEV;
        	VALIDATE_STATE(s);
 	file->private_data = s;
 	/* wait for device to become free */
@@ -2256,33 +2265,31 @@
 	return 0;
 }
 
-static int solo1_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data)
-{
-	struct solo1_state *s = (struct solo1_state*) dev->data;
-	if (s) {
-		switch(rqst) {
-		case PM_RESUME:
-			setup_solo1(s);
-			break;
+static void
+solo1_suspend(struct pci_dev *pci_dev) {
+	struct solo1_state *s = (struct solo1_state*)pci_get_drvdata(pci_dev);
+	if (!s)
+		return;
+	outb(0, s->iobase+6);
+	/* DMA master clear */
+	outb(0, s->ddmabase+0xd); 
+	/* reset sequencer and FIFO */
+	outb(3, s->sbbase+6); 
+	/* turn off DDMA controller address space */
+	pci_write_config_word(s->dev, 0x60, 0); 
+}
 
-		case PM_SUSPEND:
-			outb(0, s->iobase+6);
-			/* DMA master clear */
-			outb(0, s->ddmabase+0xd); 
-			/* reset sequencer and FIFO */
-			outb(3, s->sbbase+6); 
-			/* turn off DDMA controller address space */
-			pci_write_config_word(s->dev, 0x60, 0); 
-			break;
-		}
-	}
-	return 0;
+static void
+solo1_resume(struct pci_dev *pci_dev) {
+	struct solo1_state *s = (struct solo1_state*)pci_get_drvdata(pci_dev);
+	if (!s)
+		return;
+	setup_solo1(s);
 }
 
 static int __devinit solo1_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid)
 {
 	struct solo1_state *s;
-	struct pm_dev *pmdev;
 	int ret;
 
  	if ((ret=pci_enable_device(pcidev)))
@@ -2324,7 +2331,6 @@
 	s->ddmabase = s->vcbase + DDMABASE_OFFSET;
 	s->mpubase = pci_resource_start(pcidev, 3);
 	s->gameport.io = pci_resource_start(pcidev, 4);
-	s->gameport.size = pci_resource_len(pcidev,4);
 	s->irq = pcidev->irq;
 	ret = -EBUSY;
 	if (!request_region(s->iobase, IOBASE_EXTENT, "ESS Solo1")) {
@@ -2343,11 +2349,9 @@
 		printk(KERN_ERR "solo1: io ports in use\n");
 		goto err_region4;
 	}
-	if (!s->gameport.size)
-		s->gameport.io = 0;
-	if (s->gameport.io && !request_region(s->gameport.io, s->gameport.size, "ESS Solo1")) {
+	if (s->gameport.io && !request_region(s->gameport.io, GAMEPORT_EXTENT, "ESS Solo1")) {
 		printk(KERN_ERR "solo1: gameport io ports in use\n");
-		s->gameport.io = s->gameport.size = 0;
+		s->gameport.io = 0;
 	}
 	if ((ret=request_irq(s->irq,solo1_interrupt,SA_SHIRQ,"ESS Solo1",s))) {
 		printk(KERN_ERR "solo1: irq %u in use\n", s->irq);
@@ -2379,13 +2383,6 @@
 	gameport_register_port(&s->gameport);
 	/* store it in the driver field */
 	pci_set_drvdata(pcidev, s);
-	/* put it into driver list */
-	list_add_tail(&s->devs, &devs);
-
-	pmdev = pm_register(PM_PCI_DEV, PM_PCI_ID(pcidev), solo1_pm_callback);
-	if (pmdev)
-		pmdev->data = s;
-
 	return 0;
 
  err:
@@ -2401,7 +2398,7 @@
 	free_irq(s->irq, s);
  err_irq:
 	if (s->gameport.io)
-		release_region(s->gameport.io, s->gameport.size);
+		release_region(s->gameport.io, GAMEPORT_EXTENT);
 	release_region(s->iobase, IOBASE_EXTENT);
  err_region4:
 	release_region(s->sbbase+FMSYNTH_EXTENT, SBBASE_EXTENT-FMSYNTH_EXTENT);
@@ -2420,7 +2417,6 @@
 	
 	if (!s)
 		return;
-	list_del(&s->devs);
 	/* stop DMA controller */
 	outb(0, s->iobase+6);
 	outb(0, s->ddmabase+0xd); /* DMA master clear */
@@ -2430,7 +2426,7 @@
 	free_irq(s->irq, s);
 	if (s->gameport.io) {
 		gameport_unregister_port(&s->gameport);
-		release_region(s->gameport.io, s->gameport.size);
+		release_region(s->gameport.io, GAMEPORT_EXTENT);
 	}
 	release_region(s->iobase, IOBASE_EXTENT);
 	release_region(s->sbbase+FMSYNTH_EXTENT, SBBASE_EXTENT-FMSYNTH_EXTENT);
@@ -2455,7 +2451,9 @@
 	name: "ESS Solo1",
 	id_table: id_table,
 	probe: solo1_probe,
-	remove: solo1_remove
+	remove: solo1_remove,
+	suspend: solo1_suspend,
+	resume: solo1_resume
 };
 
 
@@ -2463,7 +2461,7 @@
 {
 	if (!pci_present())   /* No PCI bus in this machine! */
 		return -ENODEV;
-	printk(KERN_INFO "solo1: version v0.18 time " __TIME__ " " __DATE__ "\n");
+	printk(KERN_INFO "solo1: version v0.19 time " __TIME__ " " __DATE__ "\n");
 	if (!pci_register_driver(&solo1_driver)) {
 		pci_unregister_driver(&solo1_driver);
                 return -ENODEV;
@@ -2480,7 +2478,6 @@
 {
 	printk(KERN_INFO "solo1: unloading\n");
 	pci_unregister_driver(&solo1_driver);
-	pm_unregister_all(solo1_pm_callback);
 }
 
 /* --------------------------------------------------------------------- */
diff -urN linux-2.4.7-pre6/drivers/sound/msnd_pinnacle.c linux/drivers/sound/msnd_pinnacle.c
--- linux-2.4.7-pre6/drivers/sound/msnd_pinnacle.c	Tue Mar  6 19:44:37 2001
+++ linux/drivers/sound/msnd_pinnacle.c	Mon Dec  3 22:55:50 2001
@@ -1570,7 +1570,6 @@
 MODULE_PARM				(irq, "i");
 MODULE_PARM				(mem, "i");
 MODULE_PARM				(write_ndelay, "i");
-MODULE_PARM				(major, "i");
 MODULE_PARM				(fifosize, "i");
 MODULE_PARM				(calibrate_signal, "i");
 #ifndef MSND_CLASSIC
diff -urN linux-2.4.7-pre6/drivers/sound/trident.c linux/drivers/sound/trident.c
--- linux-2.4.7-pre6/drivers/sound/trident.c	Sat May 19 17:43:10 2001
+++ linux/drivers/sound/trident.c	Mon Dec  3 22:55:50 2001
@@ -31,6 +31,17 @@
  *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  *  History
+ *  v0.14.8a
+ *	July 7 2001 Alan Cox
+ *	Moved Matt Wu's ac97 register cache into the card structure
+ *  v0.14.8
+ *	Apr 30 2001 Matt Wu
+ *	Set EBUF1 and EBUF2 to still mode
+ *	Add dc97/ac97 reset function
+ *	Fix power management: ali_restore_regs
+ *  unreleased 
+ *	Mar 09 2001 Matt Wu
+ *	Add cache for ac97 access
  *  v0.14.7
  *	Feb 06 2001 Matt Wu
  *	Fix ac97 initialization
@@ -104,6 +115,11 @@
  *	Mmap support
  *	"Channel Binding" ioctl extension (done)
  *	new pci device driver interface for 2.4 kernel (done)
+ *
+ *	Lock order (high->low)
+ *		lock	-	hardware lock
+ *		open_sem - 	guard opens
+ *		sem	-	guard dmabuf, write re-entry etc
  */
 
 #include <linux/config.h>
@@ -131,11 +147,15 @@
 #include <linux/bitops.h>
 #include <linux/proc_fs.h>
 
+#if defined CONFIG_ALPHA_NAUTILUS || CONFIG_ALPHA_GENERIC
+#include <asm/hwrpb.h>
+#endif
+
 #include "trident.h"
 
 #include <linux/pm.h>
 
-#define DRIVER_VERSION "0.14.6"
+#define DRIVER_VERSION "0.14.8"
 
 /* magic numbers to protect our data structures */
 #define TRIDENT_CARD_MAGIC	0x5072696E /* "Prin" */
@@ -243,6 +263,9 @@
 	int multi_channels_adjust_count;
 	unsigned chans_num;
 	unsigned fmt_flag:1;
+	/* Guard against mmap/write/read races */
+	struct semaphore sem;
+
 };
 
 /* hardware channels */
@@ -296,7 +319,7 @@
 	/* The trident has a certain amount of cross channel interaction
 	   so we use a single per card lock */
 	spinlock_t lock;
-
+	
 	/* PCI device stuff */
 	struct pci_dev * pci_dev;
 	u16 pci_id;
@@ -320,9 +343,11 @@
 	void (*free_pcm_channel)(struct trident_card *, unsigned int chan);
 	void (*address_interrupt)(struct trident_card *);
 	
-	/* Add by Matt Wu 01-05-2001 for spdif in */
+	/* Added by Matt Wu 01-05-2001 for spdif in */
 	int multi_channel_use_count;
 	int rec_channel_use_count;
+	u16 mixer_regs[64][NR_AC97];	/* Made card local by Alan */
+	int mixer_regs_ready;
 };
 
 /* table to map from CHANNELMASK to channel attribute for SiS 7018 */
@@ -338,11 +363,14 @@
 	DSP_BIND_I2S, DSP_BIND_CENTER_LFE, DSP_BIND_SURR, DSP_BIND_SPDIF
 };
 
-/* Add by Matt Wu 01-05-2001 for spdif in */
+/* Added by Matt Wu 01-05-2001 for spdif in */
 static int ali_close_multi_channels(void);
 static void ali_delay(struct trident_card *card,int interval);
 static void ali_detect_spdif_rate(struct trident_card *card);
 
+static void ali_ac97_write(struct ac97_codec *codec, u8 reg, u16 val);
+static u16 ali_ac97_read(struct ac97_codec *codec, u8 reg);
+
 static struct trident_card *devs;
 
 static void trident_ac97_set(struct ac97_codec *codec, u8 reg, u16 val);
@@ -353,15 +381,16 @@
 				unsigned long arg);
 static loff_t trident_llseek(struct file *file, loff_t offset, int origin);
 
-static void ali_ac97_set(struct ac97_codec *codec, u8 reg, u16 val);
-static u16 ali_ac97_get(struct ac97_codec *codec, u8 reg);
+static void ali_ac97_set(struct trident_card *card, int secondary, u8 reg, u16 val);
+static u16 ali_ac97_get(struct trident_card *card, int secondary, u8 reg);
 static void ali_set_spdif_out_rate(struct trident_card *card, unsigned int rate);
 static void ali_enable_special_channel(struct trident_state *stat);
 static struct trident_channel *ali_alloc_rec_pcm_channel(struct trident_card *card);
 static struct trident_channel *ali_alloc_pcm_channel(struct trident_card *card);
-static int ali_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data);
 static void ali_restore_regs(struct trident_card *card);
 static void ali_save_regs(struct trident_card *card);
+static int trident_suspend(struct pci_dev *dev, u32 unused);
+static int trident_resume(struct pci_dev *dev);
 static void ali_free_pcm_channel(struct trident_card *card, unsigned int channel);
 static int ali_setup_multi_channels(struct trident_card *card, int chan_nums);
 static unsigned int ali_get_spdif_in_rate(struct trident_card *card);
@@ -607,6 +636,10 @@
 			continue;
 		outl(data[i], TRID_REG(card, CHANNEL_START + 4*i));
 	}
+	if (card->pci_id == PCI_DEVICE_ID_ALI_5451) {
+		outl(ALI_EMOD_Still, TRID_REG(card, ALI_EBUF1));
+		outl(ALI_EMOD_Still, TRID_REG(card, ALI_EBUF2));
+	}
 	return TRUE;
 }
 
@@ -989,7 +1022,7 @@
 static int alloc_dmabuf(struct trident_state *state)
 {
 	struct dmabuf *dmabuf = &state->dmabuf;
-	void *rawbuf=NULL;
+	void *rawbuf = NULL;
 	int order;
 	struct page *page, *pend;
 
@@ -1221,7 +1254,7 @@
 			return -EBUSY;
 		}
 
-		/* No matter how much data left in the buffer, we have to wait untill
+		/* No matter how much data is left in the buffer, we have to wait until
 		   CSO == ESO/2 or CSO == ESO when address engine interrupts */
 	 	if (state->card->pci_id == PCI_DEVICE_ID_ALI_5451)
 		{	
@@ -1234,7 +1267,6 @@
 			tmo = (dmabuf->dmasize * HZ) / dmabuf->rate;
 		}
 		tmo >>= sample_shift[dmabuf->fmt];
-//		printk("trident: diff=%d count= %d/%d total=%d tmo=%d hwptr=%d swptr=%d curptr=%d\n",diff,dmabuf->count,dmabuf->dmasize,dmabuf->total_bytes,tmo,dmabuf->hwptr,dmabuf->swptr,trident_get_dma_addr(state));
 		if (!schedule_timeout(tmo ? tmo : 1) && tmo){
 			break;
 		}
@@ -1416,7 +1448,7 @@
 {
 	struct trident_state *state = (struct trident_state *)file->private_data;
 	struct dmabuf *dmabuf = &state->dmabuf;
-	ssize_t ret;
+	ssize_t ret = 0;
 	unsigned long flags;
 	unsigned swptr;
 	int cnt;
@@ -1428,13 +1460,15 @@
 	VALIDATE_STATE(state);
 	if (ppos != &file->f_pos)
 		return -ESPIPE;
+		
 	if (dmabuf->mapped)
 		return -ENXIO;
-	if (!dmabuf->ready && (ret = prog_dmabuf(state, 1)))
-		return ret;
 	if (!access_ok(VERIFY_WRITE, buffer, count))
 		return -EFAULT;
-	ret = 0;
+		
+	down(&state->sem);
+	if (!dmabuf->ready && (ret = prog_dmabuf(state, 1)))
+		goto out;
 
 	while (count > 0) {
 		spin_lock_irqsave(&state->card->lock, flags);
@@ -1459,8 +1493,10 @@
 			start_adc(state);
 			if (file->f_flags & O_NONBLOCK) {
 				if (!ret) ret = -EAGAIN;
-				return ret;
+				goto out;
 			}
+			
+			up(&state->sem);
 			/* No matter how much space left in the buffer, we have to wait until
 			   CSO == ESO/2 or CSO == ESO when address engine interrupts */
 			tmo = (dmabuf->dmasize * HZ) / (dmabuf->rate * 2);
@@ -1483,15 +1519,22 @@
 				   while loop begin and we REALLY have space to record */
 			}
 			if (signal_pending(current)) {
-				ret = ret ? ret : -ERESTARTSYS;
-				return ret;
+				if(!ret) ret = -ERESTARTSYS;
+				goto out;
+			}
+			down(&state->sem);
+			if(dmabuf->mapped)
+			{
+				if(!ret)
+					ret = -ENXIO;
+				goto out;
 			}
 			continue;
 		}
 
 		if (copy_to_user(buffer, dmabuf->rawbuf + swptr, cnt)) {
 			if (!ret) ret = -EFAULT;
-			return ret;
+			goto out;
 		}
 
 		swptr = (swptr + cnt) % dmabuf->dmasize;
@@ -1506,11 +1549,14 @@
 		ret += cnt;
 		start_adc(state);
 	}
+out:
+	up(&state->sem);
 	return ret;
 }
 
 /* in this loop, dmabuf.count signifies the amount of data that is waiting to be dma to
    the soundcard.  it is drained by the dma machine and filled by this loop. */
+
 static ssize_t trident_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
 {
 	struct trident_state *state = (struct trident_state *)file->private_data;
@@ -1528,12 +1574,27 @@
 	VALIDATE_STATE(state);
 	if (ppos != &file->f_pos)
 		return -ESPIPE;
+	
+	/*
+	 *	Guard against an mmap or ioctl while writing
+	 */	
+	 
+	down(&state->sem);
+	
 	if (dmabuf->mapped)
-		return -ENXIO;
+	{
+		ret = -ENXIO;
+		goto out;
+	}
 	if (!dmabuf->ready && (ret = prog_dmabuf(state, 0)))
-		return ret;
+		goto out;
+
 	if (!access_ok(VERIFY_READ, buffer, count))
-		return -EFAULT;
+	{
+		ret= -EFAULT;
+		goto out;
+	}
+	
 	ret = 0;
 
 	while (count > 0) {
@@ -1559,7 +1620,7 @@
 			start_dac(state);
 			if (file->f_flags & O_NONBLOCK) {
 				if (!ret) ret = -EAGAIN;
-				return ret;
+				goto out;
 			}
 			/* No matter how much data left in the buffer, we have to wait until
 			   CSO == ESO/2 or CSO == ESO when address engine interrupts */
@@ -1567,6 +1628,8 @@
 			tmo = (dmabuf->dmasize * HZ) / (dmabuf->rate * 2);
 			tmo >>= sample_shift[dmabuf->fmt];
 			unlock_set_fmt(state);
+			up(&state->sem);
+			
 			/* There are two situations when sleep_on_timeout returns, one is when
 			   the interrupt is serviced correctly and the process is waked up by
 			   ISR ON TIME. Another is when timeout is expired, which means that
@@ -1586,7 +1649,14 @@
 			}
 			if (signal_pending(current)) {
 				if (!ret) ret = -ERESTARTSYS;
-				return ret;
+				goto out;
+			}
+			down(&state->sem);
+			if(dmabuf->mapped)
+			{
+				if(!ret)
+					ret = -ENXIO;
+				goto out;
 			}
 			continue;
 		}
@@ -1606,14 +1676,14 @@
 				ret += copy_count;
 				if (!ret) ret = -EFAULT;
 				unlock_set_fmt(state);
-				return ret;
+				goto out;
 			}
 		}
 		else {
 			if (copy_from_user(dmabuf->rawbuf + swptr, buffer, cnt)) {
 				if (!ret) ret = -EFAULT;
 				unlock_set_fmt(state);
-				return ret;
+				goto out;
 			}
 			state_cnt = cnt;
 		}
@@ -1632,9 +1702,12 @@
 		ret += cnt;
 		start_dac(state);
 	}
+out:
+	up(&state->sem);
 	return ret;
 }
 
+
 /* No kernel lock - we have our own spinlock */
 static unsigned int trident_poll(struct file *file, struct poll_table_struct *wait)
 {
@@ -1645,17 +1718,32 @@
 
 	VALIDATE_STATE(state);
 
+	/*
+	 *	Guard against a parallel poll and write causing multiple
+	 *	prog_dmabuf events
+	 */
+	 
+	down(&state->sem);
+
 	if (file->f_mode & FMODE_WRITE) {
 		if (!dmabuf->ready && prog_dmabuf(state, 0))
+		{
+			up(&state->sem);
 			return 0;
+		}
 		poll_wait(file, &dmabuf->wait, wait);
 	}
 	if (file->f_mode & FMODE_READ) {
 		if (!dmabuf->ready && prog_dmabuf(state, 1))
+		{
+			up(&state->sem);
 			return 0;
+		}
 		poll_wait(file, &dmabuf->wait, wait);
 	}
 
+	up(&state->sem);
+	
 	spin_lock_irqsave(&state->card->lock, flags);
 	trident_update_ptr(state);
 	if (file->f_mode & FMODE_READ) {
@@ -1685,6 +1773,14 @@
 
 	VALIDATE_STATE(state);
 	lock_kernel();
+	
+	/*
+	 *	Lock against poll read write or mmap creating buffers. Also lock
+	 *	a read or write against an mmap.
+	 */
+	 
+	down(&state->sem);
+	
 	if (vma->vm_flags & VM_WRITE) {
 		if ((ret = prog_dmabuf(state, 0)) != 0)
 			goto out;
@@ -1707,6 +1803,7 @@
 	dmabuf->mapped = 1;
 	ret = 0;
 out:
+	up(&state->sem);
 	unlock_kernel();
 	return ret;
 }
@@ -1718,7 +1815,7 @@
 	unsigned long flags;
 	audio_buf_info abinfo;
 	count_info cinfo;
-	int val, mapped, ret;
+	int val, mapped, ret = 0;
 
 	struct trident_card *card = state->card;
 
@@ -1733,8 +1830,9 @@
 	switch (cmd) 
 	{
 	case OSS_GETVERSION:
-		return put_user(SOUND_VERSION, (int *)arg);
-
+		ret = put_user(SOUND_VERSION, (int *)arg);
+		break;
+		
 	case SNDCTL_DSP_RESET:
 		/* FIXME: spin_lock ? */
 		if (file->f_mode & FMODE_WRITE) {
@@ -1751,16 +1849,19 @@
 			dmabuf->swptr = dmabuf->hwptr = 0;
 			dmabuf->count = dmabuf->total_bytes = 0;
 		}
-		return 0;
+		break;
 
 	case SNDCTL_DSP_SYNC:
 		if (file->f_mode & FMODE_WRITE)
-			return drain_dac(state, file->f_flags & O_NONBLOCK);
-		return 0;
+			ret = drain_dac(state, file->f_flags & O_NONBLOCK);
+		break;
 
 	case SNDCTL_DSP_SPEED: /* set smaple rate */
 		if (get_user(val, (int *)arg))
-			return -EFAULT;
+		{
+			ret = -EFAULT;
+			break;
+		}
 		if (val >= 0) {
 			if (file->f_mode & FMODE_WRITE) {
 				stop_dac(state);
@@ -1777,11 +1878,15 @@
 				spin_unlock_irqrestore(&state->card->lock, flags);
 			}
 		}
-		return put_user(dmabuf->rate, (int *)arg);
+		ret = put_user(dmabuf->rate, (int *)arg);
+		break;
 
 	case SNDCTL_DSP_STEREO: /* set stereo or mono channel */
 		if (get_user(val, (int *)arg))
-			return -EFAULT;
+		{
+			ret = -EFAULT;
+			break;
+		}
 		lock_set_fmt(state);
 		if (file->f_mode & FMODE_WRITE) {
 			stop_dac(state);
@@ -1800,26 +1905,34 @@
 				dmabuf->fmt &= ~TRIDENT_FMT_STEREO;
 		}
 		unlock_set_fmt(state);
-		return 0;
+		break;
 
 	case SNDCTL_DSP_GETBLKSIZE:
 		if (file->f_mode & FMODE_WRITE) {
 			if ((val = prog_dmabuf(state, 0)))
-				return val;
-			return put_user(dmabuf->fragsize, (int *)arg);
+				ret = val;
+			else
+				ret = put_user(dmabuf->fragsize, (int *)arg);
+			break;
 		}
 		if (file->f_mode & FMODE_READ) {
 			if ((val = prog_dmabuf(state, 1)))
-				return val;
-			return put_user(dmabuf->fragsize, (int *)arg);
+				ret = val;
+			else
+				ret = put_user(dmabuf->fragsize, (int *)arg);
+			break;
 		}
 
 	case SNDCTL_DSP_GETFMTS: /* Returns a mask of supported sample format*/
-		return put_user(AFMT_S16_LE|AFMT_U16_LE|AFMT_S8|AFMT_U8, (int *)arg);
+		ret = put_user(AFMT_S16_LE|AFMT_U16_LE|AFMT_S8|AFMT_U8, (int *)arg);
+		break;
 
 	case SNDCTL_DSP_SETFMT: /* Select sample format */
 		if (get_user(val, (int *)arg))
-			return -EFAULT;
+		{
+			ret = -EFAULT;
+			break;
+		}
 		lock_set_fmt(state);
 		if (val != AFMT_QUERY) {
 			if (file->f_mode & FMODE_WRITE) {
@@ -1840,12 +1953,16 @@
 			}
 		}
 		unlock_set_fmt(state);
-		return put_user((dmabuf->fmt & TRIDENT_FMT_16BIT) ?
+		ret = put_user((dmabuf->fmt & TRIDENT_FMT_16BIT) ?
 				AFMT_S16_LE : AFMT_U8, (int *)arg);
+		break;
 
 	case SNDCTL_DSP_CHANNELS:
 		if (get_user(val, (int *)arg))
-			return -EFAULT;
+		{
+			ret = -EFAULT;
+			break;
+		}
 		if (val != 0) {
 			lock_set_fmt(state);
 			if (file->f_mode & FMODE_WRITE) {
@@ -1866,21 +1983,22 @@
 
 						if( card->rec_channel_use_count > 0 )
 						{
-							printk("Err: Record is working on the card!\n");
-							return -EBUSY;
+							printk(KERN_ERR "trident: Record is working on the card!\n");
+							ret = -EBUSY;
+							break;
 						}
 
 						ret = ali_setup_multi_channels(state->card, 6);
 						if (ret < 0) {
 							unlock_set_fmt(state);
-							return ret;
+							break;
 						}
 						down(&state->card->open_sem);
 						ret = ali_allocate_other_states_resources(state, 6);
 						if (ret < 0) {
 							up(&state->card->open_sem);
 							unlock_set_fmt(state);
-							return ret;
+							break;
 						}
 						state->card->multi_channel_use_count ++;
 						up(&state->card->open_sem);
@@ -1905,25 +2023,38 @@
 			}
 			unlock_set_fmt(state);
 		}
-		return put_user(val, (int *)arg);
+		ret = put_user(val, (int *)arg);
+		break;
 
 	case SNDCTL_DSP_POST:
-		/* FIXME: the same as RESET ?? */
-		return 0;
+		/* Cause the working fragment to be output */
+		break;
 
 	case SNDCTL_DSP_SUBDIVIDE:
 		if (dmabuf->subdivision)
-			return -EINVAL;
+		{
+			ret = -EINVAL;
+			break;
+		}
 		if (get_user(val, (int *)arg))
-			return -EFAULT;
+		{
+			ret = -EFAULT;
+			break;
+		}
 		if (val != 1 && val != 2 && val != 4)
-			return -EINVAL;
+		{
+			ret = -EINVAL;
+			break;
+		}
 		dmabuf->subdivision = val;
-		return 0;
+		break;
 
 	case SNDCTL_DSP_SETFRAGMENT:
 		if (get_user(val, (int *)arg))
-			return -EFAULT;
+		{
+			ret = -EFAULT;
+			break;
+		}
 
 		dmabuf->ossfragshift = val & 0xffff;
 		dmabuf->ossmaxfrags = (val >> 16) & 0xffff;
@@ -1934,13 +2065,19 @@
 		if (dmabuf->ossmaxfrags < 4)
 			dmabuf->ossmaxfrags = 4;
 
-		return 0;
+		break;
 
 	case SNDCTL_DSP_GETOSPACE:
 		if (!(file->f_mode & FMODE_WRITE))
-			return -EINVAL;
+		{
+			ret = -EINVAL;
+			break;
+		}
 		if (!dmabuf->ready && (val = prog_dmabuf(state, 0)) != 0)
-			return val;
+		{ 
+			ret = val;
+			break;
+		}
 		spin_lock_irqsave(&state->card->lock, flags);
 		trident_update_ptr(state);
 		abinfo.fragsize = dmabuf->fragsize;
@@ -1948,13 +2085,20 @@
 		abinfo.fragstotal = dmabuf->numfrag;
 		abinfo.fragments = abinfo.bytes >> dmabuf->fragshift;
 		spin_unlock_irqrestore(&state->card->lock, flags);
-		return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
+		ret = copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
+		break;
 
 	case SNDCTL_DSP_GETISPACE:
 		if (!(file->f_mode & FMODE_READ))
-			return -EINVAL;
+		{
+			ret = -EINVAL;
+			break;
+		}
 		if (!dmabuf->ready && (val = prog_dmabuf(state, 1)) != 0)
-			return val;
+		{
+			ret = val;
+			break;
+		}
 		spin_lock_irqsave(&state->card->lock, flags);
 		trident_update_ptr(state);
 		abinfo.fragsize = dmabuf->fragsize;
@@ -1962,15 +2106,17 @@
 		abinfo.fragstotal = dmabuf->numfrag;
 		abinfo.fragments = abinfo.bytes >> dmabuf->fragshift;
 		spin_unlock_irqrestore(&state->card->lock, flags);
-		return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
+		ret = copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
+		break;
 
 	case SNDCTL_DSP_NONBLOCK:
 		file->f_flags |= O_NONBLOCK;
-		return 0;
+		break;
 
 	case SNDCTL_DSP_GETCAPS:
-	    return put_user(DSP_CAP_REALTIME|DSP_CAP_TRIGGER|DSP_CAP_MMAP|DSP_CAP_BIND,
+		ret = put_user(DSP_CAP_REALTIME|DSP_CAP_TRIGGER|DSP_CAP_MMAP|DSP_CAP_BIND,
 			    (int *)arg);
+		break;
 
 	case SNDCTL_DSP_GETTRIGGER:
 		val = 0;
@@ -1978,15 +2124,19 @@
 			val |= PCM_ENABLE_INPUT;
 		if ((file->f_mode & FMODE_WRITE) && dmabuf->enable)
 			val |= PCM_ENABLE_OUTPUT;
-		return put_user(val, (int *)arg);
+		ret = put_user(val, (int *)arg);
+		break;
 
 	case SNDCTL_DSP_SETTRIGGER:
 		if (get_user(val, (int *)arg))
-			return -EFAULT;
+		{
+			ret = -EFAULT;
+			break;
+		}
 		if (file->f_mode & FMODE_READ) {
 			if (val & PCM_ENABLE_INPUT) {
 				if (!dmabuf->ready && (ret = prog_dmabuf(state, 1)))
-					return ret;
+					break;
 				start_adc(state);
 			} else
 				stop_adc(state);
@@ -1994,18 +2144,24 @@
 		if (file->f_mode & FMODE_WRITE) {
 			if (val & PCM_ENABLE_OUTPUT) {
 				if (!dmabuf->ready && (ret = prog_dmabuf(state, 0)))
-					return ret;
+					break;
 				start_dac(state);
 			} else
 				stop_dac(state);
 		}
-		return 0;
+		break;
 
 	case SNDCTL_DSP_GETIPTR:
 		if (!(file->f_mode & FMODE_READ))
-			return -EINVAL;
+		{
+			ret = -EINVAL;
+			break;
+		}
 		if (!dmabuf->ready && (val = prog_dmabuf(state, 1)) != 0)
-			return val;
+		{
+			ret = val;
+			break;
+		}
 		spin_lock_irqsave(&state->card->lock, flags);
 		trident_update_ptr(state);
 		cinfo.bytes = dmabuf->total_bytes;
@@ -2014,13 +2170,21 @@
 		if (dmabuf->mapped)
 			dmabuf->count &= dmabuf->fragsize-1;
 		spin_unlock_irqrestore(&state->card->lock, flags);
-		return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));
+		ret = copy_to_user((void *)arg, &cinfo, sizeof(cinfo));
+		break;
 
 	case SNDCTL_DSP_GETOPTR:
 		if (!(file->f_mode & FMODE_WRITE))
-			return -EINVAL;
+		{
+			ret = -EINVAL;
+			break;
+		}
 		if (!dmabuf->ready && (val = prog_dmabuf(state, 0)) != 0)
-			return val;
+		{
+			ret = val;
+			break;
+		}
+		
 		spin_lock_irqsave(&state->card->lock, flags);
 		trident_update_ptr(state);
 		cinfo.bytes = dmabuf->total_bytes;
@@ -2029,43 +2193,62 @@
 		if (dmabuf->mapped)
 			dmabuf->count &= dmabuf->fragsize-1;
 		spin_unlock_irqrestore(&state->card->lock, flags);
-		return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));
+		ret = copy_to_user((void *)arg, &cinfo, sizeof(cinfo))?-EFAULT:0;
+		break;
 
 	case SNDCTL_DSP_SETDUPLEX:
-		return -EINVAL;
+		ret = -EINVAL;
+		break;
 
 	case SNDCTL_DSP_GETODELAY:
 		if (!(file->f_mode & FMODE_WRITE))
-			return -EINVAL;
+		{
+			ret = -EINVAL;
+			break;
+		}
 		if (!dmabuf->ready && (val = prog_dmabuf(state, 0)) != 0)
-			return val;
+		{
+			ret = val;
+			break;
+		}
 		spin_lock_irqsave(&state->card->lock, flags);
 		trident_update_ptr(state);
 		val = dmabuf->count;
 		spin_unlock_irqrestore(&state->card->lock, flags);
-		return put_user(val, (int *)arg);
+		ret = put_user(val, (int *)arg);
+		break;
 
 	case SOUND_PCM_READ_RATE:
-		return put_user(dmabuf->rate, (int *)arg);
+		ret = put_user(dmabuf->rate, (int *)arg);
+		break;
 
 	case SOUND_PCM_READ_CHANNELS:
-		return put_user((dmabuf->fmt & TRIDENT_FMT_STEREO) ? 2 : 1,
+		ret = put_user((dmabuf->fmt & TRIDENT_FMT_STEREO) ? 2 : 1,
 				(int *)arg);
+		break;
 
 	case SOUND_PCM_READ_BITS:
-		return put_user((dmabuf->fmt & TRIDENT_FMT_16BIT) ?
+		ret = put_user((dmabuf->fmt & TRIDENT_FMT_16BIT) ?
 				AFMT_S16_LE : AFMT_U8, (int *)arg);
+		break;
 
 	case SNDCTL_DSP_GETCHANNELMASK:
-		return put_user(DSP_BIND_FRONT|DSP_BIND_SURR|DSP_BIND_CENTER_LFE,
+		ret = put_user(DSP_BIND_FRONT|DSP_BIND_SURR|DSP_BIND_CENTER_LFE,
 				(int *)arg);
+		break;
 
 	case SNDCTL_DSP_BIND_CHANNEL:
 		if (state->card->pci_id != PCI_DEVICE_ID_SI_7018)
-			return -EINVAL;
+		{
+			ret = -EINVAL;
+			break;
+		}
 
 		if (get_user(val, (int *)arg))
-			return -EFAULT;
+		{
+			ret = -EFAULT;
+			break;
+		}
 		if (val == DSP_BIND_QUERY) {
 			val = dmabuf->channel->attribute | 0x3c00;
 			val = attr2mask[val >> 8];
@@ -2077,17 +2260,20 @@
 				dmabuf->channel->attribute = (CHANNEL_SPC_PB|SRC_ENABLE);
 			dmabuf->channel->attribute |= mask2attr[ffs(val)];
 		}
-		return put_user(val, (int *)arg);
+		ret = put_user(val, (int *)arg);
+		break;
 
 	case SNDCTL_DSP_MAPINBUF:
 	case SNDCTL_DSP_MAPOUTBUF:
 	case SNDCTL_DSP_SETSYNCRO:
 	case SOUND_PCM_WRITE_FILTER:
 	case SOUND_PCM_READ_FILTER:
-		return -EINVAL;
+	default:
+		ret = -EINVAL;
+		break;
 		
 	}
-	return -EINVAL;
+	return ret;
 }
 
 static int trident_open(struct inode *inode, struct file *file)
@@ -2098,7 +2284,16 @@
 	struct trident_state *state = NULL;
 	struct dmabuf *dmabuf = NULL;
 	
-	/* find an avaiable virtual channel (instance of /dev/dsp) */
+	/* Added by Matt Wu 01-05-2001 */
+	if(file->f_mode & FMODE_READ)
+	{
+		if(card->pci_id == PCI_DEVICE_ID_ALI_5451) {
+			if (card->multi_channel_use_count > 0)
+				return -EBUSY;
+		}
+	}
+
+	/* find an available virtual channel (instance of /dev/dsp) */
 	while (card != NULL) {
 		down(&card->open_sem);
 		if(file->f_mode & FMODE_READ)
@@ -2119,6 +2314,7 @@
 					return -ENOMEM;
 				}
 				memset(state, 0, sizeof(struct trident_state));
+				init_MUTEX(&state->sem);
 				dmabuf = &state->dmabuf;
 				goto found_virt;
 			}
@@ -2183,7 +2379,10 @@
 				(CHANNEL_REC|PCM_LR|MONO_MIX);
 		}
 		trident_set_adc_rate(state, 8000);
-		card->rec_channel_use_count ++;
+	
+		/* Added by Matt Wu 01-05-2001 */
+		if(card->pci_id == PCI_DEVICE_ID_ALI_5451)
+			card->rec_channel_use_count ++;
 	}
 
 	state->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);
@@ -2225,15 +2424,15 @@
 		dealloc_dmabuf(state);
 		state->card->free_pcm_channel(state->card, dmabuf->channel->num);
 
-		if (state->chans_num > 2)
-		{
-			if( card->multi_channel_use_count-- < 0 )
-				card->multi_channel_use_count = 0;
-
-			if (card->multi_channel_use_count == 0)
-				ali_close_multi_channels();
-
-			ali_free_other_states_resources(state);
+		/* Added by Matt Wu */
+		if (card->pci_id == PCI_DEVICE_ID_ALI_5451) {
+			if (state->chans_num > 2) {
+				if (card->multi_channel_use_count-- < 0)
+					card->multi_channel_use_count = 0;
+				if (card->multi_channel_use_count == 0)
+					ali_close_multi_channels();
+				ali_free_other_states_resources(state);
+			}
 		}
 	}
 	if (file->f_mode & FMODE_READ) {
@@ -2241,8 +2440,11 @@
 		dealloc_dmabuf(state);
 		state->card->free_pcm_channel(state->card, dmabuf->channel->num);
 
-		if( card->rec_channel_use_count-- < 0 )
-			card->rec_channel_use_count = 0;
+		/* Added by Matt Wu */
+		if (card->pci_id == PCI_DEVICE_ID_ALI_5451) {
+			if( card->rec_channel_use_count-- < 0 )
+				card->rec_channel_use_count = 0;
+		}
 	}
 
 	card->states[state->virt] = NULL;
@@ -2373,9 +2575,8 @@
 }
 
 /* Write AC97 codec registers for ALi*/
-static void ali_ac97_set(struct ac97_codec *codec, u8 reg, u16 val)
+static void ali_ac97_set(struct trident_card *card, int secondary, u8 reg, u16 val)
 {
-	struct trident_card *card = (struct trident_card *)codec->private_data;
 	unsigned int address, mask;
 	unsigned int wCount1 = 0xffff;
 	unsigned int wCount2= 0xffff;
@@ -2390,7 +2591,7 @@
 		
 	address = ALI_AC97_WRITE;
 	mask = ALI_AC97_WRITE_ACTION | ALI_AC97_AUDIO_BUSY;
-	if (codec->id)
+	if (secondary)
 		mask |= ALI_AC97_SECONDARY;
 	if (card->revision == ALI_5451_V02)
 		mask |= ALI_AC97_WRITE_MIXER_REGISTER;
@@ -2421,9 +2622,8 @@
 }
 
 /* Read AC97 codec registers for ALi*/
-static u16 ali_ac97_get(struct ac97_codec *codec, u8 reg)
+static u16 ali_ac97_get(struct trident_card *card, int secondary, u8 reg)
 {
-	struct trident_card *card = (struct trident_card *)codec->private_data;
 	unsigned int address, mask;
         unsigned int wCount1 = 0xffff;
         unsigned int wCount2= 0xffff;
@@ -2431,13 +2631,15 @@
 	unsigned long flags;
 	u32 data;
 
+	if(!card)
+		BUG();
+
 	address = ALI_AC97_READ;
 	if (card->revision == ALI_5451_V02) {
 		address = ALI_AC97_WRITE;
-		mask &= ALI_AC97_READ_MIXER_REGISTER;
 	}
 	mask = ALI_AC97_READ_ACTION | ALI_AC97_AUDIO_BUSY;
-	if (codec->id)
+	if (secondary)
 		mask |= ALI_AC97_SECONDARY;
 
 	spin_lock_irqsave(&card->lock, flags);
@@ -2480,6 +2682,56 @@
 	outl(s_channels, TRID_REG(card, ALI_GLOBAL_CONTROL));
 }
 
+static u16 ali_ac97_read(struct ac97_codec *codec, u8 reg)
+{
+	int id;
+	u16 data;
+	struct trident_card *card = NULL;
+
+	/* Added by Matt Wu */
+	if (!codec)
+		BUG();
+		
+	card = (struct trident_card *)codec->private_data;
+
+	if(!card->mixer_regs_ready)
+		return ali_ac97_get(card, codec->id, reg);
+
+	if(codec->id)
+		id = 1;
+	else
+		id = 0;
+
+	data = card->mixer_regs[reg/2][id];
+	return data;
+}
+
+static void ali_ac97_write(struct ac97_codec *codec, u8 reg, u16 val)
+{
+	int id;
+	struct trident_card *card;
+
+	/*  Added by Matt Wu */
+	if (!codec)
+		BUG();
+		
+	card = (struct trident_card *)codec->private_data;
+
+	if (!card->mixer_regs_ready)
+	{
+		ali_ac97_set(card, codec->id, reg, val);
+		return;
+	}
+
+	if(codec->id)
+		id = 1;
+	else
+		id = 0;
+
+	card->mixer_regs[reg/2][id] = val;
+	ali_ac97_set(card, codec->id, reg, val);
+}
+
 /*
 flag:	ALI_SPDIF_OUT_TO_SPDIF_OUT
 	ALI_PCM_TO_SPDIF_OUT
@@ -2493,7 +2745,7 @@
         char temp;
         struct pci_dev *pci_dev = NULL;
 
-        pci_dev = pci_find_device(PCI_VENDOR_ID_AL,PCI_DEVICE_ID_AL_M1533, pci_dev);
+        pci_dev = pci_find_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, pci_dev);
         if (pci_dev == NULL)
                 return;
         pci_read_config_byte(pci_dev, 0x61, &temp);
@@ -2748,14 +3000,14 @@
 		mdelay(4);
 		dwValue = inl(TRID_REG(card, ALI_SCTRL));
 		if (dwValue & 0x2000000) {
-			ali_ac97_set(card->ac97_codec[0], 0x02, 8080);
-			ali_ac97_set(card->ac97_codec[0], 0x36, 0);
-			ali_ac97_set(card->ac97_codec[0], 0x38, 0);
-			ali_ac97_set(card->ac97_codec[1], 0x36, 0);
-			ali_ac97_set(card->ac97_codec[1], 0x38, 0);
-			ali_ac97_set(card->ac97_codec[1], 0x02, 0);
-			ali_ac97_set(card->ac97_codec[1], 0x18, 0x0808);
-			ali_ac97_set(card->ac97_codec[1], 0x74, 0x3);
+			ali_ac97_write(card->ac97_codec[0], 0x02, 8080);
+			ali_ac97_write(card->ac97_codec[0], 0x36, 0);
+			ali_ac97_write(card->ac97_codec[0], 0x38, 0);
+			ali_ac97_write(card->ac97_codec[1], 0x36, 0);
+			ali_ac97_write(card->ac97_codec[1], 0x38, 0);
+			ali_ac97_write(card->ac97_codec[1], 0x02, 0x0606);
+			ali_ac97_write(card->ac97_codec[1], 0x18, 0x0303);
+			ali_ac97_write(card->ac97_codec[1], 0x74, 0x3);
 			return 1;
 		}
 	}
@@ -2853,7 +3105,7 @@
 	outl(ALI_DISABLE_ALL_IRQ, TRID_REG(card, T4D_MISCINT));
 	
 	for (i = 1; i < ALI_MIXER_REGS; i++)
-		ali_registers.mixer_regs[i] = ali_ac97_get (card->ac97_codec[0], i*2);
+		ali_registers.mixer_regs[i] = ali_ac97_read (card->ac97_codec[0], i*2);
 	
 	for (i = 0; i < ALI_GLOBAL_REGS; i++)
 	{	
@@ -2884,7 +3136,7 @@
 	cli();
 	
 	for (i = 1; i < ALI_MIXER_REGS; i++)
-		ali_ac97_set(card->ac97_codec[0], i*2, ali_registers.mixer_regs[i]);
+		ali_ac97_write(card->ac97_codec[0], i*2, ali_registers.mixer_regs[i]);
 	
 	for (i = 0; i < ALI_CHANNELS; i++) 
 	{
@@ -2908,19 +3160,22 @@
 	restore_flags(flags);
 }
 
-static int ali_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data)
+static int trident_suspend(struct pci_dev *dev, u32 unused)
 {
-	struct trident_card *card = (struct trident_card *)dev->data;
-	
-	if (card) {
-		switch (rqst) {
-			case PM_SUSPEND: 
-				ali_save_regs(card);
-				break;
-			case PM_RESUME: 
-				ali_restore_regs(card);
-				break;
-		}
+	struct trident_card *card = (struct trident_card *) dev;
+
+	if(card->pci_id == PCI_DEVICE_ID_ALI_5451) {
+		ali_save_regs(card);
+	}
+	return 0;
+}
+
+static int trident_resume(struct pci_dev *dev)
+{
+	struct trident_card *card = (struct trident_card *) dev;
+
+	if(card->pci_id == PCI_DEVICE_ID_ALI_5451) {
+		ali_restore_regs(card);
 	}
 	return 0;
 }
@@ -3236,29 +3491,75 @@
 	open:		trident_open_mixdev,
 };
 
+static int ali_reset_5451(struct trident_card *card)
+{
+	struct pci_dev *pci_dev = NULL;
+	unsigned int   dwVal;
+	unsigned short wCount, wReg;
+
+	pci_dev = pci_find_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, pci_dev);
+	if (pci_dev == NULL)
+		return -1;
+	
+	pci_read_config_dword(pci_dev, 0x7c, &dwVal);
+	pci_write_config_dword(pci_dev, 0x7c, dwVal | 0x08000000);
+	udelay(5000);
+	pci_read_config_dword(pci_dev, 0x7c, &dwVal);
+	pci_write_config_dword(pci_dev, 0x7c, dwVal & 0xf7ffffff);
+	udelay(5000);
+
+	pci_dev = card->pci_dev;
+	if (pci_dev == NULL)
+		return -1;
+
+	pci_read_config_dword(pci_dev, 0x44, &dwVal);
+	pci_write_config_dword(pci_dev, 0x44, dwVal | 0x000c0000);
+	udelay(500);
+	pci_read_config_dword(pci_dev, 0x44, &dwVal);
+	pci_write_config_dword(pci_dev, 0x44, dwVal & 0xfffbffff);
+	udelay(5000);
+
+	wCount = 200;
+	while(wCount--) {
+		wReg = ali_ac97_get(card, 0, AC97_POWER_CONTROL);
+		if((wReg & 0x000f) == 0x000f)
+			return 0;
+		udelay(500);
+	}
+	return 0;
+}
+
 /* AC97 codec initialisation. */
 static int __init trident_ac97_init(struct trident_card *card)
 {
 	int num_ac97 = 0;
 	unsigned long ready_2nd = 0;
 	struct ac97_codec *codec;
+	int i = 0;
+	
 
 	/* initialize controller side of AC link, and find out if secondary codes
 	   really exist */
 	switch (card->pci_id)
 	{
 	case PCI_DEVICE_ID_ALI_5451:
-		outl(0x80000000,TRID_REG(card, ALI_GLOBAL_CONTROL));
-		outl(0x00000000,TRID_REG(card, 0xa4));
-		outl(0xffffffff,TRID_REG(card, 0x98));
-		outl(0x00000000,TRID_REG(card, 0xa8));
-		outb(0x10, 	TRID_REG(card, 0x22));
+		if (ali_reset_5451(card)) 
+		{
+			printk(KERN_ERR "trident_ac97_init: error resetting 5451.\n");
+			return -1;
+		}
+		outl(0x80000001,TRID_REG(card, ALI_GLOBAL_CONTROL));
+		outl(0x00000000,TRID_REG(card, T4D_AINTEN_A));
+		outl(0xffffffff,TRID_REG(card, T4D_AINT_A));
+		outl(0x00000000,TRID_REG(card, T4D_MUSICVOL_WAVEVOL));
+		outb(0x10,	TRID_REG(card, ALI_MPUR2));
 		ready_2nd = inl(TRID_REG(card, ALI_SCTRL));
 		ready_2nd &= 0x3fff;
 		outl(ready_2nd | PCMOUT | 0x8000, TRID_REG(card, ALI_SCTRL));
 		ready_2nd = inl(TRID_REG(card, ALI_SCTRL)); 
 		ready_2nd &= SI_AC97_SECONDARY_READY;
-//		printk("codec 2 ready flag= %lx\n", ready_2nd);
+		if (card->revision < ALI_5451_V02)
+			ready_2nd = 0;
 		break;
 	case PCI_DEVICE_ID_SI_7018:
 		/* disable AC97 GPIO interrupt */
@@ -3295,8 +3596,8 @@
 		codec->id = num_ac97;
 
 		if (card->pci_id == PCI_DEVICE_ID_ALI_5451) {
-			codec->codec_read = ali_ac97_get;
-			codec->codec_write = ali_ac97_set;
+			codec->codec_read = ali_ac97_read;
+			codec->codec_write = ali_ac97_write;
 		}
 		else {
 			codec->codec_read = trident_ac97_get;
@@ -3316,10 +3617,18 @@
 
 		/* if there is no secondary codec at all, don't probe any more */
 		if (!ready_2nd)
-			return num_ac97+1;
+			break;
 	}
 
-	return 1/*num_ac97*/;
+	if (card->pci_id == PCI_DEVICE_ID_ALI_5451) {
+		for (num_ac97 = 0; num_ac97 < NR_AC97; num_ac97++) {
+			if (card->ac97_codec[num_ac97] == NULL)
+				break;
+			for (i=0; i<64;i++)
+				card->mixer_regs[i][num_ac97] = ali_ac97_get(card, num_ac97,i*2);
+		}
+	}
+	return num_ac97+1;
 }
 
 /* install the driver, we do not allocate hardware channel nor DMA buffer now, they are defered 
@@ -3331,20 +3640,14 @@
 	dma_addr_t mask;
 	int bits;
 	u8 revision;
+	int i = 0;
 
 	if (pci_enable_device(pci_dev))
 	    return -ENODEV;
 
-	if (pci_dev->device == PCI_DEVICE_ID_ALI_5451) {
-		mask = 0xffffffff;
-		bits = 32;
-	} else {
-		mask = TRIDENT_DMA_MASK;
-		bits = 30;
-	}
-	if (pci_set_dma_mask(pci_dev, mask)) {
+	if (pci_set_dma_mask(pci_dev, TRIDENT_DMA_MASK)) {
 		printk(KERN_ERR "trident: architecture does not support"
-		       " %dbit PCI busmaster DMA\n", bits);
+		       " 30bit PCI busmaster DMA\n");
 		return -ENODEV;
 	}
 	pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &revision);
@@ -3383,14 +3686,6 @@
 	       card_names[pci_id->driver_data], card->iobase, card->irq);
 
 	if(card->pci_id == PCI_DEVICE_ID_ALI_5451) {
-		/* ALi Power Management */
-		struct pm_dev *pmdev;
-		
-		pmdev = pm_register(PM_PCI_DEV, PM_PCI_ID(pci_dev),
-				ali_pm_callback);
-		if (pmdev)
-			pmdev->data = card;
-		
 		/* ALi channel Management */	
 		card->alloc_pcm_channel = ali_alloc_pcm_channel;
 		card->alloc_rec_pcm_channel = ali_alloc_rec_pcm_channel;
@@ -3438,22 +3733,38 @@
 		kfree(card);
 		return -ENODEV;
 	}
+	card->mixer_regs_ready = 0;
 	/* initialize AC97 codec and register /dev/mixer */
 	if (trident_ac97_init(card) <= 0) {
+		/* unregister audio devices */
+		for (i = 0; i < NR_AC97; i++) {
+			if (card->ac97_codec[i] != NULL) {
+				unregister_sound_mixer(card->ac97_codec[i]->dev_mixer);
+				kfree (card->ac97_codec[i]);
+			}
+		}
 		unregister_sound_dsp(card->dev_audio);
 		release_region(iobase, 256);
 		free_irq(card->irq, card);
 		kfree(card);
 		return -ENODEV;
 	}
+	card->mixer_regs_ready = 1;
 	outl(0x00, TRID_REG(card, T4D_MUSICVOL_WAVEVOL));
 
 	if (card->pci_id == PCI_DEVICE_ID_ALI_5451) {
+		if(card->revision == ALI_5451_V02)
+			ali_close_multi_channels();
 		/* edited by HMSEO for GT sound */
-#ifdef CONFIG_ALPHA_NAUTILUS
+#if defined CONFIG_ALPHA_NAUTILUS || CONFIG_ALPHA_GENERIC
 		u16 ac97_data;
-		ac97_data = ali_ac97_get (card->ac97_codec[0], AC97_POWER_CONTROL);
-		ali_ac97_set (card->ac97_codec[0], AC97_POWER_CONTROL, ac97_data | ALI_EAPD_POWER_DOWN);
+		extern struct hwrpb_struct *hwrpb;
+		
+		if ((hwrpb->sys_type) == 201) {
+			printk(KERN_INFO "trident: Running on Alpha system type Nautilus\n");
+			ac97_data = ali_ac97_get(card, 0, AC97_POWER_CONTROL);
+			ali_ac97_set(card, 0, AC97_POWER_CONTROL, ac97_data |
+		}
 #endif
 		/* edited by HMSEO for GT sound*/
 	}
@@ -3479,7 +3790,6 @@
 #ifdef CONFIG_PROC_FS
 		remove_proc_entry("ALi5451", NULL);
 #endif
-		pm_unregister_all(ali_pm_callback);
 	}
 
 	/* Kill interrupts, and SP/DIF */
@@ -3512,6 +3822,8 @@
 	id_table:	trident_pci_tbl,
 	probe:		trident_probe,
 	remove:		trident_remove,
+	suspend:	trident_suspend,
+	resume:		trident_resume
 };
 
 static int __init trident_init_module (void)
diff -urN linux-2.4.7-pre6/drivers/sound/trident.h linux/drivers/sound/trident.h
--- linux-2.4.7-pre6/drivers/sound/trident.h	Thu Oct 26 23:07:58 2000
+++ linux/drivers/sound/trident.h	Mon Dec  3 22:55:50 2001
@@ -90,7 +90,10 @@
 	T4D_STOP_B      = 0xb8, T4D_CSPF_B	= 0xbc,
 	T4D_SBBL_SBCL	= 0xc0, T4D_SBCTRL_SBE2R_SBDD    = 0xc4,
 	T4D_STIMER	= 0xc8, T4D_LFO_B_I2S_DELTA      = 0xcc,
-	T4D_AINT_B	= 0xd8, T4D_AINTEN_B    = 0xdc
+	T4D_AINT_B	= 0xd8,	T4D_AINTEN_B 	= 0xdc,
+	ALI_MPUR2 = 0x22,
+	ALI_EBUF1 = 0xf4,
+	ALI_EBUF2 = 0xf8
 };
 
 enum ali_op_registers {
@@ -136,7 +139,13 @@
 	ALI_CHANNELS		= 32,
 	ALI_STOP_ALL_CHANNELS	= 0xffffffff,
 	ALI_MULTI_CHANNELS_START_STOP	= 0x07800000
+};
 
+enum ali_EMOD_control_bit {
+	ALI_EMOD_DEC	= 0x00000000,
+	ALI_EMOD_INC	= 0x10000000,
+	ALI_EMOD_Delay	= 0x20000000,
+	ALI_EMOD_Still	= 0x30000000
 };
 
 enum ali_pcm_in_channel_num {
diff -urN linux-2.4.7-pre6/drivers/sound/wavfront.c linux/drivers/sound/wavfront.c
--- linux-2.4.7-pre6/drivers/sound/wavfront.c	Wed Jun 27 17:10:55 2001
+++ linux/drivers/sound/wavfront.c	Mon Dec  3 22:55:50 2001
@@ -166,7 +166,7 @@
 
 /*** Module-accessible parameters ***************************************/
 
-int wf_raw = 0; /* we normally check for "raw state" to firmware
+int wf_raw;     /* we normally check for "raw state" to firmware
 		   loading. if set, then during driver loading, the
 		   state of the board is ignored, and we reset the
 		   board and load the firmware anyway.
@@ -179,7 +179,7 @@
 		   operation, whatever that means.
 		*/
 
-int debug_default = 0;  /* you can set this to control debugging
+int debug_default;      /* you can set this to control debugging
 			      during driver loading. it takes any combination
 			      of the WF_DEBUG_* flags defined in
 			      wavefront.h
diff -urN linux-2.4.7-pre6/drivers/usb/bluetooth.c linux/drivers/usb/bluetooth.c
--- linux-2.4.7-pre6/drivers/usb/bluetooth.c	Wed Jun 20 16:52:30 2001
+++ linux/drivers/usb/bluetooth.c	Mon Dec  3 22:55:50 2001
@@ -1,11 +1,15 @@
 /*
- * bluetooth.c   Version 0.11
+ * bluetooth.c   Version 0.12
  *
  * Copyright (c) 2000, 2001 Greg Kroah-Hartman	<greg@kroah.com>
  * Copyright (c) 2000 Mark Douglas Corner	<mcorner@umich.edu>
  *
  * USB Bluetooth driver, based on the Bluetooth Spec version 1.0B
  * 
+ * (2001/07/09) Version 0.12 gkh
+ *	- removed in_interrupt() call, as it doesn't make sense to do 
+ *	  that anymore.
+ *
  * (2001/06/05) Version 0.11 gkh
  *	- Fixed problem with read urb status saying that we have shutdown,
  *	  and that we shouldn't resubmit the urb.  Patch from unknown.
@@ -114,9 +118,9 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v0.11"
+#define DRIVER_VERSION "v0.12"
 #define DRIVER_AUTHOR "Greg Kroah-Hartman, Mark Douglas Corner"
-#define DRIVER_DESC "USB Bluetooth driver"
+#define DRIVER_DESC "USB Bluetooth tty driver"
 
 /* define this if you have hardware that is not good */
 /*#define	BTBUGGYHARDWARE */
@@ -484,12 +488,6 @@
 		case CMD_PKT:
 			/* dbg(__FUNCTION__ "- Send cmd_pkt len:%d", count);*/
 
-			if (in_interrupt()){
-				printk("cmd_pkt from interrupt!\n");
-				retval = count;
-				goto exit;
-			}
-
 			retval = bluetooth_ctrl_msg (bluetooth, 0x00, 0x00, &current_buffer[1], count-1);
 			if (retval) {
 				goto exit;
@@ -1329,7 +1327,7 @@
 		return -1;
 	}
 
-	info(DRIVER_VERSION ":" DRIVER_DESC);
+	info(DRIVER_DESC " " DRIVER_VERSION);
 
 	return 0;
 }
diff -urN linux-2.4.7-pre6/drivers/usb/devio.c linux/drivers/usb/devio.c
--- linux-2.4.7-pre6/drivers/usb/devio.c	Fri Apr  6 15:51:50 2001
+++ linux/drivers/usb/devio.c	Mon Dec  3 22:55:50 2001
@@ -429,11 +429,14 @@
 }
 #endif
 
-static int check_ctrlrecip(struct dev_state *ps, unsigned int recip, unsigned int index)
+static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype, unsigned int index)
 {
 	int ret;
 
-	switch (recip & USB_RECIP_MASK) {
+	if (USB_TYPE_VENDOR == (USB_TYPE_MASK & requesttype))
+		return 0;
+
+	switch (requesttype & USB_RECIP_MASK) {
 	case USB_RECIP_ENDPOINT:
 		if ((ret = findintfep(ps->dev, index & 0xff)) < 0)
 			return ret;
@@ -760,7 +763,8 @@
 
 	if (copy_from_user(&uurb, arg, sizeof(uurb)))
 		return -EFAULT;
-	if (uurb.flags & ~(USBDEVFS_URB_ISO_ASAP|USBDEVFS_URB_DISABLE_SPD|USBDEVFS_URB_QUEUE_BULK))
+	if (uurb.flags & ~(USBDEVFS_URB_ISO_ASAP|USBDEVFS_URB_DISABLE_SPD|USBDEVFS_URB_QUEUE_BULK|
+			   USB_NO_FSBR|USB_ZERO_PACKET))
 		return -EINVAL;
 	if (!uurb.buffer)
 		return -EINVAL;
diff -urN linux-2.4.7-pre6/drivers/usb/dsbr100.c linux/drivers/usb/dsbr100.c
--- linux-2.4.7-pre6/drivers/usb/dsbr100.c	Tue Jun 12 15:53:37 2001
+++ linux/drivers/usb/dsbr100.c	Mon Dec  3 22:55:50 2001
@@ -85,6 +85,8 @@
 static int usb_dsbr100_open(struct video_device *dev, int flags);
 static void usb_dsbr100_close(struct video_device *dev);
 
+static int radio_nr = -1;
+MODULE_PARM(radio_nr, "i");
 
 typedef struct
 {	struct urb readurb,writeurb;
@@ -107,7 +109,6 @@
 };
 
 static int users = 0;
-static int radio_nr = -1;
 
 static struct usb_device_id usb_dsbr100_table [] = {
 	{ USB_DEVICE(DSB100_VENDOR, DSB100_PRODUCT) },
diff -urN linux-2.4.7-pre6/drivers/usb/ov511.c linux/drivers/usb/ov511.c
--- linux-2.4.7-pre6/drivers/usb/ov511.c	Tue Jun 12 15:53:37 2001
+++ linux/drivers/usb/ov511.c	Mon Dec  3 22:55:50 2001
@@ -152,6 +152,7 @@
 MODULE_PARM_DESC(sensor_gbr, "Make sensor output GBR422 rather than YUV420");
 MODULE_PARM(dumppix, "i");
 MODULE_PARM_DESC(dumppix, "Dump raw pixel data, in one of 3 formats. See ov511_dumppix() for details");
+MODULE_PARM(video_nr,"i");
 
 MODULE_AUTHOR( DRIVER_AUTHOR );
 MODULE_DESCRIPTION( DRIVER_DESC );
@@ -2521,6 +2522,9 @@
 		PDEBUG(4, "syncing to frame %d, grabstate = %d", frame,
 		       ov511->frame[frame].grabstate);
 
+		if(frame < 0 || frame >= OV511_NUMFRAMES)
+			return -EINVAL;
+			
 		switch (ov511->frame[frame].grabstate) {
 		case FRAME_UNUSED:
 			return -EINVAL;
@@ -3146,11 +3150,6 @@
 
 	init_waitqueue_head(&ov511->wq);
 
-	if (video_register_device(&ov511->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
-		err("video_register_device failed");
-		return -EBUSY;
-	}
-
 	if (ov511_write_regvals(dev, aRegvalsInit)) goto error;
 	if (ov511_write_regvals(dev, aRegvalsNorm511)) goto error;
 
@@ -3219,7 +3218,6 @@
 	return 0;
 	
 error:
-	video_unregister_device(&ov511->vdev);
 	usb_driver_release_interface(&ov511_driver,
 		&dev->actconfig->interface[ov511->iface]);
 
@@ -3328,6 +3326,11 @@
 		ov511->buf_state = BUF_NOT_ALLOCATED;
 	} else {
 		err("Failed to configure camera");
+		goto error;
+	}
+
+	if (video_register_device(&ov511->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
+		err("video_register_device failed");
 		goto error;
 	}
 
diff -urN linux-2.4.7-pre6/drivers/usb/serial/Config.in linux/drivers/usb/serial/Config.in
--- linux-2.4.7-pre6/drivers/usb/serial/Config.in	Wed Jun 27 13:59:32 2001
+++ linux/drivers/usb/serial/Config.in	Mon Dec  3 22:55:50 2001
@@ -4,7 +4,7 @@
 mainmenu_option next_comment
 comment 'USB Serial Converter support'
 
-tristate 'USB Serial Converter support' CONFIG_USB_SERIAL $CONFIG_USB
+dep_tristate 'USB Serial Converter support' CONFIG_USB_SERIAL $CONFIG_USB
 if [ "$CONFIG_USB_SERIAL" != "n" ]; then
   if [ "$CONFIG_USB_SERIAL" = "y" ]; then
      bool '  USB Serial Converter verbose debug' CONFIG_USB_SERIAL_DEBUG
diff -urN linux-2.4.7-pre6/drivers/usb/serial/io_edgeport.c linux/drivers/usb/serial/io_edgeport.c
--- linux-2.4.7-pre6/drivers/usb/serial/io_edgeport.c	Tue Jun 12 15:53:37 2001
+++ linux/drivers/usb/serial/io_edgeport.c	Mon Dec  3 22:55:50 2001
@@ -25,6 +25,9 @@
  *
  * Version history:
  * 
+ * 2.1 2001_07_09 greg kroah-hartman
+ *	- added support for TIOCMBIS and TIOCMBIC.
+ *
  *     (04/08/2001) gb
  *	- Identify version on module load.
  *
@@ -260,7 +263,7 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v2.0.0"
+#define DRIVER_VERSION "v2.1"
 #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com> and David Iacovelli"
 #define DRIVER_DESC "Edgeport USB Serial Driver"
 
@@ -1718,7 +1721,7 @@
 	return -ENOIOCTLCMD;
 }
 
-static int set_modem_info(struct edgeport_port *edge_port, unsigned int *value)
+static int set_modem_info(struct edgeport_port *edge_port, unsigned int cmd, unsigned int *value)
 {
 	unsigned int mcr = edge_port->shadowMCR;
 	unsigned int arg;
@@ -1726,11 +1729,34 @@
 	if (copy_from_user(&arg, value, sizeof(int)))
 		return -EFAULT;
 
-	// turn off the RTS and DTR
-	mcr &=  ~(MCR_RTS | MCR_DTR);
+	switch (cmd) {
+		case TIOCMBIS:
+			if (arg & TIOCM_RTS)
+				mcr |= MCR_RTS;
+			if (arg & TIOCM_DTR)
+				mcr |= MCR_RTS;
+			if (arg & TIOCM_LOOP)
+				mcr |= MCR_LOOPBACK;
+			break;
 
-	mcr |= ((arg & TIOCM_RTS) ? MCR_RTS : 0);
-	mcr |= ((arg & TIOCM_DTR) ? MCR_DTR : 0);
+		case TIOCMBIC:
+			if (arg & TIOCM_RTS)
+				mcr &= ~MCR_RTS;
+			if (arg & TIOCM_DTR)
+				mcr &= ~MCR_RTS;
+			if (arg & TIOCM_LOOP)
+				mcr &= ~MCR_LOOPBACK;
+			break;
+
+		case TIOCMSET:
+			/* turn off the RTS and DTR and LOOPBACK 
+			 * and then only turn on what was asked to */
+			mcr &=  ~(MCR_RTS | MCR_DTR | MCR_LOOPBACK);
+			mcr |= ((arg & TIOCM_RTS) ? MCR_RTS : 0);
+			mcr |= ((arg & TIOCM_DTR) ? MCR_DTR : 0);
+			mcr |= ((arg & TIOCM_LOOP) ? MCR_LOOPBACK : 0);
+			break;
+	}
 
 	edge_port->shadowMCR = mcr;
 
@@ -1827,9 +1853,11 @@
 			return get_lsr_info(edge_port, (unsigned int *) arg);
 			return 0;
 
-		case TIOCMSET:  
-			dbg(__FUNCTION__" (%d) TIOCMSET",  port->number);
-			return set_modem_info(edge_port, (unsigned int *) arg);
+		case TIOCMBIS:
+		case TIOCMBIC:
+		case TIOCMSET:
+			dbg(__FUNCTION__" (%d) TIOCMSET/TIOCMBIC/TIOCMSET",  port->number);
+			return set_modem_info(edge_port, cmd, (unsigned int *) arg);
 
 		case TIOCMGET:  
 			dbg(__FUNCTION__" (%d) TIOCMGET",  port->number);
@@ -3037,7 +3065,7 @@
 	usb_serial_register (&edgeport_16dual_device);
 	usb_serial_register (&edgeport_compat_id_device);
 	usb_serial_register (&edgeport_8i_device);
-	info(DRIVER_VERSION ":" DRIVER_DESC);
+	info(DRIVER_DESC " " DRIVER_VERSION);
 	return 0;
 }
 
diff -urN linux-2.4.7-pre6/drivers/usb/usb.c linux/drivers/usb/usb.c
--- linux-2.4.7-pre6/drivers/usb/usb.c	Mon Dec  3 22:55:41 2001
+++ linux/drivers/usb/usb.c	Mon Dec  3 22:55:50 2001
@@ -698,10 +698,12 @@
 		return -1;
 	}
 
+	down(&dev->serialize);
+
 	interface = dev->actconfig->interface + ifnum;
 
 	if (usb_interface_claimed(interface))
-		return -1;
+		goto out_err;
 
 	private = NULL;
 	for (tmp = usb_driver_list.next; tmp != &usb_driver_list;) {
@@ -709,7 +711,6 @@
 		driver = list_entry(tmp, struct usb_driver, driver_list);
 		tmp = tmp->next;
 
-		down(&driver->serialize);
 		id = driver->id_table;
 		/* new style driver? */
 		if (id) {
@@ -717,7 +718,9 @@
 			  	interface->act_altsetting = i;
 				id = usb_match_id(dev, interface, id);
 				if (id) {
+					down(&driver->serialize);
 					private = driver->probe(dev,ifnum,id);
+					up(&driver->serialize);
 					if (private != NULL)
 						break;
 				}
@@ -727,15 +730,21 @@
 				interface->act_altsetting = 0;
 		}
 		else /* "old style" driver */
+		{
+			down(&driver->serialize);
 			private = driver->probe(dev, ifnum, NULL);
+			up(&driver->serialize);
+		}
 
-		up(&driver->serialize);
 		if (private) {
 			usb_driver_claim_interface(driver, interface, private);
+			up(&dev->serialize);
 			return 0;
 		}
 	}
 
+out_err:
+	up(&dev->serialize);
 	return -1;
 }
 
@@ -934,6 +943,8 @@
 	atomic_set(&dev->refcnt, 1);
 	INIT_LIST_HEAD(&dev->inodes);
 	INIT_LIST_HEAD(&dev->filelist);
+
+	init_MUTEX(&dev->serialize);
 
 	dev->bus->op->allocate(dev);
 
diff -urN linux-2.4.7-pre6/drivers/video/clgenfb.c linux/drivers/video/clgenfb.c
--- linux-2.4.7-pre6/drivers/video/clgenfb.c	Tue Mar  6 19:28:33 2001
+++ linux/drivers/video/clgenfb.c	Mon Dec  3 22:55:50 2001
@@ -46,7 +46,7 @@
 #include <linux/init.h>
 #include <linux/selection.h>
 #include <asm/pgtable.h>
-#include <asm/io.h>
+
 #ifdef CONFIG_ZORRO
 #include <linux/zorro.h>
 #endif
@@ -168,15 +168,15 @@
 		TRUE,
 		TRUE,
 		TRUE,
-		0xF0,		
+		0xF0,
 		0xF0,
 		0,		/* unused, does not multiplex */
 		0xF1,
 		0,		/* unused, does not multiplex */
-		0x20 },		
+		0x20 },
 	{ BT_PICCOLO,
 		"CL Piccolo",
-		90000,		
+		90000,
 		TRUE,
 		TRUE,
 		FALSE,
@@ -286,22 +286,28 @@
 static const struct {
 	clgen_board_t btype;
 	zorro_id id, id2;
+	unsigned long size;
 } clgen_zorro_probe_list[] __initdata = {
 	{ BT_SD64,
 		ZORRO_PROD_HELFRICH_SD64_RAM,
-		ZORRO_PROD_HELFRICH_SD64_REG },
+		ZORRO_PROD_HELFRICH_SD64_REG,
+		0x400000 },
 	{ BT_PICCOLO,
 		ZORRO_PROD_HELFRICH_PICCOLO_RAM,
-		ZORRO_PROD_HELFRICH_PICCOLO_REG },
+		ZORRO_PROD_HELFRICH_PICCOLO_REG,
+		0x200000 },
 	{ BT_PICASSO,
 		ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM,
-		ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG },
+		ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG,
+		0x200000 },
 	{ BT_SPECTRUM,
 		ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM,
-		ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG },
+		ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG,
+		0x200000 },
 	{ BT_PICASSO4,
 		ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z3,
-		0 },
+		0,
+		0x400000 },
 };
 #endif /* CONFIG_ZORRO */
 
@@ -431,7 +437,7 @@
 	 }
 	},
 
-	/* 
+	/*
 	   Modeline from XF86Config:
 	   Mode "1024x768" 80  1024 1136 1340 1432  768 770 774 805
 	 */
@@ -705,7 +711,7 @@
 	assert (div != NULL);
 
 	/* Calculate MCLK, in case VCLK is high enough to require > 50MHz.
-	 * Assume a 64-bit data path for now.  The formula is: 
+	 * Assume a 64-bit data path for now.  The formula is:
 	 * ((B * PCLK * 2)/W) * 1.2
 	 * B = bytes per pixel, PCLK = pixclock, W = data width in bytes */
 	mclk = ((bpp / 8) * freq * 2) / 4;
@@ -1211,7 +1217,7 @@
 		/* 1280x1024 */
 		vga_wcrt (fb_info->regs, VGA_CRTC_MODE, 0xc7);
 	else
-		/* mode control: VGA_CRTC_START_HI enable, ROTATE(?), 16bit 
+		/* mode control: VGA_CRTC_START_HI enable, ROTATE(?), 16bit
 		 * address wrap, no compat. */
 		vga_wcrt (fb_info->regs, VGA_CRTC_MODE, 0xc3);
 
@@ -1243,7 +1249,7 @@
 	 * 1 bpp
 	 *
 	 */
-	
+
 	/* programming for different color depths */
 	if (_par->var.bits_per_pixel == 1) {
 		DPRINTK ("clgen: preparing for 1 bit deep display\n");
@@ -1269,7 +1275,7 @@
 			vga_wseq (fb_info->regs, CL_SEQR7,
 				vga_rseq (fb_info->regs, CL_SEQR7) & ~0x01);
 			break;
-			
+
 		default:
 			printk (KERN_WARNING "clgen: unknown Board\n");
 			break;
@@ -1310,7 +1316,7 @@
 			DPRINTK (" (for GD54xx)\n");
 			/* do nothing */
 			break;
-			
+
 		default:
 			printk (KERN_WARNING "clgen: unknown Board\n");
 			break;
@@ -1325,13 +1331,13 @@
 		vga_wseq (fb_info->regs, VGA_SEQ_PLANE_WRITE, 0x01);	/* plane mask: only write to first plane */
 		offset = _par->var.xres_virtual / 16;
 	}
-	
+
 	/******************************************************
 	 *
 	 * 8 bpp
 	 *
 	 */
-	
+
 	else if (_par->var.bits_per_pixel == 8) {
 		DPRINTK ("clgen: preparing for 8 bit deep display\n");
 		switch (fb_info->btype) {
@@ -1353,7 +1359,7 @@
 			vga_wseq (fb_info->regs, CL_SEQR7,
 				vga_rseq (fb_info->regs, CL_SEQR7) | 0x01);
 			break;
-			
+
 		default:
 			printk (KERN_WARNING "clgen: unknown Board\n");
 			break;
@@ -1395,7 +1401,7 @@
 			DPRINTK (" (for GD54xx)\n");
 			/* do nothing */
 			break;
-			
+
 		default:
 			printk (KERN_WARNING "clgen: unknown Board\n");
 			break;
@@ -1411,13 +1417,13 @@
 		vga_wseq (fb_info->regs, VGA_SEQ_PLANE_WRITE, 0xff);	/* plane mask: enable writing to all 4 planes */
 		offset = _par->var.xres_virtual / 8;
 	}
-	
+
 	/******************************************************
 	 *
 	 * 16 bpp
 	 *
 	 */
-	
+
 	else if (_par->var.bits_per_pixel == 16) {
 		DPRINTK ("clgen: preparing for 16 bit deep display\n");
 		switch (fb_info->btype) {
@@ -1469,7 +1475,7 @@
 			vga_wseq (fb_info->regs, CL_SEQR7,
 				vga_rseq (fb_info->regs, CL_SEQR7) & ~0x01);
 			break;
-			
+
 		default:
 			printk (KERN_WARNING "CLGEN: unknown Board\n");
 			break;
@@ -1479,20 +1485,21 @@
 		WGen (fb_info, VGA_PEL_MSK, 0xff);	/* pixel mask: pass-through all planes */
 #ifdef CONFIG_PCI
 		WHDR (fb_info, 0xc0);	/* Copy Xbh */
-#elif CONFIG_ZORRO
+#elif defined(CONFIG_ZORRO)
+		/* FIXME: CONFIG_PCI and CONFIG_ZORRO may be defined both */
 		WHDR (fb_info, 0xa0);	/* hidden dac reg: nothing special */
 #endif
 		vga_wseq (fb_info->regs, VGA_SEQ_MEMORY_MODE, 0x0a);	/* memory mode: chain4, ext. memory */
 		vga_wseq (fb_info->regs, VGA_SEQ_PLANE_WRITE, 0xff);	/* plane mask: enable writing to all 4 planes */
 		offset = _par->var.xres_virtual / 4;
 	}
-	
+
 	/******************************************************
 	 *
 	 * 32 bpp
 	 *
 	 */
-	
+
 	else if (_par->var.bits_per_pixel == 32) {
 		DPRINTK ("clgen: preparing for 24/32 bit deep display\n");
 		switch (fb_info->btype) {
@@ -1541,7 +1548,7 @@
 			vga_wseq (fb_info->regs, CL_SEQR7,
 				vga_rseq (fb_info->regs, CL_SEQR7) & ~0x01);
 			break;
-			
+
 		default:
 			printk (KERN_WARNING "clgen: unknown Board\n");
 			break;
@@ -1554,18 +1561,18 @@
 		vga_wseq (fb_info->regs, VGA_SEQ_PLANE_WRITE, 0xff);	/* plane mask: enable writing to all 4 planes */
 		offset = _par->var.xres_virtual / 4;
 	}
-	
+
 	/******************************************************
 	 *
 	 * unknown/unsupported bpp
 	 *
 	 */
-	
+
 	else {
 		printk (KERN_ERR "clgen: What's this?? requested color depth == %d.\n",
 			_par->var.bits_per_pixel);
 	}
-	
+
 	vga_wcrt (fb_info->regs, VGA_CRTC_OFFSET, offset & 0xff);
 	tmp = 0x22;
 	if (offset & 0x100)
@@ -1674,7 +1681,7 @@
 
 	if (regno >= 16)
 		return 0;
-		
+
 	switch (fb_info->currentmode.var.bits_per_pixel) {
 
 #ifdef FBCON_HAS_CFB16
@@ -1871,11 +1878,11 @@
 static void __init init_vgachip (struct clgenfb_info *fb_info)
 {
 	const struct clgen_board_info_rec *bi;
-	
+
 	DPRINTK ("ENTER\n");
 
 	assert (fb_info != NULL);
-	
+
 	bi = &clgen_board_info[fb_info->btype];
 
 	/* reset board globally */
@@ -1918,16 +1925,7 @@
 		break;
 	}
 
-#ifdef CLGEN_USE_HARDCODED_RAM_SETTINGS
-	/* "pre-set" a RAMsize; if the test succeeds, double it */
-	if (fb_info->btype == BT_SD64 ||
-	    fb_info->btype == BT_PICASSO4)
-		fb_info->size = 0x400000;
-	else
-		fb_info->size = 0x200000;
-#else
 	assert (fb_info->size > 0); /* make sure RAM size set by this point */
-#endif
 
 	/* assume it's a "large memory" board (2/4 MB) */
 	fb_info->smallboard = FALSE;
@@ -2141,7 +2139,7 @@
 		default: /* do nothing */ break;
 		}
 	}
-	
+
 	DPRINTK ("EXIT\n");
 #endif /* CONFIG_ZORRO */
 }
@@ -2154,10 +2152,10 @@
 	int accel_text;
 
 	DPRINTK ("ENTER\n");
-	
+
 	assert (_par != NULL);
 	assert (fb_info != NULL);
-	
+
 	accel_text = _par->var.accel_flags & FB_ACCELF_TEXT;
 
 	printk ("Cirrus Logic video mode: ");
@@ -2428,19 +2426,19 @@
 	int i;
 
 	DPRINTK ("ENTER\n");
-	
+
 	for (i = 0; i < ARRAY_SIZE(clgen_pci_probe_list); i++) {
 		pdev = NULL;
 		while ((pdev = pci_find_device (PCI_VENDOR_ID_CIRRUS,
 				clgen_pci_probe_list[i].device, pdev)) != NULL) {
 			if (pci_enable_device(pdev) == 0) {
-				*btype = clgen_pci_probe_list[i - 1].btype;
+				*btype = clgen_pci_probe_list[i].btype;
 				DPRINTK ("EXIT, returning pdev=%p\n", pdev);
 				return pdev;
 			}
 		}
 	}
-	
+
 	DPRINTK ("EXIT, returning NULL\n");
 	return NULL;
 }
@@ -2572,7 +2570,7 @@
 #ifdef CONFIG_ZORRO
 static int __init clgen_zorro_find (struct zorro_dev **z_o,
 				    struct zorro_dev **z2_o,
-				    clgen_board_t *btype)
+				    clgen_board_t *btype, unsigned long *size)
 {
 	struct zorro_dev *z = NULL;
 	int i;
@@ -2590,14 +2588,16 @@
 			*z2_o = zorro_find_device(clgen_zorro_probe_list[i].id2, NULL);
 		else
 			*z2_o = NULL;
-		*btype = clgen_zorro_probe_list[i - 1].btype;
-		
+
+		*btype = clgen_zorro_probe_list[i].btype;
+		*size = clgen_zorro_probe_list[i].size;
+
 		printk (KERN_INFO "clgen: %s board detected; ",
 			clgen_board_info[*btype].name);
-		
+
 		return 0;
 	}
-	
+
 	printk (KERN_NOTICE "clgen: no supported board found.\n");
 	return -1;
 }
@@ -2621,20 +2621,21 @@
 				     clgen_board_t *btype)
 {
 	struct zorro_dev *z = NULL, *z2 = NULL;
-	unsigned long board_addr, board_size;
-	
+	unsigned long board_addr, board_size, size;
+
 	assert (info != NULL);
 	assert (btype != NULL);
 
-	if (clgen_zorro_find (&z, &z2, btype))
+	if (clgen_zorro_find (&z, &z2, btype, &size))
 		return -1;
 
 	assert (z > 0);
 	assert (z2 >= 0);
 	assert (*btype != BT_NONE);
-	
+
 	info->board_addr = board_addr = z->resource.start;
 	info->board_size = board_size = z->resource.end-z->resource.start+1;
+	info->size = size;
 
 	if (!request_mem_region(board_addr, board_size, "clgenfb")) {
 		printk(KERN_ERR "clgen: cannot reserve region 0x%lx, abort\n",
@@ -2675,7 +2676,7 @@
 	}
 
 	printk (KERN_INFO "Cirrus Logic chipset on Zorro bus\n");
-	
+
 	return 0;
 }
 #endif /* CONFIG_ZORRO */
@@ -2704,7 +2705,8 @@
 		return -ENXIO;
 	}
 
-#elif CONFIG_ZORRO
+#elif defined(CONFIG_ZORRO)
+	/* FIXME: CONFIG_PCI and CONFIG_ZORRO may be defined both */
 	if (clgen_zorro_setup (fb_info, &btype)) {
 		DPRINTK ("EXIT, returning -ENXIO\n");
 		return -ENXIO;
@@ -2808,18 +2810,18 @@
 int __init clgenfb_setup(char *options) {
 	char *this_opt, s[32];
 	int i;
-	
+
 	DPRINTK ("ENTER\n");
-	
+
 	if (!options || !*options)
 		return 0;
-	
+
 	for (this_opt = strtok (options, ","); this_opt != NULL;
 	     this_opt = strtok (NULL, ",")) {
 		if (!*this_opt) continue;
-		
+
 		DPRINTK("clgenfb_setup: option '%s'\n", this_opt);
-		
+
 		for (i = 0; i < NUM_TOTAL_MODES; i++) {
 			sprintf (s, "mode:%s", clgenfb_predefined[i].name);
 			if (strcmp (this_opt, s) == 0)
@@ -2915,9 +2917,9 @@
 }
 
 /*** WHDR() - write into the Hidden DAC register ***/
-/* as the HDR is the only extension register that requires special treatment 
+/* as the HDR is the only extension register that requires special treatment
  * (the other extension registers are accessible just like the "ordinary"
- * registers of their functional group) here is a specialized routine for 
+ * registers of their functional group) here is a specialized routine for
  * accessing the HDR
  */
 static void WHDR (const struct clgenfb_info *fb_info, unsigned char val)
@@ -2966,7 +2968,7 @@
 #ifdef CONFIG_ZORRO
 	assert (fb_info->regs != NULL);
 	fb_info->SFR = val;
-	writeb (val, fb_info->regs + 0x8000);
+	z_writeb (val, fb_info->regs + 0x8000);
 #endif
 }
 
@@ -2978,7 +2980,7 @@
 	/* to flip to Amiga display */
 	assert (fb_info->regs != NULL);
 	fb_info->SFR = val;
-	writeb (val, fb_info->regs + 0x9000);
+	z_writeb (val, fb_info->regs + 0x9000);
 #endif
 }
 
@@ -3383,7 +3385,7 @@
  *
  * DESCRIPTION:
  */
- 
+
 static
 void clgen_dump (void)
 {
diff -urN linux-2.4.7-pre6/fs/affs/Changes linux/fs/affs/Changes
--- linux-2.4.7-pre6/fs/affs/Changes	Thu Apr 19 22:57:06 2001
+++ linux/fs/affs/Changes	Mon Dec  3 22:55:50 2001
@@ -28,6 +28,18 @@
 
 Please direct bug reports to: zippel@linux-m68k.org
 
+Version 3.16
+------------
+
+- use mark_buffer_dirty_inode instead of mark_buffer_dirty.
+- introduce affs_lock_{link|dir|ext}.
+
+Version 3.15
+------------
+
+- disable link to directories until we can properly support them.
+- locking fixes for link creation/removal.
+
 Version 3.14
 ------------
 
diff -urN linux-2.4.7-pre6/fs/affs/amigaffs.c linux/fs/affs/amigaffs.c
--- linux-2.4.7-pre6/fs/affs/amigaffs.c	Thu Apr 26 22:17:26 2001
+++ linux/fs/affs/amigaffs.c	Mon Dec  3 22:55:50 2001
@@ -57,6 +57,7 @@
 	}
 	AFFS_TAIL(sb, bh)->parent = cpu_to_be32(dir->i_ino);
 	AFFS_TAIL(sb, bh)->hash_chain = 0;
+	affs_fix_checksum(sb, bh);
 
 	if (dir->i_ino == dir_bh->b_blocknr)
 		AFFS_HEAD(dir_bh)->table[offset] = cpu_to_be32(ino);
@@ -64,7 +65,7 @@
 		AFFS_TAIL(sb, dir_bh)->hash_chain = cpu_to_be32(ino);
 
 	affs_adjust_checksum(dir_bh, ino);
-	mark_buffer_dirty(dir_bh);
+	mark_buffer_dirty_inode(dir_bh, dir);
 	affs_brelse(dir_bh);
 
 	dir->i_mtime = dir->i_ctime = CURRENT_TIME;
@@ -105,7 +106,8 @@
 			else
 				AFFS_TAIL(sb, bh)->hash_chain = ino;
 			affs_adjust_checksum(bh, be32_to_cpu(ino) - hash_ino);
-			mark_buffer_dirty(bh);
+			mark_buffer_dirty_inode(bh, dir);
+			AFFS_TAIL(sb, rem_bh)->parent = 0;
 			retval = 0;
 			break;
 		}
@@ -159,7 +161,6 @@
 	int retval;
 
 	pr_debug("AFFS: remove_link(key=%ld)\n", inode->i_ino);
-	down(&AFFS_INODE->i_link_lock);
 	retval = -EIO;
 	bh = affs_bread(sb, inode->i_ino);
 	if (!bh)
@@ -179,18 +180,20 @@
 		if (!dir)
 			goto done;
 
-		down(&AFFS_DIR->i_hash_lock);
+		affs_lock_dir(dir);
 		affs_fix_dcache(dentry, link_ino);
 		retval = affs_remove_hash(dir, link_bh);
 		if (retval)
 			goto done;
+		mark_buffer_dirty_inode(link_bh, inode);
 
 		memcpy(AFFS_TAIL(sb, bh)->name, AFFS_TAIL(sb, link_bh)->name, 32);
 		retval = affs_insert_hash(dir, bh);
 		if (retval)
 			goto done;
+		mark_buffer_dirty_inode(bh, inode);
 
-		up(&AFFS_DIR->i_hash_lock);
+		affs_unlock_dir(dir);
 		iput(dir);
 	} else {
 		link_bh = affs_bread(sb, link_ino);
@@ -203,7 +206,7 @@
 			ino = AFFS_TAIL(sb, link_bh)->link_chain;
 			AFFS_TAIL(sb, bh)->link_chain = ino;
 			affs_adjust_checksum(bh, be32_to_cpu(ino) - link_ino);
-			mark_buffer_dirty(bh);
+			mark_buffer_dirty_inode(bh, inode);
 			retval = 0;
 			/* Fix the link count, if bh is a normal header block without links */
 			switch (be32_to_cpu(AFFS_TAIL(sb, bh)->stype)) {
@@ -226,7 +229,6 @@
 done:
 	affs_brelse(link_bh);
 	affs_brelse(bh);
-	up(&AFFS_INODE->i_link_lock);
 	return retval;
 }
 
@@ -281,28 +283,41 @@
 		goto done;
 
 	pr_debug("AFFS: remove_header(key=%ld)\n", inode->i_ino);
-	down(&AFFS_DIR->i_hash_lock);
-	if (S_ISDIR(inode->i_mode)) {
+	retval = -EIO;
+	bh = affs_bread(sb, (u32)dentry->d_fsdata);
+	if (!bh)
+		goto done;
+
+	affs_lock_link(inode);
+	affs_lock_dir(dir);
+	switch (be32_to_cpu(AFFS_TAIL(sb, bh)->stype)) {
+	case ST_USERDIR:
+		/* if we ever want to support links to dirs
+		 * i_hash_lock of the inode must only be
+		 * taken after some checks
+		 */
+		affs_lock_dir(inode);
 		retval = affs_empty_dir(inode);
+		affs_unlock_dir(inode);
 		if (retval)
 			goto done_unlock;
+		break;
+	default:
+		break;
 	}
 
-	retval = -EIO;
-	bh = affs_bread(sb, inode->i_ino);
-	if (!bh)
-		goto done;
-
 	retval = affs_remove_hash(dir, bh);
 	if (retval)
 		goto done_unlock;
+	mark_buffer_dirty_inode(bh, inode);
 
-	up(&AFFS_DIR->i_hash_lock);
+	affs_lock_dir(dir);
 
 	if (inode->i_nlink > 1)
 		retval = affs_remove_link(dentry);
 	else
 		inode->i_nlink = 0;
+	affs_unlock_link(inode);
 	inode->i_ctime = CURRENT_TIME;
 	mark_inode_dirty(inode);
 
@@ -311,7 +326,8 @@
 	return retval;
 
 done_unlock:
-	up(&AFFS_DIR->i_hash_lock);
+	affs_unlock_dir(dir);
+	affs_unlock_link(inode);
 	goto done;
 }
 
diff -urN linux-2.4.7-pre6/fs/affs/dir.c linux/fs/affs/dir.c
--- linux-2.4.7-pre6/fs/affs/dir.c	Thu Apr 26 22:17:26 2001
+++ linux/fs/affs/dir.c	Mon Dec  3 22:55:50 2001
@@ -85,7 +85,7 @@
 		stored++;
 	}
 
-	down(&AFFS_INODE->i_hash_lock);
+	affs_lock_dir(inode);
 	chain_pos = (f_pos - 2) & 0xffff;
 	hash_pos  = (f_pos - 2) >> 16;
 	if (chain_pos == 0xffff) {
@@ -157,7 +157,7 @@
 readdir_out:
 	affs_brelse(dir_bh);
 	affs_brelse(fh_bh);
-	up(&AFFS_INODE->i_hash_lock);
+	affs_unlock_dir(inode);
 	pr_debug("AFFS: readdir()=%d\n", stored);
 	return res;
 }
diff -urN linux-2.4.7-pre6/fs/affs/file.c linux/fs/affs/file.c
--- linux-2.4.7-pre6/fs/affs/file.c	Fri Jun 29 15:36:10 2001
+++ linux/fs/affs/file.c	Mon Dec  3 22:55:50 2001
@@ -174,14 +174,14 @@
 	AFFS_TAIL(sb, new_bh)->parent = cpu_to_be32(inode->i_ino);
 	affs_fix_checksum(sb, new_bh);
 
-	mark_buffer_dirty(new_bh);
+	mark_buffer_dirty_inode(new_bh, inode);
 
 	tmp = be32_to_cpu(AFFS_TAIL(sb, bh)->extension);
 	if (tmp)
 		affs_warning(sb, "alloc_ext", "previous extension set (%x)", tmp);
 	AFFS_TAIL(sb, bh)->extension = cpu_to_be32(blocknr);
 	affs_adjust_checksum(bh, blocknr - tmp);
-	mark_buffer_dirty(bh);
+	mark_buffer_dirty_inode(bh, inode);
 
 	AFFS_INODE->i_extcnt++;
 	mark_inode_dirty(inode);
@@ -349,7 +349,7 @@
 		create = 0;
 
 	//lock cache
-	down(&AFFS_INODE->i_ext_lock);
+	affs_lock_ext(inode);
 
 	ext = block / AFFS_SB->s_hashsize;
 	block -= ext * AFFS_SB->s_hashsize;
@@ -388,7 +388,7 @@
 
 	affs_brelse(ext_bh);
 	//unlock cache
-	up(&AFFS_INODE->i_ext_lock);
+	affs_unlock_ext(inode);
 	return 0;
 
 err_small:
@@ -399,13 +399,13 @@
 	return -EIO;
 err_ext:
 	// unlock cache
-	up(&AFFS_INODE->i_ext_lock);
+	affs_unlock_ext(inode);
 	return PTR_ERR(ext_bh);
 err_alloc:
 	brelse(ext_bh);
 	bh_result->b_state &= ~(1UL << BH_Mapped);
 	// unlock cache
-	up(&AFFS_INODE->i_ext_lock);
+	affs_unlock_ext(inode);
 	return -ENOSPC;
 }
 
@@ -561,7 +561,7 @@
 		memset(AFFS_DATA(bh) + boff, 0, tmp);
 		AFFS_DATA_HEAD(bh)->size = cpu_to_be32(be32_to_cpu(AFFS_DATA_HEAD(bh)->size) + tmp);
 		affs_fix_checksum(sb, bh);
-		mark_buffer_dirty(bh);
+		mark_buffer_dirty_inode(bh, inode);
 		size += tmp;
 		bidx++;
 	} else if (bidx) {
@@ -581,14 +581,14 @@
 		AFFS_DATA_HEAD(bh)->sequence = cpu_to_be32(bidx);
 		AFFS_DATA_HEAD(bh)->size = cpu_to_be32(tmp);
 		affs_fix_checksum(sb, bh);
-		mark_buffer_dirty(bh);
+		mark_buffer_dirty_inode(bh, inode);
 		if (prev_bh) {
 			u32 tmp = be32_to_cpu(AFFS_DATA_HEAD(prev_bh)->next);
 			if (tmp)
 				affs_warning(sb, "prepare_write_ofs", "next block already set for %d (%d)", bidx, tmp);
 			AFFS_DATA_HEAD(prev_bh)->next = cpu_to_be32(bh->b_blocknr);
 			affs_adjust_checksum(prev_bh, bidx - tmp);
-			mark_buffer_dirty(prev_bh);
+			mark_buffer_dirty_inode(prev_bh, inode);
 			affs_brelse(prev_bh);
 		}
 		size += bsize;
@@ -688,7 +688,7 @@
 		memcpy(AFFS_DATA(bh) + boff, data + from, tmp);
 		AFFS_DATA_HEAD(bh)->size = cpu_to_be32(be32_to_cpu(AFFS_DATA_HEAD(bh)->size) + tmp);
 		affs_fix_checksum(sb, bh);
-		mark_buffer_dirty(bh);
+		mark_buffer_dirty_inode(bh, inode);
 		written += tmp;
 		from += tmp;
 		bidx++;
@@ -715,12 +715,12 @@
 					affs_warning(sb, "prepare_write_ofs", "next block already set for %d (%d)", bidx, tmp);
 				AFFS_DATA_HEAD(prev_bh)->next = cpu_to_be32(bh->b_blocknr);
 				affs_adjust_checksum(prev_bh, bidx - tmp);
-				mark_buffer_dirty(prev_bh);
+				mark_buffer_dirty_inode(prev_bh, inode);
 			}
 		}
 		affs_brelse(prev_bh);
 		affs_fix_checksum(sb, bh);
-		mark_buffer_dirty(bh);
+		mark_buffer_dirty_inode(bh, inode);
 		written += bsize;
 		from += bsize;
 		bidx++;
@@ -744,13 +744,13 @@
 					affs_warning(sb, "prepare_write_ofs", "next block already set for %d (%d)", bidx, tmp);
 				AFFS_DATA_HEAD(prev_bh)->next = cpu_to_be32(bh->b_blocknr);
 				affs_adjust_checksum(prev_bh, bidx - tmp);
-				mark_buffer_dirty(prev_bh);
+				mark_buffer_dirty_inode(prev_bh, inode);
 			}
 		} else if (be32_to_cpu(AFFS_DATA_HEAD(bh)->size) < tmp)
 			AFFS_DATA_HEAD(bh)->size = cpu_to_be32(tmp);
 		affs_brelse(prev_bh);
 		affs_fix_checksum(sb, bh);
-		mark_buffer_dirty(bh);
+		mark_buffer_dirty_inode(bh, inode);
 		written += tmp;
 		from += tmp;
 		bidx++;
@@ -866,7 +866,7 @@
 	}
 	AFFS_TAIL(sb, ext_bh)->extension = 0;
 	affs_fix_checksum(sb, ext_bh);
-	mark_buffer_dirty(ext_bh);
+	mark_buffer_dirty_inode(ext_bh, inode);
 	affs_brelse(ext_bh);
 
 	if (inode->i_size) {
diff -urN linux-2.4.7-pre6/fs/affs/inode.c linux/fs/affs/inode.c
--- linux-2.4.7-pre6/fs/affs/inode.c	Wed Apr 25 14:35:25 2001
+++ linux/fs/affs/inode.c	Mon Dec  3 22:55:50 2001
@@ -120,8 +120,15 @@
 		inode->i_fop = &affs_dir_operations;
 		break;
 	case ST_LINKDIR:
+#if 0
 		affs_warning(sb, "read_inode", "inode is LINKDIR");
 		goto bad_inode;
+#else
+		inode->i_mode |= S_IFDIR;
+		inode->i_op = NULL;
+		inode->i_fop = NULL;
+		break;
+#endif
 	case ST_LINKFILE:
 		affs_warning(sb, "read_inode", "inode is LINKFILE");
 		goto bad_inode;
@@ -207,7 +214,7 @@
 		}
 	}
 	affs_fix_checksum(sb, bh);
-	mark_buffer_dirty(bh);
+	mark_buffer_dirty_inode(bh, inode);
 	affs_brelse(bh);
 	unlock_kernel();
 }
@@ -302,7 +309,7 @@
 	bh = affs_getzeroblk(sb, block);
 	if (!bh)
 		goto err_bh;
-	mark_buffer_dirty(bh);
+	mark_buffer_dirty_inode(bh, inode);
 	affs_brelse(bh);
 
 	inode->i_sb      = sb;
@@ -352,6 +359,7 @@
 	if (!bh)
 		goto done;
 
+	affs_lock_link(inode);
 	switch (type) {
 	case ST_LINKFILE:
 	case ST_LINKDIR:
@@ -377,25 +385,25 @@
 
 	if (inode_bh) {
 		u32 chain;
-		down(&AFFS_INODE->i_link_lock);
 	       	chain = AFFS_TAIL(sb, inode_bh)->link_chain;
 		AFFS_TAIL(sb, bh)->original = cpu_to_be32(inode->i_ino);
 		AFFS_TAIL(sb, bh)->link_chain = chain;
 		AFFS_TAIL(sb, inode_bh)->link_chain = cpu_to_be32(block);
 		affs_adjust_checksum(inode_bh, block - be32_to_cpu(chain));
-		mark_buffer_dirty(inode_bh);
+		mark_buffer_dirty_inode(inode_bh, inode);
 		inode->i_nlink = 2;
 		atomic_inc(&inode->i_count);
-		up(&AFFS_INODE->i_link_lock);
 	}
 	affs_fix_checksum(sb, bh);
-	mark_buffer_dirty(bh);
+	mark_buffer_dirty_inode(bh, inode);
+	dentry->d_fsdata = (void *)bh->b_blocknr;
 
-	down(&AFFS_DIR->i_hash_lock);
+	affs_lock_dir(dir);
 	retval = affs_insert_hash(dir, bh);
-	up(&AFFS_DIR->i_hash_lock);
+	mark_buffer_dirty_inode(bh, inode);
+	affs_unlock_dir(dir);
+	affs_unlock_link(inode);
 
-	dentry->d_fsdata = (void *)bh->b_blocknr;
 	d_instantiate(dentry, inode);
 done:
 	affs_brelse(inode_bh);
@@ -404,5 +412,6 @@
 err:
 	if (block)
 		affs_free_block(sb, block);
+	affs_unlock_link(inode);
 	goto done;
 }
diff -urN linux-2.4.7-pre6/fs/affs/namei.c linux/fs/affs/namei.c
--- linux-2.4.7-pre6/fs/affs/namei.c	Wed Apr 25 14:57:29 2001
+++ linux/fs/affs/namei.c	Mon Dec  3 22:55:50 2001
@@ -217,9 +217,9 @@
 
 	pr_debug("AFFS: lookup(\"%.*s\")\n",(int)dentry->d_name.len,dentry->d_name.name);
 
-	down(&AFFS_DIR->i_hash_lock);
+	affs_lock_dir(dir);
 	bh = affs_find_entry(dir, dentry);
-	up(&AFFS_DIR->i_hash_lock);
+	affs_unlock_dir(dir);
 	if (IS_ERR(bh))
 		return ERR_PTR(PTR_ERR(bh));
 	if (bh) {
@@ -228,7 +228,8 @@
 		/* store the real header ino in d_fsdata for faster lookups */
 		dentry->d_fsdata = (void *)(long)ino;
 		switch (be32_to_cpu(AFFS_TAIL(sb, bh)->stype)) {
-		case ST_LINKDIR:
+		//link to dirs disabled
+		//case ST_LINKDIR:
 		case ST_LINKFILE:
 			ino = be32_to_cpu(AFFS_TAIL(sb, bh)->original);
 		}
@@ -381,7 +382,7 @@
 				symname++;
 	}
 	*p = 0;
-	mark_buffer_dirty(bh);
+	mark_buffer_dirty_inode(bh, inode);
 	affs_brelse(bh);
 	mark_inode_dirty(inode);
 
@@ -407,6 +408,9 @@
 	pr_debug("AFFS: link(%u, %u, \"%.*s\")\n", (u32)inode->i_ino, (u32)dir->i_ino,
 		 (int)dentry->d_name.len,dentry->d_name.name);
 
+	if (S_ISDIR(inode->i_mode))
+		return -EPERM;
+
 	error = affs_add_entry(dir, inode, dentry, S_ISDIR(inode->i_mode) ? ST_LINKDIR : ST_LINKFILE);
 	if (error) {
 		inode->i_nlink = 0;
@@ -422,7 +426,6 @@
 	    struct inode *new_dir, struct dentry *new_dentry)
 {
 	struct super_block *sb = old_dir->i_sb;
-	struct inode *dir;
 	struct buffer_head *bh = NULL;
 	int retval;
 
@@ -445,30 +448,28 @@
 	if (!bh)
 		goto done;
 
+	affs_lock_dir(old_dir);
+	if (old_dir != new_dir)
+		affs_lock_dir(new_dir);
+
 	/* Remove header from its parent directory. */
-	dir = old_dir;
-	down(&AFFS_DIR->i_hash_lock);
-	retval = affs_remove_hash(dir, bh);
+	retval = affs_remove_hash(old_dir, bh);
 	if (retval)
 		goto done_unlock;
 
-	up(&AFFS_DIR->i_hash_lock);
-
 	/* And insert it into the new directory with the new name. */
-	dir = new_dir;
 	affs_copy_name(AFFS_TAIL(sb, bh)->name, new_dentry);
 	affs_fix_checksum(sb, bh);
-	down(&AFFS_DIR->i_hash_lock);
 	retval = affs_insert_hash(new_dir, bh);
-	if (retval)
-		goto done_unlock;
-	up(&AFFS_DIR->i_hash_lock);
+	/* TODO: move it back to old_dir? */
+
+done_unlock:
+	affs_unlock_dir(old_dir);
+	if (old_dir != new_dir)
+		affs_unlock_dir(new_dir);
 
 done:
+	mark_buffer_dirty_inode(bh, retval ? old_dir : new_dir);
 	affs_brelse(bh);
 	return retval;
-
-done_unlock:
-	up(&AFFS_DIR->i_hash_lock);
-	goto done;
 }
diff -urN linux-2.4.7-pre6/fs/binfmt_elf.c linux/fs/binfmt_elf.c
--- linux-2.4.7-pre6/fs/binfmt_elf.c	Mon Jul  2 14:38:38 2001
+++ linux/fs/binfmt_elf.c	Mon Dec  3 22:55:50 2001
@@ -888,11 +888,15 @@
  */
 static inline int maydump(struct vm_area_struct *vma)
 {
-	if (!(vma->vm_flags & (VM_READ|VM_WRITE|VM_EXEC)))
+	/*
+	 * If we may not read the contents, don't allow us to dump
+	 * them either. "dump_write()" can't handle it anyway.
+	 */
+	if (!(vma->vm_flags & VM_READ))
 		return 0;
 
 	/* Do not dump I/O mapped devices! -DaveM */
-	if(vma->vm_flags & VM_IO)
+	if (vma->vm_flags & VM_IO)
 		return 0;
 #if 1
 	if (vma->vm_flags & (VM_WRITE|VM_GROWSUP|VM_GROWSDOWN))
@@ -1205,13 +1209,12 @@
 			pte_t *pte;
 
 			pgd = pgd_offset(vma->vm_mm, addr);
+			if (pgd_none(*pgd))
+				goto nextpage_coredump;
 			pmd = pmd_offset(pgd, addr);
-	
-			if (!pmd)
+			if (pmd_none(*pmd))
 				goto nextpage_coredump;
 			pte = pte_offset(pmd, addr);
-			if (!pte)
-				goto nextpage_coredump;
 			if (pte_none(*pte)) {
 nextpage_coredump:
 				DUMP_SEEK (file->f_pos + PAGE_SIZE);
diff -urN linux-2.4.7-pre6/fs/buffer.c linux/fs/buffer.c
--- linux-2.4.7-pre6/fs/buffer.c	Mon Dec  3 22:55:41 2001
+++ linux/fs/buffer.c	Mon Dec  3 22:55:50 2001
@@ -45,6 +45,7 @@
 #include <linux/quotaops.h>
 #include <linux/iobuf.h>
 #include <linux/highmem.h>
+#include <linux/completion.h>
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
@@ -1159,7 +1160,7 @@
 		put_bh(buf);
 		return;
 	}
-	printk("VFS: brelse: Trying to free free buffer\n");
+	printk(KERN_ERR "VFS: brelse: Trying to free free buffer\n");
 }
 
 /*
@@ -2262,7 +2263,7 @@
 	int isize;
 
 	if ((size & 511) || (size > PAGE_SIZE)) {
-		printk("VFS: grow_buffers: size = %d\n",size);
+		printk(KERN_ERR "VFS: grow_buffers: size = %d\n",size);
 		return 0;
 	}
 
@@ -2692,7 +2693,7 @@
  * the syscall above, but now we launch it ourselves internally with
  * kernel_thread(...)  directly after the first thread in init/main.c
  */
-int bdflush(void *sem)
+int bdflush(void *startup)
 {
 	struct task_struct *tsk = current;
 	int flushed;
@@ -2713,7 +2714,7 @@
 	recalc_sigpending(tsk);
 	spin_unlock_irq(&tsk->sigmask_lock);
 
-	up((struct semaphore *)sem);
+	complete((struct completion *)startup);
 
 	for (;;) {
 		CHECK_EMERGENCY_SYNC
@@ -2738,7 +2739,7 @@
  * You don't need to change your userspace configuration since
  * the userspace `update` will do_exit(0) at the first sys_bdflush().
  */
-int kupdate(void *sem)
+int kupdate(void *startup)
 {
 	struct task_struct * tsk = current;
 	int interval;
@@ -2754,7 +2755,7 @@
 	recalc_sigpending(tsk);
 	spin_unlock_irq(&tsk->sigmask_lock);
 
-	up((struct semaphore *)sem);
+	complete((struct completion *)startup);
 
 	for (;;) {
 		/* update interval */
@@ -2781,7 +2782,7 @@
 				goto stop_kupdate;
 		}
 #ifdef DEBUG
-		printk("kupdate() activated...\n");
+		printk(KERN_DEBUG "kupdate() activated...\n");
 #endif
 		sync_old_buffers();
 	}
@@ -2789,11 +2790,12 @@
 
 static int __init bdflush_init(void)
 {
-	DECLARE_MUTEX_LOCKED(sem);
-	kernel_thread(bdflush, &sem, CLONE_FS | CLONE_FILES | CLONE_SIGNAL);
-	down(&sem);
-	kernel_thread(kupdate, &sem, CLONE_FS | CLONE_FILES | CLONE_SIGNAL);
-	down(&sem);
+	static DECLARE_COMPLETION(startup);
+
+	kernel_thread(bdflush, &startup, CLONE_FS | CLONE_FILES | CLONE_SIGNAL);
+	wait_for_completion(&startup);
+	kernel_thread(kupdate, &startup, CLONE_FS | CLONE_FILES | CLONE_SIGNAL);
+	wait_for_completion(&startup);
 	return 0;
 }
 
diff -urN linux-2.4.7-pre6/fs/devfs/base.c linux/fs/devfs/base.c
--- linux-2.4.7-pre6/fs/devfs/base.c	Wed Jun 20 10:54:31 2001
+++ linux/fs/devfs/base.c	Mon Dec  3 22:55:50 2001
@@ -507,6 +507,10 @@
 	       Replaced <devfsd_read> stack usage with <devfsd_ioctl> kmalloc.
 	       Simplified locking in <devfsd_ioctl> and fixed memory leak.
   v0.106
+    20010709   Richard Gooch <rgooch@atnf.csiro.au>
+	       Removed broken devnum allocation and use <devfs_alloc_devnum>.
+	       Fixed old devnum leak by calling new <devfs_dealloc_devnum>.
+  v0.107
 */
 #include <linux/types.h>
 #include <linux/errno.h>
@@ -524,8 +528,6 @@
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/locks.h>
-#include <linux/kdev_t.h>
 #include <linux/devfs_fs.h>
 #include <linux/devfs_fs_kernel.h>
 #include <linux/smp_lock.h>
@@ -541,7 +543,7 @@
 #include <asm/bitops.h>
 #include <asm/atomic.h>
 
-#define DEVFS_VERSION            "0.106 (20010617)"
+#define DEVFS_VERSION            "0.107 (20010709)"
 
 #define DEVFS_NAME "devfs"
 
@@ -550,9 +552,6 @@
 
 #define STRING_LENGTH 256
 
-#define MIN_DEVNUM 36864  /*  Use major numbers 144   */
-#define MAX_DEVNUM 61439  /*  through 239, inclusive  */
-
 #ifndef TRUE
 #  define TRUE 1
 #  define FALSE 0
@@ -626,6 +625,7 @@
     unsigned char aopen_notify:1;
     unsigned char removable:1;  /*  Belongs in device_type, but save space   */
     unsigned char open:1;       /*  Not entirely correct                     */
+    unsigned char autogen:1;    /*  Belongs in device_type, but save space   */
 };
 
 struct symlink_type
@@ -712,8 +712,6 @@
 };
 
 static struct fs_info fs_info = {devfsd_buffer_lock: SPIN_LOCK_UNLOCKED};
-static unsigned int next_devnum_char = MIN_DEVNUM;
-static unsigned int next_devnum_block = MIN_DEVNUM;
 static const int devfsd_buf_size = PAGE_SIZE / sizeof(struct devfsd_buf_entry);
 #ifdef CONFIG_DEVFS_DEBUG
 static unsigned int devfs_debug_init __initdata = DEBUG_NONE;
@@ -873,6 +871,7 @@
 
 static struct devfs_entry *get_root_entry (void)
 {
+    kdev_t devnum;
     struct devfs_entry *new;
 
     /*  Always ensure the root is created  */
@@ -885,9 +884,9 @@
     /*  And create the entry for ".devfsd"  */
     if ( ( new = create_entry (root_entry, ".devfsd", 0) ) == NULL )
 	return NULL;
-    new->u.fcb.u.device.major = next_devnum_char >> 8;
-    new->u.fcb.u.device.minor = next_devnum_char & 0xff;
-    ++next_devnum_char;
+    devnum = devfs_alloc_devnum (DEVFS_SPECIAL_CHR);
+    new->u.fcb.u.device.major = MAJOR (devnum);
+    new->u.fcb.u.device.minor = MINOR (devnum);
     new->mode = S_IFCHR | S_IRUSR | S_IWUSR;
     new->u.fcb.default_uid = 0;
     new->u.fcb.default_gid = 0;
@@ -1264,7 +1263,9 @@
 			       unsigned int major, unsigned int minor,
 			       umode_t mode, void *ops, void *info)
 {
+    char devtype = S_ISCHR (mode) ? DEVFS_SPECIAL_CHR : DEVFS_SPECIAL_BLK;
     int is_new;
+    kdev_t devnum = NODEV;
     struct devfs_entry *de;
 
     if (name == NULL)
@@ -1296,29 +1297,17 @@
 		DEVFS_NAME, name);
 	return NULL;
     }
-    if ( S_ISCHR (mode) && (flags & DEVFS_FL_AUTO_DEVNUM) )
-    {
-	if (next_devnum_char >= MAX_DEVNUM)
-	{
-	    printk ("%s: devfs_register(%s): exhausted char device numbers\n",
-		    DEVFS_NAME, name);
-	    return NULL;
-	}
-	major = next_devnum_char >> 8;
-	minor = next_devnum_char & 0xff;
-	++next_devnum_char;
-    }
-    if ( S_ISBLK (mode) && (flags & DEVFS_FL_AUTO_DEVNUM) )
+    if ( ( S_ISCHR (mode) || S_ISBLK (mode) ) &&
+	 (flags & DEVFS_FL_AUTO_DEVNUM) )
     {
-	if (next_devnum_block >= MAX_DEVNUM)
+	if ( ( devnum = devfs_alloc_devnum (devtype) ) == NODEV )
 	{
-	    printk ("%s: devfs_register(%s): exhausted block device numbers\n",
-		    DEVFS_NAME, name);
+	    printk ("%s: devfs_register(%s): exhausted %s device numbers\n",
+		    DEVFS_NAME, name, S_ISCHR (mode) ? "char" : "block");
 	    return NULL;
 	}
-	major = next_devnum_block >> 8;
-	minor = next_devnum_block & 0xff;
-	++next_devnum_block;
+	major = MAJOR (devnum);
+	minor = MINOR (devnum);
     }
     de = search_for_entry (dir, name, strlen (name), TRUE, TRUE, &is_new,
 			   FALSE);
@@ -1326,6 +1315,7 @@
     {
 	printk ("%s: devfs_register(): could not create entry: \"%s\"\n",
 		DEVFS_NAME, name);
+	if (devnum != NODEV) devfs_dealloc_devnum (devtype, devnum);
 	return NULL;
     }
 #ifdef CONFIG_DEVFS_DEBUG
@@ -1341,19 +1331,23 @@
 	{
 	    printk ("%s: devfs_register(): existing non-device/file entry: \"%s\"\n",
 		    DEVFS_NAME, name);
+	    if (devnum != NODEV) devfs_dealloc_devnum (devtype, devnum);
 	    return NULL;
 	}
 	if (de->registered)
 	{
 	    printk("%s: devfs_register(): device already registered: \"%s\"\n",
 		   DEVFS_NAME, name);
+	    if (devnum != NODEV) devfs_dealloc_devnum (devtype, devnum);
 	    return NULL;
 	}
     }
+    de->u.fcb.autogen = 0;
     if ( S_ISCHR (mode) || S_ISBLK (mode) )
     {
 	de->u.fcb.u.device.major = major;
 	de->u.fcb.u.device.minor = minor;
+	de->u.fcb.autogen = (devnum == NODEV) ? 0 : 1;
     }
     else if ( S_ISREG (mode) ) de->u.fcb.u.file.size = 0;
     else
@@ -1417,6 +1411,14 @@
     {
 	de->registered = FALSE;
 	de->u.fcb.ops = NULL;
+	if (!S_ISREG (de->mode) && de->u.fcb.autogen)
+	{
+	    devfs_dealloc_devnum ( S_ISCHR (de->mode) ? DEVFS_SPECIAL_CHR :
+				   DEVFS_SPECIAL_BLK,
+				   MKDEV (de->u.fcb.u.device.major,
+					  de->u.fcb.u.device.minor) );
+	}
+	de->u.fcb.autogen = 0;
 	return;
     }
     if (S_ISLNK (de->mode) && de->registered)
diff -urN linux-2.4.7-pre6/fs/devfs/util.c linux/fs/devfs/util.c
--- linux-2.4.7-pre6/fs/devfs/util.c	Tue Jun 12 10:57:46 2001
+++ linux/fs/devfs/util.c	Mon Dec  3 22:55:50 2001
@@ -35,12 +35,18 @@
                Took account of interface change to <devfs_mk_dir>.
     20010519   Richard Gooch <rgooch@atnf.csiro.au>
                Documentation cleanup.
+    20010709   Richard Gooch <rgooch@atnf.csiro.au>
+               Created <devfs_*alloc_major> and <devfs_*alloc_devnum>.
+    20010710   Richard Gooch <rgooch@atnf.csiro.au>
+               Created <devfs_*alloc_unique_number>.
 */
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/locks.h>
-#include <linux/kdev_t.h>
 #include <linux/devfs_fs_kernel.h>
+#include <linux/malloc.h>
+#include <linux/vmalloc.h>
+
+#include <asm/bitops.h>
 
 
 /*  Private functions follow  */
@@ -166,3 +172,297 @@
     }
 }   /*  End Function devfs_register_series  */
 EXPORT_SYMBOL(devfs_register_series);
+
+
+struct major_list
+{
+    spinlock_t lock;
+    __u32 bits[8];
+};
+
+/*  Block majors already assigned:
+    0-3, 7-9, 11-12, 13-63, 65-93, 95-99, 101, 103-111, 120-127, 199, 201,
+    240-255
+*/
+static struct major_list block_major_list =
+{SPIN_LOCK_UNLOCKED,
+    {0xfffffb8f,  /*  Majors 0   to 31   */
+     0xffffffff,  /*  Majors 32  to 63   */
+     0xbffffffe,  /*  Majors 64  to 95   */
+     0xff00ffaf,  /*  Majors 96  to 127  */
+     0x00000000,  /*  Majors 128 to 159  */
+     0x00000000,  /*  Majors 160 to 191  */
+     0x00000280,  /*  Majors 192 to 223  */
+     0xffff0000}  /*  Majors 224 to 255  */
+};
+
+/*  Char majors already assigned:
+    0-7, 9-151, 154-158, 160-195, 198-211, 216-221, 224-225, 240-255
+*/
+static struct major_list char_major_list =
+{SPIN_LOCK_UNLOCKED,
+    {0xfffffeff,  /*  Majors 0   to 31   */
+     0xffffffff,  /*  Majors 32  to 63   */
+     0xffffffff,  /*  Majors 64  to 95   */
+     0xffffffff,  /*  Majors 96  to 127  */
+     0x7cffffff,  /*  Majors 128 to 159  */
+     0xffffffff,  /*  Majors 160 to 191  */
+     0x3f0fffcf,  /*  Majors 192 to 223  */
+     0xffff0003}  /*  Majors 224 to 255  */
+};
+
+
+/**
+ *	devfs_alloc_major - Allocate a major number.
+ *	@type: The type of the major (DEVFS_SPECIAL_CHR or DEVFS_SPECIAL_BLOCK)
+
+ *	Returns the allocated major, else -1 if none are available.
+ *	This routine is thread safe and does not block.
+ */
+
+int devfs_alloc_major (char type)
+{
+    int major;
+    struct major_list *list;
+
+    list = (type == DEVFS_SPECIAL_CHR) ? &char_major_list : &block_major_list;
+    spin_lock (&list->lock);
+    major = find_first_zero_bit (list->bits, 256);
+    if (major < 256) __set_bit (major, list->bits);
+    else major = -1;
+    spin_unlock (&list->lock);
+    return major;
+}   /*  End Function devfs_alloc_major  */
+EXPORT_SYMBOL(devfs_alloc_major);
+
+
+/**
+ *	devfs_dealloc_major - Deallocate a major number.
+ *	@type: The type of the major (DEVFS_SPECIAL_CHR or DEVFS_SPECIAL_BLOCK)
+ *	@major: The major number.
+ *	This routine is thread safe and does not block.
+ */
+
+void devfs_dealloc_major (char type, int major)
+{
+    int was_set;
+    struct major_list *list;
+
+    if (major < 0) return;
+    list = (type == DEVFS_SPECIAL_CHR) ? &char_major_list : &block_major_list;
+    spin_lock (&list->lock);
+    was_set = __test_and_clear_bit (major, list->bits);
+    spin_unlock (&list->lock);
+    if (!was_set)
+	printk (KERN_ERR __FUNCTION__ "(): major %d was already free\n",
+		major);
+}   /*  End Function devfs_dealloc_major  */
+EXPORT_SYMBOL(devfs_dealloc_major);
+
+
+struct minor_list
+{
+    int major;
+    __u32 bits[8];
+    struct minor_list *next;
+};
+
+struct device_list
+{
+    struct minor_list *first, *last;
+    int none_free;
+};
+
+DECLARE_MUTEX (block_semaphore);
+static struct device_list block_list;
+
+DECLARE_MUTEX (char_semaphore);
+static struct device_list char_list;
+
+
+/**
+ *	devfs_alloc_devnum - Allocate a device number.
+ *	@type: The type (DEVFS_SPECIAL_CHR or DEVFS_SPECIAL_BLOCK).
+ *
+ *	Returns the allocated device number, else NODEV if none are available.
+ *	This routine is thread safe and may block.
+ */
+
+kdev_t devfs_alloc_devnum (char type)
+{
+    int minor;
+    struct semaphore *semaphore;
+    struct device_list *list;
+    struct minor_list *entry;
+
+    if (type == DEVFS_SPECIAL_CHR)
+    {
+	semaphore = &char_semaphore;
+	list = &char_list;
+    }
+    else
+    {
+	semaphore = &block_semaphore;
+	list = &block_list;
+    }
+    if (list->none_free) return NODEV;  /*  Fast test  */
+    down (semaphore);
+    if (list->none_free)
+    {
+	up (semaphore);
+	return NODEV;
+    }
+    for (entry = list->first; entry != NULL; entry = entry->next)
+    {
+	minor = find_first_zero_bit (entry->bits, 256);
+	if (minor >= 256) continue;
+	__set_bit (minor, entry->bits);
+	up (semaphore);
+	return MKDEV (entry->major, minor);
+    }
+    /*  Need to allocate a new major  */
+    if ( ( entry = kmalloc (sizeof *entry, GFP_KERNEL) ) == NULL )
+    {
+	list->none_free = 1;
+	up (semaphore);
+	return NODEV;
+    }
+    memset (entry, 0, sizeof *entry);
+    if ( ( entry->major = devfs_alloc_major (type) ) < 0 )
+    {
+	list->none_free = 1;
+	up (semaphore);
+	kfree (entry);
+	return NODEV;
+    }
+    __set_bit (0, entry->bits);
+    if (list->first == NULL) list->first = entry;
+    else list->last->next = entry;
+    list->last = entry;
+    up (semaphore);
+    return MKDEV (entry->major, 0);
+}   /*  End Function devfs_alloc_devnum  */
+EXPORT_SYMBOL(devfs_alloc_devnum);
+
+
+/**
+ *	devfs_dealloc_devnum - Dellocate a device number.
+ *	@type: The type (DEVFS_SPECIAL_CHR or DEVFS_SPECIAL_BLOCK).
+ *	@devnum: The device number.
+ *
+ *	This routine is thread safe and does not block.
+ */
+
+void devfs_dealloc_devnum (char type, kdev_t devnum)
+{
+    int major, minor;
+    struct semaphore *semaphore;
+    struct device_list *list;
+    struct minor_list *entry;
+
+    if (devnum == NODEV) return;
+    if (type == DEVFS_SPECIAL_CHR)
+    {
+	semaphore = &char_semaphore;
+	list = &char_list;
+    }
+    else
+    {
+	semaphore = &block_semaphore;
+	list = &block_list;
+    }
+    major = MAJOR (devnum);
+    minor = MINOR (devnum);
+    down (semaphore);
+    for (entry = list->first; entry != NULL; entry = entry->next)
+    {
+	int was_set;
+
+	if (entry->major != major) continue;
+	was_set = __test_and_clear_bit (minor, entry->bits);
+	if (was_set) list->none_free = 0;
+	up (semaphore);
+	if (!was_set)
+	    printk ( KERN_ERR __FUNCTION__ "(): device %s was already free\n",
+		     kdevname (devnum) );
+	return;
+    }
+    up (semaphore);
+    printk ( KERN_ERR __FUNCTION__ "(): major for %s not previously allocated\n",
+	     kdevname (devnum) );
+}   /*  End Function devfs_dealloc_devnum  */
+EXPORT_SYMBOL(devfs_dealloc_devnum);
+
+
+/**
+ *	devfs_alloc_unique_number - Allocate a unique (positive) number.
+ *	@space: The number space to allocate from.
+ *
+ *	Returns the allocated unique number, else a negative error code.
+ *	This routine is thread safe and may block.
+ */
+
+int devfs_alloc_unique_number (struct unique_numspace *space)
+{
+    int number;
+    unsigned int length;
+    __u32 *bits;
+
+    /*  Get around stupid lack of semaphore initialiser  */
+    spin_lock (&space->init_lock);
+    if (!space->sem_initialised)
+    {
+	sema_init (&space->semaphore, 1);
+	space->sem_initialised = 1;
+    }
+    spin_unlock (&space->init_lock);
+    down (&space->semaphore);
+    if (space->num_free < 1)
+    {
+	if (space->length < 16) length = 16;
+	else length = space->length << 1;
+	if ( ( bits = vmalloc (length) ) == NULL )
+	{
+	    up (&space->semaphore);
+	    return -ENOMEM;
+	}
+	if (space->bits != NULL)
+	{
+	    memcpy (bits, space->bits, space->length);
+	    vfree (space->bits);
+	}
+	space->num_free = (length - space->length) << 3;
+	space->bits = bits;
+	memset (bits + space->length, 0, length - space->length);
+	space->length = length;
+    }
+    number = find_first_zero_bit (space->bits, space->length << 3);
+    __set_bit (number, space->bits);
+    up (&space->semaphore);
+    return number;
+}   /*  End Function devfs_alloc_unique_number  */
+EXPORT_SYMBOL(devfs_alloc_unique_number);
+
+
+/**
+ *	devfs_dealloc_unique_number - Deallocate a unique (positive) number.
+ *	@space: The number space to deallocate from.
+ *	@number: The number to deallocate.
+ *
+ *	This routine is thread safe and may block.
+ */
+
+void devfs_dealloc_unique_number (struct unique_numspace *space, int number)
+{
+    int was_set;
+
+    if (number < 0) return;
+    down (&space->semaphore);
+    was_set = __test_and_clear_bit (number, space->bits);
+    if (was_set) ++space->num_free;
+    up (&space->semaphore);
+    if (!was_set)
+	printk (KERN_ERR __FUNCTION__ "(): number %d was already free\n",
+		number);
+}   /*  End Function devfs_dealloc_unique_number  */
+EXPORT_SYMBOL(devfs_dealloc_unique_number);
diff -urN linux-2.4.7-pre6/fs/dquot.c linux/fs/dquot.c
--- linux-2.4.7-pre6/fs/dquot.c	Tue Jun 12 16:03:27 2001
+++ linux/fs/dquot.c	Mon Dec  3 22:55:50 2001
@@ -1467,7 +1467,7 @@
 	if (IS_ERR(f))
 		goto out_lock;
 	error = -EIO;
-	if (!f->f_op || (!f->f_op->read && !f->f_op->write))
+	if (!f->f_op || !f->f_op->read || !f->f_op->write)
 		goto out_f;
 	inode = f->f_dentry->d_inode;
 	error = -EACCES;
diff -urN linux-2.4.7-pre6/fs/exec.c linux/fs/exec.c
--- linux-2.4.7-pre6/fs/exec.c	Thu Apr 26 14:11:29 2001
+++ linux/fs/exec.c	Mon Dec  3 22:55:50 2001
@@ -927,12 +927,13 @@
 	char corename[6+sizeof(current->comm)];
 	struct file * file;
 	struct inode * inode;
+	int retval = 0;
 
 	lock_kernel();
 	binfmt = current->binfmt;
 	if (!binfmt || !binfmt->core_dump)
 		goto fail;
-	if (!current->dumpable || atomic_read(&current->mm->mm_users) != 1)
+	if (!current->dumpable)
 		goto fail;
 	current->dumpable = 0;
 	if (current->rlim[RLIMIT_CORE].rlim_cur < binfmt->min_coredump)
@@ -961,15 +962,14 @@
 		goto close_fail;
 	if (do_truncate(file->f_dentry, 0) != 0)
 		goto close_fail;
-	if (!binfmt->core_dump(signr, regs, file))
-		goto close_fail;
-	unlock_kernel();
-	filp_close(file, NULL);
-	return 1;
+
+	down_read(&current->mm->mmap_sem);
+	retval = binfmt->core_dump(signr, regs, file);
+	up_read(&current->mm->mmap_sem);
 
 close_fail:
 	filp_close(file, NULL);
 fail:
 	unlock_kernel();
-	return 0;
+	return retval;
 }
diff -urN linux-2.4.7-pre6/fs/ext2/balloc.c linux/fs/ext2/balloc.c
--- linux-2.4.7-pre6/fs/ext2/balloc.c	Fri Dec 29 14:36:44 2000
+++ linux/fs/ext2/balloc.c	Mon Dec  3 22:55:50 2001
@@ -174,7 +174,7 @@
 			sb->u.ext2_sb.s_loaded_block_bitmaps++;
 		else
 			brelse (sb->u.ext2_sb.s_block_bitmap[EXT2_MAX_GROUP_LOADED - 1]);
-		for (j = sb->u.ext2_sb.s_loaded_block_bitmaps - 1; j > 0;  j--) {
+		for (j = sb->u.ext2_sb.s_loaded_block_bitmaps - 1; j > 0; j--) {
 			sb->u.ext2_sb.s_block_bitmap_number[j] =
 				sb->u.ext2_sb.s_block_bitmap_number[j - 1];
 			sb->u.ext2_sb.s_block_bitmap[j] =
@@ -276,7 +276,7 @@
 		goto error_return;
 	}
 
-	ext2_debug ("freeing block %lu\n", block);
+	ext2_debug ("freeing block(s) %lu-%lu\n", block, block + count - 1);
 
 do_more:
 	overflow = 0;
@@ -315,8 +315,8 @@
 	for (i = 0; i < count; i++) {
 		if (!ext2_clear_bit (bit + i, bh->b_data))
 			ext2_error (sb, "ext2_free_blocks",
-				      "bit already cleared for block %lu", 
-				      block);
+				      "bit already cleared for block %lu",
+				      block + i);
 		else {
 			DQUOT_FREE_BLOCK(sb, inode, 1);
 			gdp->bg_free_blocks_count =
@@ -411,10 +411,7 @@
 		ext2_debug ("goal is at %d:%d.\n", i, j);
 
 		if (!ext2_test_bit(j, bh->b_data)) {
-#ifdef EXT2FS_DEBUG
-			goal_hits++;
-			ext2_debug ("goal bit allocated.\n");
-#endif
+			ext2_debug("goal bit allocated, %d hits\n",++goal_hits);
 			goto got_block;
 		}
 		if (j) {
@@ -471,10 +468,8 @@
 		if (i >= sb->u.ext2_sb.s_groups_count)
 			i = 0;
 		gdp = ext2_get_group_desc (sb, i, &bh2);
-		if (!gdp) {
-			*err = -EIO;
-			goto out;
-		}
+		if (!gdp)
+			goto io_error;
 		if (le16_to_cpu(gdp->bg_free_blocks_count) > 0)
 			break;
 	}
@@ -766,7 +761,7 @@
 		for (j = 0; j < sb->u.ext2_sb.s_itb_per_group; j++)
 			if (!block_in_use (le32_to_cpu(gdp->bg_inode_table) + j, sb, bh->b_data))
 				ext2_error (sb, "ext2_check_blocks_bitmap",
-					    "Block #%d of the inode table in "
+					    "Block #%ld of the inode table in "
 					    "group %d is marked free", j, i);
 
 		x = ext2_count_free (bh, sb->s_blocksize);
diff -urN linux-2.4.7-pre6/fs/ext2/dir.c linux/fs/ext2/dir.c
--- linux-2.4.7-pre6/fs/ext2/dir.c	Wed Jun 20 11:40:14 2001
+++ linux/fs/ext2/dir.c	Mon Dec  3 22:55:50 2001
@@ -363,7 +363,7 @@
 void ext2_set_link(struct inode *dir, struct ext2_dir_entry_2 *de,
 			struct page *page, struct inode *inode)
 {
-	unsigned from = (char *)de-(char*)page_address(page);
+	unsigned from = (char *) de - (char *) page_address(page);
 	unsigned to = from + le16_to_cpu(de->rec_len);
 	int err;
 
@@ -578,5 +578,6 @@
 struct file_operations ext2_dir_operations = {
 	read:		generic_read_dir,
 	readdir:	ext2_readdir,
+	ioctl:		ext2_ioctl,
 	fsync:		ext2_sync_file,
 };
diff -urN linux-2.4.7-pre6/fs/ext2/file.c linux/fs/ext2/file.c
--- linux-2.4.7-pre6/fs/ext2/file.c	Wed Sep 27 13:41:33 2000
+++ linux/fs/ext2/file.c	Mon Dec  3 22:55:50 2001
@@ -69,7 +69,7 @@
 
 /*
  * Called when an inode is released. Note that this is different
- * from ext2_file_open: open gets called at every open, but release
+ * from ext2_open_file: open gets called at every open, but release
  * gets called only when /all/ the files are closed.
  */
 static int ext2_release_file (struct inode * inode, struct file * filp)
diff -urN linux-2.4.7-pre6/fs/ext2/inode.c linux/fs/ext2/inode.c
--- linux-2.4.7-pre6/fs/ext2/inode.c	Mon Jun 11 19:15:27 2001
+++ linux/fs/ext2/inode.c	Mon Dec  3 22:55:50 2001
@@ -99,16 +99,12 @@
 		result = inode->u.ext2_i.i_prealloc_block++;
 		inode->u.ext2_i.i_prealloc_count--;
 		/* Writer: end */
-#ifdef EXT2FS_DEBUG
 		ext2_debug ("preallocation hit (%lu/%lu).\n",
 			    ++alloc_hits, ++alloc_attempts);
-#endif
 	} else {
 		ext2_discard_prealloc (inode);
-#ifdef EXT2FS_DEBUG
 		ext2_debug ("preallocation miss (%lu/%lu).\n",
 			    alloc_hits, ++alloc_attempts);
-#endif
 		if (S_ISREG(inode->i_mode))
 			result = ext2_new_block (inode, goal, 
 				 &inode->u.ext2_i.i_prealloc_count,
@@ -367,7 +363,7 @@
  *	be placed into *branch->p to fill that gap.
  *
  *	If allocation fails we free all blocks we've allocated (and forget
- *	ther buffer_heads) and return the error value the from failed
+ *	their buffer_heads) and return the error value the from failed
  *	ext2_alloc_block() (normally -ENOSPC). Otherwise we set the chain
  *	as described above and return 0.
  */
@@ -964,12 +960,10 @@
 	inode->u.ext2_i.i_frag_no = raw_inode->i_frag;
 	inode->u.ext2_i.i_frag_size = raw_inode->i_fsize;
 	inode->u.ext2_i.i_file_acl = le32_to_cpu(raw_inode->i_file_acl);
-	if (S_ISDIR(inode->i_mode))
-		inode->u.ext2_i.i_dir_acl = le32_to_cpu(raw_inode->i_dir_acl);
-	else {
-		inode->u.ext2_i.i_high_size = le32_to_cpu(raw_inode->i_size_high);
+	if (S_ISREG(inode->i_mode))
 		inode->i_size |= ((__u64)le32_to_cpu(raw_inode->i_size_high)) << 32;
-	}
+	else
+		inode->u.ext2_i.i_dir_acl = le32_to_cpu(raw_inode->i_dir_acl);
 	inode->i_generation = le32_to_cpu(raw_inode->i_generation);
 	inode->u.ext2_i.i_prealloc_count = 0;
 	inode->u.ext2_i.i_block_group = block_group;
@@ -1114,7 +1108,7 @@
 		raw_inode->i_dir_acl = cpu_to_le32(inode->u.ext2_i.i_dir_acl);
 	else {
 		raw_inode->i_size_high = cpu_to_le32(inode->i_size >> 32);
-		if (raw_inode->i_size_high) {
+		if (inode->i_size > 0x7fffffffULL) {
 			struct super_block *sb = inode->i_sb;
 			if (!EXT2_HAS_RO_COMPAT_FEATURE(sb,
 					EXT2_FEATURE_RO_COMPAT_LARGE_FILE) ||
diff -urN linux-2.4.7-pre6/fs/ext2/super.c linux/fs/ext2/super.c
--- linux-2.4.7-pre6/fs/ext2/super.c	Wed May 16 10:31:27 2001
+++ linux/fs/ext2/super.c	Mon Dec  3 22:55:50 2001
@@ -446,20 +446,17 @@
 		return NULL;
 	}
 	/*
-	 * Note: s_es must be initialized s_es as soon as possible because
-	 * some ext2 macro-instructions depend on its value
+	 * Note: s_es must be initialized as soon as possible because
+	 *       some ext2 macro-instructions depend on its value
 	 */
 	es = (struct ext2_super_block *) (((char *)bh->b_data) + offset);
 	sb->u.ext2_sb.s_es = es;
 	sb->s_magic = le16_to_cpu(es->s_magic);
 	if (sb->s_magic != EXT2_SUPER_MAGIC) {
 		if (!silent)
-			printk ("VFS: Can't find an ext2 filesystem on dev "
-				"%s.\n", bdevname(dev));
-	failed_mount:
-		if (bh)
-			brelse(bh);
-		return NULL;
+			printk ("VFS: Can't find ext2 filesystem on dev %s.\n",
+				bdevname(dev));
+		goto failed_mount;
 	}
 	if (le32_to_cpu(es->s_rev_level) == EXT2_GOOD_OLD_REV &&
 	    (EXT2_HAS_COMPAT_FEATURE(sb, ~0U) ||
@@ -622,11 +619,9 @@
 		}
 	}
 	if (!ext2_check_descriptors (sb)) {
-		for (j = 0; j < db_count; j++)
-			brelse (sb->u.ext2_sb.s_group_desc[j]);
-		kfree(sb->u.ext2_sb.s_group_desc);
-		printk ("EXT2-fs: group descriptors corrupted !\n");
-		goto failed_mount;
+		printk ("EXT2-fs: group descriptors corrupted!\n");
+		db_count = i;
+		goto failed_mount2;
 	}
 	for (i = 0; i < EXT2_MAX_GROUP_LOADED; i++) {
 		sb->u.ext2_sb.s_inode_bitmap_number[i] = 0;
@@ -642,17 +637,25 @@
 	 */
 	sb->s_op = &ext2_sops;
 	sb->s_root = d_alloc_root(iget(sb, EXT2_ROOT_INO));
-	if (!sb->s_root) {
-		for (i = 0; i < db_count; i++)
-			if (sb->u.ext2_sb.s_group_desc[i])
-				brelse (sb->u.ext2_sb.s_group_desc[i]);
-		kfree(sb->u.ext2_sb.s_group_desc);
-		brelse (bh);
-		printk ("EXT2-fs: get root inode failed\n");
-		return NULL;
+	if (!sb->s_root || !S_ISDIR(sb->s_root->d_inode->i_mode) ||
+	    !sb->s_root->d_inode->i_blocks || !sb->s_root->d_inode->i_size) {
+		if (sb->s_root) {
+			dput(sb->s_root);
+			sb->s_root = NULL;
+			printk ("EXT2-fs: corrupt root inode, run e2fsck\n");
+		} else
+			printk ("EXT2-fs: get root inode failed\n");
+		goto failed_mount2;
 	}
 	ext2_setup_super (sb, es, sb->s_flags & MS_RDONLY);
 	return sb;
+failed_mount2:
+	for (i = 0; i < db_count; i++)
+		brelse(sb->u.ext2_sb.s_group_desc[i]);
+	kfree(sb->u.ext2_sb.s_group_desc);
+failed_mount:
+	brelse(bh);
+	return NULL;
 }
 
 static void ext2_commit_super (struct super_block * sb,
diff -urN linux-2.4.7-pre6/fs/namei.c linux/fs/namei.c
--- linux-2.4.7-pre6/fs/namei.c	Tue Jul  3 08:05:42 2001
+++ linux/fs/namei.c	Mon Dec  3 22:55:50 2001
@@ -886,7 +886,7 @@
 {
 	int error;
 
-	mode &= S_IALLUGO & ~current->fs->umask;
+	mode &= S_IALLUGO;
 	mode |= S_IFREG;
 
 	down(&dir->i_zombie);
@@ -975,7 +975,8 @@
 
 	/* Negative dentry, just create the file */
 	if (!dentry->d_inode) {
-		error = vfs_create(dir->d_inode, dentry, mode);
+		error = vfs_create(dir->d_inode, dentry,
+				   mode & ~current->fs->umask);
 		up(&dir->d_inode->i_sem);
 		dput(nd->dentry);
 		nd->dentry = dentry;
@@ -1164,8 +1165,6 @@
 {
 	int error = -EPERM;
 
-	mode &= ~current->fs->umask;
-
 	down(&dir->i_zombie);
 	if ((S_ISCHR(mode) || S_ISBLK(mode)) && !capable(CAP_MKNOD))
 		goto exit_lock;
@@ -1208,6 +1207,8 @@
 		goto out;
 	dentry = lookup_create(&nd, 0);
 	error = PTR_ERR(dentry);
+
+	mode &= ~current->fs->umask;
 	if (!IS_ERR(dentry)) {
 		switch (mode & S_IFMT) {
 		case 0: case S_IFREG:
@@ -1246,7 +1247,7 @@
 		goto exit_lock;
 
 	DQUOT_INIT(dir);
-	mode &= (S_IRWXUGO|S_ISVTX) & ~current->fs->umask;
+	mode &= (S_IRWXUGO|S_ISVTX);
 	lock_kernel();
 	error = dir->i_op->mkdir(dir, dentry, mode);
 	unlock_kernel();
@@ -1276,7 +1277,8 @@
 		dentry = lookup_create(&nd, 1);
 		error = PTR_ERR(dentry);
 		if (!IS_ERR(dentry)) {
-			error = vfs_mkdir(nd.dentry->d_inode, dentry, mode);
+			error = vfs_mkdir(nd.dentry->d_inode, dentry,
+					  mode & ~current->fs->umask);
 			dput(dentry);
 		}
 		up(&nd.dentry->d_inode->i_sem);
diff -urN linux-2.4.7-pre6/fs/ntfs/Makefile linux/fs/ntfs/Makefile
--- linux-2.4.7-pre6/fs/ntfs/Makefile	Wed Apr 18 11:49:13 2001
+++ linux/fs/ntfs/Makefile	Mon Dec  3 22:55:50 2001
@@ -2,10 +2,10 @@
 
 O_TARGET := ntfs.o
 
-obj-y   := fs.o sysctl.o support.o util.o inode.o dir.o super.o attr.o
+obj-y   := fs.o sysctl.o support.o util.o inode.o dir.o super.o attr.o unistr.o
 obj-m   := $(O_TARGET)
-# Version format: YYMMDD
-EXTRA_CFLAGS = -DNTFS_IN_LINUX_KERNEL -DNTFS_VERSION=\"010116\"
+# New version format started 3 February 2001.
+EXTRA_CFLAGS = -DNTFS_VERSION=\"1.1.15\" #-DDEBUG
 
 include $(TOPDIR)/Rules.make
 
diff -urN linux-2.4.7-pre6/fs/ntfs/attr.c linux/fs/ntfs/attr.c
--- linux-2.4.7-pre6/fs/ntfs/attr.c	Wed Apr 18 11:49:13 2001
+++ linux/fs/ntfs/attr.c	Mon Dec  3 22:55:50 2001
@@ -1,10 +1,11 @@
-/*  attr.c
+/*
+ * attr.c
  *
- *  Copyright (C) 1996-1999 Martin von Löwis
- *  Copyright (C) 1996-1997 Régis Duchesne
- *  Copyright (C) 1998 Joseph Malicki
- *  Copyright (C) 1999 Steve Dodd
- *  Copyright (C) 2001 Anton Altaparmakov (AIA)
+ * Copyright (C) 1996-1999 Martin von Löwis
+ * Copyright (C) 1996-1997 Régis Duchesne
+ * Copyright (C) 1998 Joseph Malicki
+ * Copyright (C) 1999 Steve Dodd
+ * Copyright (C) 2001 Anton Altaparmakov (AIA)
  */
 
 #include "ntfstypes.h"
@@ -17,37 +18,156 @@
 #include "util.h"
 #include "super.h"
 #include "inode.h"
+#include "unistr.h"
+
+/**
+ * ntfs_find_attr_in_mft_rec - find attribute in mft record
+ * @vol:	volume on which attr resides
+ * @m:		mft record to search
+ * @type:	attribute type to find
+ * @name:	attribute name to find (optional, i.e. NULL means don't care)
+ * @name_len:	attribute name length (only needed if @name present)
+ * @ic:		ignore case if 1 or case sensitive if 0 (ignored if @name NULL)
+ * @instance:	instance number to find
+ *
+ * Only search the specified mft record and it ignores the presence of an
+ * attribute list attribute (unless it is the one being searched for,
+ * obviously, in which case it is returned).
+ */
+ntfs_u8* ntfs_find_attr_in_mft_rec(ntfs_volume *vol, ntfs_u8 *m, __u32 type,
+		wchar_t *name, __u32 name_len, int ic, __u16 instance)
+{
+	ntfs_u8 *a;
+	
+	/* Iterate over attributes in mft record @m. */
+	a = m + NTFS_GETU16(m + 20);	/* attrs_offset */
+	for (; a >= m && a <= m + vol->mft_record_size;
+				a += NTFS_GETU32(a + 4 /* length */)) {
+		/* We catch $END with this more general check, too... */
+		if (NTFS_GETU32(a + 0 /* type */) > type)
+			return NULL;
+		if (!NTFS_GETU32(a + 4 /* length */))
+			break;
+		if (NTFS_GETU32(a + 0 /* type */) != type)
+			continue;
+		/* If @name is present, compare the two names. */
+		if (name && !ntfs_are_names_equal(name, name_len, (wchar_t*)
+				(a + NTFS_GETU16(a + 10 /* name_offset */)),
+				a[9] /* name_length */, ic, vol->upcase,
+				vol->upcase_length)) {
+			register int rc;
+			
+			rc = ntfs_collate_names(vol->upcase, vol->upcase_length,
+					name, name_len, (wchar_t*)(a +
+					NTFS_GETU16(a + 10 /* name_offset */)),
+					a[9] /* name_length */, 1, 1);
+			/*
+			 * If @name collates before a->name, there is no
+			 * matching attribute.
+			 */
+			if (rc == -1)
+				return NULL;
+			/* If the strings are not equal, continue search. */
+			if (rc)
+	 			continue;
+			rc = ntfs_collate_names(vol->upcase, vol->upcase_length,
+					name, name_len, (wchar_t*)(a +
+					NTFS_GETU16(a + 10 /* name_offset */)),
+					a[9] /* name_length */, 0, 1);
+			if (rc == -1)
+				return NULL;
+			if (rc)
+				continue;
+		}
+		/*
+		 * The names match or @name not present. Check instance number.
+		 * and if it matches we have found the attribute and are done.
+		 */
+		if (instance != NTFS_GETU16(a + 14 /* instance */))
+			continue;
+		ntfs_debug(DEBUG_FILE3, "ntfs_find_attr_in_mft_record: found: "
+			"attr type 0x%x, instance number = 0x%x.\n",
+			NTFS_GETU32(a + 0), instance);
+		return a;
+	}
+	ntfs_error("ntfs_find_attr_in_mft_record: mft record 0x%x is corrupt"
+			". Run chkdsk.\n", m);
+	return NULL;
+}
 
 /* Look if an attribute already exists in the inode, and if not, create it. */
-int ntfs_new_attr(ntfs_inode *ino, int type, void *name, int namelen, int *pos,
-		  int *found, int do_search)
+int ntfs_new_attr(ntfs_inode *ino, int type, void *name, int namelen,
+		  void *value, int value_len, int *pos, int *found)
 {
 	int do_insert = 0;
-	int i;
+	int i, m;
+	ntfs_attribute *a;
 
 	for (i = 0; i < ino->attr_count; i++)
 	{
-		int n = min(namelen, ino->attrs[i].namelen);
-		int s = ntfs_uni_strncmp(ino->attrs[i].name, name, n);
-		if (do_search) {
-			/* We assume that each attribute can be uniquely 
-			 * identified by inode number, attribute type and
-			 * attribute name. */
-			if (ino->attrs[i].type == type && 
-			    ino->attrs[i].namelen == namelen && !s) {
-				*found = 1;
-				*pos = i;
-				return 0;
-			}
-		}
-		/* Attributes are ordered by type, then by name. */
-		if (ino->attrs[i].type > type || 
-		    (ino->attrs[i].type == type && s == 1)) {
+		a = ino->attrs + i;
+		if (a->type < type)
+			continue;
+		if (a->type > type) {
 			do_insert = 1;
 			break;
 		}
+		/* If @name is present, compare the two names. */
+		if (namelen && !ntfs_are_names_equal((wchar_t*)name, namelen,
+				a->name, a->namelen /* name_length */,
+				1 /* ignore case*/, ino->vol->upcase,
+				ino->vol->upcase_length)) {
+			register int rc;
+
+			rc = ntfs_collate_names(ino->vol->upcase,
+					ino->vol->upcase_length, a->name,
+					a->namelen, (wchar_t*)name, namelen,
+					1 /* ignore case */, 1);
+			if (rc == -1)
+				continue;
+			if (rc == 1) {
+	 			do_insert = 1;
+				break;
+			}
+			rc = ntfs_collate_names(ino->vol->upcase,
+					ino->vol->upcase_length, a->name,
+					a->namelen, (wchar_t*)name, namelen,
+					0 /* case sensitive */, 1);
+			if (rc == -1)
+				continue;
+			if (rc == 1) {
+				do_insert = 1;
+				break;
+			}
+		}
+		/* Names are equal or no name was asked for. */
+		/* If a value was specified compare the values. */
+		if (value_len && a->resident) {
+			if (!a->resident) {
+				ntfs_error("ntfs_new_attr: Value specified but "
+					"attribute non-resident. Bug!\n");
+				return -EINVAL;
+			}
+			m = memcmp(value, a->d.data, min(value_len, a->size));
+			if (m > 0)
+				continue;
+			if (m < 0) {
+				do_insert = 1;
+				break;
+			}
+			/* Values match until min of value lengths. */
+			if (value_len > a->size)
+				continue;
+			if (value_len < a->size) {
+				do_insert = 1;
+				break;
+			}
+		}
+		/* Full match! */
+		*found = 1;
+		*pos = i;
+		return 0;
 	}
-
 	/* Re-allocate space. */
 	if (ino->attr_count % 8 == 0)
 	{
@@ -77,7 +197,7 @@
 
 int ntfs_make_attr_resident(ntfs_inode *ino, ntfs_attribute *attr)
 {
-	int size = attr->size;
+	__s64 size = attr->size;
 	if (size > 0) {
 		/* FIXME: read data, free clusters */
 		return -EOPNOTSUPP;
@@ -87,19 +207,35 @@
 }
 
 /* Store in the inode readable information about a run. */
-void ntfs_insert_run(ntfs_attribute *attr, int cnum, ntfs_cluster_t cluster,
+int ntfs_insert_run(ntfs_attribute *attr, int cnum, ntfs_cluster_t cluster,
 		     int len)
 {
 	/* (re-)allocate space if necessary. */
-	if (attr->d.r.len % 8 == 0) {
+	if ((attr->d.r.len * sizeof(ntfs_runlist)) % PAGE_SIZE == 0) {
 		ntfs_runlist* new;
-		new = ntfs_malloc((attr->d.r.len + 8) * sizeof(ntfs_runlist));
-		if (!new)
-			return;
+		unsigned long new_size;
+
+		ntfs_debug(DEBUG_MALLOC, "ntfs_insert_run: re-allocating "
+				"space: old attr->d.r.len = 0x%x\n",
+				attr->d.r.len);
+		new_size = attr->d.r.len * sizeof(ntfs_runlist) + PAGE_SIZE;
+		if ((new_size >> PAGE_SHIFT) > num_physpages) {
+			ntfs_error("ntfs_insert_run: attempted to allocate "
+					"more pages than num_physpages."
+					"This might be a bug or a corrupt"
+					"file system.\n");
+			return -1;
+		}
+		new = ntfs_vmalloc(new_size);
+		if (!new) {
+			ntfs_error("ntfs_insert_run: ntfs_vmalloc(new_size = "
+					"0x%x) failed\n", new_size);
+			return -1;
+		}
 		if (attr->d.r.runlist) {
 			ntfs_memcpy(new, attr->d.r.runlist, attr->d.r.len
 							* sizeof(ntfs_runlist));
-			ntfs_free(attr->d.r.runlist);
+			ntfs_vfree(attr->d.r.runlist);
 		}
 		attr->d.r.runlist = new;
 	}
@@ -110,6 +246,7 @@
 	attr->d.r.runlist[cnum].cluster = cluster;
 	attr->d.r.runlist[cnum].len = len;
 	attr->d.r.len++;
+	return 0;
 }
 
 /* Extends an attribute. Another run will be added if necessary, but we try to
@@ -119,7 +256,7 @@
  *
  * *len: the desired new length of the attr (_not_ the amount to extend by)
  */
-int ntfs_extend_attr(ntfs_inode *ino, ntfs_attribute *attr, int *len, int flags)
+int ntfs_extend_attr(ntfs_inode *ino, ntfs_attribute *attr, __s64 *len, int flags)
 {
 	int error = 0;
 	ntfs_runlist *rl;
@@ -145,8 +282,8 @@
 		cluster = 0;
 	/* Calculate the extra space we need, and round up to multiple of
 	 * cluster size to get number of new clusters needed */
-	clen = ((*len - attr->allocated) + ino->vol->clustersize - 1) /
-		ino->vol->clustersize;
+	clen = ((*len - attr->allocated) + ino->vol->cluster_size - 1) >>
+						ino->vol->cluster_size_bits;
 	if (clen == 0)
 		return 0;
 	/* FIXME: try to allocate smaller pieces */
@@ -154,13 +291,17 @@
 				       flags | ALLOC_REQUIRE_SIZE);
 	if (error)
 		return error;
-	attr->allocated += clen * ino->vol->clustersize;
+	attr->allocated += (__s64)clen << ino->vol->cluster_size_bits;
 	*len = attr->allocated;
 	/* Contiguous chunk. */
 	if (rlen >= 0 && cluster == rl[rlen].cluster + rl[rlen].len) {
 		rl[rlen].len += clen;
 		return 0;
 	}
+	/*
+	 * FIXME: if ntfs_insert_run fails we need to deallocate the cluster
+	 * to revert to state before we were called...
+	 */
 	ntfs_insert_run(attr, rlen + 1, cluster, clen);
 	return 0;
 }
@@ -168,13 +309,14 @@
 int ntfs_make_attr_nonresident(ntfs_inode *ino, ntfs_attribute *attr)
 {
 	void *data = attr->d.data;
-	int len = attr->size;
-	int error, alen;
+	__s64 len = attr->size;
+	int error;
+	__s64 alen;
 	ntfs_io io;
 	attr->d.r.len = 0;
 	attr->d.r.runlist = 0;
 	attr->resident = 0;
-	attr->allocated=attr->initialized = 0;
+	attr->allocated = attr->initialized = 0;
 	alen = len;
 	error = ntfs_extend_attr(ino, attr, &alen, ALLOC_REQUIRE_SIZE);
 	if (error)
@@ -203,13 +345,14 @@
 }
 
 /* Resize the attribute to a newsize. */
-int ntfs_resize_attr(ntfs_inode *ino, ntfs_attribute *attr, int newsize)
+int ntfs_resize_attr(ntfs_inode *ino, ntfs_attribute *attr, __s64 newsize)
 {
 	int error = 0;
-	int oldsize = attr->size;
-	int clustersize = ino->vol->clustersize;
-	int i, count, newlen, newcount;
+	__s64 oldsize = attr->size;
+	int clustersizebits = ino->vol->cluster_size_bits;
+	int i, count, newcount;
 	ntfs_runlist *rl;
+	__s64 newlen;
 
 	if (newsize == oldsize)
 		return 0;
@@ -219,7 +362,7 @@
 		return -EOPNOTSUPP;
 	if (attr->resident) {
 		void *v;
-		if (newsize > ino->vol->mft_recordsize) {
+		if (newsize > ino->vol->mft_record_size) {
 			error = ntfs_make_attr_nonresident(ino, attr);
 			if (error)
 				return error;
@@ -247,16 +390,19 @@
 	rl = attr->d.r.runlist;
 	if (newsize < oldsize) {
 		for (i = 0, count = 0; i < attr->d.r.len; i++) {
-			if ((count + rl[i].len) * clustersize > newsize)
+			if ((__s64)(count + rl[i].len) << clustersizebits >
+									newsize)
 				break;
 			count += (int)rl[i].len;
 		}
 		newlen = i + 1;
 		/* Free unused clusters in current run, unless sparse. */
 		newcount = count;
-		if (rl[i].cluster != MAX_CLUSTER_T) {
-			int rounded = newsize - count * clustersize;
-			rounded = (rounded + clustersize - 1) / clustersize;
+		if (rl[i].cluster != (ntfs_cluster_t)-1) {
+			int rounded = newsize - ((__s64)count <<
+							clustersizebits);
+			rounded = (rounded + ino->vol->cluster_size - 1) >>
+								clustersizebits;
 			error = ntfs_deallocate_clusters(ino->vol, 
 						rl[i].cluster + rounded,
 						(int)rl[i].len - rounded);
@@ -267,7 +413,7 @@
 		}
 		/* Free all other runs. */
 		for (i++; i < attr->d.r.len; i++)
-			if (rl[i].cluster != MAX_CLUSTER_T) {
+			if (rl[i].cluster != (ntfs_cluster_t)-1) {
 				error = ntfs_deallocate_clusters(ino->vol,
 								rl[i].cluster,
 								(int)rl[i].len);
@@ -283,10 +429,10 @@
 					 ALLOC_REQUIRE_SIZE);
 		if (error)
 			return error; /* FIXME: Incomplete operation. */
-		newcount = newlen / clustersize;
+		newcount = newlen >> clustersizebits;
 	}
 	/* Fill in new sizes. */
-	attr->allocated = newcount * clustersize;
+	attr->allocated = (__s64)newcount << clustersizebits;
 	attr->size = newsize;
 	/* attr->initialized does not change. */
 	if (!newsize)
@@ -303,7 +449,7 @@
 	int error;
 	ntfs_attribute *attr;
 	
-	if (dsize > ino->vol->mft_recordsize)
+	if (dsize > ino->vol->mft_record_size)
 		/* FIXME: Non-resident attributes. */
 		return -EOPNOTSUPP;
 	if (aname) {
@@ -316,14 +462,11 @@
 		name = 0;
 		namelen = 0;
 	}
-	error = ntfs_new_attr(ino, anum, name, namelen, &i, &found, 1);
-	if (error) {
+	error = ntfs_new_attr(ino, anum, name, namelen, data, dsize, &i,
+									&found);
+	if (error || found) {
 		ntfs_free(name);
-		return error;
-	}
-	if (found) {
-		ntfs_free(name);
-		return -EEXIST;
+		return error ? error : -EEXIST;
 	}
 	*rattr = attr = ino->attrs + i;
 	/* Allocate a new number.
@@ -333,6 +476,10 @@
 	if (error)
 		return error;
 	attr->attrno = i;
+	if (attr->attrno + 1 != NTFS_GETU16(ino->attr + 0x28))
+		ntfs_error("UH OH! attr->attrno (%i) != NTFS_GETU16(ino->attr "
+				"+ 0x28) (%i)\n", attr->attrno,
+				NTFS_GETU16(ino->attr + 0x28));
 	attr->resident = 1;
 	attr->compressed = attr->cengine = 0;
 	attr->size = attr->allocated = attr->initialized = dsize;
@@ -340,9 +487,9 @@
 	/* FIXME: INDEXED information should come from $AttrDef
 	 * Currently, only file names are indexed. As of NTFS v3.0 (Win2k),
 	 * this is no longer true. Different attributes can be indexed now. */
-	if (anum == ino->vol->at_file_name) {
+	if (anum == ino->vol->at_file_name)
 		attr->indexed = 1;
-	} else
+	else
 		attr->indexed = 0;
 	attr->d.data = ntfs_malloc(dsize);
 	if (!attr->d.data)
@@ -354,7 +501,8 @@
 /* Non-resident attributes are stored in runs (intervals of clusters).
  *
  * This function stores in the inode readable information about a non-resident
- * attribute. */
+ * attribute.
+ */
 static int ntfs_process_runs(ntfs_inode *ino, ntfs_attribute* attr,
 			     unsigned char *data)
 {
@@ -362,33 +510,71 @@
 	int vcn, cnum;
 	ntfs_cluster_t cluster;
 	int len, ctype;
-	startvcn = NTFS_GETU64(data + 0x10);
-	endvcn = NTFS_GETU64(data + 0x18);
-
-	/* Check whether this chunk really belongs to the end. */
+	int er = 0;
+	startvcn = NTFS_GETS64(data + 0x10);
+	endvcn = NTFS_GETS64(data + 0x18);
+
+	/* Check whether this chunk really belongs to the end. Problem with
+	 * this: this functions can get called on the last extent first, before
+	 * it is called on the other extents in sequence. This happens when the
+	 * base mft record contains the last extent instead of the first one
+	 * and the first extent is stored, like any intermediate extents in
+	 * extension mft records. This would be difficult to allow the way the
+	 * run list is stored in memory. Thus we fix else where by causing the
+	 * attribute list attribute to be processed immediately when found. The
+	 * extents will then be processed starting with the first one. */
 	for (cnum = 0, vcn = 0; cnum < attr->d.r.len; cnum++)
 		vcn += attr->d.r.runlist[cnum].len;
 	if (vcn != startvcn) {
-		ntfs_error("Problem with runlist in extended record\n");
-		return -1;
+		ntfs_debug(DEBUG_FILE3, "ntfs_process_runs: ino = 0x%x, "
+			"attr->type = 0x%x, startvcn = 0x%x, endvcn = 0x%x, "
+			"vcn = 0x%x, cnum = 0x%x\n", ino->i_number, attr->type,
+			startvcn, endvcn, vcn, cnum);
+		if (vcn < startvcn) {
+			ntfs_error("Problem with runlist in extended record\n");
+			return -1;
+		}
+		/* Tried to insert an already inserted run list. */
+		return 0;
 	}
 	if (!endvcn) {
-		endvcn = NTFS_GETU64(data + 0x28) - 1; /* Allocated length. */
-		endvcn /= ino->vol->clustersize;
+		if (!startvcn) {
+			/* Allocated length. */
+			endvcn = NTFS_GETS64(data + 0x28) - 1;
+			endvcn >>= ino->vol->cluster_size_bits;
+		} else {
+			/* This is an extent. Allocated length is not defined!
+			 * Extents must have an endvcn though so this is an
+			 * error. */
+			ntfs_error("Corrupt attribute extent. (endvcn is "
+				"missing)\n");
+			return -1;
+		}
 	}
 	data = data + NTFS_GETU16(data + 0x20);
 	cnum = attr->d.r.len;
 	cluster = 0;
 	for (vcn = startvcn; vcn <= endvcn; vcn += len)	{
-		if (ntfs_decompress_run(&data, &len, &cluster, &ctype))
+		if (ntfs_decompress_run(&data, &len, &cluster, &ctype)) {
+			ntfs_debug(DEBUG_FILE3, "ntfs_process_runs: "
+				"ntfs_decompress_run failed. i_number = 0x%x\n",
+				ino->i_number);
 			return -1;
+		}
 		if (ctype)
-			ntfs_insert_run(attr, cnum, -1, len);
+			er = ntfs_insert_run(attr, cnum, -1, len);
 		else
-			ntfs_insert_run(attr, cnum, cluster, len);
+			er = ntfs_insert_run(attr, cnum, cluster, len);
+		if (er)
+			break;
 		cnum++;
 	}
-	return 0;
+	if (er)
+		ntfs_error("ntfs_process_runs: ntfs_insert_run failed\n");
+	ntfs_debug(DEBUG_FILE3, "ntfs_process_runs: startvcn = 0x%x, vcn = 0x%x"
+				", endvcn = 0x%x, cnum = %i\n", startvcn, vcn,
+				endvcn, cnum);
+	return er;
 }
   
 /* Insert the attribute starting at attr in the inode ino. */
@@ -404,6 +590,8 @@
 
 	type = NTFS_GETU32(attrdata);
 	namelen = NTFS_GETU8(attrdata + 9);
+	ntfs_debug(DEBUG_FILE3, "ntfs_insert_attribute: ino->i_number 0x%x, "
+			"attr type 0x%x\n", ino->i_number, type);
 	/* Read the attribute's name if it has one. */
 	if (!namelen)
 		name = 0;
@@ -415,25 +603,30 @@
 		ntfs_memcpy(name, attrdata + NTFS_GETU16(attrdata + 10),
 			    2 * namelen);
 	}
-	error = ntfs_new_attr(ino, type, name, namelen, &i, &found, 1);
+	/* If resident look for value, too. */
+	if (NTFS_GETU8(attrdata + 8) == 0)
+		error = ntfs_new_attr(ino, type, name, namelen,
+				attrdata + NTFS_GETU16(attrdata + 0x14),
+				NTFS_GETU16(attrdata + 0x10), &i, &found);
+	else
+		error = ntfs_new_attr(ino, type, name, namelen, NULL, 0, &i,
+				&found);
 	if (error) {
+		ntfs_debug(DEBUG_FILE3, "ntfs_insert_attribute: ntfs_new_attr "
+				"failed.\n");
 		if (name)
 			ntfs_free(name);
 		return error;
 	}
-	/* We can have in one inode two attributes with type 0x00000030 (File
-	 * Name) and without name. FIXME: We can have a lot more than two!
-	 * That is how hard links are implemented. (AIA) */
-	if (found && /*FIXME*/ type != ino->vol->at_file_name)
-	{
-		ntfs_process_runs(ino, ino->attrs + i, attrdata);
+	if (found) {
+		/* It's already there, if not resident just process the runs. */
+		if (!ino->attrs[i].resident) {
+			ntfs_debug(DEBUG_FILE3, "ntfs_insert_attribute:"
+						" processing runs 1.\n");
+			/* FIXME: Check error code! (AIA) */
+			ntfs_process_runs(ino, ino->attrs + i, attrdata);
+		}
 		return 0;
- 	} else if (found) {
- 		/* Don't understand the above, but I know it leaks memory below
-		 * as it overwrites a found entry without freeing it. So here
-		 * we call ntfs_new_attr again but this time ask it to always
-		 * allocate a new entry. */
- 		ntfs_new_attr(ino, type, name, namelen, &i, &found, 0);
 	}
 	attr = ino->attrs + i;
 	attr->resident = NTFS_GETU8(attrdata + 8) == 0;
@@ -449,14 +642,21 @@
 		ntfs_memcpy(attr->d.data, data, attr->size);
 		attr->indexed = NTFS_GETU16(attrdata + 0x16);
 	} else {
-		attr->allocated = NTFS_GETU32(attrdata + 0x28);
-		attr->size = NTFS_GETU32(attrdata + 0x30);
-		attr->initialized = NTFS_GETU32(attrdata + 0x38);
+		attr->allocated = NTFS_GETS64(attrdata + 0x28);
+		attr->size = NTFS_GETS64(attrdata + 0x30);
+		attr->initialized = NTFS_GETS64(attrdata + 0x38);
 		attr->cengine = NTFS_GETU16(attrdata + 0x22);
 		if (attr->compressed)
-			attr->compsize = NTFS_GETU32(attrdata + 0x40);
+			attr->compsize = NTFS_GETS64(attrdata + 0x40);
+		ntfs_debug(DEBUG_FILE3, "ntfs_insert_attribute: "
+			"attr->allocated = 0x%Lx, attr->size = 0x%Lx, "
+			"attr->initialized = 0x%Lx\n", attr->allocated,
+			attr->size, attr->initialized);
 		ino->attrs[i].d.r.runlist = 0;
 		ino->attrs[i].d.r.len = 0;
+		ntfs_debug(DEBUG_FILE3, "ntfs_insert_attribute: processing "
+				"runs 2.\n");
+		/* FIXME: Check error code! (AIA) */
 		ntfs_process_runs(ino, attr, attrdata);
 	}
 	return 0;
@@ -477,12 +677,13 @@
 }
 
 /* Process compressed attributes. */
-int ntfs_read_compressed(ntfs_inode *ino, ntfs_attribute *attr, int offset,
+int ntfs_read_compressed(ntfs_inode *ino, ntfs_attribute *attr, __s64 offset,
 			 ntfs_io *dest)
 {
 	int error = 0;
-	int clustersize, l;
-	int s_vcn, rnum, vcn, len, chunk, got, l1, offs1, copied;
+	int clustersizebits;
+	int s_vcn, rnum, vcn, got, l1;
+	__s64 copied, len, chunk, offs1, l;
 	ntfs_cluster_t cluster, cl1;
 	char *comp = 0, *comp1;
 	char *decomp = 0;
@@ -490,13 +691,13 @@
 	ntfs_runlist *rl;
 
 	l = dest->size;
-	clustersize = ino->vol->clustersize;
+	clustersizebits = ino->vol->cluster_size_bits;
 	/* Starting cluster of potential chunk. There are three situations:
 	   a) In a large uncompressible or sparse chunk, s_vcn is in the middle
 	      of a run.
 	   b) s_vcn is right on a run border.
 	   c) When several runs make a chunk, s_vcn is before the chunks. */
-	s_vcn = offset / clustersize;
+	s_vcn = offset >> clustersizebits;
 	/* Round down to multiple of 16. */
 	s_vcn &= ~15;
 	rl = attr->d.r.runlist;
@@ -517,18 +718,19 @@
 	copied = 0;
 	while (l) {
 		chunk = 0;
-		if (cluster == MAX_CLUSTER_T) {
+		if (cluster == (ntfs_cluster_t)-1) {
 			/* Sparse cluster. */
-			int l1;
+			__s64 l1;
 			if ((len - (s_vcn - vcn)) & 15)
 				ntfs_error("Unexpected sparse chunk size.");
-			l1 = chunk = min((vcn + len) * clustersize - offset, l);
+			l1 = chunk = min(((__s64)(vcn + len) << clustersizebits)
+								- offset, l);
 			error = ntfs_read_zero(dest, l1);
 			if (error)
 				goto out;
 		} else if (dest->do_read) {
 			if (!comp) {
-				comp = ntfs_malloc(16 * clustersize);
+				comp = ntfs_malloc(16 << clustersizebits);
 				if (!comp) {
 					error = -ENOMEM;
 					goto out;
@@ -541,7 +743,7 @@
 			do {
 				io.param = comp1;
 				l1 = min(len - max(s_vcn - vcn, 0), 16 - got);
-				io.size = l1 * clustersize;
+				io.size = (__s64)l1 << clustersizebits;
 				error = ntfs_getput_clusters(ino->vol, cl1, 0,
 					       		     &io);
 				if (error)
@@ -554,16 +756,17 @@
 					len = rl->len;
 				}
 				got += l1;
-				comp1 += l1 * clustersize;
-			} while (cluster != MAX_CLUSTER_T && got < 16);
+				comp1 += (__s64)l1 << clustersizebits;
+			} while (cluster != (ntfs_cluster_t)-1 && got < 16);
 							/* Until empty run. */
-			chunk = 16 * clustersize;
-			if (cluster != MAX_CLUSTER_T || got == 16)
+			chunk = 16 << clustersizebits;
+			if (cluster != (ntfs_cluster_t)-1 || got == 16)
 				/* Uncompressible */
 				comp1 = comp;
 			else {
 				if (!decomp) {
-					decomp = ntfs_malloc(16 * clustersize);
+					decomp = ntfs_malloc(16 << 
+							clustersizebits);
 					if (!decomp) {
 						error = -ENOMEM;
 						goto out;
@@ -575,16 +778,16 @@
 				ntfs_decompress(decomp, comp, chunk);
 				comp1 = decomp;
 			}
-			offs1 = offset - s_vcn * clustersize;
-			chunk = min(16 * clustersize - offs1, chunk);
+			offs1 = offset - ((__s64)s_vcn << clustersizebits);
+			chunk = min((16 << clustersizebits) - offs1, chunk);
 			chunk = min(l, chunk);
 			dest->fn_put(dest, comp1 + offs1, chunk);
 		}
 		l -= chunk;
 		copied += chunk;
 		offset += chunk;
-		s_vcn = offset / clustersize & ~15;
-		if (l && offset >= ((vcn + len) * clustersize)) {
+		s_vcn = (offset >> clustersizebits) & ~15;
+		if (l && offset >= ((__s64)(vcn + len) << clustersizebits)) {
 			rnum++;
 			rl++;
 			vcn += len;
@@ -601,7 +804,7 @@
 	return error;
 }
 
-int ntfs_write_compressed(ntfs_inode *ino, ntfs_attribute *attr, int offset,
+int ntfs_write_compressed(ntfs_inode *ino, ntfs_attribute *attr, __s64 offset,
 			  ntfs_io *dest)
 {
 	return -EOPNOTSUPP;
diff -urN linux-2.4.7-pre6/fs/ntfs/attr.h linux/fs/ntfs/attr.h
--- linux-2.4.7-pre6/fs/ntfs/attr.h	Wed Apr 18 11:49:13 2001
+++ linux/fs/ntfs/attr.h	Mon Dec  3 22:55:50 2001
@@ -1,19 +1,25 @@
-/*  attr.h -  Header file for attr.c
+/*
+ * attr.h -  Header file for attr.c
  *
- *  Copyright (C) 1997 Régis Duchesne
+ * Copyright (C) 1997 Régis Duchesne
+ * Copyright (c) 2001 Anton Altaparmakov (AIA)
  */
+#include <linux/nls.h>
 
-int ntfs_extend_attr(ntfs_inode *ino, ntfs_attribute *attr, int *len,
+ntfs_u8* ntfs_find_attr_in_mft_rec(ntfs_volume *vol, ntfs_u8 *m, __u32 type,
+			wchar_t *name, __u32 name_len, int ic, __u16 instance);
+
+int ntfs_extend_attr(ntfs_inode *ino, ntfs_attribute *attr, __s64 *len,
 		     int flags);
 
-int ntfs_resize_attr(ntfs_inode *ino, ntfs_attribute *attr, int newsize);
+int ntfs_resize_attr(ntfs_inode *ino, ntfs_attribute *attr, __s64 newsize);
 
 int ntfs_insert_attribute(ntfs_inode *ino, unsigned char* attrdata);
 
-int ntfs_read_compressed(ntfs_inode *ino, ntfs_attribute *attr, int offset,
+int ntfs_read_compressed(ntfs_inode *ino, ntfs_attribute *attr, __s64 offset,
 			 ntfs_io *dest);
 
-int ntfs_write_compressed(ntfs_inode *ino, ntfs_attribute *attr, int offset,
+int ntfs_write_compressed(ntfs_inode *ino, ntfs_attribute *attr, __s64 offset,
 			  ntfs_io *dest);
 
 int ntfs_create_attr(ntfs_inode *ino, int anum, char *aname, void *data,
@@ -26,8 +32,8 @@
 int ntfs_attr_allnonresident(ntfs_inode *ino);
 
 int ntfs_new_attr(ntfs_inode *ino, int type, void *name, int namelen,
-		  int *pos, int *found, int do_search );
+		  void *value, int value_len, int *pos, int *found);
 
-void ntfs_insert_run(ntfs_attribute *attr, int cnum, ntfs_cluster_t cluster,
+int ntfs_insert_run(ntfs_attribute *attr, int cnum, ntfs_cluster_t cluster,
 		     int len );
 
diff -urN linux-2.4.7-pre6/fs/ntfs/dir.c linux/fs/ntfs/dir.c
--- linux-2.4.7-pre6/fs/ntfs/dir.c	Wed Apr 18 11:49:13 2001
+++ linux/fs/ntfs/dir.c	Mon Dec  3 22:55:50 2001
@@ -1,9 +1,10 @@
-/*  dir.c
+/*
+ * dir.c
  *
- *  Copyright (C) 1995-1997, 1999 Martin von Löwis
- *  Copyright (C) 1999 Steve Dodd
- *  Copyright (C) 1999 Joseph Malicki
- *  Copyright (C) 2001 Anton Altaparmakov (AIA)
+ * Copyright (C) 1995-1997, 1999 Martin von Löwis
+ * Copyright (C) 1999 Steve Dodd
+ * Copyright (C) 1999 Joseph Malicki
+ * Copyright (C) 2001 Anton Altaparmakov (AIA)
  */
 
 #include "ntfstypes.h"
@@ -17,8 +18,9 @@
 #include "attr.h"
 #include "support.h"
 #include "util.h"
+#include <linux/smp_lock.h>
 
-static char I30[]="$I30";
+static char I30[] = "$I30";
 
 /* An index record should start with INDX, and the last word in each block
  * should contain the check value. If it passes, the original values need to
@@ -104,9 +106,13 @@
 	return (int)(NTFS_GETU8(entry + 12) & 2) == 0;
 }
 
+/*
+ * Removed RACE for allocating index blocks. But stil not too happy.
+ * There might be more races afterwards. (AIA)
+ */
 static int ntfs_allocate_index_block(ntfs_iterate_s *walk)
 {
-	ntfs_attribute *allocation = 0, *bitmap = 0;
+	ntfs_attribute *allocation, *bitmap = 0;
 	int error, size, i, bit;
 	ntfs_u8 *bmap;
 	ntfs_io io;
@@ -120,68 +126,82 @@
 		error = ntfs_create_attr(walk->dir, vol->at_index_allocation,
 					 I30, 0, 0, &allocation);
 		if (error)
-			return error;
+			goto err_ret;
 		ntfs_bzero(bmp, sizeof(bmp));
 		error = ntfs_create_attr(walk->dir, vol->at_bitmap, I30, bmp,
 					 sizeof(bmp), &bitmap);
 		if (error)
-			return error;
+			goto err_ret;
 	} else
 		bitmap = ntfs_find_attr(walk->dir, vol->at_bitmap, I30);
 	if (!bitmap) {
 		ntfs_error("Directory w/o bitmap\n");
-		return -EINVAL;
+		error = -EINVAL;
+		goto err_ret;
 	}
 	size = bitmap->size;
 	bmap = ntfs_malloc(size);
-	if (!bmap)
-		return -ENOMEM;
+	if (!bmap) {
+		error = -ENOMEM;
+		goto err_ret;
+	}
 	io.fn_put = ntfs_put;
 	io.fn_get = ntfs_get;
+try_again:
 	io.param = bmap;
 	io.size = size;
 	error = ntfs_read_attr(walk->dir, vol->at_bitmap, I30, 0, &io);
-	if (error) {
-		ntfs_free(bmap);
-		return error;
-	}
-	if (io.size != size) {
-		ntfs_free(bmap);
-		return -EIO;
-	}
+	if (error || (io.size != size && (error = -EIO, 1)))
+		goto err_fb_out;
 	/* Allocate a bit. */
-	for (i = bit = 0; i < size; i++) {
+	for (bit = i = 0; i < size; i++) {
 		if (bmap[i] == 0xFF)
 			continue;
-		for (bit = 0; bit < 8; bit++)
-			if (((bmap[i] >> bit) & 1) == 0)
-				break;
-		if (bit != 8)
+		bit = ffz(bmap[i]);
+		if (bit < 8)
 			break;
 	}
-	if (i == size)
+	if (i >= size) {
 		/* FIXME: Extend bitmap. */
-		return -EOPNOTSUPP;
-	walk->newblock = (i * 8 + bit) * walk->dir->u.index.clusters_per_record;
-	bmap[i] |= 1 << bit;
+		error = -EOPNOTSUPP;
+		goto err_fb_out;
+	}
+	/* Get the byte containing our bit again, now taking the BKL. */
 	io.param = bmap;
-	io.size = size;
-	error = ntfs_write_attr(walk->dir, vol->at_bitmap, I30, 0, &io);
-	if (error || io.size != size) {
-		ntfs_free(bmap);
-		return error ? error : -EIO;
+	io.size = 1;
+	lock_kernel();
+	error = ntfs_read_attr(walk->dir, vol->at_bitmap, I30, i, &io);
+	if (error || (io.size != 1 && (error = -EIO, 1)))
+		goto err_unl_out;
+	if (ntfs_test_and_set_bit(bmap, bit)) {
+		unlock_kernel();
+		/* Give other process(es) a chance to finish. */
+		schedule();
+		goto try_again;
 	}
+	walk->newblock = (i * 8 + bit) * walk->dir->u.index.clusters_per_record;
+	io.param = bmap;
+	error = ntfs_write_attr(walk->dir, vol->at_bitmap, I30, i, &io);
+	if (error || (io.size != size && (error = -EIO, 1)))
+		goto err_unl_out;
+	/* Change inode on disk, required when bitmap is resident. */
+	error = ntfs_update_inode(walk->dir);
+	if (error)
+		goto err_unl_out;
+	unlock_kernel();
 	ntfs_free(bmap);
 	/* Check whether record is out of allocated range. */
 	size = allocation->size;
-	if (walk->newblock * vol->clustersize >= size) {
+	if (walk->newblock * vol->cluster_size >= size) {
 		/* Build index record. */
-		int s1 = walk->dir->u.index.recordsize;
-		int nr_fix = s1/vol->blocksize + 1;
 		int hsize;
+		int s1 = walk->dir->u.index.recordsize;
+		int nr_fix = (s1 >> vol->sector_size) + 1;
 		char *record = ntfs_malloc(s1);
-		if (!record)
-			return -ENOMEM;
+		if (!record) {
+			error = -ENOMEM;
+			goto err_ret;
+		}
 		ntfs_bzero(record, s1);
 		/* Magic */
 		ntfs_memcpy(record, "INDX", 4);
@@ -205,13 +225,20 @@
 		io.size = s1;
 		io.do_read = 0;
 		error = ntfs_readwrite_attr(walk->dir, allocation, size, &io);
-		if (error || io.size != s1) {
-			ntfs_free(record);
-			return error ? error : -EIO;
-		}
 		ntfs_free(record);
+		if (error || (io.size != s1 && (error = -EIO, 1)))
+			goto err_ret;
+		error = ntfs_update_inode(walk->dir);
+		if (error)
+			goto err_ret;
 	}
 	return 0;
+err_unl_out:
+	unlock_kernel();
+err_fb_out:
+	ntfs_free(bmap);
+err_ret:
+	return error;
 }
 
 /* Write an index block (root or allocation) back to storage.
@@ -227,30 +254,27 @@
 	io.fn_put = 0;
 	io.fn_get = ntfs_get;
 	io.param = buf;
-	if (block == -1) {
+	if (block == -1) {	/* Index root. */
 		NTFS_PUTU16(buf + 0x14, used - 0x10);
 		/* 0x18 is a copy thereof. */
 		NTFS_PUTU16(buf + 0x18, used - 0x10);
 		io.size = used;
 		error = ntfs_write_attr(walk->dir, vol->at_index_root, I30, 0,
 					&io);
-		if (error)
+		if (error || (io.size != used && (error = -EIO, 1)))
 			return error;
-		if (io.size != used)
-			return -EIO;
 		/* Shrink if necessary. */
 		a = ntfs_find_attr(walk->dir, vol->at_index_root, I30);
 		ntfs_resize_attr(walk->dir, a, used);
 	} else {
 		NTFS_PUTU16(buf + 0x1C, used - 0x18);
-		ntfs_insert_fixups(buf, vol->blocksize);
+		ntfs_insert_fixups(buf, vol->sector_size);
 		io.size = walk->dir->u.index.recordsize;
 		error = ntfs_write_attr(walk->dir, vol->at_index_allocation,
-					I30, block*vol->clustersize, &io);
-		if (error)
+			I30, (__s64)block << vol->cluster_size_bits, &io);
+		if (error || (io.size != walk->dir->u.index.recordsize &&
+							(error = -EIO, 1)))
 			return error;
-		if (io.size != walk->dir->u.index.recordsize)
-			return -EIO;
 	}
 	return 0;
 }
@@ -277,19 +301,19 @@
 	for (prev = entry; entry - start < usize / 2; 
 					       entry += NTFS_GETU16(entry + 8))
 		prev = entry;
-	newbuf = ntfs_malloc(vol->index_recordsize);
+	newbuf = ntfs_malloc(vol->index_record_size);
 	if (!newbuf)
 		return -ENOMEM;
 	io.fn_put = ntfs_put;
 	io.fn_get = ntfs_get;
 	io.param = newbuf;
-	io.size = vol->index_recordsize;
+	io.size = vol->index_record_size;
 	/* Read in old header. FIXME: Reading everything is overkill. */
 	error = ntfs_read_attr(walk->dir, vol->at_index_allocation, I30,
-			       walk->newblock * vol->clustersize, &io);
+			(__s64)walk->newblock << vol->cluster_size_bits, &io);
 	if (error)
 		goto out;
-	if (io.size != vol->index_recordsize) {
+	if (io.size != vol->index_record_size) {
 		error = -EIO;
 		goto out;
 	}
@@ -355,7 +379,7 @@
 	int do_split = 0;
 	offset = entry - start;
 	if (walk->block == -1) { /* index root */
-		blocksize = walk->dir->vol->mft_recordsize;
+		blocksize = walk->dir->vol->mft_record_size;
 		usedsize = NTFS_GETU16(start + 0x14) + 0x10;
 	} else {
 		blocksize = walk->dir->u.index.recordsize;
@@ -399,7 +423,7 @@
 	ra = ntfs_find_attr(ino, ino->vol->at_index_root, I30);
 	if (!ra)
 		return -E2BIG;
-	bsize = ino->vol->mft_recordsize;
+	bsize = ino->vol->mft_record_size;
 	root = ntfs_malloc(bsize);
 	if (!root)
 		return -E2BIG;
@@ -418,7 +442,7 @@
 		error = -E2BIG;
 		goto out;
 	}
-	index = ntfs_malloc(ino->vol->index_recordsize);
+	index = ntfs_malloc(ino->vol->index_record_size);
 	if (!index) {
 		error = -ENOMEM;
 		goto out;
@@ -432,9 +456,9 @@
 		goto out;
 	/* Write old root to new index block. */
 	io.param = index;
-	io.size = ino->vol->index_recordsize;
+	io.size = ino->vol->index_record_size;
 	error = ntfs_read_attr(ino, ino->vol->at_index_allocation, I30,
-			       walk.newblock * ino->vol->clustersize, &io);
+		(__s64)walk.newblock << ino->vol->cluster_size_bits, &io);
 	if (error)
 		goto out;
 	isize = NTFS_GETU16(root + 0x18) - 0x10;
@@ -460,10 +484,10 @@
 }
 
 /* The entry has been found. Copy the result in the caller's buffer */
-static int ntfs_copyresult(char *dest,char *source)
+static int ntfs_copyresult(char *dest, char *source)
 {
-	int length=NTFS_GETU16(source+8);
-	ntfs_memcpy(dest,source,length);
+	int length = NTFS_GETU16(source + 8);
+	ntfs_memcpy(dest, source, length);
 	return 1;
 }
 
@@ -521,7 +545,7 @@
 	io.size = length;
 	/* Read the block from the index allocation attribute. */
 	error = ntfs_read_attr(walk->dir, walk->dir->vol->at_index_allocation,
-			       I30, block * walk->dir->vol->clustersize, &io);
+		I30, (__s64)block << walk->dir->vol->cluster_size_bits, &io);
 	if (error || io.size != length) {
 		ntfs_error("read failed\n");
 		ntfs_free(record);
@@ -546,7 +570,7 @@
 static int ntfs_descend(ntfs_iterate_s *walk, ntfs_u8 *start, ntfs_u8 *entry)
 {
 	int length = NTFS_GETU16(entry + 8);
-	int nextblock=NTFS_GETU32(entry+length-8);
+	int nextblock = NTFS_GETU32(entry + length - 8);
 	int error;
 
 	if (!ntfs_entry_has_subnodes(entry)) {
@@ -649,23 +673,21 @@
 		switch (walk->type) {
 		case BY_NAME:
 			switch (cmp) {
-				case -1:
-					return ntfs_entry_has_subnodes(entry) ?
-					       ntfs_descend(walk,start,entry) :
-					       0;
-				case  0:
-					return ntfs_copyresult(walk->result,
-							       entry);
-				case  1:
-					break;
+			case -1:
+				return ntfs_entry_has_subnodes(entry) ?
+					ntfs_descend(walk, start, entry) : 0;
+			case  0:
+				return ntfs_copyresult(walk->result, entry);
+			case  1:
+				break;
 			}
 			break;
 		case DIR_INSERT:
 			switch (cmp) {
 			case -1:
 				return ntfs_entry_has_subnodes(entry) ?
-					   ntfs_descend(walk, start, entry) :
-					   ntfs_dir_insert(walk, start, entry);
+					ntfs_descend(walk, start, entry) :
+					ntfs_dir_insert(walk, start, entry);
 			case  0:
 				return -EEXIST;
 			case  1:
@@ -712,7 +734,7 @@
  * entry to the result buffer. */
 int ntfs_getdir(ntfs_iterate_s* walk)
 {
-	int length = walk->dir->vol->mft_recordsize;
+	int length = walk->dir->vol->mft_record_size;
 	int retval, error;
 	/* Start at the index root. */
 	char *root = ntfs_malloc(length);
@@ -782,7 +804,7 @@
 	ntfs_debug(DEBUG_DIR3, "unsorted 1\n");
 	/* Are we still in the index root? */
 	if (*p_high == 0) {
-		buf = ntfs_malloc(length = vol->mft_recordsize);
+		buf = ntfs_malloc(length = vol->mft_record_size);
 		if (!buf)
 			return -ENOMEM;
 		io.fn_put = ntfs_put;
@@ -808,7 +830,7 @@
 		/* 0 is index root, index allocation starts with 4. */
 		block = *p_high - ino->u.index.clusters_per_record;
 		error = ntfs_read_attr(ino, vol->at_index_allocation, I30,
-				       block*vol->clustersize, &io);
+				(__s64)block << vol->cluster_size_bits, &io);
 		if (!error && io.size != length)
 			error = -EIO;
 		if (error) {
@@ -873,7 +895,7 @@
 	}
 	attr = ntfs_find_attr(ino, vol->at_index_allocation, I30);
 	while (1) {
-		if (*p_high * vol->clustersize > attr->size) {
+		if ((__s64)*p_high << vol->cluster_size_bits > attr->size) {
 			/* No more index records. */
 			*p_high = 0xFFFFFFFF;
 			ntfs_free(buf);
@@ -882,7 +904,7 @@
 		}
 		*p_high += ino->u.index.clusters_per_record;
 		byte = *p_high / ino->u.index.clusters_per_record - 1;
-		bit  = 1 << (byte & 7);
+		bit = 1 << (byte & 7);
 		byte = byte >> 3;
 		/* This record is allocated. */
 		if (buf[byte] & bit)
@@ -907,16 +929,17 @@
 	ndata = name->d.data;
 	walk.name = (ntfs_u16*)(ndata + 0x42);
 	walk.namelen = NTFS_GETU8(ndata + 0x40);
-	walk.new_entry_size = esize = ((nsize + 0x18) / 8) * 8;
+	walk.new_entry_size = esize = (nsize + 0x10 + 7) & ~7;
 	walk.new_entry = entry = ntfs_malloc(esize);
 	if (!entry)
 		return -ENOMEM;
-	ntfs_bzero(entry, esize);
 	NTFS_PUTINUM(entry, new);
 	NTFS_PUTU16(entry + 0x8, esize); /* Size of entry. */
 	NTFS_PUTU16(entry + 0xA, nsize); /* Size of original name attribute. */
-	NTFS_PUTU32(entry + 0xC, 0);     /* FIXME: D-F? */
+	NTFS_PUTU16(entry + 0xC, 0);     /* Flags. */
+	NTFS_PUTU16(entry + 0xE, 0);	 /* Reserved. */
 	ntfs_memcpy(entry + 0x10, ndata, nsize);
+	ntfs_bzero(entry + 0x10 + nsize, esize - 0x10 - nsize);
 	error = ntfs_getdir(&walk);
 	if (walk.new_entry)
 		ntfs_free(walk.new_entry);
@@ -972,11 +995,11 @@
 	char name[10];
 
 	NTFS_PUTU32(data, type);
-	/* FIXME: ??? */
+	/* Collation rule. 1 == COLLATION_FILENAME */
 	NTFS_PUTU32(data + 4, 1);
-	NTFS_PUTU32(data + 8, ino->vol->index_recordsize);
+	NTFS_PUTU32(data + 8, ino->vol->index_record_size);
 	NTFS_PUTU32(data + 0xC, ino->vol->index_clusters_per_record);
-	/* FXIME: ??? */
+	/* Byte offset to first INDEX_ENTRY. */
 	NTFS_PUTU32(data + 0x10, 0x10);
 	/* Size of entries, including header. */
 	NTFS_PUTU32(data + 0x14, 0x20);
@@ -1012,7 +1035,7 @@
 	error = ntfs_update_inode(dir);
 	if (error)
 		goto out;
-	error = ntfs_update_inode (result);
+	error = ntfs_update_inode(result);
 	if (error)
 		goto out;
  out:
diff -urN linux-2.4.7-pre6/fs/ntfs/dir.h linux/fs/ntfs/dir.h
--- linux-2.4.7-pre6/fs/ntfs/dir.h	Wed Apr 18 11:49:13 2001
+++ linux/fs/ntfs/dir.h	Mon Dec  3 22:55:50 2001
@@ -1,8 +1,8 @@
-/*  dir.h - Header file for dir.c
+/*
+ * dir.h - Header file for dir.c
  *
- *  Copyright (C) 1997 Régis Duchesne
+ * Copyright (C) 1997 Régis Duchesne
  */
-
 #define ITERATE_SPLIT_DONE      1
 
 enum ntfs_iterate_e {
@@ -12,7 +12,7 @@
 };
 
 /* not all fields are used for all operations */
-typedef struct ntfs_iterate_s{
+typedef struct ntfs_iterate_s {
 	enum ntfs_iterate_e type;
 	ntfs_inode *dir;
 	union{
diff -urN linux-2.4.7-pre6/fs/ntfs/fs.c linux/fs/ntfs/fs.c
--- linux-2.4.7-pre6/fs/ntfs/fs.c	Wed Apr 18 11:49:13 2001
+++ linux/fs/ntfs/fs.c	Mon Dec  3 22:55:50 2001
@@ -1,9 +1,13 @@
-/*  fs.c - NTFS driver for Linux 2.4.x
+/*
+ * fs.c - NTFS driver for Linux 2.4.x
+ *
+ * Development has as of recently (since June '01) been sponsored
+ * by Legato Systems, Inc. (http://www.legato.com)
  *
- *  Copyright (C) 1995-1997, 1999 Martin von Löwis
- *  Copyright (C) 1996 Richard Russon
- *  Copyright (C) 1996-1997 Régis Duchesne
- *  Copyright (C) 2000-2001, Anton Altaparmakov (AIA)
+ * Copyright (C) 1995-1997, 1999 Martin von Löwis
+ * Copyright (C) 1996 Richard Russon
+ * Copyright (C) 1996-1997 Régis Duchesne
+ * Copyright (C) 2000-2001, Anton Altaparmakov (AIA)
  */
 
 #include <linux/config.h>
@@ -19,12 +23,15 @@
 #include "sysctl.h"
 #include <linux/module.h>
 #include <asm/uaccess.h>
-#include <linux/nls.h>
 #include <linux/locks.h>
 #include <linux/init.h>
 #include <linux/smp_lock.h>
 #include <asm/page.h>
 
+#ifndef NLS_MAX_CHARSET_SIZE
+#include <linux/nls.h>
+#endif
+
 /* Forward declarations. */
 static struct inode_operations ntfs_dir_inode_operations;
 static struct file_operations ntfs_dir_operations;
@@ -55,6 +62,7 @@
 }
 #endif
 
+/* loff_t is 64 bit signed, so is cool. */
 static ssize_t ntfs_read(struct file *filp, char *buf, size_t count,loff_t *off)
 {
 	int error;
@@ -64,20 +72,28 @@
 	/* Inode is not properly initialized. */
 	if (!ino)
 		return -EINVAL;
-	ntfs_debug(DEBUG_OTHER, "ntfs_read %x,%x,%x ->",
-		   (unsigned)ino->i_number, (unsigned)*off, (unsigned)count);
+	ntfs_debug(DEBUG_OTHER, "ntfs_read %x, %Lx, %x ->",
+		   (unsigned)ino->i_number, (unsigned long long)*off,
+		   (unsigned)count);
 	/* Inode has no unnamed data attribute. */
-	if(!ntfs_find_attr(ino, ino->vol->at_data, NULL))
+	if(!ntfs_find_attr(ino, ino->vol->at_data, NULL)) {
+		ntfs_debug(DEBUG_OTHER, "ntfs_read: $DATA not found!\n");
 		return -EINVAL;
+	}
 	/* Read the data. */
 	io.fn_put = ntfs_putuser;
 	io.fn_get = 0;
 	io.param = buf;
 	io.size = count;
 	error = ntfs_read_attr(ino, ino->vol->at_data, NULL, *off, &io);
-	if (error && !io.size)
+	if (error && !io.size) {
+		ntfs_debug(DEBUG_OTHER, "ntfs_read: read_attr failed with "
+				"error %i, io size %u.\n", error, io.size);
 		return error;
+	}
 	*off += io.size;
+	ntfs_debug(DEBUG_OTHER, "ntfs_read: finished. read %u bytes.\n",
+								io.size);
 	return io.size;
 }
 
@@ -326,6 +342,13 @@
 			if (!simple_getbool(value, &val))
 				goto needs_bool;
 			vol->ngt = val ? ngt_posix : ngt_nt;
+		} else if (strcmp(opt, "show_sys_files") == 0) {
+			int val = 0;
+			if (!value || !*value)
+				val = 1;
+			else if (!simple_getbool(value, &val))
+				goto needs_bool;
+			vol->ngt = val ? ngt_full : ngt_nt;
 		} else if (strcmp(opt, "utf8") == 0) {
 			int val = 0;
 			if (!value || !*value)
@@ -433,8 +456,13 @@
 	ino = NTFS_LINO2NINO(r);
 	error = ntfs_alloc_file(NTFS_LINO2NINO(dir), ino, (char*)d->d_name.name,
 				d->d_name.len);
-	if (error)
+	if (error) {
+		ntfs_error("ntfs_alloc_file FAILED: error = %i", error);
 		goto fail;
+	}
+	/* Not doing this one was causing a huge amount of corruption! Now the
+	 * bugger bytes the dust! (-8 (AIA) */
+	r->i_ino = ino->i_number;
 	error = ntfs_update_inode(ino);
 	if (error)
 		goto fail;
@@ -491,6 +519,9 @@
 			   ino);
 	if (error)
 		goto out;
+	/* Not doing this one was causing a huge amount of corruption! Now the
+	 * bugger bytes the dust! (-8 (AIA) */
+	r->i_ino = ino->i_number;
 	r->i_uid = vol->uid;
 	r->i_gid = vol->gid;
 	si = ntfs_find_attr(ino, vol->at_standard_information, NULL);
@@ -608,19 +639,75 @@
 
 	vol = NTFS_INO2VOL(inode);
 	inode->i_mode = 0;
-	ntfs_debug(DEBUG_OTHER, "ntfs_read_inode %x\n", (unsigned)inode->i_ino);
+	ntfs_debug(DEBUG_OTHER, "ntfs_read_inode 0x%x\n", (unsigned)inode->i_ino);
+	/*
+	 * This kills all accesses to system files (except $Extend directory).
+	 * The driver can bypass this by calling ntfs_init_inode() directly.
+	 * Only if ngt is ngt_full do we allow access to the system files.
+	 */
 	switch (inode->i_ino) {
 		/* Those are loaded special files. */
 	case FILE_$Mft:
-		ntfs_error("Trying to open MFT\n");
-		return;
+		if (vol->ngt != ngt_full) {
+			ntfs_error("Trying to open $MFT!\n");
+			return;
+		}
+		if (!vol->mft_ino || ((vol->ino_flags & 1) == 0))
+			goto sys_file_error;
+		ntfs_memcpy(&inode->u.ntfs_i, vol->mft_ino, sizeof(ntfs_inode));
+		ino = vol->mft_ino;
+		vol->mft_ino = &inode->u.ntfs_i;
+		vol->ino_flags &= ~1;
+		ntfs_free(ino);
+		ino = vol->mft_ino;
+		ntfs_debug(DEBUG_OTHER, "Opening $MFT!\n");
+		break;
+	case FILE_$MftMirr:
+		if (vol->ngt != ngt_full) {
+			ntfs_error("Trying to open $MFTMirr!\n");
+			return;
+		}
+		if (!vol->mftmirr || ((vol->ino_flags & 2) == 0))
+			goto sys_file_error;
+		ntfs_memcpy(&inode->u.ntfs_i, vol->mftmirr, sizeof(ntfs_inode));
+		ino = vol->mftmirr;
+		vol->mftmirr = &inode->u.ntfs_i;
+		vol->ino_flags &= ~2;
+		ntfs_free(ino);
+		ino = vol->mftmirr;
+		ntfs_debug(DEBUG_OTHER, "Opening $MFTMirr!\n");
+		break;
+	case FILE_$BitMap:
+		if (vol->ngt != ngt_full) {
+			ntfs_error("Trying to open $Bitmap!\n");
+			return;
+		}
+		if (!vol->bitmap || ((vol->ino_flags & 4) == 0))
+			goto sys_file_error;
+		ntfs_memcpy(&inode->u.ntfs_i, vol->bitmap, sizeof(ntfs_inode));
+		ino = vol->bitmap;
+		vol->bitmap = &inode->u.ntfs_i;
+		vol->ino_flags &= ~4;
+		ntfs_free(ino);
+		ino = vol->bitmap;
+		ntfs_debug(DEBUG_OTHER, "Opening $Bitmap!\n");
+		break;
+	case FILE_$LogFile ... FILE_$AttrDef:
+	/* We need to allow reading the root directory. */
+	case FILE_$Boot ... FILE_$UpCase:
+		if (vol->ngt != ngt_full) {
+			ntfs_error("Trying to open system file %i!\n",
+								inode->i_ino);
+	 		return;
+		} /* Do the default for ngt_full. */
+		ntfs_debug(DEBUG_OTHER, "Opening system file %i!\n", inode->i_ino);
 	default:
 		ino = &inode->u.ntfs_i;
 		if (!ino || ntfs_init_inode(ino, NTFS_INO2VOL(inode),
 								inode->i_ino))
 		{
-			ntfs_debug(DEBUG_OTHER, "NTFS :Error loading inode "
-					"%x\n", (unsigned int)inode->i_ino);
+			ntfs_debug(DEBUG_OTHER, "NTFS: Error loading inode "
+					"0x%x\n", (unsigned int)inode->i_ino);
 			return;
 		}
 	}
@@ -641,7 +728,7 @@
 		can_mmap = 0;
 	}
 	/* Get the file modification times from the standard information. */
-	si = ntfs_find_attr(ino,vol->at_standard_information, NULL);
+	si = ntfs_find_attr(ino, vol->at_standard_information, NULL);
 	if (si) {
 		char *attr = si->d.data;
 		inode->i_atime = ntfs_ntutc2unixutc(NTFS_GETU64(attr + 0x18));
@@ -678,24 +765,85 @@
 		inode->i_mode |= S_IWUGO;
 #endif
 	inode->i_mode &= ~vol->umask;
+	return;
+sys_file_error:
+	ntfs_error("Critical error. Tried to call ntfs_read_inode() before we "
+		"have completed read_super() or VFS error.\n");
+	// FIXME: Should we panic() at this stage?
 }
 
 #ifdef CONFIG_NTFS_RW
 static void ntfs_write_inode(struct inode *ino, int unused)
 {
 	lock_kernel();
-	ntfs_debug(DEBUG_LINUX, "ntfs_write_inode %x\n", ino->i_ino);
+	ntfs_debug(DEBUG_LINUX, "ntfs_write_inode 0x%x\n", ino->i_ino);
 	ntfs_update_inode(NTFS_LINO2NINO(ino));
 	unlock_kernel();
 }
 #endif
 
-static void _ntfs_clear_inode(struct inode *ino)
+static void _ntfs_clear_inode(struct inode *inode)
 {
+	ntfs_inode *ino;
+	ntfs_volume *vol;
+	
 	lock_kernel();
-	ntfs_debug(DEBUG_OTHER, "ntfs_clear_inode %lx\n", ino->i_ino);
-	if (ino->i_ino != FILE_$Mft)
-		ntfs_clear_inode(&ino->u.ntfs_i);
+	ntfs_debug(DEBUG_OTHER, "_ntfs_clear_inode 0x%x\n", inode->i_ino);
+	vol = NTFS_INO2VOL(inode);
+	if (!vol)
+		ntfs_error("_ntfs_clear_inode: vol = NTFS_INO2VOL(inode) is NULL.\n");
+	switch (inode->i_ino) {
+	case FILE_$Mft:
+		if (vol->ngt != ngt_full) {
+			ntfs_error("Trying to _clear_inode of $MFT!\n");
+			goto unl_out;
+		}
+		if (vol->mft_ino && ((vol->ino_flags & 1) == 0)) {
+			ino = (ntfs_inode*)ntfs_malloc(sizeof(ntfs_inode));
+			ntfs_memcpy(ino, &inode->u.ntfs_i, sizeof(ntfs_inode));
+			vol->mft_ino = ino;
+			vol->ino_flags |= 1;
+			goto unl_out;
+		}
+		break;
+	case FILE_$MftMirr:
+		if (vol->ngt != ngt_full) {
+			ntfs_error("Trying to _clear_inode of $MFTMirr!\n");
+			goto unl_out;
+		}
+		if (vol->mftmirr && ((vol->ino_flags & 2) == 0)) {
+			ino = (ntfs_inode*)ntfs_malloc(sizeof(ntfs_inode));
+			ntfs_memcpy(ino, &inode->u.ntfs_i, sizeof(ntfs_inode));
+			vol->mftmirr = ino;
+			vol->ino_flags |= 2;
+			goto unl_out;
+		}
+		break;
+	case FILE_$BitMap:
+		if (vol->ngt != ngt_full) {
+			ntfs_error("Trying to _clear_inode of $Bitmap!\n");
+			goto unl_out;
+		}
+		if (vol->bitmap && ((vol->ino_flags & 4) == 0)) {
+			ino = (ntfs_inode*)ntfs_malloc(sizeof(ntfs_inode));
+			ntfs_memcpy(ino, &inode->u.ntfs_i, sizeof(ntfs_inode));
+			vol->bitmap = ino;
+			vol->ino_flags |= 4;
+			goto unl_out;
+		}
+		break;
+	case FILE_$LogFile ... FILE_$AttrDef:
+	case FILE_$Boot ... FILE_$UpCase:
+		if (vol->ngt != ngt_full) {
+			ntfs_error("Trying to _clear_inode of system file %i! "
+					"Shouldn't happen.\n", inode->i_ino);
+			goto unl_out;
+		} /* Do the default for ngt_full. */
+	default:
+		/* Nothing. Just clear the inode and exit. */
+	}
+	ntfs_clear_inode(&inode->u.ntfs_i);
+unl_out:
 	unlock_kernel();
 	return;
 }
@@ -718,25 +866,29 @@
 {
 	struct inode *mft;
 	ntfs_volume *vol;
-	ntfs_u64 size;
+	__s64 size;
 	int error;
 
 	ntfs_debug(DEBUG_OTHER, "ntfs_statfs\n");
 	vol = NTFS_SB2VOL(sb);
 	sf->f_type = NTFS_SUPER_MAGIC;
-	sf->f_bsize = vol->clustersize;
+	sf->f_bsize = vol->cluster_size;
 	error = ntfs_get_volumesize(NTFS_SB2VOL(sb), &size);
 	if (error)
 		return error;
 	sf->f_blocks = size;	/* Volumesize is in clusters. */
-	sf->f_bfree = ntfs_get_free_cluster_count(vol->bitmap);
-	sf->f_bavail = sf->f_bfree;
+	size = (__s64)ntfs_get_free_cluster_count(vol->bitmap);
+	/* Just say zero if the call failed. */
+	if (size < 0LL)
+		size = 0;
+	sf->f_bfree = sf->f_bavail = size;
+	ntfs_debug(DEBUG_OTHER, "ntfs_statfs: calling mft = iget(sb, FILE_$Mft)\n");
 	mft = iget(sb, FILE_$Mft);
+	ntfs_debug(DEBUG_OTHER, "ntfs_statfs: iget(sb, FILE_$Mft) returned 0x%x\n", mft);
 	if (!mft)
 		return -EIO;
-	/* So ... we lie... thus this following cast of loff_t value is ok
-	 * here.. */
-	sf->f_files = (unsigned long)mft->i_size / vol->mft_recordsize;
+	sf->f_files = mft->i_size >> vol->mft_record_size_bits;
+	ntfs_debug(DEBUG_OTHER, "ntfs_statfs: calling iput(mft)\n");
 	iput(mft);
 	/* Should be read from volume. */
 	sf->f_namelen = 255;
@@ -763,6 +915,77 @@
 	clear_inode:	_ntfs_clear_inode,
 };
 
+/**
+ * is_boot_sector_ntfs - check an NTFS boot sector for validity
+ * @b:		buffer containing bootsector to check
+ * 
+ * Check whether @b contains a valid NTFS boot sector.
+ * Return 1 if @b is a valid NTFS bootsector or 0 if not.
+ */
+static int is_boot_sector_ntfs(ntfs_u8 *b)
+{
+	ntfs_u32 i;
+
+	/* FIXME: We don't use checksumming yet as NT4(SP6a) doesn't either...
+	 * But we might as well have the code ready to do it. (AIA) */
+#if 0
+	/* Calculate the checksum. */
+	if (b < b + 0x50) {
+		ntfs_u32 *u;
+		ntfs_u32 *bi = (ntfs_u32 *)(b + 0x50);
+		
+		for (u = bi, i = 0; u < bi; ++u)
+			i += NTFS_GETU32(*u);
+	}
+#endif
+	/* Check magic is "NTFS    " */
+	if (b[3] != 0x4e) goto not_ntfs;
+	if (b[4] != 0x54) goto not_ntfs;
+	if (b[5] != 0x46) goto not_ntfs;
+	if (b[6] != 0x53) goto not_ntfs;
+	for (i = 7; i < 0xb; ++i)
+		if (b[i] != 0x20) goto not_ntfs;
+	/* Check bytes per sector value is between 512 and 4096. */
+	if (b[0xb] != 0) goto not_ntfs;
+	if (b[0xc] > 0x10) goto not_ntfs;
+	/* Check sectors per cluster value is valid. */
+	switch (b[0xd]) {
+	case 1: case 2: case 4: case 8: case 16:
+	case 32: case 64: case 128:
+		break;
+	default:
+		goto not_ntfs;
+	}
+	/* Check reserved sectors value and four other fields are zero. */
+	for (i = 0xe; i < 0x15; ++i) 
+		if (b[i] != 0) goto not_ntfs;
+	if (b[0x16] != 0) goto not_ntfs;
+	if (b[0x17] != 0) goto not_ntfs;
+	for (i = 0x20; i < 0x24; ++i)
+		if (b[i] != 0) goto not_ntfs;
+	/* Check clusters per file record segment value is valid. */
+	if (b[0x40] < 0xe1 || b[0x40] > 0xf7) {
+		switch (b[0x40]) {
+		case 1: case 2: case 4: case 8: case 16: case 32: case 64:
+			break;
+		default:
+			goto not_ntfs;
+		}
+	}
+	/* Check clusters per index block value is valid. */
+	if (b[0x44] < 0xe1 || b[0x44] > 0xf7) {
+		switch (b[0x44]) {
+		case 1: case 2: case 4: case 8: case 16: case 32: case 64:
+			break;
+		default:
+			goto not_ntfs;
+		}
+	}
+	return 1;
+not_ntfs:
+	return 0;
+}
+
 /* Called to mount a filesystem by read_super() in fs/super.c.
  * Return a super block, the main structure of a filesystem.
  *
@@ -782,10 +1005,6 @@
 	vol = NTFS_SB2VOL(sb);
 	if (!parse_options(vol, (char*)options))
 		goto ntfs_read_super_vol;
-#if 0
-	/* Set to read only, user option might reset it */
-	sb->s_flags |= MS_RDONLY;
-#endif
 	/* Assume a 512 bytes block device for now. */
 	set_blocksize(sb->s_dev, 512);
 	/* Read the super block (boot block). */
@@ -795,50 +1014,49 @@
 	}
 	ntfs_debug(DEBUG_OTHER, "Done reading boot block\n");
 	/* Check for 'NTFS' magic number */
-	if (!IS_NTFS_VOLUME(bh->b_data)) {
+	if (!is_boot_sector_ntfs(bh->b_data)) {
 		ntfs_debug(DEBUG_OTHER, "Not a NTFS volume\n");
-		brelse(bh);
+		bforget(bh);
 		goto ntfs_read_super_unl;
 	}
 	ntfs_debug(DEBUG_OTHER, "Going to init volume\n");
 	if (ntfs_init_volume(vol, bh->b_data) < 0) {
 		ntfs_debug(DEBUG_OTHER, "Init volume failed.\n");
-		brelse(bh);
+		bforget(bh);
 		goto ntfs_read_super_unl;
 	}
-	ntfs_debug(DEBUG_OTHER, "$Mft at cluster 0x%Lx\n", vol->mft_cluster);
-	brelse(bh);
+	ntfs_debug(DEBUG_OTHER, "$Mft at cluster 0x%Lx\n", vol->mft_lcn);
+	bforget(bh);
 	NTFS_SB(vol) = sb;
-	ntfs_debug(DEBUG_OTHER, "Done to init volume\n");
-	/* Inform the kernel that a device block is a NTFS cluster. */
-	sb->s_blocksize = vol->clustersize;
-	if (sb->s_blocksize > PAGE_SIZE) {
-		ntfs_error("Partition cluster size is not supported yet (too "
-			   "large for kernel blocksize).\n");
+	if (vol->cluster_size > PAGE_SIZE) {
+		ntfs_error("Partition cluster size is not supported yet (it "
+			   "is > max kernel blocksize).\n");
 		goto ntfs_read_super_unl;
 	}
+	ntfs_debug(DEBUG_OTHER, "Done to init volume\n");
+	/* Inform the kernel that a device block is a NTFS cluster. */
+	sb->s_blocksize = vol->cluster_size;
 	for (i = sb->s_blocksize, sb->s_blocksize_bits = 0; i != 1; i >>= 1)
 		sb->s_blocksize_bits++;
 	set_blocksize(sb->s_dev, sb->s_blocksize);
 	ntfs_debug(DEBUG_OTHER, "set_blocksize\n");
-
-	/* Allocate a MFT record (MFT record can be smaller than a cluster). */
-	if (!(vol->mft = ntfs_malloc(max(vol->mft_recordsize,
-							   vol->clustersize))))
+	/* Allocate an MFT record (MFT record can be smaller than a cluster). */
+	if (!(vol->mft = ntfs_malloc(max(vol->mft_record_size,
+							 vol->cluster_size))))
 		goto ntfs_read_super_unl;
 
 	/* Read at least the MFT record for $Mft. */
 	for (i = 0; i < max(vol->mft_clusters_per_record, 1); i++) {
-		if (!(bh = bread(sb->s_dev, vol->mft_cluster + i,
-							  vol->clustersize))) {
+		if (!(bh = bread(sb->s_dev, vol->mft_lcn + i,
+							  vol->cluster_size))) {
 			ntfs_error("Could not read $Mft record 0\n");
 			goto ntfs_read_super_mft;
 		}
-		ntfs_memcpy(vol->mft + i * vol->clustersize, bh->b_data,
-							     vol->clustersize);
+		ntfs_memcpy(vol->mft + ((__s64)i << vol->cluster_size_bits),
+						bh->b_data, vol->cluster_size);
 		brelse(bh);
-		ntfs_debug(DEBUG_OTHER, "Read cluster %x\n",
-							 vol->mft_cluster + i);
+		ntfs_debug(DEBUG_OTHER, "Read cluster 0x%x\n",
+							 vol->mft_lcn + i);
 	}
 	/* Check and fixup this MFT record */
 	if (!ntfs_check_mft_record(vol, vol->mft)){
@@ -848,7 +1066,7 @@
 	/* Inform the kernel about which super operations are available. */
 	sb->s_op = &ntfs_super_operations;
 	sb->s_magic = NTFS_SUPER_MAGIC;
-	sb->s_maxbytes = ~0ULL;
+	sb->s_maxbytes = ~0ULL >> 1;
 	ntfs_debug(DEBUG_OTHER, "Reading special files\n");
 	if (ntfs_load_special_files(vol)) {
 		ntfs_error("Error loading special files\n");
@@ -860,14 +1078,15 @@
 		ntfs_error("Could not get root dir inode\n");
 		goto ntfs_read_super_mft;
 	}
+ntfs_read_super_ret:
 	ntfs_debug(DEBUG_OTHER, "read_super: done\n");
 	return sb;
 ntfs_read_super_mft:
 	ntfs_free(vol->mft);
 ntfs_read_super_unl:
 ntfs_read_super_vol:
-	ntfs_debug(DEBUG_OTHER, "read_super: done\n");
-	return NULL;
+	sb = NULL;
+	goto ntfs_read_super_ret;
 }
 
 /* Define the filesystem */
@@ -894,7 +1113,11 @@
 }
 
 EXPORT_NO_SYMBOLS;
-MODULE_AUTHOR("Martin von Löwis");
+/*
+ * Not strictly true. The driver was written originally by Martin von Löwis.
+ * I am just maintaining and rewriting it.
+ */
+MODULE_AUTHOR("Anton Altaparmakov <aia21@cus.cam.ac.uk>");
 MODULE_DESCRIPTION("NTFS driver");
 #ifdef DEBUG
 MODULE_PARM(ntdebug, "i");
diff -urN linux-2.4.7-pre6/fs/ntfs/inode.c linux/fs/ntfs/inode.c
--- linux-2.4.7-pre6/fs/ntfs/inode.c	Wed Apr 18 11:49:13 2001
+++ linux/fs/ntfs/inode.c	Mon Dec  3 22:55:50 2001
@@ -1,11 +1,12 @@
-/*  inode.c
+/*
+ * inode.c
  *
- *  Copyright (C) 1995-1999 Martin von Löwis
- *  Copyright (C) 1996 Albert D. Cahalan
- *  Copyright (C) 1996-1997 Régis Duchesne
- *  Copyright (C) 1998 Joseph Malicki
- *  Copyright (C) 1999 Steve Dodd
- *  Copyright (C) 2000-2001 Anton Altaparmakov (AIA)
+ * Copyright (C) 1995-1999 Martin von Löwis
+ * Copyright (C) 1996 Albert D. Cahalan
+ * Copyright (C) 1996-1997 Régis Duchesne
+ * Copyright (C) 1998 Joseph Malicki
+ * Copyright (C) 1999 Steve Dodd
+ * Copyright (C) 2000-2001 Anton Altaparmakov (AIA)
  */
 
 #include "ntfstypes.h"
@@ -19,6 +20,7 @@
 #include "dir.h"
 #include "support.h"
 #include "util.h"
+#include <linux/smp_lock.h>
 
 typedef struct {
 	int recno;
@@ -86,27 +88,31 @@
 	/* Try to allocate at least 0.1% of the remaining disk space for
 	 * inodes. If the disk is almost full, make sure at least one inode is
 	 * requested. */
-	int size, rcount, error, block;
+	int rcount, error, block, blockbits;
+	__s64 size;
 	ntfs_attribute *mdata, *bmp;
 	ntfs_u8 *buf;
 	ntfs_io io;
 
 	mdata = ntfs_find_attr(vol->mft_ino, vol->at_data, 0);
 	/* First check whether there is uninitialized space. */
-	if (mdata->allocated < mdata->size + vol->mft_recordsize) {
-		size = ntfs_get_free_cluster_count(vol->bitmap) *
-							      vol->clustersize;
-		block = vol->mft_recordsize;
-		size = max(size / 1000, mdata->size + vol->mft_recordsize);
-		size = ((size + block - 1) / block) * block;
+	if (mdata->allocated < mdata->size + vol->mft_record_size) {
+		size = (__s64)ntfs_get_free_cluster_count(vol->bitmap) <<
+							vol->cluster_size_bits;
+		/* On error, size will be negative. We can ignore this as we
+		 * will fall back to the minimal size allocation below. (AIA) */
+		block = vol->mft_record_size;
+		blockbits = vol->mft_record_size_bits;
+		size = max(size >> 10, mdata->size + vol->mft_record_size);
+		size = (__s64)((size + block - 1) >> blockbits) << blockbits;
 		/* Require this to be a single chunk. */
 		error = ntfs_extend_attr(vol->mft_ino, mdata, &size,
 							   ALLOC_REQUIRE_SIZE);
 		/* Try again, now we have the largest available fragment. */
 		if (error == -ENOSPC) {
 			/* Round down to multiple of mft record size. */
-			size = (size / vol->mft_recordsize) *
-							   vol->mft_recordsize;
+			size = (__s64)(size >> vol->mft_record_size_bits) <<
+						vol->mft_record_size_bits;
 			if (!size)
 				return -ENOSPC;
 			error = ntfs_extend_attr(vol->mft_ino, mdata, &size,
@@ -117,9 +123,9 @@
 	}
 	/* Even though we might have allocated more than needed, we initialize
 	 * only one record. */
-	mdata->size += vol->mft_recordsize;
+	mdata->size += vol->mft_record_size;
 	/* Now extend the bitmap if necessary. */
-	rcount = mdata->size / vol->mft_recordsize;
+	rcount = mdata->size >> vol->mft_record_size_bits;
 	bmp = ntfs_find_attr(vol->mft_ino, vol->at_bitmap, 0);
 	if (bmp->size * 8 < rcount) { /* Less bits than MFT records. */
 		ntfs_u8 buf[1];
@@ -141,20 +147,20 @@
 			return -EIO;
 	}
 	/* Now fill in the MFT header for the new block. */
-	buf = ntfs_calloc(vol->mft_recordsize);
+	buf = ntfs_calloc(vol->mft_record_size);
 	if (!buf)
 		return -ENOMEM;
-	ntfs_fill_mft_header(buf, vol->mft_recordsize, vol->blocksize, 0);
-	ntfs_insert_fixups(buf, vol->blocksize);
+	ntfs_fill_mft_header(buf, vol->mft_record_size, vol->sector_size, 0);
+	ntfs_insert_fixups(buf, vol->sector_size);
 	io.param = buf;
-	io.size = vol->mft_recordsize;
+	io.size = vol->mft_record_size;
 	io.fn_put = ntfs_put;
 	io.fn_get = ntfs_get;
 	error = ntfs_write_attr(vol->mft_ino, vol->at_data, 0,
-				(rcount - 1) * vol->mft_recordsize, &io);
+			(__s64)(rcount - 1) << vol->mft_record_size_bits, &io);
 	if (error)
 		return error;
-	if (io.size != vol->mft_recordsize)
+	if (io.size != vol->mft_record_size)
 		return -EIO;
 	error = ntfs_update_inode(vol->mft_ino);
 	if (error)
@@ -162,35 +168,47 @@
 	return 0;
 }
 
-/* Insert all attributes from the record mftno of the MFT in the inode ino.
+/*
+ * Insert all attributes from the record mftno of the MFT in the inode ino.
+ * If mftno is a base mft record we abort as soon as we find the attribute
+ * list, but only on the first pass. We will get called later when the attribute
+ * list attribute is being parsed so we need to distinguish the two cases.
  * FIXME: We should be performing structural consistency checks. (AIA)
- * Return 0 on success or -errno on error. */
+ * Return 0 on success or -errno on error.
+ */
 static int ntfs_insert_mft_attributes(ntfs_inode* ino, char *mft, int mftno)
 {
-	int i, error, type, len;
+	int i, error, type, len, present = 0;
 	char *it;
-	
-	/* Check for duplicate. */
-	for(i = 0; i < ino->record_count; i++)
-		if (ino->records[i] == mftno)
-			return 0;
-	/* (re-)allocate space if necessary. */
-	if (ino->record_count % 8 == 0)	{
-		int *new;
 
-		new = ntfs_malloc((ino->record_count + 8) * sizeof(int));
-		if (!new)
-			return -ENOMEM;
-		if (ino->records) {
-			for (i = 0; i < ino->record_count; i++)
-				new[i] = ino->records[i];
-			ntfs_free(ino->records);
-		}
-		ino->records = new;
-	}
-	ino->records[ino->record_count] = mftno;
-	ino->record_count++;
-	it = mft + NTFS_GETU16(mft + 0x14);
+	/* Check for duplicate extension record. */
+	for(i = 0; i < ino->record_count; i++)
+		if (ino->records[i] == mftno) {
+			if (i)
+				return 0;
+			present = 1;
+			break;
+		}
+	if (!present) {
+		/* (re-)allocate space if necessary. */
+		if (ino->record_count % 8 == 0)	{
+			int *new;
+
+			new = ntfs_malloc((ino->record_count + 8) *
+								sizeof(int));
+			if (!new)
+				return -ENOMEM;
+			if (ino->records) {
+				for (i = 0; i < ino->record_count; i++)
+					new[i] = ino->records[i];
+				ntfs_free(ino->records);
+			}
+			ino->records = new;
+		}
+		ino->records[ino->record_count] = mftno;
+		ino->record_count++;
+	}
+	it = mft + NTFS_GETU16(mft + 0x14); /* mft->attrs_offset */
 	do {
 		type = NTFS_GETU32(it);
 		len = NTFS_GETU32(it + 4);
@@ -199,8 +217,66 @@
 			if (error)
 				return error;
 		}
+		/* If we have just processed the attribute list and this is
+		 * the first time we are parsing this (base) mft record then we
+		 * are done so that the attribute list gets parsed before the
+		 * entries in the base mft record. Otherwise we run into
+		 * problems with encountering attributes out of order and when
+		 * this happens with different attribute extents we die. )-:
+		 * This way we are ok as the attribute list is always sorted
+		 * fully and correctly. (-: */
+		if (type == 0x20 && !present)
+			return 0;
 		it += len;
-	} while (type != -1); /* Attribute list ends with type -1. */
+	} while (type != -1); /* Attribute listing ends with type -1. */
+	return 0;
+}
+
+/*
+ * Insert a single specific attribute from the record mftno of the MFT in the
+ * inode ino. We disregard the attribute list assuming we have already parsed
+ * it.
+ * FIXME: We should be performing structural consistency checks. (AIA)
+ * Return 0 on success or -errno on error.
+ */
+static int ntfs_insert_mft_attribute(ntfs_inode* ino, int mftno,
+				     ntfs_u8 *attr)
+{
+	int i, error, present = 0;
+
+	/* Check for duplicate extension record. */
+	for(i = 0; i < ino->record_count; i++)
+		if (ino->records[i] == mftno) {
+			present = 1;
+			break;
+		}
+	if (!present) {
+		/* (re-)allocate space if necessary. */
+		if (ino->record_count % 8 == 0)	{
+			int *new;
+
+			new = ntfs_malloc((ino->record_count + 8) *
+								sizeof(int));
+			if (!new)
+				return -ENOMEM;
+			if (ino->records) {
+				for (i = 0; i < ino->record_count; i++)
+					new[i] = ino->records[i];
+				ntfs_free(ino->records);
+			}
+			ino->records = new;
+		}
+		ino->records[ino->record_count] = mftno;
+		ino->record_count++;
+	}
+	if (NTFS_GETU32(attr) == -1) {
+		ntfs_debug(DEBUG_FILE3, "ntfs_insert_mft_attribute: attribute "
+				"type is -1.\n");
+		return 0;
+	}
+	error = ntfs_insert_attribute(ino, attr);
+	if (error)
+		return error;
 	return 0;
 }
 
@@ -208,12 +284,17 @@
  * Return the number of remaining bytes in *plen. */
 static int parse_attributes(ntfs_inode *ino, ntfs_u8 *alist, int *plen)
 {
-	char *mft;
+	ntfs_u8 *mft, *attr;
 	int mftno, l, error;
 	int last_mft = -1;
 	int len = *plen;
 	
-	mft = ntfs_malloc(ino->vol->mft_recordsize);
+	if (!ino->attr) {
+		ntfs_error("parse_attributes: called on inode 0x%x without a "
+				"loaded base mft record.\n", ino->i_number);
+		return -EINVAL;
+	}
+	mft = ntfs_malloc(ino->vol->mft_record_size);
 	if (!mft)
 		return -ENOMEM;
 	while (len > 8)	{
@@ -222,23 +303,49 @@
 			break;
 	        /* Process an attribute description. */
 		mftno = NTFS_GETU32(alist + 0x10); 
-			/* FIXME: The mft reference (alist + 0x10) is __u64.
+			/* FIXME: The mft reference (alist + 0x10) is __s64.
 			* - Not a problem unless we encounter a huge partition.
 			* - Should be consistency checking the sequence numbers
 			*   though! This should maybe happen in 
 			*   ntfs_read_mft_record() itself and a hotfix could
 			*   then occur there or the user notified to run
 			*   ntfsck. (AIA) */
-		if (mftno != last_mft){
+		if (mftno != ino->i_number && mftno != last_mft) {
 			last_mft = mftno;
-			/* FIXME: Avoid loading record if it's already
-			 * processed. */
 			error = ntfs_read_mft_record(ino->vol, mftno, mft);
-			if (error)
-				return error;
-			error = ntfs_insert_mft_attributes(ino, mft, mftno);
-			if (error)
+			if (error) {
+				ntfs_debug(DEBUG_FILE3, "parse_attributes: "
+					"ntfs_read_mft_record(mftno = 0x%x) "
+					"failed\n", mftno);
+				ntfs_free(mft);
 				return error;
+			}
+		}
+		attr = ntfs_find_attr_in_mft_rec(
+				ino->vol,		/* ntfs volume */
+				mftno == ino->i_number ?/* mft record is: */
+					ino->attr:	/*   base record */
+					mft,		/*   extension record */
+				NTFS_GETU32(alist + 0),	/* type */
+				(wchar_t*)(alist + alist[7]),	/* name */
+				alist[6], 		/* name length */
+				1,			/* ignore case */
+				NTFS_GETU16(alist + 24)	/* instance number */
+				);
+		if (!attr) {
+			ntfs_error("parse_attributes: mft records 0x%x and/or "
+				       "0x%x corrupt!\n", ino->i_number, mftno);
+			ntfs_free(mft);
+			return -EINVAL; /* FIXME: Better error code? (AIA) */
+		}
+		error = ntfs_insert_mft_attribute(ino, mftno, attr);
+		if (error) {
+			ntfs_debug(DEBUG_FILE3, "parse_attributes: "
+				"ntfs_insert_mft_attribute(mftno 0x%x, "
+				"attribute type 0x%x) failed\n", mftno,
+				NTFS_GETU32(alist + 0));
+			ntfs_free(mft);
+			return error;
 		}
 		len -= l;
 		alist += l;
@@ -266,10 +373,13 @@
 		return;
 	ntfs_debug(DEBUG_FILE2, "load_attributes %x 4\n", ino->i_number);
 	datasize = alist->size;
+	ntfs_debug(DEBUG_FILE2, "load_attributes %x: alist->size = 0x%x\n",
+			ino->i_number, alist->size);
 	if (alist->resident) {
 		parse_attributes(ino, alist->d.data, &datasize);
 		return;
 	}
+	ntfs_debug(DEBUG_FILE2, "load_attributes %x 5\n", ino->i_number);
 	buf = ntfs_malloc(1024);
 	if (!buf)    /* FIXME: Should be passing error code to caller. (AIA) */
 		return;
@@ -281,16 +391,24 @@
 		io.fn_get = 0;
 		io.param = buf + delta;
 		io.size = len = min(datasize, 1024 - delta);
+		ntfs_debug(DEBUG_FILE2, "load_attributes %x: len = %i\n",
+						ino->i_number, len);
+		ntfs_debug(DEBUG_FILE2, "load_attributes %x: delta = %i\n",
+						ino->i_number, delta);
 		if (ntfs_read_attr(ino, vol->at_attribute_list, 0, offset,
 				   &io))
 			ntfs_error("error in load_attributes\n");
 		delta += len;
+		ntfs_debug(DEBUG_FILE2, "load_attributes %x: after += len, "
+				"delta = %i\n", ino->i_number, delta);
 		parse_attributes(ino, buf, &delta);
+		ntfs_debug(DEBUG_FILE2, "load_attributes %x: after parse_attr, "
+				"delta = %i\n", ino->i_number, delta);
 		if (delta)
 			/* Move remaining bytes to buffer start. */
 			ntfs_memmove(buf, buf + len - delta, delta);
 	}
-	ntfs_debug(DEBUG_FILE2, "load_attributes %x 5\n", ino->i_number);
+	ntfs_debug(DEBUG_FILE2, "load_attributes %x 6\n", ino->i_number);
 	ntfs_free(buf);
 }
 	
@@ -300,11 +418,9 @@
 	int error;
 
 	ntfs_debug(DEBUG_FILE1, "Initializing inode %x\n", inum);
-	if (!vol)
-		ntfs_error("NO VOLUME!\n");
 	ino->i_number = inum;
 	ino->vol = vol;
-	ino->attr = buf = ntfs_malloc(vol->mft_recordsize);
+	ino->attr = buf = ntfs_malloc(vol->mft_record_size);
 	if (!buf)
 		return -ENOMEM;
 	error = ntfs_read_mft_record(vol, inum, ino->attr);
@@ -342,7 +458,7 @@
 				ntfs_free(ino->attrs[i].d.data);
 		} else {
 			if (ino->attrs[i].d.r.runlist)
-				ntfs_free(ino->attrs[i].d.r.runlist);
+				ntfs_vfree(ino->attrs[i].d.r.runlist);
 		}
 	}
 	ntfs_free(ino->attrs);
@@ -352,7 +468,7 @@
 /* Check and fixup a MFT record. */
 int ntfs_check_mft_record(ntfs_volume *vol, char *record)
 {
-	return ntfs_fixup_record(vol, record, "FILE", vol->mft_recordsize);
+	return ntfs_fixup_record(vol, record, "FILE", vol->mft_record_size);
 }
 
 /* Return (in result) the value indicating the next available attribute 
@@ -406,7 +522,7 @@
 	return it;
 }
 
-int ntfs_get_attr_size(ntfs_inode *ino, int type, char *name)
+__s64 ntfs_get_attr_size(ntfs_inode *ino, int type, char *name)
 {
 	ntfs_attribute *attr = ntfs_find_attr(ino, type, name);
 	if (!attr)
@@ -462,6 +578,7 @@
 		ntfs_error("Can't decode run type field %x\n", type);
 		return -1;
 	}
+//	ntfs_debug(DEBUG_FILE3, "ntfs_decompress_run: length = 0x%x\n",*length);
 	if (*length < 0)
 	{
 		ntfs_error("Negative run length decoded\n");
@@ -502,6 +619,8 @@
 		ntfs_error("Can't decode run type field %x\n", type);
 		return -1;
 	}
+//	ntfs_debug(DEBUG_FILE3, "ntfs_decompress_run: cluster = 0x%x\n",
+//								*cluster);
 	*data += (type >> 4);
 	return 0;
 }
@@ -519,17 +638,18 @@
 /* Reads l bytes of the attribute (attr, name) of ino starting at offset on
  * vol into buf. Returns the number of bytes read in the ntfs_io struct.
  * Returns 0 on success, errno on failure */
-int ntfs_readwrite_attr(ntfs_inode *ino, ntfs_attribute *attr, int offset,
+int ntfs_readwrite_attr(ntfs_inode *ino, ntfs_attribute *attr, __s64 offset,
 			ntfs_io *dest)
 {
 	int rnum;
 	ntfs_cluster_t cluster, s_cluster, vcn, len;
-	int l, chunk, copied;
+	__s64 l, chunk, copied;
 	int s_vcn;
-	int clustersize;
-	int error;
+	int error, clustersizebits;
 
-	clustersize = ino->vol->clustersize;
+	ntfs_debug(DEBUG_FILE3, "ntfs_readwrite_attr 0: inode = 0x%x, attr->"
+		"type = 0x%x, offset = 0x%Lx, dest->size = 0x%x\n",
+		ino->i_number, attr->type, offset, dest->size);
 	l = dest->size;
 	if (l == 0)
 		return 0;
@@ -567,40 +687,49 @@
 		dest->size = l;
 		return 0;
 	}
-	/* Read uninitialized data. */
-	if (offset >= attr->initialized && dest->do_read)
-		return ntfs_read_zero(dest, l);
-	if (offset + l > attr->initialized && dest->do_read) {
-		dest->size = chunk = offset + l - attr->initialized;
-		error = ntfs_readwrite_attr(ino, attr, offset, dest);
-		if (error)
-			return error;		
-		return ntfs_read_zero(dest, l - chunk);
-	}
-	if (attr->compressed) {
-		if (dest->do_read)
+	if (dest->do_read) {
+		/* Read uninitialized data. */
+		if (offset >= attr->initialized)
+			return ntfs_read_zero(dest, l);
+		if (offset + l > attr->initialized) {
+			dest->size = chunk = offset + l - attr->initialized;
+			error = ntfs_readwrite_attr(ino, attr, offset, dest);
+			if (error)
+				return error;
+			return ntfs_read_zero(dest, l - chunk);
+		}
+		if (attr->compressed)
 			return ntfs_read_compressed(ino, attr, offset, dest);
-		else
+	} else {
+		if (attr->compressed)
 			return ntfs_write_compressed(ino, attr, offset, dest);
 	}
 	vcn = 0;
-	s_vcn = offset / clustersize;
+	clustersizebits = ino->vol->cluster_size_bits;
+	s_vcn = offset >> clustersizebits;
 	for (rnum = 0; rnum < attr->d.r.len && 
-		       vcn + attr->d.r.runlist[rnum].len <= s_vcn; rnum++)
+		       vcn + attr->d.r.runlist[rnum].len <= s_vcn; rnum++) {
 		vcn += attr->d.r.runlist[rnum].len;
-	if (rnum == attr->d.r.len)
+	}
+	if (rnum == attr->d.r.len) {
+		ntfs_debug(DEBUG_FILE3, "ntfs_readwrite_attr: EOPNOTSUPP: "
+			"inode = 0x%x, rnum = %i, offset = 0x%Lx, vcn = , 0x%x"
+			"s_vcn = 0x%x\n", ino->i_number, rnum, offset, vcn,
+			s_vcn);
 		/*FIXME: Should extend runlist. */
 		return -EOPNOTSUPP;
+	}
 	copied = 0;
 	while (l) {
-		s_vcn = offset / clustersize;
+		s_vcn = offset >> clustersizebits;
 		cluster = attr->d.r.runlist[rnum].cluster;
 		len = attr->d.r.runlist[rnum].len;
 		s_cluster = cluster + s_vcn - vcn;
-		chunk = min((vcn + len) * clustersize - offset, l);
+		chunk = min(((__s64)(vcn + len) << clustersizebits) - offset,
+									l);
 		dest->size = chunk;
-		error = ntfs_getput_clusters(ino->vol, s_cluster, 
-					   offset - s_vcn * clustersize, dest);
+		error = ntfs_getput_clusters(ino->vol, s_cluster, offset -
+				((__s64)s_vcn << clustersizebits), dest);
 		if (error) {
 			ntfs_error("Read/write error\n");
 			dest->size = copied;
@@ -609,7 +738,7 @@
 		l -= chunk;
 		copied += chunk;
 		offset += chunk;
-		if (l && offset >= ((vcn + len) * clustersize))	{
+		if (l && offset >= ((__s64)(vcn + len) << clustersizebits)) {
 			rnum++;
 			vcn += len;
 			cluster = attr->d.r.runlist[rnum].cluster;
@@ -620,19 +749,22 @@
 	return 0;
 }
 
-int ntfs_read_attr(ntfs_inode *ino, int type, char *name, int offset,
+int ntfs_read_attr(ntfs_inode *ino, int type, char *name, __s64 offset,
 		   ntfs_io *buf)
 {
 	ntfs_attribute *attr;
 
 	buf->do_read = 1;
 	attr = ntfs_find_attr(ino, type, name);
-	if (!attr)
+	if (!attr) {
+		ntfs_debug(DEBUG_FILE3, "ntfs_read_attr: attr 0x%x not found "
+				"in inode 0x%x\n", type, ino->i_number);
 		return -EINVAL;
+	}
 	return ntfs_readwrite_attr(ino, attr, offset, buf);
 }
 
-int ntfs_write_attr(ntfs_inode *ino, int type, char *name, int offset,
+int ntfs_write_attr(ntfs_inode *ino, int type, char *name, __s64 offset,
 		    ntfs_io *buf)
 {
 	ntfs_attribute *attr;
@@ -653,15 +785,19 @@
 	/* It's hard to give an error code. */
 	if (!data || data->resident || data->compressed)
 		return -1;
-	if (data->size <= vcn*ino->vol->clustersize)
+	if (data->size <= (__s64)vcn << ino->vol->cluster_size_bits)
 		return -1;
-	/* For Linux, block number 0 represents a hole.
-	 * Hopefully, nobody will attempt to bmap $Boot. */
-	if (data->initialized <= vcn * ino->vol->clustersize)
+	/*
+	 * For Linux, block number 0 represents a hole. Hopefully, nobody will
+	 * attempt to bmap $Boot. FIXME: Hopes are not good enough! We need to
+	 * fix this properly before reenabling mmap-ed stuff. (AIA)
+	 */
+	if (data->initialized <= (__s64)vcn << ino->vol->cluster_size_bits)
 		return 0;
 	for (rnum = 0; rnum < data->d.r.len &&
-		       vcn >= data->d.r.runlist[rnum].len; rnum++)
+				vcn >= data->d.r.runlist[rnum].len; rnum++)
 		vcn -= data->d.r.runlist[rnum].len;
+	/* We need to cope with sparse runs. (AIA) */
 	return data->d.r.runlist[rnum].cluster + vcn;
 }
 
@@ -685,7 +821,7 @@
 		store->records = n;
 	}
 	for (i = store->count; i < count; i++) {
-		store->records[i].record = ntfs_malloc(vol->mft_recordsize);
+		store->records[i].record = ntfs_malloc(vol->mft_record_size);
 		if (!store->records[i].record)
 			return -ENOMEM;
 		store->count++;
@@ -717,79 +853,99 @@
  * mapping pairs array. On exit, it contains the offset in @rec of the first
  * byte after the end of the mapping pairs array.
  */
-static int layout_runs(ntfs_attribute *attr, char* rec, int* offs, int size)
+static int layout_runs(ntfs_attribute *attr, char *rec, int *offs, int size)
 {
 	int i, len, offset, coffs;
+	/* ntfs_cluster_t MUST be signed! (AIA) */
 	ntfs_cluster_t cluster, rclus;
 	ntfs_runlist *rl = attr->d.r.runlist;
 	cluster = 0;
 	offset = *offs;
 	for (i = 0; i < attr->d.r.len; i++) {
+		/*
+		 * We cheat with this check on the basis that cluster will never
+		 * be less than -1 and the cluster delta will fit in signed
+		 * 32-bits (ntfs_cluster_t). (AIA)
+		 */
+		if (rl[i].cluster < (ntfs_cluster_t)-1) {
+			ntfs_error("layout_runs() encountered an out of bounds "
+					"cluster delta!\n");
+			return -ERANGE;
+		}
 		rclus = rl[i].cluster - cluster;
 		len = rl[i].len;
 		rec[offset] = 0;
  		if (offset + 9 > size)
 			return -E2BIG; /* It might still fit, but this
 					* simplifies testing. */
-		/* Run length is stored as signed number. */
-		if (len <= 0x7F) {
-			NTFS_PUTU8(rec + offset + 1, len);
+		/*
+		 * Run length is stored as signed number, so deal with it
+		 * properly, i.e. observe that a negative number will have all
+		 * its most significant bits set to 1 but we don't store that
+		 * in the mapping pairs array. We store the smallest type of
+		 * negative number required, thus in the first if we check
+		 * whether len fits inside a signed byte and if so we store it
+		 * as such, the next ifs check for a signed short, then a signed
+		 * 24-bit and finally the full blown signed 32-bit. Same goes
+		 * for rlus below. (AIA)
+		 */
+		if (len >= -0x80 && len <= 0x7f) {
+			NTFS_PUTU8(rec + offset + 1, len & 0xff);
 			coffs = 1;
- 		} else if (len <= 0x7FFF) {
-			NTFS_PUTU16(rec + offset + 1, len);
+ 		} else if (len >= -0x8000 && len <= 0x7fff) {
+			NTFS_PUTU16(rec + offset + 1, len & 0xffff);
 			coffs = 2;
- 		} else if (len <= 0x7FFFFF) {
-			NTFS_PUTU24(rec + offset + 1, len);
+ 		} else if (len >= -0x800000 && len <= 0x7fffff) {
+			NTFS_PUTU24(rec + offset + 1, len & 0xffffff);
 			coffs = 3;
-		} else {
+		} else /* if (len >= -0x80000000LL && len <= 0x7fffffff */ {
 			NTFS_PUTU32(rec + offset + 1, len);
 			coffs = 4;
-		}
-    		*(rec + offset) |= coffs++;
-		if (rl[i].cluster == MAX_CLUSTER_T) /* Compressed run. */
+		} /* else ... FIXME: When len becomes 64-bit we need to extend
+		   * 		     the else if () statements. (AIA) */
+		*(rec + offset) |= coffs++;
+		if (rl[i].cluster == (ntfs_cluster_t)-1) /* Compressed run. */
 			/* Nothing */;
-		else if (rclus >= -0x80 && rclus <= 0x7F) {
+		else if (rclus >= -0x80 && rclus <= 0x7f) {
 			*(rec + offset) |= 0x10;
-			NTFS_PUTS8(rec + offset + coffs, rclus);
+			NTFS_PUTS8(rec + offset + coffs, rclus & 0xff);
 			coffs += 1;
-		} else if(rclus >= -0x8000 && rclus <= 0x7FFF) {
+		} else if (rclus >= -0x8000 && rclus <= 0x7fff) {
 			*(rec + offset) |= 0x20;
-			NTFS_PUTS16(rec + offset + coffs, rclus);
+			NTFS_PUTS16(rec + offset + coffs, rclus & 0xffff);
 			coffs += 2;
-		} else if(rclus >= -0x800000 && rclus <= 0x7FFFFF) {
+		} else if (rclus >= -0x800000 && rclus <= 0x7fffff) {
 			*(rec + offset) |= 0x30;
-			NTFS_PUTS24(rec + offset + coffs, rclus);
+			NTFS_PUTS24(rec + offset + coffs, rclus & 0xffffff);
 			coffs += 3;
-		} else
-#if 0 /* In case ntfs_cluster_t ever becomes 64bit. */
-	       	if (rclus >= -0x80000000LL && rclus <= 0x7FFFFFFF)
-#endif
-		{
+		} else /* if (rclus >= -0x80000000LL && rclus <= 0x7fffffff)*/ {
 			*(rec + offset) |= 0x40;
-			NTFS_PUTS32(rec + offset + coffs, rclus);
+			NTFS_PUTS32(rec + offset + coffs, rclus
+							/* & 0xffffffffLL */);
 			coffs += 4;
-		}
-#if 0 /* For 64-bit ntfs_cluster_t */
+		} /* FIXME: When rclus becomes 64-bit.
 		else if (rclus >= -0x8000000000 && rclus <= 0x7FFFFFFFFF) {
 			*(rec + offset) |= 0x50;
-			NTFS_PUTS40(rec + offset + coffs, rclus);
+			NTFS_PUTS40(rec + offset + coffs, rclus &
+							0xffffffffffLL);
 			coffs += 5;
 		} else if (rclus >= -0x800000000000 && 
 						rclus <= 0x7FFFFFFFFFFF) {
 			*(rec + offset) |= 0x60;
-			NTFS_PUTS48(rec + offset + coffs, rclus);
+			NTFS_PUTS48(rec + offset + coffs, rclus &
+							0xffffffffffffLL);
 			coffs += 6;
 		} else if (rclus >= -0x80000000000000 && 
 						rclus <= 0x7FFFFFFFFFFFFF) {
 			*(rec + offset) |= 0x70;
-			NTFS_PUTS56(rec + offset + coffs, rclus);
+			NTFS_PUTS56(rec + offset + coffs, rclus &
+							0xffffffffffffffLL);
 			coffs += 7;
 		} else {
 			*(rec + offset) |= 0x80;
 			NTFS_PUTS64(rec + offset + coffs, rclus);
 			coffs += 8;
-		}
-#endif
+		} */
 		offset += coffs;
 		if (rl[i].cluster)
 			cluster = rl[i].cluster;
@@ -828,64 +984,59 @@
  */
 static int layout_attr(ntfs_attribute* attr, char *buf, int size, int *psize)
 {
-	int asize, error;
-	if (size < 10)
-		return -E2BIG;
-	NTFS_PUTU32(buf, attr->type);
-	/* Fill in length later. */
-	NTFS_PUTU8(buf + 8, attr->resident ? 0 : 1);
-	NTFS_PUTU8(buf + 9, attr->namelen);
-	/* Fill in offset to name later. */
-	NTFS_PUTU16(buf + 0xA, 0);
-	NTFS_PUTU16(buf + 0xC, attr->compressed);
-	/* Assign attribute instance. */
-	NTFS_PUTU16(buf + 0xE, attr->attrno);
+	int nameoff, hdrsize, asize;
+	
 	if (attr->resident) {
-		if (size < attr->size + 0x18 + attr->namelen)
+		nameoff = 0x18;
+		hdrsize = (nameoff + 2 * attr->namelen + 7) & ~7;
+		asize = (hdrsize + attr->size + 7) & ~7;
+		if (size < asize)
 			return -E2BIG;
-		asize = 0x18;
 		NTFS_PUTU32(buf + 0x10, attr->size);
 		NTFS_PUTU16(buf + 0x16, attr->indexed);
-		if (attr->name) {
-			ntfs_memcpy(buf + asize, attr->name, 2 * attr->namelen);
-			NTFS_PUTU16(buf + 0xA, asize);
-			asize += 2 * attr->namelen;
-			asize = (asize + 7) & ~7;
-		}
-		NTFS_PUTU16(buf + 0x14, asize);
-		ntfs_memcpy(buf + asize, attr->d.data, attr->size);
-		asize += attr->size;
+		NTFS_PUTU16(buf + 0x14, hdrsize);
+		if (attr->size)
+			ntfs_memcpy(buf + hdrsize, attr->d.data, attr->size);
 	} else {
+		int error;
+
+ 		if (attr->compressed)
+ 			nameoff = 0x48;
+ 		else
+ 			nameoff = 0x40;
+ 		hdrsize = (nameoff + 2 * attr->namelen + 7) & ~7;
+ 		if (size < hdrsize)
+ 			return -E2BIG;
+ 		/* Make asize point at the end of the attribute record header,
+		   i.e. at the beginning of the mapping pairs array. */
+ 		asize = hdrsize;
+ 		error = layout_runs(attr, buf, &asize, size);
+ 		/* Now, asize points one byte beyond the end of the mapping
+		   pairs array. */
+		if (error)
+ 			return error;
+ 		/* The next attribute has to begin on 8-byte boundary. */
+		asize = (asize + 7) & ~7;
 		/* FIXME: fragments */
 		count_runs(attr, buf);
-		/* Offset to data is added later. */
+		NTFS_PUTU16(buf + 0x20, hdrsize);
 		NTFS_PUTU16(buf + 0x22, attr->cengine);
 		NTFS_PUTU32(buf + 0x24, 0);
-		NTFS_PUTU64(buf + 0x28, attr->allocated);
-		NTFS_PUTU64(buf + 0x30, attr->size);
-		NTFS_PUTU64(buf + 0x38, attr->initialized);
-		if (attr->compressed) {
-			NTFS_PUTU64(buf + 0x40, attr->compsize);
-			asize = 0x48;
-		} else
-			asize = 0x40;
-		if (attr->name) {
-			NTFS_PUTU16(buf + 0xA, asize);
-			ntfs_memcpy(buf + asize, attr->name, 2 * attr->namelen);
-			asize += 2 * attr->namelen;
-			/* SRD: you whaaa? - AIA: Align to next 8 byte boundary
-			 * as required by NTFS design and implementation. */
-			asize = (asize + 7) & ~7;
-		}
-		/* asize points at the beginning of the data. */
-		NTFS_PUTU16(buf + 0x20, asize);
-		error = layout_runs(attr, buf, &asize, size);
-		/* Now asize points at the end of the data. */
-		if (error)
-			return error;
+		NTFS_PUTS64(buf + 0x28, attr->allocated);
+		NTFS_PUTS64(buf + 0x30, attr->size);
+		NTFS_PUTS64(buf + 0x38, attr->initialized);
+		if (attr->compressed)
+			NTFS_PUTS64(buf + 0x40, attr->compsize);
 	}
-	asize = (asize + 7) & ~7;
+	NTFS_PUTU32(buf, attr->type);
 	NTFS_PUTU32(buf + 4, asize);
+	NTFS_PUTU8(buf + 8, attr->resident ? 0 : 1);
+	NTFS_PUTU8(buf + 9, attr->namelen);
+	NTFS_PUTU16(buf + 0xa, nameoff);
+	NTFS_PUTU16(buf + 0xc, attr->compressed);
+	NTFS_PUTU16(buf + 0xe, attr->attrno);
+	if (attr->namelen)
+		ntfs_memcpy(buf + nameoff, attr->name, 2 * attr->namelen);
 	*psize = asize;
 	return 0;
 }
@@ -905,42 +1056,56 @@
  */
 int layout_inode(ntfs_inode *ino, ntfs_disk_inode *store)
 {
-	int offset, i;
+	int offset, i, size, psize, error, count, recno;
 	ntfs_attribute *attr;
 	unsigned char *rec;
-	int size, psize;
-	int error;
 
-	if (ino->record_count > 1) {
-		ntfs_error("layout_inode: attribute lists not supported\n");
-		return -EOPNOTSUPP;
-	}
-	error = allocate_store(ino->vol, store, 1);
+	error = allocate_store(ino->vol, store, ino->record_count);
 	if (error)
 		return error;
-	rec = store->records[0].record;
-	size = ino->vol->mft_recordsize;
-	store->records[0].recno = ino->records[0];
-	/* Copy header. */
-	offset = NTFS_GETU16(ino->attr + 0x14);
-	ntfs_memcpy(rec, ino->attr, offset);
-	for (i = 0; i < ino->attr_count; i++) {
-		attr = ino->attrs + i;
-		error = layout_attr(attr, rec + offset, size - offset, &psize);
-		if (error)
-			return error;
-		offset += psize;
-	}
-	/* Terminating attribute. */
-	if (offset + 8 < size) {
+	size = ino->vol->mft_record_size;
+ 	count = i = 0;
+ 	do {
+ 		if (count < ino->record_count) {
+ 			recno = ino->records[count];
+ 		} else {
+ 			error = allocate_store(ino->vol, store, count + 1);
+ 			if (error)
+ 				return error;
+	 		recno = -1;
+		}
+		/*
+		 * FIXME: We need to support extension records properly.
+		 * At the moment they wouldn't work. Probably would "just" get
+		 * corrupted if we write to them... (AIA)
+		 */
+	 	store->records[count].recno = recno;
+ 		rec = store->records[count].record;
+	 	count++;
+ 		/* Copy header. */
+	 	offset = NTFS_GETU16(ino->attr + 0x14);
+		ntfs_memcpy(rec, ino->attr, offset);
+	 	/* Copy attributes. */
+ 		while (i < ino->attr_count) {
+ 			attr = ino->attrs + i;
+	 		error = layout_attr(attr, rec + offset,
+						size - offset - 8, &psize);
+	 		if (error == -E2BIG && offset != NTFS_GETU16(ino->attr
+						+ 0x14))
+ 				break;
+ 			if (error)
+ 				return error;
+ 			offset += psize;
+ 			i++;
+ 		}
+ 		/* Terminating attribute. */
 		NTFS_PUTU32(rec + offset, 0xFFFFFFFF);
 		offset += 4;
 		NTFS_PUTU32(rec + offset, 0);
 		offset += 4;
-	} else
-		return -E2BIG;
-	NTFS_PUTU32(rec + 0x18, offset);
-	return 0;
+		NTFS_PUTU32(rec + 0x18, offset);
+	} while (i < ino->attr_count || count < ino->record_count);
+	return count - ino->record_count;
 }
 
 /*
@@ -952,13 +1117,11 @@
  */
 int ntfs_update_inode(ntfs_inode *ino)
 {
-	int error;
+	int error, i;
 	ntfs_disk_inode store;
 	ntfs_io io;
-	int i;
 
-	store.count = store.size = 0;
-	store.records = 0;
+	ntfs_bzero(&store, sizeof(store));
 	error = layout_inode(ino, &store);
 	if (error == -E2BIG) {
 		error = ntfs_split_indexroot(ino);
@@ -970,13 +1133,14 @@
 		if (!error)
 			error = layout_inode(ino, &store);
 	}
-	if (error == -E2BIG) {
-		/* FIXME: should try: introduce extension records */
-		ntfs_error("cannot handle saving inode %x\n", ino->i_number);
-		deallocate_store(&store);
-		return -EOPNOTSUPP;
+	if (error > 0) {
+		/* FIXME: Introduce extension records. */
+		error = -E2BIG;
 	}
 	if (error) {
+		if (error == -E2BIG)
+			ntfs_error("cannot handle saving inode %x\n",
+				   ino->i_number);
 		deallocate_store(&store);
 		return error;
 	}
@@ -984,21 +1148,22 @@
 	io.fn_put = 0;
 	for (i = 0; i < store.count; i++) {
 		ntfs_insert_fixups(store.records[i].record,
-							  ino->vol->blocksize);
+						ino->vol->sector_size);
 		io.param = store.records[i].record;
-		io.size = ino->vol->mft_recordsize;
+		io.size = ino->vol->mft_record_size;
 		/* FIXME: Is this the right way? */
 		error = ntfs_write_attr(ino->vol->mft_ino, ino->vol->at_data,
-					0, store.records[i].recno * 
-					ino->vol->mft_recordsize, &io);
-		if (error || io.size != ino->vol->mft_recordsize) {
+					0, (__s64)store.records[i].recno <<
+					ino->vol->mft_record_size_bits, &io);
+		if (error || io.size != ino->vol->mft_record_size) {
 			/* Big trouble, partially written file. */
-			ntfs_error("Please unmount: Write error in inode %x\n",
-				   ino->i_number);
+			ntfs_error("Please unmount: Write error in inode "
+					"0x%x\n", ino->i_number);
 			deallocate_store(&store);
 			return error ? error : -EIO;
 		}
 	}
+	deallocate_store(&store);
 	return 0;
 }	
 
@@ -1080,19 +1245,42 @@
 	}
 }
 
-/* Caveat: No range checking in either ntfs_set_bit or ntfs_clear_bit. */
-void ntfs_set_bit(unsigned char *byte, int bit)
+/*
+ * NOTE: Neither of the ntfs_*_bit functions are atomic! But we don't need
+ * them atomic at present as we never operate on shared/cached bitmaps.
+ */
+static __inline__ int ntfs_get_bit(unsigned char *byte, const int bit)
+{
+	return byte[bit >> 3] & (1 << (bit & 7)) ? 1 : 0;
+}
+
+static __inline__ void ntfs_set_bit(unsigned char *byte, const int bit)
+{
+	byte[bit >> 3] |= 1 << (bit & 7);
+}
+
+static __inline__ void ntfs_clear_bit(unsigned char *byte, const int bit)
 {
-	byte += (bit >> 3);
-	bit &= 7;
-	*byte |= (1 << bit);
+	byte[bit >> 3] &= ~(1 << (bit & 7));
 }
 
-void ntfs_clear_bit(unsigned char *byte, int bit)
+__inline__ int ntfs_test_and_set_bit(unsigned char *byte, const int bit)
 {
-	byte += (bit >> 3);
-	bit &= 7;
-	*byte &= ~(1 << bit);
+	unsigned char *ptr = byte + (bit >> 3);
+	int b = 1 << (bit & 7);
+	int oldbit = *ptr & b ? 1 : 0;
+	*ptr |= b;
+	return oldbit;
+}
+
+static __inline__ int ntfs_test_and_clear_bit(unsigned char *byte,
+					      const int bit)
+{
+	unsigned char *ptr = byte + (bit >> 3);
+	int b = 1 << (bit & 7);
+	int oldbit = *ptr & b ? 1 : 0;
+	*ptr &= ~b;
+	return oldbit;
 }
 
 /**
@@ -1104,50 +1292,87 @@
  * and allocating it in the mft bitmap.
  * Return 0 on success or -ERRNO on error.
  *
- * TODO(AIA): Implement mft bitmap caching. Replace function by race safe one.
+ * TODO(AIA): Implement mft bitmap caching.
  */
-static int ntfs_new_inode(ntfs_volume* vol, int* result)
+static int ntfs_new_inode(ntfs_volume *vol, unsigned long *result)
 {
-	int byte, error;
-	int bit;
-	int size, length;
+	int byte, bit, error, size, length;
 	unsigned char value;
 	ntfs_u8 *buffer;
 	ntfs_io io;
 	ntfs_attribute *data;
 
-	buffer = ntfs_malloc(2048);
+	*result = 0;
+	/* Determine the number of mft records in the mft. */
+	data = ntfs_find_attr(vol->mft_ino, vol->at_data, 0);
+	length = data->size >> vol->mft_record_size_bits;
+	/* Allocate sufficient space for the mft bitmap attribute value,
+	   inferring it from the number of mft records. */
+	buffer = ntfs_malloc((length + 7) >> 3);
 	if (!buffer)
 		return -ENOMEM;
 	io.fn_put = ntfs_put;
 	io.fn_get = ntfs_get;
+try_again:
 	io.param = buffer;
-	/* FIXME: Bitmaps larger than 2048 bytes. */
-	io.size = 2048;
+	io.size = (length + 7) >> 3;
 	error = ntfs_read_attr(vol->mft_ino, vol->at_bitmap, 0, 0, &io);
-	if (error) {
-		ntfs_free(buffer);
-		return error;
-	}
+	if (error)
+		goto err_out;
 	size = io.size;
-	data = ntfs_find_attr(vol->mft_ino, vol->at_data, 0);
-	length = data->size / vol->mft_recordsize;
-	/* SRD: Start at byte 0: bits for system files _are_ already set in 
-	 * bitmap. AIA: This includes the reserved entries as well. */
-	for (byte = 0; 8 * byte < length; byte++) {
+	/* Start at byte 0, as the bits for all 16 system files are already
+	   set in the bitmap. */
+	for (bit = byte = 0; (byte << 3) < length; byte++) {
 		value = buffer[byte];
 		if (value == 0xFF)
 			continue;
-		for (bit = 0; (bit < 8) && (8 * byte + bit < length); 
-							 bit++, value >>= 1) {
-			if (!(value & 1)) {
-				*result = byte * 8 + bit;
-				return 0;
-			}
-		}
+		bit = ffz(value);
+		if (bit < 8)
+			break;
+	}
+	if ((byte << 3) + bit >= length) {
+		/* No free space left. Need to extend the mft. */
+		error = -ENOSPC;
+		goto err_out;
+	}
+	/* Get the byte containing our bit again, now taking the BKL. */
+	io.param = buffer;
+	io.size = 1;
+	lock_kernel();
+	error = ntfs_read_attr(vol->mft_ino, vol->at_bitmap, 0, byte, &io);
+	if (error || (io.size != 1 && (error = -EIO, 1)))
+		goto err_unl_out;
+	if (ntfs_test_and_set_bit(buffer, bit)) {
+		unlock_kernel();
+		/* Give other process(es) a chance to finish. */
+		schedule();
+		goto try_again;
 	}
-	/* There is no free space. We must first extend the MFT. */
-	return -ENOSPC;
+	io.param = buffer;
+ 	error = ntfs_write_attr(vol->mft_ino, vol->at_bitmap, 0, byte, &io);
+	if (error || (io.size != 1 && (error = -EIO, 1)))
+		goto err_unl_out;
+	/* Change mft on disk, required when mft bitmap is resident. */
+	error = ntfs_update_inode(vol->mft_ino);
+	if (!error)
+		*result = (byte << 3) + bit;
+err_unl_out:
+	unlock_kernel();
+err_out:
+	ntfs_free(buffer);
+#ifdef DEBUG
+	if (error)
+		printk(KERN_INFO "ntfs_new_inode() failed to allocate an "
+				 "mft record. Error = %i\n", error);
+	else
+		printk(KERN_INFO "ntfs_new_inode() allocated mft record number "
+				 "0x%lx\n", *result);
+#endif
+	return error;
+	/*
+	 * FIXME: Don't forget $MftMirr, though this probably belongs
+	 * in ntfs_update_inode() (or even deeper). (AIA)
+	 */
 }
 
 static int add_mft_header(ntfs_inode *ino)
@@ -1156,8 +1381,8 @@
 	ntfs_volume *vol = ino->vol;
 
 	mft = ino->attr;
-	ntfs_bzero(mft, vol->mft_recordsize);
-	ntfs_fill_mft_header(mft, vol->mft_recordsize, vol->blocksize,
+	ntfs_bzero(mft, vol->mft_record_size);
+	ntfs_fill_mft_header(mft, vol->mft_record_size, vol->sector_size,
 			     ino->sequence_number);
 	return 0;
 }
@@ -1183,8 +1408,6 @@
 	return error;
 }
 
-/* FIXME: Need to pass in the size of the file (Data size) as well as the
- * allocated size for file data on disk (Allocated size). (AIA) */
 static int add_filename(ntfs_inode* ino, ntfs_inode* dir, 
 			const unsigned char *filename, int length, 
 			ntfs_u32 flags)
@@ -1201,7 +1424,6 @@
 	data = ntfs_malloc(size);
 	if (!data)
 		return -ENOMEM;
-	ntfs_bzero(data, size);
 	/* Search for a position. */
 	position = data;
 	NTFS_PUTINUM(position, dir);			/* Inode num of dir */
@@ -1210,10 +1432,16 @@
 	NTFS_PUTU64(position + 0x10, now);		/* Last modification */
 	NTFS_PUTU64(position + 0x18, now);		/* Last mod for MFT */
 	NTFS_PUTU64(position + 0x20, now);		/* Last access */
-	/*NTFS_PUTU64(position + 0x28, 0);*/		/* Allocated size */
-	/*NTFS_PUTU64(position + 0x30, 0);*/		/* Data size */
+	/* FIXME: Get the following two sizes by finding the data attribute
+	 * in ino->attr and copying the corresponding fields from there.
+	 * If no data present then set to zero. In current implementation
+	 * add_data is called after add_filename so zero is correct on
+	 * creation. Need to change when we have hard links / support different
+	 * filename namespaces. (AIA) */
+	NTFS_PUTS64(position + 0x28, 0);		/* Allocated size */
+	NTFS_PUTS64(position + 0x30, 0);		/* Data size */
 	NTFS_PUTU32(position + 0x38, flags);		/* File flags */
-	/*NTFS_PUTU32(position + 0x3c, 0);*/		/* We don't use these
+	NTFS_PUTU32(position + 0x3c, 0);		/* We don't use these
 							 * features yet. */
 	NTFS_PUTU8(position + 0x40, length);		/* Filename length */
 	NTFS_PUTU8(position + 0x41, 0);			/* Only long name */
@@ -1281,11 +1509,10 @@
 int ntfs_alloc_inode(ntfs_inode *dir, ntfs_inode *result, const char *filename,
 		     int namelen, ntfs_u32 flags)
 {
-	ntfs_io io;
 	int error;
-	ntfs_u8 buffer[2];
 	ntfs_volume *vol = dir->vol;
-	int byte, bit;
+	ntfs_u8 buffer[2];
+	ntfs_io io;
 
 	error = ntfs_new_inode(vol, &(result->i_number));
 	if (error == -ENOSPC) {
@@ -1295,50 +1522,26 @@
 		error = ntfs_new_inode(vol, &(result->i_number));
 	}
 	if (error) {
-		ntfs_error("ntfs_get_empty_inode: no free inodes\n");
+		if (error == -ENOSPC)
+			ntfs_error("ntfs_get_empty_inode: no free inodes\n");
 		return error;
 	}
-	byte = result->i_number / 8;
-	bit = result->i_number & 7;
+	/* Get the sequence number. */
 	io.fn_put = ntfs_put;
 	io.fn_get = ntfs_get;
 	io.param = buffer;
-	io.size = 1;
-	/* Set a single bit. */
-	error = ntfs_read_attr(vol->mft_ino, vol->at_bitmap, 0, byte, &io);
-	if (error)
-		return error;
-	if (io.size != 1)
-		return -EIO;
-	ntfs_set_bit(buffer, bit);
-	io.param = buffer;
-	io.size = 1;
- 	error = ntfs_write_attr(vol->mft_ino, vol->at_bitmap, 0, byte, &io);
-	if (error)
-		return error;
-	if (io.size != 1)
-		return -EIO;
-	/* FIXME: Should change $Mft on disk.
-	 * error = ntfs_update_inode(vol->mft_ino);
-	 * if (error)
-	 * 	return error; 
-	 * FIXME: And don't forget $MftMirr, though this probably belongs
-	 * in ntfs_update_inode() (or even deeper). (AIA) */
-	/* Get the sequence number. */
-	io.param = buffer;
 	io.size = 2;
 	error = ntfs_read_attr(vol->mft_ino, vol->at_data, 0, 
-			       result->i_number * vol->mft_recordsize + 0x10,
-			       &io);
+			((__s64)result->i_number << vol->mft_record_size_bits)
+			+ 0x10, &io);
 	if (error)
 		return error;
 	/* Increment the sequence number skipping zero. */
-	if (NTFS_GETU16(buffer) == 0xffff)
-		result->sequence_number = 1;
-	else
-		result->sequence_number = NTFS_GETU16(buffer) + 1;
+	result->sequence_number = (NTFS_GETU16(buffer) + 1) & 0xffff;
+	if (!result->sequence_number)
+		result->sequence_number++;
 	result->vol = vol;
-	result->attr = ntfs_malloc(vol->mft_recordsize);
+	result->attr = ntfs_malloc(vol->mft_record_size);
 	if (!result->attr)
 		return -ENOMEM;
 	result->attr_count = 0;
diff -urN linux-2.4.7-pre6/fs/ntfs/inode.h linux/fs/ntfs/inode.h
--- linux-2.4.7-pre6/fs/ntfs/inode.h	Wed Apr 18 11:49:13 2001
+++ linux/fs/ntfs/inode.h	Mon Dec  3 22:55:50 2001
@@ -1,16 +1,18 @@
-/*  inode.h -  Header file for inode.c
+/*
+ * inode.h -  Header file for inode.c
  *
- *  Copyright (C) 1997 Régis Duchesne
- *  Copyright (C) 1998 Martin von Löwis
+ * Copyright (C) 1997 Régis Duchesne
+ * Copyright (C) 1998 Martin von Löwis
+ * Copyright (c) 2001 Anton Altparmakov (AIA)
  */
 
 ntfs_attribute *ntfs_find_attr(ntfs_inode *ino, int type, char *name);
 
-int ntfs_read_attr(ntfs_inode *ino, int type, char *name, int offset,
-		   ntfs_io *buf);
+int ntfs_read_attr(ntfs_inode *ino, int type, char *name, __s64 offset,
+		ntfs_io *buf);
 
-int ntfs_write_attr(ntfs_inode *ino, int type, char *name, int offset,
-		    ntfs_io *buf);
+int ntfs_write_attr(ntfs_inode *ino, int type, char *name, __s64 offset,
+		ntfs_io *buf);
 
 int ntfs_init_inode(ntfs_inode *ino, ntfs_volume *vol, int inum);
 
@@ -19,25 +21,28 @@
 int ntfs_check_mft_record(ntfs_volume *vol, char *record);
 
 int ntfs_alloc_inode(ntfs_inode *dir, ntfs_inode *result, const char *filename,
-		     int namelen, ntfs_u32);
+		int namelen, ntfs_u32);
 
 int ntfs_alloc_file(ntfs_inode *dir, ntfs_inode *result, char *filename,
-		    int namelen);
+		int namelen);
 
 int ntfs_update_inode(ntfs_inode *ino);
 
 int ntfs_vcn_to_lcn(ntfs_inode *ino, int vcn);
 
-int ntfs_readwrite_attr(ntfs_inode *ino, ntfs_attribute *attr, int offset,
-			ntfs_io *dest);
+int ntfs_readwrite_attr(ntfs_inode *ino, ntfs_attribute *attr, __s64 offset,
+		ntfs_io *dest);
 
 int ntfs_allocate_attr_number(ntfs_inode *ino, int *result);
 
 int ntfs_decompress_run(unsigned char **data, int *length,
-			ntfs_cluster_t *cluster, int *ctype);
+		ntfs_cluster_t *cluster, int *ctype);
 
 void ntfs_decompress(unsigned char *dest, unsigned char *src, ntfs_size_t l);
 
 void ntfs_fill_mft_header(ntfs_u8 *mft, int recordsize, int blocksize,
-			  int sequence_number);
+		int sequence_number);
+
+extern __inline__ int ntfs_test_and_set_bit(unsigned char *byte,
+		const int bit);
 
diff -urN linux-2.4.7-pre6/fs/ntfs/macros.h linux/fs/ntfs/macros.h
--- linux-2.4.7-pre6/fs/ntfs/macros.h	Wed Apr 18 11:49:13 2001
+++ linux/fs/ntfs/macros.h	Mon Dec  3 22:55:50 2001
@@ -19,7 +19,6 @@
 
 #define IS_MAGIC(a,b)		(*(int*)(a) == *(int*)(b))
 #define IS_MFT_RECORD(a)	IS_MAGIC((a),"FILE")
-#define IS_NTFS_VOLUME(a)	IS_MAGIC((a) + 3,"NTFS")
 #define IS_INDEX_RECORD(a)	IS_MAGIC((a),"INDX")
 
 /* 'NTFS' in little endian */
diff -urN linux-2.4.7-pre6/fs/ntfs/ntfsendian.h linux/fs/ntfs/ntfsendian.h
--- linux-2.4.7-pre6/fs/ntfs/ntfsendian.h	Wed Apr 18 11:49:13 2001
+++ linux/fs/ntfs/ntfsendian.h	Mon Dec  3 22:55:50 2001
@@ -1,11 +1,11 @@
-/*  ntfsendian.h
+/*
+ * ntfsendian.h
  *
- *  Copyright (C) 1998, 1999 Martin von Löwis
- *  Copyright (C) 1998 Joseph Malicki
- *  Copyright (C) 1999 Werner Seiler
- *  Copyright (C) 2001 Anton Altaparmakov (AIA)
+ * Copyright (C) 1998, 1999 Martin von Löwis
+ * Copyright (C) 1998 Joseph Malicki
+ * Copyright (C) 1999 Werner Seiler
+ * Copyright (C) 2001 Anton Altaparmakov (AIA)
  */
-
 #include <asm/byteorder.h>
 
 #define CPU_TO_LE16(a) __cpu_to_le16(a)
@@ -56,4 +56,5 @@
 #define NTFS_PUTS16(p,v)     NTFS_PUTU16(p,v)
 #define NTFS_PUTS24(p,v)     NTFS_PUTU24(p,v)
 #define NTFS_PUTS32(p,v)     NTFS_PUTU32(p,v)
+#define NTFS_PUTS64(p,v)     NTFS_PUTU64(p,v)
 
diff -urN linux-2.4.7-pre6/fs/ntfs/ntfstypes.h linux/fs/ntfs/ntfstypes.h
--- linux-2.4.7-pre6/fs/ntfs/ntfstypes.h	Wed Apr 18 11:49:13 2001
+++ linux/fs/ntfs/ntfstypes.h	Mon Dec  3 22:55:50 2001
@@ -1,17 +1,14 @@
-/*  ntfstypes.h - This file defines four things:
- *   - Generic platform independent fixed-size types (e.g. ntfs_u32).
- *   - Specific fixed-size types (e.g. ntfs_offset_t).
- *   - Macros that read and write those types from and to byte arrays.
- *   - Types derived from OS specific ones.
+/*
+ * ntfstypes.h - This file defines four things:
+ * - Generic platform independent fixed-size types (e.g. ntfs_u32).
+ * - Specific fixed-size types (e.g. ntfs_offset_t).
+ * - Macros that read and write those types from and to byte arrays.
+ * - Types derived from OS specific ones.
  *
- *  Copyright (C) 1996, 1998, 1999 Martin von Löwis
- *  Copyright (C) 2001 Anton Altaparmakov (AIA)
+ * Copyright (C) 1996, 1998, 1999 Martin von Löwis
+ * Copyright (C) 2001 Anton Altaparmakov (AIA)
  */
-
 #include <linux/fs.h>
-
-/* We don't need to define __LITTLE_ENDIAN, as we use
-   <asm/byteorder>. */
 #include "ntfsendian.h"
 #include <asm/types.h>
 
@@ -36,21 +33,24 @@
 /* File offset */
 #ifndef NTFS_OFFSET_T
 #define NTFS_OFFSET_T
-typedef u64 ntfs_offset_t;
+typedef s64 ntfs_offset_t;
 #endif
 /* UTC */
 #ifndef NTFS_TIME64_T
 #define NTFS_TIME64_T
 typedef u64 ntfs_time64_t;
 #endif
-/* This is really unsigned long long. So we support only volumes up to 2Tb. */
+/*
+ * This is really signed long long. So we support only volumes up to 2Tb. This
+ * is ok as Win2k also only uses 32-bits to store clusters.
+ * Whatever you do keep this a SIGNED value or a lot of NTFS users with
+ * corrupted filesystems will lynch you! It causes massive fs corruption when
+ * unsigned due to the nature of many checks relying on being performed on
+ * signed quantities. (AIA)
+ */
 #ifndef NTFS_CLUSTER_T
 #define NTFS_CLUSTER_T
-typedef u32 ntfs_cluster_t;
-#endif
-
-#ifndef MAX_CLUSTER_T
-#define MAX_CLUSTER_T (~((ntfs_cluster_t)0))
+typedef s32 ntfs_cluster_t;
 #endif
 
 /* Architecture independent macros. */
diff -urN linux-2.4.7-pre6/fs/ntfs/struct.h linux/fs/ntfs/struct.h
--- linux-2.4.7-pre6/fs/ntfs/struct.h	Wed Apr 18 11:49:13 2001
+++ linux/fs/ntfs/struct.h	Mon Dec  3 22:55:50 2001
@@ -1,7 +1,8 @@
-/*  struct.h - Structure definitions
+/*
+ * struct.h - Structure definitions
  *
- *  Copyright (C) 1997 Régis Duchesne
- *  Copyright (C) 2000-2001 Anton Altaparmakov (AIA)
+ * Copyright (C) 1997 Régis Duchesne
+ * Copyright (C) 2000-2001 Anton Altaparmakov (AIA)
  */
 
 /* Necessary forward definition. */
@@ -14,7 +15,6 @@
 #define ngt_posix 3	/* all names except hidden files */
 #define ngt_full  4	/* all entries */
 
-
 typedef struct ntfs_sb_info ntfs_volume;
 
 typedef struct {
@@ -27,31 +27,31 @@
 	ntfs_u16 *name;
 	int namelen;
 	int attrno;
-	int size, allocated, initialized, compsize;
+	__s64 size, allocated, initialized, compsize;
 	int compressed, resident, indexed;
 	int cengine;
 	union {
 		void *data;             /* if resident */
 		struct {
 			ntfs_runlist *runlist;
-			int len;
+			unsigned long len;
 		} r;
 	} d;
 } ntfs_attribute;
 
+typedef struct ntfs_inode_info ntfs_inode;
+
 /* Structure to define IO to user buffer. do_read means that the destination
  * has to be written using fn_put, do_write means that the destination has to
  * read using fn_get. So, do_read is from a user's point of view, while put and
  * get are from the driver's point of view. The first argument is always the
  * destination of the IO. */
-typedef struct ntfs_inode_info ntfs_inode;
-
 typedef struct ntfs_io{
 	int do_read;
 	void (*fn_put)(struct ntfs_io *dest, void *buf, ntfs_size_t);
 	void (*fn_get)(void *buf, struct ntfs_io *src, ntfs_size_t len);
 	void *param;
-	int size;
+	unsigned long size;
 } ntfs_io;
 
 #if 0
diff -urN linux-2.4.7-pre6/fs/ntfs/super.c linux/fs/ntfs/super.c
--- linux-2.4.7-pre6/fs/ntfs/super.c	Wed Apr 18 11:49:13 2001
+++ linux/fs/ntfs/super.c	Mon Dec  3 22:55:50 2001
@@ -1,9 +1,10 @@
-/*  super.c
+/*
+ * super.c
  *
- *  Copyright (C) 1995-1997, 1999 Martin von Löwis
- *  Copyright (C) 1996-1997 Régis Duchesne
- *  Copyright (C) 1999 Steve Dodd
- *  Copyright (C) 2000-2001 Anton Altparmakov (AIA)
+ * Copyright (C) 1995-1997, 1999 Martin von Löwis
+ * Copyright (C) 1996-1997 Régis Duchesne
+ * Copyright (C) 1999 Steve Dodd
+ * Copyright (C) 2000-2001 Anton Altparmakov (AIA)
  */
 
 #include "ntfstypes.h"
@@ -40,17 +41,17 @@
 	start = NTFS_GETU16(record + 4);
 	count = NTFS_GETU16(record + 6);
 	count--;
-	if(size && vol->blocksize * count != size)
+	if(size && vol->sector_size * count != size)
 		return 0;
 	fixup = NTFS_GETU16(record + start);
 	start += 2;
-	offset = vol->blocksize - 2;
+	offset = vol->sector_size - 2;
 	while (count--){
 		if (NTFS_GETU16(record + offset) != fixup)
 			return 0;
 		NTFS_PUTU16(record + offset, NTFS_GETU16(record + start));
 		start += 2;
-		offset += vol->blocksize;
+		offset += vol->sector_size;
 	}
 	return 1;
 }
@@ -61,6 +62,8 @@
  */
 int ntfs_init_volume(ntfs_volume *vol, char *boot)
 {
+	int sectors_per_cluster_bits;
+
 	/* Historical default values, in case we don't load $AttrDef. */
 	vol->at_standard_information = 0x10;
 	vol->at_attribute_list = 0x20;
@@ -75,53 +78,71 @@
 	vol->at_bitmap = 0xB0;
 	vol->at_symlink = 0xC0;
 	/* Sector size */
-	vol->blocksize = NTFS_GETU16(boot + 0xB);
-	vol->clusterfactorbits = ffs(NTFS_GETU8(boot + 0xD)) - 1;
+	vol->sector_size = NTFS_GETU16(boot + 0xB);
+	ntfs_debug(DEBUG_FILE3, "ntfs_init_volume: vol->sector_size = 0x%x\n",
+				vol->sector_size);
+	ntfs_debug(DEBUG_FILE3, "ntfs_init_volume: sectors_per_cluster = "
+				"0x%x\n", NTFS_GETU8(boot + 0xD));
+	sectors_per_cluster_bits = ffs(NTFS_GETU8(boot + 0xD)) - 1;
+	ntfs_debug(DEBUG_FILE3, "ntfs_init_volume: sectors_per_cluster_bits "
+				"= 0x%x\n", sectors_per_cluster_bits); 
 	vol->mft_clusters_per_record = NTFS_GETS8(boot + 0x40);
+	ntfs_debug(DEBUG_FILE3, "ntfs_init_volume: vol->mft_clusters_per_record"
+				" = 0x%x\n", vol->mft_clusters_per_record); 
 	vol->index_clusters_per_record = NTFS_GETS8(boot + 0x44);
-	/* Just some consistency checks. */
-	if (NTFS_GETU32(boot + 0x40) > 256)
-		ntfs_error("Unexpected data #1 in boot block\n");
-	if (NTFS_GETU32(boot+ 0x44) > 256)
-		ntfs_error("Unexpected data #2 in boot block\n");
-	vol->clustersize = vol->blocksize << vol->clusterfactorbits;
+	ntfs_debug(DEBUG_FILE3, "ntfs_init_volume: "
+				"vol->index_clusters_per_record = 0x%x\n",
+				vol->index_clusters_per_record); 
+	vol->cluster_size = vol->sector_size << sectors_per_cluster_bits;
+	vol->cluster_size_bits = ffs(vol->cluster_size) - 1;
+	ntfs_debug(DEBUG_FILE3, "ntfs_init_volume: vol->cluster_size = 0x%x\n",
+				vol->cluster_size); 
+	ntfs_debug(DEBUG_FILE3, "ntfs_init_volume: vol->cluster_size_bits = "
+				"0x%x\n", vol->cluster_size_bits); 
 	if (vol->mft_clusters_per_record > 0)
-		vol->mft_recordsize =
-			       vol->clustersize * vol->mft_clusters_per_record;
-	else {
-		/* If mft_recordsize < clustersize then mft_clusters_per_record
-		   = -log2(mft_recordsize) bytes. Mft_recordsize normaly equals
-		   1024 bytes, which is encoded as 0xF6. */
-		if (vol->mft_clusters_per_record < -31 ||
-					-9 < vol->mft_clusters_per_record) {
-			ntfs_error("Unexpected mft clusters per record value "
-				   "in boot block.\n");
-			return -1;
-		}
-		vol->mft_recordsize = 1 << (-vol->mft_clusters_per_record);
-	}
+		vol->mft_record_size = vol->cluster_size <<
+				(ffs(vol->mft_clusters_per_record) - 1);
+	else
+		/*
+		 * When mft_record_size < cluster_size, mft_clusters_per_record
+		 * = -log2(mft_record_size) bytes. mft_record_size normaly is
+		 * 1024 bytes, which is encoded as 0xF6 (-10 in decimal).
+		 */
+		vol->mft_record_size = 1 << -vol->mft_clusters_per_record;
+	vol->mft_record_size_bits = ffs(vol->mft_record_size) - 1;
+	ntfs_debug(DEBUG_FILE3, "ntfs_init_volume: vol->mft_record_size = 0x%x"
+				"\n", vol->mft_record_size); 
+	ntfs_debug(DEBUG_FILE3, "ntfs_init_volume: vol->mft_record_size_bits = "
+				"0x%x\n", vol->mft_record_size_bits); 
 	if (vol->index_clusters_per_record > 0)
-		vol->index_recordsize =
-			vol->clustersize * vol->index_clusters_per_record;
-	else {
-		/* If index_recordsize < clustersize then
-		   index_clusters_per_record = -log2(index_recordsize) bytes.
-		   Index_recordsize normaly equals 1024 bytes, which is
-		   encoded as 0xF6. */
-		if (vol->index_clusters_per_record < -31 ||
-					-9 < vol->index_clusters_per_record) {
-			ntfs_error("Unexpected index clusters per record "
-				   "value in boot block.\n");
-			return -1;
-		}
-		vol->index_recordsize = 1 << (-vol->index_clusters_per_record);
-	}
-	if (NTFS_GETU64(boot + 0x30) >= (1ULL << 32)) {
-		ntfs_error("Would require 64-bit inodes to mount partition.");
+		vol->index_record_size = vol->cluster_size <<
+				(ffs(vol->index_clusters_per_record) - 1);
+	else
+		/*
+		 * When index_record_size < cluster_size,
+		 * index_clusters_per_record = -log2(index_record_size) bytes.
+		 * index_record_size normaly equals 4096 bytes, which is
+		 * encoded as 0xF4 (-12 in decimal).
+		 */
+		vol->index_record_size = 1 << -vol->index_clusters_per_record;
+	vol->index_record_size_bits = ffs(vol->index_record_size) - 1;
+	ntfs_debug(DEBUG_FILE3, "ntfs_init_volume: vol->index_record_size = "
+				"0x%x\n", vol->index_record_size); 
+	ntfs_debug(DEBUG_FILE3, "ntfs_init_volume: vol->index_record_size_bits "
+				"= 0x%x\n", vol->index_record_size_bits); 
+	/*
+	 * Check mft and mftmirr locations for 64-bit-ness. NOTE: This is a
+	 * crude check only as many other things could be out of bounds later
+	 * on, but it will catch at least some of the cases, since the mftmirr
+	 * is located in the middle of the volume so if the volume is very
+	 * large the mftmirr probably will be out of 32-bit bounds.
+	 */
+	vol->mft_lcn = NTFS_GETS64(boot + 0x30);
+	if (vol->mft_lcn >= (__s64)1 << 31 ||
+	    NTFS_GETS64(boot + 0x38) >= (__s64)1 << 31) {
+		ntfs_error("Cannot handle 64-bit clusters yet.\n");
 		return -1;
 	}
-	/* FIXME: long long value */
-	vol->mft_cluster = NTFS_GETU64(boot + 0x30);
 	/* This will be initialized later. */
 	vol->upcase = 0;
 	vol->upcase_length = 0;
@@ -151,6 +172,11 @@
 	ntfs_volume *vol = attrdef->vol;
 	ntfs_u16* name = (ntfs_u16*)def;
 
+	if (!type) {
+		ntfs_debug(DEBUG_OTHER, "process_atrdef: finished processing "
+							"and returning 1\n");
+		return 1;
+	}
 	if (ntfs_ua_strncmp(name, "$STANDARD_INFORMATION", 64) == 0) {
 		vol->at_standard_information = type;
 		check_type = 0x10;
@@ -190,9 +216,12 @@
 		check_type = 0xC0;
 	}
 	if (check_type && check_type != type) {
-		ntfs_error("Unexpected type %x for %x\n", type, check_type);
+		ntfs_error("process_attrdef: unexpected type 0x%x for 0x%x\n",
+							type, check_type);
 		return -EINVAL;
 	}
+	ntfs_debug(DEBUG_OTHER, "process_attrdef: found %s attribute of type "
+			"0x%x\n", check_type ? "known" : "unknown", type);
 	return 0;
 }
 
@@ -200,9 +229,12 @@
 {
 	ntfs_u8 *buf;
 	ntfs_io io;
-	int offset, error,i;
+	__s64 offset;
+	unsigned i;
+	int error;
 	ntfs_attribute *data;
 
+	ntfs_debug(DEBUG_BSD, "Entered ntfs_init_attrdef()\n");
 	buf = ntfs_malloc(4050); /* 90*45 */
 	if (!buf)
 		return -ENOMEM;
@@ -211,6 +243,8 @@
 	io.do_read = 1;
 	offset = 0;
 	data = ntfs_find_attr(attrdef, attrdef->vol->at_data, 0);
+	ntfs_debug(DEBUG_BSD, "In ntfs_init_attrdef() after call to "
+			"ntfs_find_attr.\n");
 	if (!data) {
 		ntfs_free(buf);
 		return -EINVAL;
@@ -218,13 +252,23 @@
 	do {
 		io.param = buf;
 		io.size = 4050;
+		ntfs_debug(DEBUG_BSD, "In ntfs_init_attrdef() going to call "
+				"ntfs_readwrite_attr.\n");
 		error = ntfs_readwrite_attr(attrdef, data, offset, &io);
-		for (i = 0; !error && i < io.size - 0xA0; i += 0xA0)
+		ntfs_debug(DEBUG_BSD, "In ntfs_init_attrdef() after call to "
+				"ntfs_readwrite_attr.\n");
+		for (i = 0; !error && i <= io.size - 0xA0; i += 0xA0) {
+			ntfs_debug(DEBUG_BSD, "In ntfs_init_attrdef() going "
+					"to call process_attrdef.\n");
 			error = process_attrdef(attrdef, buf + i);
+			ntfs_debug(DEBUG_BSD, "In ntfs_init_attrdef() after "
+					"call to process_attrdef.\n");
+		}
 		offset += 4096;
 	} while (!error && io.size);
+	ntfs_debug(DEBUG_BSD, "Exiting ntfs_init_attrdef()\n");
 	ntfs_free(buf);
-	return error;
+	return error == 1 ? 0 : error;
 }
 
 /* ntfs_get_version will determine the NTFS version of the volume and will
@@ -253,7 +297,10 @@
 	int error;
 	ntfs_inode upcase, attrdef, volume;
 
-	vol->mft_ino = (ntfs_inode*)ntfs_calloc(3 * sizeof(ntfs_inode));
+	vol->mft_ino = (ntfs_inode*)ntfs_calloc(sizeof(ntfs_inode));
+	vol->mftmirr = (ntfs_inode*)ntfs_calloc(sizeof(ntfs_inode));
+	vol->bitmap = (ntfs_inode*)ntfs_calloc(sizeof(ntfs_inode));
+	vol->ino_flags = 4 | 2 | 1;
 	error = -ENOMEM;
 	ntfs_debug(DEBUG_BSD, "Going to load MFT\n");
 	if (!vol->mft_ino || (error = ntfs_init_inode(vol->mft_ino, vol,
@@ -263,13 +310,11 @@
 		return error;
 	}
 	ntfs_debug(DEBUG_BSD, "Going to load MIRR\n");
-	vol->mftmirr = vol->mft_ino + 1;
 	if ((error = ntfs_init_inode(vol->mftmirr, vol, FILE_$MftMirr))) {
 		ntfs_error("Problem %d loading MFTMirr\n", error);
 		return error;
 	}
 	ntfs_debug(DEBUG_BSD, "Going to load BITMAP\n");
-	vol->bitmap = vol->mft_ino + 2;
 	if ((error = ntfs_init_inode(vol->bitmap, vol, FILE_$BitMap))) {
 		ntfs_error("Problem loading Bitmap\n");
 		return error;
@@ -311,36 +356,48 @@
 
 int ntfs_release_volume(ntfs_volume *vol)
 {
-	if (vol->mft_ino) {
+	if (((vol->ino_flags & 1) == 1) && vol->mft_ino) {
 		ntfs_clear_inode(vol->mft_ino);
-		ntfs_clear_inode(vol->mftmirr);
-		ntfs_clear_inode(vol->bitmap);
 		ntfs_free(vol->mft_ino);
 		vol->mft_ino = 0;
 	}
+	if (((vol->ino_flags & 2) == 2) && vol->mftmirr) {
+		ntfs_clear_inode(vol->mftmirr);
+		ntfs_free(vol->mftmirr);
+		vol->mftmirr = 0;
+	}
+	if (((vol->ino_flags & 4) == 4) && vol->bitmap) {
+		ntfs_clear_inode(vol->bitmap);
+		ntfs_free(vol->bitmap);
+		vol->bitmap = 0;
+	}
 	ntfs_free(vol->mft);
 	ntfs_free(vol->upcase);
 	return 0;
 }
 
-/* Writes the volume size into vol_size. Returns 0 if successful or error. */
-int ntfs_get_volumesize(ntfs_volume *vol, ntfs_u64 *vol_size)
+/*
+ * Writes the volume size (units of clusters) into vol_size.
+ * Returns 0 if successful or error.
+ */
+int ntfs_get_volumesize(ntfs_volume *vol, ntfs_s64 *vol_size)
 {
 	ntfs_io io;
 	char *cluster0;
 
 	if (!vol_size)
 		return -EFAULT;
-	cluster0 = ntfs_malloc(vol->clustersize);
+	cluster0 = ntfs_malloc(vol->cluster_size);
 	if (!cluster0)
 		return -ENOMEM;
 	io.fn_put = ntfs_put;
 	io.fn_get = ntfs_get;
 	io.param = cluster0;
 	io.do_read = 1;
-	io.size = vol->clustersize;
+	io.size = vol->cluster_size;
 	ntfs_getput_clusters(vol, 0, 0, &io);
-	*vol_size = NTFS_GETU64(cluster0 + 0x28) >> vol->clusterfactorbits;
+	*vol_size = NTFS_GETU64(cluster0 + 0x28) >>
+					(ffs(NTFS_GETU8(cluster0 + 0xD)) - 1);
 	ntfs_free(cluster0);
 	return 0;
 }
@@ -349,12 +406,12 @@
 
 int ntfs_get_free_cluster_count(ntfs_inode *bitmap)
 {
-	unsigned char bits[2048];
-	int offset, error;
-	int clusters = 0;
 	ntfs_io io;
-
-	offset = 0;
+	int offset, error, clusters;
+	unsigned char *bits = ntfs_malloc(2048);
+	if (!bits)
+		return -ENOMEM;
+	offset = clusters = 0;
 	io.fn_put = ntfs_put;
 	io.fn_get = ntfs_get;
 	while (1) {
@@ -382,6 +439,7 @@
 		}
 		offset += io.size;
 	}
+	ntfs_free(bits);
 	return clusters;
 }
 
diff -urN linux-2.4.7-pre6/fs/ntfs/super.h linux/fs/ntfs/super.h
--- linux-2.4.7-pre6/fs/ntfs/super.h	Wed Apr 18 11:49:13 2001
+++ linux/fs/ntfs/super.h	Mon Dec  3 22:55:50 2001
@@ -1,7 +1,8 @@
-/*  super.h - Header file for super.c
+/*
+ * super.h - Header file for super.c
  *
- *  Copyright (C) 1995-1997 Martin von Löwis
- *  Copyright (C) 1996-1997 Régis Duchesne
+ * Copyright (C) 1995-1997 Martin von Löwis
+ * Copyright (C) 1996-1997 Régis Duchesne
  */
 
 #define ALLOC_REQUIRE_LOCATION 1
@@ -9,7 +10,7 @@
 
 int ntfs_get_free_cluster_count(ntfs_inode *bitmap);
 
-int ntfs_get_volumesize(ntfs_volume *vol, ntfs_u64 *vol_size );
+int ntfs_get_volumesize(ntfs_volume *vol, __s64 *vol_size);
 
 int ntfs_init_volume(ntfs_volume *vol, char *boot);
 
diff -urN linux-2.4.7-pre6/fs/ntfs/support.c linux/fs/ntfs/support.c
--- linux-2.4.7-pre6/fs/ntfs/support.c	Wed Apr 18 11:49:13 2001
+++ linux/fs/ntfs/support.c	Mon Dec  3 22:55:50 2001
@@ -1,8 +1,9 @@
-/*  support.c -  Specific support functions
+/*
+ * support.c -  Specific support functions
  *
- *  Copyright (C) 1997 Martin von Löwis
- *  Copyright (C) 1997 Régis Duchesne
- *  Copyright (C) 2001 Anton Altaparmakov (AIA)
+ * Copyright (C) 1997 Martin von Löwis
+ * Copyright (C) 1997 Régis Duchesne
+ * Copyright (C) 2001 Anton Altaparmakov (AIA)
  */
 
 #include "ntfstypes.h"
@@ -12,11 +13,15 @@
 #include <stdarg.h>
 #include <linux/slab.h>
 #include <linux/locks.h>
-#include <linux/nls.h>
+#include <linux/fs.h>
 #include "util.h"
 #include "inode.h"
 #include "macros.h"
 
+#ifndef NLS_MAX_CHARSET_SIZE
+#include <linux/nls.h>
+#endif
+
 static char print_buf[1024];
 
 #ifdef DEBUG
@@ -29,7 +34,7 @@
 	va_list ap;
 
 	/* Filter it with the debugging level required */
-	if(ntdebug & mask){
+	if (ntdebug & mask) {
 		va_start(ap,fmt);
 		strcpy(print_buf, KERN_DEBUG);
 		vsprintf(print_buf + 3, fmt, ap);
@@ -114,13 +119,13 @@
 	int error;
 	ntfs_io io;
 
-	ntfs_debug(DEBUG_OTHER, "read_mft_record %x\n",mftno);
-	if(mftno == FILE_$Mft)
+	ntfs_debug(DEBUG_OTHER, "read_mft_record 0x%x\n", mftno);
+	if (mftno == FILE_$Mft)
 	{
-		ntfs_memcpy(buf, vol->mft, vol->mft_recordsize);
+		ntfs_memcpy(buf, vol->mft, vol->mft_record_size);
 		return 0;
 	}
-	if(!vol->mft_ino)
+	if (!vol->mft_ino)
 	{
 		printk(KERN_ERR "NTFS: mft_ino is NULL. Something is terribly "
 				"wrong here!\n");
@@ -129,28 +134,31 @@
  	io.fn_put = ntfs_put;
 	io.fn_get = 0;
 	io.param = buf;
-	io.size = vol->mft_recordsize;
+	io.size = vol->mft_record_size;
+	ntfs_debug(DEBUG_OTHER, "read_mft_record: calling ntfs_read_attr with: "
+		"mftno = 0x%x, vol->mft_record_size_bits = 0x%x, "
+		"mftno << vol->mft_record_size_bits = 0x%Lx\n", mftno,
+		vol->mft_record_size_bits,
+		(__s64)mftno << vol->mft_record_size_bits);
 	error = ntfs_read_attr(vol->mft_ino, vol->at_data, NULL,
-					mftno * vol->mft_recordsize, &io);
-	if (error || (io.size != vol->mft_recordsize))
-	{
-		ntfs_debug(DEBUG_OTHER, "read_mft_record: read %x failed "
+				(__s64)mftno << vol->mft_record_size_bits, &io);
+	if (error || (io.size != vol->mft_record_size)) {
+		ntfs_debug(DEBUG_OTHER, "read_mft_record: read 0x%x failed "
 				   	"(%d,%d,%d)\n", mftno, error, io.size,
-				   	vol->mft_recordsize);
+				   	vol->mft_record_size);
 		return error ? error : -ENODATA;
 	}
-	ntfs_debug(DEBUG_OTHER, "read_mft_record: finished read %x\n", mftno);
-	if(!ntfs_check_mft_record(vol, buf))
-	{
+	ntfs_debug(DEBUG_OTHER, "read_mft_record: finished read 0x%x\n", mftno);
+	if (!ntfs_check_mft_record(vol, buf)) {
 		/* FIXME: This is incomplete behaviour. We might be able to
 		 * recover at this stage. ntfs_check_mft_record() is too
 		 * conservative at aborting it's operations. It is OK for
 		 * now as we just can't handle some on disk structures
 		 * this way. (AIA) */
-		printk(KERN_WARNING "NTFS: Invalid MFT record for %x\n", mftno);
+		printk(KERN_WARNING "NTFS: Invalid MFT record for 0x%x\n", mftno);
 		return -EINVAL;
 	}
-	ntfs_debug(DEBUG_OTHER, "read_mft_record: Done %x\n", mftno);
+	ntfs_debug(DEBUG_OTHER, "read_mft_record: Done 0x%x\n", mftno);
 	return 0;
 }
 
@@ -159,32 +167,57 @@
 {
 	struct super_block *sb = NTFS_SB(vol);
 	struct buffer_head *bh;
-	ntfs_size_t to_copy;
 	int length = buf->size;
+	int error = 0;
+	ntfs_size_t to_copy;
 
 	ntfs_debug(DEBUG_OTHER, "%s_clusters %d %d %d\n", 
 		   buf->do_read ? "get" : "put", cluster, start_offs, length);
 	while (length) {
-		if (!(bh = bread(sb->s_dev, cluster, vol->clustersize))) {
+		if (!(bh = bread(sb->s_dev, cluster, vol->cluster_size))) {
 			ntfs_debug(DEBUG_OTHER, "%s failed\n",
 				   buf->do_read ? "Reading" : "Writing");
-			return -EIO;
+			error = -EIO;
+			goto error_ret;
 		}
-		to_copy = min(vol->clustersize - start_offs, length);
+		to_copy = min(vol->cluster_size - start_offs, length);
 		lock_buffer(bh);
-		if (buf->do_read)
+		if (buf->do_read) {
 			buf->fn_put(buf, bh->b_data + start_offs, to_copy);
-		else {
+			unlock_buffer(bh);
+		} else {
 			buf->fn_get(bh->b_data + start_offs, buf, to_copy);
 			mark_buffer_dirty(bh);
+			unlock_buffer(bh);
+			/*
+			 * Note: We treat synchronous IO on a per volume basis
+			 * disregarding flags of individual inodes. This can
+			 * lead to some strange write ordering effects upon a
+			 * remount with a change in the sync flag but it should
+			 * not break anything. [Except if the system crashes
+			 * at that point in time but there would be more thigs
+			 * to worry about than that in that case...]. (AIA)
+			 */
+			if (sb->s_flags & MS_SYNCHRONOUS) {
+				ll_rw_block(WRITE, 1, &bh);
+				wait_on_buffer(bh);
+				if (buffer_req(bh) && !buffer_uptodate(bh)) {
+					printk(KERN_ERR "IO error syncing NTFS "
+					       "cluster [%s:%i]\n",
+					       bdevname(sb->s_dev), cluster);
+					brelse(bh);
+					error = -EIO;
+					goto error_ret;
+				}
+			}
 		}
-		unlock_buffer(bh);
 		length -= to_copy;
 		start_offs = 0;
 		cluster++;
 		brelse(bh);
 	}
-	return 0;
+error_ret:
+	return error;
 }
 
 ntfs_time64_t ntfs_now(void)
@@ -241,6 +274,10 @@
 				/* adjust result buffer */
 				if (chl > 1) {
 					buf = ntfs_malloc(*out_len + chl - 1);
+					if (!buf) {
+						ntfs_free(result);
+						return -ENOMEM;
+					}
 					memcpy(buf, result, o);
 					ntfs_free(result);
 					result = buf;
diff -urN linux-2.4.7-pre6/fs/ntfs/support.h linux/fs/ntfs/support.h
--- linux-2.4.7-pre6/fs/ntfs/support.h	Wed Apr 18 11:49:13 2001
+++ linux/fs/ntfs/support.h	Mon Dec  3 22:55:50 2001
@@ -1,6 +1,8 @@
-/*  support.h - Header file for specific support.c
+/*
+ * support.h - Header file for specific support.c
  *
- *  Copyright (C) 1997 Régis Duchesne
+ * Copyright (C) 1997 Régis Duchesne
+ * Copyright (c) 2001 Anton Altaparmakov (AIA)
  */
 
 /* Debug levels */
@@ -20,10 +22,15 @@
 void ntfs_debug(int mask, const char *fmt, ...);
 
 #include <linux/slab.h>
+#include <linux/vmalloc.h>
 
 #define ntfs_malloc(size)  kmalloc(size, GFP_KERNEL)
 
 #define ntfs_free(ptr)     kfree(ptr)
+
+#define ntfs_vmalloc(size)	vmalloc_32(size)
+
+#define ntfs_vfree(ptr)		vfree(ptr)
 
 void ntfs_bzero(void *s, int n);
 
diff -urN linux-2.4.7-pre6/fs/ntfs/sysctl.c linux/fs/ntfs/sysctl.c
--- linux-2.4.7-pre6/fs/ntfs/sysctl.c	Fri Dec 19 15:24:21 1997
+++ linux/fs/ntfs/sysctl.c	Mon Dec  3 22:55:50 2001
@@ -1,10 +1,8 @@
 /*
- *  sysctl.c
- *  System control stuff
- *
- *  Copyright (C) 1997 Martin von Löwis
- *  Copyright (C) 1997 Régis Duchesne
+ * sysctl.c - System control stuff
  *
+ * Copyright (C) 1997 Martin von Löwis
+ * Copyright (C) 1997 Régis Duchesne
  */
 
 #include "sysctl.h"
@@ -55,8 +53,3 @@
 }
 #endif /* DEBUG */
 
-/*
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff -urN linux-2.4.7-pre6/fs/ntfs/sysctl.h linux/fs/ntfs/sysctl.h
--- linux-2.4.7-pre6/fs/ntfs/sysctl.h	Wed Apr 18 11:49:13 2001
+++ linux/fs/ntfs/sysctl.h	Mon Dec  3 22:55:50 2001
@@ -1,8 +1,8 @@
-/*  sysctl.h - Header file for sysctl.c
- *
- *  Copyright (C) 1997 Martin von Löwis
- *  Copyright (C) 1997 Régis Duchesne
+/*
+ * sysctl.h - Header file for sysctl.c
  *
+ * Copyright (C) 1997 Martin von Löwis
+ * Copyright (C) 1997 Régis Duchesne
  */
 
 #ifdef DEBUG
diff -urN linux-2.4.7-pre6/fs/ntfs/unistr.c linux/fs/ntfs/unistr.c
--- linux-2.4.7-pre6/fs/ntfs/unistr.c	Wed Dec 31 16:00:00 1969
+++ linux/fs/ntfs/unistr.c	Mon Dec  3 22:55:50 2001
@@ -0,0 +1,167 @@
+/*
+ * $Id: unistr.c,v 1.4 2001/04/08 03:02:55 antona Exp $
+ *
+ * unistr.c - Unicode string handling. Part of the Linux-NTFS project.
+ *
+ * Copyright (c) 2000,2001 Anton Altaparmakov.
+ *
+ * This program/include file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program/include file is distributed in the hope that it will be 
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program (in the main directory of the Linux-NTFS 
+ * distribution in the file COPYING); if not, write to the Free Software
+ * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/string.h>
+#include <asm/byteorder.h>
+
+#include "unistr.h"
+#include "macros.h"
+
+/*
+ * This is used by the name collation functions to quickly determine what
+ * characters are (in)valid.
+ */
+const __u8 legal_ansi_char_array[0x40] = {
+	0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+
+	0x17, 0x07, 0x18, 0x17, 0x17, 0x17, 0x17, 0x17,
+	0x17, 0x17, 0x18, 0x16, 0x16, 0x17, 0x07, 0x00,
+
+	0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17,
+	0x17, 0x17, 0x04, 0x16, 0x18, 0x16, 0x18, 0x18,
+};
+
+/**
+ * ntfs_are_names_equal - compare two Unicode names for equality
+ * @s1:			name to compare to @s2
+ * @s1_len:		length in Unicode characters of @s1
+ * @s2:			name to compare to @s1
+ * @s2_len:		length in Unicode characters of @s2
+ * @ic:			ignore case bool
+ * @upcase:		upcase table (only if @ic == IGNORE_CASE)
+ * @upcase_size:	length in Unicode characters of @upcase (if present)
+ *
+ * Compare the names @s1 and @s2 and return TRUE (1) if the names are
+ * identical, or FALSE (0) if they are not identical. If @ic is IGNORE_CASE,
+ * the @upcase table is used to performa a case insensitive comparison.
+ */
+int ntfs_are_names_equal(wchar_t *s1, size_t s1_len,
+		     wchar_t *s2, size_t s2_len, int ic,
+		     wchar_t *upcase, __u32 upcase_size)
+{
+	if (s1_len != s2_len)
+		return 0;
+	if (!ic)
+		return memcmp(s1, s2, s1_len << 1) ? 0: 1;
+	return ntfs_wcsncasecmp(s1, s2, s1_len, upcase, upcase_size) ? 0: 1;
+}
+
+/**
+ * ntfs_collate_names - collate two Unicode names
+ * @upcase:	upcase table (ignored if @ic is CASE_SENSITIVE)
+ * @upcase_len:	upcase table size (ignored if @ic is CASE_SENSITIVE)
+ * @name1:	first Unicode name to compare
+ * @name2:	second Unicode name to compare
+ * @ic:         either CASE_SENSITIVE or IGNORE_CASE
+ * @err_val:	if @name1 contains an invalid character return this value
+ *
+ * ntfs_collate_names collates two Unicode names and returns:
+ * 
+ *  -1 if the first name collates before the second one,
+ *   0 if the names match,
+ *   1 if the second name collates before the first one, or
+ * @ec if an invalid character is encountered in @name1 during the comparison.
+ *
+ * The following characters are considered invalid: '"', '*', '<', '>' and '?'.
+ */
+int ntfs_collate_names(wchar_t *upcase, __u32 upcase_len,
+		       wchar_t *name1, __u32 name1_len,
+		       wchar_t *name2, __u32 name2_len,
+		       int ic, int err_val)
+{
+	__u32 cnt;
+	wchar_t c1, c2;
+
+	for (cnt = 0; cnt < min(name1_len, name2_len); ++cnt)
+	{
+		c1 = le16_to_cpu(*name1++);
+		c2 = le16_to_cpu(*name2++);
+		if (ic) {
+			if (c1 < upcase_len)
+				c1 = le16_to_cpu(upcase[c1]);
+			if (c2 < upcase_len)
+				c2 = le16_to_cpu(upcase[c2]);
+		}
+		if (c1 < 64 && legal_ansi_char_array[c1] & 8);
+			return err_val;
+		if (c1 < c2)
+			return -1;
+		if (c1 > c2)
+			return 1;
+		++name1;
+		++name2;
+	}
+	if (name1_len < name2_len)
+		return -1;
+	if (name1_len == name2_len)
+		return 0;
+	/* name1_len > name2_len */
+	c1 = le16_to_cpu(*name1);
+	if (c1 < 64 && legal_ansi_char_array[c1] & 8)
+		return err_val;
+	return 1;
+}
+
+/**
+ * ntfs_wcsncasecmp - compare two little endian Unicode strings, ignoring case
+ * @s1:			first string
+ * @s2:			second string
+ * @n:			maximum unicode characters to compare
+ * @upcase:		upcase table
+ * @upcase_size:	upcase table size in Unicode characters
+ *
+ * Compare the first @n characters of the Unicode strings @s1 and @s2,
+ * ignoring case. The strings in little endian format and appropriate
+ * le16_to_cpu() conversion is performed on non-little endian machines.
+ * 
+ * Each character is uppercased using the @upcase table before the comparison.
+ *
+ * The function returns an integer less than, equal to, or greater than zero
+ * if @s1 (or the first @n Unicode characters thereof) is found, respectively,
+ * to be less than, to match, or be greater than @s2.
+ */
+int ntfs_wcsncasecmp(wchar_t *s1, wchar_t *s2, size_t n,
+		     wchar_t *upcase, __u32 upcase_size)
+{
+	wchar_t c1, c2;
+	size_t i;
+
+	for (i = 0; i < n; ++i) {
+		if ((c1 = le16_to_cpu(s1[i])) < upcase_size)
+			c1 = le16_to_cpu(upcase[c1]);
+		if ((c2 = le16_to_cpu(s2[i])) < upcase_size)
+			c2 = le16_to_cpu(upcase[c2]);
+		if (c1 < c2)
+			return -1;
+		if (c1 > c2)
+			return 1;
+		if (!c1)
+			break;
+	}
+	return 0;
+}
+
diff -urN linux-2.4.7-pre6/fs/ntfs/unistr.h linux/fs/ntfs/unistr.h
--- linux-2.4.7-pre6/fs/ntfs/unistr.h	Wed Dec 31 16:00:00 1969
+++ linux/fs/ntfs/unistr.h	Mon Dec  3 22:55:50 2001
@@ -0,0 +1,46 @@
+/*
+ * $Id: unistr.h,v 1.5 2001/04/11 11:49:16 antona Exp $
+ *
+ * unistr.h - Exports for unicode string handling. Part of the Linux-NTFS
+ *	      project.
+ *
+ * Copyright (c) 2000,2001 Anton Altaparmakov.
+ *
+ * This program/include file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program/include file is distributed in the hope that it will be 
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program (in the main directory of the Linux-NTFS 
+ * distribution in the file COPYING); if not, write to the Free Software
+ * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _LINUX_NTFS_UNISTR_H
+#define _LINUX_NTFS_UNISTR_H
+
+#include <linux/types.h>
+#include <linux/nls.h>
+
+extern const __u8 legal_ansi_char_array[0x40];
+
+int ntfs_are_names_equal(wchar_t *s1, size_t s1_len,
+			  wchar_t *s2, size_t s2_len, int ic,
+			  wchar_t *upcase, __u32 upcase_size);
+
+int ntfs_collate_names(wchar_t *upcase, __u32 upcase_len,
+		       wchar_t *name1, __u32 name1_len,
+		       wchar_t *name2, __u32 name2_len,
+		       int ic, int err_val);
+
+int ntfs_wcsncasecmp(wchar_t *s1, wchar_t *s2, size_t n,
+		     wchar_t *upcase, __u32 upcase_size);
+
+#endif /* defined _LINUX_NTFS_UNISTR_H */
+
diff -urN linux-2.4.7-pre6/fs/ntfs/util.c linux/fs/ntfs/util.c
--- linux-2.4.7-pre6/fs/ntfs/util.c	Wed Apr 18 11:49:13 2001
+++ linux/fs/ntfs/util.c	Mon Dec  3 22:55:50 2001
@@ -1,16 +1,16 @@
-/*  util.c -  Miscellaneous support
+/*
+ * util.c -  Miscellaneous support
  *
- *  Copyright (C) 1997,1999 Martin von Löwis
- *  Copyright (C) 1997 Régis Duchesne
- *  Copyright (C) 2001 Anton Altaparmakov (AIA)
+ * Copyright (C) 1997,1999 Martin von Löwis
+ * Copyright (C) 1997 Régis Duchesne
+ * Copyright (C) 2001 Anton Altaparmakov (AIA)
  *
- *  The utf8 routines are copied from Python wstrop module.
+ * The utf8 routines are copied from Python wstrop module.
  */
 
 #include "ntfstypes.h"
 #include "struct.h"
 #include "util.h"
-
 #include <linux/string.h>
 #include <linux/errno.h>
 #include "support.h"
@@ -258,7 +258,7 @@
 		if (NTFS_GETU16(b + i) < NTFS_GETU16(a + i))
 			return 1;
 		if (NTFS_GETU16(a + i) == 0)
-			return 0;
+			break;
 	}
 	return 0;
 }
diff -urN linux-2.4.7-pre6/fs/ntfs/util.h linux/fs/ntfs/util.h
--- linux-2.4.7-pre6/fs/ntfs/util.h	Wed Apr 18 11:49:13 2001
+++ linux/fs/ntfs/util.h	Mon Dec  3 22:55:50 2001
@@ -1,7 +1,8 @@
-/*  util.h - Header file for util.c
+/*
+ * util.h - Header file for util.c
  *
- *  Copyright (C) 1997 Régis Duchesne
- *  Copyright (C) 2001 Anton Altaparmakov
+ * Copyright (C) 1997 Régis Duchesne
+ * Copyright (C) 2001 Anton Altaparmakov (AIA)
  */
 
 /* Which character set is used for file names. */
@@ -16,7 +17,7 @@
 /*  Use a mapping table to determine printables. */
 #define nct_map              16
 
-/* The first 16 inodes correspond to NTFS special files */
+/* The first 16 inodes correspond to NTFS special files. */
 typedef enum {
 	FILE_$Mft	= 0,
 	FILE_$MftMirr	= 1,
diff -urN linux-2.4.7-pre6/fs/partitions/Config.in linux/fs/partitions/Config.in
--- linux-2.4.7-pre6/fs/partitions/Config.in	Fri Feb 16 16:02:37 2001
+++ linux/fs/partitions/Config.in	Mon Dec  3 22:55:50 2001
@@ -37,7 +37,7 @@
 	"$CONFIG_SGI_IP27" != "y" ]; then
       define_bool CONFIG_MSDOS_PARTITION y
    fi
-   if [ "$CONFIG_AMIGA" = "y" ]; then
+   if [ "$CONFIG_AMIGA" = "y" -o "CONFIG_AFFS_FS" = "y" ]; then
       define_bool CONFIG_AMIGA_PARTITION y
    fi
    if [ "$CONFIG_MAC" = "y" ]; then
diff -urN linux-2.4.7-pre6/fs/partitions/check.c linux/fs/partitions/check.c
--- linux-2.4.7-pre6/fs/partitions/check.c	Tue Jun 12 11:17:17 2001
+++ linux/fs/partitions/check.c	Mon Dec  3 22:55:50 2001
@@ -328,6 +328,8 @@
 			    dev->fops, NULL);
 }
 
+static struct unique_numspace disc_numspace = UNIQUE_NUMBERSPACE_INITIALISER;
+
 static void devfs_register_disc (struct gendisk *dev, int minor)
 {
 	int pos = 0;
@@ -335,7 +337,6 @@
 	devfs_handle_t dir, slave;
 	unsigned int devfs_flags = DEVFS_FL_DEFAULT;
 	char dirname[64], symlink[16];
-	static unsigned int disc_counter;
 	static devfs_handle_t devfs_handle;
 
 	if (dev->part[minor].de) return;
@@ -356,7 +357,8 @@
 	}
 	if (!devfs_handle)
 		devfs_handle = devfs_mk_dir (NULL, "discs", NULL);
-	sprintf (symlink, "disc%u", disc_counter++);
+	dev->part[minor].number = devfs_alloc_unique_number (&disc_numspace);
+	sprintf (symlink, "disc%d", dev->part[minor].number);
 	devfs_mk_symlink (devfs_handle, symlink, DEVFS_FL_DEFAULT,
 			  dirname + pos, &slave, NULL);
 	dev->part[minor].de =
@@ -386,6 +388,8 @@
 	if (unregister) {
 		devfs_unregister (dev->part[minor].de);
 		dev->part[minor].de = NULL;
+		devfs_dealloc_unique_number (&disc_numspace,
+					     dev->part[minor].number);
 	}
 #endif  /*  CONFIG_DEVFS_FS  */
 }
diff -urN linux-2.4.7-pre6/fs/sysv/dir.c linux/fs/sysv/dir.c
--- linux-2.4.7-pre6/fs/sysv/dir.c	Mon Dec  3 22:55:41 2001
+++ linux/fs/sysv/dir.c	Mon Dec  3 22:55:50 2001
@@ -40,6 +40,8 @@
 {
 	struct inode *dir = (struct inode *)page->mapping->host;
 	int err = 0;
+
+	dir->i_version = ++event;
 	page->mapping->a_ops->commit_write(NULL, page, from, to);
 	if (IS_SYNC(dir))
 		err = waitfor_one_page(page);
@@ -109,6 +111,7 @@
 
 done:
 	filp->f_pos = (n << PAGE_CACHE_SHIFT) | offset;
+	filp->f_version = inode->i_version;
 	UPDATE_ATIME(inode);
 	return 0;
 }
diff -urN linux-2.4.7-pre6/fs/sysv/ialloc.c linux/fs/sysv/ialloc.c
--- linux-2.4.7-pre6/fs/sysv/ialloc.c	Mon Jul  2 14:03:04 2001
+++ linux/fs/sysv/ialloc.c	Mon Dec  3 22:55:50 2001
@@ -136,7 +136,8 @@
 	sb = dir->i_sb;
 	inode = new_inode(sb);
 	if (!inode)
-		return NULL;
+		return ERR_PTR(-ENOMEM);
+
 	lock_super(sb);
 	count = fs16_to_cpu(sb, *sb->sv_sb_fic_count);
 	if (count == 0 || (*sv_sb_fic_inode(sb,count-1) == 0)) {
@@ -144,7 +145,7 @@
 		if (count == 0) {
 			iput(inode);
 			unlock_super(sb);
-			return NULL;
+			return ERR_PTR(-ENOSPC);
 		}
 	}
 	/* Now count > 0. */
@@ -152,16 +153,23 @@
 	*sb->sv_sb_fic_count = cpu_to_fs16(sb, count);
 	fs16_add(sb, sb->sv_sb_total_free_inodes, -1);
 	dirty_sb(sb);
+	
+	if (dir->i_mode & S_ISGID) {
+		inode->i_gid = dir->i_gid;
+		if (S_ISDIR(mode))
+			mode |= S_ISGID;
+	} else
+		inode->i_gid = current->fsgid;
+
 	inode->i_uid = current->fsuid;
-	inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
 	inode->i_ino = fs16_to_cpu(sb, ino);
 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
 	inode->i_blocks = inode->i_blksize = 0;
 	insert_inode_hash(inode);
 	mark_inode_dirty(inode);
+
 	inode->i_mode = mode;		/* for sysv_write_inode() */
 	sysv_write_inode(inode, 0);	/* ensure inode not allocated again */
-					/* FIXME: caller may call this too. */
 	mark_inode_dirty(inode);	/* cleared by sysv_write_inode() */
 	/* That's it. */
 	unlock_super(sb);
diff -urN linux-2.4.7-pre6/fs/sysv/inode.c linux/fs/sysv/inode.c
--- linux-2.4.7-pre6/fs/sysv/inode.c	Mon Jul  2 14:03:04 2001
+++ linux/fs/sysv/inode.c	Mon Dec  3 22:55:50 2001
@@ -28,11 +28,10 @@
 #include <linux/highuid.h>
 #include <asm/byteorder.h>
 
-
 /* This is only called on sync() and umount(), when s_dirt=1. */
 static void sysv_write_super(struct super_block *sb)
 {
-	if (buffer_dirty(sb->sv_bh1) || buffer_dirty(sb->sv_bh2)) {
+	if (!(sb->s_flags & MS_RDONLY)) {
 		/* If we are going to write out the super block,
 		   then attach current time stamp.
 		   But if the filesystem was marked clean, keep it clean. */
@@ -49,13 +48,16 @@
 
 static void sysv_put_super(struct super_block *sb)
 {
-	/* we can assume sysv_write_super() has already been called,
-	   and that the superblock is locked */
+	if (!(sb->s_flags & MS_RDONLY)) {
+		/* XXX ext2 also updates the state here */
+		mark_buffer_dirty(sb->sv_bh1);
+		if (sb->sv_bh1 != sb->sv_bh2)
+			mark_buffer_dirty(sb->sv_bh2);
+	}
+
 	brelse(sb->sv_bh1);
-	if (sb->sv_bh1 != sb->sv_bh2) brelse(sb->sv_bh2);
-	/* switch back to default block size */
-	if (sb->s_blocksize != BLOCK_SIZE)
-		set_blocksize(sb->s_dev,BLOCK_SIZE);
+	if (sb->sv_bh1 != sb->sv_bh2)
+		brelse(sb->sv_bh2);
 }
 
 static int sysv_statfs(struct super_block *sb, struct statfs *buf)
diff -urN linux-2.4.7-pre6/fs/sysv/namei.c linux/fs/sysv/namei.c
--- linux-2.4.7-pre6/fs/sysv/namei.c	Mon Jul  2 14:03:04 2001
+++ linux/fs/sysv/namei.c	Mon Dec  3 22:55:50 2001
@@ -86,11 +86,14 @@
 static int sysv_mknod(struct inode * dir, struct dentry * dentry, int mode, int rdev)
 {
 	struct inode * inode = sysv_new_inode(dir, mode);
-	if (!inode)
-		return -ENOSPC;
-	sysv_set_inode(inode, rdev);
-	mark_inode_dirty(inode);
-	return add_nondir(dentry, inode);
+	int err = PTR_ERR(inode);
+
+	if (!IS_ERR(inode)) {
+		sysv_set_inode(inode, rdev);
+		mark_inode_dirty(inode);
+		err = add_nondir(dentry, inode);
+	}
+	return err;
 }
 
 static int sysv_create(struct inode * dir, struct dentry * dentry, int mode)
@@ -108,16 +111,17 @@
 	if (l > dir->i_sb->s_blocksize)
 		goto out;
 
-	err = -ENOSPC;
 	inode = sysv_new_inode(dir, S_IFLNK|0777);
-	if (!inode)
+	err = PTR_ERR(inode);
+	if (IS_ERR(inode))
 		goto out;
-
+	
 	sysv_set_inode(inode, 0);
 	err = block_symlink(inode, symname, l);
 	if (err)
 		goto out_fail;
 
+	mark_inode_dirty(inode);
 	err = add_nondir(dentry, inode);
 out:
 	return err;
@@ -153,16 +157,13 @@
 
 	if (dir->i_nlink >= dir->i_sb->sv_link_max) 
 		goto out;
-
 	inc_count(dir);
 
-	if (dir->i_mode & S_ISGID)
-		mode |= S_ISGID;
-
-	err = -ENOSPC;
 	inode = sysv_new_inode(dir, S_IFDIR|mode);
-	if (!inode)
+	err = PTR_ERR(inode);
+	if (IS_ERR(inode))
 		goto out_dir;
+
 	sysv_set_inode(inode, 0);
 
 	inc_count(inode);
@@ -217,6 +218,7 @@
 	if (sysv_empty_dir(inode)) {
 		err = sysv_unlink(dir, dentry);
 		if (!err) {
+			inode->i_size = 0;
 			dec_count(inode);
 			dec_count(dir);
 		}
diff -urN linux-2.4.7-pre6/include/linux/amigaffs.h linux/include/linux/amigaffs.h
--- linux-2.4.7-pre6/include/linux/amigaffs.h	Thu Apr 19 22:57:06 2001
+++ linux/include/linux/amigaffs.h	Mon Dec  3 22:55:50 2001
@@ -90,6 +90,38 @@
 	((u32 *)bh->b_data)[0] = cpu_to_be32(tmp - val);
 }
 
+static inline void
+affs_lock_link(struct inode *inode)
+{
+	down(&AFFS_INODE->i_link_lock);
+}
+static inline void
+affs_unlock_link(struct inode *inode)
+{
+	up(&AFFS_INODE->i_link_lock);
+}
+static inline void
+affs_lock_dir(struct inode *inode)
+{
+	down(&AFFS_INODE->i_hash_lock);
+}
+static inline void
+affs_unlock_dir(struct inode *inode)
+{
+	up(&AFFS_INODE->i_hash_lock);
+}
+static inline void
+affs_lock_ext(struct inode *inode)
+{
+	down(&AFFS_INODE->i_ext_lock);
+}
+static inline void
+affs_unlock_ext(struct inode *inode)
+{
+	up(&AFFS_INODE->i_ext_lock);
+}
+
+
 #define MIN(a, b) ({		\
 	typeof(a) _a = (a);	\
 	typeof(b) _b = (b);	\
diff -urN linux-2.4.7-pre6/include/linux/cdrom.h linux/include/linux/cdrom.h
--- linux-2.4.7-pre6/include/linux/cdrom.h	Tue Jul  3 15:42:55 2001
+++ linux/include/linux/cdrom.h	Mon Dec  3 22:55:50 2001
@@ -729,7 +729,8 @@
 	struct cdrom_device_ops  *ops;  /* link to device_ops */
 	struct cdrom_device_info *next; /* next device_info for this major */
 	void *handle;		        /* driver-dependent data */
-	devfs_handle_t de;		/* real driver creates this  */
+	devfs_handle_t de;		/* real driver should create this  */
+	int number;			/* generic driver updates this  */
 /* specifications */
         kdev_t dev;	                /* device number */
 	int mask;                       /* mask of capability: disables them */
diff -urN linux-2.4.7-pre6/include/linux/completion.h linux/include/linux/completion.h
--- linux-2.4.7-pre6/include/linux/completion.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/completion.h	Mon Dec  3 22:55:50 2001
@@ -0,0 +1,35 @@
+#ifndef __LINUX_COMPLETION_H
+#define __LINUX_COMPLETION_H
+
+/*
+ * (C) Copyright 2001 Linus Torvalds
+ *
+ * Atomic wait-for-completion handler data structures.
+ * See kernel/sched.c for details.
+ */
+
+#include <linux/wait.h>
+
+struct completion {
+	unsigned int done;
+	wait_queue_head_t wait;
+};
+
+#define COMPLETION_INITIALIZER(work) \
+	{ 0, __WAIT_QUEUE_HEAD_INITIALIZER((work).wait) }
+
+#define DECLARE_COMPLETION(work) \
+	struct completion work = COMPLETION_INITIALIZER(work)
+
+static inline void init_completion(struct completion *x)
+{
+	x->done = 0;
+	init_waitqueue_head(&x->wait);
+}
+
+extern void FASTCALL(wait_for_completion(struct completion *));
+extern void FASTCALL(complete(struct completion *));
+
+#define INIT_COMPLETION(x)	((x).done = 0)
+
+#endif
diff -urN linux-2.4.7-pre6/include/linux/devfs_fs_kernel.h linux/include/linux/devfs_fs_kernel.h
--- linux-2.4.7-pre6/include/linux/devfs_fs_kernel.h	Tue Jul  3 15:42:55 2001
+++ linux/include/linux/devfs_fs_kernel.h	Mon Dec  3 22:55:50 2001
@@ -3,6 +3,11 @@
 
 #include <linux/fs.h>
 #include <linux/config.h>
+#include <linux/locks.h>
+#include <linux/kdev_t.h>
+#include <linux/types.h>
+
+#include <asm/semaphore.h>
 
 #define DEVFS_SUPER_MAGIC                0x1373
 
@@ -53,6 +58,19 @@
 
 
 #ifdef CONFIG_DEVFS_FS
+
+struct unique_numspace
+{
+    spinlock_t init_lock;
+    unsigned char sem_initialised;
+    unsigned int num_free;          /*  Num free in bits       */
+    unsigned int length;            /*  Array length in bytes  */
+    __u32 *bits;
+    struct semaphore semaphore;
+};
+
+#define UNIQUE_NUMBERSPACE_INITIALISER {SPIN_LOCK_UNLOCKED, 0, 0, 0, NULL}
+
 extern devfs_handle_t devfs_register (devfs_handle_t dir, const char *name,
 				      unsigned int flags,
 				      unsigned int major, unsigned int minor,
@@ -95,10 +113,26 @@
 				   unsigned int flags, unsigned int major,
 				   unsigned int minor_start,
 				   umode_t mode, void *ops, void *info);
+extern int devfs_alloc_major (char type);
+extern void devfs_dealloc_major (char type, int major);
+extern kdev_t devfs_alloc_devnum (char type);
+extern void devfs_dealloc_devnum (char type, kdev_t devnum);
+extern int devfs_alloc_unique_number (struct unique_numspace *space);
+extern void devfs_dealloc_unique_number (struct unique_numspace *space,
+					 int number);
 
 extern void mount_devfs_fs (void);
 extern void devfs_make_root (const char *name);
+
 #else  /*  CONFIG_DEVFS_FS  */
+
+struct unique_numspace
+{
+    char dummy;
+};
+
+#define UNIQUE_NUMBERSPACE_INITIALISER {0}
+
 static inline devfs_handle_t devfs_register (devfs_handle_t dir,
 					     const char *name,
 					     unsigned int flags,
@@ -228,6 +262,37 @@
 					  unsigned int major,
 					  unsigned int minor_start,
 					  umode_t mode, void *ops, void *info)
+{
+    return;
+}
+
+static inline int devfs_alloc_major (char type)
+{
+    return -1;
+}
+
+static inline void devfs_dealloc_major (char type, int major)
+{
+    return;
+}
+
+static inline kdev_t devfs_alloc_devnum (char type)
+{
+    return NODEV;
+}
+
+static inline void devfs_dealloc_devnum (char type, kdev_t devnum)
+{
+    return;
+}
+
+static inline int devfs_alloc_unique_number (struct unique_numspace *space)
+{
+    return -1;
+}
+
+static inline void devfs_dealloc_unique_number (struct unique_numspace *space,
+						int number)
 {
     return;
 }
diff -urN linux-2.4.7-pre6/include/linux/ext2_fs.h linux/include/linux/ext2_fs.h
--- linux-2.4.7-pre6/include/linux/ext2_fs.h	Tue Jul  3 15:42:55 2001
+++ linux/include/linux/ext2_fs.h	Mon Dec  3 22:55:50 2001
@@ -53,7 +53,7 @@
 #endif
 
 /*
- * Special inodes numbers
+ * Special inode numbers
  */
 #define	EXT2_BAD_INO		 1	/* Bad blocks inode */
 #define EXT2_ROOT_INO		 2	/* Root inode */
@@ -448,19 +448,31 @@
 	EXT2_SB(sb)->s_es->s_feature_incompat &= ~cpu_to_le32(mask)
 
 #define EXT2_FEATURE_COMPAT_DIR_PREALLOC	0x0001
+#define EXT2_FEATURE_COMPAT_IMAGIC_INODES	0x0002
+#define EXT3_FEATURE_COMPAT_HAS_JOURNAL		0x0004
+#define EXT2_FEATURE_COMPAT_EXT_ATTR		0x0008
+#define EXT2_FEATURE_COMPAT_RESIZE_INO		0x0010
+#define EXT2_FEATURE_COMPAT_DIR_INDEX		0x0020
+#define EXT2_FEATURE_COMPAT_ANY			0xffffffff
 
 #define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER	0x0001
 #define EXT2_FEATURE_RO_COMPAT_LARGE_FILE	0x0002
 #define EXT2_FEATURE_RO_COMPAT_BTREE_DIR	0x0004
+#define EXT2_FEATURE_RO_COMPAT_ANY		0xffffffff
 
 #define EXT2_FEATURE_INCOMPAT_COMPRESSION	0x0001
 #define EXT2_FEATURE_INCOMPAT_FILETYPE		0x0002
+#define EXT3_FEATURE_INCOMPAT_RECOVER		0x0004
+#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV	0x0008
+#define EXT2_FEATURE_INCOMPAT_ANY		0xffffffff
 
 #define EXT2_FEATURE_COMPAT_SUPP	0
 #define EXT2_FEATURE_INCOMPAT_SUPP	EXT2_FEATURE_INCOMPAT_FILETYPE
 #define EXT2_FEATURE_RO_COMPAT_SUPP	(EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
 					 EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
 					 EXT2_FEATURE_RO_COMPAT_BTREE_DIR)
+#define EXT2_FEATURE_RO_COMPAT_UNSUPPORTED	~EXT2_FEATURE_RO_COMPAT_SUPP
+#define EXT2_FEATURE_INCOMPAT_UNSUPPORTED	~EXT2_FEATURE_INCOMPAT_SUPP
 
 /*
  * Default values for user and/or group using reserved blocks
diff -urN linux-2.4.7-pre6/include/linux/ext2_fs_i.h linux/include/linux/ext2_fs_i.h
--- linux-2.4.7-pre6/include/linux/ext2_fs_i.h	Tue May 11 14:37:47 1999
+++ linux/include/linux/ext2_fs_i.h	Mon Dec  3 22:55:50 2001
@@ -29,13 +29,11 @@
 	__u32	i_file_acl;
 	__u32	i_dir_acl;
 	__u32	i_dtime;
-	__u32	not_used_1;	/* FIX: not used/ 2.2 placeholder */
 	__u32	i_block_group;
 	__u32	i_next_alloc_block;
 	__u32	i_next_alloc_goal;
 	__u32	i_prealloc_block;
 	__u32	i_prealloc_count;
-	__u32	i_high_size;
 	int	i_new_inode:1;	/* Is a freshly allocated inode */
 };
 
diff -urN linux-2.4.7-pre6/include/linux/fs_struct.h linux/include/linux/fs_struct.h
--- linux-2.4.7-pre6/include/linux/fs_struct.h	Thu Mar 15 09:56:07 2001
+++ linux/include/linux/fs_struct.h	Mon Dec  3 22:55:50 2001
@@ -13,7 +13,7 @@
 #define INIT_FS { \
 	ATOMIC_INIT(1), \
 	RW_LOCK_UNLOCKED, \
-	0000, \
+	0022, \
 	NULL, NULL, NULL, NULL, NULL, NULL \
 }
 
diff -urN linux-2.4.7-pre6/include/linux/genhd.h linux/include/linux/genhd.h
--- linux-2.4.7-pre6/include/linux/genhd.h	Tue Jul  3 15:42:55 2001
+++ linux/include/linux/genhd.h	Mon Dec  3 22:55:50 2001
@@ -51,6 +51,7 @@
 	long start_sect;
 	long nr_sects;
 	devfs_handle_t de;              /* primary (master) devfs entry  */
+	int number;                     /* stupid old code wastes space  */
 };
 
 #define GENHD_FL_REMOVABLE  1
diff -urN linux-2.4.7-pre6/include/linux/lvm.h linux/include/linux/lvm.h
--- linux-2.4.7-pre6/include/linux/lvm.h	Fri Feb 16 16:06:17 2001
+++ linux/include/linux/lvm.h	Mon Dec  3 22:55:50 2001
@@ -299,7 +299,7 @@
 
 #define	LVM_SNAPSHOT_MAX_CHUNK	1024	/* 1024 KB */
 #define	LVM_SNAPSHOT_DEF_CHUNK	64	/* 64  KB */
-#define	LVM_SNAPSHOT_MIN_CHUNK	1	/* 1   KB */
+#define	LVM_SNAPSHOT_MIN_CHUNK	(PAGE_SIZE/1024)	/* 4 or 8 KB */
 
 #define	UNDEF	-1
 #define FALSE	0
@@ -585,7 +585,7 @@
 } le_remap_req_t;
 
 typedef struct lv_bmap {
-	ulong lv_block;
+	uint32_t lv_block;
 	dev_t lv_dev;
 } lv_bmap_t;
 
diff -urN linux-2.4.7-pre6/include/linux/ntfs_fs_i.h linux/include/linux/ntfs_fs_i.h
--- linux-2.4.7-pre6/include/linux/ntfs_fs_i.h	Wed Apr 18 11:49:12 2001
+++ linux/include/linux/ntfs_fs_i.h	Mon Dec  3 22:55:50 2001
@@ -42,34 +42,41 @@
 /* unicode character type */
 #ifndef NTFS_WCHAR_T
 #define NTFS_WCHAR_T
-typedef unsigned short     ntfs_wchar_t;
+typedef u16 ntfs_wchar_t;
 #endif
 /* file offset */
 #ifndef NTFS_OFFSET_T
 #define NTFS_OFFSET_T
-typedef unsigned long long ntfs_offset_t;
+typedef s64 ntfs_offset_t;
 #endif
 /* UTC */
 #ifndef NTFS_TIME64_T
 #define NTFS_TIME64_T
-typedef unsigned long long ntfs_time64_t;
+typedef u64 ntfs_time64_t;
 #endif
-/* This is really unsigned long long. So we support only volumes up to 2 TB */
+/*
+ * This is really signed long long. So we support only volumes up to 2Tb. This
+ * is ok as Win2k also only uses 32-bits to store clusters.
+ * Whatever you do keep this a SIGNED value or a lot of NTFS users with
+ * corrupted filesystems will lynch you! It causes massive fs corruption when
+ * unsigned due to the nature of many checks relying on being performed on
+ * signed quantities. (AIA)
+ */
 #ifndef NTFS_CLUSTER_T
 #define NTFS_CLUSTER_T
-typedef unsigned int ntfs_cluster_t;
+typedef s32 ntfs_cluster_t;
 #endif
 
 /* Definition of the NTFS in-memory inode structure. */
 struct ntfs_inode_info{
 	unsigned long mmu_private;
 	struct ntfs_sb_info *vol;
-	int i_number;                /* Should be really 48 bits. */
-	__u16 sequence_number;	     /* The current sequence number. */
-	unsigned char* attr;         /* Array of the attributes. */
-	int attr_count;              /* Size of attrs[]. */
+	unsigned long i_number;		/* Should be really 48 bits. */
+	__u16 sequence_number;		/* The current sequence number. */
+	unsigned char *attr;		/* Array of the attributes. */
+	int attr_count;			/* Size of attrs[]. */
 	struct ntfs_attribute *attrs;
-	int record_count;            /* Size of records[]. */
+	int record_count;		/* Size of records[]. */
 	int *records; /* Array of the record numbers of the $Mft whose 
 		       * attributes have been inserted in the inode. */
 	union {
diff -urN linux-2.4.7-pre6/include/linux/ntfs_fs_sb.h linux/include/linux/ntfs_fs_sb.h
--- linux-2.4.7-pre6/include/linux/ntfs_fs_sb.h	Wed Apr 18 11:49:12 2001
+++ linux/include/linux/ntfs_fs_sb.h	Mon Dec  3 22:55:50 2001
@@ -1,6 +1,8 @@
 #ifndef _LINUX_NTFS_FS_SB_H
 #define _LINUX_NTFS_FS_SB_H
 
+typedef __s64 LCN;
+
 struct ntfs_sb_info{
 	/* Configuration provided by user at mount time. */
 	ntfs_uid_t uid;
@@ -26,14 +28,16 @@
 	ntfs_u32 at_bitmap;
 	ntfs_u32 at_symlink; /* aka SYMBOLIC_LINK or REPARSE_POINT */
 	/* Data read / calculated from the boot file. */
-	int blocksize;
-	int clusterfactorbits;
-	int clustersize;
-	int mft_recordsize;
+	int sector_size;
+	int cluster_size;
+	int cluster_size_bits;
 	int mft_clusters_per_record;
-	int index_recordsize;
+	int mft_record_size;
+	int mft_record_size_bits;
 	int index_clusters_per_record;
-	int mft_cluster;
+	int index_record_size;
+	int index_record_size_bits;
+	LCN mft_lcn;
 	/* Data read from special files. */
 	unsigned char *mft;
 	unsigned short *upcase;
@@ -43,6 +47,7 @@
 	struct ntfs_inode_info *mftmirr;
 	struct ntfs_inode_info *bitmap;
 	struct super_block *sb;
+	unsigned char ino_flags;
 };
 
 #endif
diff -urN linux-2.4.7-pre6/include/linux/sched.h linux/include/linux/sched.h
--- linux-2.4.7-pre6/include/linux/sched.h	Tue Jul  3 15:42:55 2001
+++ linux/include/linux/sched.h	Mon Dec  3 22:55:50 2001
@@ -124,6 +124,8 @@
 	int sched_priority;
 };
 
+struct completion;
+
 #ifdef __KERNEL__
 
 #include <linux/spinlock.h>
@@ -344,7 +346,7 @@
 	struct task_struct **pidhash_pprev;
 
 	wait_queue_head_t wait_chldexit;	/* for wait4() */
-	struct semaphore *vfork_sem;		/* for vfork() */
+	struct completion *vfork_done;		/* for vfork() */
 	unsigned long rt_priority;
 	unsigned long it_real_value, it_prof_value, it_virt_value;
 	unsigned long it_real_incr, it_prof_incr, it_virt_incr;
@@ -412,7 +414,6 @@
 #define PF_DUMPCORE	0x00000200	/* dumped core */
 #define PF_SIGNALED	0x00000400	/* killed by a signal */
 #define PF_MEMALLOC	0x00000800	/* Allocating memory */
-#define PF_VFORK	0x00001000	/* Wake up parent in mm_release */
 
 #define PF_USEDFPU	0x00100000	/* task used FPU this quantum (SMP) */
 
diff -urN linux-2.4.7-pre6/include/linux/usb.h linux/include/linux/usb.h
--- linux-2.4.7-pre6/include/linux/usb.h	Mon Dec  3 22:55:41 2001
+++ linux/include/linux/usb.h	Mon Dec  3 22:55:50 2001
@@ -21,6 +21,7 @@
 /*
  * USB types
  */
+#define USB_TYPE_MASK			(0x03 << 5)
 #define USB_TYPE_STANDARD		(0x00 << 5)
 #define USB_TYPE_CLASS			(0x01 << 5)
 #define USB_TYPE_VENDOR			(0x02 << 5)
@@ -595,6 +596,7 @@
 	int slow;			/* Slow device? */
 
 	atomic_t refcnt;		/* Reference count */
+	struct semaphore serialize;
 
 	unsigned int toggle[2];		/* one bit for each endpoint ([0] = IN, [1] = OUT) */
 	unsigned int halted[2];		/* endpoint halts; one bit per endpoint # & direction; */
diff -urN linux-2.4.7-pre6/kernel/fork.c linux/kernel/fork.c
--- linux-2.4.7-pre6/kernel/fork.c	Mon Apr 30 22:23:29 2001
+++ linux/kernel/fork.c	Mon Dec  3 22:55:50 2001
@@ -18,6 +18,7 @@
 #include <linux/smp_lock.h>
 #include <linux/module.h>
 #include <linux/vmalloc.h>
+#include <linux/completion.h>
 
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
@@ -269,11 +270,12 @@
 void mm_release(void)
 {
 	struct task_struct *tsk = current;
+	struct completion *vfork_done = tsk->vfork_done;
 
 	/* notify parent sleeping on vfork() */
-	if (tsk->flags & PF_VFORK) {
-		tsk->flags &= ~PF_VFORK;
-		up(tsk->p_opptr->vfork_sem);
+	if (vfork_done) {
+		tsk->vfork_done = NULL;
+		complete(vfork_done);
 	}
 }
 
@@ -536,12 +538,10 @@
 {
 	unsigned long new_flags = p->flags;
 
-	new_flags &= ~(PF_SUPERPRIV | PF_USEDFPU | PF_VFORK);
+	new_flags &= ~(PF_SUPERPRIV | PF_USEDFPU);
 	new_flags |= PF_FORKNOEXEC;
 	if (!(clone_flags & CLONE_PTRACE))
 		p->ptrace = 0;
-	if (clone_flags & CLONE_VFORK)
-		new_flags |= PF_VFORK;
 	p->flags = new_flags;
 }
 
@@ -557,18 +557,22 @@
 int do_fork(unsigned long clone_flags, unsigned long stack_start,
 	    struct pt_regs *regs, unsigned long stack_size)
 {
-	int retval = -ENOMEM;
+	int retval;
 	struct task_struct *p;
-	DECLARE_MUTEX_LOCKED(sem);
+	struct completion vfork;
+
+	retval = -EPERM;
 
+	/* 
+	 * CLONE_PID is only allowed for the initial SMP swapper
+	 * calls
+	 */
 	if (clone_flags & CLONE_PID) {
-		/* This is only allowed from the boot up thread */
 		if (current->pid)
-			return -EPERM;
+			goto fork_out;
 	}
-	
-	current->vfork_sem = &sem;
 
+	retval = -ENOMEM;
 	p = alloc_task_struct();
 	if (!p)
 		goto fork_out;
@@ -578,6 +582,7 @@
 	retval = -EAGAIN;
 	if (atomic_read(&p->user->processes) >= p->rlim[RLIMIT_NPROC].rlim_cur)
 		goto bad_fork_free;
+
 	atomic_inc(&p->user->__count);
 	atomic_inc(&p->user->processes);
 
@@ -604,14 +609,13 @@
 	p->run_list.next = NULL;
 	p->run_list.prev = NULL;
 
-	if ((clone_flags & CLONE_VFORK) || !(clone_flags & CLONE_PARENT)) {
-		p->p_opptr = current;
-		if (!(p->ptrace & PT_PTRACED))
-			p->p_pptr = current;
-	}
 	p->p_cptr = NULL;
 	init_waitqueue_head(&p->wait_chldexit);
-	p->vfork_sem = NULL;
+	p->vfork_done = NULL;
+	if (clone_flags & CLONE_VFORK) {
+		p->vfork_done = &vfork;
+		init_completion(&vfork);
+	}
 	spin_lock_init(&p->alloc_lock);
 
 	p->sigpending = 0;
@@ -685,11 +689,24 @@
 	retval = p->pid;
 	p->tgid = retval;
 	INIT_LIST_HEAD(&p->thread_group);
+
+	/* Need tasklist lock for parent etc handling! */
 	write_lock_irq(&tasklist_lock);
+
+	/* CLONE_PARENT and CLONE_THREAD re-use the old parent */
+	p->p_opptr = current->p_opptr;
+	p->p_pptr = current->p_pptr;
+	if (!(clone_flags & (CLONE_PARENT | CLONE_THREAD))) {
+		p->p_opptr = current;
+		if (!(p->ptrace & PT_PTRACED))
+			p->p_pptr = current;
+	}
+
 	if (clone_flags & CLONE_THREAD) {
 		p->tgid = current->tgid;
 		list_add(&p->thread_group, &current->thread_group);
 	}
+
 	SET_LINKS(p);
 	hash_pid(p);
 	nr_threads++;
@@ -700,10 +717,10 @@
 
 	wake_up_process(p);		/* do this last */
 	++total_forks;
+	if (clone_flags & CLONE_VFORK)
+		wait_for_completion(&vfork);
 
 fork_out:
-	if ((clone_flags & CLONE_VFORK) && (retval > 0)) 
-		down(&sem);
 	return retval;
 
 bad_fork_cleanup_mm:
diff -urN linux-2.4.7-pre6/kernel/kmod.c linux/kernel/kmod.c
--- linux-2.4.7-pre6/kernel/kmod.c	Tue May  1 16:05:00 2001
+++ linux/kernel/kmod.c	Mon Dec  3 22:55:50 2001
@@ -24,6 +24,7 @@
 #include <linux/unistd.h>
 #include <linux/kmod.h>
 #include <linux/smp_lock.h>
+#include <linux/completion.h>
 
 #include <asm/uaccess.h>
 
@@ -263,7 +264,7 @@
 #endif /* CONFIG_HOTPLUG */
 
 struct subprocess_info {
-	struct semaphore *sem;
+	struct completion *complete;
 	char *path;
 	char **argv;
 	char **envp;
@@ -302,7 +303,7 @@
 	pid = kernel_thread(____call_usermodehelper, sub_info, CLONE_VFORK | SIGCHLD);
 	if (pid < 0)
 		sub_info->retval = pid;
-	up(sub_info->sem);
+	complete(sub_info->complete);
 }
 
 /**
@@ -320,9 +321,9 @@
  */
 int call_usermodehelper(char *path, char **argv, char **envp)
 {
-	DECLARE_MUTEX_LOCKED(sem);
+	DECLARE_COMPLETION(work);
 	struct subprocess_info sub_info = {
-		sem:		&sem,
+		complete:	&work,
 		path:		path,
 		argv:		argv,
 		envp:		envp,
@@ -341,7 +342,7 @@
 		__call_usermodehelper(&sub_info);
 	} else {
 		schedule_task(&tqs);
-		down(&sem);		/* Wait until keventd has started the subprocess */
+		wait_for_completion(&work);
 	}
 out:
 	return sub_info.retval;
diff -urN linux-2.4.7-pre6/kernel/ksyms.c linux/kernel/ksyms.c
--- linux-2.4.7-pre6/kernel/ksyms.c	Mon Dec  3 22:55:41 2001
+++ linux/kernel/ksyms.c	Mon Dec  3 22:55:50 2001
@@ -23,8 +23,6 @@
 #include <linux/serial.h>
 #include <linux/locks.h>
 #include <linux/delay.h>
-#include <linux/minix_fs.h>
-#include <linux/ext2_fs.h>
 #include <linux/random.h>
 #include <linux/reboot.h>
 #include <linux/pagemap.h>
diff -urN linux-2.4.7-pre6/kernel/sched.c linux/kernel/sched.c
--- linux-2.4.7-pre6/kernel/sched.c	Mon Dec  3 22:55:41 2001
+++ linux/kernel/sched.c	Mon Dec  3 22:55:50 2001
@@ -25,6 +25,7 @@
 #include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
+#include <linux/completion.h>
 
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
@@ -606,8 +607,11 @@
 #endif
 	spin_unlock_irq(&runqueue_lock);
 
-	if (prev == next)
+	if (prev == next) {
+		/* We won't go through the normal tail, so do this by hand */
+		prev->policy &= ~SCHED_YIELD;
 		goto same_process;
+	}
 
 #ifdef CONFIG_SMP
  	/*
@@ -756,6 +760,36 @@
 		__wake_up_common(q, mode, nr, 1);
 		wq_read_unlock_irqrestore(&q->lock, flags);
 	}
+}
+
+void complete(struct completion *x)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&x->wait.lock, flags);
+	x->done++;
+	__wake_up_common(&x->wait, TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE, 1, 0);
+	spin_unlock_irqrestore(&x->wait.lock, flags);
+}
+
+void wait_for_completion(struct completion *x)
+{
+	spin_lock_irq(&x->wait.lock);
+	if (!x->done) {
+		DECLARE_WAITQUEUE(wait, current);
+
+		wait.flags |= WQ_FLAG_EXCLUSIVE;
+		__add_wait_queue_tail(&x->wait, &wait);
+		do {
+			__set_current_state(TASK_UNINTERRUPTIBLE);
+			spin_unlock_irq(&x->wait.lock);
+			schedule();
+			spin_lock_irq(&x->wait.lock);
+		} while (!x->done);
+		__remove_wait_queue(&x->wait, &wait);
+	}
+	x->done--;
+	spin_unlock_irq(&x->wait.lock);
 }
 
 #define	SLEEP_ON_VAR				\
diff -urN linux-2.4.7-pre6/mm/Makefile linux/mm/Makefile
--- linux-2.4.7-pre6/mm/Makefile	Fri Dec 29 14:07:24 2000
+++ linux/mm/Makefile	Mon Dec  3 22:55:50 2001
@@ -9,6 +9,8 @@
 
 O_TARGET := mm.o
 
+export-objs := shmem.o
+
 obj-y	 := memory.o mmap.o filemap.o mprotect.o mlock.o mremap.o \
 	    vmalloc.o slab.o bootmem.o swap.o vmscan.o page_io.o \
 	    page_alloc.o swap_state.o swapfile.o numa.o oom_kill.o \
diff -urN linux-2.4.7-pre6/mm/filemap.c linux/mm/filemap.c
--- linux-2.4.7-pre6/mm/filemap.c	Mon Dec  3 22:55:41 2001
+++ linux/mm/filemap.c	Mon Dec  3 22:55:50 2001
@@ -760,7 +760,7 @@
 		lock_page(page);
 
 		/* Is the page still hashed? Ok, good.. */
-		if (page->mapping)
+		if (page->mapping == mapping && page->index == offset)
 			return page;
 
 		/* Nope: we raced. Release and try again.. */
diff -urN linux-2.4.7-pre6/mm/memory.c linux/mm/memory.c
--- linux-2.4.7-pre6/mm/memory.c	Mon Dec  3 22:55:41 2001
+++ linux/mm/memory.c	Mon Dec  3 22:55:50 2001
@@ -888,8 +888,7 @@
  * change only once the write actually happens. This avoids a few races,
  * and potentially makes it more efficient.
  *
- * We enter with the page table read-lock held, and need to exit without
- * it.
+ * We hold the mm semaphore and the page_table_lock on entry and exit.
  */
 static int do_wp_page(struct mm_struct *mm, struct vm_area_struct * vma,
 	unsigned long address, pte_t *page_table, pte_t pte)
diff -urN linux-2.4.7-pre6/mm/shmem.c linux/mm/shmem.c
--- linux-2.4.7-pre6/mm/shmem.c	Mon Dec  3 22:55:41 2001
+++ linux/mm/shmem.c	Mon Dec  3 22:55:50 2001
@@ -3,7 +3,8 @@
  *
  * Copyright (C) 2000 Linus Torvalds.
  *		 2000 Transmeta Corp.
- *		 2000 Christoph Rohland
+ *		 2000-2001 Christoph Rohland
+ *		 2000-2001 SAP AG
  * 
  * This file is released under the GPL.
  */
@@ -33,7 +34,7 @@
 #define TMPFS_MAGIC	0x01021994
 
 #define ENTRIES_PER_PAGE (PAGE_SIZE/sizeof(unsigned long))
-#define NR_SINGLE (ENTRIES_PER_PAGE + SHMEM_NR_DIRECT)
+#define SHMEM_MAX_BLOCKS (SHMEM_NR_DIRECT + ENTRIES_PER_PAGE*ENTRIES_PER_PAGE)
 
 static struct super_operations shmem_ops;
 static struct address_space_operations shmem_aops;
@@ -193,7 +194,14 @@
 	}
 
 out:
-	info->max_index = index;
+	/*
+	 * We have no chance to give an error, so we limit it to max
+	 * size here and the application will fail later
+	 */
+	if (index > SHMEM_MAX_BLOCKS) 
+		info->max_index = SHMEM_MAX_BLOCKS;
+	else
+		info->max_index = index;
 	info->swapped -= freed;
 	shmem_recalc_inode(inode);
 	spin_unlock (&info->lock);
@@ -311,6 +319,7 @@
 		return page;
 	}
 	
+	shmem_recalc_inode(inode);
 	if (entry->val) {
 		unsigned long flags;
 
@@ -390,22 +399,9 @@
 
 static int shmem_getpage(struct inode * inode, unsigned long idx, struct page **ptr)
 {
-	struct address_space * mapping = inode->i_mapping;
 	int error;
 
-	*ptr = NOPAGE_SIGBUS;
-	if (inode->i_size <= (loff_t) idx * PAGE_CACHE_SIZE)
-		return -EFAULT;
-
-	*ptr = __find_get_page(mapping, idx, page_hash(mapping, idx));
-	if (*ptr) {
-		if (Page_Uptodate(*ptr))
-			return 0;
-		page_cache_release(*ptr);
-	}
-
 	down (&inode->i_sem);
-	/* retest we may have slept */
 	if (inode->i_size < (loff_t) idx * PAGE_CACHE_SIZE)
 		goto sigbus;
 	*ptr = shmem_getpage_locked(inode, idx);
@@ -1024,6 +1020,8 @@
 	unsigned long max_inodes, inodes;
 	struct shmem_sb_info *info = &sb->u.shmem_sb;
 
+	max_blocks = info->max_blocks;
+	max_inodes = info->max_inodes;
 	if (shmem_parse_options (data, NULL, &max_blocks, &max_inodes))
 		return -EINVAL;
 
@@ -1071,7 +1069,7 @@
 	sb->u.shmem_sb.free_blocks = blocks;
 	sb->u.shmem_sb.max_inodes = inodes;
 	sb->u.shmem_sb.free_inodes = inodes;
-	sb->s_maxbytes = (unsigned long long)(SHMEM_NR_DIRECT + (ENTRIES_PER_PAGE*ENTRIES_PER_PAGE)) << PAGE_CACHE_SHIFT;
+	sb->s_maxbytes = (unsigned long long)SHMEM_MAX_BLOCKS << PAGE_CACHE_SHIFT;
 	sb->s_blocksize = PAGE_CACHE_SIZE;
 	sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
 	sb->s_magic = TMPFS_MAGIC;
@@ -1279,9 +1277,11 @@
 	struct qstr this;
 	int vm_enough_memory(long pages);
 
-	error = -ENOMEM;
+	if (size > (unsigned long long) SHMEM_MAX_BLOCKS << PAGE_CACHE_SHIFT)
+		return ERR_PTR(-EINVAL);
+
 	if (!vm_enough_memory((size) >> PAGE_SHIFT))
-		goto out;
+		return ERR_PTR(-ENOMEM);
 
 	this.name = name;
 	this.len = strlen(name);
@@ -1289,7 +1289,7 @@
 	root = tmpfs_fs_type.kern_mnt->mnt_root;
 	dentry = d_alloc(root, &this);
 	if (!dentry)
-		goto out;
+		return ERR_PTR(-ENOMEM);
 
 	error = -ENFILE;
 	file = get_empty_filp();
@@ -1315,7 +1315,6 @@
 	put_filp(file);
 put_dentry:
 	dput (dentry);
-out:
 	return ERR_PTR(error);	
 }
 /*
diff -urN linux-2.4.7-pre6/net/core/dev.c linux/net/core/dev.c
--- linux-2.4.7-pre6/net/core/dev.c	Mon Dec  3 22:55:41 2001
+++ linux/net/core/dev.c	Mon Dec  3 22:55:50 2001
@@ -2654,10 +2654,6 @@
 	if (!dev_boot_phase)
 		return 0;
 
-#ifdef CONFIG_NET_SCHED
-	pktsched_init();
-#endif
-
 #ifdef CONFIG_NET_DIVERT
 	dv_init();
 #endif /* CONFIG_NET_DIVERT */
@@ -2771,6 +2767,10 @@
 
 	dst_init();
 	dev_mcast_init();
+
+#ifdef CONFIG_NET_SCHED
+	pktsched_init();
+#endif
 
 	/*
 	 *	Initialise network devices
diff -urN linux-2.4.7-pre6/net/netsyms.c linux/net/netsyms.c
--- linux-2.4.7-pre6/net/netsyms.c	Mon Dec  3 22:55:41 2001
+++ linux/net/netsyms.c	Mon Dec  3 22:55:50 2001
@@ -252,6 +252,7 @@
 EXPORT_SYMBOL(ip_mc_inc_group);
 EXPORT_SYMBOL(ip_mc_dec_group);
 EXPORT_SYMBOL(ip_finish_output);
+EXPORT_SYMBOL(inet_stream_ops);
 EXPORT_SYMBOL(inet_dgram_ops);
 EXPORT_SYMBOL(ip_cmsg_recv);
 EXPORT_SYMBOL(inet_addr_type); 
@@ -282,7 +283,6 @@
 #endif
 #if defined (CONFIG_IPV6_MODULE) || defined (CONFIG_KHTTPD) || defined (CONFIG_KHTTPD_MODULE)
 /* inet functions common to v4 and v6 */
-EXPORT_SYMBOL(inet_stream_ops);
 EXPORT_SYMBOL(inet_release);
 EXPORT_SYMBOL(inet_stream_connect);
 EXPORT_SYMBOL(inet_dgram_connect);
diff -urN linux-2.4.7-pre6/net/unix/af_unix.c linux/net/unix/af_unix.c
--- linux-2.4.7-pre6/net/unix/af_unix.c	Mon Dec  3 22:55:41 2001
+++ linux/net/unix/af_unix.c	Mon Dec  3 22:55:50 2001
@@ -674,6 +674,7 @@
 	atomic_set(&addr->refcnt, 1);
 
 	if (sunaddr->sun_path[0]) {
+		unsigned int mode;
 		err = 0;
 		/*
 		 * Get the parent directory, calculate the hash for last
@@ -713,8 +714,8 @@
 		/*
 		 * All right, let's create it.
 		 */
-		err = vfs_mknod(nd.dentry->d_inode, dentry,
-			S_IFSOCK|sock->inode->i_mode, 0);
+		mode = S_IFSOCK | (sock->inode->i_mode & ~current->fs->umask);
+		err = vfs_mknod(nd.dentry->d_inode, dentry, mode, 0);
 		if (err)
 			goto out_mknod_dput;
 		up(&nd.dentry->d_inode->i_sem);
