diff -u --recursive --new-file v2.3.0/linux/CREDITS linux/CREDITS
--- v2.3.0/linux/CREDITS	Tue May 11 09:57:14 1999
+++ linux/CREDITS	Thu May 13 11:00:07 1999
@@ -91,6 +91,11 @@
 S: Cambridge, Massachusetts 02139
 S: USA
 
+N: Michel Aubry
+E: giovanni <giovanni@sudfr.com>
+D: Aladdin 1533/1543(C) chipset IDE
+D: VIA MVP-3/TX Pro III chipset IDE
+
 N: Jens Axboe
 E: axboe@image.dk
 D: Linux CD-ROM maintainer
@@ -765,6 +770,17 @@
 E: ajh@primag.co.uk
 D: Selection mechanism
 
+N: Andre Hedrick
+E: hedrick@astro.dyer.vanderbilt.edu
+D: Uniform Multi-Platform E-IDE driver
+D: Aladdin 1533/1543(C) chipset IDE
+D: HighPoint HPT343/5 chipset IDE
+D: PIIX chipset IDE
+D: Promise Ultra/33 chipset IDE
+D: Promise Ultra/66 chipset IDE
+S: Nashville, TN
+S: USA
+
 N: Jochen Hein
 E: jochen.hein@delphi.central.de
 P: 1024/4A27F015 25 72 FB E3 85 9F DE 3B  CB 0A DA DA 40 77 05 6C
@@ -928,6 +944,10 @@
 S: 160 00 Praha 6
 S: Czech Republic
 
+N: Andreas S. Krebs
+E: akrebs@altavista.net
+D: CYPRESS CY82C693 chipset IDE, Digital's PC-Alpha 164SX boards
+
 N: Niels Kristian Bech Jensen
 E: nkbj@image.dk
 W: http://www.image.dk/~nkbj
@@ -938,6 +958,13 @@
 S: DK-8230 Åbyhøj
 S: Denmark
 
+N: Andrzej Krzysztofowicz
+E: ankry@green.mif.pg.gda.pl
+D: Aladdin 1533/1543(C) chipset IDE
+D: PIIX chipset IDE
+S: Faculty of Applied Phys. & Math.
+S: Technical University of Gdansk
+
 N: Michael K. Johnson
 E: johnsonm@redhat.com
 W: http://www.redhat.com/~johnsonm
@@ -1729,6 +1756,10 @@
 D: added PCI support to the serial driver
 S: Buckenhof, Germany
 
+N: Michael Schmitz
+E:
+D: Macintosh IDE Driver
+
 N: Martin Schulze
 E: joey@linux.de
 W: http://home.pages.de/~joey/
@@ -2015,6 +2046,9 @@
 D: Frame buffer device and XF68_FBDev maintainer
 D: m68k IDE maintainer
 D: Amiga Zorro maintainer
+D: Amiga Buddha and Catweasel chipset IDE
+D: Atari Falcon chipset IDE
+D: Amiga Gayle chipset IDE
 S: C. Huysmansstraat 12
 S: B-3128 Baal
 S: Belgium
diff -u --recursive --new-file v2.3.0/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v2.3.0/linux/Documentation/Configure.help	Tue May 11 09:57:14 1999
+++ linux/Documentation/Configure.help	Thu May 13 11:00:08 1999
@@ -289,9 +289,9 @@
 Enhanced IDE/MFM/RLL disk/cdrom/tape/floppy support
 CONFIG_BLK_DEV_IDE
   If you say Y here, you will use the full-featured IDE driver to
-  control up to four IDE interfaces, each being able to serve a
-  "master" and a "slave" device, for a total of up to eight IDE
-  disk/cdrom/tape/floppy drives. People with SCSI-only systems
+  control up to eight IDE interfaces, each being able to serve a
+  "master" and a "slave" device, for a total of up to sixteen (16)
+  IDE disk/cdrom/tape/floppy drives.  People with SCSI-only systems
   can say N here.
 
   Useful information about large (>540 MB) IDE disks, multiple
@@ -370,6 +370,15 @@
   root filesystem (the one containing the directory /) is located on
   the IDE disk. If unsure, say Y.
 
+Use multi-mode by default
+CONFIG_IDEDISK_MULTI_MODE
+  If you get this error, try to enable this option.
+
+  hda: set_multmode: status=0x51 { DriveReady SeekComplete Error }
+  hda: set_multmode: error=0x04 { DriveStatusError }
+
+  If in doubt, say N.
+
 Include IDE/ATAPI CDROM support
 CONFIG_BLK_DEV_IDECD
   If you have a CDROM drive using the ATAPI protocol, say Y. ATAPI is
@@ -396,6 +405,17 @@
   say M here and read Documentation/modules.txt. The module will be
   called ide-cd.o.
 
+Include CD-Changer Reporting
+CONFIG_IDECD_SLOTS
+  If you have an IDE/ATAPI multi-slot cd-changer and you want
+  to report which slots have disk-present, say Y.  If you say Y
+  and there is not a multi-slot cdrom present, this code is skipped.
+
+  This could be the bases of multi-disk access based on multi-mounts.
+  This is still pie-in-the-sky.
+
+  If unsure, say N.
+
 Include IDE/ATAPI TAPE support
 CONFIG_BLK_DEV_IDETAPE
   If you have an IDE tape drive using the ATAPI protocol, say Y.
@@ -638,14 +658,28 @@
 
   Please read the comments at the top of drivers/block/ns87415.c.
 
+CY82C693 chipset support (EXPERIMENTAL)
+CONFIG_BLK_DEV_CY82C693
+
+  This driver adds detection and support for the CY82C693 chipset
+  used on Digital's PC-Alpha 164SX boards.
+
+  This requires CONFIG_IDEDMA_AUTO to be enabled.
+
+  Please read the comments at the top of drivers/block/cy82c693.c
+
 VIA82C586 chipset support (EXPERIMENTAL)
 CONFIG_BLK_DEV_VIA82C586
-  This adds initial timing settings for VIA (U)DMA onboard ide
-  controllers that are ATA3 compliant. May work with ATA4 systems, but
-  not tested to date.
+  This allows you to to configure your chipset for a better use while
+  running (U)DMA: it will allow you to enable efficiently the second
+  channel dma usage, as it is may not be set by BIOS. It allows you to
+  run a kernel command line at boot time in order to set fifo config.
+  If no command line is provided, it will try to set fifo configuration
+  at its best. It will allow you to get a proc/ide/via display
+  (while running a "cat") provided you enabled "proc" support and
+  set DISPLAY_APOLLO_TIMINGS in via82c586.c
 
-  If you say Y here, you also need to say Y to "Use DMA by default
-  when available", above.
+  This requires CONFIG_IDEDMA_AUTO to be enabled.
 
   If unsure, say N.
 
@@ -653,6 +687,81 @@
 CONFIG_BLK_DEV_CMD646
   Say Y here if you have an IDE controller like this.
 
+ALI M15x3 chipset support (EXPERIMENTAL)
+CONFIG_BLK_DEV_ALI15X3
+  This driver ensures (U)DMA support for ALI 1533, 1543 and 1543C
+  onboard chipsets.  It also tests for Simplex mode and enables
+  normal dual channel support.
+
+  This requires CONFIG_IDEDMA_AUTO to be enabled.
+
+  Please read the comments at the top of drivers/block/alim15x3.c
+
+  If unsure, say N.
+
+PROMISE PDC20246 support (EXPERIMENTAL)
+CONFIG_BLK_DEV_PDC20246
+  This driver adds up to 4 more eide devices sharing a single interrupt.
+  This add-on card is a bootable PCI UDMA controller.
+  Since multiple cards can be installed and there are BIOS ROM problems
+  that happen if the BIOS revisions of all installed cards (three-max)
+  do not match.  Should you be unable to make new BIOS chips with a burner,
+  the driver attempts to dynamic tuning of the chipset at boot-time
+  for max-speed.  Ultra33 BIOS 1.25 or new required for more than one card.
+
+  This requires CONFIG_IDEDMA_AUTO to be enabled.
+
+  Please read the comments at the top of drivers/block/pdc202xx.c
+
+  If unsure, say N.
+
+PROMISE PDC20262 support (EXPERIMENTAL)
+CONFIG_BLK_DEV_PDC20262
+  This driver adds up to 4 more eide devices sharing a single interrupt.
+  This add-on card is a bootable PCI UDMA ATA-66 controller.
+  The driver attempts to dynamic tuning of the chipset at boot-time
+  for max-speed.  Note tested limits are UDMA-2.
+  Ultra66 BIOS 1.11 or newer required.
+
+  This requires CONFIG_IDEDMA_AUTO to be enabled.
+
+  Please read the comments at the top of drivers/block/pdc202xx.c
+
+  If unsure, say N.
+
+AEC6210 chipset support
+CONFIG_BLK_DEV_AEC6210
+  This driver adds up to 4 more eide devices sharing a single interrupt.
+  This add-on card is a bootable PCI UDMA controller.  In order to get this
+  card to initialize correctly in some cases, you should include this driver.
+
+  This prefers CONFIG_IDEDMA_AUTO to be enabled, regardless.
+
+  Please read the comments at the top of drivers/block/aec6210.c
+
+Intel PIIXn chipsets support (EXPERIMENTAL)
+CONFIG_BLK_DEV_PIIX
+  This driver adds PIO mode setting and tuning for all PIIX IDE
+  controllers by Intel.  Since the BIOS can sometimes improperly tune
+  PIO 0-4 mode settings, this allows dynamic tuning of the chipset
+  via the standard end-user tool 'hdparm'.
+
+  Please read the comments at the top of drivers/block/piix.c
+
+  If unsure, say N.
+
+HPT343 chipset support (EXPERIMENTAL)
+CONFIG_BLK_DEV_HPT343
+  This driver adds up to 4 more EIDE devices sharing a single
+  interrupt. The HPT343 chipset in its current form is a non-bootable
+  PCI UDMA controller. This driver requires dynamic tuning of the
+  chipset during the ide-probe at boot. It is reported to support DVD
+  II drives, by the manufacturer.
+
+  This requires CONFIG_IDEDMA_AUTO to be enabled.
+
+  Please read the comments at the top of drivers/block/hpt343.c
+
 QDI QD6580 support
 CONFIG_BLK_DEV_QD6580
   This driver is enabled at runtime using the "ide0=qd6580" kernel
@@ -675,6 +784,68 @@
   of the ALI M1439/1443/1445/1487/1489 chipsets, and permits faster
   I/O speeds to be set as well. See the files Documentation/ide.txt
   and drivers/block/ali14xx.c for more info.
+
+Amiga builtin Gayle IDE interface support
+CONFIG_BLK_DEV_GAYLE
+  This is the IDE driver for the builtin IDE interface on some Amiga
+  models.  It supports both the `A1200 style' (used in A600 and A1200)
+  and `A4000 style' (used in A4000 and A4000T) of the Gayle IDE interface.
+  Say Y if you have such an Amiga model and want to use IDE devices
+  (hard disks, CD-ROM drives, etc.) that are connected to the builtin
+  IDE interface.
+
+Falcon IDE interface support
+CONFIG_BLK_DEV_FALCON_IDE
+  This is the IDE driver for the builtin IDE interface on the Atari Falcon.
+  Say Y if you have a Falcon and want to use IDE devices (hard disks,
+  CD-ROM drives, etc.) that are connected to the builtin IDE interface.
+
+Amiga Buddha/Catweasel IDE interface support (EXPERIMENTAL)
+CONFIG_BLK_DEV_BUDDHA
+  This is the IDE driver for the IDE interfaces on the Buddha and
+  Catweasel expansion boards.  It supports up to two interfaces on the
+  Buddha and three on the Catweasel.
+  Say Y if you have a Buddha or Catweasel expansion board and want to
+  use IDE devices (hard disks, CD-ROM drives, etc.) that are connected
+  to one of its IDE interfaces.
+
+Amiga IDE Doubler support (EXPERIMENTAL)
+CONFIG_BLK_DEV_IDEDOUBLER
+  This driver provides support for the so called `IDE doublers' (made by
+  various manufacturers, e.g. Eyetech) that can be connected to the
+  builtin IDE interface of some Amiga models. Using such an IDE doubler,
+  you can connect up to four instead of two IDE devices on the Amiga's
+  builtin IDE interface.
+  Note that the normal Amiga Gayle IDE driver may not work correctly if
+  you have an IDE doubler and don't enable this driver!
+  Say Y if you have an IDE doubler.  The driver is enabled at kernel
+  runtime using the "ide=doubler" kernel boot parameter.
+
+ Support for PowerMac IDE devices (must also enable IDE)
+ CONFIG_BLK_DEV_IDE_PMAC
+   No help for CONFIG_BLK_DEV_IDE_PMAC
+
+ PowerMac IDE DMA support
+ CONFIG_BLK_DEV_IDEDMA_PMAC
+   No help for CONFIG_BLK_DEV_IDEDMA_PMAC
+
+ Use DMA by default
+ CONFIG_PMAC_IDEDMA_AUTO
+   No help for CONFIG_PMAC_IDEDMA_AUTO
+
+Macintosh Quadra/Powerbook IDE interface support
+CONFIG_BLK_DEV_MAC_IDE
+  This is the IDE driver for the builtin IDE interface on the some m68k
+  Macintosh models. It supports both the `Quadra style' (used in Quadra/
+  Centris 630 and Performa 588 models) and `Powerbook style' (used in the
+  Powerbook 150 and 190 models) IDE interface.
+  Say Y if you have such an Macintosh model and want to use IDE devices
+  (hard disks, CD-ROM drives, etc.) that are connected to the builtin
+  IDE interface.
+
+ RapIDE interface support
+ CONFIG_BLK_DEV_IDE_RAPIDE
+   No help for CONFIG_BLK_DEV_IDE_RAPIDE
 
 XT hard disk support
 CONFIG_BLK_DEV_XD
diff -u --recursive --new-file v2.3.0/linux/Documentation/devices.tex linux/Documentation/devices.tex
--- v2.3.0/linux/Documentation/devices.tex	Sun Aug 16 11:35:51 1998
+++ linux/Documentation/devices.tex	Thu May 13 11:00:08 1999
@@ -254,7 +254,9 @@
 \major{86}{}{char }{SCSI media changer}
 \major{87}{}{char }{Sony Control-A1 stereo control bus}
 \major{88}{}{char }{COMX synchronous serial card}
+\major{  }{}{block}{Sixth IDE hard disk/CD-ROM interface}
 \major{89}{}{char }{I$^2$C bus interface}
+\major{  }{}{block}{Seventh IDE hard disk/CD-ROM interface}
 \major{90}{}{char }{Memory Technology Device (RAM, ROM, Flash)}
 \major{91}{}{char }{CAN-Bus controller}
 \major{92}{}{char }{Reserved for ith Kommunikationstechnik MIC ISDN card}
@@ -1746,11 +1748,31 @@
 \end{devicelist}
 
 \begin{devicelist}
+\major{  }{}{block}{Sixth IDE hard disk/CD-ROM interface}
+        \minor{0}{/dev/hdm}{Master: whole disk (or CD-ROM)}
+        \minor{64}{/dev/hdn}{Slave: whole disk (or CD-ROM)}
+\end{devicelist}
+
+\noindent
+Partitions are handled the same way as for the first interface (see
+major number 3).
+
+\begin{devicelist}
 \major{89}{}{char }{I$^2$C bus interface}
 	\minor{0}{/dev/i2c0}{First I$^2$C adapter}
 	\minor{1}{/dev/i2c1}{Second I$^2$C adapter}
 	\minordots
 \end{devicelist}
+
+\begin{devicelist}
+\major{  }{}{block}{Seventh IDE hard disk/CD-ROM interface}
+        \minor{0}{/dev/hdo}{Master: whole disk (or CD-ROM)}
+        \minor{64}{/dev/hdp}{Slave: whole disk (or CD-ROM)}
+\end{devicelist}
+
+\noindent
+Partitions are handled the same way as for the first interface (see
+major number 3).
 
 \begin{devicelist}
 \major{90}{}{char }{Memory Technology Device (RAM, ROM, Flash)}
diff -u --recursive --new-file v2.3.0/linux/Documentation/devices.txt linux/Documentation/devices.txt
--- v2.3.0/linux/Documentation/devices.txt	Wed Dec 16 12:52:00 1998
+++ linux/Documentation/devices.txt	Thu May 13 11:00:08 1999
@@ -1215,10 +1215,24 @@
 		  1 = /dev/comx1	COMX channel 1
 		    ...
 
+    block	Sixth IDE hard disk/CD-ROM interface
+		  0 = /dev/hdm		Master: whole disk (or CD-ROM)
+		 64 = /dev/hdn		Slave: whole disk (or CD-ROM)
+
+		Partitions are handled the same way as for the first
+		interface (see major number 3).
+
  89 char	I2C bus interface
 		  0 = /dev/i2c0		First I2C adapter
 		  1 = /dev/i2c1		Second I2C adapter
 		    ...
+
+    block	Seventh IDE hard disk/CD-ROM interface
+		  0 = /dev/hdo		Master: whole disk (or CD-ROM)
+		 64 = /dev/hdp		Slave: whole disk (or CD-ROM)
+
+		Partitions are handled the same way as for the first
+		interface (see major number 3).
 
  90 char	Memory Technology Device (RAM, ROM, Flash)
 		  0 = /dev/mtd0		First MTD (rw)
diff -u --recursive --new-file v2.3.0/linux/Makefile linux/Makefile
--- v2.3.0/linux/Makefile	Tue May 11 13:03:06 1999
+++ linux/Makefile	Tue May 11 14:37:31 1999
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 3
-SUBLEVEL = 0
+SUBLEVEL = 1
 EXTRAVERSION =
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
diff -u --recursive --new-file v2.3.0/linux/README linux/README
--- v2.3.0/linux/README	Thu Jan  7 08:41:55 1999
+++ linux/README	Thu May 13 10:56:25 1999
@@ -1,9 +1,23 @@
-	Linux kernel release 2.2.xx
+	Linux kernel release 2.3.xx
 
-These are the release notes for Linux version 2.2.  Read them carefully,
+These are the release notes for Linux version 2.3.  Read them carefully,
 as they tell you what this is all about, explain how to install the
 kernel, and what to do if something goes wrong. 
 
+Linux version 2.3 is a DEVELOPMENT kernel, and not intended for general
+public use.  Different releases may have various and sometimes severe
+bugs.  It is *strongly* recommended that you back up the previous kernel
+before installing any new 2.3.xx release.
+
+If you need to use a proven and stable Linux kernel, please use 1.2.13,
+2.0.36 or 2.2.xx.  All features which will be in the 2.3.xx releases will
+be contained in 2.4.xx when the code base has stabilized again.
+
+If you decide to use 2.3, it is recommended that you join the kernel mailing
+list.  To do this, e-mail majordomo@vger.rutgers.edu, and put in the body
+of the message "subscribe linux-kernel" or "subscribe linux-kernel-digest"
+for a daily digest of the mailing list (it is a high-traffic list.)
+
 However, please make sure you don't ask questions which are already answered
 in various files in the Documentation directory.  See DOCUMENTATION below.
 
@@ -48,12 +62,12 @@
  - If you install the full sources, do a
 
 		cd /usr/src
-		gzip -cd linux-2.2.XX.tar.gz | tar xfv -
+		gzip -cd linux-2.3.XX.tar.gz | tar xfv -
 
    to get it all put in place. Replace "XX" with the version number of the
    latest kernel.
 
- - You can also upgrade between 2.2.xx releases by patching.  Patches are
+ - You can also upgrade between 2.3.xx releases by patching.  Patches are
    distributed in the traditional gzip and the new bzip2 format.  To
    install by patching, get all the newer patch files and do
 
@@ -91,7 +105,7 @@
 
 SOFTWARE REQUIREMENTS
 
-   Compiling and running the 2.2.x kernels requires up-to-date
+   Compiling and running the 2.3.x kernels requires up-to-date
    versions of various software packages.  Consult
    ./Documentation/Changes for the minimum version numbers required
    and how to get updates for these packages.  Beware that using
diff -u --recursive --new-file v2.3.0/linux/arch/i386/config.in linux/arch/i386/config.in
--- v2.3.0/linux/arch/i386/config.in	Mon Apr 26 13:49:17 1999
+++ linux/arch/i386/config.in	Thu May 13 14:11:52 1999
@@ -168,7 +168,7 @@
 
 source drivers/char/Config.in
 
-# source drivers/usb/Config.in
+source drivers/usb/Config.in
 
 source fs/Config.in
 
diff -u --recursive --new-file v2.3.0/linux/arch/i386/defconfig linux/arch/i386/defconfig
--- v2.3.0/linux/arch/i386/defconfig	Mon Apr 12 13:12:57 1999
+++ linux/arch/i386/defconfig	Thu May 13 14:14:40 1999
@@ -73,7 +73,9 @@
 #
 # CONFIG_BLK_DEV_HD_IDE is not set
 CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
 CONFIG_BLK_DEV_IDECD=y
+# CONFIG_IDECD_SLOTS is not set
 # CONFIG_BLK_DEV_IDETAPE is not set
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
 # CONFIG_BLK_DEV_IDESCSI is not set
@@ -83,6 +85,7 @@
 CONFIG_BLK_DEV_IDEPCI=y
 CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_BLK_DEV_OFFBOARD is not set
+# CONFIG_BLK_DEV_AEC6210 is not set
 CONFIG_IDEDMA_AUTO=y
 # CONFIG_IDE_CHIPSETS is not set
 
@@ -96,6 +99,7 @@
 # CONFIG_BLK_DEV_XD is not set
 CONFIG_PARIDE_PARPORT=y
 # CONFIG_PARIDE is not set
+CONFIG_BLK_DEV_IDE_MODES=y
 # CONFIG_BLK_DEV_HD is not set
 
 #
@@ -290,6 +294,17 @@
 # Ftape, the floppy tape device driver
 #
 # CONFIG_FTAPE is not set
+
+#
+# USB drivers - not for the faint of heart
+#
+CONFIG_USB=y
+CONFIG_USB_UHCI=y
+# CONFIG_USB_OHCI is not set
+# CONFIG_USB_OHCI_HCD is not set
+CONFIG_USB_MOUSE=y
+CONFIG_USB_KBD=y
+# CONFIG_USB_AUDIO is not set
 
 #
 # Filesystems
diff -u --recursive --new-file v2.3.0/linux/arch/i386/kernel/apm.c linux/arch/i386/kernel/apm.c
--- v2.3.0/linux/arch/i386/kernel/apm.c	Thu Jan 14 22:57:25 1999
+++ linux/arch/i386/kernel/apm.c	Wed May 12 08:31:44 1999
@@ -1017,7 +1017,7 @@
 	struct apm_bios_struct *	as;
 	int			i;
 	apm_event_t		event;
-	struct wait_queue	wait = { current,	NULL };
+        DECLARE_WAITQUEUE(wait, current);
 
 	as = fp->private_data;
 	if (check_apm_bios_struct(as, "read"))
diff -u --recursive --new-file v2.3.0/linux/arch/i386/kernel/init_task.c linux/arch/i386/kernel/init_task.c
--- v2.3.0/linux/arch/i386/kernel/init_task.c	Sun Sep 13 12:16:22 1998
+++ linux/arch/i386/kernel/init_task.c	Tue May 11 14:37:40 1999
@@ -10,7 +10,7 @@
 static struct file * init_fd_array[NR_OPEN] = { NULL, };
 static struct files_struct init_files = INIT_FILES;
 static struct signal_struct init_signals = INIT_SIGNALS;
-struct mm_struct init_mm = INIT_MM;
+struct mm_struct init_mm = INIT_MM(init_mm);
 
 /*
  * Initial task structure.
@@ -20,5 +20,6 @@
  * "init_task" linker map entry..
  */
 union task_union init_task_union 
-	__attribute__((__section__(".data.init_task"))) = { INIT_TASK };
+	__attribute__((__section__(".data.init_task"))) =
+		{ INIT_TASK(init_task_union.task) };
  
diff -u --recursive --new-file v2.3.0/linux/arch/m68k/kernel/ints.c linux/arch/m68k/kernel/ints.c
--- v2.3.0/linux/arch/m68k/kernel/ints.c	Tue May 11 09:57:14 1999
+++ linux/arch/m68k/kernel/ints.c	Wed May 12 08:50:00 1999
@@ -25,6 +25,7 @@
  *           which must be served                               /Roman Zippel
  */
 
+#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/sched.h>
 #include <linux/kernel_stat.h>
diff -u --recursive --new-file v2.3.0/linux/arch/m68k/mm/kmap.c linux/arch/m68k/mm/kmap.c
--- v2.3.0/linux/arch/m68k/mm/kmap.c	Tue May 11 09:57:14 1999
+++ linux/arch/m68k/mm/kmap.c	Wed May 12 08:50:00 1999
@@ -7,6 +7,7 @@
  *	     used by other architectures		/Roman Zippel
  */
 
+#include <linux/config.h>
 #include <linux/mm.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
diff -u --recursive --new-file v2.3.0/linux/arch/m68k/mvme147/config.c linux/arch/m68k/mvme147/config.c
--- v2.3.0/linux/arch/m68k/mvme147/config.c	Tue May 11 09:57:14 1999
+++ linux/arch/m68k/mvme147/config.c	Wed May 12 08:50:00 1999
@@ -13,7 +13,6 @@
  * for more details.
  */
 
-#include <linux/config.h>
 #include <stdarg.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
diff -u --recursive --new-file v2.3.0/linux/arch/m68k/q40/config.c linux/arch/m68k/q40/config.c
--- v2.3.0/linux/arch/m68k/q40/config.c	Tue May 11 09:57:14 1999
+++ linux/arch/m68k/q40/config.c	Wed May 12 08:50:00 1999
@@ -13,6 +13,7 @@
  */
 
 #include <stdarg.h>
+#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
diff -u --recursive --new-file v2.3.0/linux/arch/m68k/sun3x/time.c linux/arch/m68k/sun3x/time.c
--- v2.3.0/linux/arch/m68k/sun3x/time.c	Tue May 11 09:57:14 1999
+++ linux/arch/m68k/sun3x/time.c	Wed May 12 08:50:00 1999
@@ -4,7 +4,6 @@
  *  Sun3x-specific time handling
  */
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/init.h>
 #include <linux/sched.h>
diff -u --recursive --new-file v2.3.0/linux/arch/mips/lib/ide-no.c linux/arch/mips/lib/ide-no.c
--- v2.3.0/linux/arch/mips/lib/ide-no.c	Tue Oct 20 13:52:54 1998
+++ linux/arch/mips/lib/ide-no.c	Thu May 13 11:00:08 1999
@@ -11,6 +11,7 @@
  */
 #include <linux/hdreg.h>
 #include <linux/kernel.h>
+#include <asm/hdreg.h>
 #include <asm/ptrace.h>
 #include <asm/ide.h>
 
@@ -24,8 +25,10 @@
 	return 0;
 }
 
-static void no_ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base,
-                                     int *irq)
+static void no_ide_init_hwif_ports (	hw_regs_t *hw,
+					ide_ioreg_t data_port,
+					ide_ioreg_t ctrl_port,
+					int *irq)
 {
 }
 
diff -u --recursive --new-file v2.3.0/linux/arch/mips/lib/ide-std.c linux/arch/mips/lib/ide-std.c
--- v2.3.0/linux/arch/mips/lib/ide-std.c	Tue Aug  4 16:06:57 1998
+++ linux/arch/mips/lib/ide-std.c	Thu May 13 11:00:08 1999
@@ -11,6 +11,7 @@
  */
 #include <linux/hdreg.h>
 #include <asm/ptrace.h>
+#include <asm/hdreg.h>
 #include <asm/ide.h>
 
 static int std_ide_default_irq(ide_ioreg_t base)
@@ -41,15 +42,23 @@
 	}
 }
 
-static void std_ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base,
-                                     int *irq)
+static void std_ide_init_hwif_ports (	hw_regs_t *hw,
+					ide_ioreg_t data_port,
+					ide_ioreg_t ctrl_port,
+					int *irq)
 {
-	ide_ioreg_t port = base;
-	int i = 8;
+	ide_ioreg_t reg = data_port;
+	int i;
 
-	while (i--)
-		*p++ = port++;
-	*p++ = base + 0x206;
+	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+		hw->io_ports[i] = reg;
+		reg += 1;
+	}
+	if (ctrl_port) {
+		hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
+	} else {
+		hw->io_ports[IDE_CONTROL_OFFSET] = hw->io_ports[IDE_DATA_OFFSET] + 0x206;
+	}
 	if (irq != NULL)
 		*irq = 0;
 }
diff -u --recursive --new-file v2.3.0/linux/arch/ppc/kernel/apus_setup.c linux/arch/ppc/kernel/apus_setup.c
--- v2.3.0/linux/arch/ppc/kernel/apus_setup.c	Thu Apr 29 12:39:01 1999
+++ linux/arch/ppc/kernel/apus_setup.c	Thu May 13 11:00:08 1999
@@ -561,9 +561,9 @@
 }
 
 __initfunc(void
-apus_ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq))
+apus_ide_init_hwif_ports (hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq))
 {
-        m68k_ide_init_hwif_ports(p, base, irq);
+        m68k_ide_init_hwif_ports(hw, data_port, ctrl_port, irq);
 }
 #endif
 
diff -u --recursive --new-file v2.3.0/linux/arch/ppc/kernel/chrp_setup.c linux/arch/ppc/kernel/chrp_setup.c
--- v2.3.0/linux/arch/ppc/kernel/chrp_setup.c	Tue May 11 08:24:32 1999
+++ linux/arch/ppc/kernel/chrp_setup.c	Thu May 13 11:00:08 1999
@@ -37,6 +37,7 @@
 #include <asm/processor.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
+#include <linux/ide.h>
 #include <asm/ide.h>
 #include <asm/prom.h>
 #include <asm/gg2.h>
@@ -561,16 +562,23 @@
         ppc_generic_ide_fix_driveid(id);
 }
 
-void chrp_ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq)
+void
+chrp_ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq)
 {
-        ide_ioreg_t port = base;
-        int i = 8;
+	ide_ioreg_t reg = data_port;
+	int i;
 
-        while (i--)
-                *p++ = port++;
-        *p++ = port;
-        if (irq != NULL)
-                *irq = chrp_ide_irq;
+	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+		hw->io_ports[i] = reg;
+		reg += 1;
+	}
+	if (ctrl_port) {
+		hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
+	} else {
+		hw->io_ports[IDE_CONTROL_OFFSET] = 0;
+	}
+	if (irq != NULL)
+		hw->irq = chrp_ide_irq;
 }
 
 EXPORT_SYMBOL(chrp_ide_irq);
diff -u --recursive --new-file v2.3.0/linux/arch/ppc/kernel/mbx_setup.c linux/arch/ppc/kernel/mbx_setup.c
--- v2.3.0/linux/arch/ppc/kernel/mbx_setup.c	Thu Apr 29 12:39:01 1999
+++ linux/arch/ppc/kernel/mbx_setup.c	Thu May 13 11:00:08 1999
@@ -380,23 +380,35 @@
         ppc_generic_ide_fix_driveid(id);
 }
 
-void __init mbx_ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base, int *irq)
+void
+mbx_ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq)
 {
-	ide_ioreg_t port = base;
-	int i = 8;
+	ide_ioreg_t reg = data_port;
+	int i;
+
+	*irq = 0;
+
+	if (data_port != 0)	/* Only map the first ATA flash drive */
+		return;
 
-	while (i--)
-		*p++ = port++;
-	*p++ = base + 0x206;
-	if (irq != NULL)
-		*irq = 0;
 #ifdef ATA_FLASH
-	base = (unsigned long) ioremap(PCMCIA_MEM_ADDR, 0x200);
-	for (i = 0; i < 8; ++i)
-		*p++ = base++;
-	*p = ++base;		/* Does not matter */
+
+	reg = (ide_ioreg_t) ioremap(PCMCIA_MEM_ADDR, 0x200);
+
+	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+		hw->io_ports[i] = reg;
+		reg += 1;
+	}
+
+	/* Does not matter */
+
+	if (ctrl_port) {
+		hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
+	} else {
+		hw->io_ports[IDE_CONTROL_OFFSET] = reg;
+	}
 	if (irq)
-		*irq = 13;
+		hw->irq = 13;
 #endif
 }
 #endif
diff -u --recursive --new-file v2.3.0/linux/arch/ppc/kernel/pmac_pic.c linux/arch/ppc/kernel/pmac_pic.c
--- v2.3.0/linux/arch/ppc/kernel/pmac_pic.c	Tue May 11 08:24:32 1999
+++ linux/arch/ppc/kernel/pmac_pic.c	Wed May 12 08:50:00 1999
@@ -1,4 +1,4 @@
-
+#include <linux/config.h>
 #include <linux/stddef.h>
 #include <linux/init.h>
 #include <linux/sched.h>
diff -u --recursive --new-file v2.3.0/linux/arch/ppc/kernel/pmac_setup.c linux/arch/ppc/kernel/pmac_setup.c
--- v2.3.0/linux/arch/ppc/kernel/pmac_setup.c	Tue May 11 08:24:32 1999
+++ linux/arch/ppc/kernel/pmac_setup.c	Thu May 13 11:00:08 1999
@@ -365,7 +365,7 @@
 #ifdef CONFIG_BLK_DEV_IDE_PMAC
 extern int pmac_ide_count;
 extern struct device_node *pmac_ide_node[];
-static int ide_majors[] = { 3, 22, 33, 34, 56, 57 };
+static int ide_majors[] = { 3, 22, 33, 34, 56, 57, 88, 89 };
 
 __initfunc(kdev_t find_ide_boot(void))
 {
@@ -544,7 +544,16 @@
 }
 
 /* This is declared in drivers/block/ide-pmac.c */
-void pmac_ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq);
+void pmac_ide_init_hwif_ports (hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq);
+
+/*
+ * This registers the standard ports for this architecture with the IDE
+ * driver.
+ */
+void
+ide_init_default_hwifs(void)
+{
+}
 #endif
 
 __initfunc(void
diff -u --recursive --new-file v2.3.0/linux/arch/ppc/kernel/ppc_ksyms.c linux/arch/ppc/kernel/ppc_ksyms.c
--- v2.3.0/linux/arch/ppc/kernel/ppc_ksyms.c	Thu Apr 29 12:39:01 1999
+++ linux/arch/ppc/kernel/ppc_ksyms.c	Thu May 13 11:00:08 1999
@@ -13,6 +13,7 @@
 #include <asm/processor.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
+#include <linux/ide.h>
 #include <asm/ide.h>
 #include <asm/atomic.h>
 #include <asm/bitops.h>
diff -u --recursive --new-file v2.3.0/linux/arch/ppc/kernel/prep_setup.c linux/arch/ppc/kernel/prep_setup.c
--- v2.3.0/linux/arch/ppc/kernel/prep_setup.c	Tue May 11 08:24:32 1999
+++ linux/arch/ppc/kernel/prep_setup.c	Thu May 13 11:00:08 1999
@@ -39,6 +39,7 @@
 #include <asm/residual.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
+#include <linux/ide.h>
 #include <asm/ide.h>
 #include <asm/cache.h>
 #include <asm/dma.h>
@@ -691,14 +692,20 @@
 }
 
 __initfunc(void
-prep_ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq))
+prep_ide_init_hwif_ports (hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq))
 {
-	ide_ioreg_t port = base;
-	int i = 8;
+	ide_ioreg_t reg = data_port;
+	int i;
 
-	while (i--)
-		*p++ = port++;
-	*p++ = base + 0x206;
+	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+		hw->io_ports[i] = reg;
+		reg += 1;
+	}
+	if (ctrl_port) {
+		hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
+	} else {
+		hw->io_ports[IDE_CONTROL_OFFSET] =  hw->io_ports[IDE_DATA_OFFSET] + 0x206;
+	}
 	if (irq != NULL)
 		*irq = 0;
 }
diff -u --recursive --new-file v2.3.0/linux/arch/ppc/kernel/residual.c linux/arch/ppc/kernel/residual.c
--- v2.3.0/linux/arch/ppc/kernel/residual.c	Sun Nov 15 10:51:44 1998
+++ linux/arch/ppc/kernel/residual.c	Thu May 13 11:00:08 1999
@@ -46,6 +46,7 @@
 #include <asm/processor.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
+#include <linux/ide.h>
 #include <asm/ide.h>
 
 
diff -u --recursive --new-file v2.3.0/linux/arch/ppc/kernel/setup.c linux/arch/ppc/kernel/setup.c
--- v2.3.0/linux/arch/ppc/kernel/setup.c	Thu Apr 29 12:39:01 1999
+++ linux/arch/ppc/kernel/setup.c	Thu May 13 11:00:08 1999
@@ -17,6 +17,7 @@
 #include <asm/pmu.h>
 #include <asm/residual.h>
 #include <asm/io.h>
+#include <linux/ide.h>
 #include <asm/ide.h>
 #include <asm/prom.h>
 #include <asm/processor.h>
@@ -160,10 +161,10 @@
 }
   
 #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
-void ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq)
+void ide_init_hwif_ports (hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq)
 {
 	if (ppc_ide_md.ide_init_hwif != NULL) {
-		ppc_ide_md.ide_init_hwif(p, base, irq);
+		ppc_ide_md.ide_init_hwif(hw, data_port, ctrl_port, irq);
 	}
 }
 #endif
diff -u --recursive --new-file v2.3.0/linux/arch/sparc/ap1000/util.c linux/arch/sparc/ap1000/util.c
--- v2.3.0/linux/arch/sparc/ap1000/util.c	Wed Dec 23 09:44:40 1998
+++ linux/arch/sparc/ap1000/util.c	Wed May 12 08:41:12 1999
@@ -355,7 +355,7 @@
 }
 
 
-static struct wait_queue *timer_wait = NULL;
+static DECLARE_WAIT_QUEUE_HEAD(timer_wait);
 
 static void wait_callback(unsigned long _ignored)
 {
diff -u --recursive --new-file v2.3.0/linux/arch/sparc/kernel/init_task.c linux/arch/sparc/kernel/init_task.c
--- v2.3.0/linux/arch/sparc/kernel/init_task.c	Tue Oct 27 09:52:20 1998
+++ linux/arch/sparc/kernel/init_task.c	Wed May 12 08:41:12 1999
@@ -9,11 +9,13 @@
 static struct file * init_fd_array[NR_OPEN] = { NULL, };
 static struct files_struct init_files = INIT_FILES;
 static struct signal_struct init_signals = INIT_SIGNALS;
-struct mm_struct init_mm = INIT_MM;
+struct mm_struct init_mm = INIT_MM(init_mm);
 
 /* .text section in head.S is aligned at 8k boundry and this gets linked
  * right after that so that the init_task_union is aligned properly as well.
  * If this is not aligned on a 8k boundry, then you should change code
  * in etrap.S which assumes it.
  */
-union task_union init_task_union __attribute__((__section__(".text"))) = { INIT_TASK };
+union task_union init_task_union
+	__attribute__((__section__(".text"))) =
+		{ INIT_TASK(init_task_union.task) };
diff -u --recursive --new-file v2.3.0/linux/arch/sparc/mm/asyncd.c linux/arch/sparc/mm/asyncd.c
--- v2.3.0/linux/arch/sparc/mm/asyncd.c	Sun Oct  4 10:22:42 1998
+++ linux/arch/sparc/mm/asyncd.c	Wed May 12 08:41:12 1999
@@ -1,4 +1,4 @@
-/*  $Id: asyncd.c,v 1.12 1998/09/13 04:30:30 davem Exp $
+/*  $Id: asyncd.c,v 1.13 1999/05/12 11:11:34 davem Exp $
  *  The asyncd kernel daemon. This handles paging on behalf of 
  *  processes that receive page faults due to remote (async) memory
  *  accesses. 
@@ -39,7 +39,7 @@
 /* 
  * The wait queue for waking up the async daemon:
  */
-static struct wait_queue * asyncd_wait = NULL;
+static DECLARE_WAIT_QUEUE_HEAD(asyncd_wait);
 
 struct async_job {
 	volatile struct async_job *next;
diff -u --recursive --new-file v2.3.0/linux/arch/sparc64/kernel/init_task.c linux/arch/sparc64/kernel/init_task.c
--- v2.3.0/linux/arch/sparc64/kernel/init_task.c	Tue Apr 14 17:44:20 1998
+++ linux/arch/sparc64/kernel/init_task.c	Wed May 12 08:41:12 1999
@@ -9,11 +9,13 @@
 static struct file * init_fd_array[NR_OPEN] = { NULL, };
 static struct files_struct init_files = INIT_FILES;
 static struct signal_struct init_signals = INIT_SIGNALS;
-struct mm_struct init_mm = INIT_MM;
+struct mm_struct init_mm = INIT_MM(init_mm);
 
 /* .text section in head.S is aligned at 2 page boundry and this gets linked
  * right after that so that the init_task_union is aligned properly as well.
  * We really don't need this special alignment like the Intel does, but
  * I do it anyways for completeness.
  */
-union task_union init_task_union __attribute__((__section__(".text"))) = { INIT_TASK };
+union task_union init_task_union
+	__attribute__((__section__(".text"))) =
+		{ INIT_TASK(init_task_union.task) };
diff -u --recursive --new-file v2.3.0/linux/arch/sparc64/mm/asyncd.c linux/arch/sparc64/mm/asyncd.c
--- v2.3.0/linux/arch/sparc64/mm/asyncd.c	Sun Oct  4 10:22:43 1998
+++ linux/arch/sparc64/mm/asyncd.c	Wed May 12 08:41:12 1999
@@ -1,4 +1,4 @@
-/*  $Id: asyncd.c,v 1.5 1998/09/13 04:30:33 davem Exp $
+/*  $Id: asyncd.c,v 1.6 1999/05/12 11:11:48 davem Exp $
  *  The asyncd kernel daemon. This handles paging on behalf of 
  *  processes that receive page faults due to remote (async) memory
  *  accesses. 
@@ -39,7 +39,7 @@
 /* 
  * The wait queue for waking up the async daemon:
  */
-static struct wait_queue * asyncd_wait = NULL;
+static DECLARE_WAIT_QUEUE_HEAD(asyncd_wait);
 
 struct async_job {
 	volatile struct async_job *next;
diff -u --recursive --new-file v2.3.0/linux/arch/sparc64/solaris/fs.c linux/arch/sparc64/solaris/fs.c
--- v2.3.0/linux/arch/sparc64/solaris/fs.c	Wed Mar 10 16:53:37 1999
+++ linux/arch/sparc64/solaris/fs.c	Thu May 13 10:53:58 1999
@@ -410,7 +410,11 @@
 	mm_segment_t old_fs = get_fs();
 	int error;
 	struct sol_statvfs *ss = (struct sol_statvfs *)A(buf);
-			
+
+	if (!inode->i_sb)
+		return -ENODEV;
+	if (!inode->i_sb->s_op->statfs)
+		return -ENOSYS;
 	set_fs (KERNEL_DS);
 	error = inode->i_sb->s_op->statfs(inode->i_sb, &s, sizeof(struct statfs));
 	set_fs (old_fs);
@@ -448,6 +452,10 @@
 	int error;
 	struct sol_statvfs64 *ss = (struct sol_statvfs64 *)A(buf);
 			
+	if (!inode->i_sb)
+		return -ENODEV;
+	if (!inode->i_sb->s_op->statfs)
+		return -ENOSYS;
 	set_fs (KERNEL_DS);
 	error = inode->i_sb->s_op->statfs(inode->i_sb, &s, sizeof(struct statfs));
 	set_fs (old_fs);
@@ -489,9 +497,7 @@
 	if (!IS_ERR(dentry)) {
 		struct inode * inode = dentry->d_inode;
 
-		error = -ENOSYS;
-		if (inode->i_sb->s_op->statfs)
-			error = report_statvfs(inode, buf);
+		error = report_statvfs(inode, buf);
 		dput(dentry);
 	}
 	unlock_kernel();
@@ -515,10 +521,6 @@
 		error = -ENOENT;
 	else if (!(inode = dentry->d_inode))
 		error = -ENOENT;
-	else if (!inode->i_sb)
-		error = -ENODEV;
-	else if (!inode->i_sb->s_op->statfs)
-		error = -ENOSYS;
 	else
 		error = report_statvfs(inode, buf);
 	fput(file);
@@ -538,9 +540,7 @@
 	if (!IS_ERR(dentry)) {
 		struct inode * inode = dentry->d_inode;
 
-		error = -ENOSYS;
-		if (inode->i_sb->s_op->statfs)
-			error = report_statvfs64(inode, buf);
+		error = report_statvfs64(inode, buf);
 		dput(dentry);
 	}
 	unlock_kernel();
@@ -564,10 +564,6 @@
 		error = -ENOENT;
 	else if (!(inode = dentry->d_inode))
 		error = -ENOENT;
-	else if (!inode->i_sb)
-		error = -ENODEV;
-	else if (!inode->i_sb->s_op->statfs)
-		error = -ENOSYS;
 	else
 		error = report_statvfs64(inode, buf);
 	fput(file);
diff -u --recursive --new-file v2.3.0/linux/arch/sparc64/solaris/timod.c linux/arch/sparc64/solaris/timod.c
--- v2.3.0/linux/arch/sparc64/solaris/timod.c	Tue Apr 14 17:44:21 1998
+++ linux/arch/sparc64/solaris/timod.c	Wed May 12 08:41:12 1999
@@ -1,4 +1,4 @@
-/* $Id: timod.c,v 1.1 1998/03/26 08:46:18 jj Exp $
+/* $Id: timod.c,v 1.2 1999/05/12 11:11:55 davem Exp $
  * timod.c: timod emulation.
  *
  * Copyright (C) 1998 Patrik Rak (prak3264@ss1000.ms.mff.cuni.cz)
@@ -76,7 +76,7 @@
 
 #define BUF_SIZE	PAGE_SIZE
 #define PUT_MAGIC(a,m)
-#define CHECK_MAGIC(a,m)
+#define SCHECK_MAGIC(a,m)
 #define BUF_OFFSET	0
 #define MKCTL_TRAILER	0
 
@@ -86,7 +86,7 @@
 #define BUFPAGE_MAGIC	0xBADC0DEDDEADBABEL
 #define MKCTL_MAGIC	0xDEADBABEBADC0DEDL
 #define PUT_MAGIC(a,m)	do{(*(u64*)(a))=(m);}while(0)
-#define CHECK_MAGIC(a,m)	do{if((*(u64*)(a))!=(m))printk("%s,%u,%s(): magic %08x at %p corrupted!\n",\
+#define SCHECK_MAGIC(a,m)	do{if((*(u64*)(a))!=(m))printk("%s,%u,%s(): magic %08x at %p corrupted!\n",\
 				__FILE__,__LINE__,__FUNCTION__,(m),(a));}while(0)
 #define BUF_OFFSET	sizeof(u64)
 #define MKCTL_TRAILER	sizeof(u64)
@@ -117,8 +117,8 @@
 {
 	SOLD("putting page");
 	p = p - BUF_OFFSET;
-	CHECK_MAGIC(p,BUFPAGE_MAGIC);
-	CHECK_MAGIC(p+PAGE_SIZE-sizeof(u64),BUFPAGE_MAGIC);
+	SCHECK_MAGIC(p,BUFPAGE_MAGIC);
+	SCHECK_MAGIC(p+PAGE_SIZE-sizeof(u64),BUFPAGE_MAGIC);
 	spin_lock(&timod_pagelock);
 	if (page) {
 		spin_unlock(&timod_pagelock);
@@ -721,7 +721,7 @@
 #define min(a,b) ((a)<(b)?(a):(b))
 #endif
 		int l = min(ctl_maxlen, it->length);
-		CHECK_MAGIC((char*)((u64)(((char *)&it->type)+sock->offset+it->length+7)&~7),MKCTL_MAGIC);
+		SCHECK_MAGIC((char*)((u64)(((char *)&it->type)+sock->offset+it->length+7)&~7),MKCTL_MAGIC);
 		SOLD("purting ctl data");
 		if(copy_to_user(ctl_buf,
 			(char*)&it->type + sock->offset, l))
diff -u --recursive --new-file v2.3.0/linux/drivers/block/Config.in linux/drivers/block/Config.in
--- v2.3.0/linux/drivers/block/Config.in	Thu Apr 29 12:53:48 1999
+++ linux/drivers/block/Config.in	Thu May 13 11:00:08 1999
@@ -19,7 +19,13 @@
 else
   bool '   Use old disk-only driver on primary interface' CONFIG_BLK_DEV_HD_IDE
   dep_tristate '   Include IDE/ATA-2 DISK support' CONFIG_BLK_DEV_IDEDISK $CONFIG_BLK_DEV_IDE
+  if [ "$CONFIG_BLK_DEV_IDEDISK" != "n" ]; then
+    bool '     Use multi-mode by default' CONFIG_IDEDISK_MULTI_MODE
+  fi
   dep_tristate '   Include IDE/ATAPI CDROM support' CONFIG_BLK_DEV_IDECD $CONFIG_BLK_DEV_IDE
+  if [ "$CONFIG_BLK_DEV_IDECD" = "y" ]; then
+    bool '     Include CD-Changer Reporting' CONFIG_IDECD_SLOTS
+  fi
   dep_tristate '   Include IDE/ATAPI TAPE support' CONFIG_BLK_DEV_IDETAPE $CONFIG_BLK_DEV_IDE
   dep_tristate '   Include IDE/ATAPI FLOPPY support' CONFIG_BLK_DEV_IDEFLOPPY $CONFIG_BLK_DEV_IDE
   dep_tristate '   SCSI emulation support' CONFIG_BLK_DEV_IDESCSI $CONFIG_BLK_DEV_IDE
@@ -34,16 +40,29 @@
       if [ "$CONFIG_BLK_DEV_IDEPCI" = "y" ]; then
         bool '     Generic PCI bus-master DMA support' CONFIG_BLK_DEV_IDEDMA
         bool '     Boot off-board chipsets first support' CONFIG_BLK_DEV_OFFBOARD
+        bool '     AEC6210 chipset support' CONFIG_BLK_DEV_AEC6210
         if [ "$CONFIG_BLK_DEV_IDEDMA" = "y" ]; then
           bool '     Use DMA by default when available' CONFIG_IDEDMA_AUTO
         fi
         if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
           bool '     OPTi 82C621 chipset enhanced support (EXPERIMENTAL)' CONFIG_BLK_DEV_OPTI621
+          bool '     Intel PIIXn chipsets support (EXPERIMENTAL)' CONFIG_BLK_DEV_PIIX
           if [ "$CONFIG_BLK_DEV_IDEDMA" = "y" ]; then
             bool '     Tekram TRM290 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_TRM290
             bool '     NS87415 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_NS87415
             bool '     VIA82C586 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_VIA82C586
             bool '     CMD646 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_CMD646
+            bool '     ALI M15x3 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_ALI15X3
+            bool '     CY82C693 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_CY82C693
+            bool '     PDC20246 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_PDC20246
+            bool '     PDC20262 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_PDC20262
+            if [ "$CONFIG_BLK_DEV_PDC20246" = "y" -o \
+                 "$CONFIG_BLK_DEV_PDC20262" = "y" ]; then
+              define_bool CONFIG_BLK_DEV_PDC202XX y
+            else
+              define_bool CONFIG_BLK_DEV_PDC202XX n
+            fi
+            bool '     HPT343 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_HPT343
           fi
         fi
       fi
@@ -72,10 +91,25 @@
       bool '     UMC-8672 support' CONFIG_BLK_DEV_UMC8672
       if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
         if [ "$CONFIG_BLK_DEV_IDEDISK" = "y" ]; then
-        bool '     PROMISE DC4030 support (EXPERIMENTAL)' CONFIG_BLK_DEV_PDC4030
-	 fi
+          bool '     PROMISE DC4030 support (EXPERIMENTAL)' CONFIG_BLK_DEV_PDC4030
+        fi
       fi
     fi
+    if [ "$CONFIG_AMIGA" = "y" ]; then
+      bool '   Amiga Gayle IDE interface support' CONFIG_BLK_DEV_GAYLE
+      if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+        bool '   Amiga IDE Doubler support' CONFIG_BLK_DEV_IDEDOUBLER $CONFIG_BLK_DEV_GAYLE
+      fi
+    fi
+    if [ "$CONFIG_ZORRO" = "y" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then
+        bool '   Buddha/Catweasel IDE interface support' CONFIG_BLK_DEV_BUDDHA
+    fi
+    if [ "$CONFIG_ATARI" = "y" ]; then
+      bool '   Falcon IDE interface support' CONFIG_BLK_DEV_FALCON_IDE
+    fi
+    if [ "$CONFIG_MAC" = "y" ]; then
+      bool '   Macintosh Quadra/Powerbook IDE interface support' CONFIG_BLK_DEV_MAC_IDE
+    fi
   fi
 fi
 if [ "$CONFIG_MCA" = "y" ]; then
@@ -127,6 +161,19 @@
 dep_tristate 'Parallel port IDE device support' CONFIG_PARIDE $CONFIG_PARIDE_PARPORT
 if [ "$CONFIG_PARIDE" = "y" -o "$CONFIG_PARIDE" = "m" ]; then
   source drivers/block/paride/Config.in
+fi
+
+
+if [ "$CONFIG_BLK_DEV_CMD640" = "y" -o \
+     "$CONFIG_IDE_CHIPSETS" = "y" -o \
+     "$CONFIG_BLK_DEV_OPTI621" = "y" -o \
+     "$CONFIG_BLK_DEV_IDE_PMAC" = "y" -o \
+     "$CONFIG_BLK_DEV_CY82C693" = "y" -o \
+     "$CONFIG_BLK_DEV_HPT343" = "y" -o \
+     "$CONFIG_BLK_DEV_PIIX" = "y" ]; then
+  define_bool CONFIG_BLK_DEV_IDE_MODES y
+else
+  define_bool CONFIG_BLK_DEV_IDE_MODES n
 fi
 
 if [ "$CONFIG_BLK_DEV_HD_IDE" = "y" -o "$CONFIG_BLK_DEV_HD_ONLY" = "y" ]; then
diff -u --recursive --new-file v2.3.0/linux/drivers/block/MAKEDEV-IDE45 linux/drivers/block/MAKEDEV-IDE45
--- v2.3.0/linux/drivers/block/MAKEDEV-IDE45	Wed Dec 31 16:00:00 1969
+++ linux/drivers/block/MAKEDEV-IDE45	Thu May 13 11:00:08 1999
@@ -0,0 +1,99 @@
+#!/bin/sh
+#
+#	Andre Hedrick <hedrick@astro.dyer.vanderbilt.edu>
+#
+#	The song goes, "I did it the hard way..........."
+#
+
+if [ ! -f /dev/hdi ]; then \
+	echo "Making IDE4 Primary Devices hdi's"; \
+	mknod /dev/hdi b 56 0; \
+	mknod /dev/hdi1 b 56 1; \
+	mknod /dev/hdi2 b 56 2; \
+	mknod /dev/hdi3 b 56 3; \
+	mknod /dev/hdi4 b 56 4; \
+	mknod /dev/hdi5 b 56 5; \
+	mknod /dev/hdi6 b 56 6; \
+	mknod /dev/hdi7 b 56 7; \
+	mknod /dev/hdi8 b 56 8; \
+	mknod /dev/hdi9 b 56 9; \
+	mknod /dev/hdi10 b 56 10; \
+	mknod /dev/hdi11 b 56 11; \
+	mknod /dev/hdi12 b 56 12; \
+	mknod /dev/hdi13 b 56 13; \
+	mknod /dev/hdi14 b 56 14; \
+	mknod /dev/hdi15 b 56 15; \
+	mknod /dev/hdi16 b 56 16; \
+	chown root.disk /dev/hdi*; \
+	chmod 660 /dev/hdi*; \
+fi
+
+if [ ! -f /dev/hdj ]; then \
+	echo "Making IDE4 Secondary Devices hdj's"; \
+	mknod /dev/hdj b 56 64; \
+	mknod /dev/hdj1 b 56 65; \
+	mknod /dev/hdj2 b 56 66; \
+	mknod /dev/hdj3 b 56 67; \
+	mknod /dev/hdj4 b 56 68; \
+	mknod /dev/hdj5 b 56 69; \
+	mknod /dev/hdj6 b 56 70; \
+	mknod /dev/hdj7 b 56 71; \
+	mknod /dev/hdj8 b 56 72; \
+	mknod /dev/hdj9 b 56 73; \
+	mknod /dev/hdj10 b 56 74; \
+	mknod /dev/hdj11 b 56 75; \
+	mknod /dev/hdj12 b 56 76; \
+	mknod /dev/hdj13 b 56 77; \
+	mknod /dev/hdj14 b 56 78; \
+	mknod /dev/hdj15 b 56 79; \
+	mknod /dev/hdj16 b 56 80; \
+	chown root.disk /dev/hdj*; \
+	chmod 660 /dev/hdj*; \
+fi
+
+if [ ! -f /dev/hdk ]; then \
+	echo "Making IDE5 Primary Devices hdk's"; \
+	mknod /dev/hdk b 57 0; \
+	mknod /dev/hdk1 b 57 1; \
+	mknod /dev/hdk2 b 57 2; \
+	mknod /dev/hdk3 b 57 3; \
+	mknod /dev/hdk4 b 57 4; \
+	mknod /dev/hdk5 b 57 5; \
+	mknod /dev/hdk6 b 57 6; \
+	mknod /dev/hdk7 b 57 7; \
+	mknod /dev/hdk8 b 57 8; \
+	mknod /dev/hdk9 b 57 9; \
+	mknod /dev/hdk10 b 57 10; \
+	mknod /dev/hdk11 b 57 11; \
+	mknod /dev/hdk12 b 57 12; \
+	mknod /dev/hdk13 b 57 13; \
+	mknod /dev/hdk14 b 57 14; \
+	mknod /dev/hdk15 b 57 15; \
+	mknod /dev/hdk16 b 57 16; \
+	chown root.disk /dev/hdk*; \
+	chmod 660 /dev/hdk*; \
+fi
+
+if [ ! -f /dev/hdl ]; then \
+	echo "Making IDE5 Secondary Devices hdl's"; \
+	mknod /dev/hdl b 57 64; \
+	mknod /dev/hdl1 b 57 65; \
+	mknod /dev/hdl2 b 57 66; \
+	mknod /dev/hdl3 b 57 67; \
+	mknod /dev/hdl4 b 57 68; \
+	mknod /dev/hdl5 b 57 69; \
+	mknod /dev/hdl6 b 57 70; \
+	mknod /dev/hdl7 b 57 71; \
+	mknod /dev/hdl8 b 57 72; \
+	mknod /dev/hdl9 b 57 73; \
+	mknod /dev/hdl10 b 57 74; \
+	mknod /dev/hdl11 b 57 75; \
+	mknod /dev/hdl12 b 57 76; \
+	mknod /dev/hdl13 b 57 77; \
+	mknod /dev/hdl14 b 57 78; \
+	mknod /dev/hdl15 b 57 79; \
+	mknod /dev/hdl16 b 57 80; \
+	chown root.disk /dev/hdl*; \
+	chmod 660 /dev/hdl*; \
+fi
+
diff -u --recursive --new-file v2.3.0/linux/drivers/block/MAKEDEV-IDE67 linux/drivers/block/MAKEDEV-IDE67
--- v2.3.0/linux/drivers/block/MAKEDEV-IDE67	Wed Dec 31 16:00:00 1969
+++ linux/drivers/block/MAKEDEV-IDE67	Thu May 13 11:00:08 1999
@@ -0,0 +1,99 @@
+#!/bin/sh
+#
+#	Andre Hedrick <hedrick@astro.dyer.vanderbilt.edu>
+#
+#	The song goes, "I did it the hard way..........."
+#
+
+if [ ! -f /dev/hdm ]; then \
+	echo "Making IDE6 Primary Devices hdm's"; \
+	mknod /dev/hdm b 88 0; \
+	mknod /dev/hdm1 b 88 1; \
+	mknod /dev/hdm2 b 88 2; \
+	mknod /dev/hdm3 b 88 3; \
+	mknod /dev/hdm4 b 88 4; \
+	mknod /dev/hdm5 b 88 5; \
+	mknod /dev/hdm6 b 88 6; \
+	mknod /dev/hdm7 b 88 7; \
+	mknod /dev/hdm8 b 88 8; \
+	mknod /dev/hdm9 b 88 9; \
+	mknod /dev/hdm10 b 88 10; \
+	mknod /dev/hdm11 b 88 11; \
+	mknod /dev/hdm12 b 88 12; \
+	mknod /dev/hdm13 b 88 13; \
+	mknod /dev/hdm14 b 88 14; \
+	mknod /dev/hdm15 b 88 15; \
+	mknod /dev/hdm16 b 88 16; \
+	chown root.disk /dev/hdm*; \
+	chmod 660 /dev/hdm*; \
+fi
+
+if [ ! -f /dev/hdn ]; then \
+	echo "Making IDE6 Secondary Devices hdn's"; \
+	mknod /dev/hdn b 88 64; \
+	mknod /dev/hdn1 b 88 65; \
+	mknod /dev/hdn2 b 88 66; \
+	mknod /dev/hdn3 b 88 67; \
+	mknod /dev/hdn4 b 88 68; \
+	mknod /dev/hdn5 b 88 69; \
+	mknod /dev/hdn6 b 88 70; \
+	mknod /dev/hdn7 b 88 71; \
+	mknod /dev/hdn8 b 88 72; \
+	mknod /dev/hdn9 b 88 73; \
+	mknod /dev/hdn10 b 88 74; \
+	mknod /dev/hdn11 b 88 75; \
+	mknod /dev/hdn12 b 88 76; \
+	mknod /dev/hdn13 b 88 77; \
+	mknod /dev/hdn14 b 88 78; \
+	mknod /dev/hdn15 b 88 79; \
+	mknod /dev/hdn16 b 88 80; \
+	chown root.disk /dev/hdn*; \
+	chmod 660 /dev/hdn*; \
+fi
+
+if [ ! -f /dev/hdo ]; then \
+	echo "Making IDE7 Primary Devices hdo's"; \
+	mknod /dev/hdo b 89 0; \
+	mknod /dev/hdo1 b 89 1; \
+	mknod /dev/hdo2 b 89 2; \
+	mknod /dev/hdo3 b 89 3; \
+	mknod /dev/hdo4 b 89 4; \
+	mknod /dev/hdo5 b 89 5; \
+	mknod /dev/hdo6 b 89 6; \
+	mknod /dev/hdo7 b 89 7; \
+	mknod /dev/hdo8 b 89 8; \
+	mknod /dev/hdo9 b 89 9; \
+	mknod /dev/hdo10 b 89 10; \
+	mknod /dev/hdo11 b 89 11; \
+	mknod /dev/hdo12 b 89 12; \
+	mknod /dev/hdo13 b 89 13; \
+	mknod /dev/hdo14 b 89 14; \
+	mknod /dev/hdo15 b 89 15; \
+	mknod /dev/hdo16 b 89 16; \
+	chown root.disk /dev/hdo*; \
+	chmod 660 /dev/hdo*; \
+fi
+
+if [ ! -f /dev/hdp ]; then \
+	echo "Making IDE7 Secondary Devices hdp's"; \
+	mknod /dev/hdp b 89 64; \
+	mknod /dev/hdp1 b 89 65; \
+	mknod /dev/hdp2 b 89 66; \
+	mknod /dev/hdp3 b 89 67; \
+	mknod /dev/hdp4 b 89 68; \
+	mknod /dev/hdp5 b 89 69; \
+	mknod /dev/hdp6 b 89 70; \
+	mknod /dev/hdp7 b 89 71; \
+	mknod /dev/hdp8 b 89 72; \
+	mknod /dev/hdp9 b 89 73; \
+	mknod /dev/hdp10 b 89 74; \
+	mknod /dev/hdp11 b 89 75; \
+	mknod /dev/hdp12 b 89 76; \
+	mknod /dev/hdp13 b 89 77; \
+	mknod /dev/hdp14 b 89 78; \
+	mknod /dev/hdp15 b 89 79; \
+	mknod /dev/hdp16 b 89 80; \
+	chown root.disk /dev/hdp*; \
+	chmod 660 /dev/hdp*; \
+fi
+
diff -u --recursive --new-file v2.3.0/linux/drivers/block/Makefile linux/drivers/block/Makefile
--- v2.3.0/linux/drivers/block/Makefile	Mon Apr 12 16:18:27 1999
+++ linux/drivers/block/Makefile	Thu May 13 11:00:08 1999
@@ -158,12 +158,52 @@
 IDE_OBJS += via82c586.o
 endif
 
+ifeq ($(CONFIG_BLK_DEV_GAYLE),y)
+IDE_OBJS += gayle.o
+endif
+
+ifeq ($(CONFIG_BLK_DEV_FALCON_IDE),y)
+IDE_OBJS += falconide.o
+endif
+
+ifeq ($(CONFIG_BLK_DEV_MAC_IDE),y)
+IDE_OBJS += macide.o
+endif
+
+ifeq ($(CONFIG_BLK_DEV_BUDDHA),y)
+IDE_OBJS += buddha.o
+endif
+
 ifeq ($(CONFIG_BLK_DEV_CMD646),y)
 IDE_OBJS += cmd646.o
 endif
 
 ifeq ($(CONFIG_BLK_DEV_SL82C105),y)
 IDE_OBJS += sl82c105.o
+endif
+
+ifeq ($(CONFIG_BLK_DEV_ALI15X3),y)
+IDE_OBJS += alim15x3.o
+endif
+
+ifeq ($(CONFIG_BLK_DEV_CY82C693),y)
+IDE_OBJS += cy82c693.o
+endif
+
+ifeq ($(CONFIG_BLK_DEV_PIIX),y)
+IDE_OBJS += piix.o
+endif
+
+ifeq ($(CONFIG_BLK_DEV_PDC202XX),y)
+IDE_OBJS += pdc202xx.o
+endif
+
+ifeq ($(CONFIG_BLK_DEV_AEC6210),y)
+IDE_OBJS += aec6210.o
+endif
+
+ifeq ($(CONFIG_BLK_DEV_HPT343),y)
+IDE_OBJS += hpt343.o
 endif
 
 ### if CONFIG_BLK_DEV_IDE is n, IDE_OBJS will be ignored
diff -u --recursive --new-file v2.3.0/linux/drivers/block/acsi.c linux/drivers/block/acsi.c
--- v2.3.0/linux/drivers/block/acsi.c	Tue Dec 29 11:23:59 1998
+++ linux/drivers/block/acsi.c	Tue May 11 23:32:31 1999
@@ -245,7 +245,7 @@
 static struct hd_struct	acsi_part[MAX_DEV<<4] = { {0,0}, };
 static int 				access_count[MAX_DEV] = { 0, };
 static char 			busy[MAX_DEV] = { 0, };
-static struct wait_queue *busy_wait;
+static DECLARE_WAIT_QUEUE_HEAD(busy_wait);
 
 static int				CurrentNReq;
 static int				CurrentNSect;
diff -u --recursive --new-file v2.3.0/linux/drivers/block/acsi_slm.c linux/drivers/block/acsi_slm.c
--- v2.3.0/linux/drivers/block/acsi_slm.c	Tue Dec 29 11:23:59 1998
+++ linux/drivers/block/acsi_slm.c	Tue May 11 23:33:00 1999
@@ -143,8 +143,8 @@
 static int				SLMError;
 
 /* wait queues */
-static struct wait_queue *slm_wait;		/* waiting for buffer */
-static struct wait_queue *print_wait;	/* waiting for printing finished */
+static DECLARE_WAIT_QUEUE_HEAD(slm_wait);	/* waiting for buffer */
+static DECLARE_WAIT_QUEUE_HEAD(print_wait);	/* waiting for printing finished */
 
 /* status codes */
 #define	SLMSTAT_OK		0x00
diff -u --recursive --new-file v2.3.0/linux/drivers/block/aec6210.c linux/drivers/block/aec6210.c
--- v2.3.0/linux/drivers/block/aec6210.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/block/aec6210.c	Thu May 13 11:04:54 1999
@@ -0,0 +1,64 @@
+/*
+ * linux/drivers/block/aec6210.c	Version 0.01	Nov 17, 1998
+ *
+ * Copyright (C) 1998	Andre Hedrick (hedrick@astro.dyer.vanderbilt.edu)
+ *
+ *  pio 0 ::       40: 00 07 00 00 00 00 00 00 02 07 a6 04 00 02 00 02
+ *  pio 1 ::       40: 0a 07 00 00 00 00 00 00 02 07 a6 05 00 02 00 02
+ *  pio 2 ::       40: 08 07 00 00 00 00 00 00 02 07 a6 05 00 02 00 02
+ *  pio 3 ::       40: 03 04 00 00 00 00 00 00 02 05 a6 05 00 02 00 02
+ *  pio 4 ::       40: 01 04 00 00 00 00 00 00 02 05 a6 05 00 02 00 02
+ *  dma 0 ::       40: 0a 07 00 00 00 00 00 00 02 05 a6 05 00 02 00 02
+ *  dma 1 ::       40: 02 04 00 00 00 00 00 00 02 05 a6 05 00 02 00 02
+ *  dma 2 ::       40: 01 04 00 00 00 00 00 00 02 05 a6 05 00 02 00 02
+ *                 50: ff ff ff ff 00 06 04 00 00 00 00 00 00 00 00 00
+ *
+ * udma 0 ::       40: 01 04 00 00 00 00 00 00 02 05 a6 05 00 02 00 02
+ *                 50: ff ff ff ff 01 06 04 00 00 00 00 00 00 00 00 00
+ *
+ * udma 1 ::       40: 01 04 00 00 00 00 00 00 02 05 a6 05 00 02 00 02
+ *                 50: ff ff ff ff 01 06 04 00 00 00 00 00 00 00 00 00
+ *
+ * udma 2 ::       40: 01 04 00 00 00 00 00 00 02 05 a6 05 00 02 00 02
+ *                 50: ff ff ff ff 02 06 04 00 00 00 00 00 00 00 00 00
+ *
+ * auto   ::       40: 01 04 00 00 00 00 00 00 02 05 a6 05 00 02 00 02
+ *                 50: ff ff ff ff 02 06 04 00 00 00 00 00 00 00 00 00
+ *
+ * auto   ::       40: 01 04 01 04 01 04 01 04 02 05 a6 cf 00 02 00 02
+ *                 50: ff ff ff ff aa 06 04 00 00 00 00 00 00 00 00 00
+ *
+ *                 NO-Devices
+ *                 40: 00 00 00 00 00 00 00 00 02 05 a6 00 00 02 00 02
+ *                 50: ff ff ff ff 00 06 00 00 00 00 00 00 00 00 00 00
+
+ */
+
+#include <linux/config.h>	/* for CONFIG_BLK_DEV_IDEPCI */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/ioport.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/ide.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+
+__initfunc(unsigned int pci_init_aec6210 (struct pci_dev *dev, const char *name))
+{
+	if (dev->rom_address) {
+		pci_write_config_dword(dev, PCI_ROM_ADDRESS,
+			dev->rom_address | PCI_ROM_ADDRESS_ENABLE);
+		printk("%s: ROM enabled at 0x%08lx\n",
+			name, dev->rom_address);
+	}
+	return dev->irq;
+}
diff -u --recursive --new-file v2.3.0/linux/drivers/block/ali14xx.c linux/drivers/block/ali14xx.c
--- v2.3.0/linux/drivers/block/ali14xx.c	Wed May  6 14:42:53 1998
+++ linux/drivers/block/ali14xx.c	Thu May 13 11:04:54 1999
@@ -47,8 +47,10 @@
 #include <linux/ioport.h>
 #include <linux/blkdev.h>
 #include <linux/hdreg.h>
+#include <linux/ide.h>
+
 #include <asm/io.h>
-#include "ide.h"
+
 #include "ide_modes.h"
 
 /* port addresses for auto-detection */
diff -u --recursive --new-file v2.3.0/linux/drivers/block/alim15x3.c linux/drivers/block/alim15x3.c
--- v2.3.0/linux/drivers/block/alim15x3.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/block/alim15x3.c	Thu May 13 11:04:54 1999
@@ -0,0 +1,347 @@
+/*
+ * linux/drivers/block/alim15x3.c	Version 0.04	Feb. 8, 1999
+ *
+ *  Copyright (C) 1998-99 Michel Aubry, Maintainer
+ *  Copyright (C) 1998-99 Andrzej Krzysztofowicz, Maintainer
+ *  Copyright (C) 1998-99 Andre Hedrick, Integrater and Maintainer
+ *
+ *  (U)DMA capable version of ali 1533/1543(C)
+ *
+ *  Default disable (U)DMA on all devices execpt hard disks.
+ *  This measure of overkill is needed to stablize the chipset code.
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
+
+#include <asm/io.h>
+
+#define DISPLAY_ALI_TIMINGS
+
+#if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS)
+#include <linux/stat.h>
+#include <linux/proc_fs.h>
+
+static int ali_get_info(char *buffer, char **addr, off_t offset, int count, int dummy);
+extern int (*ali_display_info)(char *, char **, off_t, int, int);  /* ide-proc.c */
+struct pci_dev *bmide_dev;
+
+char *fifo[4] = {
+	"FIFO Off",
+	"FIFO On ",
+	"DMA mode",
+	"PIO mode" };
+
+char *udmaT[8] = {
+	"1.5T",
+	"  2T",
+	"2.5T",
+	"  3T",
+	"3.5T",
+	"  4T",
+	"  6T",
+	"  8T"
+};
+
+char *channel_status[8] = {
+	"OK            ",
+	"busy          ",
+	"DRQ           ",
+	"DRQ busy      ",
+	"error         ",
+	"error busy    ",
+	"error DRQ     ",
+	"error DRQ busy"
+};
+#endif  /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) */
+
+__initfunc(unsigned int pci_init_ali15x3 (struct pci_dev *dev, const char *name))
+{
+	byte confreg0 = 0, confreg1 =0, progif = 0;
+	int errors = 0;
+
+	if (pci_read_config_byte(dev, 0x50, &confreg1))
+		goto veryspecialsettingserror;
+	if (!(confreg1 & 0x02))
+		if (pci_write_config_byte(dev, 0x50, confreg1 | 0x02))
+			goto veryspecialsettingserror;
+
+	if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif))
+		goto veryspecialsettingserror;
+	if (!(progif & 0x40)) {
+		/*
+		 * The way to enable them is to set progif
+		 * writable at 0x4Dh register, and set bit 6
+		 * of progif to 1:
+		 */
+		if (pci_read_config_byte(dev, 0x4d, &confreg0))
+			goto veryspecialsettingserror;
+		if (confreg0 & 0x80)
+			if (pci_write_config_byte(dev, 0x4d, confreg0 & ~0x80))
+				goto veryspecialsettingserror;
+		if (pci_write_config_byte(dev, PCI_CLASS_PROG, progif | 0x40))
+			goto veryspecialsettingserror;
+		if (confreg0 & 0x80)
+			if (pci_write_config_byte(dev, 0x4d, confreg0))
+				errors++;
+	}
+
+	if ((pci_read_config_byte(dev, PCI_CLASS_PROG, &progif)) || (!(progif & 0x40)))
+		goto veryspecialsettingserror;
+
+	printk("%s: enabled read of IDE channels state (en/dis-abled) %s.\n",
+		name, errors ? "with Error(s)" : "Succeeded" );
+	return 0;
+
+veryspecialsettingserror:
+	printk("%s: impossible to enable read of IDE channels state (en/dis-abled)!\n", name);
+	return 0;
+}
+
+int ali15x3_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
+{
+	switch (func) {
+		case ide_dma_check:
+			if (drive->media == ide_cdrom) {
+				ide_hwif_t *hwif	= HWIF(drive);
+				struct pci_dev *dev	= hwif->pci_dev;
+				struct hd_driveid *id	= drive->id;
+				byte cd_dma_fifo	= 0;
+
+				pci_read_config_byte(dev, 0x53, &cd_dma_fifo);
+
+				if (((id->field_valid & 4) || (id->field_valid & 2)) &&
+				    (id->capability & 1) && hwif->autodma) {
+					unsigned long dma_set_bit  = hwif->dma_base + 2;
+#if 0
+					if (cd_dma_fifo & 0x02)
+						pci_write_config_byte(dev, 0x53, cd_dma_fifo & ~0x02);
+					pci_write_config_byte(dev, 0x53, cd_dma_fifo|0x01);
+#else
+					pci_write_config_byte(dev, 0x53, cd_dma_fifo|0x01|0x02);
+#endif
+					if (drive->select.b.unit & 0x01) {
+						outb(inb(dma_set_bit)|0x40, dma_set_bit);
+					} else {
+						outb(inb(dma_set_bit)|0x20, dma_set_bit);
+					}
+				} else {
+					if (cd_dma_fifo & 0x01)
+						pci_write_config_byte(dev, 0x53, cd_dma_fifo & ~0x01);
+					pci_write_config_byte(dev, 0x53, cd_dma_fifo|0x02);
+				}
+			} else if (drive->media != ide_disk) {
+				return ide_dmaproc(ide_dma_off_quietly, drive);
+			}
+		default:
+			break;
+	}
+	return ide_dmaproc(func, drive);	/* use standard DMA stuff */
+}
+
+__initfunc(void ide_init_ali15x3 (ide_hwif_t *hwif))
+{
+	struct pci_dev *dev;
+	byte ideic, inmir;
+	byte irq_routing_table[] = { -1,  9, 3, 10, 4,  5, 7,  6,
+				      1, 11, 0, 12, 0, 14, 0, 15 };
+	hwif->irq = hwif->channel ? 15 : 14;
+	for (dev = pci_devices; dev; dev=dev->next) /* look for ISA bridge */
+		if (dev->vendor==PCI_VENDOR_ID_AL &&
+		   dev->device==PCI_DEVICE_ID_AL_M1533)
+			break;
+	if (dev) {			
+		pci_read_config_byte(dev, 0x58, &ideic);
+		ideic = ideic & 0x03;
+		if ((hwif->channel && ideic == 0x03) ||
+		   (!hwif->channel && !ideic)) {
+			pci_read_config_byte(dev, 0x44, &inmir);
+			inmir = inmir & 0x0f;
+			hwif->irq = irq_routing_table[inmir];
+		} else
+			if (hwif->channel && !(ideic & 0x01)) {
+				pci_read_config_byte(dev, 0x75, &inmir);
+				inmir = inmir & 0x0f;
+				hwif->irq = irq_routing_table[inmir];
+			}
+	}
+#if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS)
+	bmide_dev = hwif->pci_dev;
+	ali_display_info = &ali_get_info;
+#endif  /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) */
+
+	if (hwif->dma_base)
+		hwif->dmaproc = &ali15x3_dmaproc;
+	return;
+}
+
+#if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS)
+static int ali_get_info(char *buffer, char **addr, off_t offset, int count, int dummy)
+{
+	byte reg53h, reg5xh, reg5yh, reg5xh1, reg5yh1;
+	unsigned int bibma;
+	byte c0, c1;
+	byte rev, tmp;
+	char *p = buffer;
+	char *q;
+
+	/* fetch rev. */
+	pci_read_config_byte(bmide_dev, 0x08, &rev);
+	if (rev >= 0xc1)	/* M1543C or newer */
+		udmaT[7] = " ???";
+	else
+		fifo[3]  = "   ???  ";
+
+	/* first fetch bibma: */
+	pci_read_config_dword(bmide_dev, 0x20, &bibma);
+	bibma = (bibma & 0xfff0) ;
+	/*
+	 * at that point bibma+0x2 et bibma+0xa are byte
+	 * registers to investigate:
+	 */
+	c0 = inb((unsigned short)bibma + 0x02);
+	c1 = inb((unsigned short)bibma + 0x0a);
+
+	p += sprintf(p,
+		"\n                                Ali M15x3 Chipset.\n");
+	p += sprintf(p,
+		"                                ------------------\n");
+	pci_read_config_byte(bmide_dev, 0x78, &reg53h);
+	p += sprintf(p, "PCI Clock: %d.\n", reg53h);
+
+	pci_read_config_byte(bmide_dev, 0x53, &reg53h);
+	p += sprintf(p,
+		"CD_ROM FIFO:%s, CD_ROM DMA:%s\n",
+		(reg53h & 0x02) ? "Yes" : "No ",
+		(reg53h & 0x01) ? "Yes" : "No " );
+	pci_read_config_byte(bmide_dev, 0x74, &reg53h);
+	p += sprintf(p,
+		"FIFO Status: contains %d Words, runs%s%s\n\n",
+		(reg53h & 0x3f),
+		(reg53h & 0x40) ? " OVERWR" : "",
+		(reg53h & 0x80) ? " OVERRD." : "." );
+
+	p += sprintf(p,
+		"-------------------primary channel-------------------secondary channel---------\n\n");
+
+	pci_read_config_byte(bmide_dev, 0x09, &reg53h);
+	p += sprintf(p,
+		"channel status:       %s                               %s\n",
+		(reg53h & 0x20) ? "On " : "Off",
+		(reg53h & 0x10) ? "On " : "Off" );
+
+	p += sprintf(p,
+		"both channels togth:  %s                               %s\n",
+		(c0&0x80) ? "No " : "Yes",
+		(c1&0x80) ? "No " : "Yes" );
+
+	pci_read_config_byte(bmide_dev, 0x76, &reg53h);
+	p += sprintf(p,
+		"Channel state:        %s                    %s\n",
+		channel_status[reg53h & 0x07],
+		channel_status[(reg53h & 0x70) >> 4] );
+
+	pci_read_config_byte(bmide_dev, 0x58, &reg5xh);
+	pci_read_config_byte(bmide_dev, 0x5c, &reg5yh);
+	p += sprintf(p,
+		"Add. Setup Timing:    %dT                                %dT\n",
+		(reg5xh & 0x07) ? (reg5xh & 0x07) : 8,
+		(reg5yh & 0x07) ? (reg5yh & 0x07) : 8 );
+
+	pci_read_config_byte(bmide_dev, 0x59, &reg5xh);
+	pci_read_config_byte(bmide_dev, 0x5d, &reg5yh);
+	p += sprintf(p,
+		"Command Act. Count:   %dT                                %dT\n"
+		"Command Rec. Count:   %dT                               %dT\n\n",
+		(reg5xh & 0x70) ? ((reg5xh & 0x70) >> 4) : 8,
+		(reg5yh & 0x70) ? ((reg5yh & 0x70) >> 4) : 8, 
+		(reg5xh & 0x0f) ? (reg5xh & 0x0f) : 16,
+		(reg5yh & 0x0f) ? (reg5yh & 0x0f) : 16 );
+
+	p += sprintf(p,
+		"----------------drive0-----------drive1------------drive0-----------drive1------\n\n");
+	p += sprintf(p,
+		"DMA enabled:      %s              %s               %s              %s\n",
+		(c0&0x20) ? "Yes" : "No ",
+		(c0&0x40) ? "Yes" : "No ",
+		(c1&0x20) ? "Yes" : "No ",
+		(c1&0x40) ? "Yes" : "No " );
+
+	pci_read_config_byte(bmide_dev, 0x54, &reg5xh);
+	pci_read_config_byte(bmide_dev, 0x55, &reg5yh);
+	q = "FIFO threshold:   %2d Words         %2d Words          %2d Words         %2d Words\n";
+	if (rev < 0xc1) {
+		if ((rev == 0x20) && (pci_read_config_byte(bmide_dev, 0x4f, &tmp), (tmp &= 0x20))) {
+			p += sprintf(p, q, 8, 8, 8, 8);
+		} else {
+			p += sprintf(p, q,
+				(reg5xh & 0x03) + 12,
+				((reg5xh & 0x30)>>4) + 12,
+				(reg5yh & 0x03) + 12,
+				((reg5yh & 0x30)>>4) + 12 );
+		}
+	} else {
+		p += sprintf(p, q,
+			(tmp = (reg5xh & 0x03)) ? (tmp << 3) : 4,
+			(tmp = ((reg5xh & 0x30)>>4)) ? (tmp << 3) : 4,
+			(tmp = (reg5yh & 0x03)) ? (tmp << 3) : 4,
+			(tmp = ((reg5yh & 0x30)>>4)) ? (tmp << 3) : 4 );
+	}
+
+#if 0
+	p += sprintf(p, 
+		"FIFO threshold:   %2d Words         %2d Words          %2d Words         %2d Words\n",
+		(reg5xh & 0x03) + 12,
+		((reg5xh & 0x30)>>4) + 12,
+		(reg5yh & 0x03) + 12,
+		((reg5yh & 0x30)>>4) + 12 );
+#endif
+
+	p += sprintf(p,
+		"FIFO mode:        %s         %s          %s         %s\n",
+		fifo[((reg5xh & 0x0c) >> 2)],
+		fifo[((reg5xh & 0xc0) >> 6)],
+		fifo[((reg5yh & 0x0c) >> 2)],
+		fifo[((reg5yh & 0xc0) >> 6)] );
+
+	pci_read_config_byte(bmide_dev, 0x5a, &reg5xh);
+	pci_read_config_byte(bmide_dev, 0x5b, &reg5xh1);
+	pci_read_config_byte(bmide_dev, 0x5e, &reg5yh);
+	pci_read_config_byte(bmide_dev, 0x5f, &reg5yh1);
+
+	p += sprintf(p,/*
+		"------------------drive0-----------drive1------------drive0-----------drive1------\n")*/
+		"Dt RW act. Cnt    %2dT              %2dT               %2dT              %2dT\n"
+		"Dt RW rec. Cnt    %2dT              %2dT               %2dT              %2dT\n\n",
+		(reg5xh & 0x70) ? ((reg5xh & 0x70) >> 4) : 8,
+		(reg5xh1 & 0x70) ? ((reg5xh1 & 0x70) >> 4) : 8,
+		(reg5yh & 0x70) ? ((reg5yh & 0x70) >> 4) : 8,
+		(reg5yh1 & 0x70) ? ((reg5yh1 & 0x70) >> 4) : 8,
+		(reg5xh & 0x0f) ? (reg5xh & 0x0f) : 16,
+		(reg5xh1 & 0x0f) ? (reg5xh1 & 0x0f) : 16,
+		(reg5yh & 0x0f) ? (reg5yh & 0x0f) : 16,
+		(reg5yh1 & 0x0f) ? (reg5yh1 & 0x0f) : 16 );
+
+	p += sprintf(p,
+		"-----------------------------------UDMA Timings--------------------------------\n\n");
+
+	pci_read_config_byte(bmide_dev, 0x56, &reg5xh);
+	pci_read_config_byte(bmide_dev, 0x57, &reg5yh);
+	p += sprintf(p,
+		"UDMA:             %s               %s                %s               %s\n"
+		"UDMA timings:     %s             %s              %s             %s\n\n",
+		(reg5xh & 0x08) ? "OK" : "No",
+		(reg5xh & 0x80) ? "OK" : "No",
+		(reg5yh & 0x08) ? "OK" : "No",
+		(reg5yh & 0x80) ? "OK" : "No",
+		udmaT[(reg5xh & 0x07)],
+		udmaT[(reg5xh & 0x70) >> 4],
+		udmaT[reg5yh & 0x07],
+		udmaT[(reg5yh & 0x70) >> 4] );
+
+	return p-buffer; /* => must be less than 4k! */
+}
+#endif  /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) */
diff -u --recursive --new-file v2.3.0/linux/drivers/block/amiflop.c linux/drivers/block/amiflop.c
--- v2.3.0/linux/drivers/block/amiflop.c	Sun Nov 15 11:23:08 1998
+++ linux/drivers/block/amiflop.c	Tue May 11 23:33:42 1999
@@ -167,9 +167,9 @@
 /* request loop (trackbuffer) */
 static volatile int fdc_busy = -1;
 static volatile int fdc_nested = 0;
-static struct wait_queue *fdc_wait = NULL;
+static DECLARE_WAIT_QUEUE_HEAD(fdc_wait);
  
-static struct wait_queue *motor_wait = NULL;
+static DECLARE_WAIT_QUEUE_HEAD(motor_wait);
 
 static volatile int selected = -1;	/* currently selected drive */
 
@@ -185,7 +185,7 @@
  * request.
  */
 static volatile char block_flag = 0;
-static struct wait_queue *wait_fd_block = NULL;
+static DECLARE_WAIT_QUEUE_HEAD(wait_fd_block);
 
 /* MS-Dos MFM Coding tables (should go quick and easy) */
 static unsigned char mfmencode[16]={
@@ -196,7 +196,7 @@
 
 /* floppy internal millisecond timer stuff */
 static volatile int ms_busy = -1;
-static struct wait_queue *ms_wait = NULL;
+static DECLARE_WAIT_QUEUE_HEAD(ms_wait);
 #define MS_TICKS ((amiga_eclock+50)/1000)
 
 /*
diff -u --recursive --new-file v2.3.0/linux/drivers/block/ataflop.c linux/drivers/block/ataflop.c
--- v2.3.0/linux/drivers/block/ataflop.c	Tue Dec 29 11:23:59 1998
+++ linux/drivers/block/ataflop.c	Tue May 11 23:34:07 1999
@@ -314,8 +314,8 @@
 
 /* Synchronization of FDC access. */
 static volatile int fdc_busy = 0;
-static struct wait_queue *fdc_wait = NULL;
-static struct wait_queue *format_wait = NULL;
+static DECLARE_WAIT_QUEUE_HEAD(fdc_wait);
+static DECLARE_WAIT_QUEUE_HEAD(format_wait);
 
 static unsigned int changed_floppies = 0xff, fake_change = 0;
 #define	CHECK_CHANGE_DELAY	HZ/2
diff -u --recursive --new-file v2.3.0/linux/drivers/block/buddha.c linux/drivers/block/buddha.c
--- v2.3.0/linux/drivers/block/buddha.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/block/buddha.c	Thu May 13 11:04:54 1999
@@ -0,0 +1,161 @@
+/*
+ *  linux/drivers/block/buddha.c -- Amiga Buddha and Catweasel IDE Driver
+ *
+ *	Copyright (C) 1997 by Geert Uytterhoeven
+ *
+ *  This driver was written by based on the specifications in README.buddha.
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive for
+ *  more details.
+ *
+ *  TODO:
+ *    - test it :-)
+ *    - tune the timings using the speed-register
+ */
+
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+#include <linux/zorro.h>
+#include <linux/ide.h>
+
+#include <asm/amigahw.h>
+#include <asm/amigaints.h>
+
+
+    /*
+     *  The Buddha has 2 IDE interfaces, the Catweasel has 3
+     */
+
+#define BUDDHA_NUM_HWIFS	2
+#define CATWEASEL_NUM_HWIFS	3
+
+
+    /*
+     *  Bases of the IDE interfaces (relative to the board address)
+     */
+
+#define BUDDHA_BASE1	0x800
+#define BUDDHA_BASE2	0xa00
+#define BUDDHA_BASE3	0xc00
+
+static const u_int buddha_bases[CATWEASEL_NUM_HWIFS] = {
+    BUDDHA_BASE1, BUDDHA_BASE2, BUDDHA_BASE3
+};
+
+
+    /*
+     *  Offsets from one of the above bases
+     */
+
+#define BUDDHA_DATA	0x00
+#define BUDDHA_ERROR	0x06		/* see err-bits */
+#define BUDDHA_NSECTOR	0x0a		/* nr of sectors to read/write */
+#define BUDDHA_SECTOR	0x0e		/* starting sector */
+#define BUDDHA_LCYL	0x12		/* starting cylinder */
+#define BUDDHA_HCYL	0x16		/* high byte of starting cyl */
+#define BUDDHA_SELECT	0x1a		/* 101dhhhh , d=drive, hhhh=head */
+#define BUDDHA_STATUS	0x1e		/* see status-bits */
+#define BUDDHA_CONTROL	0x11a
+
+static int buddha_offsets[IDE_NR_PORTS] = {
+    BUDDHA_DATA, BUDDHA_ERROR, BUDDHA_NSECTOR, BUDDHA_SECTOR, BUDDHA_LCYL,
+    BUDDHA_HCYL, BUDDHA_SELECT, BUDDHA_STATUS, BUDDHA_CONTROL
+};
+
+
+    /*
+     *  Other registers
+     */
+
+#define BUDDHA_IRQ1	0xf00		/* MSB = 1, Harddisk is source of */
+#define BUDDHA_IRQ2	0xf40		/* interrupt */
+#define BUDDHA_IRQ3	0xf80
+
+static const int buddha_irqports[CATWEASEL_NUM_HWIFS] = {
+    BUDDHA_IRQ1, BUDDHA_IRQ2, BUDDHA_IRQ3
+};
+
+#define BUDDHA_IRQ_MR	0xfc0		/* master interrupt enable */
+
+
+    /*
+     *  Board information
+     */
+
+static u_long buddha_board = 0;
+static int buddha_num_hwifs = -1;
+
+
+    /*
+     *  Check and acknowledge the interrupt status
+     */
+
+static int buddha_ack_intr(ide_hwif_t *hwif)
+{
+    unsigned char ch;
+
+    ch = inb(hwif->io_ports[IDE_IRQ_OFFSET]);
+    if (!(ch & 0x80))
+	return 0;
+    return 1;
+}
+
+
+    /*
+     *  Any Buddha or Catweasel boards present?
+     */
+
+static int find_buddha(void)
+{
+    u_int key;
+    const struct ConfigDev *cd;
+
+    buddha_num_hwifs = 0;
+    if ((key = zorro_find(ZORRO_PROD_INDIVIDUAL_COMPUTERS_BUDDHA, 0, 0)))
+	buddha_num_hwifs = BUDDHA_NUM_HWIFS;
+    else if ((key = zorro_find(ZORRO_PROD_INDIVIDUAL_COMPUTERS_CATWEASEL, 0,
+			       0)))
+	buddha_num_hwifs = CATWEASEL_NUM_HWIFS;
+    if (key) {
+	cd = zorro_get_board(key);
+	buddha_board = (u_long)cd->cd_BoardAddr;
+	if (buddha_board) {
+	    buddha_board = ZTWO_VADDR(buddha_board);
+	    /* write to BUDDHA_IRQ_MR to enable the board IRQ */
+	    *(char *)(buddha_board+BUDDHA_IRQ_MR) = 0;
+	    zorro_config_board(key, 0);
+	}
+    }
+    return buddha_num_hwifs;
+}
+
+
+    /*
+     *  Probe for a Buddha or Catweasel IDE interface
+     *  We support only _one_ of them, no multiple boards!
+     */
+
+void buddha_init(void)
+{
+    hw_regs_t hw;
+    int i, index;
+
+    if (buddha_num_hwifs < 0 && !find_buddha())
+	return;
+
+    for (i = 0; i < buddha_num_hwifs; i++) {
+	ide_setup_ports(&hw, (ide_ioreg_t)(buddha_board+buddha_bases[i]),
+			buddha_offsets, 0,
+			(ide_ioreg_t)(buddha_board+buddha_irqports[i]),
+			buddha_ack_intr, IRQ_AMIGA_PORTS);
+	index = ide_register_hw(&hw, NULL);
+	if (index != -1)
+	    printk("ide%d: %s IDE interface\n", index,
+		   buddha_num_hwifs == BUDDHA_NUM_HWIFS ? "Buddha" :
+		   					  "Catweasel");
+    }
+}
diff -u --recursive --new-file v2.3.0/linux/drivers/block/cmd640.c linux/drivers/block/cmd640.c
--- v2.3.0/linux/drivers/block/cmd640.c	Mon Jan  4 15:07:27 1999
+++ linux/drivers/block/cmd640.c	Thu May 13 11:04:54 1999
@@ -110,8 +110,10 @@
 #include <linux/ioport.h>
 #include <linux/blkdev.h>
 #include <linux/hdreg.h>
+#include <linux/ide.h>
+
 #include <asm/io.h>
-#include "ide.h"
+
 #include "ide_modes.h"
 
 /*
diff -u --recursive --new-file v2.3.0/linux/drivers/block/cmd646.c linux/drivers/block/cmd646.c
--- v2.3.0/linux/drivers/block/cmd646.c	Mon Mar 15 16:11:29 1999
+++ linux/drivers/block/cmd646.c	Thu May 13 11:04:54 1999
@@ -12,8 +12,10 @@
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
+#include <linux/hdreg.h>
+#include <linux/ide.h>
+
 #include <asm/io.h>
-#include "ide.h"
 
 static int cmd646_config_drive_for_dma(ide_drive_t *drive)
 {
@@ -43,14 +45,14 @@
 }
 
 /* This is fun.  -DaveM */
-#define IDE_SETXFER		0x03
-#define IDE_SETFEATURE		0xef
-#define IDE_DMA2_ENABLE		0x22
-#define IDE_DMA1_ENABLE		0x21
-#define IDE_DMA0_ENABLE		0x20
-#define IDE_UDMA2_ENABLE	0x42
-#define IDE_UDMA1_ENABLE	0x41
-#define IDE_UDMA0_ENABLE	0x40
+#define IDE_SETXFER		SETFEATURES_XFER
+#define IDE_SETFEATURE		WIN_SETFEATURES
+#define IDE_DMA2_ENABLE		XFER_MW_DMA_2
+#define IDE_DMA1_ENABLE		XFER_MW_DMA_1
+#define IDE_DMA0_ENABLE		XFER_MW_DMA_0
+#define IDE_UDMA2_ENABLE	XFER_UDMA_2
+#define IDE_UDMA1_ENABLE	XFER_UDMA_1
+#define IDE_UDMA0_ENABLE	XFER_UDMA_0
 
 static __inline__ unsigned char dma2_bits_to_command(unsigned char bits)
 {
@@ -212,10 +214,36 @@
 	return ide_dmaproc(func, drive);
 }
 
+/*
+ * ASUS P55T2P4D with CMD646 chipset revision 0x01 requires the old
+ * event order for DMA transfers.
+ */
+static int cmd646_1_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
+{
+	ide_hwif_t *hwif = HWIF(drive);
+	unsigned long dma_base = hwif->dma_base;
+	byte dma_stat;
+
+	if (func == ide_dma_end) {
+		drive->waiting_for_dma = 0;
+		dma_stat = inb(dma_base+2);		/* get DMA status */
+		outb(inb(dma_base)&~1, dma_base);	/* stop DMA */
+		outb(dma_stat|6, dma_base+2);	/* clear the INTR & ERROR bits */
+		return (dma_stat & 7) != 4;	/* verify good DMA status */
+	}
+
+	/* Other cases are done by generic IDE-DMA code. */
+	return cmd646_dmaproc(func, drive);
+}
+
 __initfunc(void ide_init_cmd646 (ide_hwif_t *hwif))
 {
 	struct pci_dev *dev = hwif->pci_dev;
 	unsigned char mrdmode;
+	unsigned int class_rev;
+
+	pci_read_config_dword(hwif->pci_dev, PCI_CLASS_REVISION, &class_rev);
+	class_rev &= 0xff;
 
 	hwif->chipset = ide_cmd646;
 
@@ -247,5 +275,9 @@
 	(void) pci_write_config_byte(dev, 0x58, 0x3f);
 	(void) pci_write_config_byte(dev, 0x5b, 0x3f);
 
-	hwif->dmaproc = &cmd646_dmaproc;
+	if (class_rev == 0x01) {
+		hwif->dmaproc = &cmd646_1_dmaproc;
+	} else {
+		hwif->dmaproc = &cmd646_dmaproc;
+	}
 }
diff -u --recursive --new-file v2.3.0/linux/drivers/block/cy82c693.c linux/drivers/block/cy82c693.c
--- v2.3.0/linux/drivers/block/cy82c693.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/block/cy82c693.c	Thu May 13 11:04:54 1999
@@ -0,0 +1,431 @@
+/*
+ * linux/drivers/block/cy82c693.c	Version 0.33	Jan. 23, 1999
+ *
+ *  Copyright (C) 1998, 1999 Andreas S. Krebs (akrebs@altavista.net), Maintainer
+ *  Copyright (C) 1998 Andre Hedrick, Integrater
+ *
+ * CYPRESS CY82C693 chipset IDE controller
+ *
+ * The CY82C693 chipset is used on Digital's PC-Alpha 164SX boards.
+ * Writting the driver was quite simple, since most of the job is
+ * done by the generic pci-ide support. 
+ * The hard part was finding the CY82C693's datasheet on Cypress's
+ * web page :-(. But Altavista solved this problem :-).
+ *
+ *
+ * Notes:
+ * - I recently got a 16.8G IBM DTTA, so I was able to test it with
+ *   a large and fast disk - the results look great, so I'd say the
+ *   driver is working fine :-)
+ *   hdparm -t reports 8.17 MB/sec at about 6% CPU usage for the DTTA 
+ * - this is my first linux driver, so there's probably a lot  of room 
+ *   for optimizations and bug fixing, so fell free to do it.
+ * - use idebus=xx parameter to set PCI bus speed - needed to calc
+ *   timings for PIO modes (default will be 40)
+ * - if using PIO mode it's a good idea to set the PIO mode and 
+ *   32-bit I/O support (if possible), e.g. hdparm -p2 -c1 /dev/hda
+ * - I had some problems with my IBM DHEA with PIO modes < 2
+ *   (lost interrupts) ?????
+ * - first tests with DMA look okay, they seem to work, but there is a
+ *   problem with sound - the BusMaster IDE TimeOut should fixed this
+ *
+ *
+ * History:
+ * ASK@1999-01-23: v0.33 made a few minor code clean ups
+ *                       removed DMA clock speed setting by default
+ *                       added boot message
+ * ASK@1998-11-01: v0.32 added support to set BusMaster IDE TimeOut
+ *                       added support to set DMA Controller Clock Speed
+ * ASK@1998-10-31: v0.31 fixed problem with setting to high DMA modes on some drive
+ * ASK@1998-10-29: v0.3 added support to set DMA modes
+ * ASK@1998-10-28: v0.2 added support to set PIO modes
+ * ASK@1998-10-27: v0.1 first version - chipset detection
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/ide.h>
+
+#include <asm/io.h>
+
+#include "ide_modes.h"
+
+/* the current version */
+#define CY82_VERSION	"CY82C693U driver v0.33 99-01-23 Andreas S. Krebs (akrebs@altavista.net)"
+
+/*
+ *	The following are used to debug the driver.
+ */
+#define	CY82C693_DEBUG_LOGS	0
+#define	CY82C693_DEBUG_INFO	0
+
+/* define CY82C693_SETDMA_CLOCK to set DMA Controller Clock Speed to ATCLK */
+#undef CY82C693_SETDMA_CLOCK
+
+/*
+ * note: the value for busmaster timeout is tricky and i got it by trial and error !
+ *       using a to low value will cause DMA timeouts and drop IDE performance
+ *       using a to high value will cause audio playback to scatter
+ *       if you know a better value or how to calc it, please let me know 
+ */
+#define BUSMASTER_TIMEOUT	0x50	/* twice the value written in cy82c693ub datasheet */
+/*
+ * the value above was tested on my machine and it seems to work okay
+ */
+
+/* here are the offset definitions for the registers */
+#define CY82_IDE_CMDREG		0x04
+#define CY82_IDE_ADDRSETUP	0x48
+#define CY82_IDE_MASTER_IOR	0x4C	
+#define CY82_IDE_MASTER_IOW	0x4D	
+#define CY82_IDE_SLAVE_IOR	0x4E	
+#define CY82_IDE_SLAVE_IOW	0x4F
+#define CY82_IDE_MASTER_8BIT	0x50	
+#define CY82_IDE_SLAVE_8BIT	0x51	
+
+#define CY82_INDEX_PORT		0x22
+#define CY82_DATA_PORT		0x23
+
+#define CY82_INDEX_CTRLREG1	0x01
+#define CY82_INDEX_CHANNEL0	0x30
+#define CY82_INDEX_CHANNEL1	0x31
+#define CY82_INDEX_TIMEOUT	0x32
+
+/* the max PIO mode - from datasheet */
+#define CY82C693_MAX_PIO	4
+
+/* the min and max PCI bus speed in MHz - from datasheet */
+#define CY82C963_MIN_BUS_SPEED	25
+#define CY82C963_MAX_BUS_SPEED	33
+
+/* the struct for the PIO mode timings */
+typedef struct pio_clocks_s {
+        byte	address_time;		/* Address setup (clocks) */
+	byte	time_16r;		/* clocks for 16bit IOR (0xF0=Active/data, 0x0F=Recovery) */
+	byte	time_16w;		/* clocks for 16bit IOW (0xF0=Active/data, 0x0F=Recovery) */
+	byte	time_8;			/* clocks for 8bit (0xF0=Active/data, 0x0F=Recovery) */
+} pio_clocks_t;
+
+/*
+ * calc clocks using bus_speed
+ * returns (rounded up) time in bus clocks for time in ns
+ */
+static int calc_clk (int time, int bus_speed)
+{
+	int clocks;
+
+	clocks = (time*bus_speed+999)/1000 -1;
+
+	if (clocks < 0)
+		clocks = 0;
+
+	if (clocks > 0x0F)
+		clocks = 0x0F;
+
+	return clocks;
+}
+
+/*
+ * compute the values for the clock registers for PIO
+ * mode and pci_clk [MHz] speed
+ *
+ * NOTE: for mode 0,1 and 2 drives 8-bit IDE command control registers are used
+ *       for mode 3 and 4 drives 8 and 16-bit timings are the same
+ *
+ */ 
+static void compute_clocks (byte pio, pio_clocks_t *p_pclk)
+{
+	int clk1, clk2;
+	int bus_speed;
+
+	bus_speed = ide_system_bus_speed();	/* get speed of PCI bus */
+	/* we don't check against CY82C693's min and max speed,
+	 * so you can play with the idebus=xx parameter
+	 */
+
+	if (pio > CY82C693_MAX_PIO)
+		pio = CY82C693_MAX_PIO;
+
+	/* let's calc the address setup time clocks */
+	p_pclk->address_time = (byte)calc_clk(ide_pio_timings[pio].setup_time, bus_speed);
+
+	/* let's calc the active and recovery time clocks */
+	clk1 = calc_clk(ide_pio_timings[pio].active_time, bus_speed);
+
+	/* calc recovery timing */
+	clk2 =	ide_pio_timings[pio].cycle_time -
+		ide_pio_timings[pio].active_time -
+		ide_pio_timings[pio].setup_time;
+
+	clk2 = calc_clk(clk2, bus_speed);
+
+	clk1 = (clk1<<4)|clk2;	/* combine active and recovery clocks */
+
+	/* note: we use the same values for 16bit IOR and IOW
+         *	those are all the same, since I don't have other
+	 *	timings than those from ide_modes.h
+	 */
+
+	p_pclk->time_16r = (byte)clk1;
+	p_pclk->time_16w = (byte)clk1;
+
+	/* what are good values for 8bit ?? */
+	p_pclk->time_8 = (byte)clk1;
+}
+
+/*
+ * set DMA mode a specific channel for CY82C693
+ */
+static void cy82c693_dma_enable (ide_drive_t *drive, int mode, int single)
+{
+        byte index;
+	byte data;
+
+        if (mode>2)	/* make sure we set a valid mode */
+		mode = 2;
+			   
+	if (mode > drive->id->tDMA)  /* to be absolutly sure we have a valid mode */
+		mode = drive->id->tDMA;
+	
+        index = (HWIF(drive)->channel==0) ? CY82_INDEX_CHANNEL0 : CY82_INDEX_CHANNEL1;
+
+#if CY82C693_DEBUG_LOGS
+       	/* for debug let's show the previous values */
+
+	OUT_BYTE(index, CY82_INDEX_PORT);
+	data = IN_BYTE(CY82_DATA_PORT);
+
+	printk (KERN_INFO "%s (ch=%d, dev=%d): DMA mode is %d (single=%d)\n", drive->name, HWIF(drive)->channel, drive->select.b.unit, (data&0x3), ((data>>2)&1));
+#endif /* CY82C693_DEBUG_LOGS */
+
+	data = (byte)mode|(byte)(single<<2);
+
+	OUT_BYTE(index, CY82_INDEX_PORT);
+	OUT_BYTE(data, CY82_DATA_PORT);
+
+#if CY82C693_DEBUG_INFO
+	printk (KERN_INFO "%s (ch=%d, dev=%d): set DMA mode to %d (single=%d)\n", drive->name, HWIF(drive)->channel, drive->select.b.unit, mode, single);
+#endif /* CY82C693_DEBUG_INFO */
+
+	/* 
+	 * note: below we set the value for Bus Master IDE TimeOut Register
+	 * I'm not absolutly sure what this does, but it solved my problem
+	 * with IDE DMA and sound, so I now can play sound and work with
+	 * my IDE driver at the same time :-)
+	 *
+	 * If you know the correct (best) value for this register please
+	 * let me know - ASK
+	 */
+
+	data = BUSMASTER_TIMEOUT;
+	OUT_BYTE(CY82_INDEX_TIMEOUT, CY82_INDEX_PORT);
+	OUT_BYTE(data, CY82_DATA_PORT);
+
+#if CY82C693_DEBUG_INFO	
+	printk (KERN_INFO "%s: Set IDE Bus Master TimeOut Register to 0x%X\n", drive->name, data);
+#endif /* CY82C693_DEBUG_INFO */
+}
+
+/* 
+ * used to set DMA mode for CY82C693 (single and multi modes)
+ */
+static int cy82c693_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
+{
+	/*
+	 * if the function is dma on, set dma mode for drive everything
+	 * else is done by the defaul func
+	 */
+	if (func == ide_dma_on) {
+		struct hd_driveid *id = drive->id;
+
+#if CY82C693_DEBUG_INFO
+		printk (KERN_INFO "dma_on: %s\n", drive->name);
+#endif /* CY82C693_DEBUG_INFO */
+
+		if (id != NULL) {		
+                       /* Enable DMA on any drive that has DMA (multi or single) enabled */
+                       if (id->field_valid & 2) {       /* regular DMA */
+			       int mmode, smode;
+
+			       mmode = id->dma_mword & (id->dma_mword >> 8);
+			       smode = id->dma_1word & (id->dma_1word >> 8);
+			       		      
+		               if (mmode != 0)
+				     cy82c693_dma_enable(drive, (mmode >> 1), 0); /* enable multi */
+			       else if (smode != 0)
+				     cy82c693_dma_enable(drive, (smode >> 1), 1); /* enable single */
+			}
+		}
+	}
+        return ide_dmaproc(func, drive);
+}
+
+/*
+ * tune ide drive - set PIO mode
+ */
+static void cy82c693_tune_drive (ide_drive_t *drive, byte pio)
+{
+	ide_hwif_t *hwif = HWIF(drive);
+	struct pci_dev *dev = hwif->pci_dev;
+	pio_clocks_t pclk;
+	unsigned int addrCtrl;
+
+	/* select primary or secondary channel */
+	if (hwif->index > 0)  /* drive is on the secondary channel */
+		dev = dev->next;
+
+#if CY82C693_DEBUG_LOGS
+	/* for debug let's show the register values */
+	
+       	if (drive->select.b.unit == 0) {
+		/*
+		 * get master drive registers               	
+		 * address setup control register
+		 * is 32 bit !!!
+		 */ 
+	  	pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl);                
+		addrCtrl &= 0x0F;
+
+		/* now let's get the remaining registers */
+		pci_read_config_byte(dev, CY82_IDE_MASTER_IOR, &pclk.time_16r);
+		pci_read_config_byte(dev, CY82_IDE_MASTER_IOW, &pclk.time_16w);
+		pci_read_config_byte(dev, CY82_IDE_MASTER_8BIT, &pclk.time_8);
+	} else {
+		/*
+		 * set slave drive registers
+		 * address setup control register
+		 * is 32 bit !!!
+		 */ 
+		pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl);
+
+		addrCtrl &= 0xF0;
+		addrCtrl >>= 4;
+
+		/* now let's get the remaining registers */
+		pci_read_config_byte(dev, CY82_IDE_SLAVE_IOR, &pclk.time_16r);
+		pci_read_config_byte(dev, CY82_IDE_SLAVE_IOW, &pclk.time_16w);
+		pci_read_config_byte(dev, CY82_IDE_SLAVE_8BIT, &pclk.time_8);
+	}
+
+	printk (KERN_INFO "%s (ch=%d, dev=%d): PIO timing is (addr=0x%X, ior=0x%X, iow=0x%X, 8bit=0x%X)\n", drive->name, hwif->channel, drive->select.b.unit, addrCtrl, pclk.time_16r, pclk.time_16w, pclk.time_8);
+#endif /* CY82C693_DEBUG_LOGS */
+
+        /* first let's calc the pio modes */
+	pio = ide_get_best_pio_mode(drive, pio, CY82C693_MAX_PIO, NULL);
+
+#if CY82C693_DEBUG_INFO
+	printk (KERN_INFO "%s: Selected PIO mode %d\n", drive->name, pio);
+#endif /* CY82C693_DEBUG_INFO */
+
+        compute_clocks(pio, &pclk);  /* let's calc the values for this PIO mode */
+
+	/* now let's write  the clocks registers */
+	if (drive->select.b.unit == 0) {
+		/*
+		 * set master drive
+		 * address setup control register
+		 * is 32 bit !!!
+		 */ 
+		pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl);
+		
+		addrCtrl &= (~0xF);
+		addrCtrl |= (unsigned int)pclk.address_time;
+		pci_write_config_dword(dev, CY82_IDE_ADDRSETUP, addrCtrl);
+
+		/* now let's set the remaining registers */
+		pci_write_config_byte(dev, CY82_IDE_MASTER_IOR, pclk.time_16r);
+		pci_write_config_byte(dev, CY82_IDE_MASTER_IOW, pclk.time_16w);
+		pci_write_config_byte(dev, CY82_IDE_MASTER_8BIT, pclk.time_8);
+		
+		addrCtrl &= 0xF;
+	} else {
+		/*
+		 * set slave drive
+		 * address setup control register
+		 * is 32 bit !!!
+		 */ 
+		pci_read_config_dword(dev, CY82_IDE_ADDRSETUP, &addrCtrl);
+
+		addrCtrl &= (~0xF0);
+		addrCtrl |= ((unsigned int)pclk.address_time<<4);
+		pci_write_config_dword(dev, CY82_IDE_ADDRSETUP, addrCtrl);
+
+		/* now let's set the remaining registers */
+		pci_write_config_byte(dev, CY82_IDE_SLAVE_IOR, pclk.time_16r);
+		pci_write_config_byte(dev, CY82_IDE_SLAVE_IOW, pclk.time_16w);
+		pci_write_config_byte(dev, CY82_IDE_SLAVE_8BIT, pclk.time_8);
+
+		addrCtrl >>= 4;
+		addrCtrl &= 0xF;
+	}	
+
+#if CY82C693_DEBUG_INFO
+	printk (KERN_INFO "%s (ch=%d, dev=%d): set PIO timing to (addr=0x%X, ior=0x%X, iow=0x%X, 8bit=0x%X)\n", drive->name, hwif->channel, drive->select.b.unit, addrCtrl, pclk.time_16r, pclk.time_16w, pclk.time_8);
+#endif /* CY82C693_DEBUG_INFO */
+}
+
+/*
+ * this function is called during init and is used to setup the cy82c693 chip
+ */
+static void init_cy82c693_chip (struct pci_dev *dev)
+{
+	static int initDone = 0;
+#ifdef CY82C693_SETDMA_CLOCK
+        byte data;
+#endif /* CY82C693_SETDMA_CLOCK */ 
+
+	if (initDone != 0)	/* only perform setup once */
+		return;
+	initDone = 1;
+
+	/* write info about this verion of the driver */
+	printk (KERN_INFO CY82_VERSION "\n");
+
+#ifdef CY82C693_SETDMA_CLOCK
+       /* okay let's set the DMA clock speed */
+        
+        OUT_BYTE(CY82_INDEX_CTRLREG1, CY82_INDEX_PORT);
+        data = IN_BYTE(CY82_DATA_PORT);
+
+#if CY82C693_DEBUG_INFO
+	printk (KERN_INFO "CY82U693: Peripheral Configuration Register: 0x%X\n", data);
+#endif /* CY82C693_DEBUG_INFO */
+
+        /*
+	 * for some reason sometimes the DMA controller
+	 * speed is set to ATCLK/2 ???? - we fix this here
+	 * 
+	 * note: i don't know what causes this strange behaviour,
+	 *       but even changing the dma speed doesn't solve it :-(
+	 *       the ide performance is still only half the normal speed 
+	 * 
+	 *       if anybody knows what goes wrong with my machine, please
+	 *       let me know - ASK
+         */
+
+	data |= 0x03;
+
+        OUT_BYTE(CY82_INDEX_CTRLREG1, CY82_INDEX_PORT);
+        OUT_BYTE(data, CY82_DATA_PORT);
+
+#if CY82C693_DEBUG_INFO
+	printk (KERN_INFO "CY82U693: New Peripheral Configuration Register: 0x%X\n", data);
+#endif /* CY82C693_DEBUG_INFO */
+
+#endif /* CY82C693_SETDMA_CLOCK */ 
+}
+
+/*
+ * the init function - called for each ide channel once
+ */
+__initfunc(void ide_init_cy82c693(ide_hwif_t *hwif))
+{
+	hwif->chipset = ide_cy82c693;
+	hwif->dmaproc = &cy82c693_dmaproc;
+	hwif->tuneproc = &cy82c693_tune_drive;
+
+	init_cy82c693_chip(hwif->pci_dev);
+}
+
diff -u --recursive --new-file v2.3.0/linux/drivers/block/dtc2278.c linux/drivers/block/dtc2278.c
--- v2.3.0/linux/drivers/block/dtc2278.c	Wed May  6 14:42:53 1998
+++ linux/drivers/block/dtc2278.c	Thu May 13 11:04:54 1999
@@ -14,8 +14,10 @@
 #include <linux/ioport.h>
 #include <linux/blkdev.h>
 #include <linux/hdreg.h>
+#include <linux/ide.h>
+
 #include <asm/io.h>
-#include "ide.h"
+
 #include "ide_modes.h"
 
 /*
diff -u --recursive --new-file v2.3.0/linux/drivers/block/falconide.c linux/drivers/block/falconide.c
--- v2.3.0/linux/drivers/block/falconide.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/block/falconide.c	Thu May 13 11:04:54 1999
@@ -0,0 +1,66 @@
+/*
+ *  linux/drivers/block/falconide.c -- Atari Falcon IDE Driver
+ *
+ *     Created 12 Jul 1997 by Geert Uytterhoeven
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+#include <linux/ide.h>
+
+#include <asm/atarihw.h>
+#include <asm/atariints.h>
+#include <asm/atari_stdma.h>
+
+
+    /*
+     *  Base of the IDE interface
+     */
+
+#define ATA_HD_BASE	0xfff00000
+
+    /*
+     *  Offsets from the above base
+     */
+
+#define ATA_HD_DATA	0x00
+#define ATA_HD_ERROR	0x05		/* see err-bits */
+#define ATA_HD_NSECTOR	0x09		/* nr of sectors to read/write */
+#define ATA_HD_SECTOR	0x0d		/* starting sector */
+#define ATA_HD_LCYL	0x11		/* starting cylinder */
+#define ATA_HD_HCYL	0x15		/* high byte of starting cyl */
+#define ATA_HD_SELECT	0x19		/* 101dhhhh , d=drive, hhhh=head */
+#define ATA_HD_STATUS	0x1d		/* see status-bits */
+#define ATA_HD_CONTROL	0x39
+
+static int falconide_offsets[IDE_NR_PORTS] = {
+    ATA_HD_DATA, ATA_HD_ERROR, ATA_HD_NSECTOR, ATA_HD_SECTOR, ATA_HD_LCYL,
+    ATA_HD_HCYL, ATA_HD_SELECT, ATA_HD_STATUS, ATA_HD_CONTROL, -1
+};
+
+
+    /*
+     *  Probe for a Falcon IDE interface
+     */
+
+void falconide_init(void)
+{
+    if (MACH_IS_ATARI && ATARIHW_PRESENT(IDE)) {
+	hw_regs_t hw;
+	int index;
+
+	ide_setup_ports(&hw, (ide_ioreg_t)ATA_HD_BASE, falconide_offsets,
+			0, 0, NULL, IRQ_MFP_IDE);
+	index = ide_register_hw(&hw, NULL);
+
+	if (index != -1)
+	    printk("ide%d: Falcon IDE interface\n", index);
+    }
+}
diff -u --recursive --new-file v2.3.0/linux/drivers/block/floppy.c linux/drivers/block/floppy.c
--- v2.3.0/linux/drivers/block/floppy.c	Fri Mar 26 13:29:14 1999
+++ linux/drivers/block/floppy.c	Tue May 11 14:48:07 1999
@@ -466,7 +466,9 @@
 #define FD_COMMAND_OKAY 3
 
 static volatile int command_status = FD_COMMAND_NONE, fdc_busy = 0;
-static struct wait_queue *fdc_wait = NULL, *command_done = NULL;
+static DECLARE_WAIT_QUEUE_HEAD(fdc_wait);
+static DECLARE_WAIT_QUEUE_HEAD(command_done);
+
 #define NO_SIGNAL (!interruptible || !signal_pending(current))
 #define CALL(x) if ((x) == -EINTR) return -EINTR
 #define ECALL(x) if ((ret = (x))) return ret;
diff -u --recursive --new-file v2.3.0/linux/drivers/block/gayle.c linux/drivers/block/gayle.c
--- v2.3.0/linux/drivers/block/gayle.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/block/gayle.c	Thu May 13 11:04:54 1999
@@ -0,0 +1,169 @@
+/*
+ *  linux/drivers/block/gayle.c -- Amiga Gayle IDE Driver
+ *
+ *     Created 9 Jul 1997 by Geert Uytterhoeven
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+#include <linux/ide.h>
+
+#include <asm/amigahw.h>
+#include <asm/amigaints.h>
+
+
+    /*
+     *  Bases of the IDE interfaces
+     */
+
+#define GAYLE_BASE_4000	0xdd2020	/* A4000/A4000T */
+#define GAYLE_BASE_1200	0xda0000	/* A1200/A600 */
+
+    /*
+     *  Offsets from one of the above bases
+     */
+
+#define GAYLE_DATA	0x00
+#define GAYLE_ERROR	0x06		/* see err-bits */
+#define GAYLE_NSECTOR	0x0a		/* nr of sectors to read/write */
+#define GAYLE_SECTOR	0x0e		/* starting sector */
+#define GAYLE_LCYL	0x12		/* starting cylinder */
+#define GAYLE_HCYL	0x16		/* high byte of starting cyl */
+#define GAYLE_SELECT	0x1a		/* 101dhhhh , d=drive, hhhh=head */
+#define GAYLE_STATUS	0x1e		/* see status-bits */
+#define GAYLE_CONTROL	0x101a
+
+static int gayle_offsets[IDE_NR_PORTS] = {
+    GAYLE_DATA, GAYLE_ERROR, GAYLE_NSECTOR, GAYLE_SECTOR, GAYLE_LCYL,
+    GAYLE_HCYL, GAYLE_SELECT, GAYLE_STATUS, -1, -1
+};
+
+
+    /*
+     *  These are at different offsets from the base
+     */
+
+#define GAYLE_IRQ_4000	0xdd3020	/* MSB = 1, Harddisk is source of */
+#define GAYLE_IRQ_1200	0xda9000	/* interrupt */
+
+
+    /*
+     *  Offset of the secondary port for IDE doublers
+     *  Note that GAYLE_CONTROL is NOT available then!
+     */
+
+#define GAYLE_NEXT_PORT	0x1000
+
+#ifndef CONFIG_BLK_DEV_IDEDOUBLER
+#define GAYLE_NUM_HWIFS		1
+#define GAYLE_NUM_PROBE_HWIFS	GAYLE_NUM_HWIFS
+#define GAYLE_HAS_CONTROL_REG	1
+#else /* CONFIG_BLK_DEV_IDEDOUBLER */
+#define GAYLE_NUM_HWIFS		2
+#define GAYLE_NUM_PROBE_HWIFS	(ide_doubler ? GAYLE_NUM_HWIFS : \
+					       GAYLE_NUM_HWIFS-1)
+#define GAYLE_HAS_CONTROL_REG	(!ide_doubler)
+int ide_doubler = 0;	/* support IDE doublers? */
+#endif /* CONFIG_BLK_DEV_IDEDOUBLER */
+
+
+    /*
+     *  Check and acknowledge the interrupt status
+     */
+
+static int gayle_ack_intr_a4000(ide_hwif_t *hwif)
+{
+    unsigned char ch;
+
+    ch = inb(hwif->io_ports[IDE_IRQ_OFFSET]);
+    if (!(ch & 0x80))
+	return 0;
+    return 1;
+}
+
+static int gayle_ack_intr_a1200(ide_hwif_t *hwif)
+{
+    unsigned char ch;
+
+    ch = inb(hwif->io_ports[IDE_IRQ_OFFSET]);
+    if (!(ch & 0x80))
+	return 0;
+    (void)inb(hwif->io_ports[IDE_STATUS_OFFSET]);
+    outb(0x7c | (ch & 0x03), hwif->io_ports[IDE_IRQ_OFFSET]);
+    return 1;
+}
+
+    /*
+     *  Probe for a Gayle IDE interface (and optionally for an IDE doubler)
+     */
+
+void gayle_init(void)
+{
+    int a4000, i;
+
+    if (!MACH_IS_AMIGA)
+	return;
+
+    if (!(a4000 = AMIGAHW_PRESENT(A4000_IDE)) && !AMIGAHW_PRESENT(A1200_IDE))
+	return;
+
+    for (i = 0; i < GAYLE_NUM_PROBE_HWIFS; i++) {
+	ide_ioreg_t base, ctrlport, irqport;
+	ide_ack_intr_t *ack_intr;
+	hw_regs_t hw;
+	int index;
+
+	if (a4000) {
+	    base = (ide_ioreg_t)ZTWO_VADDR(GAYLE_BASE_4000);
+	    irqport = (ide_ioreg_t)ZTWO_VADDR(GAYLE_IRQ_4000);
+	    ack_intr = gayle_ack_intr_a4000;
+	} else {
+	    base = (ide_ioreg_t)ZTWO_VADDR(GAYLE_BASE_1200);
+	    irqport = (ide_ioreg_t)ZTWO_VADDR(GAYLE_IRQ_1200);
+	    ack_intr = gayle_ack_intr_a1200;
+	}
+
+	if (GAYLE_HAS_CONTROL_REG)
+	    ctrlport = base + GAYLE_CONTROL;
+	else
+	    ctrlport = 0;
+
+	base += i*GAYLE_NEXT_PORT;
+
+	ide_setup_ports(&hw, base, gayle_offsets,
+			ctrlport, irqport, ack_intr, IRQ_AMIGA_PORTS);
+
+	index = ide_register_hw(&hw, NULL);
+	if (index != -1) {
+	    switch (i) {
+		case 0:
+		    printk("ide%d: Gayle IDE interface (A%d style)\n", index,
+			   a4000 ? 4000 : 1200);
+		    break;
+#ifdef CONFIG_BLK_DEV_IDEDOUBLER
+		case 1:
+		    printk("ide%d: IDE doubler\n", index);
+		    break;
+#endif /* CONFIG_BLK_DEV_IDEDOUBLER */
+	    }
+	}
+#if 1 /* TESTING */
+	if (i == 1) {
+	    volatile u_short *addr = (u_short *)base;
+	    u_short data;
+	    printk("+++ Probing for IDE doubler... ");
+	    *addr = 0xffff;
+	    data = *addr;
+	    printk("probe returned 0x%02x (PLEASE REPORT THIS!!)\n", data);
+	}
+#endif /* TESTING */
+    }
+}
diff -u --recursive --new-file v2.3.0/linux/drivers/block/genhd.c linux/drivers/block/genhd.c
--- v2.3.0/linux/drivers/block/genhd.c	Mon Apr 12 16:18:27 1999
+++ linux/drivers/block/genhd.c	Thu May 13 11:00:08 1999
@@ -83,6 +83,10 @@
 	 * This requires special handling here.
 	 */
 	switch (hd->major) {
+		case IDE7_MAJOR:
+			unit += 2;
+		case IDE6_MAJOR:
+			unit += 2;
 		case IDE5_MAJOR:
 			unit += 2;
 		case IDE4_MAJOR:
diff -u --recursive --new-file v2.3.0/linux/drivers/block/hd.c linux/drivers/block/hd.c
--- v2.3.0/linux/drivers/block/hd.c	Wed Feb 24 16:27:53 1999
+++ linux/drivers/block/hd.c	Tue May 11 15:22:57 1999
@@ -68,7 +68,7 @@
 static char special_op[MAX_HD] = { 0, };
 static int access_count[MAX_HD] = {0, };
 static char busy[MAX_HD] = {0, };
-static struct wait_queue * busy_wait = NULL;
+static DECLARE_WAIT_QUEUE_HEAD(busy_wait);
 
 static int reset = 0;
 static int hd_error = 0;
diff -u --recursive --new-file v2.3.0/linux/drivers/block/hpt343.c linux/drivers/block/hpt343.c
--- v2.3.0/linux/drivers/block/hpt343.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/block/hpt343.c	Thu May 13 11:04:54 1999
@@ -0,0 +1,394 @@
+/*
+ * linux/drivers/block/hpt343.c		Version 0.23	May 12, 1999
+ *
+ * Copyright (C) 1998-99	Andre Hedrick
+ *					(hedrick@astro.dyer.vanderbilt.edu)
+ *
+ * 00:12.0 Unknown mass storage controller:
+ * Triones Technologies, Inc.
+ * Unknown device 0003 (rev 01)
+ *
+ * hde: UDMA 2 (0x0000 0x0002) (0x0000 0x0010)
+ * hdf: UDMA 2 (0x0002 0x0012) (0x0010 0x0030)
+ * hde: DMA 2  (0x0000 0x0002) (0x0000 0x0010)
+ * hdf: DMA 2  (0x0002 0x0012) (0x0010 0x0030)
+ * hdg: DMA 1  (0x0012 0x0052) (0x0030 0x0070)
+ * hdh: DMA 1  (0x0052 0x0252) (0x0070 0x00f0)
+ *
+ * drive_number
+ *	= ((HWIF(drive)->channel ? 2 : 0) + (drive->select.b.unit & 0x01));
+ *	= ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01));
+ */
+
+#include <linux/config.h>	/* for CONFIG_BLK_DEV_IDEPCI */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/ioport.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/ide.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include "ide_modes.h"
+
+#ifndef SPLIT_BYTE
+#define SPLIT_BYTE(B,H,L)	((H)=(B>>4), (L)=(B-((B>>4)<<4)))
+#endif
+
+#define HPT343_DEBUG_DRIVE_INFO		0
+#define HPT343_DISABLE_ALL_DMAING	0
+#define HPT343_DMA_DISK_ONLY		0
+
+extern char *ide_xfer_verbose (byte xfer_rate);
+
+static void hpt343_clear_chipset (ide_drive_t *drive)
+{
+	int drive_number	= ((HWIF(drive)->channel ? 2 : 0) + (drive->select.b.unit & 0x01));
+	unsigned int reg1	= 0, tmp1 = 0;
+	unsigned int reg2	= 0, tmp2 = 0;
+
+	pci_read_config_dword(HWIF(drive)->pci_dev, 0x44, &reg1);
+	pci_read_config_dword(HWIF(drive)->pci_dev, 0x48, &reg2);
+	tmp1 = ((0x00 << (3*drive_number)) | (reg1 & ~(7 << (3*drive_number))));
+	tmp2 = ((0x00 << drive_number) | reg2);
+	pci_write_config_dword(HWIF(drive)->pci_dev, 0x44, tmp1);
+	pci_write_config_dword(HWIF(drive)->pci_dev, 0x48, tmp2);
+}
+
+static int hpt343_tune_chipset (ide_drive_t *drive, byte speed)
+{
+	int			err;
+	byte			hi_speed, lo_speed;
+	int drive_number	= ((HWIF(drive)->channel ? 2 : 0) + (drive->select.b.unit & 0x01));
+	unsigned int reg1	= 0, tmp1 = 0;
+	unsigned int reg2	= 0, tmp2 = 0;
+
+	SPLIT_BYTE(speed, hi_speed, lo_speed);
+
+	if (hi_speed & 7) {
+		hi_speed = (hi_speed & 4) ? 0x01 : 0x10;
+	} else {
+		lo_speed <<= 5;
+		lo_speed >>= 5;
+	}
+
+	pci_read_config_dword(HWIF(drive)->pci_dev, 0x44, &reg1);
+	pci_read_config_dword(HWIF(drive)->pci_dev, 0x48, &reg2);
+	tmp1 = ((lo_speed << (3*drive_number)) | (reg1 & ~(7 << (3*drive_number))));
+	tmp2 = ((hi_speed << drive_number) | reg2);
+	err = ide_wait_cmd(drive, WIN_SETFEATURES, speed, SETFEATURES_XFER, 0, NULL);
+	pci_write_config_dword(HWIF(drive)->pci_dev, 0x44, tmp1);
+	pci_write_config_dword(HWIF(drive)->pci_dev, 0x48, tmp2);
+
+#if HPT343_DEBUG_DRIVE_INFO
+	printk("%s: %s drive%d (0x%04x 0x%04x) (0x%04x 0x%04x)" \
+		" (0x%02x 0x%02x) 0x%04x\n",
+		drive->name, ide_xfer_verbose(speed),
+		drive_number, reg1, tmp1, reg2, tmp2,
+		hi_speed, lo_speed, err);
+#endif /* HPT343_DEBUG_DRIVE_INFO */
+
+	return(err);
+}
+
+/*
+ * This allows the configuration of ide_pci chipset registers
+ * for cards that learn about the drive's UDMA, DMA, PIO capabilities
+ * after the drive is reported by the OS.  Initally for designed for
+ * HPT343 UDMA chipset by HighPoint|Triones Technologies, Inc.
+ */
+static int config_chipset_for_dma (ide_drive_t *drive)
+{
+	struct hd_driveid *id	= drive->id;
+	byte speed		= 0x00;
+
+#if HPT343_DISABLE_ALL_DMAING
+	return ((int) ide_dma_off);
+#elif HPT343_DMA_DISK_ONLY
+	if (drive->media != ide_disk)
+		return ((int) ide_dma_off_quietly);
+#endif /* HPT343_DISABLE_ALL_DMAING */
+
+	if (id->dma_ultra & 0x0004) {
+		if (!((id->dma_ultra >> 8) & 4)) {
+			drive->id->dma_ultra &= ~0x0F00;
+			drive->id->dma_ultra |= 0x0404;
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_1word &= ~0x0F00;
+		}
+		speed = XFER_UDMA_2;
+	} else if (id->dma_ultra & 0x0002) {
+		if (!((id->dma_ultra >> 8) & 2)) {
+			drive->id->dma_ultra &= ~0x0F00;
+			drive->id->dma_ultra |= 0x0202;
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_1word &= ~0x0F00;
+		}
+		speed = XFER_UDMA_1;
+	} else if (id->dma_ultra & 0x0001) {
+		if (!((id->dma_ultra >> 8) & 1)) {
+			drive->id->dma_ultra &= ~0x0F00;
+			drive->id->dma_ultra |= 0x0101;
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_1word &= ~0x0F00;
+		}
+		speed = XFER_UDMA_0;
+	} else if (id->dma_mword & 0x0004) {
+		if (!((id->dma_mword >> 8) & 4)) {
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_mword |= 0x0404;
+			drive->id->dma_1word &= ~0x0F00;
+		}
+		speed = XFER_MW_DMA_2;
+	} else if (id->dma_mword & 0x0002) {
+		if (!((id->dma_mword >> 8) & 2)) {
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_mword |= 0x0202;
+			drive->id->dma_1word &= ~0x0F00;
+		}
+		speed = XFER_MW_DMA_1;
+	} else if (id->dma_mword & 0x0001) {
+		if (!((id->dma_mword >> 8) & 1)) {
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_mword |= 0x0101;
+			drive->id->dma_1word &= ~0x0F00;
+		}
+		speed = XFER_MW_DMA_0;
+	} else if (id->dma_1word & 0x0004) {
+		if (!((id->dma_1word >> 8) & 4)) {
+			drive->id->dma_1word &= ~0x0F00;
+			drive->id->dma_1word |= 0x0404;
+			drive->id->dma_mword &= ~0x0F00;
+		}
+		speed = XFER_SW_DMA_2;
+	} else if (id->dma_1word & 0x0002) {
+		if (!((id->dma_1word >> 8) & 2)) {
+			drive->id->dma_1word &= ~0x0F00;
+			drive->id->dma_1word |= 0x0202;
+			drive->id->dma_mword &= ~0x0F00;
+		}
+		speed = XFER_SW_DMA_1;
+	} else if (id->dma_1word & 0x0001) {
+		if (!((id->dma_1word >> 8) & 1)) {
+			drive->id->dma_1word &= ~0x0F00;
+			drive->id->dma_1word |= 0x0101;
+			drive->id->dma_mword &= ~0x0F00;
+		}
+		speed = XFER_SW_DMA_0;
+        } else {
+		return ((int) ide_dma_off_quietly);
+	}
+
+	(void) hpt343_tune_chipset(drive, speed);
+
+	return ((int)	((id->dma_ultra >> 8) & 7) ? ide_dma_on :
+			((id->dma_mword >> 8) & 7) ? ide_dma_on :
+			((id->dma_1word >> 8) & 7) ? ide_dma_on :
+						     ide_dma_off_quietly);
+}
+
+static void config_chipset_for_pio (ide_drive_t *drive)
+{
+	unsigned short eide_pio_timing[6] = {960, 480, 240, 180, 120, 90};
+	unsigned short xfer_pio	= drive->id->eide_pio_modes;
+
+	byte			timing, speed, pio;
+
+	pio = ide_get_best_pio_mode(drive, 255, 5, NULL);
+
+	if (xfer_pio> 4)
+		xfer_pio = 0;
+
+	if (drive->id->eide_pio_iordy > 0) {
+		for (xfer_pio = 5;
+			xfer_pio>0 &&
+			drive->id->eide_pio_iordy>eide_pio_timing[xfer_pio];
+			xfer_pio--);
+	} else {
+		xfer_pio = (drive->id->eide_pio_modes & 4) ? 0x05 :
+			   (drive->id->eide_pio_modes & 2) ? 0x04 :
+			   (drive->id->eide_pio_modes & 1) ? 0x03 : xfer_pio;
+	}
+
+	timing = (xfer_pio >= pio) ? xfer_pio : pio;
+
+	switch(timing) {
+		case 4: speed = XFER_PIO_4;break;
+		case 3: speed = XFER_PIO_3;break;
+		case 2: speed = XFER_PIO_2;break;
+		case 1: speed = XFER_PIO_1;break;
+		default:
+			speed = (!drive->id->tPIO) ? XFER_PIO_0 : XFER_PIO_SLOW;
+			break;
+	}
+
+	(void) hpt343_tune_chipset(drive, speed);
+}
+
+#if 0
+static void hpt343_tune_drive (ide_drive_t *drive, byte pio)
+{
+}
+#endif
+
+static int config_drive_xfer_rate (ide_drive_t *drive)
+{
+	struct hd_driveid *id = drive->id;
+	ide_dma_action_t dma_func = ide_dma_on;
+
+	if (id && (id->capability & 1) && HWIF(drive)->autodma) {
+		/* Consult the list of known "bad" drives */
+		if (ide_dmaproc(ide_dma_bad_drive, drive)) {
+			dma_func = ide_dma_off;
+			goto fast_ata_pio;
+		}
+		dma_func = ide_dma_off_quietly;
+		if (id->field_valid & 4) {
+			if (id->dma_ultra & 0x0007) {
+				/* Force if Capable UltraDMA */
+				dma_func = config_chipset_for_dma(drive);
+				if ((id->field_valid & 2) &&
+				    (dma_func != ide_dma_on))
+					goto try_dma_modes;
+			}
+		} else if (id->field_valid & 2) {
+try_dma_modes:
+			if ((id->dma_mword & 0x0007) ||
+			    (id->dma_1word & 0x0007)) {
+				/* Force if Capable regular DMA modes */
+				dma_func = config_chipset_for_dma(drive);
+				if (dma_func != ide_dma_on)
+					goto no_dma_set;
+			}
+		} else if (ide_dmaproc(ide_dma_good_drive, drive)) {
+			if (id->eide_dma_time > 150) {
+				goto no_dma_set;
+			}
+			/* Consult the list of known "good" drives */
+			dma_func = config_chipset_for_dma(drive);
+			if (dma_func != ide_dma_on)
+				goto no_dma_set;
+		} else {
+			goto fast_ata_pio;
+		}
+	} else if ((id->capability & 8) || (id->field_valid & 2)) {
+fast_ata_pio:
+		dma_func = ide_dma_off_quietly;
+no_dma_set:
+
+		config_chipset_for_pio(drive);
+	}
+	return HWIF(drive)->dmaproc(dma_func, drive);
+}
+
+/*
+ * hpt343_dmaproc() initiates/aborts (U)DMA read/write operations on a drive.
+ *
+ * This is specific to the HPT343 UDMA bios-less chipset
+ * and HPT345 UDMA bios chipset (stamped HPT363)
+ * by HighPoint|Triones Technologies, Inc.
+ */
+
+int hpt343_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
+{
+	switch (func) {
+		case ide_dma_check:
+			hpt343_clear_chipset(drive);
+			return config_drive_xfer_rate(drive);
+#if 0
+		case ide_dma_off:
+		case ide_dma_off_quietly:
+		case ide_dma_on:
+		case ide_dma_check:
+			return config_drive_xfer_rate(drive);
+		case ide_dma_read:
+		case ide_dma_write:
+		case ide_dma_begin:
+		case ide_dma_end:
+		case ide_dma_test_irq:
+#endif
+		default:
+			break;
+	}
+	return ide_dmaproc(func, drive);	/* use standard DMA stuff */
+}
+
+/*
+ * If the BIOS does not set the IO base addaress to XX00, 343 will fail.
+ */
+#define	HPT343_PCI_INIT_REG		0x80
+
+__initfunc(unsigned int pci_init_hpt343 (struct pci_dev *dev, const char *name))
+{
+	int i;
+	unsigned short cmd;
+	unsigned long hpt343IoBase = dev->base_address[4] & PCI_BASE_ADDRESS_IO_MASK;
+#if 0
+	unsigned char misc10 = inb(hpt343IoBase + 0x0010);
+	unsigned char misc11 = inb(hpt343IoBase + 0x0011);
+#endif
+
+	pci_write_config_byte(dev, HPT343_PCI_INIT_REG, 0x00);
+	pci_read_config_word(dev, PCI_COMMAND, &cmd);
+	pci_write_config_word(dev, PCI_COMMAND, cmd & ~PCI_COMMAND_IO);
+
+	dev->base_address[0] = (hpt343IoBase + 0x20);
+	dev->base_address[1] = (hpt343IoBase + 0x34);
+	dev->base_address[2] = (hpt343IoBase + 0x28);
+	dev->base_address[3] = (hpt343IoBase + 0x3c);
+
+	for(i=0; i<4; i++)
+		dev->base_address[i] |= PCI_BASE_ADDRESS_SPACE_IO;
+
+	/*
+	 * Since 20-23 can be assigned and are R/W, we correct them.
+	 */
+	pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, dev->base_address[0]);
+	pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, dev->base_address[1]);
+	pci_write_config_dword(dev, PCI_BASE_ADDRESS_2, dev->base_address[2]);
+	pci_write_config_dword(dev, PCI_BASE_ADDRESS_3, dev->base_address[3]);
+	pci_write_config_word(dev, PCI_COMMAND, cmd);
+
+#if 0
+	outb(misc10|0x78, (hpt343IoBase + 0x0010));
+	outb(misc11, (hpt343IoBase + 0x0011));
+#endif
+
+#ifdef DEBUG
+	printk("%s: 0x%02x 0x%02x\n",
+		(pcicmd & PCI_COMMAND_MEMORY) ? "HPT345" : name,
+		inb(hpt343IoBase + 0x0010),
+		inb(hpt343IoBase + 0x0011));
+#endif
+
+	pci_write_config_byte(dev, HPT343_PCI_INIT_REG, 0x80);
+	if (cmd & PCI_COMMAND_MEMORY) {
+		if (dev->rom_address) {
+			pci_write_config_byte(dev, PCI_ROM_ADDRESS, dev->rom_address | PCI_ROM_ADDRESS_ENABLE);
+			printk(KERN_INFO "HPT345: ROM enabled at 0x%08lx\n", dev->rom_address);
+		}
+	} else {
+		pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20);
+	}
+	return dev->irq;
+}
+
+__initfunc(void ide_init_hpt343 (ide_hwif_t *hwif))
+{
+	if (hwif->dma_base) {
+		unsigned short pcicmd = 0;
+
+		pci_read_config_word(hwif->pci_dev, PCI_COMMAND, &pcicmd);
+		hwif->autodma = (pcicmd & PCI_COMMAND_MEMORY) ? 1 : 0;
+		hwif->dmaproc = &hpt343_dmaproc;
+	}
+}
diff -u --recursive --new-file v2.3.0/linux/drivers/block/ht6560b.c linux/drivers/block/ht6560b.c
--- v2.3.0/linux/drivers/block/ht6560b.c	Wed Jun 24 14:30:09 1998
+++ linux/drivers/block/ht6560b.c	Thu May 13 11:04:54 1999
@@ -57,8 +57,10 @@
 #include <linux/ioport.h>
 #include <linux/blkdev.h>
 #include <linux/hdreg.h>
+#include <linux/ide.h>
+
 #include <asm/io.h>
-#include "ide.h"
+
 #include "ide_modes.h"
 
 /*
diff -u --recursive --new-file v2.3.0/linux/drivers/block/ide-cd.c linux/drivers/block/ide-cd.c
--- v2.3.0/linux/drivers/block/ide-cd.c	Mon Apr 12 16:18:26 1999
+++ linux/drivers/block/ide-cd.c	Thu May 13 11:04:54 1999
@@ -258,13 +258,14 @@
 #include <linux/interrupt.h>
 #include <linux/errno.h>
 #include <linux/cdrom.h>
+#include <linux/ide.h>
+
 #include <asm/irq.h>
 #include <asm/io.h>
 #include <asm/byteorder.h>
 #include <asm/uaccess.h>
 #include <asm/unaligned.h>
 
-#include "ide.h"
 #include "ide-cd.h"
 
 /****************************************************************************
@@ -670,7 +671,8 @@
 
 	OUT_BYTE (xferlen & 0xff, IDE_LCYL_REG);
 	OUT_BYTE (xferlen >> 8  , IDE_HCYL_REG);
-	OUT_BYTE (drive->ctl, IDE_CONTROL_REG);
+	if (IDE_CONTROL_REG)
+		OUT_BYTE (drive->ctl, IDE_CONTROL_REG);
  
 	if (info->dma)
 		(void) (HWIF(drive)->dmaproc(ide_dma_begin, drive));
@@ -2940,7 +2942,19 @@
         else 	
         	printk (" drive");
 
-	printk (", %dkB Cache\n", ntohs(buf.cap.buffer_size));
+	printk (", %dkB Cache", ntohs(buf.cap.buffer_size));
+
+	if (drive->using_dma) {
+		if ((drive->id->field_valid & 4) &&
+		    (drive->id->dma_ultra & (drive->id->dma_ultra >> 8) & 7)) {
+			printk(", UDMA");	/* UDMA BIOS-enabled! */
+		} else if (drive->id->field_valid & 4) {
+			printk(", (U)DMA");	/* Can be BIOS-enabled! */
+		} else {
+			printk(", DMA");
+		}
+	}
+	printk("\n");
 
 	return nslots;
 }
@@ -2956,6 +2970,53 @@
 	ide_add_setting(drive,	"dsc_overlap",		SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1,	1, &drive->dsc_overlap, NULL);
 }
 
+#ifdef CONFIG_IDECD_SLOTS
+static void ide_cdrom_slot_check (ide_drive_t *drive, int nslots)
+{
+	tracktype tracks;
+	struct cdrom_info *info = drive->driver_data;
+	struct cdrom_device_info *devinfo = &info->devinfo;
+	int slot_count = 0, drive_stat = 0, tmp;
+
+	for (slot_count=0;slot_count<nslots;slot_count++) {
+		(void) ide_cdrom_select_disc(devinfo, slot_count);
+		printk("     CD Slot %d ", slot_count+1);
+
+		drive_stat = ide_cdrom_drive_status(devinfo, slot_count);
+		if (drive_stat<0) {
+			continue;
+		} else switch(drive_stat) {
+			case CDS_DISC_OK:
+				/* use routine in Uniform CD-ROM driver */
+				cdrom_count_tracks(devinfo, &tracks);
+				tmp = tracks.audio + tracks.data +
+					tracks.cdi + tracks.xa;
+				printk(": Disc has %d track%s: ", tmp,
+					(tmp == 1)? "" : "s");
+				printk("%d=data %d=audio %d=Cd-I %d=XA\n",
+					tracks.data, tracks.audio,
+					tracks.cdi, tracks.xa);
+				break;
+			case CDS_NO_DISC:
+				printk("Empty slot.\n");
+				break;
+			case CDS_TRAY_OPEN:
+				printk("CD-ROM tray open.\n");
+				break;
+			case CDS_DRIVE_NOT_READY:
+				printk("CD-ROM drive not ready.\n");
+				break;
+			case CDS_NO_INFO:
+				printk("No Information available.\n");
+				break;
+			default:
+				printk("This Should not happen!\n");
+				break;
+		}
+	}
+}
+#endif /* CONFIG_IDECD_SLOTS */
+
 static
 int ide_cdrom_setup (ide_drive_t *drive)
 {
@@ -3083,6 +3144,11 @@
 		return 1;
 	}
 	ide_cdrom_add_settings(drive);
+#ifdef CONFIG_IDECD_SLOTS
+	if (CDROM_CONFIG_FLAGS (drive)->is_changer) {
+		ide_cdrom_slot_check(drive, nslots);
+	}
+#endif /* CONFIG_IDECD_SLOTS */
 	return 0;
 }
 
diff -u --recursive --new-file v2.3.0/linux/drivers/block/ide-disk.c linux/drivers/block/ide-disk.c
--- v2.3.0/linux/drivers/block/ide-disk.c	Wed Mar 10 17:49:43 1999
+++ linux/drivers/block/ide-disk.c	Thu May 13 11:04:54 1999
@@ -1,5 +1,5 @@
 /*
- *  linux/drivers/block/ide-disk.c	Version 1.08  Dec   10, 1998
+ *  linux/drivers/block/ide-disk.c	Version 1.09  April 23, 1999
  *
  *  Copyright (C) 1994-1998  Linus Torvalds & authors (see below)
  */
@@ -25,12 +25,16 @@
  *			process of adding new ATA4 compliance.
  *			fixed problems in allowing fdisk to see
  *			the entire disk.
+ * Version 1.09		added increment of rq->sector in ide_multwrite
+ *			added UDMA 3/4 reporting
  */
 
-#define IDEDISK_VERSION	"1.08"
+#define IDEDISK_VERSION	"1.09"
 
 #undef REALLY_SLOW_IO		/* most systems can safely undef this */
 
+#define _IDE_DISK_C		/* Tell linux/hdsmart.h it's really us */
+
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/types.h>
@@ -44,14 +48,13 @@
 #include <linux/genhd.h>
 #include <linux/malloc.h>
 #include <linux/delay.h>
+#include <linux/ide.h>
 
 #include <asm/byteorder.h>
 #include <asm/irq.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 
-#include "ide.h"
-
 static void idedisk_bswap_data (void *buffer, int wcount)
 {
 	u16 *p = buffer;
@@ -101,6 +104,15 @@
 		id->cyls = lba_sects / (16 * 63); /* correct cyls */
 		return 1;	/* lba_capacity is our only option */
 	}
+	/*
+	 * ... and at least one TLA VBC has POS instead of brain and can't
+	 * tell 16 from 15.
+	 */
+	if ((id->lba_capacity >= 15481935) && (id->cyls == 0x3fff) &&
+	    (id->heads == 15) && (id->sectors == 63)) {
+		id->cyls = lba_sects / (15 * 63); /* correct cyls */
+		return 1;	/* lba_capacity is our only option */
+	}
 	/* perform a rough sanity check on lba_sects:  within 10% is "okay" */
 	if ((lba_sects - chs_sects) < _10_percent) {
 		return 1;	/* lba_capacity is good */
@@ -221,6 +233,9 @@
 			drive->name, rq->sector, (unsigned long) rq->buffer,
 			nsect, rq->nr_sectors - nsect);
 #endif
+#ifdef CONFIG_BLK_DEV_PDC4030
+		rq->sector += nsect;
+#endif
 		if ((rq->nr_sectors -= nsect) <= 0)
 			break;
 		if ((rq->current_nr_sectors -= nsect) == 0) {
@@ -279,7 +294,11 @@
 {
 	byte stat = GET_STAT();
 
+#if 0
+	if (OK_STAT(stat,READY_STAT,BAD_STAT) || drive->mult_req == 0) {
+#else
 	if (OK_STAT(stat,READY_STAT,BAD_STAT)) {
+#endif
 		drive->mult_count = drive->mult_req;
 	} else {
 		drive->mult_req = drive->mult_count = 0;
@@ -322,14 +341,21 @@
 	int use_pdc4030_io = 0;
 #endif /* CONFIG_BLK_DEV_PDC4030 */
 
-	OUT_BYTE(drive->ctl,IDE_CONTROL_REG);
+	if (IDE_CONTROL_REG)
+		OUT_BYTE(drive->ctl,IDE_CONTROL_REG);
 	OUT_BYTE(rq->nr_sectors,IDE_NSECTOR_REG);
 #ifdef CONFIG_BLK_DEV_PDC4030
+#ifdef CONFIG_BLK_DEV_PDC4030_TESTING
+	if (IS_PDC4030_DRIVE) {
+		use_pdc4030_io = 1;
+	}
+#else
 	if (IS_PDC4030_DRIVE) {
 		if (hwif->channel != 0 || rq->cmd == READ) {
 			use_pdc4030_io = 1;
 		}
 	}
+#endif /* CONFIG_BLK_DEV_PDC4030_TESTING */
 	if (drive->select.b.lba || use_pdc4030_io) {
 #else /* !CONFIG_BLK_DEV_PDC4030 */
 	if (drive->select.b.lba) {
@@ -760,9 +786,12 @@
 			drive->bios_cyl, drive->bios_head, drive->bios_sect);
 
 	if (drive->using_dma) {
-		if ((id->field_valid & 4) &&
-		    (id->dma_ultra & (id->dma_ultra >> 8) & 7)) {
-			printk(", UDMA");	/* UDMA BIOS-enabled! */
+		if  ((id->field_valid & 4) && (id->word93 & 0x2000) &&
+		     (id->dma_ultra & (id->dma_ultra >> 11) & 3)) {
+			printk(", UDMA(66)");	/* UDMA BIOS-enabled! */
+		} else if ((id->field_valid & 4) &&
+			   (id->dma_ultra & (id->dma_ultra >> 8) & 7)) {
+			printk(", UDMA(33)");	/* UDMA BIOS-enabled! */
 		} else if (id->field_valid & 4) {
 			printk(", (U)DMA");	/* Can be BIOS-enabled! */
 		} else {
@@ -786,17 +815,17 @@
 
 	drive->mult_count = 0;
 	if (id->max_multsect) {
-#if 1	/* original, pre IDE-NFG, per request of AC */
+#ifdef CONFIG_IDEDISK_MULTI_MODE
+		id->multsect = ((id->max_multsect/2) > 1) ? id->max_multsect : 0;
+		id->multsect_valid = id->multsect ? 1 : 0;
+		drive->mult_req = id->multsect_valid ? id->max_multsect : INITIAL_MULT_COUNT;
+		drive->special.b.set_multmode = drive->mult_req ? 1 : 0;
+#else	/* original, pre IDE-NFG, per request of AC */
 		drive->mult_req = INITIAL_MULT_COUNT;
 		if (drive->mult_req > id->max_multsect)
 			drive->mult_req = id->max_multsect;
 		if (drive->mult_req || ((id->multsect_valid & 1) && id->multsect))
 			drive->special.b.set_multmode = 1;
-#else
-		id->multsect = ((id->max_multsect/2) > 1) ? id->max_multsect : 0;
-		id->multsect_valid = id->multsect ? 1 : 0;
-		drive->mult_req = id->multsect_valid ? id->max_multsect : INITIAL_MULT_COUNT;
-		drive->special.b.set_multmode = drive->mult_req ? 1 : 0;
 #endif
 	}
 	drive->no_io_32bit = id->dword_io ? 1 : 0;
diff -u --recursive --new-file v2.3.0/linux/drivers/block/ide-dma.c linux/drivers/block/ide-dma.c
--- v2.3.0/linux/drivers/block/ide-dma.c	Sun Jan 17 18:23:01 1999
+++ linux/drivers/block/ide-dma.c	Thu May 13 11:04:54 1999
@@ -1,5 +1,12 @@
 /*
- *  linux/drivers/block/ide-dma.c	Version 4.08  December 31, 1997
+ *  linux/drivers/block/ide-dma.c	Version 4.09  April 23, 1999
+ *
+ *  Copyright (c) 1999  Andre Hedrick
+ *  May be copied or modified under the terms of the GNU General Public License
+ */
+
+/*
+ *  Special Thanks to Mark for his Six years of work.
  *
  *  Copyright (c) 1995-1998  Mark Lord
  *  May be copied or modified under the terms of the GNU General Public License
@@ -24,7 +31,7 @@
  *
  * Use "hdparm -i" to view modes supported by a given drive.
  *
- * The hdparm-2.4 (or later) utility can be used for manually enabling/disabling
+ * The hdparm-3.5 (or later) utility can be used for manually enabling/disabling
  * DMA support, but must be (re-)compiled against this kernel version or later.
  *
  * To enable DMA, use "hdparm -d1 /dev/hd?" on a per-drive basis after booting.
@@ -79,11 +86,51 @@
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/init.h>
+#include <linux/ide.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
 
-#include "ide.h"
+#define IDE_DMA_NEW_LISTINGS		0
+
+#if IDE_DMA_NEW_LISTINGS
+struct drive_list_entry {
+	char * id_model;
+	char * id_firmware;
+};
+
+struct drive_list_entry drive_whitelist [] = {
+
+	{ "Micropolis 2112A"	,       "ALL"		},
+	{ "CONNER CTMA 4000"	,       "ALL"		},
+	{ "CONNER CTT8000-A"	,       "ALL"		},
+	{ "ST34342A"		,	"ALL"		},
+	{ 0			,	0		}
+};
+
+struct drive_list_entry drive_blacklist [] = {
+
+	{ "WDC AC11000H"	,	"ALL"		},
+	{ "WDC AC22100H"	,	"ALL"		},
+	{ "WDC AC32500H"	,	"ALL"		},
+	{ "WDC AC33100H"	,	"ALL"		},
+	{ "WDC AC31600H"	,	"ALL"		},
+	{ "WDC AC32100H"	,	"24.09P07"	},
+	{ "WDC AC23200L"	,	"21.10N21"	},
+	{ 0			,	0		}
+
+};
+
+int in_drive_list(struct hd_driveid *id, struct drive_list_entry * drive_table)
+{
+	for ( ; drive_table->id_model ; drive_table++)
+		if ((!strcmp(drive_table->id_model, id->model)) &&
+		    ((!strstr(drive_table->id_firmware, id->fw_rev)) ||
+		     (!strcmp(drive_table->id_firmware, "ALL"))))
+			return 1;
+	return 0;
+}
+#else /* !IDE_DMA_NEW_LISTINGS */
 
 /*
  * good_dma_drives() lists the model names (from "hdparm -i")
@@ -109,11 +156,14 @@
  */
 const char *bad_dma_drives[] = {"WDC AC11000H",
 				"WDC AC22100H",
+				"WDC AC32100H",
 				"WDC AC32500H",
 				"WDC AC33100H",
 				"WDC AC31600H",
  				NULL};
 
+#endif /* IDE_DMA_NEW_LISTINGS */
+
 /*
  * Our Physical Region Descriptor (PRD) table should be large enough
  * to handle the biggest I/O request we are likely to see.  Since requests
@@ -164,11 +214,12 @@
  * Returns 0 if all went okay, returns 1 otherwise.
  * May also be invoked from trm290.c
  */
-int ide_build_dmatable (ide_drive_t *drive)
+int ide_build_dmatable (ide_drive_t *drive, ide_dma_action_t func)
 {
 	struct request *rq = HWGROUP(drive)->rq;
 	struct buffer_head *bh = rq->bh;
 	unsigned int size, addr, *table = (unsigned int *)HWIF(drive)->dmatable;
+	unsigned char *virt_addr;
 #ifdef CONFIG_BLK_DEV_TRM290
 	unsigned int is_trm290_chipset = (HWIF(drive)->chipset == ide_trm290);
 #else
@@ -185,11 +236,13 @@
 		 * than two possibly non-adjacent physical 4kB pages.
 		 */
 		if (bh == NULL) {  /* paging requests have (rq->bh == NULL) */
-			addr = virt_to_bus (rq->buffer);
+			virt_addr = rq->buffer;
+			addr = virt_to_bus (virt_addr);
 			size = rq->nr_sectors << 9;
 		} else {
 			/* group sequential buffers into one large buffer */
-			addr = virt_to_bus (bh->b_data);
+			virt_addr = bh->b_data;
+			addr = virt_to_bus (virt_addr);
 			size = bh->b_size;
 			while ((bh = bh->b_reqnext) != NULL) {
 				if ((addr + size) != virt_to_bus (bh->b_data))
@@ -206,6 +259,20 @@
 			printk("%s: misaligned DMA buffer\n", drive->name);
 			return 0;
 		}
+
+		/*
+		 * Some CPUs without cache snooping need to invalidate/write
+		 * back their caches before DMA transfers to guarantee correct
+		 * data.        -- rmk
+		 */
+		if (size) {
+			if (func == ide_dma_read) {
+				dma_cache_inv((unsigned int)virt_addr, size);
+			} else {
+				dma_cache_wback((unsigned int)virt_addr, size);
+			}
+		}
+
 		while (size) {
 			if (++count >= PRD_ENTRIES) {
 				printk("%s: DMA table too small\n", drive->name);
@@ -224,10 +291,17 @@
 			}
 		}
 	} while (bh != NULL);
-	if (!count)
+	if (!count) {
 		printk("%s: empty DMA table?\n", drive->name);
-	else if (!is_trm290_chipset)
-		*--table |= cpu_to_le32(0x80000000);	/* set End-Of-Table (EOT) bit */
+	} else {
+		if (!is_trm290_chipset)
+			*--table |= cpu_to_le32(0x80000000);	/* set End-Of-Table (EOT) bit */
+		/*
+		 * Some CPUs need to flush the DMA table to physical RAM
+		 * before DMA can start.        -- rmk
+		 */
+		dma_cache_wback((unsigned long)HWIF(drive)->dmatable, count * sizeof(unsigned int) * 2);
+	}
 	return count;
 }
 
@@ -238,9 +312,22 @@
  */
 int check_drive_lists (ide_drive_t *drive, int good_bad)
 {
-	const char **list;
 	struct hd_driveid *id = drive->id;
 
+#if IDE_DMA_NEW_LISTINGS
+
+	if (good_bad) {
+		return in_drive_list(id, drive_whitelist);
+	} else {
+		int blacklist = in_drive_list(id, drive_blacklist);
+		if (blacklist)
+			printk("%s: Disabling (U)DMA for %s\n", drive->name, id->model);
+		return(blacklist);
+	}
+#else /* !IDE_DMA_NEW_LISTINGS */
+
+	const char **list;
+
 	if (good_bad) {
 		/* Consult the list of known "good" drives */
 		list = good_dma_drives;
@@ -259,6 +346,7 @@
 			}
 		}
 	}
+#endif /* IDE_DMA_NEW_LISTINGS */
 	return 0;
 }
 
@@ -269,18 +357,24 @@
 
 	if (id && (id->capability & 1) && hwif->autodma) {
 		/* Consult the list of known "bad" drives */
-		if (check_drive_lists(drive, BAD_DMA_DRIVE))
+		if (ide_dmaproc(ide_dma_bad_drive, drive))
 			return hwif->dmaproc(ide_dma_off, drive);
+#if 0
+		/* Enable DMA on any drive that has UltraDMA (mode 3/4) enabled */
+		if ((id->field_valid & 4) && (id->word93 & 0x2000))
+			if ((id->dma_ultra & (id->dma_ultra >> 11) & 3))
+				return hwif->dmaproc(ide_dma_on, drive);
+#endif
 		/* Enable DMA on any drive that has UltraDMA (mode 0/1/2) enabled */
 		if (id->field_valid & 4)	/* UltraDMA */
-			if  ((id->dma_ultra & (id->dma_ultra >> 8) & 7))
+			if ((id->dma_ultra & (id->dma_ultra >> 8) & 7))
 				return hwif->dmaproc(ide_dma_on, drive);
 		/* Enable DMA on any drive that has mode2 DMA (multi or single) enabled */
 		if (id->field_valid & 2)	/* regular DMA */
 			if ((id->dma_mword & 0x404) == 0x404 || (id->dma_1word & 0x404) == 0x404)
 				return hwif->dmaproc(ide_dma_on, drive);
 		/* Consult the list of known "good" drives */
-		if (check_drive_lists(drive, GOOD_DMA_DRIVE))
+		if (ide_dmaproc(ide_dma_good_drive, drive))
 			return hwif->dmaproc(ide_dma_on, drive);
 	}
 	return hwif->dmaproc(ide_dma_off_quietly, drive);
@@ -321,7 +415,7 @@
 		case ide_dma_read:
 			reading = 1 << 3;
 		case ide_dma_write:
-			if (!(count = ide_build_dmatable(drive)))
+			if (!(count = ide_build_dmatable(drive, func)))
 				return 1;	/* try PIO instead of DMA */
 			outl(virt_to_bus(hwif->dmatable), dma_base + 4); /* PRD table */
 			outb(reading, dma_base);			/* specify r/w */
@@ -348,6 +442,9 @@
 		case ide_dma_test_irq: /* returns 1 if dma irq issued, 0 otherwise */
 			dma_stat = inb(dma_base+2);
 			return (dma_stat & 4) == 4;	/* return 1 if INTR asserted */
+		case ide_dma_bad_drive:
+		case ide_dma_good_drive:
+			return check_drive_lists(drive, (func == ide_dma_good_drive));
 		default:
 			printk("ide_dmaproc: unsupported func: %d\n", func);
 			return 1;
@@ -425,7 +522,7 @@
 	} else {
 		dma_base = dev->base_address[4] & PCI_BASE_ADDRESS_IO_MASK;
 		if (!dma_base || dma_base == PCI_BASE_ADDRESS_IO_MASK) {
-			printk("%s: dma_base is invalid (0x%04lx, BIOS problem), please report to <mj@ucw.cz>\n", name, dma_base);
+			printk("%s: dma_base is invalid (0x%04lx)\n", name, dma_base);
 			dma_base = 0;
 		}
 	}
@@ -434,9 +531,29 @@
 			request_region(dma_base+16, extra, name);
 		dma_base += hwif->channel ? 8 : 0;
 		hwif->dma_extra = extra;
-		if (inb(dma_base+2) & 0x80) {
-			printk("%s: simplex device:  DMA disabled\n", name);
-			dma_base = 0;
+
+		switch(dev->device) {
+			case PCI_DEVICE_ID_CMD_643:
+				/*
+				 * Lets attempt to use the same Ali tricks
+				 * to fix CMD643.....
+				 */
+			case PCI_DEVICE_ID_AL_M5219:
+			case PCI_DEVICE_ID_AL_M5229:
+				outb(inb(dma_base+2) & 0x60, dma_base+2);
+				/*
+				 * Ali 15x3 chipsets know as ALI IV and V report
+				 * this as simplex, skip this test for them.
+				 */
+				if (inb(dma_base+2) & 0x80) {
+					printk("%s: simplex device: DMA forced\n", name);
+				}
+				break;
+			default:
+				if (inb(dma_base+2) & 0x80) {
+					printk("%s: simplex device:  DMA disabled\n", name);
+					dma_base = 0;
+				}
 		}
 	}
 	return dma_base;
diff -u --recursive --new-file v2.3.0/linux/drivers/block/ide-floppy.c linux/drivers/block/ide-floppy.c
--- v2.3.0/linux/drivers/block/ide-floppy.c	Wed Dec 23 07:54:22 1998
+++ linux/drivers/block/ide-floppy.c	Thu May 13 11:04:54 1999
@@ -44,6 +44,7 @@
 #include <linux/genhd.h>
 #include <linux/malloc.h>
 #include <linux/cdrom.h>
+#include <linux/ide.h>
 
 #include <asm/byteorder.h>
 #include <asm/irq.h>
@@ -53,11 +54,6 @@
 #include <asm/bitops.h>
 
 /*
- *	Main Linux ide driver include file
- */
-#include "ide.h"
-
-/*
  *	The following are used to debug the driver.
  */
 #define IDEFLOPPY_DEBUG_LOG		0
@@ -1011,7 +1007,8 @@
 		dma_ok=!HWIF(drive)->dmaproc(test_bit (PC_WRITING, &pc->flags) ? ide_dma_write : ide_dma_read, drive);
 #endif /* CONFIG_BLK_DEV_IDEDMA */
 
-	OUT_BYTE (drive->ctl,IDE_CONTROL_REG);
+	if (IDE_CONTROL_REG)
+		OUT_BYTE (drive->ctl,IDE_CONTROL_REG);
 	OUT_BYTE (dma_ok ? 1:0,IDE_FEATURE_REG);			/* Use PIO/DMA */
 	OUT_BYTE (bcount.b.high,IDE_BCOUNTH_REG);
 	OUT_BYTE (bcount.b.low,IDE_BCOUNTL_REG);
diff -u --recursive --new-file v2.3.0/linux/drivers/block/ide-pci.c linux/drivers/block/ide-pci.c
--- v2.3.0/linux/drivers/block/ide-pci.c	Sun Jan 24 21:54:35 1999
+++ linux/drivers/block/ide-pci.c	Thu May 13 11:04:54 1999
@@ -1,5 +1,7 @@
 /*
- *  linux/drivers/block/ide-pci.c	Version 1.02  December 29, 1997
+ *  linux/drivers/block/ide-pci.c	Version 1.03  May 1, 1999
+ *
+ *  Copyright (c) 1998-1999  Andre Hedrick
  *
  *  Copyright (c) 1995-1998  Mark Lord
  *  May be copied or modified under the terms of the GNU General Public License
@@ -18,26 +20,28 @@
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/init.h>
+#include <linux/ide.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
 
-#include "ide.h"
-
 #define DEVID_PIIXa	((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82371FB_0})
 #define DEVID_PIIXb	((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82371FB_1})
 #define DEVID_PIIX3	((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82371SB_1})
 #define DEVID_PIIX4	((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82371AB})
 #define DEVID_VP_IDE	((ide_pci_devid_t){PCI_VENDOR_ID_VIA,     PCI_DEVICE_ID_VIA_82C586_1})
 #define DEVID_PDC20246	((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20246})
+#define DEVID_PDC20262	((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20262})
 #define DEVID_RZ1000	((ide_pci_devid_t){PCI_VENDOR_ID_PCTECH,  PCI_DEVICE_ID_PCTECH_RZ1000})
 #define DEVID_RZ1001	((ide_pci_devid_t){PCI_VENDOR_ID_PCTECH,  PCI_DEVICE_ID_PCTECH_RZ1001})
+#define DEVID_SAMURAI	((ide_pci_devid_t){PCI_VENDOR_ID_PCTECH,  PCI_DEVICE_ID_PCTECH_SAMURAI_IDE})
 #define DEVID_CMD640	((ide_pci_devid_t){PCI_VENDOR_ID_CMD,     PCI_DEVICE_ID_CMD_640})
+#define DEVID_CMD643	((ide_pci_devid_t){PCI_VENDOR_ID_CMD,     PCI_DEVICE_ID_CMD_643})
 #define DEVID_CMD646	((ide_pci_devid_t){PCI_VENDOR_ID_CMD,     PCI_DEVICE_ID_CMD_646})
 #define DEVID_SIS5513	((ide_pci_devid_t){PCI_VENDOR_ID_SI,      PCI_DEVICE_ID_SI_5513})
 #define DEVID_OPTI621	((ide_pci_devid_t){PCI_VENDOR_ID_OPTI,    PCI_DEVICE_ID_OPTI_82C621})
 #define DEVID_OPTI621V	((ide_pci_devid_t){PCI_VENDOR_ID_OPTI,    PCI_DEVICE_ID_OPTI_82C558})
-#define DEVID_OPTI621X	((ide_pci_devid_t){PCI_VENDOR_ID_OPTI,    0xd568})  /* from datasheets */
+#define DEVID_OPTI621X	((ide_pci_devid_t){PCI_VENDOR_ID_OPTI,    PCI_DEVICE_ID_OPTI_82C825})
 #define DEVID_TRM290	((ide_pci_devid_t){PCI_VENDOR_ID_TEKRAM,  PCI_DEVICE_ID_TEKRAM_DC290})
 #define DEVID_NS87410	((ide_pci_devid_t){PCI_VENDOR_ID_NS,      PCI_DEVICE_ID_NS_87410})
 #define DEVID_NS87415	((ide_pci_devid_t){PCI_VENDOR_ID_NS,      PCI_DEVICE_ID_NS_87415})
@@ -47,6 +51,10 @@
 #define DEVID_UM8886A	((ide_pci_devid_t){PCI_VENDOR_ID_UMC,     PCI_DEVICE_ID_UMC_UM8886A})
 #define DEVID_UM8886BF	((ide_pci_devid_t){PCI_VENDOR_ID_UMC,     PCI_DEVICE_ID_UMC_UM8886BF})
 #define DEVID_HPT343	((ide_pci_devid_t){PCI_VENDOR_ID_TTI,     PCI_DEVICE_ID_TTI_HPT343})
+#define DEVID_ALI15X3	((ide_pci_devid_t){PCI_VENDOR_ID_AL,      PCI_DEVICE_ID_AL_M5229})
+#define DEVID_CY82C693	((ide_pci_devid_t){PCI_VENDOR_ID_CONTAQ,  PCI_DEVICE_ID_CONTAQ_82C693})
+#define DEVID_HINT	((ide_pci_devid_t){0x3388,                0x8013})
+#define DEVID_CX5530	((ide_pci_devid_t){PCI_VENDOR_ID_CYRIX,   PCI_DEVICE_ID_CYRIX_5530_IDE})
 
 #define IDE_IGNORE	((void *)-1)
 
@@ -98,11 +106,68 @@
 
 #ifdef CONFIG_BLK_DEV_VIA82C586
 extern void ide_init_via82c586(ide_hwif_t *);
+extern void ide_dmacapable_via82c586(ide_hwif_t *, unsigned long dmabase);
 #define	INIT_VIA82C586	&ide_init_via82c586
+#define	DMA_VIA82C586	&ide_dmacapable_via82c586
 #else
 #define	INIT_VIA82C586	NULL
+#define	DMA_VIA82C586	NULL
+#endif
+
+#ifdef CONFIG_BLK_DEV_ALI15X3
+extern unsigned int pci_init_ali15x3(struct pci_dev *, const char *);
+extern void ide_init_ali15x3(ide_hwif_t *);
+#define PCI_ALI15X3	&pci_init_ali15x3
+#define	INIT_ALI15X3	&ide_init_ali15x3
+#else
+#define PCI_ALI15X3	NULL
+#define	INIT_ALI15X3	NULL
+#endif
+
+#ifdef CONFIG_BLK_DEV_CY82C693
+extern void ide_init_cy82c693(ide_hwif_t *);
+#define	INIT_CY82C693	&ide_init_cy82c693
+#else
+#define	INIT_CY82C693	NULL
+#endif
+
+#ifdef CONFIG_BLK_DEV_PDC202XX
+extern unsigned int pci_init_pdc202xx(struct pci_dev *, const char *);
+extern void ide_init_pdc202xx(ide_hwif_t *);
+#define PCI_PDC202XX	&pci_init_pdc202xx
+#define	INIT_PDC202XX	&ide_init_pdc202xx
+#else
+#define PCI_PDC202XX	NULL
+#define	INIT_PDC202XX	NULL
+#endif
+
+#ifdef CONFIG_BLK_DEV_PIIX
+extern void ide_init_piix(ide_hwif_t *);
+#define	INIT_PIIX	&ide_init_piix
+#else
+#define	INIT_PIIX	NULL
+#endif
+
+#ifdef CONFIG_BLK_DEV_AEC6210
+extern unsigned int pci_init_aec6210(struct pci_dev *, const char *);
+#define PCI_AEC6210	&pci_init_aec6210
+#else
+#define PCI_AEC6210	NULL
+#endif
+
+#ifdef CONFIG_BLK_DEV_HPT343
+extern unsigned int pci_init_hpt343(struct pci_dev *, const char *);
+extern void ide_init_hpt343(ide_hwif_t *);
+#define PCI_HPT343	&pci_init_hpt343
+#define	INIT_HPT343	&ide_init_hpt343
+#else
+#define PCI_HPT343	NULL
+#define	INIT_HPT343	NULL
 #endif
 
+#define INIT_SAMURAI	NULL
+#define INIT_CX5530	NULL
+
 typedef struct ide_pci_enablebit_s {
 	byte	reg;	/* byte pci reg holding the enable-bit */
 	byte	mask;	/* mask to isolate the enable-bit */
@@ -112,36 +177,45 @@
 typedef struct ide_pci_device_s {
 	ide_pci_devid_t		devid;
 	const char		*name;
+	unsigned int		(*init_chipset)(struct pci_dev *dev, const char *name);
 	void 			(*init_hwif)(ide_hwif_t *hwif);
+	void			(*dma_init)(ide_hwif_t *hwif, unsigned long dmabase);
 	ide_pci_enablebit_t	enablebits[2];
 	byte			bootable;
 	unsigned int		extra;
 } ide_pci_device_t;
 
 static ide_pci_device_t ide_pci_chipsets[] __initdata = {
-	{DEVID_PIIXa,	"PIIX",		NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}}, 	ON_BOARD,	0 },
-	{DEVID_PIIXb,	"PIIX",		NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}}, 	ON_BOARD,	0 },
-	{DEVID_PIIX3,	"PIIX3",	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}}, 	ON_BOARD,	0 },
-	{DEVID_PIIX4,	"PIIX4",	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}}, 	ON_BOARD,	0 },
-	{DEVID_VP_IDE,	"VP_IDE",	INIT_VIA82C586,	{{0x40,0x02,0x02}, {0x40,0x01,0x01}}, 	ON_BOARD,	0 },
-	{DEVID_PDC20246,"PDC20246",	NULL,		{{0x50,0x02,0x02}, {0x50,0x04,0x04}}, 	OFF_BOARD,	16 },
-	{DEVID_RZ1000,	"RZ1000",	INIT_RZ1000,	{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 },
-	{DEVID_RZ1001,	"RZ1001",	INIT_RZ1000,	{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 },
-	{DEVID_CMD640,	"CMD640",	IDE_IGNORE,	{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 },
-	{DEVID_NS87410,	"NS87410",	NULL,		{{0x43,0x08,0x08}, {0x47,0x08,0x08}}, 	ON_BOARD,	0 },
-	{DEVID_SIS5513,	"SIS5513",	NULL,		{{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, 	ON_BOARD,	0 },
-	{DEVID_CMD646,	"CMD646",	INIT_CMD646,	{{0x00,0x00,0x00}, {0x51,0x80,0x80}}, 	ON_BOARD,	0 },
-	{DEVID_HT6565,	"HT6565",	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 },
-	{DEVID_OPTI621,	"OPTI621",	INIT_OPTI621,	{{0x45,0x80,0x00}, {0x40,0x08,0x00}}, 	ON_BOARD,	0 },
-	{DEVID_OPTI621X,"OPTI621X",	INIT_OPTI621,	{{0x45,0x80,0x00}, {0x40,0x08,0x00}}, 	ON_BOARD,	0 },
-	{DEVID_TRM290,	"TRM290",	INIT_TRM290,	{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 },
-	{DEVID_NS87415,	"NS87415",	INIT_NS87415,	{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 },
-	{DEVID_AEC6210,	"AEC6210",	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	OFF_BOARD,	0 },
-	{DEVID_W82C105,	"W82C105",	INIT_W82C105,	{{0x40,0x01,0x01}, {0x40,0x10,0x10}}, 	ON_BOARD,	0 },
-	{DEVID_UM8886A,	"UM8886A",	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
-	{DEVID_UM8886BF,"UM8886BF",	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 },
-	{DEVID_HPT343,	"HPT343",	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	NEVER_BOARD,	16 },
-	{IDE_PCI_DEVID_NULL, "PCI_IDE",	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 }};
+	{DEVID_PIIXa,	"PIIX",		NULL,		INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}}, 	ON_BOARD,	0 },
+	{DEVID_PIIXb,	"PIIX",		NULL,		INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}}, 	ON_BOARD,	0 },
+	{DEVID_PIIX3,	"PIIX3",	NULL,		INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}}, 	ON_BOARD,	0 },
+	{DEVID_PIIX4,	"PIIX4",	NULL,		INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}}, 	ON_BOARD,	0 },
+	{DEVID_VP_IDE,	"VP_IDE",	NULL,		INIT_VIA82C586,	DMA_VIA82C586,	{{0x40,0x02,0x02}, {0x40,0x01,0x01}}, 	ON_BOARD,	0 },
+	{DEVID_PDC20246,"PDC20246",	PCI_PDC202XX,	INIT_PDC202XX,	NULL,		{{0x50,0x02,0x02}, {0x50,0x04,0x04}}, 	OFF_BOARD,	16 },
+	{DEVID_PDC20262,"PDC20262",	PCI_PDC202XX,	INIT_PDC202XX,	NULL,		{{0x50,0x02,0x02}, {0x50,0x04,0x04}},	OFF_BOARD,	48 },
+	{DEVID_RZ1000,	"RZ1000",	NULL,		INIT_RZ1000,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 },
+	{DEVID_RZ1001,	"RZ1001",	NULL,		INIT_RZ1000,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 },
+	{DEVID_SAMURAI,	"SAMURAI",	NULL,		INIT_SAMURAI,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
+	{DEVID_CMD640,	"CMD640",	NULL,		IDE_IGNORE,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 },
+	{DEVID_NS87410,	"NS87410",	NULL,		NULL,		NULL,		{{0x43,0x08,0x08}, {0x47,0x08,0x08}}, 	ON_BOARD,	0 },
+	{DEVID_SIS5513,	"SIS5513",	NULL,		NULL,		NULL,		{{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, 	ON_BOARD,	0 },
+	{DEVID_CMD643,	"CMD643",	NULL,		NULL,		NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
+	{DEVID_CMD646,	"CMD646",	NULL,		INIT_CMD646,	NULL,		{{0x00,0x00,0x00}, {0x51,0x80,0x80}}, 	ON_BOARD,	0 },
+	{DEVID_HT6565,	"HT6565",	NULL,		NULL,		NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 },
+	{DEVID_OPTI621,	"OPTI621",	NULL,		INIT_OPTI621,	NULL,		{{0x45,0x80,0x00}, {0x40,0x08,0x00}}, 	ON_BOARD,	0 },
+	{DEVID_OPTI621X,"OPTI621X",	NULL,		INIT_OPTI621,	NULL,		{{0x45,0x80,0x00}, {0x40,0x08,0x00}}, 	ON_BOARD,	0 },
+	{DEVID_TRM290,	"TRM290",	NULL,		INIT_TRM290,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 },
+	{DEVID_NS87415,	"NS87415",	NULL,		INIT_NS87415,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 },
+	{DEVID_AEC6210,	"AEC6210",	PCI_AEC6210,	NULL,		NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	OFF_BOARD,	0 },
+	{DEVID_W82C105,	"W82C105",	NULL,		INIT_W82C105,	NULL,		{{0x40,0x01,0x01}, {0x40,0x10,0x10}}, 	ON_BOARD,	0 },
+	{DEVID_UM8886A,	"UM8886A",	NULL,		NULL,		NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
+	{DEVID_UM8886BF,"UM8886BF",	NULL,		NULL,		NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 },
+	{DEVID_HPT343,	"HPT343",	PCI_HPT343,	INIT_HPT343,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	NEVER_BOARD,	16 },
+	{DEVID_ALI15X3,	"ALI15X3",	PCI_ALI15X3,	INIT_ALI15X3,	NULL,		{{0x09,0x20,0x20}, {0x09,0x10,0x10}},	ON_BOARD,	0 },
+	{DEVID_CY82C693,"CY82C693",	NULL,		INIT_CY82C693,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
+	{DEVID_HINT,	"HINT_IDE",	NULL,		NULL,		NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
+	{DEVID_CX5530,	"CX5530",	NULL,		INIT_CX5530,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
+	{IDE_PCI_DEVID_NULL, "PCI_IDE",	NULL,		NULL,		NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 }};
 
 /*
  * This allows offboard ide-pci cards the enable a BIOS, verify interrupt
@@ -151,27 +225,28 @@
 __initfunc(static unsigned int ide_special_settings (struct pci_dev *dev, const char *name))
 {
 	switch(dev->device) {
-		case PCI_DEVICE_ID_ARTOP_ATP850UF:
-		case PCI_DEVICE_ID_PROMISE_20246:
-			if (dev->rom_address) {
-				pci_write_config_byte(dev, PCI_ROM_ADDRESS,
-					dev->rom_address | PCI_ROM_ADDRESS_ENABLE);
-				printk(KERN_INFO "%s: ROM enabled at 0x%08lx\n", name, dev->rom_address);
-			}
-			
-			if ((dev->class >> 8) == PCI_CLASS_STORAGE_RAID) {
-				unsigned char irq1 = 0, irq2 = 0;
-
-				pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq1);
-				pci_read_config_byte(dev, (PCI_INTERRUPT_LINE)|0x80, &irq2);	/* 0xbc */
-				if (irq1 != irq2) {
-					printk("%s: IRQ1 %d IRQ2 %d\n",
-						name, irq1, irq2);
-					pci_write_config_byte(dev, (PCI_INTERRUPT_LINE)|0x80, irq1);	/* 0xbc */
-				}
-			}
-			return dev->irq;
 		case PCI_DEVICE_ID_TTI_HPT343:
+			{
+				int i;
+				unsigned short pcicmd = 0;
+				unsigned long hpt343IoBase = dev->base_address[4] & PCI_BASE_ADDRESS_IO_MASK;
+
+				pci_write_config_byte(dev, 0x80, 0x00);
+				dev->base_address[0] = (hpt343IoBase + 0x20);
+				dev->base_address[1] = (hpt343IoBase + 0x34);
+				dev->base_address[2] = (hpt343IoBase + 0x28);
+				dev->base_address[3] = (hpt343IoBase + 0x3c);
+				for(i=0; i<4; i++)
+					dev->base_address[i] |= PCI_BASE_ADDRESS_SPACE_IO;
+
+				pci_read_config_word(dev, PCI_COMMAND, &pcicmd);
+				pci_write_config_byte(dev, 0x80, 0x80);
+				if (!(pcicmd & PCI_COMMAND_MEMORY))
+					pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20);
+			}
+		case PCI_DEVICE_ID_PROMISE_20246:
+		case PCI_DEVICE_ID_PROMISE_20262:
+		case PCI_DEVICE_ID_ARTOP_ATP850UF:
 			return dev->irq;
 		default:
 			break;
@@ -269,7 +344,7 @@
 	 */
 	for (reg = 0; reg < 4; reg++)
 		if (!dev->base_address[reg]) {
-			printk("%s: Missing I/O address #%d, please report to <mj@ucw.cz>\n", name, reg);
+			printk("%s: Missing I/O address #%d\n", name, reg);
 			return 1;
 		}
 	return 0;
@@ -325,7 +400,13 @@
 	pciirq = dev->irq;
 	if ((dev->class & ~(0xfa)) != ((PCI_CLASS_STORAGE_IDE << 8) | 5)) {
 		printk("%s: not 100%% native mode: will probe irqs later\n", d->name);
-		pciirq = ide_special_settings(dev, d->name);
+		/*
+		 * This allows offboard ide-pci cards the enable a BIOS,
+		 * verify interrupt settings of split-mirror pci-config
+		 * space, place chipset into init-mode, and/or preserve
+		 * an interrupt if the card is not native ide support.
+		 */
+		pciirq = (d->init_chipset) ? d->init_chipset(dev, d->name) : ide_special_settings(dev, d->name);
 	} else if (tried_config) {
 		printk("%s: will probe irqs later\n", d->name);
 		pciirq = 0;
@@ -340,6 +421,19 @@
 		printk("%s: 100%% native mode on irq %d\n", d->name, pciirq);
 #endif
 	}
+	if (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT343)) {
+		/*
+		 * Since there are two cards that report almost identically,
+		 * the only discernable difference is the values
+		 * reported in pcicmd.
+		 * Booting-BIOS card or HPT363 :: pcicmd == 0x07
+		 * Non-bootable card or HPT343 :: pcicmd == 0x05
+		 */
+		if (pcicmd & PCI_COMMAND_MEMORY) {
+			printk("%s: is IDE Express HPT363.\n", d->name);
+			d->bootable = OFF_BOARD;
+		}
+	}
 	/*
 	 * Set up the IDE ports
 	 */
@@ -363,8 +457,8 @@
 		if ((hwif = ide_match_hwif(base, d->bootable, d->name)) == NULL)
 			continue;	/* no room in ide_hwifs[] */
 		if (hwif->io_ports[IDE_DATA_OFFSET] != base) {
-			ide_init_hwif_ports(hwif->io_ports, base, NULL);
-			hwif->io_ports[IDE_CONTROL_OFFSET] = ctl + 2;
+			ide_init_hwif_ports(&hwif->hw, base, (ctl + 2), NULL);
+			memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports));
 			hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET];
 		}
 		hwif->chipset = ide_pci;
@@ -382,8 +476,10 @@
 			}
 		}
 		if (IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8886A) ||
-		    IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8886BF))
+		    IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8886BF)) {
 			hwif->irq = hwif->channel ? 15 : 14;
+			goto bypass_umc_dma;
+		}
 
 #ifdef CONFIG_BLK_DEV_IDEDMA
 		if (IDE_PCI_DEVID_EQ(d->devid, DEVID_SIS5513))
@@ -391,8 +487,12 @@
 		if (autodma)
 			hwif->autodma = 1;
 		if (IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20246) ||
+		    IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20262) ||
 		    IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6210) ||
+#ifdef CONFIG_BLK_DEV_HPT343
 		    IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT343) ||
+#endif
+		    IDE_PCI_DEVID_EQ(d->devid, DEVID_CY82C693) ||
 		    ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && (dev->class & 0x80))) {
 			unsigned long dma_base = ide_get_or_set_dma_base(hwif, (!mate && d->extra) ? d->extra : 0, d->name);
 			if (dma_base && !(pcicmd & PCI_COMMAND_MASTER)) {
@@ -406,12 +506,18 @@
 					dma_base = 0;
 				}
 			}
-			if (dma_base)
-				ide_setup_dma(hwif, dma_base, 8);
-			else
+			if (dma_base) {
+				if (d->dma_init) {
+					d->dma_init(hwif, dma_base);
+				} else {
+					ide_setup_dma(hwif, dma_base, 8);
+				}
+			} else {
 				printk("%s: %s Bus-Master DMA disabled (BIOS)\n", hwif->name, d->name);
+			}
 		}
 #endif	/* CONFIG_BLK_DEV_IDEDMA */
+bypass_umc_dma:
 		if (d->init_hwif)  /* Call chipset-specific routine for each enabled hwif */
 			d->init_hwif(hwif);
 		mate = hwif;
@@ -441,6 +547,8 @@
 			printk("%s: ignored by ide_scan_pci_device() (uses own driver)\n", d->name);
 		else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_OPTI621V) && !(PCI_FUNC(dev->devfn) & 1))
 			continue;	/* OPTI Viper-M uses same devid for functions 0 and 1 */
+		else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_CY82C693) && (!(PCI_FUNC(dev->devfn) & 1) || !((dev->class >> 8) == PCI_CLASS_STORAGE_IDE)))
+			continue;	/* CY82C693 is more than only a IDE controller */
 		else if (!IDE_PCI_DEVID_EQ(d->devid, IDE_PCI_DEVID_NULL) || (dev->class >> 8) == PCI_CLASS_STORAGE_IDE) {
 			if (IDE_PCI_DEVID_EQ(d->devid, IDE_PCI_DEVID_NULL))
 				printk("%s: unknown IDE controller on PCI bus %02x device %02x, VID=%04x, DID=%04x\n",
diff -u --recursive --new-file v2.3.0/linux/drivers/block/ide-pmac.c linux/drivers/block/ide-pmac.c
--- v2.3.0/linux/drivers/block/ide-pmac.c	Wed Mar 10 21:48:46 1999
+++ linux/drivers/block/ide-pmac.c	Thu May 13 11:04:54 1999
@@ -21,6 +21,8 @@
 #include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/ide.h>
+
 #include <asm/prom.h>
 #include <asm/io.h>
 #include <asm/dbdma.h>
@@ -31,9 +33,9 @@
 #include <asm/adb.h>
 #include <asm/pmu.h>
 #endif
-#include "ide.h"
 #include "ide_modes.h"
 
+int pmac_ide_ports_known;
 ide_ioreg_t pmac_ide_regbase[MAX_HWIFS];
 int pmac_ide_irq[MAX_HWIFS];
 int pmac_ide_count;
@@ -58,24 +60,32 @@
  * N.B. this can't be an initfunc, because the media-bay task can
  * call ide_[un]register at any time.
  */
-void
-pmac_ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base, int *irq)
+void pmac_ide_init_hwif_ports (	hw_regs_t *hw,
+				ide_ioreg_t data_port,
+				ide_ioreg_t ctrl_port,
+				int *irq)
 {
+	ide_ioreg_t reg = ide_ioreg_t data_port;
 	int i, r;
 
-	*p = 0;
-	if (base == 0)
+	if (data_port == 0)
 		return;
 	/* we check only for -EINVAL meaning that we have found a matching
 	   bay but with the wrong device type */ 
 
-	r = check_media_bay_by_base(base, MB_CD);
+	r = check_media_bay_by_base(data_port, MB_CD);
 	if (r == -EINVAL)
 		return;
 		
-	for (i = 0; i < 8; ++i)
-		*p++ = base + i * 0x10;
-	*p = base + 0x160;
+	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+		hw->io_ports[i] = reg * 0x10;
+		reg += 1;
+	}
+	if (ctrl_port) {
+		hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
+	} else {
+		hw->io_ports[IDE_CONTROL_OFFSET] = hw->io_ports[IDE_DATA_OFFSET] + 0x160;
+	}
 	if (irq != NULL) {
 		*irq = 0;
 		for (i = 0; i < MAX_HWIFS; ++i) {
@@ -104,8 +114,7 @@
 	}
 }
 
-__initfunc(void
-pmac_ide_probe(void))
+__initfunc(void pmac_ide_probe(void))
 {
 	struct device_node *np;
 	int i;
@@ -172,7 +181,8 @@
 			feature_set(np, FEATURE_IDE_enable);
 
 		hwif = &ide_hwifs[i];
-		pmac_ide_init_hwif_ports(hwif->io_ports, base, &hwif->irq);
+		pmac_ide_init_hwif_ports(&hwif->hw, base, 0, &hwif->irq);
+		memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports));
 		hwif->chipset = ide_generic;
 		hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET];
 		hwif->tuneproc = pmac_ide_tuneproc;
diff -u --recursive --new-file v2.3.0/linux/drivers/block/ide-probe.c linux/drivers/block/ide-probe.c
--- v2.3.0/linux/drivers/block/ide-probe.c	Mon Mar 22 12:44:18 1999
+++ linux/drivers/block/ide-probe.c	Thu May 13 11:04:54 1999
@@ -18,6 +18,8 @@
  *			 by Andrea Arcangeli
  * Version 1.03		fix for (hwif->chipset == ide_4drives)
  * Version 1.04		fixed buggy treatments of known flash memory cards
+ *			fix for (hwif->chipset == ide_pdc4030)
+ *			added ide6/7
  */
 
 #undef REALLY_SLOW_IO		/* most systems can safely undef this */
@@ -35,14 +37,14 @@
 #include <linux/genhd.h>
 #include <linux/malloc.h>
 #include <linux/delay.h>
+#include <linux/ide.h>
+
 
 #include <asm/byteorder.h>
 #include <asm/irq.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 
-#include "ide.h"
-
 static inline void do_identify (ide_drive_t *drive, byte cmd)
 {
 	int bswap = 1;
@@ -148,17 +150,6 @@
 }
 
 /*
- * Delay for *at least* 50ms.  As we don't know how much time is left
- * until the next tick occurs, we wait an extra tick to be safe.
- * This is used only during the probing/polling for drives at boot time.
- */
-static void delay_50ms (void)
-{
-	unsigned long timeout = jiffies + ((HZ + 19)/20) + 1;
-	while (0 < (signed long)(timeout - jiffies));
-}
-
-/*
  * try_to_identify() sends an ATA(PI) IDENTIFY request to a drive
  * and waits for a response.  It also monitors irqs while this is
  * happening, in hope of automatically determining which one is
@@ -176,20 +167,26 @@
 	unsigned long irqs = 0;
 	byte s, a;
 
-	if (!HWIF(drive)->irq) {		/* already got an IRQ? */
-		probe_irq_off(probe_irq_on());	/* clear dangling irqs */
-		irqs = probe_irq_on();		/* start monitoring irqs */
-		OUT_BYTE(drive->ctl,IDE_CONTROL_REG);	/* enable device irq */
-	}
+	if (IDE_CONTROL_REG) {
+		if (!HWIF(drive)->irq) {		/* already got an IRQ? */
+			probe_irq_off(probe_irq_on());	/* clear dangling irqs */
+			irqs = probe_irq_on();		/* start monitoring irqs */
+			OUT_BYTE(drive->ctl,IDE_CONTROL_REG);	/* enable device irq */
+		}
 
-	delay_50ms();				/* take a deep breath */
-	a = IN_BYTE(IDE_ALTSTATUS_REG);
-	s = IN_BYTE(IDE_STATUS_REG);
-	if ((a ^ s) & ~INDEX_STAT) {
-		printk("%s: probing with STATUS(0x%02x) instead of ALTSTATUS(0x%02x)\n", drive->name, s, a);
-		hd_status = IDE_STATUS_REG;	/* ancient Seagate drives, broken interfaces */
-	} else
-		hd_status = IDE_ALTSTATUS_REG;	/* use non-intrusive polling */
+		ide_delay_50ms();				/* take a deep breath */
+		a = IN_BYTE(IDE_ALTSTATUS_REG);
+		s = IN_BYTE(IDE_STATUS_REG);
+		if ((a ^ s) & ~INDEX_STAT) {
+			printk("%s: probing with STATUS(0x%02x) instead of ALTSTATUS(0x%02x)\n", drive->name, s, a);
+			hd_status = IDE_STATUS_REG;	/* ancient Seagate drives, broken interfaces */
+		} else {
+			hd_status = IDE_ALTSTATUS_REG;	/* use non-intrusive polling */
+		}
+	} else {
+		ide_delay_50ms();
+		hd_status = IDE_STATUS_REG;
+	}
 
 #if CONFIG_BLK_DEV_PDC4030
 	if (IS_PDC4030_DRIVE) {
@@ -210,10 +207,10 @@
 				(void) probe_irq_off(irqs);
 			return 1;	/* drive timed-out */
 		}
-		delay_50ms();		/* give drive a breather */
+		ide_delay_50ms();		/* give drive a breather */
 	} while (IN_BYTE(hd_status) & BUSY_STAT);
 
-	delay_50ms();		/* wait for IRQ and DRQ_STAT */
+	ide_delay_50ms();		/* wait for IRQ and DRQ_STAT */
 	if (OK_STAT(GET_STAT(),DRQ_STAT,BAD_R_STAT)) {
 		unsigned long flags;
 		__save_flags(flags);	/* local CPU only */
@@ -224,7 +221,7 @@
 		__restore_flags(flags);	/* local CPU only */
 	} else
 		rc = 2;			/* drive refused ID */
-	if (!HWIF(drive)->irq) {
+	if (IDE_CONTROL_REG && !HWIF(drive)->irq) {
 		irqs = probe_irq_off(irqs);	/* get our irq number */
 		if (irqs > 0) {
 			HWIF(drive)->irq = irqs; /* save it for later */
@@ -280,11 +277,11 @@
 		(cmd == WIN_IDENTIFY) ? "ATA" : "ATAPI");
 #endif
 	SELECT_DRIVE(hwif,drive);
-	delay_50ms();
+	ide_delay_50ms();
 	if (IN_BYTE(IDE_SELECT_REG) != drive->select.all && !drive->present) {
 		if (drive->select.b.unit != 0) {
 			SELECT_DRIVE(hwif,&hwif->drives[0]);	/* exit with drive0 selected */
-			delay_50ms();		/* allow BUSY_STAT to assert & clear */
+			ide_delay_50ms();		/* allow BUSY_STAT to assert & clear */
 		}
 		return 3;    /* no i/f present: mmm.. this should be a 4 -ml */
 	}
@@ -297,13 +294,13 @@
 		if (rc == 1 && cmd == WIN_PIDENTIFY && drive->autotune != 2) {
 			unsigned long timeout;
 			printk("%s: no response (status = 0x%02x), resetting drive\n", drive->name, GET_STAT());
-			delay_50ms();
+			ide_delay_50ms();
 			OUT_BYTE (drive->select.all, IDE_SELECT_REG);
-			delay_50ms();
+			ide_delay_50ms();
 			OUT_BYTE(WIN_SRST, IDE_COMMAND_REG);
 			timeout = jiffies;
 			while ((GET_STAT() & BUSY_STAT) && time_before(jiffies, timeout + WAIT_WORSTCASE))
-				delay_50ms();
+				ide_delay_50ms();
 			rc = try_to_identify(drive, cmd);
 		}
 		if (rc == 1)
@@ -314,7 +311,7 @@
 	}
 	if (drive->select.b.unit != 0) {
 		SELECT_DRIVE(hwif,&hwif->drives[0]);	/* exit with drive0 selected */
-		delay_50ms();
+		ide_delay_50ms();
 		(void) GET_STAT();		/* ensure drive irq is clear */
 	}
 	return rc;
@@ -407,15 +404,40 @@
 	unsigned int unit;
 	unsigned long flags;
 
+	ide_ioreg_t ide_control_reg 	= hwif->io_ports[IDE_CONTROL_OFFSET];
+	ide_ioreg_t region_low 		= hwif->io_ports[IDE_DATA_OFFSET];
+	ide_ioreg_t region_high 	= region_low;
+	ide_ioreg_t region_request	= 8;
+	int i;
+
 	if (hwif->noprobe)
 		return;
 	if (hwif->io_ports[IDE_DATA_OFFSET] == HD_DATA)
 		probe_cmos_for_drives (hwif);
-	if ((hwif->chipset != ide_4drives || !hwif->mate->present)
+
+	/*
+	 * Calculate the region that this interface occupies,
+	 * handling interfaces where the registers may not be
+	 * ordered sanely.  We deal with the CONTROL register
+	 * separately.
+	 */
+	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+		if (hwif->io_ports[i]) {
+			if (hwif->io_ports[i] < region_low)
+				region_low = hwif->io_ports[i];
+			if (hwif->io_ports[i] > region_high)
+				region_high = hwif->io_ports[i];
+		}
+	}
+	region_request = (region_high - region_low);
+	if (region_request == 0x0007)
+		region_request++;
+	if ((hwif->chipset != ide_4drives || !hwif->mate->present) &&
 #if CONFIG_BLK_DEV_PDC4030
-	 && (hwif->chipset != ide_pdc4030 || hwif->channel == 0)
+	    (hwif->chipset != ide_pdc4030 || hwif->channel == 0) &&
 #endif /* CONFIG_BLK_DEV_PDC4030 */
-	 && (ide_check_region(hwif->io_ports[IDE_DATA_OFFSET],8) || ide_check_region(hwif->io_ports[IDE_CONTROL_OFFSET],1)))
+	    (ide_check_region(region_low, region_request) ||
+	    (ide_control_reg && ide_check_region(ide_control_reg,1))))
 	{
 		int msgout = 0;
 		for (unit = 0; unit < MAX_DRIVES; ++unit) {
@@ -443,21 +465,22 @@
 		if (drive->present && !hwif->present) {
 			hwif->present = 1;
 			if (hwif->chipset != ide_4drives || !hwif->mate->present) {
-				ide_request_region(hwif->io_ports[IDE_DATA_OFFSET],  8, hwif->name);
-				ide_request_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1, hwif->name);
+				ide_request_region(region_low, region_request, hwif->name);
+				if (ide_control_reg)
+					ide_request_region(ide_control_reg, 1, hwif->name);
 			}
 		}
 	}
-	if (hwif->reset) {
+	if (ide_control_reg && hwif->reset) {
 		unsigned long timeout = jiffies + WAIT_WORSTCASE;
 		byte stat;
 
 		printk("%s: reset\n", hwif->name);
-		OUT_BYTE(12, hwif->io_ports[IDE_CONTROL_OFFSET]);
+		OUT_BYTE(12, ide_control_reg);
 		udelay(10);
-		OUT_BYTE(8, hwif->io_ports[IDE_CONTROL_OFFSET]);
+		OUT_BYTE(8, ide_control_reg);
 		do {
-			delay_50ms();
+			ide_delay_50ms();
 			stat = IN_BYTE(hwif->io_ports[IDE_STATUS_OFFSET]);
 		} while ((stat & BUSY_STAT) && 0 < (signed long)(timeout - jiffies));
 
@@ -660,7 +683,11 @@
 	max_readahead[hwif->major] = max_ra;
 	for (unit = 0; unit < minors; ++unit) {
 		*bs++ = BLOCK_SIZE;
+#ifdef CONFIG_BLK_DEV_PDC4030
+		*max_sect++ = ((hwif->chipset == ide_pdc4030) ? 127 : MAX_SECTORS);
+#else
 		*max_sect++ = MAX_SECTORS;
+#endif
 		*max_ra++ = MAX_READAHEAD;
 	}
 
@@ -693,7 +720,8 @@
 	if (!hwif->present)
 		return 0;
 	if (!hwif->irq) {
-		if (!(hwif->irq = ide_default_irq(hwif->io_ports[IDE_DATA_OFFSET]))) {
+		if (!(hwif->irq = ide_default_irq(hwif->io_ports[IDE_DATA_OFFSET])))
+		{
 			printk("%s: DISABLED, NO IRQ\n", hwif->name);
 			return (hwif->present = 0);
 		}
@@ -722,6 +750,12 @@
 #endif
 #if MAX_HWIFS > 5
 	case IDE5_MAJOR: rfn = &do_ide5_request; break;
+#endif
+#if MAX_HWIFS > 6
+	case IDE6_MAJOR: rfn = &do_ide6_request; break;
+#endif
+#if MAX_HWIFS > 7
+	case IDE7_MAJOR: rfn = &do_ide7_request; break;
 #endif
 	default:
 		printk("%s: request_fn NOT DEFINED\n", hwif->name);
diff -u --recursive --new-file v2.3.0/linux/drivers/block/ide-proc.c linux/drivers/block/ide-proc.c
--- v2.3.0/linux/drivers/block/ide-proc.c	Wed May  6 14:42:53 1998
+++ linux/drivers/block/ide-proc.c	Thu May 13 11:04:54 1999
@@ -65,13 +65,22 @@
 #include <linux/mm.h>
 #include <linux/pci.h>
 #include <linux/ctype.h>
+#include <linux/ide.h>
+
 #include <asm/io.h>
-#include "ide.h"
 
 #ifndef MIN
 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
 #endif
 
+#ifdef CONFIG_BLK_DEV_VIA82C586
+int (*via_display_info)(char *, char **, off_t, int, int) = NULL;
+#endif /* CONFIG_BLK_DEV_VIA82C586 */
+
+#ifdef CONFIG_BLK_DEV_ALI15X3
+int (*ali_display_info)(char *, char **, off_t, int, int) = NULL;
+#endif /* CONFIG_BLK_DEV_ALI15X3 */
+
 static int ide_getxdigit(char c)
 {
 	int digit;
@@ -682,6 +691,18 @@
 	ent = create_proc_entry("drivers", 0, root);
 	if (!ent) return;
 	ent->read_proc  = proc_ide_read_drivers;
+#ifdef CONFIG_BLK_DEV_VIA82C586
+	if (via_display_info) {
+		ent = create_proc_entry("via", 0, root);
+		ent->get_info = via_display_info;
+	}
+#endif /* CONFIG_BLK_DEV_VIA82C586 */
+#ifdef CONFIG_BLK_DEV_ALI15X3
+	if (ali_display_info) {
+		ent = create_proc_entry("ali", 0, root);
+		ent->get_info = ali_display_info;
+	}
+#endif /* CONFIG_BLK_DEV_ALI15X3 */
 }
 
 void proc_ide_destroy(void)
@@ -690,6 +711,14 @@
 	 * Mmmm.. does this free up all resources,
 	 * or do we need to do a more proper cleanup here ??
 	 */
+#ifdef CONFIG_BLK_DEV_VIA82C586
+	if (via_display_info)
+		remove_proc_entry("ide/via",0);
+#endif /* CONFIG_BLK_DEV_VIA82C586 */
+#ifdef CONFIG_BLK_DEV_ALI15X3
+	if (ali_display_info)
+		remove_proc_entry("ide/ali",0);
+#endif /* CONFIG_BLK_DEV_ALI15X3 */
 	remove_proc_entry("ide/drivers", 0);
 	remove_proc_entry("ide", 0);
 }
diff -u --recursive --new-file v2.3.0/linux/drivers/block/ide-tape.c linux/drivers/block/ide-tape.c
--- v2.3.0/linux/drivers/block/ide-tape.c	Fri Jan  8 10:04:58 1999
+++ linux/drivers/block/ide-tape.c	Thu May 13 11:04:54 1999
@@ -338,6 +338,8 @@
 #include <linux/errno.h>
 #include <linux/genhd.h>
 #include <linux/malloc.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
 
 #include <asm/byteorder.h>
 #include <asm/irq.h>
@@ -347,11 +349,6 @@
 #include <asm/bitops.h>
 
 /*
- *	Main Linux ide driver include file
- */
-#include "ide.h"
-
-/*
  *	For general magnetic tape device compatibility.
  */
 #include <linux/mtio.h>
@@ -401,6 +398,7 @@
 /*
  *	The following are used to debug the driver:
  *
+ *	Setting IDETAPE_INFO_LOG to 1 will log driver vender information.
  *	Setting IDETAPE_DEBUG_LOG to 1 will log driver flow control.
  *	Setting IDETAPE_DEBUG_BUGS to 1 will enable self-sanity checks in
  *	some places.
@@ -415,9 +413,15 @@
  *	is verified to be stable enough. This will make it much more
  *	esthetic.
  */
+#define IDETAPE_INFO_LOG		0
 #define IDETAPE_DEBUG_LOG		0
 #define IDETAPE_DEBUG_BUGS		1
 
+#if IDETAPE_DEBUG_LOG
+#undef IDETAPE_INFO_LOG
+#define IDETAPE_INFO_LOG		IDETAPE_DEBUG_LOG
+#endif
+
 /*
  *	After each failed packet command we issue a request sense command
  *	and retry the packet command IDETAPE_MAX_PC_RETRIES times.
@@ -1968,7 +1972,8 @@
 		dma_ok=!HWIF(drive)->dmaproc(test_bit (PC_WRITING, &pc->flags) ? ide_dma_write : ide_dma_read, drive);
 #endif /* CONFIG_BLK_DEV_IDEDMA */
 
-	OUT_BYTE (drive->ctl,IDE_CONTROL_REG);
+	if (IDE_CONTROL_REG)
+		OUT_BYTE (drive->ctl,IDE_CONTROL_REG);
 	OUT_BYTE (dma_ok ? 1:0,IDE_FEATURE_REG);			/* Use PIO/DMA */
 	OUT_BYTE (bcount.b.high,IDE_BCOUNTH_REG);
 	OUT_BYTE (bcount.b.low,IDE_BCOUNTL_REG);
@@ -2334,7 +2339,7 @@
  */
 static void idetape_wait_for_request (ide_drive_t *drive, struct request *rq)
 {
-	struct semaphore sem = MUTEX_LOCKED;
+	DECLARE_MUTEX_LOCKED(sem);
 
 #if IDETAPE_DEBUG_BUGS
 	if (rq == NULL || !IDETAPE_RQ_CMD (rq->cmd)) {
@@ -3337,16 +3342,16 @@
 static int idetape_identify_device (ide_drive_t *drive,struct hd_driveid *id)
 {
 	struct idetape_id_gcw gcw;
-#if IDETAPE_DEBUG_LOG
+#if IDETAPE_INFO_LOG
 	unsigned short mask,i;
-#endif /* IDETAPE_DEBUG_LOG */
+#endif /* IDETAPE_INFO_LOG */
 
 	if (!id)
 		return 0;
 
 	*((unsigned short *) &gcw) = id->config;
 
-#if IDETAPE_DEBUG_LOG
+#if IDETAPE_INFO_LOG
 	printk (KERN_INFO "Dumping ATAPI Identify Device tape parameters\n");
 	printk (KERN_INFO "Protocol Type: ");
 	switch (gcw.protocol) {
@@ -3434,7 +3439,7 @@
 		
 	} else
 		printk (KERN_INFO "According to the device, fields 64-70 are not valid.\n");
-#endif /* IDETAPE_DEBUG_LOG */
+#endif /* IDETAPE_INFO_LOG */
 
 	/* Check that we can support this device */
 
@@ -3491,7 +3496,7 @@
 
 	tape->capabilities = *capabilities;		/* Save us a copy */
 	tape->tape_block_size = capabilities->blk512 ? 512:1024;
-#if IDETAPE_DEBUG_LOG
+#if IDETAPE_INFO_LOG
 	printk (KERN_INFO "Dumping the results of the MODE SENSE packet command\n");
 	printk (KERN_INFO "Mode Parameter Header:\n");
 	printk (KERN_INFO "Mode Data Length - %d\n",header->mode_data_length);
@@ -3519,7 +3524,7 @@
 	printk (KERN_INFO "Continuous transfer limits in blocks - %d\n",capabilities->ctl);
 	printk (KERN_INFO "Current speed in KBps - %d\n",capabilities->speed);	
 	printk (KERN_INFO "Buffer size - %d\n",capabilities->buffer_size*512);
-#endif /* IDETAPE_DEBUG_LOG */
+#endif /* IDETAPE_INFO_LOG */
 }
 
 static void idetape_add_settings(ide_drive_t *drive)
@@ -3561,7 +3566,18 @@
 
 	drive->driver_data = tape;
 	drive->ready_stat = 0;			/* An ATAPI device ignores DRDY */
-	drive->dsc_overlap = 1;
+#ifdef CONFIG_BLK_DEV_IDEPCI
+	/*
+	 *  These two ide-pci host adapters appear to need this disabled.
+	 */
+	if ((hwif->pci_dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) ||
+	    (hwif->pci_dev->device == PCI_DEVICE_ID_TTI_HPT343)) {
+		drive->dsc_overlap = 0;
+	} else
+#endif  /* CONFIG_BLK_DEV_IDEPCI */
+	{
+		drive->dsc_overlap = 1;
+	}
 	memset (tape, 0, sizeof (idetape_tape_t));
 	tape->drive = drive;
 	tape->minor = minor;
diff -u --recursive --new-file v2.3.0/linux/drivers/block/ide.c linux/drivers/block/ide.c
--- v2.3.0/linux/drivers/block/ide.c	Mon May  3 09:34:51 1999
+++ linux/drivers/block/ide.c	Thu May 13 11:31:31 1999
@@ -1,5 +1,5 @@
 /*
- *  linux/drivers/block/ide.c	Version 6.18  August 16, 1998
+ *  linux/drivers/block/ide.c	Version 6.19  January 29, 1999
  *
  *  Copyright (C) 1994-1998  Linus Torvalds & authors (see below)
  */
@@ -92,6 +92,11 @@
  * Version 6.16		fixed various bugs; even more SMP friendly
  * Version 6.17		fix for newest EZ-Drive problem
  * Version 6.18		default unpartitioned-disk translation now "BIOS LBA"
+ * Version 6.19		Re-design for a UNIFORM driver for all platforms,
+ *			model based on suggestions from Russell King and
+ *			Geert Uytterhoeven
+ *			Promise DC4030VL now supported.
+ *			delay_50ms() changed to ide_delay_50ms() and exported.
  *
  *  Some additional driver compile-time options are in ide.h
  *
@@ -99,6 +104,9 @@
  *	- modify kernel to obtain BIOS geometry for drives on 2nd/3rd/4th i/f
 */
 
+#define	REVISION	"Revision: 6.19"
+#define	VERSION		"Id: ide.c 6.19 1999/01/29"
+
 #undef REALLY_SLOW_IO		/* most systems can safely undef this */
 
 #define _IDE_C			/* Tell ide.h it's really us */
@@ -117,6 +125,7 @@
 #include <linux/malloc.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
+#include <linux/ide.h>
 
 #include <asm/byteorder.h>
 #include <asm/irq.h>
@@ -124,24 +133,29 @@
 #include <asm/io.h>
 #include <asm/bitops.h>
 
-#include "ide.h"
 #include "ide_modes.h"
 
 #ifdef CONFIG_KMOD
 #include <linux/kmod.h>
 #endif /* CONFIG_KMOD */
 
-static const byte	ide_hwif_to_major[] = {IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR, IDE4_MAJOR, IDE5_MAJOR };
+#ifdef CONFIG_BLK_DEV_VIA82C586
+extern byte fifoconfig;           /* defined in via82c586.c used by ide_setup()*/
+#endif
+
+static const byte	ide_hwif_to_major[] = {IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR, IDE4_MAJOR, IDE5_MAJOR, IDE6_MAJOR, IDE7_MAJOR };
 
 static int	idebus_parameter; /* holds the "idebus=" parameter */
 static int	system_bus_speed; /* holds what we think is VESA/PCI bus speed */
 static int	initializing;     /* set while initializing built-in drivers */
 
+#if defined(__mc68000__) || defined(CONFIG_APUS)
 /*
  * ide_lock is used by the Atari code to obtain access to the IDE interrupt,
  * which is shared between several drivers.
  */
 static int	ide_lock = 0;
+#endif /* __mc68000__ || CONFIG_APUS */
 
 /*
  * ide_modules keeps track of the available IDE chipset/probe/driver modules.
@@ -187,14 +201,18 @@
 static void init_hwif_data (unsigned int index)
 {
 	unsigned int unit;
+	hw_regs_t hw;
 	ide_hwif_t *hwif = &ide_hwifs[index];
 
 	/* bulk initialize hwif & drive info with zeros */
 	memset(hwif, 0, sizeof(ide_hwif_t));
+	memset(&hw, 0, sizeof(hw_regs_t));
 
 	/* fill in any non-zero initial values */
 	hwif->index     = index;
-	ide_init_hwif_ports(hwif->io_ports, ide_default_io_base(index), &hwif->irq);
+	ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, &hwif->irq);
+	memcpy(&hwif->hw, &hw, sizeof(hw));
+	memcpy(hwif->io_ports, hw.io_ports, sizeof(hw.io_ports));
 	hwif->noprobe	= !hwif->io_ports[IDE_DATA_OFFSET];
 #ifdef CONFIG_BLK_DEV_HD
 	if (hwif->io_ports[IDE_DATA_OFFSET] == HD_DATA)
@@ -211,6 +229,7 @@
 		drive->media			= ide_disk;
 		drive->select.all		= (unit<<4)|0xa0;
 		drive->hwif			= hwif;
+		init_waitqueue_head(&drive->wqueue);
 		drive->ctl			= 0x08;
 		drive->ready_stat		= READY_STAT;
 		drive->bad_wstat		= BAD_W_STAT;
@@ -219,6 +238,7 @@
 		drive->name[0]			= 'h';
 		drive->name[1]			= 'd';
 		drive->name[2]			= 'a' + (index * MAX_DRIVES) + unit;
+		init_waitqueue_head(&drive->wqueue);
 	}
 }
 
@@ -246,9 +266,13 @@
 		return;		/* already initialized */
 	magic_cookie = 0;
 
+	/* Initialise all interface structures */
 	for (index = 0; index < MAX_HWIFS; ++index)
 		init_hwif_data(index);
 
+	/* Add default hw interfaces */
+	ide_init_default_hwifs();
+
 	idebus_parameter = 0;
 	system_bus_speed = 0;
 }
@@ -652,6 +676,10 @@
 		pre_reset(&hwif->drives[unit]);
 
 #if OK_TO_RESET_CONTROLLER
+	if (!IDE_CONTROL_REG) {
+		__restore_flags(flags);
+		return;
+	}
 	/*
 	 * Note that we also set nIEN while resetting the device,
 	 * to mask unwanted interrupts from the interface during the reset.
@@ -857,7 +885,8 @@
 void ide_cmd(ide_drive_t *drive, byte cmd, byte nsect, ide_handler_t *handler)
 {
 	ide_set_handler (drive, handler, WAIT_CMD);
-	OUT_BYTE(drive->ctl,IDE_CONTROL_REG);	/* clear nIEN */
+	if (IDE_CONTROL_REG)
+		OUT_BYTE(drive->ctl,IDE_CONTROL_REG);	/* clear nIEN */
 	OUT_BYTE(nsect,IDE_NSECTOR_REG);
 	OUT_BYTE(cmd,IDE_COMMAND_REG);
 }
@@ -1253,6 +1282,20 @@
 }
 #endif /* MAX_HWIFS > 5 */
 
+#if MAX_HWIFS > 6
+void do_ide6_request (void)
+{
+	unlock_do_hwgroup_request (ide_hwifs[6].hwgroup);
+}
+#endif /* MAX_HWIFS > 6 */
+
+#if MAX_HWIFS > 7
+void do_ide7_request (void)
+{
+	unlock_do_hwgroup_request (ide_hwifs[7].hwgroup);
+}
+#endif /* MAX_HWIFS > 7 */
+
 static void start_next_request (ide_hwgroup_t *hwgroup, int masked_irq)
 {
 	unsigned long	flags;
@@ -1370,6 +1413,12 @@
 	__cli();	/* local CPU only */
 	spin_lock_irqsave(&hwgroup->spinlock, flags);
 	hwif = hwgroup->hwif;
+
+	if (!ide_ack_intr(hwif)) {
+		spin_unlock_irqrestore(&hwgroup->spinlock, flags);
+		return;
+	}
+
 	if ((handler = hwgroup->handler) == NULL || hwgroup->poll_timeout != 0) {
 		/*
 		 * Not expecting an interrupt from this drive.
@@ -1391,7 +1440,6 @@
 			 * Probably not a shared PCI interrupt,
 			 * so we can safely try to do something about it:
 			 */
-			(void)ide_ack_intr(hwif->io_ports[IDE_STATUS_OFFSET], hwif->io_ports[IDE_IRQ_OFFSET]);
 			unexpected_intr(irq, hwgroup);
 		}
 		spin_unlock_irqrestore(&hwgroup->spinlock, flags);
@@ -1403,7 +1451,6 @@
 		return;
 	}
 	hwgroup->handler = NULL;
-	(void)ide_ack_intr(hwif->io_ports[IDE_STATUS_OFFSET], hwif->io_ports[IDE_IRQ_OFFSET]);
 	del_timer(&(hwgroup->timer));
 	spin_unlock_irqrestore(&hwgroup->spinlock, flags);
 	if (drive->unmask)
@@ -1490,7 +1537,7 @@
 	ide_hwgroup_t *hwgroup = HWGROUP(drive);
 	unsigned int major = HWIF(drive)->major;
 	struct request *cur_rq;
-	struct semaphore sem = MUTEX_LOCKED;
+	DECLARE_MUTEX_LOCKED(sem);
 
 	if (IS_PDC4030_DRIVE && rq->buffer != NULL)
 		return -ENOSYS;  /* special drive cmds not supported */
@@ -1696,6 +1743,7 @@
 	ide_hwgroup_t *hwgroup;
 	int irq_count = 0, unit, i;
 	unsigned long flags;
+	unsigned int p, minor;
 
 	if (index >= MAX_HWIFS)
 		return;
@@ -1714,6 +1762,24 @@
 			goto abort;
 	}
 	hwif->present = 0;
+	
+	/*
+	 * All clear?  Then blow away the buffer cache
+	 */
+	sti();
+	for (unit = 0; unit < MAX_DRIVES; ++unit) {
+		drive = &hwif->drives[unit];
+		minor = drive->select.b.unit << PARTN_BITS;
+		for (p = 0; p < (1<<PARTN_BITS); ++p) {
+			if (drive->part[p].nr_sects > 0) {
+				kdev_t devp = MKDEV(hwif->major, minor+p);
+				struct super_block * sb = get_super(devp);
+				if (sb) invalidate_inodes(sb);
+				invalidate_buffers (devp);
+			}
+		}
+	}
+	cli();
 	hwgroup = hwif->hwgroup;
 
 	/*
@@ -1734,7 +1800,8 @@
 	 * allocated for weird IDE interface chipsets.
 	 */
 	ide_release_region(hwif->io_ports[IDE_DATA_OFFSET], 8);
-	ide_release_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1);
+	if (hwif->io_ports[IDE_CONTROL_OFFSET])
+		ide_release_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1);
 
 	/*
 	 * Remove us from the hwgroup, and free
@@ -1798,21 +1865,58 @@
 	restore_flags(flags);	/* all CPUs */
 }
 
-int ide_register (int arg1, int arg2, int irq)
+/*
+ * Setup hw_regs_t structure described by parameters.  You
+ * may set up the hw structure yourself OR use this routine to
+ * do it for you.
+ */
+void ide_setup_ports (	hw_regs_t *hw,
+			ide_ioreg_t base, int *offsets,
+			ide_ioreg_t ctrl, ide_ioreg_t intr,
+			ide_ack_intr_t *ack_intr, int irq)
+{
+	int i;
+
+	for (i = 0; i < IDE_NR_PORTS; i++) {
+		if (offsets[i] == -1) {
+			switch(i) {
+				case IDE_CONTROL_OFFSET:
+					hw->io_ports[i] = ctrl;
+					break;
+				case IDE_IRQ_OFFSET:
+					hw->io_ports[i] = intr;
+					break;
+				default:
+					hw->io_ports[i] = 0;
+					break;
+			}
+		} else {
+			hw->io_ports[i] = base + offsets[i];
+		}
+	}
+	hw->irq = irq;
+	hw->ack_intr = ack_intr;
+}
+
+/*
+ * Register an IDE interface, specifing exactly the registers etc
+ * Set init=1 iff calling before probes have taken place.
+ */
+int ide_register_hw (hw_regs_t *hw, ide_hwif_t **hwifp)
 {
 	int index, retry = 1;
 	ide_hwif_t *hwif;
-	ide_ioreg_t data_port = (ide_ioreg_t) arg1, ctl_port = (ide_ioreg_t) arg2;
 
 	do {
 		for (index = 0; index < MAX_HWIFS; ++index) {
 			hwif = &ide_hwifs[index];
-			if (hwif->io_ports[IDE_DATA_OFFSET] == data_port)
+			if (hwif->hw.io_ports[IDE_DATA_OFFSET] == hw->io_ports[IDE_DATA_OFFSET])
 				goto found;
 		}
 		for (index = 0; index < MAX_HWIFS; ++index) {
 			hwif = &ide_hwifs[index];
-			if (!hwif->present)
+			if ((!hwif->present && !initializing) ||
+			    (!hwif->hw.io_ports[IDE_DATA_OFFSET] && initializing))
 				goto found;
 		}
 		for (index = 0; index < MAX_HWIFS; index++)
@@ -1824,14 +1928,33 @@
 		ide_unregister(index);
 	if (hwif->present)
 		return -1;
-	ide_init_hwif_ports(hwif->io_ports, data_port, &hwif->irq);
-	if (ctl_port)
-		hwif->io_ports[IDE_CONTROL_OFFSET] = ctl_port;
-	hwif->irq = irq;
+	memcpy(&hwif->hw, hw, sizeof(*hw));
+	memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->hw.io_ports));
+	hwif->irq = hw->irq;
 	hwif->noprobe = 0;
-	ide_init_module(IDE_PROBE_MODULE);
-	ide_init_module(IDE_DRIVER_MODULE);
-	return hwif->present ? index : -1;
+
+	if (!initializing) {
+		ide_init_module(IDE_PROBE_MODULE);
+		ide_init_module(IDE_DRIVER_MODULE);
+	}
+
+	if (hwifp)
+		*hwifp = hwif;
+
+	return (initializing || hwif->present) ? index : -1;
+}
+
+/*
+ * Compatability function with existing drivers.  If you want
+ * something different, use the function above.
+ */
+int ide_register (int arg1, int arg2, int irq)
+{
+	hw_regs_t hw;
+
+	ide_init_hwif_ports(&hw, (ide_ioreg_t) arg1, (ide_ioreg_t) arg2, NULL);
+	hw.irq = irq;
+	return ide_register_hw(&hw, NULL);
 }
 
 void ide_add_setting(ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set)
@@ -2056,10 +2179,24 @@
 	return ide_do_drive_cmd(drive, &rq, ide_wait);
 }
 
+/*
+ * Delay for *at least* 50ms.  As we don't know how much time is left
+ * until the next tick occurs, we wait an extra tick to be safe.
+ * This is used only during the probing/polling for drives at boot time.
+ *
+ * However, its usefullness may be needed in other places, thus we export it now.
+ * The future may change this to a millisecond setable delay.
+ */
+void ide_delay_50ms (void)
+{
+	unsigned long timeout = jiffies + ((HZ + 19)/20) + 1;
+	while (0 < (signed long)(timeout - jiffies));
+}
+
 static int ide_ioctl (struct inode *inode, struct file *file,
 			unsigned int cmd, unsigned long arg)
 {
-	int err, major, minor;
+	int err = 0, major, minor;
 	ide_drive_t *drive;
 	struct request rq;
 	kdev_t dev;
@@ -2147,7 +2284,68 @@
 					return -ENOMEM;
 				memcpy(argbuf, args, 4);
 			}
+			if ((((byte *)arg)[0] == WIN_SETFEATURES) &&
+			    (((byte *)arg)[1] > 66) &&
+			    (((byte *)arg)[2] == 3) &&
+			    ((drive->id->word93 & 0x2000) == 0)) {
+				printk("%s: Speed warnings UDMA 3/4 is not functional.\n", drive->name);
+				goto abort;
+			}
 			err = ide_wait_cmd(drive, args[0], args[1], args[2], args[3], argbuf);
+			if (!err &&
+			    (((byte *)arg)[0] == WIN_SETFEATURES) &&
+			    (((byte *)arg)[1] >= 16) &&
+			    (((byte *)arg)[2] == 3) &&
+			    (drive->id->dma_ultra ||
+			     drive->id->dma_mword ||
+			     drive->id->dma_1word)) {
+
+				/* 
+				 * Re-read drive->id for possible DMA mode 
+				 * change (copied from ide-probe.c)
+				 */
+				struct hd_driveid *id;
+				unsigned long timeout, irqs, flags;
+
+				probe_irq_off(probe_irq_on());
+				irqs = probe_irq_on();
+				if (IDE_CONTROL_REG)
+					OUT_BYTE(drive->ctl,IDE_CONTROL_REG);
+				ide_delay_50ms();
+				OUT_BYTE(WIN_IDENTIFY, IDE_COMMAND_REG);
+				timeout = jiffies + WAIT_WORSTCASE;
+				do {
+					if (0 < (signed long)(jiffies - timeout)) {
+						if (irqs)
+							(void) probe_irq_off(irqs);
+						goto abort;	/* drive timed-out */
+					}
+					ide_delay_50ms();		/* give drive a breather */
+				} while (IN_BYTE(IDE_ALTSTATUS_REG) & BUSY_STAT);
+				ide_delay_50ms();           /* wait for IRQ and DRQ_STAT */
+				if (!OK_STAT(GET_STAT(),DRQ_STAT,BAD_R_STAT))
+					goto abort;
+				__save_flags(flags);	/* local CPU only */
+				__cli();		/* local CPU only; some systems need this */
+				id = kmalloc(SECTOR_WORDS*4, GFP_ATOMIC);
+				ide_input_data(drive, id, SECTOR_WORDS);
+				(void) GET_STAT();	/* clear drive IRQ */
+				ide__sti();		/* local CPU only */
+				__restore_flags(flags);	/* local CPU only */
+				ide_fix_driveid(id);
+				if (id && id->cyls) {
+					drive->id->dma_ultra = id->dma_ultra;
+					drive->id->dma_mword = id->dma_mword;
+					drive->id->dma_1word = id->dma_1word;
+					/* anything more ? */
+#ifdef DEBUG
+					printk("%s: dma_ultra=%04X, dma_mword=%04X, dma_1word=%04X\n",
+						drive->name, id->dma_ultra, id->dma_mword, id->dma_1word);
+#endif
+				kfree(id);
+				}
+			}
+		abort:
 			if (copy_to_user((void *)arg, argbuf, argsize))
 				err = -EFAULT;
 			if (argsize > 4)
@@ -2233,6 +2431,32 @@
 }
 
 /*
+ *
+ */
+char *ide_xfer_verbose (byte xfer_rate) {
+	switch(xfer_rate) {
+		case XFER_UDMA_4:	return("UDMA 4");
+		case XFER_UDMA_3:	return("UDMA 3");
+		case XFER_UDMA_2:	return("UDMA 2");
+		case XFER_UDMA_1:	return("UDMA 1");
+		case XFER_UDMA_0:	return("UDMA 0");
+		case XFER_MW_DMA_2:	return("MW DMA 2");
+		case XFER_MW_DMA_1:	return("MW DMA 1");
+		case XFER_MW_DMA_0:	return("MW DMA 0");
+		case XFER_SW_DMA_2:	return("SW DMA 2");
+		case XFER_SW_DMA_1:	return("SW DMA 1");
+		case XFER_SW_DMA_0:	return("SW DMA 0");
+		case XFER_PIO_4:	return("PIO 4");
+		case XFER_PIO_3:	return("PIO 3");
+		case XFER_PIO_2:	return("PIO 2");
+		case XFER_PIO_1:	return("PIO 1");
+		case XFER_PIO_0:	return("PIO 0");
+		case XFER_PIO_SLOW:	return("PIO SLOW");
+		default:		return("XFER ERROR");
+	}
+}
+
+/*
  * stridx() returns the offset of c within s,
  * or -1 if c is '\0' or not found within s.
  */
@@ -2351,7 +2575,22 @@
  * "idex=reset"		: reset interface before first use
  * "idex=dma"		: enable DMA by default on both drives if possible
  *
- * The following are valid ONLY on ide0,
+ * "splitfifo=betweenChan"
+ *			: FIFO Configuration of VIA 82c586(<nothing>,"A"or"B").
+ *                                 --see what follows...
+ * "splitfifo=betweenChan,thresholdprim,thresholdsec"
+ *			: FIFO Configuration of VIA 82c586(<nothing>,"A" or "B").
+ *				betweenChan = 1(all FIFO's to primary channel)
+ *                                          , 2(all FIFO's to secondary channel)
+ *                                          , 3 or 4(evenly shared between them).
+ *				note: without FIFO, a channel is (u)dma disabled!
+ *				thresholdprim = 4, 3, 2 or 1
+ *						(standing for 1, 3/4, 1/2, 1/4).
+ *                                    Sets the threshold of FIFO to begin dma
+ *                                    transfer on the primary channel.
+ *				thresholdsec = cf upper, but for secondary channel.
+ *
+ * The following are valid ONLY on ide0, (except dc4030)
  * and the defaults for the base,ctl ports must not be altered.
  *
  * "ide0=dtc2278"	: probe/support DTC2278 interface
@@ -2361,6 +2600,7 @@
  * "ide0=qd6580"	: probe/support qd6580 interface
  * "ide0=ali14xx"	: probe/support ali14xx chipsets (ALI M1439, M1443, M1445)
  * "ide0=umc8672"	: probe/support umc8672 chipsets
+ * "idex=dc4030"	: probe/support Promise DC4030VL interface
  */
 __initfunc(void ide_setup (char *s))
 {
@@ -2372,6 +2612,17 @@
 	const char max_hwif  = '0' + (MAX_HWIFS - 1);
 
 	printk("ide_setup: %s", s);
+
+#ifdef CONFIG_BLK_DEV_IDEDOUBLER
+	if (!strcmp(s, "ide=doubler")) {
+		extern int ide_doubler;
+
+		printk("ide: Enabled support for IDE doublers\n");
+		ide_doubler = 1;
+		return;
+	}
+#endif /* CONFIG_BLK_DEV_IDEDOUBLER */
+
 	init_ide_data ();
 
 	/*
@@ -2435,6 +2686,58 @@
 		}
 	}
 
+#if defined(CONFIG_BLK_DEV_VIA82C586)
+	/*
+	 *  Look for drive option "splitfifo=..."
+	 */
+
+	if (s[0] == 's' && s[1] == 'p' && s[2] == 'l' &&
+	    s[3] == 'i' && s[4] == 't' && s[5] == 'f' &&
+	    s[6] == 'i' && s[7] == 'f' && s[8] == 'o') {
+		byte tmp = 0x3a;		/* default config byte */
+
+		i = match_parm(&s[9], NULL, vals, 3);
+		switch(i) {
+		case 3:	
+			tmp &= 0xf0;
+			if ((vals[1] > 0) && (vals[1] < 5)) {
+				/* sets threshold for primary Channel: */
+				byte x = 4 - vals[1];
+				tmp |= (x << 2);
+			}
+			else
+				goto bad_option;
+			if ((vals[2] > 0) && (vals[2] < 5)) {
+				/* sets threshold for secondary Channel: */
+				byte x = 4 - vals[2];
+				tmp |= x;
+			}
+			else
+				goto bad_option;
+		case 1:
+			/* set the FIFO config between channels to 0: */
+			tmp &= 0x9f;
+			/* set the needed FIFO config between channels: */
+			if (vals[0] == 1)	/* primary fifo only */
+				tmp |= 0x10;
+			else if (vals[0] == 2)	/* secondary fifo only */
+				tmp |= 0x70;
+			else if (vals[0] == 4)	/* other shared fifo config */
+				tmp |= 0x50;
+			else if (vals[0] == 3)	/* default config */
+				tmp |= 0x30;
+			else
+				goto bad_option;
+			break;
+		default:
+			goto bad_option;
+		}
+		/* set the found option in fifoconfig */
+		fifoconfig = tmp;		
+		goto done;
+	}
+#endif  /* defined(CONFIG_BLK_DEV_VIA82C586) */
+
 	if (s[0] != 'i' || s[1] != 'd' || s[2] != 'e')
 		goto bad_option;
 	/*
@@ -2468,9 +2771,9 @@
 		if (i > 0 || i <= -7) {			/* is parameter a chipset name? */
 			if (hwif->chipset != ide_unknown)
 				goto bad_option;	/* chipset already specified */
-			if (i <= -7 && hw != 0)
+			if (i <= -7 && i != -14 && hw != 0)
 				goto bad_hwif;		/* chipset drivers are for "ide0=" only */
-			if (i <= -7 && ide_hwifs[hw^1].chipset != ide_unknown)
+			if (i <= -7 && i != -14 && ide_hwifs[hw+1].chipset != ide_unknown)
 				goto bad_option;	/* chipset for 2nd port already specified */
 			printk("\n");
 		}
@@ -2574,8 +2877,9 @@
 			case 2: /* base,ctl */
 				vals[2] = 0;	/* default irq = probe for it */
 			case 3: /* base,ctl,irq */
-				ide_init_hwif_ports(hwif->io_ports, (ide_ioreg_t) vals[0], &hwif->irq);
-				hwif->io_ports[IDE_CONTROL_OFFSET] = (ide_ioreg_t) vals[1];
+				hwif->hw.irq = vals[2];
+				ide_init_hwif_ports(&hwif->hw, (ide_ioreg_t) vals[0], (ide_ioreg_t) vals[1], &hwif->irq);
+				memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports));
 				hwif->irq      = vals[2];
 				hwif->noprobe  = 0;
 				hwif->chipset  = ide_generic;
@@ -2612,9 +2916,122 @@
  * an IDE disk drive, or if a geometry was "forced" on the commandline.
  * Returns 1 if the geometry translation was successful.
  */
+
+#define ANDRIES_GEOMETRY	0
+
 int ide_xlate_1024 (kdev_t i_rdev, int xparm, const char *msg)
 {
 	ide_drive_t *drive;
+
+#if ANDRIES_GEOMETRY
+	/*
+	 * This is the documented list of values (some version of)
+	 * OnTrack DM uses.
+	 */
+
+	static const byte dm_head_vals[] = {4, 8, 16, 32, 64, 128, 255, 0};
+
+	/*
+	 * This is a pure phantasy list - known to be incorrect.
+	 *
+	 * In fact it seems that EZD does not do anything to the CHS
+	 * values in the partition table, so whether EZD is present
+	 * or not should probably not influence the geometry.
+	 */
+
+	static const byte ez_head_vals[] = {4, 8, 16, 32, 64, 128, 240, 255, 0};        const byte *heads;
+	unsigned long tracks;
+
+	drive = get_info_ptr(i_rdev);
+	if (!drive)
+		return 0;
+
+	if (xparm > 1 && xparm <= drive->bios_head && drive->bios_sect == 63) {
+		/*
+		 * Update the current 3D drive values.
+		 */
+		drive->id->cur_cyls	= drive->bios_cyl;
+		drive->id->cur_heads	= drive->bios_head;
+		drive->id->cur_sectors	= drive->bios_sect;
+		return 0;	/* we already have a translation */
+	}
+
+	if (xparm == -1) {
+		int ret = 0;
+#if FAKE_FDISK_FOR_EZDRIVE
+		if (drive->remap_0_to_1 == 0) {
+			drive->remap_0_to_1 = 1;
+			printk("%s [remap 0->1]", msg);
+			msg = NULL;
+			ret = 1;
+		}
+		if (drive->bios_head > 16)
+#endif /* FAKE_FDISK_FOR_EZDRIVE */
+		{
+			/*
+			 * Update the current 3D drive values.
+			 */
+			drive->id->cur_cyls	= drive->bios_cyl;
+			drive->id->cur_heads	= drive->bios_head;
+			drive->id->cur_sectors	= drive->bios_sect;
+			return ret;	/* we already have a translation */
+		}
+	}
+
+	if (msg)
+		printk("%s ", msg);
+
+	if (drive->forced_geom) {
+		/*
+		 * Update the current 3D drive values.
+		 */
+		drive->id->cur_cyls	= drive->bios_cyl;
+		drive->id->cur_heads	= drive->bios_head;
+		drive->id->cur_sectors	= drive->bios_sect;
+		return 0;
+	}
+
+#if 1
+	/* There used to be code here that assigned drive->id->CHS
+	   to drive->CHS and that to drive->bios_CHS. However,
+	   some disks have id->C/H/S = 4092/16/63 but are larger than 2.1 GB.
+	   In such cases that code was wrong.  Moreover,
+	   there seems to be no reason to do any of these things. */
+#else
+	if (drive->id) {
+		drive->cyl  = drive->id->cyls;
+		drive->head = drive->id->heads;
+		drive->sect = drive->id->sectors;
+	}
+	drive->bios_cyl  = drive->cyl;
+	drive->bios_head = drive->head;
+	drive->bios_sect = drive->sect;
+	drive->special.b.set_geometry = 1;
+
+#endif
+
+	tracks = drive->bios_cyl * drive->bios_head * drive->bios_sect / 63;
+	drive->bios_sect = 63;
+	if (xparm > 1) {
+		drive->bios_head = xparm;
+		drive->bios_cyl = tracks / drive->bios_head;
+	} else {
+		heads = (xparm == -1) ? ez_head_vals : dm_head_vals;
+		while (drive->bios_cyl >= 1024) {
+			drive->bios_head = *heads;
+			drive->bios_cyl = tracks / drive->bios_head;
+			if (0 == *++heads)
+				break;
+		}
+		if (xparm == 1) {
+			drive->sect0 = 63;
+			drive->bios_cyl = (tracks - 1) / drive->bios_head;
+			printk("[remap +63] ");
+		}
+	}
+
+#else /* ANDRIES_GEOMETRY */
+
 	static const byte head_vals[] = {4, 8, 16, 32, 64, 128, 255, 0};
 	const byte *heads = head_vals;
 	unsigned long tracks;
@@ -2689,14 +3106,16 @@
 			printk("[remap +63] ");
 		}
 	}
+#endif /* ANDRIES_GEOMETRY */
+
 	drive->part[0].nr_sects = current_capacity(drive);
 	printk("[%d/%d/%d]", drive->bios_cyl, drive->bios_head, drive->bios_sect);
 	/*
 	 * Update the current 3D drive values.
 	 */
-	drive->id->cur_cyls    = drive->bios_cyl;
-	drive->id->cur_heads   = drive->bios_head;
-	drive->id->cur_sectors = drive->bios_sect;
+	drive->id->cur_cyls	= drive->bios_cyl;
+	drive->id->cur_heads	= drive->bios_head;
+	drive->id->cur_sectors	= drive->bios_sect;
 	return 1;
 }
 
@@ -2739,6 +3158,42 @@
 		pmac_ide_probe();
 	}
 #endif /* CONFIG_BLK_DEV_IDE_PMAC */
+#ifdef CONFIG_BLK_DEV_IDE_ICSIDE
+	{
+		extern void icside_init(void);
+		icside_init();
+	}
+#endif /* CONFIG_BLK_DEV_IDE_ICSIDE */
+#ifdef CONFIG_BLK_DEV_IDE_RAPIDE
+	{
+		extern void rapide_init(void);
+		rapide_init();
+	}
+#endif /* CONFIG_BLK_DEV_IDE_RAPIDE */
+#ifdef CONFIG_BLK_DEV_GAYLE
+	{
+		extern void gayle_init(void);
+		gayle_init();
+	}
+#endif /* CONFIG_BLK_DEV_GAYLE */
+#ifdef CONFIG_BLK_DEV_FALCON_IDE
+	{
+		extern void falconide_init(void);
+		falconide_init();
+	}
+#endif /* CONFIG_BLK_DEV_FALCON_IDE */
+#ifdef CONFIG_BLK_DEV_MAC_IDE
+	{
+		extern void macide_init(void);
+		macide_init();
+	}
+#endif /* CONFIG_BLK_DEV_MAC_IDE */
+#ifdef CONFIG_BLK_DEV_BUDDHA
+	{
+		extern void buddha_init(void);
+		buddha_init();
+	}
+#endif /* CONFIG_BLK_DEV_BUDDHA */
 }
 
 __initfunc(void ide_init_builtin_drivers (void))
@@ -3013,6 +3468,12 @@
 #if MAX_HWIFS > 5
 EXPORT_SYMBOL(do_ide5_request);
 #endif /* MAX_HWIFS > 5 */
+#if MAX_HWIFS > 6
+EXPORT_SYMBOL(do_ide6_request);
+#endif /* MAX_HWIFS > 6 */
+#if MAX_HWIFS > 7
+EXPORT_SYMBOL(do_ide7_request);
+#endif /* MAX_HWIFS > 7 */
 
 /*
  * Driver module
@@ -3037,6 +3498,7 @@
 EXPORT_SYMBOL(ide_revalidate_disk);
 EXPORT_SYMBOL(ide_cmd);
 EXPORT_SYMBOL(ide_wait_cmd);
+EXPORT_SYMBOL(ide_delay_50ms);
 EXPORT_SYMBOL(ide_stall_queue);
 #ifdef CONFIG_PROC_FS
 EXPORT_SYMBOL(ide_add_proc_entries);
@@ -3046,14 +3508,23 @@
 EXPORT_SYMBOL(ide_add_setting);
 EXPORT_SYMBOL(ide_remove_setting);
 
+EXPORT_SYMBOL(ide_register_hw);
 EXPORT_SYMBOL(ide_register);
 EXPORT_SYMBOL(ide_unregister);
+EXPORT_SYMBOL(ide_setup_ports);
 
 /*
  * This is gets invoked once during initialization, to set *everything* up
  */
 __initfunc(int ide_init (void))
 {
+	static char banner_printed = 0;
+
+	if (!banner_printed) {
+		printk(KERN_INFO "Uniform Multi-Platform E-IDE driver " REVISION "\n");
+		banner_printed = 1;
+	}
+
 	init_ide_data ();
 
 	initializing = 1;
diff -u --recursive --new-file v2.3.0/linux/drivers/block/ide.h linux/drivers/block/ide.h
--- v2.3.0/linux/drivers/block/ide.h	Tue May 11 13:04:09 1999
+++ linux/drivers/block/ide.h	Wed Dec 31 16:00:00 1969
@@ -1,769 +0,0 @@
-#ifndef _IDE_H
-#define _IDE_H
-/*
- *  linux/drivers/block/ide.h
- *
- *  Copyright (C) 1994-1998  Linus Torvalds & authors
- */
-
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/hdreg.h>
-#include <linux/blkdev.h>
-#include <linux/proc_fs.h>
-#include <asm/ide.h>
-
-/*
- * This is the multiple IDE interface driver, as evolved from hd.c.
- * It supports up to four IDE interfaces, on one or more IRQs (usually 14 & 15).
- * There can be up to two drives per interface, as per the ATA-2 spec.
- *
- * Primary i/f:    ide0: major=3;  (hda)         minor=0; (hdb)         minor=64
- * Secondary i/f:  ide1: major=22; (hdc or hd1a) minor=0; (hdd or hd1b) minor=64
- * Tertiary i/f:   ide2: major=33; (hde)         minor=0; (hdf)         minor=64
- * Quaternary i/f: ide3: major=34; (hdg)         minor=0; (hdh)         minor=64
- */
-
-/******************************************************************************
- * IDE driver configuration options (play with these as desired):
- *
- * REALLY_SLOW_IO can be defined in ide.c and ide-cd.c, if necessary
- */
-#undef REALLY_FAST_IO			/* define if ide ports are perfect */
-#define INITIAL_MULT_COUNT	0	/* off=0; on=2,4,8,16,32, etc.. */
-
-#ifndef SUPPORT_SLOW_DATA_PORTS		/* 1 to support slow data ports */
-#define SUPPORT_SLOW_DATA_PORTS	1	/* 0 to reduce kernel size */
-#endif
-#ifndef SUPPORT_VLB_SYNC		/* 1 to support weird 32-bit chips */
-#define SUPPORT_VLB_SYNC	1	/* 0 to reduce kernel size */
-#endif
-#ifndef DISK_RECOVERY_TIME		/* off=0; on=access_delay_time */
-#define DISK_RECOVERY_TIME	0	/*  for hardware that needs it */
-#endif
-#ifndef OK_TO_RESET_CONTROLLER		/* 1 needed for good error recovery */
-#define OK_TO_RESET_CONTROLLER	1	/* 0 for use with AH2372A/B interface */
-#endif
-#ifndef FAKE_FDISK_FOR_EZDRIVE		/* 1 to help linux fdisk with EZDRIVE */
-#define FAKE_FDISK_FOR_EZDRIVE 	1	/* 0 to reduce kernel size */
-#endif
-#ifndef FANCY_STATUS_DUMPS		/* 1 for human-readable drive errors */
-#define FANCY_STATUS_DUMPS	1	/* 0 to reduce kernel size */
-#endif
-
-#ifdef CONFIG_BLK_DEV_CMD640
-#if 0	/* change to 1 when debugging cmd640 problems */
-void cmd640_dump_regs (void);
-#define CMD640_DUMP_REGS cmd640_dump_regs() /* for debugging cmd640 chipset */
-#endif
-#endif  /* CONFIG_BLK_DEV_CMD640 */
-
-/*
- * IDE_DRIVE_CMD is used to implement many features of the hdparm utility
- */
-#define IDE_DRIVE_CMD		99	/* (magic) undef to reduce kernel size*/
-
-/*
- *  "No user-serviceable parts" beyond this point  :)
- *****************************************************************************/
-
-typedef unsigned char	byte;	/* used everywhere */
-
-/*
- * Probably not wise to fiddle with these
- */
-#define ERROR_MAX	8	/* Max read/write errors per sector */
-#define ERROR_RESET	3	/* Reset controller every 4th retry */
-#define ERROR_RECAL	1	/* Recalibrate every 2nd retry */
-
-/*
- * Ensure that various configuration flags have compatible settings
- */
-#ifdef REALLY_SLOW_IO
-#undef REALLY_FAST_IO
-#endif
-
-#define HWIF(drive)		((ide_hwif_t *)((drive)->hwif))
-#define HWGROUP(drive)		((ide_hwgroup_t *)(HWIF(drive)->hwgroup))
-
-/*
- * Definitions for accessing IDE controller registers
- */
-#define IDE_NR_PORTS		(10)
-
-#define IDE_DATA_OFFSET		(0)
-#define IDE_ERROR_OFFSET	(1)
-#define IDE_NSECTOR_OFFSET	(2)
-#define IDE_SECTOR_OFFSET	(3)
-#define IDE_LCYL_OFFSET		(4)
-#define IDE_HCYL_OFFSET		(5)
-#define IDE_SELECT_OFFSET	(6)
-#define IDE_STATUS_OFFSET	(7)
-#define IDE_CONTROL_OFFSET	(8)
-#define IDE_IRQ_OFFSET		(9)
-
-#define IDE_FEATURE_OFFSET	IDE_ERROR_OFFSET
-#define IDE_COMMAND_OFFSET	IDE_STATUS_OFFSET
-
-#define IDE_DATA_REG		(HWIF(drive)->io_ports[IDE_DATA_OFFSET])
-#define IDE_ERROR_REG		(HWIF(drive)->io_ports[IDE_ERROR_OFFSET])
-#define IDE_NSECTOR_REG		(HWIF(drive)->io_ports[IDE_NSECTOR_OFFSET])
-#define IDE_SECTOR_REG		(HWIF(drive)->io_ports[IDE_SECTOR_OFFSET])
-#define IDE_LCYL_REG		(HWIF(drive)->io_ports[IDE_LCYL_OFFSET])
-#define IDE_HCYL_REG		(HWIF(drive)->io_ports[IDE_HCYL_OFFSET])
-#define IDE_SELECT_REG		(HWIF(drive)->io_ports[IDE_SELECT_OFFSET])
-#define IDE_STATUS_REG		(HWIF(drive)->io_ports[IDE_STATUS_OFFSET])
-#define IDE_CONTROL_REG		(HWIF(drive)->io_ports[IDE_CONTROL_OFFSET])
-#define IDE_IRQ_REG		(HWIF(drive)->io_ports[IDE_IRQ_OFFSET])
-
-#define IDE_FEATURE_REG		IDE_ERROR_REG
-#define IDE_COMMAND_REG		IDE_STATUS_REG
-#define IDE_ALTSTATUS_REG	IDE_CONTROL_REG
-#define IDE_IREASON_REG		IDE_NSECTOR_REG
-#define IDE_BCOUNTL_REG		IDE_LCYL_REG
-#define IDE_BCOUNTH_REG		IDE_HCYL_REG
-
-#ifdef REALLY_FAST_IO
-#define OUT_BYTE(b,p)		outb((b),(p))
-#define IN_BYTE(p)		(byte)inb(p)
-#else
-#define OUT_BYTE(b,p)		outb_p((b),(p))
-#define IN_BYTE(p)		(byte)inb_p(p)
-#endif /* REALLY_FAST_IO */
-
-#define GET_ERR()		IN_BYTE(IDE_ERROR_REG)
-#define GET_STAT()		IN_BYTE(IDE_STATUS_REG)
-#define OK_STAT(stat,good,bad)	(((stat)&((good)|(bad)))==(good))
-#define BAD_R_STAT		(BUSY_STAT   | ERR_STAT)
-#define BAD_W_STAT		(BAD_R_STAT  | WRERR_STAT)
-#define BAD_STAT		(BAD_R_STAT  | DRQ_STAT)
-#define DRIVE_READY		(READY_STAT  | SEEK_STAT)
-#define DATA_READY		(DRQ_STAT)
-
-/*
- * Some more useful definitions
- */
-#define IDE_MAJOR_NAME	"ide"	/* the same for all i/f; see also genhd.c */
-#define MAJOR_NAME	IDE_MAJOR_NAME
-#define PARTN_BITS	6	/* number of minor dev bits for partitions */
-#define PARTN_MASK	((1<<PARTN_BITS)-1)	/* a useful bit mask */
-#define MAX_DRIVES	2	/* per interface; 2 assumed by lots of code */
-#define SECTOR_WORDS	(512 / 4)	/* number of 32bit words per sector */
-#define IDE_LARGE_SEEK(b1,b2,t)	(((b1) > (b2) + (t)) || ((b2) > (b1) + (t)))
-#define IDE_MIN(a,b)	((a)<(b) ? (a):(b))
-#define IDE_MAX(a,b)	((a)>(b) ? (a):(b))
-
-/*
- * Timeouts for various operations:
- */
-#define WAIT_DRQ	(5*HZ/100)	/* 50msec - spec allows up to 20ms */
-#ifdef CONFIG_APM
-#define WAIT_READY	(5*HZ)		/* 5sec - some laptops are very slow */
-#else
-#define WAIT_READY	(3*HZ/100)	/* 30msec - should be instantaneous */
-#endif /* CONFIG_APM */
-#define WAIT_PIDENTIFY	(10*HZ)	/* 10sec  - should be less than 3ms (?)
-				            if all ATAPI CD is closed at boot */
-#define WAIT_WORSTCASE	(30*HZ)	/* 30sec  - worst case when spinning up */
-#define WAIT_CMD	(10*HZ)	/* 10sec  - maximum wait for an IRQ to happen */
-#define WAIT_MIN_SLEEP	(2*HZ/100)	/* 20msec - minimum sleep time */
-
-#define SELECT_DRIVE(hwif,drive)				\
-{								\
-	if (hwif->selectproc)					\
-		hwif->selectproc(drive);			\
-	OUT_BYTE((drive)->select.all, hwif->io_ports[IDE_SELECT_OFFSET]); \
-}
-
-/*
- * Now for the data we need to maintain per-drive:  ide_drive_t
- */
-
-#define ide_scsi	0x21
-#define ide_disk	0x20
-#define ide_optical	0x7
-#define ide_cdrom	0x5
-#define ide_tape	0x1
-#define ide_floppy	0x0
-
-typedef union {
-	unsigned all			: 8;	/* all of the bits together */
-	struct {
-		unsigned set_geometry	: 1;	/* respecify drive geometry */
-		unsigned recalibrate	: 1;	/* seek to cyl 0      */
-		unsigned set_multmode	: 1;	/* set multmode count */
-		unsigned set_tune	: 1;	/* tune interface for drive */
-		unsigned reserved	: 4;	/* unused */
-		} b;
-	} special_t;
-
-typedef struct ide_drive_s {
-	struct request		*queue;	/* request queue */
-	struct ide_drive_s 	*next;	/* circular list of hwgroup drives */
-	unsigned long sleep;		/* sleep until this time */
-	unsigned long service_start;	/* time we started last request */
-	unsigned long service_time;	/* service time of last request */
-	special_t	special;	/* special action flags */
-	byte     keep_settings;		/* restore settings after drive reset */
-	byte     using_dma;		/* disk is using dma for read/write */
-	byte     waiting_for_dma;	/* dma currently in progress */
-	byte     unmask;		/* flag: okay to unmask other irqs */
-	byte     slow;			/* flag: slow data port */
-	byte     bswap;			/* flag: byte swap data */
-	byte     dsc_overlap;		/* flag: DSC overlap */
-	byte     nice1;			/* flag: give potential excess bandwidth */
-	unsigned present	: 1;	/* drive is physically present */
-	unsigned noprobe 	: 1;	/* from:  hdx=noprobe */
-	unsigned busy		: 1;	/* currently doing revalidate_disk() */
-	unsigned removable	: 1;	/* 1 if need to do check_media_change */
-	unsigned forced_geom	: 1;	/* 1 if hdx=c,h,s was given at boot */
-	unsigned no_unmask	: 1;	/* disallow setting unmask bit */
-	unsigned no_io_32bit	: 1;	/* disallow enabling 32bit I/O */
-	unsigned nobios		: 1;	/* flag: do not probe bios for drive */
-	unsigned revalidate	: 1;	/* request revalidation */
-	unsigned atapi_overlap	: 1;	/* flag: ATAPI overlap (not supported) */
-	unsigned nice0		: 1;	/* flag: give obvious excess bandwidth */
-	unsigned nice2		: 1;	/* flag: give a share in our own bandwidth */
-	unsigned doorlocking	: 1;	/* flag: for removable only: door lock/unlock works */
-	unsigned autotune	: 2;	/* 1=autotune, 2=noautotune, 0=default */
-#if FAKE_FDISK_FOR_EZDRIVE
-	unsigned remap_0_to_1	: 1;	/* flag: partitioned with ezdrive */
-#endif /* FAKE_FDISK_FOR_EZDRIVE */
-	byte		media;		/* disk, cdrom, tape, floppy, ... */
-	select_t	select;		/* basic drive/head select reg value */
-	byte		ctl;		/* "normal" value for IDE_CONTROL_REG */
-	byte		ready_stat;	/* min status value for drive ready */
-	byte		mult_count;	/* current multiple sector setting */
-	byte 		mult_req;	/* requested multiple sector setting */
-	byte 		tune_req;	/* requested drive tuning setting */
-	byte		io_32bit;	/* 0=16-bit, 1=32-bit, 2/3=32bit+sync */
-	byte		bad_wstat;	/* used for ignoring WRERR_STAT */
-	byte		nowerr;		/* used for ignoring WRERR_STAT */
-	byte		sect0;		/* offset of first sector for DM6:DDO */
-	byte 		usage;		/* current "open()" count for drive */
-	byte 		head;		/* "real" number of heads */
-	byte		sect;		/* "real" sectors per track */
-	byte		bios_head;	/* BIOS/fdisk/LILO number of heads */
-	byte		bios_sect;	/* BIOS/fdisk/LILO sectors per track */
-	unsigned short	bios_cyl;	/* BIOS/fdisk/LILO number of cyls */
-	unsigned short	cyl;		/* "real" number of cyls */
-	unsigned int	drive_data;	/* for use by tuneproc/selectproc as needed */
-	void		  *hwif;	/* actually (ide_hwif_t *) */
-	struct wait_queue *wqueue;	/* used to wait for drive in open() */
-	struct hd_driveid *id;		/* drive model identification info */
-	struct hd_struct  *part;	/* drive partition table */
-	char		name[4];	/* drive name, such as "hda" */
-	void 		*driver;	/* (ide_driver_t *) */
-	void		*driver_data;	/* extra driver data */
-	struct proc_dir_entry *proc;	/* /proc/ide/ directory entry */
-	void		*settings;	/* /proc/ide/ drive settings */
-	char		driver_req[10];	/* requests specific driver */
-	} ide_drive_t;
-
-/*
- * An ide_dmaproc_t() initiates/aborts DMA read/write operations on a drive.
- *
- * The caller is assumed to have selected the drive and programmed the drive's
- * sector address using CHS or LBA.  All that remains is to prepare for DMA
- * and then issue the actual read/write DMA/PIO command to the drive.
- *
- * Returns 0 if all went well.
- * Returns 1 if DMA read/write could not be started, in which case the caller
- * should either try again later, or revert to PIO for the current request.
- */
-typedef enum {	ide_dma_read,	ide_dma_write,	ide_dma_begin,	ide_dma_end,
-		ide_dma_check,	ide_dma_on,	ide_dma_off,	ide_dma_off_quietly,
-		ide_dma_test_irq
-	} ide_dma_action_t;
-
-typedef int (ide_dmaproc_t)(ide_dma_action_t, ide_drive_t *);
-
-
-/*
- * An ide_tuneproc_t() is used to set the speed of an IDE interface
- * to a particular PIO mode.  The "byte" parameter is used
- * to select the PIO mode by number (0,1,2,3,4,5), and a value of 255
- * indicates that the interface driver should "auto-tune" the PIO mode
- * according to the drive capabilities in drive->id;
- *
- * Not all interface types support tuning, and not all of those
- * support all possible PIO settings.  They may silently ignore
- * or round values as they see fit.
- */
-typedef void (ide_tuneproc_t)(ide_drive_t *, byte);
-
-/*
- * This is used to provide support for strange interfaces
- */
-typedef void (ide_selectproc_t) (ide_drive_t *);
-
-/*
- * hwif_chipset_t is used to keep track of the specific hardware
- * chipset used by each IDE interface, if known.
- */
-typedef enum {	ide_unknown,	ide_generic,	ide_pci,
-		ide_cmd640,	ide_dtc2278,	ide_ali14xx,
-		ide_qd6580,	ide_umc8672,	ide_ht6560b,
-		ide_pdc4030,	ide_rz1000,	ide_trm290,
-		ide_cmd646,	ide_4drives
-	} hwif_chipset_t;
-
-typedef struct ide_pci_devid_s {
-	unsigned short	vid;
-	unsigned short	did;
-} ide_pci_devid_t;
-
-#define IDE_PCI_DEVID_NULL	((ide_pci_devid_t){0,0})
-#define IDE_PCI_DEVID_EQ(a,b)	(a.vid == b.vid && a.did == b.did)
-
-typedef struct hwif_s {
-	struct hwif_s	*next;		/* for linked-list in ide_hwgroup_t */
-	void		*hwgroup;	/* actually (ide_hwgroup_t *) */
-	ide_ioreg_t	io_ports[IDE_NR_PORTS];	/* task file registers */
-	ide_drive_t	drives[MAX_DRIVES];	/* drive info */
-	struct gendisk	*gd;		/* gendisk structure */
-	ide_tuneproc_t	*tuneproc;	/* routine to tune PIO mode for drives */
-	ide_selectproc_t *selectproc;	/* tweaks hardware to select drive */
-	ide_dmaproc_t	*dmaproc;	/* dma read/write/abort routine */
-	unsigned long	*dmatable;	/* dma physical region descriptor table */
-	struct hwif_s	*mate;		/* other hwif from same PCI chip */
-	unsigned long	dma_base;	/* base addr for dma ports */
-	unsigned	dma_extra;	/* extra addr for dma ports */
-	unsigned long	config_data;	/* for use by chipset-specific code */
-	unsigned long	select_data;	/* for use by chipset-specific code */
-	struct proc_dir_entry *proc;	/* /proc/ide/ directory entry */
-	int		irq;		/* our irq number */
-	byte		major;		/* our major number */
-	char 		name[6];	/* name of interface, eg. "ide0" */
-	byte		index;		/* 0 for ide0; 1 for ide1; ... */
-	hwif_chipset_t	chipset;	/* sub-module for tuning.. */
-	unsigned	noprobe    : 1;	/* don't probe for this interface */
-	unsigned	present    : 1;	/* this interface exists */
-	unsigned	serialized : 1;	/* serialized operation with mate hwif */
-	unsigned	sharing_irq: 1;	/* 1 = sharing irq with another hwif */
-	unsigned	reset      : 1;	/* reset after probe */
-	unsigned	autodma    : 1;	/* automatically try to enable DMA at boot */
-	byte		channel;	/* for dual-port chips: 0=primary, 1=secondary */
-	struct pci_dev	*pci_dev;	/* for pci chipsets */
-	ide_pci_devid_t	pci_devid;	/* for pci chipsets: {VID,DID} */
-#if (DISK_RECOVERY_TIME > 0)
-	unsigned long	last_time;	/* time when previous rq was done */
-#endif
-	} ide_hwif_t;
-
-/*
- *  internal ide interrupt handler type
- */
-typedef void (ide_handler_t)(ide_drive_t *);
-
-typedef struct hwgroup_s {
-	spinlock_t		spinlock; /* protects "busy" and "handler" */
-	ide_handler_t		*handler;/* irq handler, if active */
-	int			busy;	/* BOOL: protects all fields below */
-	ide_drive_t		*drive;	/* current drive */
-	ide_hwif_t		*hwif;	/* ptr to current hwif in linked-list */
-	struct request		*rq;	/* current request */
-	struct timer_list	timer;	/* failsafe timer */
-	struct request		wrq;	/* local copy of current write rq */
-	unsigned long		poll_timeout;	/* timeout value during long polls */
-	} ide_hwgroup_t;
-
-/*
- * configurable drive settings
- */
-
-#define TYPE_INT	0
-#define TYPE_INTA	1
-#define TYPE_BYTE	2
-#define TYPE_SHORT	3
-
-#define SETTING_READ	(1 << 0)
-#define SETTING_WRITE	(1 << 1)
-#define SETTING_RW	(SETTING_READ | SETTING_WRITE)
-
-typedef int (ide_procset_t)(ide_drive_t *, int);
-typedef struct ide_settings_s {
-	char			*name;
-	int			rw;
-	int			read_ioctl;
-	int			write_ioctl;
-	int			data_type;
-	int			min;
-	int			max;
-	int			mul_factor;
-	int			div_factor;
-	void			*data;
-	ide_procset_t		*set;
-	int			auto_remove;
-	struct ide_settings_s	*next;
-} ide_settings_t;
-
-void ide_add_setting(ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set);
-void ide_remove_setting(ide_drive_t *drive, char *name);
-ide_settings_t *ide_find_setting_by_name(ide_drive_t *drive, char *name);
-int ide_read_setting(ide_drive_t *t, ide_settings_t *setting);
-int ide_write_setting(ide_drive_t *drive, ide_settings_t *setting, int val);
-void ide_add_generic_settings(ide_drive_t *drive);
-
-/*
- * /proc/ide interface
- */
-typedef struct {
-	const char	*name;
-	mode_t		mode;
-	read_proc_t	*read_proc;
-	write_proc_t	*write_proc;
-} ide_proc_entry_t;
-
-#ifdef CONFIG_PROC_FS
-void proc_ide_create(void);
-void proc_ide_destroy(void);
-void ide_add_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t *p, void *data);
-void ide_remove_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t *p);
-read_proc_t proc_ide_read_capacity;
-read_proc_t proc_ide_read_geometry;
-
-/*
- * Standard exit stuff:
- */
-#define PROC_IDE_READ_RETURN(page,start,off,count,eof,len) \
-{					\
-	len -= off;			\
-	if (len < count) {		\
-		*eof = 1;		\
-		if (len <= 0)		\
-			return 0;	\
-	} else				\
-		len = count;		\
-	*start = page + off;		\
-	return len;			\
-}
-#else
-#define PROC_IDE_READ_RETURN(page,start,off,count,eof,len) return 0;
-#endif
-
-/*
- * Subdrivers support.
- */
-#define IDE_SUBDRIVER_VERSION	1
-
-typedef int	(ide_cleanup_proc)(ide_drive_t *);
-typedef void 	(ide_do_request_proc)(ide_drive_t *, struct request *, unsigned long);
-typedef void	(ide_end_request_proc)(byte, ide_hwgroup_t *);
-typedef int 	(ide_ioctl_proc)(ide_drive_t *, struct inode *, struct file *, unsigned int, unsigned long);
-typedef int	(ide_open_proc)(struct inode *, struct file *, ide_drive_t *);
-typedef void 	(ide_release_proc)(struct inode *, struct file *, ide_drive_t *);
-typedef int	(ide_check_media_change_proc)(ide_drive_t *);
-typedef void	(ide_pre_reset_proc)(ide_drive_t *);
-typedef unsigned long (ide_capacity_proc)(ide_drive_t *);
-typedef void	(ide_special_proc)(ide_drive_t *);
-typedef void	(ide_setting_proc)(ide_drive_t *);
-
-typedef struct ide_driver_s {
-	const char			*name;
-	const char			*version;
-	byte				media;
-	unsigned busy			: 1;
-	unsigned supports_dma		: 1;
-	unsigned supports_dsc_overlap	: 1;
-	ide_cleanup_proc		*cleanup;
-	ide_do_request_proc		*do_request;
-	ide_end_request_proc		*end_request;
-	ide_ioctl_proc			*ioctl;
-	ide_open_proc			*open;
-	ide_release_proc		*release;
-	ide_check_media_change_proc	*media_change;
-	ide_pre_reset_proc		*pre_reset;
-	ide_capacity_proc		*capacity;
-	ide_special_proc		*special;
-	ide_proc_entry_t		*proc;
-	} ide_driver_t;
-
-#define DRIVER(drive)		((ide_driver_t *)((drive)->driver))
-
-/*
- * IDE modules.
- */
-#define IDE_CHIPSET_MODULE		0	/* not supported yet */
-#define IDE_PROBE_MODULE		1
-#define IDE_DRIVER_MODULE		2
-
-typedef int	(ide_module_init_proc)(void);
-
-typedef struct ide_module_s {
-	int				type;
-	ide_module_init_proc		*init;
-	void				*info;
-	struct ide_module_s		*next;
-} ide_module_t;
-
-/*
- * ide_hwifs[] is the master data structure used to keep track
- * of just about everything in ide.c.  Whenever possible, routines
- * should be using pointers to a drive (ide_drive_t *) or
- * pointers to a hwif (ide_hwif_t *), rather than indexing this
- * structure directly (the allocation/layout may change!).
- *
- */
-#ifndef _IDE_C
-extern	ide_hwif_t	ide_hwifs[];		/* master data repository */
-extern  ide_module_t	*ide_modules;
-#endif
-
-/*
- * We need blk.h, but we replace its end_request by our own version.
- */
-#define IDE_DRIVER		/* Toggle some magic bits in blk.h */
-#define LOCAL_END_REQUEST	/* Don't generate end_request in blk.h */
-#include <linux/blk.h>
-
-void ide_end_request(byte uptodate, ide_hwgroup_t *hwgroup);
-
-/*
- * This is used for (nearly) all data transfers from/to the IDE interface
- */
-void ide_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount);
-void ide_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount);
-
-/*
- * This is used for (nearly) all ATAPI data transfers from/to the IDE interface
- */
-void atapi_input_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount);
-void atapi_output_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount);
-
-/*
- * This is used on exit from the driver, to designate the next irq handler
- * and also to start the safety timer.
- */
-void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, unsigned int timeout);
-
-/*
- * Error reporting, in human readable form (luxurious, but a memory hog).
- */
-byte ide_dump_status (ide_drive_t *drive, const char *msg, byte stat);
-
-/*
- * ide_error() takes action based on the error returned by the controller.
- * The calling function must return afterwards, to restart the request.
- */
-void ide_error (ide_drive_t *drive, const char *msg, byte stat);
-
-/*
- * Issue a simple drive command
- * The drive must be selected beforehand.
- */
-void ide_cmd(ide_drive_t *drive, byte cmd, byte nsect, ide_handler_t *handler);
-
-/*
- * ide_fixstring() cleans up and (optionally) byte-swaps a text string,
- * removing leading/trailing blanks and compressing internal blanks.
- * It is primarily used to tidy up the model name/number fields as
- * returned by the WIN_[P]IDENTIFY commands.
- */
-void ide_fixstring (byte *s, const int bytecount, const int byteswap);
-
-/*
- * This routine busy-waits for the drive status to be not "busy".
- * It then checks the status for all of the "good" bits and none
- * of the "bad" bits, and if all is okay it returns 0.  All other
- * cases return 1 after invoking ide_error() -- caller should return.
- *
- */
-int ide_wait_stat (ide_drive_t *drive, byte good, byte bad, unsigned long timeout);
-
-/*
- * This routine is called from the partition-table code in genhd.c
- * to "convert" a drive to a logical geometry with fewer than 1024 cyls.
- *
- * The second parameter, "xparm", determines exactly how the translation
- * will be handled:
- *		 0 = convert to CHS with fewer than 1024 cyls
- *			using the same method as Ontrack DiskManager.
- *		 1 = same as "0", plus offset everything by 63 sectors.
- *		-1 = similar to "0", plus redirect sector 0 to sector 1.
- *		>1 = convert to a CHS geometry with "xparm" heads.
- *
- * Returns 0 if the translation was not possible, if the device was not
- * an IDE disk drive, or if a geometry was "forced" on the commandline.
- * Returns 1 if the geometry translation was successful.
- */
-int ide_xlate_1024 (kdev_t, int, const char *);
-
-/*
- * Start a reset operation for an IDE interface.
- * The caller should return immediately after invoking this.
- */
-void ide_do_reset (ide_drive_t *);
-
-/*
- * This function is intended to be used prior to invoking ide_do_drive_cmd().
- */
-void ide_init_drive_cmd (struct request *rq);
-
-/*
- * "action" parameter type for ide_do_drive_cmd() below.
- */
-typedef enum
-	{ide_wait,	/* insert rq at end of list, and wait for it */
-	 ide_next,	/* insert rq immediately after current request */
-	 ide_preempt,	/* insert rq in front of current request */
-	 ide_end}	/* insert rq at end of list, but don't wait for it */
- ide_action_t;
-
-/*
- * This function issues a special IDE device request
- * onto the request queue.
- *
- * If action is ide_wait, then the rq is queued at the end of the
- * request queue, and the function sleeps until it has been processed.
- * This is for use when invoked from an ioctl handler.
- *
- * If action is ide_preempt, then the rq is queued at the head of
- * the request queue, displacing the currently-being-processed
- * request and this function returns immediately without waiting
- * for the new rq to be completed.  This is VERY DANGEROUS, and is
- * intended for careful use by the ATAPI tape/cdrom driver code.
- *
- * If action is ide_next, then the rq is queued immediately after
- * the currently-being-processed-request (if any), and the function
- * returns without waiting for the new rq to be completed.  As above,
- * This is VERY DANGEROUS, and is intended for careful use by the
- * ATAPI tape/cdrom driver code.
- *
- * If action is ide_end, then the rq is queued at the end of the
- * request queue, and the function returns immediately without waiting
- * for the new rq to be completed. This is again intended for careful
- * use by the ATAPI tape/cdrom driver code.
- */
-int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t action);
-
-/*
- * Clean up after success/failure of an explicit drive cmd.
- * stat/err are used only when (HWGROUP(drive)->rq->cmd == IDE_DRIVE_CMD).
- */
-void ide_end_drive_cmd (ide_drive_t *drive, byte stat, byte err);
-
-/*
- * Issue ATA command and wait for completion.
- */
-int ide_wait_cmd (ide_drive_t *drive, int cmd, int nsect, int feature, int sectors, byte *buf);
-
-/*
- * ide_system_bus_speed() returns what we think is the system VESA/PCI
- * bus speed (in MHz).  This is used for calculating interface PIO timings.
- * The default is 40 for known PCI systems, 50 otherwise.
- * The "idebus=xx" parameter can be used to override this value.
- */
-int ide_system_bus_speed (void);
-
-/*
- * ide_multwrite() transfers a block of up to mcount sectors of data
- * to a drive as part of a disk multwrite operation.
- */
-void ide_multwrite (ide_drive_t *drive, unsigned int mcount);
-
-/*
- * ide_stall_queue() can be used by a drive to give excess bandwidth back
- * to the hwgroup by sleeping for timeout jiffies.
- */
-void ide_stall_queue (ide_drive_t *drive, unsigned long timeout);
-
-/*
- * ide_get_queue() returns the queue which corresponds to a given device.
- */
-struct request **ide_get_queue (kdev_t dev);
-
-/*
- * CompactFlash cards and their brethern pretend to be removable hard disks,
- * but they never have a slave unit, and they don't have doorlock mechanisms.
- * This test catches them, and is invoked elsewhere when setting appropriate config bits.
- */
-int drive_is_flashcard (ide_drive_t *drive);
-
-int  ide_spin_wait_hwgroup(ide_drive_t *drive, unsigned long *flags);
-void ide_timer_expiry (unsigned long data);
-void ide_intr (int irq, void *dev_id, struct pt_regs *regs);
-void ide_geninit (struct gendisk *gd);
-void do_ide0_request (void);
-#if MAX_HWIFS > 1
-void do_ide1_request (void);
-#endif
-#if MAX_HWIFS > 2
-void do_ide2_request (void);
-#endif
-#if MAX_HWIFS > 3
-void do_ide3_request (void);
-#endif
-#if MAX_HWIFS > 4
-void do_ide4_request (void);
-#endif
-#if MAX_HWIFS > 5
-void do_ide5_request (void);
-#endif
-void ide_init_subdrivers (void);
-
-#ifndef _IDE_C
-extern struct file_operations ide_fops[];
-#endif
-
-#ifdef _IDE_C
-#ifdef CONFIG_BLK_DEV_IDE
-int ideprobe_init (void);
-#endif /* CONFIG_BLK_DEV_IDE */
-#ifdef CONFIG_BLK_DEV_IDEDISK
-int idedisk_init (void);
-#endif /* CONFIG_BLK_DEV_IDEDISK */
-#ifdef CONFIG_BLK_DEV_IDECD
-int ide_cdrom_init (void);
-#endif /* CONFIG_BLK_DEV_IDECD */
-#ifdef CONFIG_BLK_DEV_IDETAPE
-int idetape_init (void);
-#endif /* CONFIG_BLK_DEV_IDETAPE */
-#ifdef CONFIG_BLK_DEV_IDEFLOPPY
-int idefloppy_init (void);
-#endif /* CONFIG_BLK_DEV_IDEFLOPPY */
-#ifdef CONFIG_BLK_DEV_IDESCSI
-int idescsi_init (void);
-#endif /* CONFIG_BLK_DEV_IDESCSI */
-#endif /* _IDE_C */
-
-int ide_register_module (ide_module_t *module);
-void ide_unregister_module (ide_module_t *module);
-ide_drive_t *ide_scan_devices (byte media, const char *name, ide_driver_t *driver, int n);
-int ide_register_subdriver (ide_drive_t *drive, ide_driver_t *driver, int version);
-int ide_unregister_subdriver (ide_drive_t *drive);
-int ide_replace_subdriver(ide_drive_t *drive, const char *driver);
-
-#ifdef CONFIG_BLK_DEV_IDEPCI
-#define ON_BOARD		1
-#define NEVER_BOARD		0
-#ifdef CONFIG_BLK_DEV_OFFBOARD
-#  define OFF_BOARD		ON_BOARD
-#else /* CONFIG_BLK_DEV_OFFBOARD */
-#  define OFF_BOARD		NEVER_BOARD
-#endif /* CONFIG_BLK_DEV_OFFBOARD */
-
-unsigned long ide_find_free_region (unsigned short size) __init;
-void ide_scan_pcibus (void) __init;
-#endif
-#ifdef CONFIG_BLK_DEV_IDEDMA
-#define BAD_DMA_DRIVE		0
-#define GOOD_DMA_DRIVE		1
-int ide_build_dmatable (ide_drive_t *drive);
-void ide_dma_intr  (ide_drive_t *drive);
-int check_drive_lists (ide_drive_t *drive, int good_bad);
-int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive);
-int ide_release_dma (ide_hwif_t *hwif);
-void ide_setup_dma (ide_hwif_t *hwif, unsigned long dmabase, unsigned int num_ports) __init;
-unsigned long ide_get_or_set_dma_base (ide_hwif_t *hwif, int extra, const char *name) __init;
-#endif
-
-#ifdef CONFIG_BLK_DEV_PDC4030
-#include "pdc4030.h"
-#define IS_PDC4030_DRIVE (HWIF(drive)->chipset == ide_pdc4030)
-#else
-#define IS_PDC4030_DRIVE (0)	/* auto-NULLs out pdc4030 code */
-#endif /* CONFIG_BLK_DEV_PDC4030 */
-
-#endif /* _IDE_H */
diff -u --recursive --new-file v2.3.0/linux/drivers/block/ide_modes.h linux/drivers/block/ide_modes.h
--- v2.3.0/linux/drivers/block/ide_modes.h	Tue May 11 13:03:59 1999
+++ linux/drivers/block/ide_modes.h	Thu May 13 14:42:14 1999
@@ -15,7 +15,7 @@
  * breaking the fragile cmd640.c support.
  */
 
-#if defined(CONFIG_BLK_DEV_CMD640) || defined(CONFIG_IDE_CHIPSETS) || defined(CONFIG_BLK_DEV_OPTI621) || defined(CONFIG_BLK_DEV_IDE_PMAC)
+#ifdef CONFIG_BLK_DEV_IDE_MODES
 
 /*
  * Standard (generic) timings for PIO modes, from ATA2 specification.
@@ -111,6 +111,8 @@
 	{ "ST3600A",  1 },
 	{ "ST3290A",  0 },
 	{ "ST3144A",  0 },
+	{ "ST3491A",  1 },	/* reports 3, should be 1 or 2 (depending on */	
+				/* drive) according to Seagates FIND-ATA program */
 
 	{ "QUANTUM ELS127A", 0 },
 	{ "QUANTUM ELS170A", 0 },
@@ -222,5 +224,5 @@
 }
 
 #endif /* _IDE_C */
-#endif /* defined(CONFIG_BLK_DEV_CMD640) || defined(CONFIG_IDE_CHIPSETS) || defined(CONFIG_BLK_DEV_OPTI621) */
+#endif /* CONFIG_BLK_DEV_IDE_MODES */
 #endif /* _IDE_MODES_H */
diff -u --recursive --new-file v2.3.0/linux/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c
--- v2.3.0/linux/drivers/block/ll_rw_blk.c	Thu Mar 11 23:20:14 1999
+++ linux/drivers/block/ll_rw_blk.c	Tue May 11 14:37:40 1999
@@ -53,7 +53,7 @@
 /*
  * used to wait on when there are no free requests
  */
-struct wait_queue * wait_for_request = NULL;
+DECLARE_WAIT_QUEUE_HEAD(wait_for_request);
 
 /* This specifies how many sectors to read ahead on the disk.  */
 
@@ -208,7 +208,7 @@
 static struct request * __get_request_wait(int n, kdev_t dev)
 {
 	register struct request *req;
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 	unsigned long flags;
 
 	add_wait_queue(&wait_for_request, &wait);
diff -u --recursive --new-file v2.3.0/linux/drivers/block/macide.c linux/drivers/block/macide.c
--- v2.3.0/linux/drivers/block/macide.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/block/macide.c	Thu May 13 11:04:54 1999
@@ -0,0 +1,167 @@
+/*
+ *  linux/drivers/block/macide.c -- Macintosh IDE Driver
+ *
+ *     Copyright (C) 1998 by Michael Schmitz
+ *
+ *  This driver was written based on information obtained from the MacOS IDE
+ *  driver binary by Mikael Forselius
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+#include <linux/zorro.h>
+#include <linux/ide.h>
+
+#include <asm/machw.h>
+#include <asm/macintosh.h>
+#include <asm/macints.h>
+
+    /*
+     *  Base of the IDE interface (see ATAManager ROM code)
+     */
+
+#define MAC_HD_BASE	0x50f1a000
+
+    /*
+     *  Offsets from the above base (scaling 4)
+     */
+
+#define MAC_HD_DATA	0x00
+#define MAC_HD_ERROR	0x04		/* see err-bits */
+#define MAC_HD_NSECTOR	0x08		/* nr of sectors to read/write */
+#define MAC_HD_SECTOR	0x0c		/* starting sector */
+#define MAC_HD_LCYL	0x10		/* starting cylinder */
+#define MAC_HD_HCYL	0x14		/* high byte of starting cyl */
+#define MAC_HD_SELECT	0x18		/* 101dhhhh , d=drive, hhhh=head */
+#define MAC_HD_STATUS	0x1c		/* see status-bits */
+#define MAC_HD_CONTROL	0x38		/* control/altstatus */
+
+static int macide_offsets[IDE_NR_PORTS] = {
+    MAC_HD_DATA, MAC_HD_ERROR, MAC_HD_NSECTOR, MAC_HD_SECTOR, MAC_HD_LCYL,
+    MAC_HD_HCYL, MAC_HD_SELECT, MAC_HD_STATUS, MAC_HD_CONTROL
+};
+
+	/*
+	 * Other registers
+	 */
+
+	/* 
+	 * IDE interrupt status register for both (?) hwifs on Quadra
+	 * Initial setting: 0xc
+	 * Guessing again:
+	 * Bit 0+1: some interrupt flags
+	 * Bit 2+3: some interrupt enable
+	 * Bit 4:   ??
+	 * Bit 5:   IDE interrupt flag (any hwif)
+	 * Bit 6:   maybe IDE interrupt enable (any hwif) ??
+	 * Bit 7:   Any interrupt condition
+	 *
+	 * Only relevant item: bit 5, to be checked by mac_ack_intr
+	 */
+
+#define MAC_HD_ISR	0x101
+
+	/*
+	 * IDE interrupt glue - seems to be wired to Nubus, Slot C?
+	 * (ROM code disassembly again)
+	 * First try: just use Nubus interrupt for Slot C. Have Nubus code call
+	 * a wrapper to ide_intr that checks the ISR (see above).
+	 * Need to #define IDE_IRQ_NUBUS though.
+	 * Alternative method: set a mac_ide_hook function pointer to the wrapper 
+	 * here and have via_do_nubus call that hook if set. 
+	 *
+	 * Quadra needs the hook, Powerbook can use Nubus slot C. 
+	 * Checking the ISR on Quadra is done by mac_ack_intr (see Amiga code). mac_ide_intr
+	 * mac_ide_intr is obsolete except for providing the hwgroup argument.
+	 */
+
+	/* The Mac hwif data, for passing hwgroup to ide_intr */
+static ide_hwif_t *mac_hwif = NULL;
+
+	/* The function pointer used in the Nubus handler */
+void (*mac_ide_intr_hook)(int, void *, struct pt_regs *) = NULL;
+
+	/*
+	 * Only purpose: feeds the hwgroup to the main IDE handler. 
+	 * Obsolete as soon as Nubus code is fixed WRT pseudo slot C int.
+	 * (should be the case on Powerbooks)
+	 * Alas, second purpose: feed correct irq to IDE handler (I know,
+	 * that's cheating) :-(((
+	 * Fix needed for interrupt code: accept Nubus ints in the regular
+	 * request_irq code, then register Powerbook IDE as Nubus slot C, 
+	 * Quadra as slot F (F for fictious).
+	 */
+void mac_ide_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+	ide_intr(mac_hwif->irq, mac_hwif->hwgroup, regs);
+}
+
+    /*
+     *  Check the interrupt status
+     *
+     *  Note: In 2.0 kernels, there have been timing problems with the 
+     *  Powerbook IDE interface (BUSY was asserted too long after the
+     *  interrupt triggered). Result: repeated errors, recalibrate etc. 
+     *  Adding a wait loop to read_intr, write_intr and set_geom_intr
+     *  fixed the problem (waits in read/write_intr were present for Amiga
+     *  already). 
+     *  Powerbooks were not tested with 2.1 due to lack of FPU emulation
+     *  (thanks Apple for using LC040). If the BUSY problem resurfaces in 
+     *  2.1, my best bet would be to add the wait loop right here, afterr
+     *  checking the interrupt register.
+     */
+
+static int mac_ack_intr(ide_hwif_t *hwif)
+{
+    unsigned char ch;
+
+    ch = inb(hwif->io_ports[IDE_IRQ_OFFSET]);
+    if (!(ch & 0x20))
+	return 0;
+    return 1;
+}
+
+    /*
+     *  Probe for a Macintosh IDE interface
+     */
+
+void macide_init(void)
+{
+    hw_regs_t hw;
+    int index = -1;
+
+    if (MACH_IS_MAC) {
+	switch(macintosh_config->ide_type) {
+	case 0:
+	    break;
+
+	case MAC_IDE_QUADRA:
+	    ide_setup_ports(&hw, (ide_ioreg_t)MAC_HD_BASE, macide_offsets,
+	    		    0, (ide_ioreg_t)(MAC_HD_BASE+MAC_HD_ISR),
+			    mac_ack_intr, IRQ_MAC_NUBUS);
+	    index = ide_register_hw(&hw, &mac_hwif);
+	    mac_ide_intr_hook = mac_ide_intr;
+	    break;
+
+	default:
+	    ide_setup_ports(&hw, (ide_ioreg_t)MAC_HD_BASE, macide_offsets,
+	    		    0, 0, NULL, IRQ_MAC_NUBUS);
+	    index = ide_register_hw(&hw, &mac_hwif);
+	    break;
+	}
+
+        if (index != -1) {
+	    if (macintosh_config->ide_type == MAC_IDE_QUADRA)
+		printk("ide%d: Macintosh Quadra IDE interface\n", index);
+	    else
+		printk("ide%d: Macintosh Powerbook IDE interface\n", index);
+	}
+    }
+}
diff -u --recursive --new-file v2.3.0/linux/drivers/block/md.c linux/drivers/block/md.c
--- v2.3.0/linux/drivers/block/md.c	Sat Oct 31 10:37:14 1998
+++ linux/drivers/block/md.c	Wed May 12 08:41:12 1999
@@ -817,12 +817,12 @@
 	struct md_thread *thread = (struct md_thread *)
 		kmalloc(sizeof(struct md_thread), GFP_KERNEL);
 	int ret;
-	struct semaphore sem = MUTEX_LOCKED;
+	DECLARE_MUTEX_LOCKED(sem);
 	
 	if (!thread) return NULL;
 	
 	memset(thread, 0, sizeof(struct md_thread));
-	init_waitqueue(&thread->wqueue);
+	init_waitqueue_head(&thread->wqueue);
 	
 	thread->sem = &sem;
 	thread->run = run;
@@ -838,7 +838,7 @@
 
 void md_unregister_thread (struct md_thread *thread)
 {
-	struct semaphore sem = MUTEX_LOCKED;
+	DECLARE_MUTEX_LOCKED(sem);
 	
 	thread->sem = &sem;
 	thread->run = NULL;
diff -u --recursive --new-file v2.3.0/linux/drivers/block/nbd.c linux/drivers/block/nbd.c
--- v2.3.0/linux/drivers/block/nbd.c	Tue Mar  9 16:58:05 1999
+++ linux/drivers/block/nbd.c	Wed May 12 08:41:12 1999
@@ -75,7 +75,7 @@
 	nbdev = &nbd_dev[dev];
 	nbd_dev[dev].refcnt++;
 	if (!(nbdev->flags & NBD_INITIALISED)) {
-		nbdev->queue_lock = MUTEX;
+		init_MUTEX(&nbdev->queue_lock);
 		nbdev->flags |= NBD_INITIALISED;
 	}
 	MOD_INC_USE_COUNT;
diff -u --recursive --new-file v2.3.0/linux/drivers/block/ns87415.c linux/drivers/block/ns87415.c
--- v2.3.0/linux/drivers/block/ns87415.c	Mon Mar 15 16:11:29 1999
+++ linux/drivers/block/ns87415.c	Thu May 13 11:04:54 1999
@@ -17,9 +17,9 @@
 #include <linux/hdreg.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
-#include <asm/io.h>
-#include "ide.h"
+#include <linux/ide.h>
 
+#include <asm/io.h>
 
 static unsigned int ns87415_count = 0, ns87415_control[MAX_HWIFS] = { 0 };
 
diff -u --recursive --new-file v2.3.0/linux/drivers/block/opti621.c linux/drivers/block/opti621.c
--- v2.3.0/linux/drivers/block/opti621.c	Mon Jan  4 15:07:27 1999
+++ linux/drivers/block/opti621.c	Thu May 13 11:04:54 1999
@@ -98,8 +98,10 @@
 #include <linux/ioport.h>
 #include <linux/blkdev.h>
 #include <linux/hdreg.h>
+#include <linux/ide.h>
+
 #include <asm/io.h>
-#include "ide.h"
+
 #include "ide_modes.h"
 
 #define OPTI621_MAX_PIO 3
diff -u --recursive --new-file v2.3.0/linux/drivers/block/paride/paride.c linux/drivers/block/paride/paride.c
--- v2.3.0/linux/drivers/block/paride/paride.c	Tue Dec 22 08:29:00 1998
+++ linux/drivers/block/paride/paride.c	Wed May 12 13:27:37 1999
@@ -247,7 +247,7 @@
 	pi->pardev = (void *) parport_register_device(
 	      pp,pi->device,NULL,pi_wake_up,NULL,0,(void *)pi);
 
-	pi->parq = NULL;
+	init_wait_queue_head(&pi->parq);
 
 	if (verbose) printk("%s: 0x%x is %s\n",pi->device,pi->port,pp->name);
 	
@@ -357,7 +357,7 @@
 
 		pi->parname = NULL;
 		pi->pardev = NULL;
-		pi->parq = NULL;
+		init_wait_queue_head(&pi->parq);
 		pi->claimed = 0;
 		pi->claim_cont = NULL;
 	        
diff -u --recursive --new-file v2.3.0/linux/drivers/block/paride/paride.h linux/drivers/block/paride/paride.h
--- v2.3.0/linux/drivers/block/paride/paride.h	Sat Jun 13 12:08:19 1998
+++ linux/drivers/block/paride/paride.h	Wed May 12 13:27:37 1999
@@ -44,7 +44,7 @@
 	int	reserved;	     /* number of ports reserved */
 	int	private;	     /* for protocol module */
 
-	struct wait_queue *parq;     /* semaphore for parport sharing */
+	wait_queue_head_t parq;     /* semaphore for parport sharing */
 	void	*pardev;	     /* pointer to pardevice */
 	char	*parname;	     /* parport name */
 	int	claimed;	     /* parport has already been claimed */
diff -u --recursive --new-file v2.3.0/linux/drivers/block/pdc202xx.c linux/drivers/block/pdc202xx.c
--- v2.3.0/linux/drivers/block/pdc202xx.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/block/pdc202xx.c	Thu May 13 11:04:54 1999
@@ -0,0 +1,568 @@
+/*
+ *  linux/drivers/block/pdc202xx.c	Version 0.26	May 12, 1999
+ *
+ *  Copyright (C) 1998-99	Andre Hedrick
+ *					(hedrick@astro.dyer.vanderbilt.edu)
+ *
+ *  Promise Ultra33 cards with BIOS v1.20 through 1.28 will need this
+ *  compiled into the kernel if you have more than one card installed.
+ *  Note that BIOS v1.29 is reported to fix the problem.  Since this is
+ *  safe chipset tuning, including this support is harmless
+ *
+ *  The latest chipset code will support the following ::
+ *  Three Ultra33 controllers and 12 drives.
+ *  8 are UDMA supported and 4 are limited to DMA mode 2 multi-word.
+ *  The 8/4 ratio is a BIOS code limit by promise.
+ *
+ *  UNLESS you enable "PDC202XX_FORCE_BURST_BIT"
+ *
+ *  There is only one BIOS in the three contollers.
+ *
+ *  May  8 20:56:17 Orion kernel:
+ *  Uniform Multi-Platform E-IDE driver Revision: 6.19
+ *  PDC20246: IDE controller on PCI bus 00 dev a0
+ *  PDC20246: not 100% native mode: will probe irqs later
+ *  PDC20246: ROM enabled at 0xfebd0000
+ *  PDC20246: (U)DMA Burst Bit ENABLED Primary PCI Mode Secondary PCI Mode.
+ *      ide0: BM-DMA at 0xef80-0xef87, BIOS settings: hda:DMA, hdb:DMA
+ *      ide1: BM-DMA at 0xef88-0xef8f, BIOS settings: hdc:pio, hdd:pio
+ *  PDC20246: IDE controller on PCI bus 00 dev 98
+ *  PDC20246: not 100% native mode: will probe irqs later
+ *  PDC20246: ROM enabled at 0xfebc0000
+ *  PDC20246: (U)DMA Burst Bit ENABLED Primary PCI Mode Secondary PCI Mode.
+ *      ide2: BM-DMA at 0xef40-0xef47, BIOS settings: hde:DMA, hdf:DMA
+ *      ide3: BM-DMA at 0xef48-0xef4f, BIOS settings: hdg:DMA, hdh:DMA
+ *  PDC20246: IDE controller on PCI bus 00 dev 90
+ *  PDC20246: not 100% native mode: will probe irqs later
+ *  PDC20246: ROM enabled at 0xfebb0000
+ *  PDC20246: (U)DMA Burst Bit DISABLED Primary PCI Mode Secondary PCI Mode.
+ *  PDC20246: FORCING BURST BIT 0x00 -> 0x01 ACTIVE
+ *      ide4: BM-DMA at 0xef00-0xef07, BIOS settings: hdi:DMA, hdj:pio
+ *      ide5: BM-DMA at 0xef08-0xef0f, BIOS settings: hdk:pio, hdl:pio
+ *  PIIX3: IDE controller on PCI bus 00 dev 39
+ *  PIIX3: device not capable of full native PCI mode
+ *
+ *  ide0 at 0xeff0-0xeff7,0xefe6 on irq 19
+ *  ide1 at 0xefa8-0xefaf,0xebe6 on irq 19
+ *  ide2 at 0xefa0-0xefa7,0xef7e on irq 18
+ *  ide3 at 0xef68-0xef6f,0xef66 on irq 18
+ *  ide4 at 0xef38-0xef3f,0xef62 on irq 17
+ *  hda: QUANTUM FIREBALL ST6.4A, 6149MB w/81kB Cache, CHS=13328/15/63, UDMA(33)
+ *  hdb: QUANTUM FIREBALL ST3.2A, 3079MB w/81kB Cache, CHS=6256/16/63, UDMA(33)
+ *  hde: Maxtor 72004 AP, 1916MB w/128kB Cache, CHS=3893/16/63, DMA
+ *  hdf: Maxtor 71626 A, 1554MB w/64kB Cache, CHS=3158/16/63, DMA
+ *  hdi: Maxtor 90680D4, 6485MB w/256kB Cache, CHS=13176/16/63, UDMA(33)
+ *  hdj: Maxtor 90680D4, 6485MB w/256kB Cache, CHS=13176/16/63, UDMA(33)
+ *
+ *  Promise Ultra66 cards with BIOS v1.11 this
+ *  compiled into the kernel if you have more than one card installed.
+ *
+ *  PDC20262: IDE controller on PCI bus 00 dev a0
+ *  PDC20262: not 100% native mode: will probe irqs later
+ *  PDC20262: ROM enabled at 0xfebb0000
+ *  PDC20262: (U)DMA Burst Bit ENABLED Primary PCI Mode Secondary PCI Mode.
+ *      ide0: BM-DMA at 0xef00-0xef07, BIOS settings: hda:pio, hdb:pio
+ *      ide1: BM-DMA at 0xef08-0xef0f, BIOS settings: hdc:pio, hdd:pio
+ *
+ *  UDMA 4/2 and UDMA 3/1 only differ by the testing bit 13 in word93.
+ *  Chipset timing speeds must be identical
+ *
+ *  drive_number
+ *      = ((HWIF(drive)->channel ? 2 : 0) + (drive->select.b.unit & 0x01));
+ *      = ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01));
+ */
+
+#include <linux/config.h>	/* for CONFIG_BLK_DEV_IDEPCI */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/ioport.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/ide.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#define PDC202XX_DEBUG_DRIVE_INFO		0
+#define PDC202XX_DECODE_REGISTER_INFO		0
+#define PDC202XX_FORCE_BURST_BIT		0
+#define PDC202XX_FORCE_MASTER_MODE		0
+
+extern char *ide_xfer_verbose (byte xfer_rate);
+
+/* A Register */
+#define	SYNC_ERRDY_EN	0xC0
+
+#define	SYNC_IN		0x80	/* control bit, different for master vs. slave drives */
+#define	ERRDY_EN	0x40	/* control bit, different for master vs. slave drives */
+#define	IORDY_EN	0x20	/* PIO: IOREADY */
+#define	PREFETCH_EN	0x10	/* PIO: PREFETCH */
+
+#define	PA3		0x08	/* PIO"A" timing */
+#define	PA2		0x04	/* PIO"A" timing */
+#define	PA1		0x02	/* PIO"A" timing */
+#define	PA0		0x01	/* PIO"A" timing */
+
+/* B Register */
+
+#define	MB2		0x80	/* DMA"B" timing */
+#define	MB1		0x40	/* DMA"B" timing */
+#define	MB0		0x20	/* DMA"B" timing */
+
+#define	PB4		0x10	/* PIO_FORCE 1:0 */
+
+#define	PB3		0x08	/* PIO"B" timing */	/* PIO flow Control mode */
+#define	PB2		0x04	/* PIO"B" timing */	/* PIO 4 */
+#define	PB1		0x02	/* PIO"B" timing */	/* PIO 3 half */
+#define	PB0		0x01	/* PIO"B" timing */	/* PIO 3 other half */
+
+/* C Register */
+#define	IORDYp_NO_SPEED	0x4F
+#define	SPEED_DIS	0x0F
+
+#define	DMARQp		0x80
+#define	IORDYp		0x40
+#define	DMAR_EN		0x20
+#define	DMAW_EN		0x10
+
+#define	MC3		0x08	/* DMA"C" timing */
+#define	MC2		0x04	/* DMA"C" timing */
+#define	MC1		0x02	/* DMA"C" timing */
+#define	MC0		0x01	/* DMA"C" timing */
+
+#if PDC202XX_DECODE_REGISTER_INFO
+
+#define REG_A		0x01
+#define REG_B		0x02
+#define REG_C		0x04
+#define REG_D		0x08
+
+static void decode_registers (byte registers, byte value)
+{
+	byte	bit = 0, bit1 = 0, bit2 = 0;
+
+	switch(registers) {
+		case REG_A:
+			bit2 = 0;
+			printk("A Register ");
+			if (value & 0x80) printk("SYNC_IN ");
+			if (value & 0x40) printk("ERRDY_EN ");
+			if (value & 0x20) printk("IORDY_EN ");
+			if (value & 0x10) printk("PREFETCH_EN ");
+			if (value & 0x08) { printk("PA3 ");bit2 |= 0x08; }
+			if (value & 0x04) { printk("PA2 ");bit2 |= 0x04; }
+			if (value & 0x02) { printk("PA1 ");bit2 |= 0x02; }
+			if (value & 0x01) { printk("PA0 ");bit2 |= 0x01; }
+			printk("PIO(A) = %d ", bit2);
+			break;
+		case REG_B:
+			bit1 = 0;bit2 = 0;
+			printk("B Register ");
+			if (value & 0x80) { printk("MB2 ");bit1 |= 0x80; }
+			if (value & 0x40) { printk("MB1 ");bit1 |= 0x40; }
+			if (value & 0x20) { printk("MB0 ");bit1 |= 0x20; }
+			printk("DMA(B) = %d ", bit1 >> 5);
+			if (value & 0x10) printk("PIO_FORCED/PB4 ");
+			if (value & 0x08) { printk("PB3 ");bit2 |= 0x08; }
+			if (value & 0x04) { printk("PB2 ");bit2 |= 0x04; }
+			if (value & 0x02) { printk("PB1 ");bit2 |= 0x02; }
+			if (value & 0x01) { printk("PB0 ");bit2 |= 0x01; }
+			printk("PIO(B) = %d ", bit2);
+			break;
+		case REG_C:
+			bit2 = 0;
+			printk("C Register ");
+			if (value & 0x80) printk("DMARQp ");
+			if (value & 0x40) printk("IORDYp ");
+			if (value & 0x20) printk("DMAR_EN ");
+			if (value & 0x10) printk("DMAW_EN ");
+
+			if (value & 0x08) { printk("MC3 ");bit2 |= 0x08; }
+			if (value & 0x04) { printk("MC2 ");bit2 |= 0x04; }
+			if (value & 0x02) { printk("MC1 ");bit2 |= 0x02; }
+			if (value & 0x01) { printk("MC0 ");bit2 |= 0x01; }
+			printk("DMA(C) = %d ", bit2);
+			break;
+		case REG_D:
+			printk("D Register ");
+			break;
+		default:
+			return;
+	}
+	printk("\n        %s ", (registers & REG_D) ? "DP" :
+				(registers & REG_C) ? "CP" :
+				(registers & REG_B) ? "BP" :
+				(registers & REG_A) ? "AP" : "ERROR");
+	for (bit=128;bit>0;bit/=2)
+		printk("%s", (value & bit) ? "1" : "0");
+	printk("\n");
+}
+
+#endif /* PDC202XX_DECODE_REGISTER_INFO */
+
+static int config_chipset_for_dma (ide_drive_t *drive, byte ultra)
+{
+	struct hd_driveid *id	= drive->id;
+	ide_hwif_t *hwif	= HWIF(drive);
+	struct pci_dev *dev	= hwif->pci_dev;
+
+	int			err;
+	unsigned int		drive_conf;
+	byte			drive_pci;
+	byte			test1, test2, speed;
+	byte			AP, BP, CP, DP, EP;
+	int drive_number	= ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01));
+	byte udma_66		= ((id->word93 & 0x2000) && (dev->device == PCI_DEVICE_ID_PROMISE_20262)) ? 1 : 0;
+	byte udma_33		= ultra ? (inb((dev->base_address[4] & PCI_BASE_ADDRESS_IO_MASK) + 0x001f) & 1) : 0;
+
+	pci_read_config_byte(dev, 0x50, &EP);
+
+	switch(drive_number) {
+		case 0:	drive_pci = 0x60;
+			pci_read_config_dword(dev, drive_pci, &drive_conf);
+			if ((drive_conf != 0x004ff304) && (drive_conf != 0x004ff3c4))
+				goto chipset_is_set;
+			pci_read_config_byte(dev, (drive_pci), &test1);
+			if (!(test1 & SYNC_ERRDY_EN))
+				pci_write_config_byte(dev, (drive_pci), test1|SYNC_ERRDY_EN);
+			break;
+		case 1:	drive_pci = 0x64;
+			pci_read_config_dword(dev, drive_pci, &drive_conf);
+			if ((drive_conf != 0x004ff304) && (drive_conf != 0x004ff3c4))
+				goto chipset_is_set;
+			pci_read_config_byte(dev, 0x60, &test1);
+			pci_read_config_byte(dev, (drive_pci), &test2);
+			if ((test1 & SYNC_ERRDY_EN) && !(test2 & SYNC_ERRDY_EN))
+				pci_write_config_byte(dev, (drive_pci), test2|SYNC_ERRDY_EN);
+			break;
+		case 2:	drive_pci = 0x68;
+			pci_read_config_dword(dev, drive_pci, &drive_conf);
+			if ((drive_conf != 0x004ff304) && (drive_conf != 0x004ff3c4))
+				goto chipset_is_set;
+			pci_read_config_byte(dev, (drive_pci), &test1);
+			if (!(test1 & SYNC_ERRDY_EN))
+				pci_write_config_byte(dev, (drive_pci), test1|SYNC_ERRDY_EN);
+			break;
+		case 3:	drive_pci = 0x6c;
+			pci_read_config_dword(dev, drive_pci, &drive_conf);
+			if ((drive_conf != 0x004ff304) && (drive_conf != 0x004ff3c4))
+				goto chipset_is_set;
+			pci_read_config_byte(dev, 0x68, &test1);
+			pci_read_config_byte(dev, (drive_pci), &test2);
+			if ((test1 & SYNC_ERRDY_EN) && !(test2 & SYNC_ERRDY_EN))
+				pci_write_config_byte(dev, (drive_pci), test2|SYNC_ERRDY_EN);
+			break;
+		default:
+			return ide_dma_off;
+	}
+
+	if (drive->media != ide_disk)
+		return ide_dma_off_quietly;
+
+	pci_read_config_byte(dev, (drive_pci), &AP);
+	pci_read_config_byte(dev, (drive_pci)|0x01, &BP);
+	pci_read_config_byte(dev, (drive_pci)|0x02, &CP);
+	pci_read_config_byte(dev, (drive_pci)|0x03, &DP);
+
+	if (id->capability & 4) {		/* IORDY_EN */
+		pci_write_config_byte(dev, (drive_pci), AP|IORDY_EN);
+		pci_read_config_byte(dev, (drive_pci), &AP);
+	}
+
+	if (drive->media == ide_disk) {		/* PREFETCH_EN */
+		pci_write_config_byte(dev, (drive_pci), AP|PREFETCH_EN);
+		pci_read_config_byte(dev, (drive_pci), &AP);
+	}
+
+	if ((BP & 0xF0) && (CP & 0x0F)) {
+		/* clear DMA modes of upper 842 bits of B Register */
+		/* clear PIO forced mode upper 1 bit of B Register */
+		pci_write_config_byte(dev, (drive_pci)|0x01, BP & ~0xF0);
+		pci_read_config_byte(dev, (drive_pci)|0x01, &BP);
+
+		/* clear DMA modes of lower 8421 bits of C Register */
+		pci_write_config_byte(dev, (drive_pci)|0x02, CP & ~0x0F);
+		pci_read_config_byte(dev, (drive_pci)|0x02, &CP);
+	}
+
+	pci_read_config_byte(dev, (drive_pci), &AP);
+	pci_read_config_byte(dev, (drive_pci)|0x01, &BP);
+	pci_read_config_byte(dev, (drive_pci)|0x02, &CP);
+
+	if ((id->dma_ultra & 0x0010) && (udma_66) && (udma_33)) {
+		if (!((id->dma_ultra >> 8) & 16)) {
+			drive->id->dma_ultra &= ~0xFF00;
+			drive->id->dma_ultra |= 0x1010;
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_1word &= ~0x0F00;
+		}
+		/* speed 8 == UDMA mode 4 == speed 6 plus cable */
+		pci_write_config_byte(dev, (drive_pci)|0x01, BP|0x20);
+		pci_write_config_byte(dev, (drive_pci)|0x02, CP|0x01);
+		speed = XFER_UDMA_4;
+	} else if ((id->dma_ultra & 0x0008) && (udma_66) && (udma_33)) {
+		if (!((id->dma_ultra >> 8) & 8)) {
+			drive->id->dma_ultra &= ~0xFF00;
+			drive->id->dma_ultra |= 0x0808;
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_1word &= ~0x0F00;
+		}
+		/* speed 7 == UDMA mode 3 == speed 5 plus cable */
+		pci_write_config_byte(dev, (drive_pci)|0x01, BP|0x40);
+		pci_write_config_byte(dev, (drive_pci)|0x02, CP|0x02);
+		speed = XFER_UDMA_3;
+	} else if ((id->dma_ultra & 0x0004) && (udma_33)) {
+		if (!((id->dma_ultra >> 8) & 4)) {
+			drive->id->dma_ultra &= ~0x0F00;
+			drive->id->dma_ultra |= 0x0404;
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_1word &= ~0x0F00;
+		}
+		/* speed 6 == UDMA mode 2 */
+		pci_write_config_byte(dev, (drive_pci)|0x01, BP|0x20);
+		pci_write_config_byte(dev, (drive_pci)|0x02, CP|0x01);
+		speed = XFER_UDMA_2;
+	} else if ((id->dma_ultra & 0x0002) && (udma_33)) {
+		if (!((id->dma_ultra >> 8) & 2)) {
+			drive->id->dma_ultra &= ~0x0F00;
+			drive->id->dma_ultra |= 0x0202;
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_1word &= ~0x0F00;
+		}
+		/* speed 5 == UDMA mode 1 */
+		pci_write_config_byte(dev, (drive_pci)|0x01, BP|0x40);
+		pci_write_config_byte(dev, (drive_pci)|0x02, CP|0x02);
+		speed = XFER_UDMA_1;
+	} else if ((id->dma_ultra & 0x0001) && (udma_33)) {
+		if (!((id->dma_ultra >> 8) & 1)) {
+			drive->id->dma_ultra &= ~0x0F00;
+			drive->id->dma_ultra |= 0x0101;
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_1word &= ~0x0F00;
+		}
+		/* speed 4 == UDMA mode 0 */
+		pci_write_config_byte(dev, (drive_pci)|0x01, BP|0x60);
+		pci_write_config_byte(dev, (drive_pci)|0x02, CP|0x03);
+		speed = XFER_UDMA_0;
+	} else if (id->dma_mword & 0x0004) {
+		if (!((id->dma_mword >> 8) & 4)) {
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_mword |= 0x0404;
+			drive->id->dma_1word &= ~0x0F00;
+		}
+		/* speed 4 == DMA mode 2 multi-word */
+		pci_write_config_byte(dev, (drive_pci)|0x01, BP|0x60);
+		pci_write_config_byte(dev, (drive_pci)|0x02, CP|0x03);
+		speed = XFER_MW_DMA_2;
+	} else if (id->dma_mword & 0x0002) {
+		if (!((id->dma_mword >> 8) & 2)) {
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_mword |= 0x0202;
+			drive->id->dma_1word &= ~0x0F00;
+		}
+		/* speed 3 == DMA mode 1 multi-word */
+		pci_write_config_byte(dev, (drive_pci)|0x01, BP|0x60);
+		pci_write_config_byte(dev, (drive_pci)|0x02, CP|0x04);
+		speed = XFER_MW_DMA_1;
+	} else if (id->dma_mword & 0x0001) {
+		if (!((id->dma_mword >> 8) & 1)) {
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_mword |= 0x0101;
+			drive->id->dma_1word &= ~0x0F00;
+		}
+		/* speed 2 == DMA mode 0 multi-word */
+		pci_write_config_byte(dev, (drive_pci)|0x01, BP|0x60);
+		pci_write_config_byte(dev, (drive_pci)|0x02, CP|0x05);
+		speed = XFER_MW_DMA_0;
+	} else if (id->dma_1word & 0x0004) {
+		if (!((id->dma_1word >> 8) & 4)) {
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_1word &= ~0x0F00;
+			drive->id->dma_1word |= 0x0404;
+		}
+		/* speed 2 == DMA mode 2 single-word */
+		pci_write_config_byte(dev, (drive_pci)|0x01, BP|0x60);
+		pci_write_config_byte(dev, (drive_pci)|0x02, CP|0x05);
+		speed = XFER_SW_DMA_2;
+	} else if (id->dma_1word & 0x0002) {
+		if (!((id->dma_1word >> 8) & 2)) {
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_1word &= ~0x0F00;
+			drive->id->dma_1word |= 0x0202;
+		}
+		/* speed 1 == DMA mode 1 single-word */
+		pci_write_config_byte(dev, (drive_pci)|0x01, BP|0x80);
+		pci_write_config_byte(dev, (drive_pci)|0x02, CP|0x06);
+		speed = XFER_SW_DMA_1;
+	} else if (id->dma_1word & 0x0001) {
+		if (!((id->dma_1word >> 8) & 1)) {
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_1word &= ~0x0F00;
+			drive->id->dma_1word |= 0x0101;
+		}
+		/* speed 0 == DMA mode 0 single-word */
+		pci_write_config_byte(dev, (drive_pci)|0x01, BP|0xC0);
+		pci_write_config_byte(dev, (drive_pci)|0x02, CP|0x0B);
+		speed = XFER_SW_DMA_0;
+	} else {
+		/* restore original pci-config space */
+		pci_write_config_dword(dev, drive_pci, drive_conf);
+		return ide_dma_off_quietly;
+	}
+
+	err = ide_wait_cmd(drive, WIN_SETFEATURES, speed, SETFEATURES_XFER, 0, NULL);
+
+#if PDC202XX_DECODE_REGISTER_INFO
+	pci_read_config_byte(dev, (drive_pci), &AP);
+	pci_read_config_byte(dev, (drive_pci)|0x01, &BP);
+	pci_read_config_byte(dev, (drive_pci)|0x02, &CP);
+
+	decode_registers(REG_A, AP);
+	decode_registers(REG_B, BP);
+	decode_registers(REG_C, CP);
+	decode_registers(REG_D, DP);
+#endif /* PDC202XX_DECODE_REGISTER_INFO */
+
+#if PDC202XX_DEBUG_DRIVE_INFO
+	printk("%s: %s drive%d 0x%08x ",
+		drive->name, ide_xfer_verbose(speed),
+		drive_number, drive_conf);
+	pci_read_config_dword(dev, drive_pci, &drive_conf);
+	printk("0x%08x\n", drive_conf);
+#endif /* PDC202XX_DEBUG_DRIVE_INFO */
+
+chipset_is_set:
+
+	return ((int)	((id->dma_ultra >> 11) & 3) ? ide_dma_on :
+			((id->dma_ultra >> 8) & 7) ? ide_dma_on :
+			((id->dma_mword >> 8) & 7) ? ide_dma_on : 
+			((id->dma_1word >> 8) & 7) ? ide_dma_on :
+						     ide_dma_off_quietly);
+}
+
+/*   0    1    2    3    4    5    6   7   8
+ * 960, 480, 390, 300, 240, 180, 120, 90, 60
+ *           180, 150, 120,  90,  60
+ * DMA_Speed
+ * 180, 120,  90,  90,  90,  60,  30
+ *  11,   5,   4,   3,   2,   1,   0
+ */
+
+static int config_drive_xfer_rate (ide_drive_t *drive)
+{
+	struct hd_driveid *id = drive->id;
+	ide_hwif_t *hwif = HWIF(drive);
+	ide_dma_action_t dma_func = ide_dma_off_quietly;
+
+	if (id && (id->capability & 1) && hwif->autodma) {
+		/* Consult the list of known "bad" drives */
+		if (ide_dmaproc(ide_dma_bad_drive, drive)) {
+			return HWIF(drive)->dmaproc(ide_dma_off, drive);
+		}
+
+		if (id->field_valid & 4) {
+			if (id->dma_ultra & 0x001F) {
+				/* Force if Capable UltraDMA */
+				dma_func = config_chipset_for_dma(drive, 1);
+				if ((id->field_valid & 2) &&
+				    (dma_func != ide_dma_on))
+					goto try_dma_modes;
+			}
+		} else if (id->field_valid & 2) {
+try_dma_modes:
+			if ((id->dma_mword & 0x0004) ||
+			    (id->dma_1word & 0x0004)) {
+				/* Force if Capable regular DMA modes */
+				dma_func = config_chipset_for_dma(drive, 0);
+			}
+		} else if ((ide_dmaproc(ide_dma_good_drive, drive)) &&
+			   (id->eide_dma_time > 150)) {
+			/* Consult the list of known "good" drives */
+			dma_func = config_chipset_for_dma(drive, 0);
+		}
+	}
+	return HWIF(drive)->dmaproc(dma_func, drive);
+}
+
+/*
+ * pdc202xx_dmaproc() initiates/aborts (U)DMA read/write operations on a drive.
+ */
+int pdc202xx_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
+{
+	switch (func) {
+		case ide_dma_check:
+			return config_drive_xfer_rate(drive);
+		default:
+			break;
+	}
+	return ide_dmaproc(func, drive);	/* use standard DMA stuff */
+}
+
+__initfunc(unsigned int pci_init_pdc202xx (struct pci_dev *dev, const char *name))
+{
+	unsigned long high_16	= dev->base_address[4] & PCI_BASE_ADDRESS_IO_MASK;
+	byte udma_speed_flag	= inb(high_16 + 0x001f);
+	byte primary_mode	= inb(high_16 + 0x001a);
+	byte secondary_mode	= inb(high_16 + 0x001b);
+
+	if (dev->rom_address) {
+		pci_write_config_dword(dev, PCI_ROM_ADDRESS, dev->rom_address | PCI_ROM_ADDRESS_ENABLE);
+		printk("%s: ROM enabled at 0x%08lx\n", name, dev->rom_address);
+	}
+
+	if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE) {
+		byte irq = 0, irq2 = 0;
+		pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
+		pci_read_config_byte(dev, (PCI_INTERRUPT_LINE)|0x80, &irq2);	/* 0xbc */
+		if (irq != irq2) {
+			pci_write_config_byte(dev, (PCI_INTERRUPT_LINE)|0x80, irq);	/* 0xbc */
+			printk("%s: pci-config space interrupt mirror fixed.\n", name);
+		}
+	}
+
+	printk("%s: (U)DMA Burst Bit %sABLED " \
+		"Primary %s Mode " \
+		"Secondary %s Mode.\n",
+		name,
+		(udma_speed_flag & 1) ? "EN" : "DIS",
+		(primary_mode & 1) ? "MASTER" : "PCI",
+		(secondary_mode & 1) ? "MASTER" : "PCI" );
+
+#if PDC202XX_FORCE_BURST_BIT
+	if (!(udma_speed_flag & 1)) {
+		printk("%s: FORCING BURST BIT 0x%02x -> 0x%02x ", name, udma_speed_flag, (udma_speed_flag|1));
+		outb(udma_speed_flag|1, high_16 + 0x001f);
+		printk("%sCTIVE\n", (inb(high_16 + 0x001f) & 1) ? "A" : "INA");
+	}
+#endif /* PDC202XX_FORCE_BURST_BIT */
+
+#if PDC202XX_FORCE_MASTER_MODE
+	if (!(primary_mode & 1)) {
+		printk("%s: FORCING PRIMARY MODE BIT 0x%02x -> 0x%02x ",
+			name, primary_mode, (primary_mode|1));
+		outb(primary_mode|1, high_16 + 0x001a);
+		printk("%s\n", (inb(high_16 + 0x001a) & 1) ? "MASTER" : "PCI");
+	}
+
+	if (!(secondary_mode & 1)) {
+		printk("%s: FORCING SECONDARY MODE BIT 0x%02x -> 0x%02x ",
+			name, secondary_mode, (secondary_mode|1));
+		outb(secondary_mode|1, high_16 + 0x001b);
+		printk("%s\n", (inb(high_16 + 0x001b) & 1) ? "MASTER" : "PCI");
+	}
+#endif /* PDC202XX_FORCE_MASTER_MODE */
+	return dev->irq;
+}
+
+__initfunc(void ide_init_pdc202xx (ide_hwif_t *hwif))
+{
+	if (hwif->dma_base) {
+		hwif->dmaproc = &pdc202xx_dmaproc;
+	}
+}
diff -u --recursive --new-file v2.3.0/linux/drivers/block/pdc4030.c linux/drivers/block/pdc4030.c
--- v2.3.0/linux/drivers/block/pdc4030.c	Tue Dec 29 11:24:57 1998
+++ linux/drivers/block/pdc4030.c	Thu May 13 11:04:54 1999
@@ -1,17 +1,18 @@
 /*  -*- linux-c -*-
- *  linux/drivers/block/pdc4030.c	Version 0.08  Nov 30, 1997
+ *  linux/drivers/block/pdc4030.c	Version 0.10  Jan 25, 1999
  *
- *  Copyright (C) 1995-1998  Linus Torvalds & authors (see below)
+ *  Copyright (C) 1995-1999  Linus Torvalds & authors (see below)
  */
 
 /*
  *  Principal Author/Maintainer:  peterd@pnd-pc.demon.co.uk
  *
  *  This file provides support for the second port and cache of Promise
- *  IDE interfaces, e.g. DC4030, DC5030.
+ *  IDE interfaces, e.g. DC4030VL, DC4030VL-1 and DC4030VL-2.
  *
  *  Thanks are due to Mark Lord for advice and patiently answering stupid
- *  questions, and all those mugs^H^H^H^Hbrave souls who've tested this.
+ *  questions, and all those mugs^H^H^H^Hbrave souls who've tested this,
+ *  especially Andre Hedrick.
  *
  *  Version 0.01	Initial version, #include'd in ide.c rather than
  *                      compiled separately.
@@ -29,6 +30,9 @@
  *  Version 0.07	Added support for DC4030 variants
  *			Secondary interface autodetection
  *  Version 0.08	Renamed to pdc4030.c
+ *  Version 0.09	Obsolete - never released - did manual write request
+ *			splitting before max_sectors[major][minor] available.
+ *  Version 0.10	Updated for 2.1 series of kernels
  */
 
 /*
@@ -37,12 +41,17 @@
  *
  *	'linux ide0=dc4030'
  *
- * As before, it seems that somewhere around 3Megs when writing, bad things
- * start to happen [timeouts/retries -ml]. If anyone can give me more feedback,
- * I'd really appreciate it.  [email: peterd@pnd-pc.demon.co.uk]
+ * It should now work as a second controller also ('ide1=dc4030') but only
+ * if you DON'T have BIOS V4.44, which has a bug. If you have this and EPROM
+ * programming facilities, I can tell you what to fix...
  *
+ * As of January 1999, Promise Technology Inc. have finally supplied me with
+ * some technical information which has shed a glimmer of light on some of the
+ * problems I was having, especially with writes. 
  */
 
+#define DEBUG_READ
+#define DEBUG_WRITE
 
 #undef REALLY_SLOW_IO		/* most systems can safely undef this */
 
@@ -54,9 +63,11 @@
 #include <linux/ioport.h>
 #include <linux/blkdev.h>
 #include <linux/hdreg.h>
+#include <linux/ide.h>
+
 #include <asm/io.h>
 #include <asm/irq.h>
-#include "ide.h"
+
 #include "pdc4030.h"
 
 /* This is needed as the controller may not interrupt if the required data is
@@ -124,40 +135,48 @@
 {
 	ide_hwif_t *hwif = hwif_required;
         ide_drive_t *drive;
-	ide_hwif_t *second_hwif;
+	ide_hwif_t *hwif2;
 	struct dc_ident ident;
 	int i;
 	
 	if (!hwif) return 0;
 
 	drive = &hwif->drives[0];
-	second_hwif = &ide_hwifs[hwif->index+1];
-	if(hwif->chipset == ide_pdc4030) /* we've already been found ! */
-	    return 1;
-
-	if(IN_BYTE(IDE_NSECTOR_REG) == 0xFF || IN_BYTE(IDE_SECTOR_REG) == 0xFF)
-	{
-	    return 0;
+	hwif2 = &ide_hwifs[hwif->index+1];
+	if (hwif->chipset == ide_pdc4030) /* we've already been found ! */
+		return 1;
+
+	if (IN_BYTE(IDE_NSECTOR_REG) == 0xFF || IN_BYTE(IDE_SECTOR_REG) == 0xFF) {
+		return 0;
 	}
 	OUT_BYTE(0x08,IDE_CONTROL_REG);
-	if(pdc4030_cmd(drive,PROMISE_GET_CONFIG)) {
-	    return 0;
+	if (pdc4030_cmd(drive,PROMISE_GET_CONFIG)) {
+		return 0;
 	}
-	if(ide_wait_stat(drive,DATA_READY,BAD_W_STAT,WAIT_DRQ)) {
-	    printk("%s: Failed Promise read config!\n",hwif->name);
-	    return 0;
+	if (ide_wait_stat(drive,DATA_READY,BAD_W_STAT,WAIT_DRQ)) {
+		printk(KERN_INFO
+			"%s: Failed Promise read config!\n",hwif->name);
+		return 0;
 	}
 	ide_input_data(drive,&ident,SECTOR_WORDS);
-	if(ident.id[1] != 'P' || ident.id[0] != 'T') {
-            return 0;
+	if (ident.id[1] != 'P' || ident.id[0] != 'T') {
+		return 0;
 	}
-	printk("%s: Promise caching controller, ",hwif->name);
+	printk(KERN_INFO "%s: Promise caching controller, ",hwif->name);
 	switch(ident.type) {
-            case 0x43:	printk("DC4030VL-2, "); break;
-            case 0x41:	printk("DC4030VL-1, "); break;
-	    case 0x40:	printk("DC4030VL, "); break;
-            default:	printk("unknown - type 0x%02x - please report!\n"
+		case 0x43:	printk("DC4030VL-2, "); break;
+		case 0x41:	printk("DC4030VL-1, "); break;
+		case 0x40:	printk("DC4030VL, "); break;
+		default:
+			printk("unknown - type 0x%02x - please report!\n"
 			       ,ident.type);
+			printk("Please e-mail the following data to "
+			       "promise@pnd-pc.demon.co.uk along with\n"
+			       "a description of your card and drives:\n");
+			for (i=0; i < 0x90; i++) {
+				printk("%02x ", ((unsigned char *)&ident)[i]);
+				if ((i & 0x0f) == 0x0f) printk("\n");
+			}
 			return 0;
 	}
 	printk("%dKB cache, ",(int)ident.cache_mem);
@@ -167,27 +186,35 @@
             default:   hwif->irq = 15; break;
 	}
 	printk("on IRQ %d\n",hwif->irq);
-	hwif->chipset     = second_hwif->chipset    = ide_pdc4030;
-	hwif->mate        = second_hwif;
-	second_hwif->mate = hwif;
-	second_hwif->channel = 1;
-	hwif->selectproc  = second_hwif->selectproc = &promise_selectproc;
+	hwif->chipset	= hwif2->chipset = ide_pdc4030;
+	hwif->mate	= hwif2;
+	hwif2->mate	= hwif;
+	hwif2->channel	= 1;
+	hwif->selectproc = hwif2->selectproc = &promise_selectproc;
 /* Shift the remaining interfaces down by one */
 	for (i=MAX_HWIFS-1 ; i > hwif->index+1 ; i--) {
 		ide_hwif_t *h = &ide_hwifs[i];
 
-		printk("Shifting i/f %d values to i/f %d\n",i-1,i);
-		ide_init_hwif_ports(h->io_ports, (h-1)->io_ports[IDE_DATA_OFFSET], NULL);
-		h->io_ports[IDE_CONTROL_OFFSET] = (h-1)->io_ports[IDE_CONTROL_OFFSET];
+#ifdef DEBUG
+		printk(KERN_DEBUG "Shifting i/f %d values to i/f %d\n",i-1,i);
+#endif
+		ide_init_hwif_ports(&h->hw, (h-1)->io_ports[IDE_DATA_OFFSET], 0, NULL);
+		memcpy(h->io_ports, h->hw.io_ports, sizeof(h->io_ports));
 		h->noprobe = (h-1)->noprobe;
 	}
-	ide_init_hwif_ports(second_hwif->io_ports, hwif->io_ports[IDE_DATA_OFFSET], NULL);
-	second_hwif->io_ports[IDE_CONTROL_OFFSET] = hwif->io_ports[IDE_CONTROL_OFFSET];
-	second_hwif->irq = hwif->irq;
+	ide_init_hwif_ports(&hwif2->hw, hwif->io_ports[IDE_DATA_OFFSET], 0, NULL);
+	memcpy(hwif2->io_ports, hwif->hw.io_ports, sizeof(hwif2->io_ports));
+	hwif2->irq = hwif->irq;
+	hwif2->hw.irq = hwif->hw.irq = hwif->irq;
 	for (i=0; i<2 ; i++) {
-            hwif->drives[i].io_32bit = 3;
-	    second_hwif->drives[i].io_32bit = 3;
-	    if(!ident.current_tm[i+2].cyl) second_hwif->drives[i].noprobe=1;
+		hwif->drives[i].io_32bit = 3;
+		hwif2->drives[i].io_32bit = 3;
+		hwif->drives[i].keep_settings = 1;
+		hwif2->drives[i].keep_settings = 1;
+		if (!ident.current_tm[i].cyl)
+			hwif->drives[i].noprobe = 1;
+		if (!ident.current_tm[i+2].cyl)
+			hwif2->drives[i].noprobe = 1;
 	}
         return 1;
 }
@@ -198,7 +225,7 @@
 static void promise_read_intr (ide_drive_t *drive)
 {
 	byte stat;
-	int i;
+	int total_remaining;
 	unsigned int sectors_left, sectors_avail, nsect;
 	struct request *rq;
 
@@ -209,99 +236,140 @@
 
 read_again:
 	do {
-	    sectors_left = IN_BYTE(IDE_NSECTOR_REG);
-	    IN_BYTE(IDE_SECTOR_REG);
+		sectors_left = IN_BYTE(IDE_NSECTOR_REG);
+		IN_BYTE(IDE_SECTOR_REG);
 	} while (IN_BYTE(IDE_NSECTOR_REG) != sectors_left);
 	rq = HWGROUP(drive)->rq;
 	sectors_avail = rq->nr_sectors - sectors_left;
+	if (!sectors_avail)
+		goto read_again;
 
 read_next:
 	rq = HWGROUP(drive)->rq;
-	if ((nsect = rq->current_nr_sectors) > sectors_avail)
+	nsect = rq->current_nr_sectors;
+	if (nsect > sectors_avail)
 		nsect = sectors_avail;
 	sectors_avail -= nsect;
 	ide_input_data(drive, rq->buffer, nsect * SECTOR_WORDS);
-#ifdef DEBUG
-	printk("%s:  promise_read: sectors(%ld-%ld), buffer=0x%08lx, "
-	       "remaining=%ld\n", drive->name, rq->sector, rq->sector+nsect-1, 
-	       (unsigned long) rq->buffer+(nsect<<9), rq->nr_sectors-nsect);
+#ifdef DEBUG_READ
+	printk(KERN_DEBUG "%s:  promise_read: sectors(%ld-%ld), "
+	       "buf=0x%08lx, rem=%ld\n", drive->name, rq->sector,
+	       rq->sector+nsect-1, (unsigned long) rq->buffer,
+	       rq->nr_sectors-nsect);
 #endif
 	rq->sector += nsect;
 	rq->buffer += nsect<<9;
 	rq->errors = 0;
-	i = (rq->nr_sectors -= nsect);
-	if ((rq->current_nr_sectors -= nsect) <= 0)
+	rq->nr_sectors -= nsect;
+	total_remaining = rq->nr_sectors;
+	if ((rq->current_nr_sectors -= nsect) <= 0) {
 		ide_end_request(1, HWGROUP(drive));
-	if (i > 0) {
+	}
+/*
+ * Now the data has been read in, do the following:
+ * 
+ * if there are still sectors left in the request, 
+ *   if we know there are still sectors available from the interface,
+ *     go back and read the next bit of the request.
+ *   else if DRQ is asserted, there are more sectors available, so
+ *     go back and find out how many, then read them in.
+ *   else if BUSY is asserted, we are going to get an interrupt, so
+ *     set the handler for the interrupt and just return
+ */
+	if (total_remaining > 0) {
 		if (sectors_avail)
-		    goto read_next;
+			goto read_next;
 		stat = GET_STAT();
-		if(stat & DRQ_STAT)
-		    goto read_again;
-		if(stat & BUSY_STAT) {
-		    ide_set_handler (drive, &promise_read_intr, WAIT_CMD);
-		    return;
+		if (stat & DRQ_STAT)
+			goto read_again;
+		if (stat & BUSY_STAT) {
+#ifdef DEBUG_READ
+			printk(KERN_DEBUG "%s: promise_read: waiting for"
+			       "interrupt\n", drive->name);
+#endif 
+			ide_set_handler (drive, &promise_read_intr, WAIT_CMD);
+			return;
 		}
-		printk("Ah! promise read intr: sectors left !DRQ !BUSY\n");
+		printk(KERN_ERR "%s: Eeek! promise_read_intr: sectors left "
+		       "!DRQ !BUSY\n", drive->name);
 		ide_error(drive, "promise read intr", stat);
 	}
 }
 
 /*
+ * promise_write_intr()
+ * This interrupt is called after the particularly odd polling for completion
+ * of the write request, once all the data has been sent.
+ */ 
+static void promise_write_intr(ide_drive_t *drive)
+{
+	byte stat;
+	int i;
+	struct request *rq;
+
+	if (!OK_STAT(stat=GET_STAT(),DRIVE_READY,drive->bad_wstat)) {
+		ide_error(drive, "promise_write_intr", stat);
+	}
+
+#ifdef DEBUG_WRITE
+	printk(KERN_DEBUG "%s: Write complete - end_request\n", drive->name);
+#endif
+	rq = HWGROUP(drive)->rq;
+	for (i = rq->nr_sectors; i > 0;) {
+		i -= rq->current_nr_sectors;
+		ide_end_request(1, HWGROUP(drive));
+	}
+}
+
+/*
  * promise_write_pollfunc() is the handler for disk write completion polling.
  */
 static void promise_write_pollfunc (ide_drive_t *drive)
 {
-	int i;
-	ide_hwgroup_t *hwgroup = HWGROUP(drive);
-	struct request *rq;
+	if (IN_BYTE(IDE_NSECTOR_REG) != 0) {
+		if (time_before(jiffies, HWGROUP(drive)->poll_timeout)) {
+			ide_set_handler (drive, &promise_write_pollfunc, 1);
+			return; /* continue polling... */
+		}
+		printk(KERN_ERR "%s: write timed-out!\n",drive->name);
+		ide_error (drive, "write timeout", GET_STAT());
+		return;
+	}
 
-        if (IN_BYTE(IDE_NSECTOR_REG) != 0) {
-            if (time_before(jiffies, hwgroup->poll_timeout)) {
-                ide_set_handler (drive, &promise_write_pollfunc, 1);
-                return; /* continue polling... */
-            }
-            printk("%s: write timed-out!\n",drive->name);
-            ide_error (drive, "write timeout", GET_STAT());
-            return;
-        }
-        
+#ifdef DEBUG_WRITE
+	printk(KERN_DEBUG "%s: Doing last 4 sectors\n", drive->name);
+#endif
 	ide_multwrite(drive, 4);
-        rq = hwgroup->rq;
-        for (i = rq->nr_sectors; i > 0;) {
-            i -= rq->current_nr_sectors;
-            ide_end_request(1, hwgroup);
-        }
-        return;
+	ide_set_handler(drive, &promise_write_intr, WAIT_CMD);
+	return;
 }
 
 /*
  * promise_write() transfers a block of one or more sectors of data to a
  * drive as part of a disk write operation. All but 4 sectors are transfered
  * in the first attempt, then the interface is polled (nicely!) for completion
- * before the final 4 sectors are transfered. Don't ask me why, but this is
- * how it's done in the drivers for other O/Ses. There is no interrupt
- * generated on writes, which is why we have to do it like this.
+ * before the final 4 sectors are transfered. The interrupt generated on 
+ * writes occurs after this process, which is why I got it wrong for so long!
  */
 static void promise_write (ide_drive_t *drive)
 {
-    ide_hwgroup_t *hwgroup = HWGROUP(drive);
-    struct request *rq = &hwgroup->wrq;
-    int i;
-
-    if (rq->nr_sectors > 4) {
-        ide_multwrite(drive, rq->nr_sectors - 4);
-        hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
-        ide_set_handler (drive, &promise_write_pollfunc, 1);
-        return;
-    } else {
-        ide_multwrite(drive, rq->nr_sectors);
-        rq = hwgroup->rq;
-        for (i = rq->nr_sectors; i > 0;) {
-            i -= rq->current_nr_sectors;
-            ide_end_request(1, hwgroup);
-        }
-    }
+	ide_hwgroup_t *hwgroup = HWGROUP(drive);
+	struct request *rq = &hwgroup->wrq;
+
+#ifdef DEBUG_WRITE
+	printk(KERN_DEBUG "%s: promise_write: sectors(%ld-%ld), "
+	       "buffer=0x%08lx\n", drive->name, rq->sector,
+	       rq->sector + rq->nr_sectors - 1, rq->buffer);
+#endif
+	if (rq->nr_sectors > 4) {
+		ide_multwrite(drive, rq->nr_sectors - 4);
+		hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
+		ide_set_handler (drive, &promise_write_pollfunc, 1);
+		return;
+	} else {
+		ide_multwrite(drive, rq->nr_sectors);
+		ide_set_handler(drive, &promise_write_intr, WAIT_CMD);
+	}
 }
 
 /*
@@ -315,43 +383,54 @@
 	byte stat;
 
 	if (rq->cmd == READ) {
-	    ide_set_handler(drive, &promise_read_intr, WAIT_CMD);
-	    OUT_BYTE(PROMISE_READ, IDE_COMMAND_REG);
-/* The card's behaviour is odd at this point. If the data is
-   available, DRQ will be true, and no interrupt will be
-   generated by the card. If this is the case, we need to simulate
-   an interrupt. Ugh! Otherwise, if an interrupt will occur, bit0
-   of the SELECT register will be high, so we can just return and
-   be interrupted.*/
-	    timeout = jiffies + HZ/20; /* 50ms wait */
-	    do {
-		stat=GET_STAT();
-		if(stat & DRQ_STAT) {
-                    disable_irq(HWIF(drive)->irq);
-		    ide_intr(HWIF(drive)->irq,HWGROUP(drive),NULL);
-                    enable_irq(HWIF(drive)->irq);
-		    return;
-		}
-		if(IN_BYTE(IDE_SELECT_REG) & 0x01)
-		    return;
-		udelay(1);
-	    } while (time_before(jiffies, timeout));
-	    printk("%s: reading: No DRQ and not waiting - Odd!\n",
-		   drive->name);
-	    return;
-	}
-	if (rq->cmd == WRITE) {
-	    OUT_BYTE(PROMISE_WRITE, IDE_COMMAND_REG);
-	    if (ide_wait_stat(drive, DATA_READY, drive->bad_wstat, WAIT_DRQ)) {
-		printk("%s: no DRQ after issuing PROMISE_WRITE\n", drive->name);
-		return;
-	    }
-	    if (!drive->unmask)
-		__cli();	/* local CPU only */
-	    HWGROUP(drive)->wrq = *rq; /* scratchpad */
-	    promise_write(drive);
-	    return;
+		OUT_BYTE(PROMISE_READ, IDE_COMMAND_REG);
+/*
+ * The card's behaviour is odd at this point. If the data is
+ * available, DRQ will be true, and no interrupt will be
+ * generated by the card. If this is the case, we need to call the 
+ * "interrupt" handler (promise_read_intr) directly. Otherwise, if
+ * an interrupt is going to occur, bit0 of the SELECT register will
+ * be high, so we can set the handler the just return and be interrupted.
+ * If neither of these is the case, we wait for up to 50ms (badly I'm
+ * afraid!) until one of them is.
+ */
+		timeout = jiffies + HZ/20; /* 50ms wait */
+		do {
+			stat=GET_STAT();
+			if (stat & DRQ_STAT) {
+				udelay(1);
+				promise_read_intr(drive);
+				return;
+			}
+			if (IN_BYTE(IDE_SELECT_REG) & 0x01) {
+#ifdef DEBUG_READ
+				printk(KERN_DEBUG "%s: read: waiting for "
+				                  "interrupt\n", drive->name);
+#endif
+				ide_set_handler(drive, &promise_read_intr, WAIT_CMD);
+				return;
+			}
+			udelay(1);
+		} while (time_before(jiffies, timeout));
+
+		printk(KERN_ERR "%s: reading: No DRQ and not waiting - Odd!\n",
+			drive->name);
+
+	} else if (rq->cmd == WRITE) {
+		OUT_BYTE(PROMISE_WRITE, IDE_COMMAND_REG);
+		if (ide_wait_stat(drive, DATA_READY, drive->bad_wstat, WAIT_DRQ)) {
+			printk(KERN_ERR "%s: no DRQ after issuing "
+			       "PROMISE_WRITE\n", drive->name);
+			return;
+	    	}
+		if (!drive->unmask)
+			__cli();	/* local CPU only */
+		HWGROUP(drive)->wrq = *rq; /* scratchpad */
+		promise_write(drive);
+
+	} else {
+		printk("KERN_WARNING %s: bad command: %d\n",
+		       drive->name, rq->cmd);
+		ide_end_request(0, HWGROUP(drive));
 	}
-	printk("%s: bad command: %d\n", drive->name, rq->cmd);
-	ide_end_request(0, HWGROUP(drive));
 }
diff -u --recursive --new-file v2.3.0/linux/drivers/block/piix.c linux/drivers/block/piix.c
--- v2.3.0/linux/drivers/block/piix.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/block/piix.c	Thu May 13 11:04:54 1999
@@ -0,0 +1,258 @@
+/*
+ * linux/drivers/block/piix.c	Version 0.22	March 29, 1999
+ *
+ *  Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer
+ *  Copyright (C) 1998-1999 Andre Hedrick, Author and Maintainer
+ *
+ *  PIO mode setting function for Intel chipsets.  
+ *  For use instead of BIOS settings.
+ *
+ * 40-41
+ * 42-43
+ * 
+ *                 41
+ *                 43
+ *
+ * | PIO 0       | c0 | 80 | 0 |
+ * | PIO 2 | SW2 | d0 | 90 | 4 |
+ * | PIO 3 | MW1 | e1 | a1 | 9 |
+ * | PIO 4 | MW2 | e3 | a3 | b |
+ * 
+ * sitre = word40 & 0x4000; primary
+ * sitre = word42 & 0x4000; secondary
+ *
+ * 44 8421|8421    hdd|hdb
+ * 
+ * 48 8421         hdd|hdc|hdb|hda udma enabled
+ *
+ *    0001         hda
+ *    0010         hdb
+ *    0100         hdc
+ *    1000         hdd
+ *
+ * 4a 84|21        hdb|hda
+ * 4b 84|21        hdd|hdc
+ * 
+ *    00|00 udma 0
+ *    01|01 udma 1
+ *    10|10 udma 2
+ *    11|11 reserved
+ *
+ * pci_read_config_word(HWIF(drive)->pci_dev, 0x40, &reg40);
+ * pci_read_config_word(HWIF(drive)->pci_dev, 0x42, &reg42);
+ * pci_read_config_word(HWIF(drive)->pci_dev, 0x44, &reg44);
+ * pci_read_config_word(HWIF(drive)->pci_dev, 0x48, &reg48);
+ * pci_read_config_word(HWIF(drive)->pci_dev, 0x4a, &reg4a);
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/hdreg.h>
+#include <linux/ide.h>
+
+#include <asm/delay.h>
+#include <asm/io.h>
+
+#include "ide_modes.h"
+
+#define PIIX_DMA_PROC			0
+#define PIIX_DEBUG_SET_XFER		0
+#define PIIX_DEBUG_DRIVE_INFO		0
+
+/*
+ *  Based on settings done by AMI BIOS
+ *  (might be usefull if drive is not registered in CMOS for any reason).
+ */
+static void piix_tune_drive (ide_drive_t *drive, byte pio)
+{
+	unsigned long flags;
+	u16 master_data;
+	byte slave_data, speed;
+	int err;
+	int is_slave = (&HWIF(drive)->drives[1] == drive);
+	int master_port = HWIF(drive)->index ? 0x42 : 0x40;
+	int slave_port = 0x44;
+			   /* ISP  RTC */
+	byte timings[][2] = { { 0, 0 },
+			      { 0, 0 },
+			      { 1, 0 },
+			      { 2, 1 },
+			      { 2, 3 }, };
+			      
+	pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
+	pci_read_config_word(HWIF(drive)->pci_dev, master_port, &master_data);
+	if (is_slave) {
+		master_data = master_data | 0x4000;
+		if (pio > 1)
+			/* enable PPE, IE and TIME */
+			master_data = master_data | 0x0070;
+		pci_read_config_byte(HWIF(drive)->pci_dev, slave_port, &slave_data);
+		slave_data = slave_data & (HWIF(drive)->index ? 0x0f : 0xf0);
+		slave_data = slave_data | ((timings[pio][0] << 2) | (timings[pio][1]
+					   << (HWIF(drive)->index ? 4 : 0)));
+	} else {
+		master_data = master_data & 0xccf8;
+		if (pio > 1)
+			/* enable PPE, IE and TIME */
+			master_data = master_data | 0x0007;
+		master_data = master_data | (timings[pio][0] << 12) |
+			      (timings[pio][1] << 8);
+	}
+	save_flags(flags);
+	cli();
+	pci_write_config_word(HWIF(drive)->pci_dev, master_port, master_data);
+	if (is_slave)
+		pci_write_config_byte(HWIF(drive)->pci_dev, slave_port, slave_data);
+	restore_flags(flags);
+
+	switch(pio) {
+		case 4: speed = XFER_PIO_4;break;
+		case 3: speed = XFER_PIO_3;break;
+		case 2: speed = XFER_PIO_2;break;
+		case 1: speed = XFER_PIO_1;break;
+		default:
+			speed = (!drive->id->tPIO) ? XFER_PIO_0 : XFER_PIO_SLOW;
+			break;
+	}
+
+	err = ide_wait_cmd(drive, WIN_SETFEATURES, speed, SETFEATURES_XFER, 0, NULL);
+}
+
+extern char *ide_xfer_verbose (byte xfer_rate);
+
+static int piix_config_drive_for_dma(ide_drive_t *drive, int ultra)
+{
+	struct hd_driveid *id = drive->id;
+	ide_hwif_t *hwif = HWIF(drive);
+	struct pci_dev *dev = hwif->pci_dev;
+
+	int			sitre;
+	short			reg4042, reg44, reg48, reg4a;
+	byte			speed;
+	int			u_speed;
+	byte maslave		= hwif->channel ? 0x42 : 0x40;			
+	int drive_number	= ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01));
+	int a_speed		= 2 << (drive_number * 4);
+	int u_flag		= 1 << drive_number;
+
+	pci_read_config_word(dev, maslave, &reg4042);
+	sitre =  (reg4042 & 0x4000) ? 1 : 0;
+	pci_read_config_word(dev, 0x44, &reg44);
+	pci_read_config_word(dev, 0x48, &reg48);
+	pci_read_config_word(dev, 0x4a, &reg4a);
+
+#if PIIX_DEBUG_SET_XFER
+	printk("PIIX%s: DMA enable ",
+		(dev->device == PCI_DEVICE_ID_INTEL_82371FB_0) ? "a" :
+		(dev->device == PCI_DEVICE_ID_INTEL_82371FB_1) ? "b" :
+		(dev->device == PCI_DEVICE_ID_INTEL_82371SB_1) ? "3" :
+		(dev->device == PCI_DEVICE_ID_INTEL_82371AB)   ? "4" : " UNKNOWN" );
+#endif /* PIIX_DEBUG_SET_XFER */
+
+	if (id->dma_ultra && (ultra)) {
+		if (!(reg48 & u_flag)) {
+			pci_write_config_word(dev, 0x48, reg48|u_flag);
+		}
+	} else {
+		pci_write_config_word(dev, 0x48, reg48 & ~u_flag);
+	}
+
+	if ((id->dma_ultra & 0x0004) && (ultra)) {
+		if (!((id->dma_ultra >> 8) & 4)) {
+			drive->id->dma_ultra &= ~0x0F00;
+			drive->id->dma_ultra |= 0x0404;
+		}
+		u_speed = 2 << (drive_number * 4);
+		if (!(reg4a & u_speed)) {
+			pci_write_config_word(dev, 0x4a, reg4a|u_speed);
+		}
+		speed = XFER_UDMA_2;
+	} else if ((id->dma_ultra & 0x0002) && (ultra)) {
+		if (!((id->dma_ultra >> 8) & 2)) {
+			drive->id->dma_ultra &= ~0x0F00;
+			drive->id->dma_ultra |= 0x0202;
+		}
+		u_speed = 1 << (drive_number * 4);
+		if (!(reg4a & u_speed)) {
+			pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
+			pci_write_config_word(dev, 0x4a, reg4a|u_speed);
+		}
+		speed = XFER_UDMA_1;
+	} else if ((id->dma_ultra & 0x0001) && (ultra)) {
+		if (!((id->dma_ultra >> 8) & 1)) {
+			drive->id->dma_ultra &= ~0x0F00;
+			drive->id->dma_ultra |= 0x0101;
+		}
+		u_speed = 0 << (drive_number * 4);
+		if (!(reg4a & u_speed)) {
+			pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
+			pci_write_config_word(dev, 0x4a, reg4a|u_speed);
+		}
+		speed = XFER_UDMA_0;
+	} else if (id->dma_mword & 0x0004) {
+		drive->id->dma_ultra &= ~0x0F0F;
+		pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
+		if (!((id->dma_mword >> 8) & 4)) {
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_mword |= 0x0404;
+		}
+		speed = XFER_MW_DMA_2;
+	} else if (id->dma_mword & 0x0002) {
+		drive->id->dma_ultra &= ~0x0F0F;
+		pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
+		if (!((id->dma_mword >> 8) & 2)) {
+			drive->id->dma_mword &= ~0x0F00;
+			drive->id->dma_mword |= 0x0202;
+		}
+		speed = XFER_MW_DMA_1;
+	} else if (id->dma_1word & 0x0004) {
+		drive->id->dma_ultra &= ~0x0F0F;
+		pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
+		if (!((id->dma_1word >> 8) & 4)) {
+			drive->id->dma_1word &= ~0x0F00;
+			drive->id->dma_1word |= 0x0404;
+		}
+		speed = XFER_SW_DMA_2;
+        } else {
+		return ide_dma_off_quietly;
+	}
+
+	(void) ide_wait_cmd(drive, WIN_SETFEATURES, speed, SETFEATURES_XFER, 0, NULL);
+
+#if PIIX_DEBUG_DRIVE_INFO
+	printk("%s: %s drive%d ",
+		drive->name,
+		ide_xfer_verbose(speed),
+		drive_number);
+	printk("\n");
+#endif /* PIIX_DEBUG_DRIVE_INFO */
+
+	return ((int)	((id->dma_ultra >> 8) & 7) ? ide_dma_on :
+			((id->dma_mword >> 8) & 7) ? ide_dma_on :
+			((id->dma_1word >> 8) & 7) ? ide_dma_on :
+						     ide_dma_off_quietly);
+}
+
+static int piix_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
+{
+	int ultra = (HWIF(drive)->pci_dev->device == PCI_DEVICE_ID_INTEL_82371AB) ? 1 : 0;
+	switch (func) {
+		case ide_dma_check:
+			return piix_config_drive_for_dma(drive, ultra);
+		default :
+			break;
+	}
+	/* Other cases are done by generic IDE-DMA code. */
+	return ide_dmaproc(func, drive);
+}
+
+void ide_init_piix (ide_hwif_t *hwif)
+{
+	hwif->tuneproc = &piix_tune_drive;
+#if PIIX_DMA_PROC
+	hwif->dmaproc = &piix_dmaproc;
+#endif /* PIIX_DMA_PROC */
+}
diff -u --recursive --new-file v2.3.0/linux/drivers/block/ps2esdi.c linux/drivers/block/ps2esdi.c
--- v2.3.0/linux/drivers/block/ps2esdi.c	Thu Jan 14 10:31:41 1999
+++ linux/drivers/block/ps2esdi.c	Tue May 11 23:32:10 1999
@@ -108,7 +108,9 @@
 
 u_int dma_arb_level;		/* DMA arbitration level */
 
-static struct wait_queue *ps2esdi_int = NULL, *ps2esdi_wait_open = NULL;
+static DECLARE_WAIT_QUEUE_HEAD(ps2esdi_int);
+static DECLARE_WAIT_QUEUE_HEAD(ps2esdi_wait_open);
+
 int no_int_yet;
 static int access_count[MAX_HD] = {0,};
 static char ps2esdi_valid[MAX_HD] = {0,};
diff -u --recursive --new-file v2.3.0/linux/drivers/block/qd6580.c linux/drivers/block/qd6580.c
--- v2.3.0/linux/drivers/block/qd6580.c	Wed May  6 14:42:54 1998
+++ linux/drivers/block/qd6580.c	Thu May 13 11:04:54 1999
@@ -19,8 +19,10 @@
 #include <linux/ioport.h>
 #include <linux/blkdev.h>
 #include <linux/hdreg.h>
+#include <linux/ide.h>
+
 #include <asm/io.h>
-#include "ide.h"
+
 #include "ide_modes.h"
 
 /*
diff -u --recursive --new-file v2.3.0/linux/drivers/block/raid5.c linux/drivers/block/raid5.c
--- v2.3.0/linux/drivers/block/raid5.c	Fri May  8 00:17:13 1998
+++ linux/drivers/block/raid5.c	Tue May 11 23:37:51 1999
@@ -91,7 +91,7 @@
 
 void __wait_on_stripe(struct stripe_head *sh)
 {
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 
 	PRINTK(("wait_on_stripe %lu\n", sh->sector));
 	sh->count++;
@@ -1395,7 +1395,7 @@
 		goto abort;
 	memset(raid_conf->stripe_hashtbl, 0, HASH_PAGES * PAGE_SIZE);
 
-	init_waitqueue(&raid_conf->wait_for_stripe);
+	init_waitqueue_head(&raid_conf->wait_for_stripe);
 	PRINTK(("raid5_run(%d) called.\n", minor));
 
   	for (i = 0; i < mddev->nb_dev; i++) {
diff -u --recursive --new-file v2.3.0/linux/drivers/block/rd.c linux/drivers/block/rd.c
--- v2.3.0/linux/drivers/block/rd.c	Thu Apr 29 11:53:41 1999
+++ linux/drivers/block/rd.c	Tue May 11 14:37:40 1999
@@ -482,6 +482,7 @@
 	memset(&inode, 0, sizeof(inode));
 	memset(&in_dentry, 0, sizeof(in_dentry));
 	inode.i_rdev = device;
+	init_waitqueue_head(&inode.i_wait);
 	infile.f_mode = 1; /* read only */
 	infile.f_dentry = &in_dentry;
 	in_dentry.d_inode = &inode;
@@ -490,6 +491,7 @@
 	memset(&out_inode, 0, sizeof(out_inode));
 	memset(&out_dentry, 0, sizeof(out_dentry));
 	out_inode.i_rdev = ram_device;
+	init_waitqueue_head(&out_inode.i_wait);
 	outfile.f_mode = 3; /* read/write */
 	outfile.f_dentry = &out_dentry;
 	out_dentry.d_inode = &out_inode;
diff -u --recursive --new-file v2.3.0/linux/drivers/block/rz1000.c linux/drivers/block/rz1000.c
--- v2.3.0/linux/drivers/block/rz1000.c	Mon Jan  4 15:07:27 1999
+++ linux/drivers/block/rz1000.c	Thu May 13 11:04:54 1999
@@ -26,9 +26,10 @@
 #include <linux/ioport.h>
 #include <linux/blkdev.h>
 #include <linux/hdreg.h>
-#include <asm/io.h>
 #include <linux/pci.h>
-#include "ide.h"
+#include <linux/ide.h>
+
+#include <asm/io.h>
 
 #ifdef CONFIG_BLK_DEV_IDEPCI
 
diff -u --recursive --new-file v2.3.0/linux/drivers/block/sl82c105.c linux/drivers/block/sl82c105.c
--- v2.3.0/linux/drivers/block/sl82c105.c	Wed Mar 10 21:48:46 1999
+++ linux/drivers/block/sl82c105.c	Thu May 13 11:04:54 1999
@@ -8,11 +8,11 @@
 #include <linux/blkdev.h>
 #include <linux/hdreg.h>
 #include <linux/pci.h>
+#include <linux/ide.h>
 
 #include <asm/io.h>
 #include <asm/dma.h>
 
-#include "ide.h"
 #include "ide_modes.h"
 
 void ide_init_sl82c105(ide_hwif_t *hwif)
diff -u --recursive --new-file v2.3.0/linux/drivers/block/swim3.c linux/drivers/block/swim3.c
--- v2.3.0/linux/drivers/block/swim3.c	Wed Mar 10 21:48:46 1999
+++ linux/drivers/block/swim3.c	Tue May 11 23:36:27 1999
@@ -193,7 +193,7 @@
 	struct timer_list timeout;
 	int	timeout_pending;
 	int	ejected;
-	struct wait_queue *wait;
+	wait_queue_head_t wait;
 	int	wanted;
 	struct device_node*	media_bay; /* NULL when not in bay */
 	char	dbdma_cmd_space[5 * sizeof(struct dbdma_cmd)];
@@ -1132,6 +1132,7 @@
 	fs->secpertrack = 18;
 	fs->total_secs = 2880;
 	fs->media_bay = mediabay;
+	init_waitqueue_head(&fs->wait);
 
 	fs->dma_cmd = (struct dbdma_cmd *) DBDMA_ALIGN(fs->dbdma_cmd_space);
 	memset(fs->dma_cmd, 0, 2 * sizeof(struct dbdma_cmd));
diff -u --recursive --new-file v2.3.0/linux/drivers/block/trm290.c linux/drivers/block/trm290.c
--- v2.3.0/linux/drivers/block/trm290.c	Fri Aug  7 17:56:09 1998
+++ linux/drivers/block/trm290.c	Thu May 13 11:04:54 1999
@@ -134,11 +134,10 @@
 #include <linux/hdreg.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
+#include <linux/ide.h>
 
 #include <asm/io.h>
 
-#include "ide.h"
-
 static void trm290_prepare_drive (ide_drive_t *drive, unsigned int use_dma)
 {
 	ide_hwif_t *hwif = HWIF(drive);
@@ -185,7 +184,7 @@
 			break;	/* always use PIO for writes */
 #endif
 		case ide_dma_read:
-			if (!(count = ide_build_dmatable(drive)))
+			if (!(count = ide_build_dmatable(drive, func)))
 				break;		/* try PIO instead of DMA */
 			trm290_prepare_drive(drive, 1);	/* select DMA xfer */
 			outl(virt_to_bus(hwif->dmatable)|reading|writing, hwif->dma_base);
diff -u --recursive --new-file v2.3.0/linux/drivers/block/umc8672.c linux/drivers/block/umc8672.c
--- v2.3.0/linux/drivers/block/umc8672.c	Wed May  6 14:42:54 1998
+++ linux/drivers/block/umc8672.c	Thu May 13 11:04:54 1999
@@ -47,8 +47,10 @@
 #include <linux/ioport.h>
 #include <linux/blkdev.h>
 #include <linux/hdreg.h>
+#include <linux/ide.h>
+
 #include <asm/io.h>
-#include "ide.h"
+
 #include "ide_modes.h"
 
 /*
diff -u --recursive --new-file v2.3.0/linux/drivers/block/via82c586.c linux/drivers/block/via82c586.c
--- v2.3.0/linux/drivers/block/via82c586.c	Fri Nov 13 10:29:44 1998
+++ linux/drivers/block/via82c586.c	Thu May 13 11:04:54 1999
@@ -1,18 +1,44 @@
 /*
- * linux/drivers/block/via82c586.c	Version 0.01	Aug 16, 1998
+ * linux/drivers/block/via82c586.c	Version 0.03	Nov. 19, 1998
  *
- *  Copyright (C) 1998 Michel Aubry
- *  Copyright (C) 1998 Andre Hedrick
+ *  Copyright (C) 1998 Michel Aubry, Maintainer
+ *  Copyright (C) 1998 Andre Hedrick, Integrater
  *
  *  The VIA MVP-3 is reported OK with UDMA.
+ *  The TX Pro III is also reported OK with UDMA.
  *
- *  VIA chips also have a single FIFO, with the same 64 bytes deep buffer (16 levels 
- *  of 4 bytes each).
- *  However, VIA chips can have the buffer split either 8:8 levels, 16:0 levels or 
- *  0:16 levels between both channels. One could think of using this feature, as even
- *  if no level of FIFO is given to a given channel, one can always reach ATAPI drives 
- *  through it, or, if one channel is unused, configuration defaults to an even split 
- *  FIFO levels.
+ *  VIA chips also have a single FIFO, with the same 64 bytes deep
+ *  buffer (16 levels of 4 bytes each).
+ *
+ *  However, VIA chips can have the buffer split either 8:8 levels,
+ *  16:0 levels or 0:16 levels between both channels. One could think
+ *  of using this feature, as even if no level of FIFO is given to a
+ *  given channel, one can for instance always reach ATAPI drives through
+ *  it, or, if one channel is unused, configuration defaults to
+ *  an even split FIFO levels.
+ *  
+ *  This feature is available only through a kernel command line :
+ *		"splitfifo=Chan,Thr0,Thr1" or "splitfifo=Chan".
+ *		where:  Chan =1,2,3 or 4 and Thrx = 1,2,3,or 4.
+ *
+ *  If Chan == 1:
+ *	gives all the fifo to channel 0,
+ *	sets its threshold to Thr0/4,
+ *	and disables any dma access to channel 1.
+ *
+ *  If chan == 2:
+ *	gives all the fifo to channel 1,
+ *	sets its threshold to Thr1/4,
+ *	and disables any dma access to channel 0.
+ *
+ *  If chan == 3 or 4:
+ *	shares evenly fifo between channels,
+ *	gives channel 0 a threshold of Thr0/4,
+ *	and channel 1 a threshold of Thr1/4.
+ *
+ *  Note that by default (if no command line is provided) and if a channel
+ *  has been disabled in Bios, all the fifo is given to the active channel,
+ *  and its threshold is set to 3/4.
  */
 
 #include <linux/types.h>
@@ -24,9 +50,255 @@
 #include <linux/blkdev.h>
 #include <linux/hdreg.h>
 #include <linux/pci.h>
+#include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/ide.h>
+
 #include <asm/io.h>
-#include "ide.h"
+
+#define DISPLAY_VIA_TIMINGS
+
+#if defined(DISPLAY_VIA_TIMINGS) && defined(CONFIG_PROC_FS)
+#include <linux/stat.h>
+#include <linux/proc_fs.h>
+
+static char *FIFO_str[] = {
+	" 1 ",
+	"3/4",
+	"1/2",
+	"1/4"
+};
+
+static char *control3_str[] = {
+	"No limitation",
+	"64",
+	"128",
+	"192"
+};
+
+static int via_get_info(char *, char **, off_t, int, int);
+extern int (*via_display_info)(char *, char **, off_t, int, int); /* ide-proc.c */
+static struct pci_dev *bmide_dev;
+
+static char * print_apollo_drive_config (char *buf, struct pci_dev *dev)
+{
+	int rc;
+	unsigned int time;
+	byte tm;
+	char *p = buf;  
+ 
+	/* Drive Timing Control */
+	rc = pci_read_config_dword(dev, 0x48, &time);
+	p += sprintf(p, "Act Pls Width:  %02d          %02d           %02d          %02d\n",
+			((time & 0xf0000000)>>28) + 1,
+			((time & 0xf00000)>>20) + 1,
+			((time & 0xf000)>>12) + 1,
+			((time & 0xf0)>>4) + 1 );
+	p += sprintf(p, "Recovery Time:  %02d          %02d           %02d          %02d\n",
+			((time & 0x0f000000)>>24) + 1,
+			((time & 0x0f0000)>>16) + 1,
+			((time & 0x0f00)>>8) + 1,
+			(time & 0x0f) + 1 );
+ 
+	/* Address Setup Time */
+	rc = pci_read_config_byte(dev, 0x4C, &tm);
+	p += sprintf(p, "Add. Setup T.:  %01dT          %01dT           %01dT          %01dT\n",
+			((tm & 0xc0)>>6) + 1,
+			((tm & 0x30)>>4) + 1,
+			((tm & 0x0c)>>2) + 1,
+			(tm & 0x03) + 1 );
+ 
+	/* UltraDMA33 Extended Timing Control */
+ 	rc = pci_read_config_dword(dev, 0x50, &time);
+ 	p += sprintf(p, "------------------UDMA-Timing-Control------------------------\n");
+ 	p += sprintf(p, "Enable Meth.:    %01d           %01d            %01d           %01d\n",
+			(time & 0x80000000)	? 1 : 0,
+			(time & 0x800000)	? 1 : 0,
+			(time & 0x8000)		? 1 : 0,
+			(time & 0x80)		? 1 : 0 );
+ 	p += sprintf(p, "Enable:         %s         %s          %s         %s\n",
+			(time & 0x40000000)	? "yes" : "no ",
+			(time & 0x400000)	? "yes" : "no ",
+			(time & 0x4000)		? "yes" : "no ",
+			(time & 0x40)		? "yes" : "no " );
+ 	p += sprintf(p, "Transfer Mode: %s         %s          %s         %s\n",
+			(time & 0x20000000)	? "PIO" : "DMA",
+			(time & 0x200000)	? "PIO" : "DMA",
+			(time & 0x2000)		? "PIO" : "DMA",
+			(time & 0x20)		? "PIO" : "DMA" );
+ 	p += sprintf(p, "Cycle Time:     %01dT          %01dT           %01dT          %01dT\n",
+			((time & 0x03000000)>>24) + 2,
+			((time & 0x030000)>>16) + 2,
+			((time & 0x0300)>>8) + 2,
+			(time & 0x03) + 2 );
+ 
+ 	return (char *)p;
+}
+
+static char * print_apollo_ide_config (char *buf, struct pci_dev *dev)
+{
+	byte time, tmp; 
+	unsigned short size0, size1;
+	int rc;
+	char *p = buf;  
+ 
+	rc = pci_read_config_byte(dev, 0x41, &time);
+	p += sprintf(p, "Prefetch Buffer :      %s                     %s\n",
+		(time & 128)	? "on " : "off",
+		(time & 32)	? "on " : "off" );
+	p += sprintf(p, "Post Write Buffer:     %s                     %s\n",
+		(time & 64)	? "on " : "off",
+		(time & 16)	? "on " : "off" );
+ 
+	/* FIFO configuration */
+	rc = pci_read_config_byte(dev, 0x43, &time);
+	tmp = ((time & 0x20)>>2) + ((time & 0x40)>>3);
+	p += sprintf(p, "FIFO Conf/Chan. :      %02d                      %02d\n",
+			16 - tmp, tmp);
+	tmp = (time & 0x0F)>>2;
+	p += sprintf(p, "Threshold Prim. :      %s                     %s\n",
+			FIFO_str[tmp],
+			FIFO_str[time & 0x03] );
+ 
+	/* chipset Control3 */
+	rc = pci_read_config_byte(dev, 0x46, &time);
+	p += sprintf(p, "Read DMA FIFO flush:   %s                     %s\n",
+			(time & 0x80)	? "on " : "off",
+			(time & 0x40)	? "on " : "off" );
+	p += sprintf(p, "End Sect. FIFO flush:  %s                     %s\n",
+			(time & 0x20)	? "on " : "off",
+			(time & 0x10)	? "on " : "off" );
+	p += sprintf(p, "Max DRDY Pulse Width:  %s %s\n",
+			control3_str[(time & 0x03)],
+			(time & 0x03) ? "PCI clocks" : "" );
+ 
+	/* Primary and Secondary sector sizes */
+	rc = pci_read_config_word(dev, 0x60, &size0);
+	rc = pci_read_config_word(dev, 0x68, &size1);
+	p += sprintf(p, "Bytes Per Sector:      %03d                     %03d\n",
+			size0 & 0xfff,
+			size1 & 0xfff );
+
+	return (char *)p;
+}
+
+static char * print_apollo_chipset_control1 (char *buf, struct pci_dev *dev)
+{
+	byte t;
+	int rc;
+	char *p = buf;  
+	unsigned short c;
+	byte l, l_max;   
+ 
+	rc = pci_read_config_word(dev, 0x04, &c);
+	rc = pci_read_config_byte(dev, 0x44, &t);
+	rc = pci_read_config_byte(dev, 0x0d, &l);
+	rc = pci_read_config_byte(dev, 0x3f, &l_max);
+
+	p += sprintf(p, "Command register = 0x%x\n", c);
+	p += sprintf(p, "Master Read  Cycle IRDY %d Wait State\n",
+			(t & 64) >>6 );
+	p += sprintf(p, "Master Write Cycle IRDY %d Wait State\n",
+			(t & 32) >> 5 );
+	p += sprintf(p, "FIFO Output Data 1/2 Clock Advance: %s\n",
+			(t & 16) ? "on " : "off" );
+	p += sprintf(p, "Bus Master IDE Status Register Read Retry: %s\n",
+			(t & 8) ? "on " : "off" );
+	p += sprintf(p, "Latency timer = %d (max. = %d)\n",
+			l, l_max);
+
+	return (char *)p;
+}
+ 
+static char * print_apollo_chipset_control2 (char *buf, struct pci_dev *dev)
+{
+	byte t;
+	int rc;
+	char *p = buf;  
+	rc = pci_read_config_byte(dev, 0x45, &t);
+	p += sprintf(p, "Interrupt Steering Swap: %s\n",
+			(t & 64) ? "on ":"off" );
+
+	return (char *)p;
+}
+ 
+static char * print_apollo_chipset_control3 (char *buf, struct pci_dev *dev,
+						unsigned short n)
+{
+	/*
+	 * at that point we can be sure that register 0x20 of the
+	 * chipset contains the right address...
+	 */
+	unsigned int bibma;
+	int rc;
+	byte c0, c1;    
+	char *p = buf; 
+ 
+	rc = pci_read_config_dword(dev, 0x20, &bibma);
+	bibma = (bibma & 0xfff0) ;
+ 
+	/*
+	 * at that point bibma+0x2 et bibma+0xa are byte registers
+	 * to investigate:
+	 */
+	c0 = inb((unsigned short)bibma + 0x02);
+	c1 = inb((unsigned short)bibma + 0x0a);
+ 
+	if (n == 0) {
+        /*p = sprintf(p,"--------------------Primary IDE------------Secondary IDE-----");*/
+		p += sprintf(p, "both channels togth:   %s                     %s\n",
+				(c0&0x80) ? "no" : "yes",
+				(c1&0x80) ? "no" : "yes" );
+	} else {
+        /*p = sprintf(p,"--------------drive0------drive1-------drive0------drive1----");*/
+		p += sprintf(p, "DMA enabled:    %s         %s          %s         %s\n",
+				(c0&0x20) ? "yes" : "no ",
+				(c0&0x40) ? "yes" : "no ",
+				(c1&0x20) ? "yes" : "no ",
+				(c1&0x40) ? "yes" : "no " );
+	}
+ 
+	return (char *)p;
+}
+
+static int via_get_info (char *buffer, char **addr, off_t offset, int count, int dummy)
+{
+	/*
+	 * print what /proc/via displays,
+	 * if required from DISPLAY_APOLLO_TIMINGS
+	 */
+	char *p = buffer;
+	/* Parameter of chipset : */
+
+	/* Miscellaneous control 1 */
+	p = print_apollo_chipset_control1(buffer, bmide_dev);
+
+	/* Miscellaneous control 2 */
+	p = print_apollo_chipset_control2(p, bmide_dev);
+	/* Parameters of drives: */
+
+	/* Header */
+	p += sprintf(p, "------------------Primary IDE------------Secondary IDE-----\n");
+	p = print_apollo_chipset_control3(p, bmide_dev, 0);
+	p = print_apollo_ide_config(p, bmide_dev);
+	p += sprintf(p, "--------------drive0------drive1-------drive0------drive1----\n");
+	p = print_apollo_chipset_control3(p, bmide_dev, 1);
+	p = print_apollo_drive_config(p, bmide_dev);
+ 
+	return p-buffer;	/* hoping it is less than 4K... */
+}
+
+#endif  /* defined(DISPLAY_VIA_TIMINGS) && defined(CONFIG_PROC_FS) */
+
+/*
+ *  Used to set Fifo configuration via kernel command line:
+ */
+
+byte fifoconfig = 0;
+static byte newfifo = 0;
+
+/* Used to just intialize once Fifo configuration */
+static short int done = 0;
 
 /*
  *  Set VIA Chipset Timings for (U)DMA modes enabled.
@@ -37,49 +309,162 @@
 static void set_via_timings (ide_hwif_t *hwif)
 {
 	struct pci_dev  *dev = hwif->pci_dev;
-	byte post  = hwif->channel ? 0xc0 : 0x30;
-	byte flush = hwif->channel ? 0xa0 : 0x50;
+	byte post  = hwif->channel ? 0x30 : 0xc0;
+	byte flush = hwif->channel ? 0x50 : 0xa0;
+	int mask = hwif->channel ? ((newfifo & 0x60) ? 0 : 1) :
+				   (((newfifo & 0x60) == 0x60) ? 1 : 0);
 	byte via_config = 0;
 	int rc = 0, errors = 0;
 
 	printk("%s: VIA Bus-Master ", hwif->name);
 
-	if (!hwif->dma_base) {
-		printk(" ERROR, NO DMA_BASE\n");
-		return;
-	}
-
-	/* setting IDE read prefetch buffer and IDE post write buffer.
+	/*
+	 * setting IDE read prefetch buffer and IDE post write buffer.
 	 * (This feature allows prefetched reads and post writes).
 	 */
-	if ((rc = pci_read_config_byte(dev, 0x41, &via_config))) {
-		errors++;
-		goto via_error;
-	}
-	if ((rc = pci_write_config_byte(dev, 0x41, via_config | post))) {
+	if ((rc = pci_read_config_byte(dev, 0x41, &via_config))) 
 		errors++;
-		goto via_error;
+
+	if (mask) {
+		if ((rc = pci_write_config_byte(dev, 0x41, via_config & ~post)))
+			errors++;
+	} else {
+		if ((rc = pci_write_config_byte(dev, 0x41, via_config | post)))
+			errors++;
 	}
 
-	/* setting Channel read and End-of-sector FIFO flush.
+	/*
+	 * setting Channel read and End-of-sector FIFO flush.
 	 * (This feature ensures that FIFO flush is enabled:
          *  - for read DMA when interrupt asserts the given channel.
          *  - at the end of each sector for the given channel.)
 	 */
-	if ((rc = pci_read_config_byte(dev, 0x46, &via_config))) {
+	if ((rc = pci_read_config_byte(dev, 0x46, &via_config)))
 		errors++;
-		goto via_error;
+
+	if (mask) {
+		if ((rc = pci_write_config_byte(dev, 0x46, via_config & ~flush)))
+			errors++;
+	} else {
+		if ((rc = pci_write_config_byte(dev, 0x46, via_config | flush)))
+			errors++;
 	}
-        if ((rc = pci_write_config_byte(dev, 0x46, via_config | flush))) {
-		errors++;
-		goto via_error;
+
+	if (!hwif->dma_base)
+		printk("Config %s. No DMA Enabled\n",
+			errors ? "ERROR":"Success");
+	else
+		printk("(U)DMA Timing Config %s\n",
+			errors ? "ERROR" : "Success");
+}
+
+/*
+ *  Sets VIA 82c586 FIFO configuration:
+ *  This chipsets gets a splitable fifo. This can be driven either by command
+ *  line option (eg "splitfifo=2,2,3" which asks this driver to switch all the 
+ *  16 fifo levels to the second drive, and give it a threshold of 3 for (u)dma 
+ *  triggering.
+ */
+
+static int via_set_fifoconfig(ide_hwif_t *hwif)
+{
+	byte fifo;
+	unsigned int timings;
+	struct pci_dev  *dev = hwif->pci_dev;
+
+	/* read port configuration */
+	if (pci_read_config_dword(dev, 0x40, &timings))
+		return 1;
+   
+	/* first read actual fifo config: */
+	if (pci_read_config_byte(dev, 0x43, &fifo))
+		return 1;
+
+	/* keep 4 and 7 bit as they seem to differ between chipsets flavors... */
+	newfifo = fifo & 0x90;
+
+	if (fifoconfig) {
+		/* we received a config request from kernel command line: */
+		newfifo |= fifoconfig & 0x6f;
+	} else {
+		/* If ever just one channel is unused, allocate all fifo levels to it
+		 * and give it a 3/4 threshold for (u)dma transfers.
+		 * Otherwise, share it evenly between channels:
+		 */
+		if ((timings & 3) == 2) {
+			/* only primary channel is  enabled
+			 * 16 buf. to prim. chan. thresh=3/4
+			 */
+			newfifo |= 0x06;
+		} else if ((timings & 3) == 1) {
+			/* only secondary channel is enabled!
+			 * 16 buffers to sec. ch. thresh=3/4
+			 */
+			newfifo |= 0x69;
+		} else {
+			/* fifo evenly distributed: */
+			newfifo |= 0x2a;
+		}
 	}
 
-via_error:
-	printk("(U)DMA Timing Config %s\n", errors ? "ERROR" : "Success");
+	/* write resulting configuration to chipset: */
+	if (pci_write_config_byte(dev, 0x43, newfifo))
+		return 1;
+
+	/* and then reread it to get the actual one */
+	if (pci_read_config_byte(dev, 0x43, &newfifo))
+		return 1;
+
+	/* print a kernel report: */
+	printk("Split FIFO Configuration: %s Primary buffers, threshold = %s\n",
+		((newfifo & 0x60) == 0x60)	? " 0" :
+		((newfifo & 0x60)		? " 8" : "16"),
+		!(newfifo & 0x0c)		? "1" :
+		(!(newfifo & 0x08)		? "3/4" :
+		(newfifo & 0x04)		? "1/4" : "1/2"));
+
+	printk("                          %s Second. buffers, threshold = %s\n",
+		((newfifo & 0x60) == 0x60)	? "16" :
+		((newfifo & 0x60)		? " 8" : " 0"),
+		!(newfifo & 0x03)		? "1" :
+		(!(newfifo & 0x02)		? "3/4" :
+		(newfifo & 0x01)		? "1/4" : "1/2"));
+
+#if defined(DISPLAY_VIA_TIMINGS) && defined(CONFIG_PROC_FS)
+	bmide_dev = hwif->pci_dev;
+	via_display_info = &via_get_info;
+#endif /* DISPLAY_VIA_TIMINGS &&  CONFIG_PROC_FS*/
+	return 0;
+}
+
+/*
+ *  ide_dmacapable_via82c568(ide_hwif_t *, unsigned long)
+ *  checks if channel "channel" of if hwif is dma
+ *  capable or not, according to kernel command line,
+ *  and the new fifo settings.
+ *  It calls "ide_setup_dma" on capable mainboards, and
+ *  bypasses the setup if not capable.
+ */
+
+void ide_dmacapable_via82c586 (ide_hwif_t *hwif, unsigned long dmabase)
+{
+	if (!done) {
+		via_set_fifoconfig(hwif);
+		done = 1;
+	}
+
+	/*
+	 * check if any fifo is available for requested port:
+	 */
+	if (((hwif->channel == 0) && ((newfifo & 0x60) == 0x60)) ||
+	    ((hwif->channel == 1) && ((newfifo & 0x60) == 0x00))) {
+		printk("    %s: VP_IDE Bus-Master DMA disabled (FIFO setting)\n", hwif->name);
+	} else {
+		ide_setup_dma(hwif, dmabase, 8);
+	}
 }
 
-void ide_init_via82c586 (ide_hwif_t *hwif)
+__initfunc(void ide_init_via82c586 (ide_hwif_t *hwif))
 {
 	set_via_timings(hwif);
 }
diff -u --recursive --new-file v2.3.0/linux/drivers/block/xd.c linux/drivers/block/xd.c
--- v2.3.0/linux/drivers/block/xd.c	Thu Jan  7 08:46:58 1999
+++ linux/drivers/block/xd.c	Tue May 11 23:37:06 1999
@@ -159,7 +159,8 @@
 	xd_release,		/* release */
 	block_fsync		/* fsync */
 };
-static struct wait_queue *xd_wait_int = NULL, *xd_wait_open = NULL;
+static DECLARE_WAIT_QUEUE_HEAD(xd_wait_int);
+static DECLARE_WAIT_QUEUE_HEAD(xd_wait_open);
 static u_char xd_valid[XD_MAXDRIVES] = { 0,0 };
 static u_char xd_drives = 0, xd_irq = 5, xd_dma = 3, xd_maxsectors;
 static u_char xd_override __initdata = 0, xd_type = 0;
@@ -167,7 +168,7 @@
 static int xd_geo[XD_MAXDRIVES*3] __initdata = { 0,0,0,0,0,0 };
 
 static volatile int xdc_busy = 0;
-static struct wait_queue *xdc_wait = NULL;
+static DECLARE_WAIT_QUEUE_HEAD(xdc_wait);
 
 typedef void (*timeout_fn)(unsigned long);
 static struct timer_list xd_timer = { NULL, NULL, 0, 0, (timeout_fn) xd_wakeup },
diff -u --recursive --new-file v2.3.0/linux/drivers/cdrom/aztcd.c linux/drivers/cdrom/aztcd.c
--- v2.3.0/linux/drivers/cdrom/aztcd.c	Mon Aug 24 13:02:43 1998
+++ linux/drivers/cdrom/aztcd.c	Wed May 12 13:27:37 1999
@@ -303,7 +303,7 @@
 static char  azt_auto_eject = AZT_AUTO_EJECT;
 
 static int AztTimeout, AztTries;
-static struct wait_queue *azt_waitq = NULL; 
+static DECLARE_WAIT_QUEUE_HEAD(azt_waitq);
 static struct timer_list delay_timer = { NULL, NULL, 0, 0, NULL };
 
 static struct azt_DiskInfo DiskInfo;
diff -u --recursive --new-file v2.3.0/linux/drivers/cdrom/cdu31a.c linux/drivers/cdrom/cdu31a.c
--- v2.3.0/linux/drivers/cdrom/cdu31a.c	Sun Dec 20 04:36:47 1998
+++ linux/drivers/cdrom/cdu31a.c	Wed May 12 13:27:37 1999
@@ -278,7 +278,7 @@
 static volatile int sony_inuse = 0;  /* Is the drive in use?  Only one operation
 					at a time allowed */
 
-static struct wait_queue * sony_wait = NULL;	/* Things waiting for the drive */
+static DECLARE_WAIT_QUEUE_HEAD(sony_wait);	/* Things waiting for the drive */
 
 static struct task_struct *has_cd_task = NULL;  /* The task that is currently
 						   using the CDROM drive, or
@@ -311,7 +311,7 @@
 
 /* The interrupt handler will wake this queue up when it gets an
    interrupts. */
-static struct wait_queue *cdu31a_irq_wait = NULL;
+DECLARE_WAIT_QUEUE_HEAD(cdu31a_irq_wait);
 
 static int curr_control_reg = 0; /* Current value of the control register */
 
@@ -577,13 +577,13 @@
       abort_read_started = 0;
 
       /* If something was waiting, wake it up now. */
-      if (cdu31a_irq_wait != NULL)
+      if (waitqueue_active(&cdu31a_irq_wait))
       {
          disable_interrupts();
          wake_up(&cdu31a_irq_wait);
       }
    }
-   else if (cdu31a_irq_wait != NULL)
+   else if (waitqueue_active(&cdu31a_irq_wait))
    {
       disable_interrupts();
       wake_up(&cdu31a_irq_wait);
diff -u --recursive --new-file v2.3.0/linux/drivers/cdrom/cm206.c linux/drivers/cdrom/cm206.c
--- v2.3.0/linux/drivers/cdrom/cm206.c	Wed Mar 10 17:01:57 1999
+++ linux/drivers/cdrom/cm206.c	Wed May 12 13:27:37 1999
@@ -262,8 +262,8 @@
   int openfiles;
   ush sector[READ_AHEAD*RAW_SECTOR_SIZE/2]; /* buffered cd-sector */
   int sector_first, sector_last; /* range of these sectors */
-  struct wait_queue * uart;	/* wait queues for interrupt */
-  struct wait_queue * data;
+  wait_queue_head_t uart;	/* wait queues for interrupt */
+  wait_queue_head_t data;
   struct timer_list timer;	/* time-out */
   char timed_out;
   signed char max_sectors;	/* number of sectors that fit in adapter mem */
@@ -360,7 +360,7 @@
     debug(("receiving #%d: 0x%x\n", cd->ur_w, cd->ur[cd->ur_w]));
     cd->ur_w++; cd->ur_w %= UR_SIZE;
     if (cd->ur_w == cd->ur_r) debug(("cd->ur overflow!\n"));
-    if (cd->uart && cd->background < 2) { 
+    if (waitqueue_active(&cd->uart) && cd->background < 2) { 
       del_timer(&cd->timer);
       wake_up_interruptible(&cd->uart);
     }
@@ -368,7 +368,7 @@
   /* data ready in fifo? */
   else if (cd->intr_ds & ds_data_ready) { 
     if (cd->background) ++cd->adapter_last;
-    if (cd->data && (cd->wait_back || !cd->background)) {
+    if (waitqueue_active(&cd->data) && (cd->wait_back || !cd->background)) {
       del_timer(&cd->timer);
       wake_up_interruptible(&cd->data);
     }
@@ -419,12 +419,12 @@
 {
   cd->timed_out = 1;
   debug(("Timing out\n"));
-  wake_up_interruptible((struct wait_queue **) who);
+  wake_up_interruptible((wait_queue_head_t *)who);
 }
 
 /* This function returns 1 if a timeout occurred, 0 if an interrupt
    happened */
-int sleep_or_timeout(struct wait_queue ** wait, int timeout)
+int sleep_or_timeout(wait_queue_head_t *wait, int timeout)
 {
   cd->timed_out=0;
   cd->timer.data=(unsigned long) wait;
@@ -442,7 +442,7 @@
 
 void cm206_delay(int nr_jiffies) 
 {
-  struct wait_queue * wait = NULL;
+  DECLARE_WAIT_QUEUE_HEAD(wait);
   sleep_or_timeout(&wait, nr_jiffies);
 }
 
diff -u --recursive --new-file v2.3.0/linux/drivers/cdrom/mcd.c linux/drivers/cdrom/mcd.c
--- v2.3.0/linux/drivers/cdrom/mcd.c	Mon Apr 12 16:18:28 1999
+++ linux/drivers/cdrom/mcd.c	Wed May 12 13:27:37 1999
@@ -162,7 +162,7 @@
 MODULE_PARM(mcd, "1-2i");
 
 static int McdTimeout, McdTries;
-static struct wait_queue *mcd_waitq = NULL;
+static DECLARE_WAIT_QUEUE_HEAD(mcd_waitq);
 
 static struct mcd_DiskInfo DiskInfo;
 static struct mcd_Toc Toc[MAX_TRACKS];
diff -u --recursive --new-file v2.3.0/linux/drivers/cdrom/mcdx.c linux/drivers/cdrom/mcdx.c
--- v2.3.0/linux/drivers/cdrom/mcdx.c	Sun Dec 20 04:36:47 1998
+++ linux/drivers/cdrom/mcdx.c	Wed May 12 13:27:37 1999
@@ -150,9 +150,9 @@
 
 struct s_drive_stuff {
 	/* waitqueues */
-    struct wait_queue *busyq;
-    struct wait_queue *lockq;
-    struct wait_queue *sleepq;
+    wait_queue_head_t busyq;
+    wait_queue_head_t lockq;
+    wait_queue_head_t sleepq;
 
  	/* flags */
     volatile int introk;	/* status of last irq operation */
@@ -1046,6 +1046,10 @@
 	stuffp->wreg_reset = stuffp->rreg_status = stuffp->wreg_data + 1;
 	stuffp->wreg_hcon = stuffp->wreg_reset + 1;
 	stuffp->wreg_chn = stuffp->wreg_hcon + 1;
+	
+	init_waitqueue_head(&stuffp->busyq);
+	init_waitqueue_head(&stuffp->lockq);
+	init_waitqueue_head(&stuffp->sleepq);
 
 	/* check if i/o addresses are available */
 	if (check_region((unsigned int) stuffp->wreg_data, MCDX_IO_SIZE)) {
diff -u --recursive --new-file v2.3.0/linux/drivers/cdrom/optcd.c linux/drivers/cdrom/optcd.c
--- v2.3.0/linux/drivers/cdrom/optcd.c	Sat Apr 24 17:49:37 1999
+++ linux/drivers/cdrom/optcd.c	Wed May 12 13:27:37 1999
@@ -257,7 +257,7 @@
 
 /* Timed waiting for status or data */
 static int sleep_timeout;	/* max # of ticks to sleep */
-static struct wait_queue *waitq = NULL;
+static DECLARE_WAIT_QUEUE_HEAD(waitq);
 static struct timer_list delay_timer = {NULL, NULL, 0, 0, NULL};
 
 #define SET_TIMER(func, jifs) \
diff -u --recursive --new-file v2.3.0/linux/drivers/cdrom/sbpcd.c linux/drivers/cdrom/sbpcd.c
--- v2.3.0/linux/drivers/cdrom/sbpcd.c	Sun Dec 20 04:36:47 1998
+++ linux/drivers/cdrom/sbpcd.c	Wed May 12 13:27:37 1999
@@ -612,7 +612,7 @@
 static volatile u_char busy_data=0;
 static volatile u_char busy_audio=0; /* true semaphores would be safer */
 #endif OLD_BUSY
-static struct semaphore ioctl_read_sem = MUTEX;
+static DECLARE_MUTEX(ioctl_read_sem);
 static u_long timeout;
 static volatile u_char timed_out_delay=0;
 static volatile u_char timed_out_data=0;
diff -u --recursive --new-file v2.3.0/linux/drivers/cdrom/sjcd.c linux/drivers/cdrom/sjcd.c
--- v2.3.0/linux/drivers/cdrom/sjcd.c	Mon Apr 12 16:18:32 1999
+++ linux/drivers/cdrom/sjcd.c	Wed May 12 13:27:37 1999
@@ -115,7 +115,7 @@
 MODULE_PARM(sjcd_base, "i");
 #endif
 
-static struct wait_queue *sjcd_waitq = NULL;
+static DECLARE_WAIT_QUEUE_HEAD(sjcd_waitq);
 
 /*
  * Data transfer.
diff -u --recursive --new-file v2.3.0/linux/drivers/cdrom/sonycd535.c linux/drivers/cdrom/sonycd535.c
--- v2.3.0/linux/drivers/cdrom/sonycd535.c	Thu Jan  7 08:46:59 1999
+++ linux/drivers/cdrom/sonycd535.c	Wed May 12 13:27:37 1999
@@ -261,7 +261,7 @@
 static int sony535_irq_used = CDU535_INTERRUPT;
 
 /* The interrupt handler will wake this queue up when it gets an interrupt. */
-static struct wait_queue *cdu535_irq_wait = NULL;
+static DECLARE_WAIT_QUEUE_HEAD(cdu535_irq_wait);
 
 
 /*
@@ -318,7 +318,7 @@
 cdu535_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	disable_interrupts();
-	if (cdu535_irq_wait != NULL)
+	if (wait_queue_active(&cdu535_irq_wait))
 		wake_up(&cdu535_irq_wait);
 	else
 		printk(CDU535_MESSAGE_NAME
diff -u --recursive --new-file v2.3.0/linux/drivers/char/atixlmouse.c linux/drivers/char/atixlmouse.c
--- v2.3.0/linux/drivers/char/atixlmouse.c	Mon Aug 24 13:02:43 1998
+++ linux/drivers/char/atixlmouse.c	Wed May 12 13:27:37 1999
@@ -67,7 +67,7 @@
 	int present;
 	int ready;
 	int active;
-	struct wait_queue *wait;
+	wait_queue_head_t wait;
 	struct fasync_struct *fasync;
 } mouse;
 
@@ -223,7 +223,7 @@
 	mouse.ready = 0;
 	mouse.buttons = mouse.latch_buttons = 0;
 	mouse.dx = mouse.dy = 0;
-	mouse.wait = NULL;
+	init_waitqueue_head(&mouse.wait);
 	printk("Bus mouse detected and installed.\n");
 	misc_register(&atixl_mouse);
 	return 0;
diff -u --recursive --new-file v2.3.0/linux/drivers/char/bttv.c linux/drivers/char/bttv.c
--- v2.3.0/linux/drivers/char/bttv.c	Sat Apr 24 17:49:37 1999
+++ linux/drivers/char/bttv.c	Wed May 12 08:41:12 1999
@@ -3421,10 +3421,10 @@
         btv->risc_jmp=NULL;
         btv->vbi_odd=NULL;
         btv->vbi_even=NULL;
-        btv->vbiq=NULL;
-        btv->capq=NULL;
-        btv->capqo=NULL;
-        btv->capqe=NULL;
+        init_waitqueue_head(&btv->vbiq);
+        init_waitqueue_head(&btv->capq);
+        init_waitqueue_head(&btv->capqo);
+        init_waitqueue_head(&btv->capqe);
         btv->vbip=VBIBUF_SIZE;
 
         btv->id=dev->device;
diff -u --recursive --new-file v2.3.0/linux/drivers/char/bttv.h linux/drivers/char/bttv.h
--- v2.3.0/linux/drivers/char/bttv.h	Sat Apr 24 17:49:37 1999
+++ linux/drivers/char/bttv.h	Wed May 12 08:41:12 1999
@@ -122,10 +122,10 @@
 	u32 *vbi_even;
 	u32 bus_vbi_even;
 	u32 bus_vbi_odd;
-	struct wait_queue *vbiq;
-	struct wait_queue *capq;
-	struct wait_queue *capqo;
-	struct wait_queue *capqe;
+	wait_queue_head_t vbiq;
+	wait_queue_head_t capq;
+	wait_queue_head_t capqo;
+	wait_queue_head_t capqe;
 	int vbip;
 
 	u32 *risc_odd;
diff -u --recursive --new-file v2.3.0/linux/drivers/char/busmouse.c linux/drivers/char/busmouse.c
--- v2.3.0/linux/drivers/char/busmouse.c	Wed Dec 16 13:38:18 1998
+++ linux/drivers/char/busmouse.c	Wed May 12 13:27:37 1999
@@ -277,7 +277,7 @@
 	mouse.buttons = 0x87;
 	mouse.dx = 0;
 	mouse.dy = 0;
-	mouse.wait = NULL;
+	init_waitqueue_head(&mouse.wait);
 	printk(KERN_INFO "Logitech bus mouse detected, using IRQ %d.\n",
 	       mouse_irq);
 	misc_register(&bus_mouse);
diff -u --recursive --new-file v2.3.0/linux/drivers/char/console.c linux/drivers/char/console.c
--- v2.3.0/linux/drivers/char/console.c	Wed Mar 10 16:51:35 1999
+++ linux/drivers/char/console.c	Tue May 11 14:37:40 1999
@@ -2269,7 +2269,7 @@
 	def_color       = 0x07;   /* white */
 	ulcolor		= 0x0f;   /* bold white */
 	halfcolor       = 0x08;   /* grey */
-	vt_cons[currcons]->paste_wait = 0;
+	init_waitqueue_head(&vt_cons[currcons]->paste_wait);
 	reset_terminal(currcons, do_clear);
 }
 
diff -u --recursive --new-file v2.3.0/linux/drivers/char/cyclades.c linux/drivers/char/cyclades.c
--- v2.3.0/linux/drivers/char/cyclades.c	Mon Apr 12 10:09:47 1999
+++ linux/drivers/char/cyclades.c	Wed May 12 13:27:37 1999
@@ -697,7 +697,7 @@
  * allocated when the first cy_open occurs.
  */
 static unsigned char *tmp_buf;
-static struct semaphore tmp_buf_sem = MUTEX;
+DECLARE_MUTEX(tmp_buf_sem);
 
 /*
  * This is used to look up the divisor speeds and the timeouts
@@ -2246,7 +2246,7 @@
 block_til_ready(struct tty_struct *tty, struct file * filp,
                            struct cyclades_port *info)
 {
-  struct wait_queue wait = { current, NULL };
+  DECLARE_WAITQUEUE(wait, current);
   struct cyclades_card *cinfo;
   unsigned long flags;
   int chip, channel,index;
@@ -5210,9 +5210,9 @@
 		                cy_callout_driver.init_termios;
                     info->normal_termios =
 		                cy_serial_driver.init_termios;
-                    info->open_wait = 0;
-                    info->close_wait = 0;
-                    info->shutdown_wait = 0;
+                    init_waitqueue_head(&info->open_wait);
+                    init_waitqueue_head(&info->close_wait);
+                    init_waitqueue_head(&info->shutdown_wait);
                     /* info->session */
                     /* info->pgrp */
                     info->read_status_mask = 0;
@@ -5279,9 +5279,9 @@
 		               cy_callout_driver.init_termios;
                     info->normal_termios =
 		               cy_serial_driver.init_termios;
-                    info->open_wait = 0;
-                    info->close_wait = 0;
-                    info->shutdown_wait = 0;
+                    init_waitqueue(&info->open_wait);
+                    init_waitqueue(&info->close_wait);
+                    init_waitqueue(&info->shutdown_wait);
                     /* info->session */
                     /* info->pgrp */
                     info->read_status_mask =
diff -u --recursive --new-file v2.3.0/linux/drivers/char/dtlk.c linux/drivers/char/dtlk.c
--- v2.3.0/linux/drivers/char/dtlk.c	Fri Apr 16 08:20:23 1999
+++ linux/drivers/char/dtlk.c	Wed May 12 13:27:37 1999
@@ -87,7 +87,7 @@
 static int dtlk_has_indexing;
 static unsigned int dtlk_portlist[] =
 {0x25e, 0x29e, 0x2de, 0x31e, 0x35e, 0x39e, 0};
-static struct wait_queue *dtlk_process_list = NULL;
+static wait_queue_head_t dtlk_process_list;
 static struct timer_list dtlk_timer;
 
 /* prototypes for file_operations struct */
@@ -382,7 +382,7 @@
 
 	init_timer(&dtlk_timer);
 	dtlk_timer.function = dtlk_timer_tick;
-	dtlk_process_list = NULL;
+	init_waitqueue_head(&dtlk_process_list);
 
 	return 0;
 }
diff -u --recursive --new-file v2.3.0/linux/drivers/char/epca.c linux/drivers/char/epca.c
--- v2.3.0/linux/drivers/char/epca.c	Tue Mar 16 14:21:51 1999
+++ linux/drivers/char/epca.c	Wed May 12 13:27:37 1999
@@ -1268,7 +1268,7 @@
                            struct file *filp, struct channel *ch)
 { /* Begin block_til_ready */
 
-	struct wait_queue wait = {current, NULL};
+	DECLARE_WAITQUEUE(wait,current);
 	int	retval, do_clocal = 0;
 	unsigned long flags;
 
@@ -2236,8 +2236,8 @@
 		ch->blocked_open = 0;
 		ch->callout_termios = pc_callout.init_termios;
 		ch->normal_termios = pc_driver.init_termios;
-		ch->open_wait = 0;
-		ch->close_wait = 0;
+		init_waitqueue_head(&ch->open_wait);
+		init_waitqueue_head(&ch->close_wait);
 		ch->tmp_buf = kmalloc(ch->txbufsize,GFP_KERNEL);
 		if (!(ch->tmp_buf))
 		{
diff -u --recursive --new-file v2.3.0/linux/drivers/char/esp.c linux/drivers/char/esp.c
--- v2.3.0/linux/drivers/char/esp.c	Sat Oct 31 11:06:21 1998
+++ linux/drivers/char/esp.c	Wed May 12 13:27:37 1999
@@ -169,7 +169,7 @@
  * memory if large numbers of serial ports are open.
  */
 static unsigned char *tmp_buf = 0;
-static struct semaphore tmp_buf_sem = MUTEX;
+static DECLARE_MUTEX(tmp_buf_sem);
 
 static inline int serial_paranoia_check(struct esp_struct *info,
 					kdev_t device, const char *routine)
@@ -2224,7 +2224,7 @@
 static int block_til_ready(struct tty_struct *tty, struct file * filp,
 			   struct esp_struct *info)
 {
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 	int		retval;
 	int		do_clocal = 0;
 
@@ -2676,6 +2676,10 @@
 		info->config.flow_off = flow_off;
 		info->config.pio_threshold = pio_threshold;
 		info->next_port = ports;
+		init_waitqueue_head(&info->open_wait);
+		init_waitqueue_head(&info->close_wait);
+		init_waitqueue_head(&info->delta_msr_wait);
+		init_waitqueue_head(&info->break_wait);
 		ports = info;
 		printk(KERN_INFO "ttyP%d at 0x%04x (irq = %d) is an ESP ",
 			info->line, info->port, info->irq);
diff -u --recursive --new-file v2.3.0/linux/drivers/char/ftape/lowlevel/fdc-io.c linux/drivers/char/ftape/lowlevel/fdc-io.c
--- v2.3.0/linux/drivers/char/ftape/lowlevel/fdc-io.c	Tue Dec 29 11:27:38 1998
+++ linux/drivers/char/ftape/lowlevel/fdc-io.c	Wed May 12 13:27:37 1999
@@ -54,7 +54,7 @@
 volatile int ftape_current_cylinder = -1;
 volatile fdc_mode_enum fdc_mode = fdc_idle;
 fdc_config_info fdc = {0};
-struct wait_queue *ftape_wait_intr = NULL;
+DECLARE_WAIT_QUEUE_HEAD(ftape_wait_intr);
 
 unsigned int ft_fdc_base       = CONFIG_FT_FDC_BASE;
 unsigned int ft_fdc_irq        = CONFIG_FT_FDC_IRQ;
@@ -385,7 +385,7 @@
  */
 int fdc_interrupt_wait(unsigned int time)
 {
-	struct wait_queue wait = {current, NULL};
+	DECLARE_WAITQUEUE(wait,current);
 	sigset_t old_sigmask;	
 	static int resetting = 0;
 	long timeout;
diff -u --recursive --new-file v2.3.0/linux/drivers/char/ftape/lowlevel/fdc-io.h linux/drivers/char/ftape/lowlevel/fdc-io.h
--- v2.3.0/linux/drivers/char/ftape/lowlevel/fdc-io.h	Tue Nov 25 14:45:27 1997
+++ linux/drivers/char/ftape/lowlevel/fdc-io.h	Wed May 12 13:27:37 1999
@@ -209,7 +209,7 @@
  */
 extern volatile fdc_mode_enum fdc_mode;
 extern int fdc_setup_error;	/* outdated ??? */
-extern struct wait_queue *ftape_wait_intr;
+extern wait_queue_head_t ftape_wait_intr;
 extern int ftape_motor;		/* fdc motor line state */
 extern volatile int ftape_current_cylinder; /* track nr FDC thinks we're on */
 extern volatile __u8 fdc_head;	/* FDC head */
diff -u --recursive --new-file v2.3.0/linux/drivers/char/hfmodem/main.c linux/drivers/char/hfmodem/main.c
--- v2.3.0/linux/drivers/char/hfmodem/main.c	Sun Jan 17 18:28:06 1999
+++ linux/drivers/char/hfmodem/main.c	Wed May 12 13:27:37 1999
@@ -638,6 +638,7 @@
 	hfmodem_state[0].ptt_out.seriobase = serio;
 	hfmodem_state[0].ptt_out.pariobase = pario;
 	hfmodem_state[0].ptt_out.midiiobase = midiio;
+	init_waitqueue_head(&hfmodem_state[0].wait);
 	hfmodem_refclock_probe();
 	output_check(&hfmodem_state[0]);
 #if defined(CONFIG_HFMODEM_WSS) && defined(CONFIG_HFMODEM_SBC)
@@ -703,7 +704,8 @@
         int i;
 
 	printk(hfmodem_drvinfo);
-        hfmodem_refclock_probe();
+ 	init_waitqueue_head(&hfmode_state[0].wait);
+       hfmodem_refclock_probe();
         output_check(&hfmodem_state[0]);
 #if defined(CONFIG_HFMODEM_WSS) && defined(CONFIG_HFMODEM_SBC)
         if (hw) 
diff -u --recursive --new-file v2.3.0/linux/drivers/char/isicom.c linux/drivers/char/isicom.c
--- v2.3.0/linux/drivers/char/isicom.c	Fri May  7 11:05:30 1999
+++ linux/drivers/char/isicom.c	Wed May 12 13:27:37 1999
@@ -80,7 +80,7 @@
 static void isicom_start(struct tty_struct * tty);
 
 static unsigned char * tmp_buf = 0;
-static struct semaphore tmp_buf_sem = MUTEX;
+static DECLARE_MUTEX(tmp_buf_sem);
 
 /*   baud index mappings from linux defns to isi */
 
@@ -870,7 +870,7 @@
 static int block_til_ready(struct tty_struct * tty, struct file * filp, struct isi_port * port) 
 {
 	int do_clocal = 0, retval;
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 
 	/* block if port is in the process of being closed */
 
@@ -1858,7 +1858,8 @@
 		 	port->bh_tqueue.routine = isicom_bottomhalf;
 		 	port->bh_tqueue.data = port;
 		 	port->status = 0;
-		 				
+			init_waitqueue_head(&port->open_wait);	 				
+			init_waitqueue_head(&port->close_wait);
 			/*  . . .  */
  		}
 	} 
diff -u --recursive --new-file v2.3.0/linux/drivers/char/joystick/joystick.c linux/drivers/char/joystick/joystick.c
--- v2.3.0/linux/drivers/char/joystick/joystick.c	Tue Dec  1 19:05:05 1998
+++ linux/drivers/char/joystick/joystick.c	Wed May 12 13:27:37 1999
@@ -491,7 +491,7 @@
 static int js_read(struct inode *inode, struct file *file, char *buf, int count)
 #endif
 {
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 	struct js_event *buff = (void *) buf;
 	struct js_list *curl;
 	struct js_dev *jd;
@@ -1081,7 +1081,7 @@
 	curd->next = NULL;
 	curd->list = NULL;
 	curd->port = port;
-	curd->wait = NULL;
+	init_waitqueue_head(&curd->wait);
 	curd->open = open;
 	curd->close = close;
 
diff -u --recursive --new-file v2.3.0/linux/drivers/char/keyboard.c linux/drivers/char/keyboard.c
--- v2.3.0/linux/drivers/char/keyboard.c	Mon Apr 26 13:21:42 1999
+++ linux/drivers/char/keyboard.c	Tue May 11 14:37:40 1999
@@ -64,7 +64,7 @@
 
 extern void ctrl_alt_del(void);
 
-struct wait_queue * keypress_wait = NULL;
+DECLARE_WAIT_QUEUE_HEAD(keypress_wait);
 struct console;
 
 int keyboard_wait_for_keypress(struct console *co)
diff -u --recursive --new-file v2.3.0/linux/drivers/char/lp.c linux/drivers/char/lp.c
--- v2.3.0/linux/drivers/char/lp.c	Mon May 10 10:26:31 1999
+++ linux/drivers/char/lp.c	Wed May 12 08:41:12 1999
@@ -187,15 +187,7 @@
 /* if you have more than 3 printers, remember to increase LP_NO */
 #define LP_NO 3
 
-struct lp_struct lp_table[LP_NO] =
-{
-	[0 ... LP_NO-1] = {NULL, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT,
-			   NULL,
-#ifdef LP_STATS
-			   0, 0, {0},
-#endif
-			   NULL, 0, 0, 0}
-};
+struct lp_struct lp_table[LP_NO];
 
 /* Test if printer is ready */
 #define	LP_READY(status)	((status) & LP_PBUSY)
@@ -737,6 +729,7 @@
 		LP_F(minor) &= ~LP_BUSY;
 		return -ENOMEM;
 	}
+	init_waitqueue_head(&(lp_table[minor].wait_q));
 	return 0;
 }
 
@@ -928,6 +921,24 @@
 	unsigned int count = 0;
 	unsigned int i;
 	struct parport *port;
+
+	for(i = 0; i < LP_NO; i++) {
+		lp_table[i].dev = NULL;
+		lp_table[i].flags = 0;
+		lp_table[i].chars = LP_INIT_CHAR;
+		lp_table[i].time = LP_INIT_TIME;
+		lp_table[i].wait = LP_INIT_WAIT;
+		lp_table[i].lp_buffer = NULL;
+#ifdef LP_STATS
+		lp_table[i].lastcall = 0;
+		lp_table[i].runchars = 0;
+		memset(&lp_table[i].stats, 0, sizeof(struct lp_stats));
+#endif
+		init_waitqueue_head(&lp_table[i].wait_q);
+		lp_table[i].last_error = 0;
+		lp_table[i].irq_detected = 0;
+		lp_table[i].irq_missed = 0;
+	}
 
 	switch (parport_nr[0])
 	{
diff -u --recursive --new-file v2.3.0/linux/drivers/char/msbusmouse.c linux/drivers/char/msbusmouse.c
--- v2.3.0/linux/drivers/char/msbusmouse.c	Wed Dec 16 13:39:11 1998
+++ linux/drivers/char/msbusmouse.c	Wed May 12 13:27:37 1999
@@ -195,7 +195,7 @@
 	mouse.present = mouse.active = mouse.ready = 0;
 	mouse.buttons = 0x80;
 	mouse.dx = mouse.dy = 0;
-	mouse.wait = NULL;
+	init_waitqueue_head(&mouse.wait);
 
 	if (check_region(MS_MSE_CONTROL_PORT, 0x04))
 		return -ENODEV;
diff -u --recursive --new-file v2.3.0/linux/drivers/char/msp3400.c linux/drivers/char/msp3400.c
--- v2.3.0/linux/drivers/char/msp3400.c	Wed Feb 17 09:37:51 1999
+++ linux/drivers/char/msp3400.c	Wed May 12 08:41:07 1999
@@ -83,7 +83,7 @@
 
 	/* thread */
 	struct task_struct  *thread;
-	struct wait_queue   *wq;
+	wait_queue_head_t    wq;
 	struct semaphore    *notify;
 	int                  active,restart,rmmod;
 
@@ -523,7 +523,6 @@
 	current->fs->umask = 0;
 	strcpy(current->comm,"msp3400");
 
-	msp->wq     = NULL;
 	msp->thread = current;
 
 #ifdef __SMP__
@@ -748,7 +747,7 @@
 {
 	unsigned long flags;
 	struct msp3400c *msp = data;
-	struct semaphore sem = MUTEX_LOCKED;
+	DECLARE_MUTEX_LOCKED(sem);
 	int              i, val;
 
 	/* lock_kernel(); */
@@ -844,7 +843,7 @@
 static struct msp3400c *mspmix = NULL;  /* ugly hack, should do something more sensible */
 static int mixer_num;
 static int mixer_modcnt = 0;
-static struct semaphore mixer_sem = MUTEX;
+static DECLARE_MUTEX(mixer_sem);
 
 static int mix_to_v4l(int i)
 {
@@ -1016,7 +1015,7 @@
 
 static int msp3400c_attach(struct i2c_device *device)
 {
-	struct semaphore sem = MUTEX_LOCKED;
+	DECLARE_MUTEX_LOCKED(sem);
 	struct msp3400c *msp;
 	int              rev1,rev2;
 	LOCK_FLAGS;
@@ -1030,6 +1029,7 @@
 	msp->right  = 65535;
 	msp->bass   = 32768;
 	msp->treble = 32768;
+	init_waitqueue_head(&msp->wq);
 
 	LOCK_I2C_BUS(msp->bus);
 	if (-1 == msp3400c_reset(msp->bus)) {
@@ -1069,7 +1069,6 @@
 
 	/* startup control thread */
 	MOD_INC_USE_COUNT;
-	msp->wq     = NULL;
 	msp->notify = &sem;
 	kernel_thread(msp3400c_thread, (void *)msp, 0);
 	down(&sem);
@@ -1090,7 +1089,7 @@
 
 static int msp3400c_detach(struct i2c_device *device)
 {
-	struct semaphore sem = MUTEX_LOCKED;
+	DECLARE_MUTEX_LOCKED(sem);
 	struct msp3400c *msp  = (struct msp3400c*)device->data;
 	LOCK_FLAGS;
     
diff -u --recursive --new-file v2.3.0/linux/drivers/char/n_hdlc.c linux/drivers/char/n_hdlc.c
--- v2.3.0/linux/drivers/char/n_hdlc.c	Fri Mar 12 08:20:38 1999
+++ linux/drivers/char/n_hdlc.c	Wed May 12 13:27:37 1999
@@ -221,8 +221,8 @@
 	struct tty_struct *backup_tty;	/* TTY to use if tty gets closed */
 	
 	/* Queues for select() functionality */
-	struct wait_queue *read_wait;
-	struct wait_queue *write_wait;
+	wait_queue_head_t read_wait;
+	wait_queue_head_t write_wait;
 
 	int		tbusy;		/* reentrancy flag for tx wakeup code */
 	int		woke_up;
@@ -724,7 +724,7 @@
 {
 	struct n_hdlc *n_hdlc = tty2n_hdlc (tty);
 	int error = 0;
-	struct wait_queue wait = {current, NULL};
+	DECLARE_WAITQUEUE(wait, current);
 	N_HDLC_BUF *tbuf;
 
 	if (debuglevel >= DEBUG_LEVEL_INFO)	
@@ -1006,8 +1006,8 @@
 	n_hdlc->magic  = HDLC_MAGIC;
 
 	n_hdlc->flags  = 0;
-	n_hdlc->read_wait  = NULL;
-	n_hdlc->write_wait = NULL;
+	init_waitqueue_head(&n_hdlc->read_wait);
+	init_waitqueue_head(&n_hdlc->write_wait);
 	
 	return n_hdlc;
 	
diff -u --recursive --new-file v2.3.0/linux/drivers/char/n_tty.c linux/drivers/char/n_tty.c
--- v2.3.0/linux/drivers/char/n_tty.c	Sat Apr 24 17:49:37 1999
+++ linux/drivers/char/n_tty.c	Tue May 11 14:37:40 1999
@@ -605,7 +605,7 @@
 			tty->canon_data++;
 			if (tty->fasync)
 				kill_fasync(tty->fasync, SIGIO);
-			if (tty->read_wait)
+			if (waitqueue_active(&tty->read_wait))
 				wake_up_interruptible(&tty->read_wait);
 			return;
 		}
@@ -707,7 +707,7 @@
 	if (!tty->icanon && (tty->read_cnt >= tty->minimum_to_wake)) {
 		if (tty->fasync)
 			kill_fasync(tty->fasync, SIGIO);
-		if (tty->read_wait)
+		if (waitqueue_active(&tty->read_wait))
 			wake_up_interruptible(&tty->read_wait);
 	}
 
@@ -868,7 +868,7 @@
 			 unsigned char *buf, size_t nr)
 {
 	unsigned char *b = buf;
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 	int c;
 	int minimum, time;
 	ssize_t retval = 0;
@@ -1058,7 +1058,7 @@
 			  const unsigned char * buf, size_t nr)
 {
 	const unsigned char *b = buf;
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 	int c;
 	ssize_t retval = 0;
 
diff -u --recursive --new-file v2.3.0/linux/drivers/char/pc110pad.c linux/drivers/char/pc110pad.c
--- v2.3.0/linux/drivers/char/pc110pad.c	Sat Sep  5 17:01:45 1998
+++ linux/drivers/char/pc110pad.c	Wed May 12 13:27:37 1999
@@ -48,7 +48,7 @@
 
 
 /* driver/filesystem interface management */
-static struct wait_queue *queue;
+static wait_queue_head_t queue;
 static struct fasync_struct *asyncptr;
 static int active=0;	/* number of concurrent open()s */
 
@@ -656,6 +656,7 @@
 		return -EBUSY;
 	}
 	request_region(current_params.io, 4, "pc110pad");
+	init_waitqueue_head(&queue);
 	printk("PC110 digitizer pad at 0x%X, irq %d.\n",
 		current_params.io,current_params.irq);
 	misc_register(&pc110_pad);
diff -u --recursive --new-file v2.3.0/linux/drivers/char/pc_keyb.c linux/drivers/char/pc_keyb.c
--- v2.3.0/linux/drivers/char/pc_keyb.c	Mon Apr 26 13:43:01 1999
+++ linux/drivers/char/pc_keyb.c	Tue May 11 14:37:40 1999
@@ -864,7 +864,7 @@
 static ssize_t read_aux(struct file * file, char * buffer,
 			size_t count, loff_t *ppos)
 {
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 	ssize_t i = count;
 	unsigned char c;
 
@@ -964,7 +964,7 @@
 	queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL);
 	memset(queue, 0, sizeof(*queue));
 	queue->head = queue->tail = 0;
-	queue->proc_list = NULL;
+	init_waitqueue_head(&queue->proc_list);
 
 #ifdef INITIALIZE_MOUSE
 	kbd_write(KBD_CNTL_REG, KBD_CCMD_MOUSE_ENABLE);	/* Enable Aux. */
diff -u --recursive --new-file v2.3.0/linux/drivers/char/pc_keyb.h linux/drivers/char/pc_keyb.h
--- v2.3.0/linux/drivers/char/pc_keyb.h	Sat Feb  6 12:46:20 1999
+++ linux/drivers/char/pc_keyb.h	Tue May 11 14:37:40 1999
@@ -124,7 +124,7 @@
 struct aux_queue {
 	unsigned long head;
 	unsigned long tail;
-	struct wait_queue *proc_list;
+	wait_queue_head_t proc_list;
 	struct fasync_struct *fasync;
 	unsigned char buf[AUX_BUF_SIZE];
 };
diff -u --recursive --new-file v2.3.0/linux/drivers/char/pty.c linux/drivers/char/pty.c
--- v2.3.0/linux/drivers/char/pty.c	Sat Feb  6 17:28:37 1999
+++ linux/drivers/char/pty.c	Wed May 12 08:41:15 1999
@@ -30,7 +30,7 @@
 
 struct pty_struct {
 	int	magic;
-	struct wait_queue * open_wait;
+	wait_queue_head_t open_wait;
 };
 
 #define PTY_MAGIC 0x5001
@@ -336,13 +336,13 @@
 
 __initfunc(int pty_init(void))
 {
-#ifdef CONFIG_UNIX98_PTYS
 	int i;
-#endif
 
 	/* Traditional BSD devices */
 
 	memset(&pty_state, 0, sizeof(pty_state));
+	for (i = 0; i < NR_PTYS; i++)
+		init_waitqueue_head(&pty_state[i].open_wait);
 	memset(&pty_driver, 0, sizeof(struct tty_driver));
 	pty_driver.magic = TTY_DRIVER_MAGIC;
 	pty_driver.driver_name = "pty_master";
@@ -405,6 +405,8 @@
 #ifdef CONFIG_UNIX98_PTYS
 	printk("pty: %d Unix98 ptys configured\n", UNIX98_NR_MAJORS*NR_PTYS);
 	for ( i = 0 ; i < UNIX98_NR_MAJORS ; i++ ) {
+		int j;
+
 		ptm_driver[i] = pty_driver;
 		ptm_driver[i].name = "ptm";
 		ptm_driver[i].proc_entry = 0;
@@ -417,6 +419,9 @@
 		ptm_driver[i].termios = ptm_termios[i];
 		ptm_driver[i].termios_locked = ptm_termios_locked[i];
 		ptm_driver[i].driver_state = ptm_state[i];
+
+		for (j = 0; j < NR_PTYS; j++)
+			init_waitqueue_head(&ptm_state[i][j].open_wait);
 		
 		pts_driver[i] = pty_slave_driver;
 		pts_driver[i].name = "pts";
diff -u --recursive --new-file v2.3.0/linux/drivers/char/qpmouse.c linux/drivers/char/qpmouse.c
--- v2.3.0/linux/drivers/char/qpmouse.c	Sat Oct 31 10:43:36 1998
+++ linux/drivers/char/qpmouse.c	Tue May 11 14:37:40 1999
@@ -55,7 +55,7 @@
 struct qp_queue {
 	unsigned long head;
 	unsigned long tail;
-	struct wait_queue *proc_list;
+	wait_queue_head_t proc_list;
 	struct fasync_struct *fasync;
 	unsigned char buf[QP_BUF_SIZE];
 };
@@ -258,7 +258,7 @@
 static ssize_t read_qp(struct file * file, char * buffer,
 			size_t count, loff_t *ppos)
 {
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 	ssize_t i = count;
 	unsigned char c;
 
@@ -354,7 +354,7 @@
 	queue = (struct qp_queue *) kmalloc(sizeof(*queue), GFP_KERNEL);
 	memset(queue, 0, sizeof(*queue));
 	queue->head = queue->tail = 0;
-	queue->proc_list = NULL;
+	init_waitqueue_head(&queue->proc_list);
 
 	return 0;
 }
diff -u --recursive --new-file v2.3.0/linux/drivers/char/radio-cadet.c linux/drivers/char/radio-cadet.c
--- v2.3.0/linux/drivers/char/radio-cadet.c	Mon May 10 13:00:10 1999
+++ linux/drivers/char/radio-cadet.c	Wed May 12 13:27:37 1999
@@ -34,7 +34,7 @@
 static int curtuner=0;
 static int tunestat=0;
 static int sigstrength=0;
-struct wait_queue *tunerq,*rdsq,*readq;
+static wait_queue_head_t tunerq,rdsq,readq;
 struct timer_list tunertimer,rdstimer,readtimer;
 static __u8 rdsin=0,rdsout=0,rdsstat=0;
 static unsigned char rdsbuf[RDS_BUFFER];
@@ -75,7 +75,7 @@
 	rdstimer.function=cadet_wake;
 	rdstimer.data=(unsigned long)1;
 	rdstimer.expires=jiffies+(HZ/10);
-	rdsq=NULL;
+	init_waitqueue_head(&rdsq);
 	add_timer(&rdstimer);
 	sleep_on(&rdsq);
 	
@@ -260,7 +260,7 @@
 		tunertimer.function=cadet_wake;
 		tunertimer.data=(unsigned long)0;
 		tunertimer.expires=jiffies+(HZ/10);
-		tunerq=NULL;
+		init_waitqueue_head(&tunerq);
 		add_timer(&tunertimer);
 		sleep_on(&tunerq);
 		cadet_gettune();
@@ -327,7 +327,7 @@
 	/*
 	 * Service pending read
 	 */
-	if((rdsin!=rdsout)&&(readq!=NULL)) {
+	if( rdsin!=rdsout) {
 	        wake_up_interruptible(&readq);
 	}
 
@@ -369,7 +369,6 @@
 		        return -EWOULDBLOCK;
 		}
 	        interruptible_sleep_on(&readq);
-       		readq=NULL;
 	}		
 	while((i<count)&&(rdsin!=rdsout)) {
 	        readbuf[i++]=rdsbuf[rdsout++];
@@ -517,7 +516,7 @@
 		return -EBUSY;
 	users++;
 	MOD_INC_USE_COUNT;
-	readq=NULL;
+	init_waitqueue_head(&readq);
 	return 0;
 }
 
diff -u --recursive --new-file v2.3.0/linux/drivers/char/random.c linux/drivers/char/random.c
--- v2.3.0/linux/drivers/char/random.c	Thu Dec 31 12:03:49 1998
+++ linux/drivers/char/random.c	Tue May 11 14:37:40 1999
@@ -424,8 +424,8 @@
 static struct timer_rand_state extract_timer_state;
 static struct timer_rand_state *irq_timer_state[NR_IRQS];
 static struct timer_rand_state *blkdev_timer_state[MAX_BLKDEV];
-static struct wait_queue *random_read_wait;
-static struct wait_queue *random_write_wait;
+static DECLARE_WAIT_QUEUE_HEAD(random_read_wait);
+static DECLARE_WAIT_QUEUE_HEAD(random_write_wait);
 
 static ssize_t random_read(struct file * file, char * buf,
 			   size_t nbytes, loff_t *ppos);
@@ -555,8 +555,6 @@
 	initialize_benchmark(&timer_benchmark, "timer", 0);
 #endif
 	extract_timer_state.dont_count_entropy = 1;
-	random_read_wait = NULL;
-	random_write_wait = NULL;
 }
 
 void rand_initialize_irq(int irq)
@@ -1303,7 +1301,7 @@
 static ssize_t
 random_read(struct file * file, char * buf, size_t nbytes, loff_t *ppos)
 {
-	struct wait_queue 	wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 	ssize_t			n, retval = 0, count = 0;
 	
 	if (nbytes == 0)
diff -u --recursive --new-file v2.3.0/linux/drivers/char/riscom8.c linux/drivers/char/riscom8.c
--- v2.3.0/linux/drivers/char/riscom8.c	Tue Dec 29 11:29:54 1998
+++ linux/drivers/char/riscom8.c	Wed May 12 13:27:37 1999
@@ -87,7 +87,7 @@
 static struct termios * riscom_termios[RC_NBOARD * RC_NPORT] = { NULL, };
 static struct termios * riscom_termios_locked[RC_NBOARD * RC_NPORT] = { NULL, };
 static unsigned char * tmp_buf = NULL;
-static struct semaphore tmp_buf_sem = MUTEX;
+static DECLARE_MUTEX(tmp_buf_sem);
 
 static unsigned long baud_table[] =  {
 	0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
@@ -946,7 +946,7 @@
 static int block_til_ready(struct tty_struct *tty, struct file * filp,
 			   struct riscom_port *port)
 {
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 	struct riscom_board *bp = port_Board(port);
 	int    retval;
 	int    do_clocal = 0;
@@ -1790,6 +1790,8 @@
 		rc_port[i].tqueue_hangup.data = &rc_port[i];
 		rc_port[i].close_delay = 50 * HZ/100;
 		rc_port[i].closing_wait = 3000 * HZ/100;
+		init_waitqueue_head(&rc_port[i].open_wait);
+		init_waitqueue_head(&rc_port[i].close_wait);
 	}
 	
 	return 0;
diff -u --recursive --new-file v2.3.0/linux/drivers/char/riscom8.h linux/drivers/char/riscom8.h
--- v2.3.0/linux/drivers/char/riscom8.h	Thu Mar  5 11:55:06 1998
+++ linux/drivers/char/riscom8.h	Wed May 12 13:27:37 1999
@@ -83,8 +83,8 @@
 	int			xmit_cnt;
 	struct termios          normal_termios;
 	struct termios		callout_termios;
-	struct wait_queue	*open_wait;
-	struct wait_queue	*close_wait;
+	wait_queue_head_t	open_wait;
+	wait_queue_head_t	close_wait;
 	struct tq_struct	tqueue;
 	struct tq_struct	tqueue_hangup;
 	short			wakeup_chars;
diff -u --recursive --new-file v2.3.0/linux/drivers/char/rocket.c linux/drivers/char/rocket.c
--- v2.3.0/linux/drivers/char/rocket.c	Wed Mar 10 16:51:35 1999
+++ linux/drivers/char/rocket.c	Wed May 12 13:27:37 1999
@@ -253,7 +253,7 @@
  * memory if large numbers of serial ports are open.
  */
 static unsigned char *tmp_buf = 0;
-static struct semaphore tmp_buf_sem = MUTEX;
+static DECLARE_MUTEX(tmp_buf_sem);
 
 static void rp_start(struct tty_struct *tty);
 
@@ -643,6 +643,8 @@
 	info->close_delay = 50;
 	info->callout_termios =callout_driver.init_termios;
 	info->normal_termios = rocket_driver.init_termios;
+	init_waitqueue_head(&info->open_wait);
+	init_waitqueue_head(&info->close_wait);
 
 	info->intmask = RXF_TRIG | TXFIFO_MT | SRC_INT | DELTA_CD |
 		DELTA_CTS | DELTA_DSR;
@@ -807,7 +809,7 @@
 static int block_til_ready(struct tty_struct *tty, struct file * filp,
 			   struct r_port *info)
 {
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 	int		retval;
 	int		do_clocal = 0, extra_count = 0;
 	unsigned long	flags;
diff -u --recursive --new-file v2.3.0/linux/drivers/char/rocket_int.h linux/drivers/char/rocket_int.h
--- v2.3.0/linux/drivers/char/rocket_int.h	Fri Jul 10 10:48:37 1998
+++ linux/drivers/char/rocket_int.h	Wed May 12 13:27:37 1999
@@ -1144,8 +1144,8 @@
 	struct termios		normal_termios;
 	struct termios		callout_termios;
 	struct tq_struct	tqueue;
-	struct wait_queue	*open_wait;
-	struct wait_queue	*close_wait;
+	wait_queue_head_t	open_wait;
+	wait_queue_head_t	close_wait;
 };
 	
 #define RPORT_MAGIC 0x525001
diff -u --recursive --new-file v2.3.0/linux/drivers/char/rtc.c linux/drivers/char/rtc.c
--- v2.3.0/linux/drivers/char/rtc.c	Thu Jan 14 22:58:47 1999
+++ linux/drivers/char/rtc.c	Tue May 11 14:37:40 1999
@@ -69,7 +69,7 @@
  *	ioctls.
  */
 
-static struct wait_queue *rtc_wait;
+static DECLARE_WAIT_QUEUE_HEAD(rtc_wait);
 
 static struct timer_list rtc_irq_timer;
 
@@ -150,7 +150,7 @@
 static ssize_t rtc_read(struct file *file, char *buf,
 			size_t count, loff_t *ppos)
 {
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 	unsigned long data;
 	ssize_t retval;
 	
@@ -567,7 +567,6 @@
 #endif
 	init_timer(&rtc_irq_timer);
 	rtc_irq_timer.function = rtc_dropped_irq;
-	rtc_wait = NULL;
 	save_flags(flags);
 	cli();
 	/* Initialize periodic freq. to CMOS reset default, which is 1024Hz */
diff -u --recursive --new-file v2.3.0/linux/drivers/char/selection.c linux/drivers/char/selection.c
--- v2.3.0/linux/drivers/char/selection.c	Thu Sep 17 09:35:03 1998
+++ linux/drivers/char/selection.c	Tue May 11 14:37:40 1999
@@ -296,7 +296,7 @@
 {
 	struct vt_struct *vt = (struct vt_struct *) tty->driver_data;
 	int	pasted = 0, count;
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 
 	poke_blanked_console();
 	add_wait_queue(&vt->paste_wait, &wait);
diff -u --recursive --new-file v2.3.0/linux/drivers/char/serial.c linux/drivers/char/serial.c
--- v2.3.0/linux/drivers/char/serial.c	Tue Mar 23 13:13:58 1999
+++ linux/drivers/char/serial.c	Thu May 13 14:52:15 1999
@@ -225,7 +225,7 @@
  * memory if large numbers of serial ports are open.
  */
 static unsigned char *tmp_buf;
-static struct semaphore tmp_buf_sem = MUTEX;
+static DECLARE_MUTEX(tmp_buf_sem);
 
 static inline int serial_paranoia_check(struct async_struct *info,
 					kdev_t device, const char *routine)
@@ -2422,7 +2422,7 @@
 static int block_til_ready(struct tty_struct *tty, struct file * filp,
 			   struct async_struct *info)
 {
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 	struct serial_state *state = info->state;
 	int		retval;
 	int		do_clocal = 0, extra_count = 0;
@@ -2571,6 +2571,9 @@
 		return -ENOMEM;
 	}
 	memset(info, 0, sizeof(struct async_struct));
+	init_waitqueue_head(&info->open_wait);
+	init_waitqueue_head(&info->close_wait);
+	init_waitqueue_head(&info->delta_msr_wait);
 	info->magic = SERIAL_MAGIC;
 	info->port = sstate->port;
 	info->flags = sstate->flags;
diff -u --recursive --new-file v2.3.0/linux/drivers/char/specialix.c linux/drivers/char/specialix.c
--- v2.3.0/linux/drivers/char/specialix.c	Sun May  2 09:51:09 1999
+++ linux/drivers/char/specialix.c	Wed May 12 13:27:37 1999
@@ -182,7 +182,7 @@
 static struct termios * specialix_termios[SX_NBOARD * SX_NPORT] = { NULL, };
 static struct termios * specialix_termios_locked[SX_NBOARD * SX_NPORT] = { NULL, };
 static unsigned char * tmp_buf = NULL;
-static struct semaphore tmp_buf_sem = MUTEX;
+static DECLARE_MUTEX(tmp_buf_sem);
 
 static unsigned long baud_table[] =  {
 	0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
@@ -1311,7 +1311,7 @@
 static int block_til_ready(struct tty_struct *tty, struct file * filp,
                            struct specialix_port *port)
 {
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait,  current);
 	struct specialix_board *bp = port_Board(port);
 	int    retval;
 	int    do_clocal = 0;
@@ -2248,6 +2248,8 @@
 		sx_port[i].tqueue_hangup.data = &sx_port[i];
 		sx_port[i].close_delay = 50 * HZ/100;
 		sx_port[i].closing_wait = 3000 * HZ/100;
+		init_waitqueue_head(&sx_port[i].open_wait);
+		init_waitqueue_head(&sx_port[i].close_wait);
 	}
 	
 	return 0;
diff -u --recursive --new-file v2.3.0/linux/drivers/char/specialix_io8.h linux/drivers/char/specialix_io8.h
--- v2.3.0/linux/drivers/char/specialix_io8.h	Wed Oct 28 22:04:05 1998
+++ linux/drivers/char/specialix_io8.h	Wed May 12 13:27:37 1999
@@ -122,8 +122,8 @@
 	int			xmit_cnt;
 	struct termios          normal_termios;
 	struct termios		callout_termios;
-	struct wait_queue	*open_wait;
-	struct wait_queue	*close_wait;
+	wait_queue_head_t	open_wait;
+	wait_queue_head_t	close_wait;
 	struct tq_struct	tqueue;
 	struct tq_struct	tqueue_hangup;
 	short			wakeup_chars;
diff -u --recursive --new-file v2.3.0/linux/drivers/char/synclink.c linux/drivers/char/synclink.c
--- v2.3.0/linux/drivers/char/synclink.c	Sun Mar 28 10:31:31 1999
+++ linux/drivers/char/synclink.c	Wed May 12 13:27:37 1999
@@ -241,11 +241,11 @@
 	int			xmit_tail;
 	int			xmit_cnt;
 	
-	struct wait_queue	*open_wait;
-	struct wait_queue	*close_wait;
+	wait_queue_head_t	open_wait;
+	wait_queue_head_t	close_wait;
 	
-	struct wait_queue	*status_event_wait_q;
-	struct wait_queue	*event_wait_q;
+	wait_queue_head_t	status_event_wait_q;
+	wait_queue_head_t	event_wait_q;
 	struct timer_list	tx_timer;	/* HDLC transmit timeout timer */
 	struct mgsl_struct	*next_device;	/* device list link */
 	
@@ -904,7 +904,7 @@
  * memory if large numbers of serial ports are open.
  */
 static unsigned char *tmp_buf;
-static struct semaphore tmp_buf_sem = MUTEX;
+static DECLARE_MUTEX(tmp_buf_sem);
 
 static inline int mgsl_paranoia_check(struct mgsl_struct *info,
 					kdev_t device, const char *routine)
@@ -2724,7 +2724,7 @@
 	
 	if (mask & (MgslEvent_ExitHuntMode + MgslEvent_IdleReceived)) {
 		spin_lock_irqsave(&info->irq_spinlock,flags);
-		if (!info->event_wait_q) {
+		if (!waitqueue_active(&info->event_wait_q)) {
 			/* disable enable exit hunt mode/idle rcvd IRQs */
 			regval = usc_InReg(info,RICR);
 			usc_OutReg(info, RICR, regval & 
@@ -3295,7 +3295,7 @@
 static int block_til_ready(struct tty_struct *tty, struct file * filp,
 			   struct mgsl_struct *info)
 {
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 	int		retval;
 	int		do_clocal = 0, extra_count = 0;
 	unsigned long	flags;
@@ -4152,6 +4152,10 @@
 		info->max_frame_size = 4096;
 		info->close_delay = 5*HZ/10;
 		info->closing_wait = 30*HZ;
+		init_waitqueue_head(&info->open_wait);
+		init_waitqueue_head(&info->close_wait);
+		init_waitqueue_head(&info->status_event_wait_q);
+		init_waitqueue_head(&info->event_wait_q);
 
 		memcpy(&info->params,&default_params,sizeof(MGSL_PARAMS));
 		info->idle_mode = HDLC_TXIDLE_FLAGS;		
diff -u --recursive --new-file v2.3.0/linux/drivers/char/tpqic02.c linux/drivers/char/tpqic02.c
--- v2.3.0/linux/drivers/char/tpqic02.c	Wed Mar 10 16:51:35 1999
+++ linux/drivers/char/tpqic02.c	Wed May 12 13:27:37 1999
@@ -127,7 +127,7 @@
 
 static volatile int ctlbits = 0;     /* control reg bits for tape interface */
 
-static struct wait_queue *qic02_tape_transfer = NULL; /* sync rw with interrupts */
+static wait_queue_t qic02_tape_transfer; /* sync rw with interrupts */
 
 static volatile struct mtget ioctl_status;	/* current generic status */
 
@@ -2936,6 +2936,7 @@
 	return -ENODEV;
     }
 
+    init_waitqueue_head(&qic02_tape_transfer);
     /* prepare timer */
     TIMEROFF;
     timer_table[QIC02_TAPE_TIMER].expires = 0;
diff -u --recursive --new-file v2.3.0/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c
--- v2.3.0/linux/drivers/char/tty_io.c	Mon Mar 22 10:06:21 1999
+++ linux/drivers/char/tty_io.c	Tue May 11 14:37:40 1999
@@ -729,7 +729,7 @@
 }
 
 /* Semaphore to protect creating and releasing a tty */
-static struct semaphore tty_sem = MUTEX;
+static DECLARE_MUTEX(tty_sem);
 
 static void down_tty_sem(int index)
 {
@@ -1930,7 +1930,9 @@
 	tty->flip.flag_buf_ptr = tty->flip.flag_buf;
 	tty->flip.tqueue.routine = flush_to_ldisc;
 	tty->flip.tqueue.data = tty;
-	tty->flip.pty_sem = MUTEX;
+	init_MUTEX(&tty->flip.pty_sem);
+	init_waitqueue_head(&tty->write_wait);
+	init_waitqueue_head(&tty->read_wait);
 	tty->tq_hangup.routine = do_tty_hangup;
 	tty->tq_hangup.data = tty;
 	sema_init(&tty->atomic_read, 1);
diff -u --recursive --new-file v2.3.0/linux/drivers/char/tty_ioctl.c linux/drivers/char/tty_ioctl.c
--- v2.3.0/linux/drivers/char/tty_ioctl.c	Tue Jan 19 10:12:05 1999
+++ linux/drivers/char/tty_ioctl.c	Tue May 11 14:37:40 1999
@@ -42,7 +42,7 @@
 
 void tty_wait_until_sent(struct tty_struct * tty, long timeout)
 {
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 
 #ifdef TTY_DEBUG_WAIT_UNTIL_SENT
 	char buf[64];
diff -u --recursive --new-file v2.3.0/linux/drivers/char/vt.c linux/drivers/char/vt.c
--- v2.3.0/linux/drivers/char/vt.c	Wed Feb  3 22:57:41 1999
+++ linux/drivers/char/vt.c	Tue May 11 14:37:40 1999
@@ -1099,7 +1099,7 @@
  * while those not ready go back to sleep. Seems overkill to add a wait
  * to each vt just for this - usually this does nothing!
  */
-static struct wait_queue *vt_activate_queue = NULL;
+static DECLARE_WAIT_QUEUE_HEAD(vt_activate_queue);
 
 /*
  * Sleeps until a vt is activated, or the task is interrupted. Returns
@@ -1108,7 +1108,7 @@
 int vt_waitactive(int vt)
 {
 	int retval;
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 
 	add_wait_queue(&vt_activate_queue, &wait);
 	for (;;) {
diff -u --recursive --new-file v2.3.0/linux/drivers/fc4/fc.c linux/drivers/fc4/fc.c
--- v2.3.0/linux/drivers/fc4/fc.c	Mon Mar 15 16:11:29 1999
+++ linux/drivers/fc4/fc.c	Wed May 12 08:41:15 1999
@@ -551,7 +551,7 @@
 	l->magic = LSMAGIC;
 	l->count = count;
 	FCND(("FCP Init for %d channels\n", count))
-	l->sem = MUTEX_LOCKED;
+	init_MUTEX_LOCKED(&l->sem);
 	l->timer.function = fcp_login_timeout;
 	l->timer.data = (unsigned long)l;
 	atomic_set (&l->todo, count);
@@ -672,7 +672,7 @@
 	l.count = count;
 	l.magic = LSOMAGIC;
 	FCND(("FCP Force Offline for %d channels\n", count))
-	l.sem = MUTEX_LOCKED;
+	init_MUTEX_LOCKED(&l.sem);
 	l.timer.function = fcp_login_timeout;
 	l.timer.data = (unsigned long)&l;
 	atomic_set (&l.todo, count);
@@ -933,7 +933,7 @@
 	fcp_cmd *cmd;
 	fcp_cmnd *fcmd;
 	fc_channel *fc = FC_SCMND(SCpnt);
-        struct semaphore sem = MUTEX_LOCKED;
+        DECLARE_MUTEX_LOCKED(sem);
 
 	if (!fc->rst_pkt) {
 		fc->rst_pkt = (Scsi_Cmnd *) kmalloc(sizeof(SCpnt), GFP_KERNEL);
@@ -1070,7 +1070,7 @@
 	
 	memset (&l, 0, sizeof(lse));
 	l.magic = LSEMAGIC;
-	l.sem = MUTEX_LOCKED;
+	init_MUTEX_LOCKED(&l.sem);
 	l.timer.function = fcp_login_timeout;
 	l.timer.data = (unsigned long)&l;
 	l.status = FC_STATUS_TIMED_OUT;
diff -u --recursive --new-file v2.3.0/linux/drivers/isdn/isdn_common.c linux/drivers/isdn/isdn_common.c
--- v2.3.0/linux/drivers/isdn/isdn_common.c	Tue Jan 19 11:06:52 1999
+++ linux/drivers/isdn/isdn_common.c	Thu May 13 10:53:38 1999
@@ -741,7 +741,6 @@
 				isdn_free_queue(&dev->drv[di]->rpqueue[i]);
 			kfree(dev->drv[di]->rpqueue);
 			kfree(dev->drv[di]->rcv_waitq);
-			kfree(dev->drv[di]->snd_waitq);
 			kfree(dev->drv[di]);
 			dev->drv[di] = NULL;
 			dev->drvid[di][0] = '\0';
@@ -785,7 +784,7 @@
  * of the mapping (di,ch)<->minor, happen during the sleep? --he 
  */
 int
-isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, struct wait_queue **sleep)
+isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, wait_queue_head_t *sleep)
 {
 	int left;
 	int count;
@@ -2088,6 +2087,7 @@
 		return 0;
 	}
 	memset((char *) d, 0, sizeof(driver));
+	init_waitqueue_head(&d->st_waitq); 
 	if (!(d->rcverr = (int *) kmalloc(sizeof(int) * n, GFP_KERNEL))) {
 		printk(KERN_WARNING "register_isdn: Could not alloc rcverr\n");
 		kfree(d);
@@ -2112,8 +2112,9 @@
 	for (j = 0; j < n; j++) {
 		skb_queue_head_init(&d->rpqueue[j]);
 	}
-	if (!(d->rcv_waitq = (struct wait_queue **)
-	      kmalloc(sizeof(struct wait_queue *) * n, GFP_KERNEL))) {
+	d->rcv_waitq = (wait_queue_head_t *)
+		kmalloc(sizeof(wait_queue_head_t) * 2 * n, GFP_KERNEL);
+	if (!d->rcv_waitq) { 
 		printk(KERN_WARNING "register_isdn: Could not alloc rcv_waitq\n");
 		kfree(d->rpqueue);
 		kfree(d->rcvcount);
@@ -2121,18 +2122,11 @@
 		kfree(d);
 		return 0;
 	}
-	memset((char *) d->rcv_waitq, 0, sizeof(struct wait_queue *) * n);
-	if (!(d->snd_waitq = (struct wait_queue **)
-	      kmalloc(sizeof(struct wait_queue *) * n, GFP_KERNEL))) {
-		printk(KERN_WARNING "register_isdn: Could not alloc snd_waitq\n");
-		kfree(d->rcv_waitq);
-		kfree(d->rpqueue);
-		kfree(d->rcvcount);
-		kfree(d->rcverr);
-		kfree(d);
-		return 0;
+	d->snd_waitq = d->rcv_waitq + n; 		
+	for (j = 0; j < n; j++) { 
+		init_waitqueue_head(&d->rcv_waitq[n]); 
+		init_waitqueue_head(&d->snd_waitq[n]); 
 	}
-	memset((char *) d->snd_waitq, 0, sizeof(struct wait_queue *) * n);
 	d->channels = n;
 	d->loaded = 1;
 	d->maxbufsize = i->maxbufsize;
@@ -2215,12 +2209,15 @@
 	memset((char *) dev, 0, sizeof(isdn_dev));
 	init_timer(&dev->timer);
 	dev->timer.function = isdn_timer_funct;
-	dev->sem = MUTEX;
+	init_MUTEX(&dev->sem);
+	init_waitqueue_head(&dev->info_waitq); 
 	for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
 		dev->drvmap[i] = -1;
 		dev->chanmap[i] = -1;
 		dev->m_idx[i] = -1;
 		strcpy(dev->num[i], "???");
+		init_waitqueue_head(&dev->mdm.info[i].open_wait);
+		init_waitqueue_head(&dev->mdm.info[i].close_wait);
 	}
 	if (register_chrdev(ISDN_MAJOR, "isdn", &isdn_fops)) {
 		printk(KERN_WARNING "isdn: Could not register control devices\n");
diff -u --recursive --new-file v2.3.0/linux/drivers/isdn/isdn_common.h linux/drivers/isdn/isdn_common.h
--- v2.3.0/linux/drivers/isdn/isdn_common.h	Tue Jan 19 11:06:52 1999
+++ linux/drivers/isdn/isdn_common.h	Thu May 13 10:53:42 1999
@@ -90,7 +90,7 @@
 extern void isdn_timer_ctrl(int tf, int onoff);
 extern void isdn_unexclusive_channel(int di, int ch);
 extern int isdn_getnum(char **);
-extern int isdn_readbchan(int, int, u_char *, u_char *, int, struct wait_queue**);
+extern int isdn_readbchan(int, int, u_char *, u_char *, int, wait_queue_head_t *);
 extern int isdn_get_free_channel(int, int, int, int, int);
 extern int isdn_writebuf_skb_stub(int, int, int, struct sk_buff *);
 extern int register_isdn(isdn_if * i);
diff -u --recursive --new-file v2.3.0/linux/drivers/isdn/isdn_ppp.c linux/drivers/isdn/isdn_ppp.c
--- v2.3.0/linux/drivers/isdn/isdn_ppp.c	Tue Jan 19 11:06:52 1999
+++ linux/drivers/isdn/isdn_ppp.c	Thu May 13 10:53:46 1999
@@ -359,8 +359,7 @@
 
 	ippp_table[lp->ppp_slot]->state = IPPP_OPEN | IPPP_CONNECT | IPPP_NOBLOCK;
 
-	if (ippp_table[lp->ppp_slot]->wq)
-		wake_up_interruptible(&ippp_table[lp->ppp_slot]->wq);
+	wake_up_interruptible(&ippp_table[lp->ppp_slot]->wq);
 }
 
 /*
@@ -377,7 +376,7 @@
 		return 0;
 	is = ippp_table[slot];
 
-	if (is->state && is->wq)
+	if (is->state)
 		wake_up_interruptible(&is->wq);
 
 	is->state = IPPP_CLOSEWAIT;
@@ -437,8 +436,9 @@
 	is->mru = 1524;         /* MRU, default 1524 */
 	is->maxcid = 16;        /* VJ: maxcid */
 	is->tk = current;
-	is->wq = NULL;          /* read() wait queue */
-	is->wq1 = NULL;         /* select() wait queue */
+	/* next two are redundant, but be paranoid */ 
+	init_waitqueue_head(&is->wq);  /* read() wait queue */
+	init_waitqueue_head(&is->wql);  /* select() wait queue */
 	is->first = is->rq + NUM_RCV_BUFFS - 1;	/* receive queue */
 	is->last = is->rq;
 	is->minor = min;
@@ -777,8 +777,7 @@
 	is->last = bl->next;
 	restore_flags(flags);
 
-	if (is->wq)
-		wake_up_interruptible(&is->wq);
+	wake_up_interruptible(&is->wq);
 
 	return len;
 }
@@ -911,6 +910,8 @@
 			return -1;
 		}
 		memset((char *) ippp_table[i], 0, sizeof(struct ippp_struct));
+		init_waitqueue_head(&ippp_table[i]->wq); 
+		init_waitqueue_head(&ippp_table[i]->wql); 
 		ippp_table[i]->state = 0;
 		ippp_table[i]->first = ippp_table[i]->rq + NUM_RCV_BUFFS - 1;
 		ippp_table[i]->last = ippp_table[i]->rq;
diff -u --recursive --new-file v2.3.0/linux/drivers/isdn/isdn_tty.c linux/drivers/isdn/isdn_tty.c
--- v2.3.0/linux/drivers/isdn/isdn_tty.c	Sat Oct 31 10:37:14 1998
+++ linux/drivers/isdn/isdn_tty.c	Thu May 13 10:53:50 1999
@@ -1567,8 +1567,7 @@
 static int
 isdn_tty_block_til_ready(struct tty_struct *tty, struct file *filp, modem_info * info)
 {
-	struct wait_queue wait =
-	{current, NULL};
+	DECLARE_WAITQUEUE(wait, current); 
 	int do_clocal = 0;
 	unsigned long flags;
 	int retval;
@@ -2004,8 +2003,8 @@
 		info->blocked_open = 0;
 		info->callout_termios = m->cua_modem.init_termios;
 		info->normal_termios = m->tty_modem.init_termios;
-		info->open_wait = 0;
-		info->close_wait = 0;
+		init_waitqueue_head(&info->open_wait);
+		init_waitqueue_head(&info->close_wait);
 		info->isdn_driver = -1;
 		info->isdn_channel = -1;
 		info->drv_index = -1;
diff -u --recursive --new-file v2.3.0/linux/drivers/misc/parport_share.c linux/drivers/misc/parport_share.c
--- v2.3.0/linux/drivers/misc/parport_share.c	Tue Oct 27 10:32:29 1998
+++ linux/drivers/misc/parport_share.c	Tue May 11 23:38:24 1999
@@ -277,7 +277,7 @@
 	inc_parport_count();
 	port->ops->inc_use_count();
 
-	init_waitqueue(&tmp->wait_q);
+	init_waitqueue_head(&tmp->wait_q);
 	tmp->timeslice = PARPORT_DEFAULT_TIMESLICE;
 	tmp->waitnext = tmp->waitprev = NULL;
 
diff -u --recursive --new-file v2.3.0/linux/drivers/net/3c527.c linux/drivers/net/3c527.c
--- v2.3.0/linux/drivers/net/3c527.c	Sun Mar 21 07:11:36 1999
+++ linux/drivers/net/3c527.c	Wed May 12 13:27:37 1999
@@ -102,7 +102,7 @@
 	u16 exec_pending;
 	u16 mc_reload_wait;	/* a multicast load request is pending */
 	atomic_t tx_count;		/* buffers left */
-	struct wait_queue *event;
+	wait_queue_head_t event;
 	struct sk_buff *tx_skb[TX_RING_MAX];	/* Transmit ring */
 	u16 tx_skb_top;
 	u16 tx_skb_end;
@@ -411,6 +411,7 @@
 	lp->rx_chain 		= lp->exec_box->data[10];
 	lp->tx_len 		= lp->exec_box->data[9];
 	lp->rx_len 		= lp->exec_box->data[11];
+	init_waitqueue_head(&lp->event);
 	
 	printk("%s: %d RX buffers, %d TX buffers. Base of 0x%08X.\n",
 		dev->name, lp->rx_len, lp->tx_len, lp->base);
diff -u --recursive --new-file v2.3.0/linux/drivers/net/ibmtr.c linux/drivers/net/ibmtr.c
--- v2.3.0/linux/drivers/net/ibmtr.c	Fri May  7 10:57:42 1999
+++ linux/drivers/net/ibmtr.c	Wed May 12 13:27:37 1999
@@ -404,6 +404,8 @@
 #endif
 	ti->mmio= t_mmio;
 	ti->readlog_pending = 0;
+	init_waitqueue_head(&ti->wait_for_tok_int);
+	init_waitqueue_head(&ti->wait_for_reset);
 
 	dev->priv = ti;     /* this seems like the logical use of the
                          field ... let's try some empirical tests
diff -u --recursive --new-file v2.3.0/linux/drivers/net/ibmtr.h linux/drivers/net/ibmtr.h
--- v2.3.0/linux/drivers/net/ibmtr.h	Tue Mar 16 14:21:52 1999
+++ linux/drivers/net/ibmtr.h	Wed May 12 13:27:37 1999
@@ -193,8 +193,8 @@
 	unsigned short maxmtu16;
 	/* Additions by David Morris       */
 	unsigned char do_tok_int;
-	struct wait_queue *wait_for_tok_int;
-	struct wait_queue *wait_for_reset;
+	wait_queue_head_t wait_for_tok_int;
+	wait_queue_head_t wait_for_reset;
 	unsigned char sram_base;
 	/* Additions by Peter De Schrijver */
 	unsigned char page_mask;          /* mask to select RAM page to Map*/
diff -u --recursive --new-file v2.3.0/linux/drivers/net/ppp.c linux/drivers/net/ppp.c
--- v2.3.0/linux/drivers/net/ppp.c	Tue May 11 09:55:45 1999
+++ linux/drivers/net/ppp.c	Wed May 12 08:41:15 1999
@@ -2834,7 +2834,7 @@
 	ppp->magic = PPP_MAGIC;
 	ppp->next = NULL;
 	ppp->inuse = 1;
-	ppp->read_wait = NULL;
+	init_waitqueue_head(&ppp->read_wait);
 
 	/*
 	 * Make up a suitable name for this device
diff -u --recursive --new-file v2.3.0/linux/drivers/net/shaper.c linux/drivers/net/shaper.c
--- v2.3.0/linux/drivers/net/shaper.c	Wed Mar 10 16:51:35 1999
+++ linux/drivers/net/shaper.c	Wed May 12 13:27:37 1999
@@ -582,6 +582,7 @@
 	init_timer(&sh->timer);
 	sh->timer.function=shaper_timer;
 	sh->timer.data=(unsigned long)sh;
+	init_waitqueue_head(&sh->wait_queue);
 	return sh;
 }
 
diff -u --recursive --new-file v2.3.0/linux/drivers/net/sktr.c linux/drivers/net/sktr.c
--- v2.3.0/linux/drivers/net/sktr.c	Thu Jan  7 08:46:59 1999
+++ linux/drivers/net/sktr.c	Wed May 12 13:27:37 1999
@@ -414,7 +414,8 @@
 	if(tp == NULL)
 		return (-ENOMEM);
 	memset(tp, 0, sizeof(struct net_local));
-
+	init_waitqueue_head(&tp->wait_for_tok_int);
+	
 	dev->priv		= tp;
 	dev->init               = sktr_init_card;
         dev->open               = sktr_open;
diff -u --recursive --new-file v2.3.0/linux/drivers/net/sktr.h linux/drivers/net/sktr.h
--- v2.3.0/linux/drivers/net/sktr.h	Wed Jun 24 14:26:13 1998
+++ linux/drivers/net/sktr.h	Wed May 12 13:27:37 1999
@@ -1087,7 +1087,7 @@
 
 	struct timer_list timer;
 
-	struct wait_queue *wait_for_tok_int;
+	wait_queue_head_t  wait_for_tok_int;
 
 	INTPTRS intptrs;	/* Internal adapter pointer. Must be read
 				 * before OPEN command.
diff -u --recursive --new-file v2.3.0/linux/drivers/pci/oldproc.c linux/drivers/pci/oldproc.c
--- v2.3.0/linux/drivers/pci/oldproc.c	Wed Apr 21 09:28:49 1999
+++ linux/drivers/pci/oldproc.c	Thu May 13 11:00:08 1999
@@ -203,6 +203,7 @@
 	DEVICE( MOTOROLA,	MOTOROLA_MPC106,"MPC106 Grackle"),
 	DEVICE( MOTOROLA,	MOTOROLA_RAVEN,	"Raven"),
 	DEVICE( PROMISE,        PROMISE_20246,	"IDE UltraDMA/33"),
+	DEVICE(	PROMISE,	PROMISE_20262,	"IDE UltraDMA/66"),
 	DEVICE( PROMISE,	PROMISE_5300,	"DC5030"),
 	DEVICE( N9,		N9_I128,	"Imagine 128"),
 	DEVICE( N9,		N9_I128_2,	"Imagine 128v2"),
@@ -290,11 +291,15 @@
 	DEVICE( AL,		AL_M1523,	"M1523"),
 	DEVICE( AL,		AL_M1531,	"M1531 Aladdin IV"),
 	DEVICE( AL,		AL_M1533,	"M1533 Aladdin IV"),
+	DEVICE(	AL,		AL_M1541,	"M1541 Aladdin V"),
+	DEVICE(	AL,		AL_M1543,	"M1543 Aladdin V"),
 	DEVICE( AL,		AL_M3307,	"M3307 MPEG-1 decoder"),
 	DEVICE( AL,		AL_M4803,	"M4803"),
 	DEVICE( AL,		AL_M5219,	"M5219"),
 	DEVICE( AL,		AL_M5229,	"M5229 TXpro"),
 	DEVICE( AL,		AL_M5237,	"M5237 USB"),
+	DEVICE(	AL,		AL_M5243,	"M5243 AGP"),
+	DEVICE(	AL,		AL_M7101,	"M7101 PMU"),
 	DEVICE( SURECOM,	SURECOM_NE34,	"NE-34PCI LAN"),
 	DEVICE( NEOMAGIC,       NEOMAGIC_MAGICGRAPH_NM2070,     "Magicgraph NM2070"),
 	DEVICE( NEOMAGIC,	NEOMAGIC_MAGICGRAPH_128V, "MagicGraph 128V"),
diff -u --recursive --new-file v2.3.0/linux/drivers/sbus/audio/audio.c linux/drivers/sbus/audio/audio.c
--- v2.3.0/linux/drivers/sbus/audio/audio.c	Thu Apr 22 19:24:51 1999
+++ linux/drivers/sbus/audio/audio.c	Wed May 12 08:41:15 1999
@@ -117,6 +117,11 @@
          * TODO: Make number of input/output buffers tunable parameters
          */
 
+        init_waitqueue_head(&drv->open_wait);
+        init_waitqueue_head(&drv->output_write_wait);
+        init_waitqueue_head(&drv->output_drain_wait);
+        init_waitqueue_head(&drv->input_read_wait);
+
         drv->num_output_buffers = 8;
 	drv->output_buffer_size = (4096 * 2);
 	drv->playing_count = 0;
diff -u --recursive --new-file v2.3.0/linux/drivers/sbus/audio/dbri.h linux/drivers/sbus/audio/dbri.h
--- v2.3.0/linux/drivers/sbus/audio/dbri.h	Mon Mar 15 16:11:30 1999
+++ linux/drivers/sbus/audio/dbri.h	Wed May 12 08:41:15 1999
@@ -85,7 +85,7 @@
   struct cs4215 mm;				/* mmcodec special info */
 
 #if 0
-  struct wait_queue *wait, *int_wait;		/* Where to sleep if busy */
+  wait_queue_head_t wait, int_wait;		/* Where to sleep if busy */
 #endif
   struct audio_info perchip_info;
 
diff -u --recursive --new-file v2.3.0/linux/drivers/sbus/char/bpp.c linux/drivers/sbus/char/bpp.c
--- v2.3.0/linux/drivers/sbus/char/bpp.c	Mon Mar 15 16:11:30 1999
+++ linux/drivers/sbus/char/bpp.c	Wed May 12 08:41:15 1999
@@ -81,7 +81,7 @@
       unsigned char repeat_byte;
 
       /* These members manage timeouts for programmed delays */
-      struct wait_queue *wait_queue;
+      wait_queue_head_t wait_queue;
       struct timer_list timer_list;
 };
 
diff -u --recursive --new-file v2.3.0/linux/drivers/sbus/char/pcikbd.c linux/drivers/sbus/char/pcikbd.c
--- v2.3.0/linux/drivers/sbus/char/pcikbd.c	Tue May 11 08:24:32 1999
+++ linux/drivers/sbus/char/pcikbd.c	Wed May 12 08:41:15 1999
@@ -1,4 +1,4 @@
-/* $Id: pcikbd.c,v 1.27 1999/05/09 06:40:47 ecd Exp $
+/* $Id: pcikbd.c,v 1.28 1999/05/12 11:15:05 davem Exp $
  * pcikbd.c: Ultra/AX PC keyboard support.
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -588,7 +588,7 @@
 struct aux_queue {
 	unsigned long head;
 	unsigned long tail;
-	struct wait_queue *proc_list;
+	wait_queue_head_t proc_list;
 	struct fasync_struct *fasync;
 	unsigned char buf[AUX_BUF_SIZE];
 };
@@ -739,7 +739,7 @@
  * doing so might cause the keyboard driver to ignore all incoming keystrokes.
  */
 
-static struct semaphore aux_sema4 = MUTEX;
+static DECLARE_MUTEX(aux_sema4);
 
 static inline void aux_start_atomic(void)
 {
@@ -879,7 +879,7 @@
 static ssize_t aux_read(struct file * file, char * buffer,
 		        size_t count, loff_t *ppos)
 {
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 	ssize_t i = count;
 	unsigned char c;
 
diff -u --recursive --new-file v2.3.0/linux/drivers/sbus/char/sab82532.c linux/drivers/sbus/char/sab82532.c
--- v2.3.0/linux/drivers/sbus/char/sab82532.c	Thu Mar 25 09:23:34 1999
+++ linux/drivers/sbus/char/sab82532.c	Wed May 12 08:41:15 1999
@@ -1,4 +1,4 @@
-/* $Id: sab82532.c,v 1.30 1999/03/24 11:34:52 davem Exp $
+/* $Id: sab82532.c,v 1.31 1999/05/12 11:15:10 davem Exp $
  * sab82532.c: ASYNC Driver for the SIEMENS SAB82532 DUSCC.
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -100,7 +100,7 @@
  * memory if large numbers of serial ports are open.
  */
 static unsigned char *tmp_buf = 0;
-static struct semaphore tmp_buf_sem = MUTEX;
+static DECLARE_MUTEX(tmp_buf_sem);
 
 static inline int serial_paranoia_check(struct sab82532 *info,
 					kdev_t device, const char *routine)
@@ -1715,7 +1715,7 @@
 static int block_til_ready(struct tty_struct *tty, struct file * filp,
 			   struct sab82532 *info)
 {
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 	int retval;
 	int do_clocal = 0;
 
@@ -2136,7 +2136,7 @@
 
 __initfunc(static inline void show_serial_version(void))
 {
-	char *revision = "$Revision: 1.30 $";
+	char *revision = "$Revision: 1.31 $";
 	char *version, *p;
 
 	version = strchr(revision, ' ');
@@ -2247,9 +2247,9 @@
 		info->tqueue_hangup.data = info;
 		info->callout_termios = callout_driver.init_termios;
 		info->normal_termios = serial_driver.init_termios;
-		info->open_wait = 0;
-		info->close_wait = 0;
-		info->delta_msr_wait = 0;
+		init_waitqueue_head(&info->open_wait);
+		init_waitqueue_head(&info->close_wait);
+		init_waitqueue_head(&info->delta_msr_wait);
 		info->icount.cts = info->icount.dsr = 
 			info->icount.rng = info->icount.dcd = 0;
 		info->icount.rx = info->icount.tx = 0;
diff -u --recursive --new-file v2.3.0/linux/drivers/sbus/char/su.c linux/drivers/sbus/char/su.c
--- v2.3.0/linux/drivers/sbus/char/su.c	Mon Mar 15 16:11:30 1999
+++ linux/drivers/sbus/char/su.c	Wed May 12 08:41:15 1999
@@ -1,4 +1,4 @@
-/* $Id: su.c,v 1.18 1999/01/02 16:47:37 davem Exp $
+/* $Id: su.c,v 1.19 1999/05/12 11:15:14 davem Exp $
  * su.c: Small serial driver for keyboard/mouse interface on sparc32/PCI
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -135,9 +135,9 @@
 	int			xmit_tail;
 	int			xmit_cnt;
 	struct tq_struct	tqueue;
-	struct wait_queue	*open_wait;
-	struct wait_queue	*close_wait;
-	struct wait_queue	*delta_msr_wait;
+	wait_queue_head_t	open_wait;
+	wait_queue_head_t	close_wait;
+	wait_queue_head_t	delta_msr_wait;
 
 	int			count;
 	struct async_icount	icount;
@@ -200,7 +200,7 @@
  * memory if large numbers of serial ports are open.
  */
 static unsigned char *tmp_buf;
-static struct semaphore tmp_buf_sem = MUTEX;
+static DECLARE_MUTEX(tmp_buf_sem);
 
 static inline int serial_paranoia_check(struct su_struct *info,
 					kdev_t device, const char *routine)
@@ -1878,7 +1878,7 @@
 block_til_ready(struct tty_struct *tty, struct file * filp,
 		struct su_struct *info)
 {
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 	int		  retval;
 	int		  do_clocal = 0, extra_count = 0;
 	unsigned long	  flags;
@@ -2215,7 +2215,7 @@
  */
 __initfunc(static __inline__ void show_su_version(void))
 {
-	char *revision = "$Revision: 1.18 $";
+	char *revision = "$Revision: 1.19 $";
 	char *version, *p;
 
 	version = strchr(revision, ' ');
diff -u --recursive --new-file v2.3.0/linux/drivers/sbus/char/sunkbd.c linux/drivers/sbus/char/sunkbd.c
--- v2.3.0/linux/drivers/sbus/char/sunkbd.c	Thu Apr 22 19:24:51 1999
+++ linux/drivers/sbus/char/sunkbd.c	Wed May 12 08:41:15 1999
@@ -85,7 +85,7 @@
 }
 
 #ifndef CONFIG_PCI
-struct wait_queue * keypress_wait = NULL;
+DECLARE_WAIT_QUEUE_HEAD(keypress_wait);
 #endif
 
 int keyboard_wait_for_keypress(struct console *co)
@@ -1261,7 +1261,7 @@
 static int kbd_head, kbd_tail;
 char kbd_opened;
 static int kbd_active = 0;
-static struct wait_queue *kbd_wait;
+static DECLARE_WAIT_QUEUE_HEAD(kbd_wait);
 static struct fasync_struct *kb_fasync;
 
 void
@@ -1285,7 +1285,7 @@
 static ssize_t
 kbd_read (struct file *f, char *buffer, size_t count, loff_t *ppos)
 {
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 	char *end, *p;
 
 	/* Return EWOULDBLOCK, because this is what the X server expects */
diff -u --recursive --new-file v2.3.0/linux/drivers/sbus/char/sunmouse.c linux/drivers/sbus/char/sunmouse.c
--- v2.3.0/linux/drivers/sbus/char/sunmouse.c	Thu Apr 22 19:24:51 1999
+++ linux/drivers/sbus/char/sunmouse.c	Wed May 12 08:41:15 1999
@@ -73,7 +73,7 @@
 	int ready;		       /* set if there if data is available */
 	int active;		       /* set if device is open */
         int vuid_mode;	               /* VUID_NATIVE or VUID_FIRM_EVENT */
-	struct wait_queue *proc_list;
+	wait_queue_head_t proc_list;
 	struct fasync_struct *fasync;
 	
 	/* The event/stream queue */
@@ -368,7 +368,7 @@
 sun_mouse_read(struct file *file, char *buffer,
 	       size_t count, loff_t *ppos)
 {
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 
 	if (queue_empty ()){
 		if (file->f_flags & O_NONBLOCK)
@@ -503,7 +503,7 @@
 	misc_register (&sun_mouse_mouse);
 	sunmouse.delta_x = sunmouse.delta_y = 0;
 	sunmouse.button_state = 0x80;
-	sunmouse.proc_list = NULL;
+	init_waitqueue_head(&sunmouse.proc_list);
 	sunmouse.byte = 69;
 	return 0;
 }
diff -u --recursive --new-file v2.3.0/linux/drivers/sbus/char/vfc.h linux/drivers/sbus/char/vfc.h
--- v2.3.0/linux/drivers/sbus/char/vfc.h	Tue May 13 22:41:12 1997
+++ linux/drivers/sbus/char/vfc.h	Wed May 12 08:41:15 1999
@@ -128,7 +128,7 @@
 	unsigned int control_reg;
 	struct semaphore device_lock_sem;
 	struct timer_list poll_timer;
-	struct wait_queue *poll_wait;
+	wait_queue_head_t poll_wait;
 	int instance;
 	int busy;
 	unsigned long which_io;
diff -u --recursive --new-file v2.3.0/linux/drivers/sbus/char/zs.c linux/drivers/sbus/char/zs.c
--- v2.3.0/linux/drivers/sbus/char/zs.c	Thu Apr 22 19:24:51 1999
+++ linux/drivers/sbus/char/zs.c	Wed May 12 08:41:15 1999
@@ -1,4 +1,4 @@
-/* $Id: zs.c,v 1.41 1999/04/16 16:22:27 jj Exp $
+/* $Id: zs.c,v 1.42 1999/05/12 11:15:26 davem Exp $
  * zs.c: Zilog serial port driver for the Sparc.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -174,7 +174,7 @@
  * memory if large numbers of serial ports are open.
  */
 static unsigned char tmp_buf[4096]; /* This is cheating */
-static struct semaphore tmp_buf_sem = MUTEX;
+static DECLARE_MUTEX(tmp_buf_sem);
 
 static inline int serial_paranoia_check(struct sun_serial *info,
 					dev_t device, const char *routine)
@@ -1628,7 +1628,7 @@
 static int block_til_ready(struct tty_struct *tty, struct file * filp,
 			   struct sun_serial *info)
 {
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 	int		retval;
 	int		do_clocal = 0;
 	unsigned char	r0;
@@ -1844,7 +1844,7 @@
 
 static void show_serial_version(void)
 {
-	char *revision = "$Revision: 1.41 $";
+	char *revision = "$Revision: 1.42 $";
 	char *version, *p;
 
 	version = strchr(revision, ' ');
@@ -2517,8 +2517,8 @@
 		info->tqueue_hangup.data = info;
 		info->callout_termios = callout_driver.init_termios;
 		info->normal_termios = serial_driver.init_termios;
-		info->open_wait = 0;
-		info->close_wait = 0;
+		init_waitqueue_head(&info->open_wait);
+		init_waitqueue_head(&info->close_wait);
 		printk("tty%02d at 0x%04x (irq = %s)", info->line, 
 		       info->port, __irq_itoa(info->irq));
 		printk(" is a Zilog8530\n");
diff -u --recursive --new-file v2.3.0/linux/drivers/sbus/char/zs.h linux/drivers/sbus/char/zs.h
--- v2.3.0/linux/drivers/sbus/char/zs.h	Thu Sep  4 12:54:49 1997
+++ linux/drivers/sbus/char/zs.h	Wed May 12 08:41:15 1999
@@ -1,4 +1,4 @@
-/* $Id: zs.h,v 1.1 1997/08/28 02:23:45 ecd Exp $
+/* $Id: zs.h,v 1.2 1999/05/12 11:15:31 davem Exp $
  * zs.h: Definitions for the Sparc Zilog serial driver.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -151,8 +151,8 @@
 	struct tq_struct	tqueue_hangup;
 	struct termios		normal_termios;
 	struct termios		callout_termios;
-	struct wait_queue	*open_wait;
-	struct wait_queue	*close_wait;
+	wait_queue_head_t	open_wait;
+	wait_queue_head_t	close_wait;
 };
 
 
diff -u --recursive --new-file v2.3.0/linux/drivers/scsi/aha152x.c linux/drivers/scsi/aha152x.c
--- v2.3.0/linux/drivers/scsi/aha152x.c	Mon Apr 12 16:18:26 1999
+++ linux/drivers/scsi/aha152x.c	Wed May 12 13:19:17 1999
@@ -414,8 +414,13 @@
 #define P_PARITY   2
 
 /* possible irq range */
+#ifdef PCMCIA
+#define IRQ_MIN 0
+#define IRQ_MAX 16
+#else
 #define IRQ_MIN 9
 #define IRQ_MAX 12
+#endif
 #define IRQS    IRQ_MAX-IRQ_MIN+1
 
 enum {
@@ -746,7 +751,7 @@
   if(!aha152x_porttest(setup->io_port))
     return 0;
   
-  if(setup->irq<IRQ_MIN && setup->irq>IRQ_MAX)
+  if((setup->irq<IRQ_MIN) || (setup->irq>IRQ_MAX))
     return 0;
   
   if((setup->scsiid < 0) || (setup->scsiid > 7))
diff -u --recursive --new-file v2.3.0/linux/drivers/scsi/atari_scsi.c linux/drivers/scsi/atari_scsi.c
--- v2.3.0/linux/drivers/scsi/atari_scsi.c	Thu Jul 30 11:17:10 1998
+++ linux/drivers/scsi/atari_scsi.c	Tue May 11 15:49:26 1999
@@ -497,9 +497,9 @@
 
 
 static int falcon_got_lock = 0;
-static struct wait_queue	*falcon_fairness_wait = NULL;
+static DECLARE_WAIT_QUEUE_HEAD(falcon_fairness_wait);
 static int falcon_trying_lock = 0;
-static struct wait_queue	*falcon_try_wait = NULL;
+static DECLARE_WAIT_QUEUE_HEAD(falcon_try_wait);
 static int falcon_dont_release = 0;
 
 /* This function releases the lock on the DMA chip if there is no
diff -u --recursive --new-file v2.3.0/linux/drivers/scsi/eata_dma_proc.c linux/drivers/scsi/eata_dma_proc.c
--- v2.3.0/linux/drivers/scsi/eata_dma_proc.c	Thu Jan  7 09:28:47 1999
+++ linux/drivers/scsi/eata_dma_proc.c	Wed May 12 13:27:37 1999
@@ -184,7 +184,7 @@
 	 * Do the command and wait for it to finish.
 	 */	
 	{
-	    struct semaphore sem = MUTEX_LOCKED;
+	    DECLARE_MUTEX_LOCKED(sem);
 	    scmd.request.rq_status = RQ_SCSI_BUSY;
 	    scmd.request.sem = &sem;
 	    scsi_do_cmd (&scmd, cmnd, buff + 0x144, 0x66,  
@@ -314,7 +314,7 @@
 	     * Do the command and wait for it to finish.
 	     */	
 	    {
-	        struct semaphore sem = MUTEX_LOCKED;
+	        DECLARE_MUTEX_LOCKED(sem);
 		scmd.request.rq_status = RQ_SCSI_BUSY;
 		scmd.request.sem = &sem;
 		scsi_do_cmd (&scmd, cmnd, buff2, 0x144,
diff -u --recursive --new-file v2.3.0/linux/drivers/scsi/gdth_proc.c linux/drivers/scsi/gdth_proc.c
--- v2.3.0/linux/drivers/scsi/gdth_proc.c	Mon Apr 12 09:56:16 1999
+++ linux/drivers/scsi/gdth_proc.c	Wed May 12 13:27:37 1999
@@ -931,7 +931,7 @@
 static void gdth_do_cmd(Scsi_Cmnd *scp,gdth_cmd_str *gdtcmd,int timeout)
 {
     char cmnd[12];
-    struct semaphore sem = MUTEX_LOCKED;
+    DECLARE_MUTEX_LOCKED(sem);
 
     TRACE2(("gdth_do_cmd()\n"));
     memset(cmnd, 0, 12);
diff -u --recursive --new-file v2.3.0/linux/drivers/scsi/hosts.c linux/drivers/scsi/hosts.c
--- v2.3.0/linux/drivers/scsi/hosts.c	Mon Apr 12 09:51:04 1999
+++ linux/drivers/scsi/hosts.c	Tue May 11 14:37:40 1999
@@ -665,7 +665,7 @@
     retval->host_no = max_scsi_hosts++; /* never reuse host_no (DB) */
     next_scsi_host++;
     retval->host_queue = NULL;
-    retval->host_wait = NULL;
+    init_waitqueue_head(&retval->host_wait);
     retval->resetting = 0;
     retval->last_reset = 0;
     retval->irq = 0;
@@ -738,7 +738,7 @@
  */
 static void launch_error_handler_thread(struct Scsi_Host * shpnt)
 {
-            struct semaphore sem = MUTEX_LOCKED;
+            DECLARE_MUTEX_LOCKED(sem);
             
             shpnt->eh_notify = &sem;
 
diff -u --recursive --new-file v2.3.0/linux/drivers/scsi/hosts.h linux/drivers/scsi/hosts.h
--- v2.3.0/linux/drivers/scsi/hosts.h	Tue May 11 13:04:44 1999
+++ linux/drivers/scsi/hosts.h	Thu May 13 14:43:03 1999
@@ -313,7 +313,7 @@
                                           host. */
     unsigned int            eh_active:1; /* Indicates the eh thread is awake and active if
                                           this is true. */
-    struct wait_queue     * host_wait;
+    wait_queue_head_t       host_wait;
     Scsi_Host_Template    * hostt;
     atomic_t                host_active; /* commands checked out */
     volatile unsigned short host_busy;   /* commands actually active on low-level */
diff -u --recursive --new-file v2.3.0/linux/drivers/scsi/megaraid.c linux/drivers/scsi/megaraid.c
--- v2.3.0/linux/drivers/scsi/megaraid.c	Thu May  6 23:14:37 1999
+++ linux/drivers/scsi/megaraid.c	Tue May 11 15:48:45 1999
@@ -1522,7 +1522,7 @@
  *----------------------------------------------------------------------*/
 volatile static int internal_done_flag = 0;
 volatile static int internal_done_errcode = 0;
-static struct wait_queue *internal_wait = NULL;
+static DECLARE_WAIT_QUEUE_HEAD(internal_wait);
 
 static void internal_done (Scsi_Cmnd * SCpnt)
 {
diff -u --recursive --new-file v2.3.0/linux/drivers/scsi/pluto.c linux/drivers/scsi/pluto.c
--- v2.3.0/linux/drivers/scsi/pluto.c	Mon Mar 15 16:11:31 1999
+++ linux/drivers/scsi/pluto.c	Wed May 12 08:41:15 1999
@@ -54,7 +54,7 @@
 static int fcscount __initdata = 0;
 static atomic_t fcss __initdata = ATOMIC_INIT(0);
 static struct timer_list fc_timer __initdata = { 0 };
-struct semaphore fc_sem __initdata = MUTEX_LOCKED;
+DECLARE_MUTEX_LOCKED(fc_sem);
 
 static int pluto_encode_addr(Scsi_Cmnd *SCpnt, u16 *addr, fc_channel *fc, fcp_cmnd *fcmd);
 
diff -u --recursive --new-file v2.3.0/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c
--- v2.3.0/linux/drivers/scsi/scsi.c	Thu Apr 29 11:53:41 1999
+++ linux/drivers/scsi/scsi.c	Tue May 11 14:37:40 1999
@@ -473,6 +473,8 @@
   SDpnt->host = shpnt;
   SDpnt->online = TRUE;
 
+  init_waitqueue_head(&SDpnt->device_wait);
+
   /*
    * Next, hook the device to the host in question.
    */
@@ -660,7 +662,7 @@
   SCpnt->lun = SDpnt->lun;
   SCpnt->channel = SDpnt->channel;
   {
-    struct semaphore sem = MUTEX_LOCKED;
+    DECLARE_MUTEX_LOCKED(sem);
     SCpnt->request.sem = &sem;
     SCpnt->request.rq_status = RQ_SCSI_BUSY;
     spin_lock_irq(&io_request_lock);
@@ -703,7 +705,7 @@
   scsi_cmd[5] = 0;
   SCpnt->cmd_len = 0;
   {
-    struct semaphore sem = MUTEX_LOCKED;
+    DECLARE_MUTEX_LOCKED(sem);
     SCpnt->request.sem = &sem;
     SCpnt->request.rq_status = RQ_SCSI_BUSY;
     spin_lock_irq(&io_request_lock);
@@ -849,7 +851,7 @@
     scsi_cmd[5] = 0;
     SCpnt->cmd_len = 0;
     {
-      struct semaphore sem = MUTEX_LOCKED;
+      DECLARE_MUTEX_LOCKED(sem);
       SCpnt->request.rq_status = RQ_SCSI_BUSY;
       SCpnt->request.sem = &sem;
       spin_lock_irq(&io_request_lock);
@@ -890,6 +892,8 @@
   SDpnt->device_queue = SCpnt;
   SDpnt->online = TRUE;
 
+  init_waitqueue_head(&SDpnt->device_wait);
+
   /*
    * Since we just found one device, there had damn well better be one in the list
    * already.
@@ -2639,7 +2643,7 @@
         {
             if( shpnt->hostt == tpnt && shpnt->hostt->use_new_eh_code )
             {
-                struct semaphore sem = MUTEX_LOCKED;
+      		DECLARE_MUTEX_LOCKED(sem);
                 
                 shpnt->eh_notify = &sem;
                 kernel_thread((int (*)(void *))scsi_error_handler, 
@@ -2876,7 +2880,7 @@
               && shpnt->hostt->use_new_eh_code
               && shpnt->ehandler != NULL )
         {
-            struct semaphore sem = MUTEX_LOCKED;
+            DECLARE_MUTEX_LOCKED(sem);
             
             shpnt->eh_notify = &sem;
             send_sig(SIGKILL, shpnt->ehandler, 1);
diff -u --recursive --new-file v2.3.0/linux/drivers/scsi/scsi.h linux/drivers/scsi/scsi.h
--- v2.3.0/linux/drivers/scsi/scsi.h	Tue May 11 13:04:47 1999
+++ linux/drivers/scsi/scsi.h	Thu May 13 14:43:05 1999
@@ -417,7 +417,7 @@
      */
     struct scsi_device * next;      /* Used for linked list */
     struct scsi_device * prev;      /* Used for linked list */
-    struct wait_queue  * device_wait;/* Used to wait if
+    wait_queue_head_t device_wait;/* Used to wait if
                                                       device is busy */
     struct Scsi_Host   * host;
     volatile unsigned short device_busy;   /* commands actually active on low-level */
@@ -711,7 +711,7 @@
 
 #define SCSI_SLEEP(QUEUE, CONDITION) {		    \
     if (CONDITION) {			            \
-	struct wait_queue wait = { current, NULL};  \
+	DECLARE_WAITQUEUE(wait, current);	    \
 	add_wait_queue(QUEUE, &wait);		    \
 	for(;;) {			            \
 	current->state = TASK_UNINTERRUPTIBLE;	    \
diff -u --recursive --new-file v2.3.0/linux/drivers/scsi/scsi_error.c linux/drivers/scsi/scsi_error.c
--- v2.3.0/linux/drivers/scsi/scsi_error.c	Wed Feb 24 16:27:54 1999
+++ linux/drivers/scsi/scsi_error.c	Tue May 11 14:37:40 1999
@@ -560,7 +560,7 @@
 
 void scsi_sleep (int timeout)
 {
-    struct semaphore sem = MUTEX_LOCKED;
+    DECLARE_MUTEX_LOCKED(sem);
     struct timer_list timer;
 
     init_timer(&timer);
@@ -603,7 +603,7 @@
 
     if (host->can_queue)
     {
-        struct semaphore sem = MUTEX_LOCKED;
+        DECLARE_MUTEX_LOCKED(sem);
 
         SCpnt->eh_state = SCSI_STATE_QUEUED;
 
@@ -1924,7 +1924,7 @@
 {
 	struct Scsi_Host     * host = (struct Scsi_Host *) data;
 	int	               rtn;
-	struct semaphore sem = MUTEX_LOCKED;
+        DECLARE_MUTEX_LOCKED(sem);
         unsigned long flags;
 
 	lock_kernel();
diff -u --recursive --new-file v2.3.0/linux/drivers/scsi/scsi_ioctl.c linux/drivers/scsi/scsi_ioctl.c
--- v2.3.0/linux/drivers/scsi/scsi_ioctl.c	Thu Apr 29 11:53:41 1999
+++ linux/drivers/scsi/scsi_ioctl.c	Tue May 11 14:37:40 1999
@@ -113,7 +113,7 @@
     SCSI_LOG_IOCTL(1, printk("Trying ioctl with scsi command %d\n", cmd[0]));
     SCpnt = scsi_allocate_device(NULL, dev, 1);
     {
-	struct semaphore sem = MUTEX_LOCKED;
+	DECLARE_MUTEX_LOCKED(sem);
 	SCpnt->request.sem = &sem;
 	scsi_do_cmd(SCpnt,  cmd, NULL,  0, scsi_ioctl_done,  timeout, retries);
 	spin_unlock_irqrestore(&io_request_lock, flags);
@@ -289,7 +289,7 @@
     SCpnt = scsi_allocate_device(NULL, dev, 1);
 
     {
-	struct semaphore sem = MUTEX_LOCKED;
+	DECLARE_MUTEX_LOCKED(sem);
 	SCpnt->request.sem = &sem;
 	scsi_do_cmd(SCpnt,  cmd,  buf, needed,  scsi_ioctl_done,
 		    timeout, retries);
diff -u --recursive --new-file v2.3.0/linux/drivers/scsi/sd.c linux/drivers/scsi/sd.c
--- v2.3.0/linux/drivers/scsi/sd.c	Thu Apr 29 11:53:41 1999
+++ linux/drivers/scsi/sd.c	Tue May 11 14:37:40 1999
@@ -1183,7 +1183,7 @@
 		SCpnt->sense_buffer[2] = 0;
 
 		{
-		    struct semaphore sem = MUTEX_LOCKED;
+		    DECLARE_MUTEX_LOCKED(sem);
 		    /* Mark as really busy again */
 		    SCpnt->request.rq_status = RQ_SCSI_BUSY;
 		    SCpnt->request.sem = &sem;
@@ -1221,7 +1221,7 @@
 		    SCpnt->sense_buffer[2] = 0;
 
 		    {
-		    	struct semaphore sem = MUTEX_LOCKED;
+		        DECLARE_MUTEX_LOCKED(sem);
 			/* Mark as really busy again */
 			SCpnt->request.rq_status = RQ_SCSI_BUSY;
 		    	SCpnt->request.sem = &sem;
@@ -1263,7 +1263,7 @@
 	SCpnt->sense_buffer[2] = 0;
 
 	{
-	    struct semaphore sem = MUTEX_LOCKED;
+            DECLARE_MUTEX_LOCKED(sem);
 	    /* Mark as really busy again */
 	    SCpnt->request.rq_status = RQ_SCSI_BUSY;
 	    SCpnt->request.sem = &sem;
@@ -1444,7 +1444,7 @@
 
 	/* same code as READCAPA !! */
 	{
-	    struct semaphore sem = MUTEX_LOCKED;
+            DECLARE_MUTEX_LOCKED(sem);
 	    SCpnt->request.rq_status = RQ_SCSI_BUSY;  /* Mark as really busy again */
 	    SCpnt->request.sem = &sem;
 	    scsi_do_cmd (SCpnt,
diff -u --recursive --new-file v2.3.0/linux/drivers/scsi/sg.c linux/drivers/scsi/sg.c
--- v2.3.0/linux/drivers/scsi/sg.c	Fri May  7 11:05:30 1999
+++ linux/drivers/scsi/sg.c	Tue May 11 14:37:40 1999
@@ -135,7 +135,7 @@
 {
     struct sg_fd * nextfp; /* NULL when last opened fd on this device */
     struct sg_device * parentdp;     /* owning device */
-    struct wait_queue * read_wait;   /* queue read until command done */
+    wait_queue_head_t read_wait;   /* queue read until command done */
     int timeout;                     /* defaults to SG_DEFAULT_TIMEOUT */
     char * fst_buf;     /* try to grab SG_SCATTER_SZ sized buffer on open */
     int fb_size;        /* actual size of allocated fst_buf */
@@ -153,7 +153,7 @@
 typedef struct sg_device /* holds the state of each scsi generic device */
 {
     Scsi_Device * device;
-    struct wait_queue * generic_wait;/* queue open if O_EXCL on prev. open */
+    wait_queue_head_t generic_wait;/* queue open if O_EXCL on prev. open */
     int sg_tablesize;   /* adapter's max scatter-gather table size */
     Sg_fd * headfp;     /* first open fd belonging to this device */
     kdev_t i_rdev;      /* holds device major+minor number */
@@ -988,7 +988,7 @@
 
     SCSI_LOG_TIMEOUT(3, printk("sg_attach: dev=%d \n", k));
     sdp->device = scsidp;
-    sdp->generic_wait = NULL;
+    init_waitqueue_head(&sdp->generic_wait);
     sdp->headfp= NULL;
     sdp->exclude = 0;
     sdp->merge_fd = 0;  /* Cope with SG_DEF_MERGE_FD on open */
diff -u --recursive --new-file v2.3.0/linux/drivers/scsi/sr.c linux/drivers/scsi/sr.c
--- v2.3.0/linux/drivers/scsi/sr.c	Fri Jan 15 14:41:04 1999
+++ linux/drivers/scsi/sr.c	Tue May 11 14:37:40 1999
@@ -895,7 +895,7 @@
 
 	/* Do the command and wait.. */
 	{
-	    struct semaphore sem = MUTEX_LOCKED;
+	    DECLARE_MUTEX_LOCKED(sem);
 	    SCpnt->request.sem = &sem;
 	    spin_lock_irqsave(&io_request_lock, flags);
 	    scsi_do_cmd (SCpnt,
diff -u --recursive --new-file v2.3.0/linux/drivers/scsi/sr_ioctl.c linux/drivers/scsi/sr_ioctl.c
--- v2.3.0/linux/drivers/scsi/sr_ioctl.c	Mon May 10 13:01:21 1999
+++ linux/drivers/scsi/sr_ioctl.c	Tue May 11 14:37:40 1999
@@ -64,7 +64,7 @@
     if( !scsi_block_when_processing_errors(SDev) )
         return -ENODEV;
     {
-	struct semaphore sem = MUTEX_LOCKED;
+	DECLARE_MUTEX_LOCKED(sem);
 	SCpnt->request.sem = &sem;
 	spin_lock_irqsave(&io_request_lock, flags);
 	scsi_do_cmd(SCpnt,
diff -u --recursive --new-file v2.3.0/linux/drivers/scsi/st.c linux/drivers/scsi/st.c
--- v2.3.0/linux/drivers/scsi/st.c	Sun Mar  7 15:20:26 1999
+++ linux/drivers/scsi/st.c	Tue May 11 14:37:40 1999
@@ -279,7 +279,7 @@
     }
 
   cmd[1] |= (SCpnt->lun << 5) & 0xe0;
-  STp->sem = MUTEX_LOCKED;
+  init_MUTEX_LOCKED(&STp->sem);
   SCpnt->use_sg = (bytes > (STp->buffer)->sg[0].length) ?
       (STp->buffer)->use_sg : 0;
   if (SCpnt->use_sg) {
diff -u --recursive --new-file v2.3.0/linux/drivers/sound/dev_table.c linux/drivers/sound/dev_table.c
--- v2.3.0/linux/drivers/sound/dev_table.c	Mon Apr 12 16:18:27 1999
+++ linux/drivers/sound/dev_table.c	Tue May 11 23:40:50 1999
@@ -435,9 +435,9 @@
 		return -(ENOMEM);
 	}
 	memset((char *) op, 0, sizeof(struct audio_operations));
-	init_waitqueue(&op->in_sleeper);
-	init_waitqueue(&op->out_sleeper);	
-	init_waitqueue(&op->poll_sleeper);
+	init_waitqueue_head(&op->in_sleeper);
+	init_waitqueue_head(&op->out_sleeper);	
+	init_waitqueue_head(&op->poll_sleeper);
 	if (driver_size < sizeof(struct audio_driver))
 		memset((char *) d, 0, sizeof(struct audio_driver));
 
diff -u --recursive --new-file v2.3.0/linux/drivers/sound/dmasound.c linux/drivers/sound/dmasound.c
--- v2.3.0/linux/drivers/sound/dmasound.c	Wed Mar 10 21:48:46 1999
+++ linux/drivers/sound/dmasound.c	Tue May 11 23:28:01 1999
@@ -809,7 +809,7 @@
 	 *	       Bit 1 is set: a frame is playing
 	 */
 	int playing;
-	struct wait_queue *write_queue, *open_queue, *sync_queue;
+	wait_queue_head_t write_queue, open_queue, sync_queue;
 	int open_mode;
 	int busy, syncing;
 #ifdef CONFIG_ATARI
@@ -4623,7 +4623,9 @@
 	if (sq_unit < 0)
 		return;
 
-	sq.write_queue = sq.open_queue = sq.sync_queue = 0;
+	init_waitqueue_head(&sq.write_queue);
+	init_waitqueue_head(&sq.open_queue);
+	init_waitqueue_head(&sq.sync_queue);
 	sq.busy = 0;
 
 	/* whatever you like as startup mode for /dev/dsp,
diff -u --recursive --new-file v2.3.0/linux/drivers/sound/es1370.c linux/drivers/sound/es1370.c
--- v2.3.0/linux/drivers/sound/es1370.c	Mon Apr 12 16:18:27 1999
+++ linux/drivers/sound/es1370.c	Wed May 12 13:27:37 1999
@@ -310,7 +310,7 @@
 	spinlock_t lock;
 	struct semaphore open_sem;
 	mode_t open_mode;
-	struct wait_queue *open_wait;
+	wait_queue_head_t open_wait;
 
 	struct dmabuf {
 		void *rawbuf;
@@ -321,7 +321,7 @@
 		unsigned total_bytes;
 		int count;
 		unsigned error; /* over/underrun */
-		struct wait_queue *wait;
+		wait_queue_head_t wait;
 		/* redundant, but makes calculations easier */
 		unsigned fragsize;
 		unsigned dmasize;
@@ -339,8 +339,8 @@
 	struct {
 		unsigned ird, iwr, icnt;
 		unsigned ord, owr, ocnt;
-		struct wait_queue *iwait;
-		struct wait_queue *owait;
+		wait_queue_head_t iwait;
+		wait_queue_head_t owait;
 		unsigned char ibuf[MIDIINBUF];
 		unsigned char obuf[MIDIOUTBUF];
 	} midi;
@@ -1007,7 +1007,7 @@
 
 static int drain_dac1(struct es1370_state *s, int nonblock)
 {
-        struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 	unsigned long flags;
 	int count, tmo;
 	
@@ -1042,7 +1042,7 @@
 
 static int drain_dac2(struct es1370_state *s, int nonblock)
 {
-        struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 	unsigned long flags;
 	int count, tmo;
 
@@ -2191,7 +2191,7 @@
 static int es1370_midi_release(struct inode *inode, struct file *file)
 {
 	struct es1370_state *s = (struct es1370_state *)file->private_data;
-        struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 	unsigned long flags;
 	unsigned count, tmo;
 
@@ -2308,13 +2308,13 @@
 			continue;
 		}
 		memset(s, 0, sizeof(struct es1370_state));
-		init_waitqueue(&s->dma_adc.wait);
-		init_waitqueue(&s->dma_dac1.wait);
-		init_waitqueue(&s->dma_dac2.wait);
-		init_waitqueue(&s->open_wait);
-		init_waitqueue(&s->midi.iwait);
-		init_waitqueue(&s->midi.owait);
-		s->open_sem = MUTEX;
+		init_waitqueue_head(&s->dma_adc.wait);
+		init_waitqueue_head(&s->dma_dac1.wait);
+		init_waitqueue_head(&s->dma_dac2.wait);
+		init_waitqueue_head(&s->open_wait);
+		init_waitqueue_head(&s->midi.iwait);
+		init_waitqueue_head(&s->midi.owait);
+		init_MUTEX(&s->open_sem);
 		s->magic = ES1370_MAGIC;
 		s->io = pcidev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;
 		s->irq = pcidev->irq;
diff -u --recursive --new-file v2.3.0/linux/drivers/sound/es1371.c linux/drivers/sound/es1371.c
--- v2.3.0/linux/drivers/sound/es1371.c	Mon Apr 12 16:18:27 1999
+++ linux/drivers/sound/es1371.c	Wed May 12 13:27:37 1999
@@ -361,7 +361,7 @@
 	spinlock_t lock;
 	struct semaphore open_sem;
 	mode_t open_mode;
-	struct wait_queue *open_wait;
+	wait_queue_head_t open_wait;
 
 	struct dmabuf {
 		void *rawbuf;
@@ -372,7 +372,7 @@
 		unsigned total_bytes;
 		int count;
 		unsigned error; /* over/underrun */
-		struct wait_queue *wait;
+		wait_queue_head_t wait;
 		/* redundant, but makes calculations easier */
 		unsigned fragsize;
 		unsigned dmasize;
@@ -390,8 +390,8 @@
 	struct {
 		unsigned ird, iwr, icnt;
 		unsigned ord, owr, ocnt;
-		struct wait_queue *iwait;
-		struct wait_queue *owait;
+		wait_queue_head_t iwait;
+		wait_queue_head_t owait;
 		unsigned char ibuf[MIDIINBUF];
 		unsigned char obuf[MIDIOUTBUF];
 	} midi;
@@ -1454,7 +1454,7 @@
 
 static int drain_dac1(struct es1371_state *s, int nonblock)
 {
-        struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 	unsigned long flags;
 	int count, tmo;
 	
@@ -1489,7 +1489,7 @@
 
 static int drain_dac2(struct es1371_state *s, int nonblock)
 {
-        struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 	unsigned long flags;
 	int count, tmo;
 
@@ -2625,7 +2625,7 @@
 static int es1371_midi_release(struct inode *inode, struct file *file)
 {
 	struct es1371_state *s = (struct es1371_state *)file->private_data;
-        struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 	unsigned long flags;
 	unsigned count, tmo;
 
@@ -2745,13 +2745,13 @@
 			continue;
 		}
 		memset(s, 0, sizeof(struct es1371_state));
-		init_waitqueue(&s->dma_adc.wait);
-		init_waitqueue(&s->dma_dac1.wait);
-		init_waitqueue(&s->dma_dac2.wait);
-		init_waitqueue(&s->open_wait);
-		init_waitqueue(&s->midi.iwait);
-		init_waitqueue(&s->midi.owait);
-		s->open_sem = MUTEX;
+		init_waitqueue_head(&s->dma_adc.wait);
+		init_waitqueue_head(&s->dma_dac1.wait);
+		init_waitqueue_head(&s->dma_dac2.wait);
+		init_waitqueue_head(&s->open_wait);
+		init_waitqueue_head(&s->midi.iwait);
+		init_waitqueue_head(&s->midi.owait);
+		init_MUTEX(&s->open_sem);
 		s->magic = ES1371_MAGIC;
 		s->io = pcidev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;
 		s->irq = pcidev->irq;
diff -u --recursive --new-file v2.3.0/linux/drivers/sound/gus_wave.c linux/drivers/sound/gus_wave.c
--- v2.3.0/linux/drivers/sound/gus_wave.c	Thu Jan 28 11:25:04 1999
+++ linux/drivers/sound/gus_wave.c	Tue May 11 23:40:50 1999
@@ -118,7 +118,7 @@
 static int      gus_audio_bsize;
 static char     bounce_buf[8 * 1024];	/* Must match value set to max_fragment */
 
-static struct wait_queue *dram_sleeper = NULL;
+static DECLARE_WAIT_QUEUE_HEAD(dram_sleeper);
 
 /*
  * Variables and buffers for PCM output
@@ -1663,7 +1663,7 @@
 			gus_no_dma = 0;
 	}
 
-	init_waitqueue(&dram_sleeper);
+	init_waitqueue_head(&dram_sleeper);
 	gus_busy = 1;
 	active_device = GUS_DEV_WAVE;
 
diff -u --recursive --new-file v2.3.0/linux/drivers/sound/midibuf.c linux/drivers/sound/midibuf.c
--- v2.3.0/linux/drivers/sound/midibuf.c	Wed Dec 16 12:52:01 1998
+++ linux/drivers/sound/midibuf.c	Tue May 11 23:40:50 1999
@@ -29,8 +29,8 @@
 
 #define MAX_QUEUE_SIZE	4000
 
-static struct wait_queue *midi_sleeper[MAX_MIDI_DEV] = {NULL};
-static struct wait_queue *input_sleeper[MAX_MIDI_DEV] = {NULL};
+static wait_queue_head_t midi_sleeper[MAX_MIDI_DEV];
+static wait_queue_head_t input_sleeper[MAX_MIDI_DEV];
 
 struct midi_buf
 {
@@ -202,8 +202,8 @@
 	midi_out_buf[dev]->len = midi_out_buf[dev]->head = midi_out_buf[dev]->tail = 0;
 	open_devs++;
 
-	init_waitqueue(&midi_sleeper[dev]);
-	init_waitqueue(&input_sleeper[dev]);
+	init_waitqueue_head(&midi_sleeper[dev]);
+	init_waitqueue_head(&input_sleeper[dev]);
 
 	if (open_devs < 2)	/* This was first open */
 	{
diff -u --recursive --new-file v2.3.0/linux/drivers/sound/msnd_pinnacle.c linux/drivers/sound/msnd_pinnacle.c
--- v2.3.0/linux/drivers/sound/msnd_pinnacle.c	Mon Jan  4 11:37:30 1999
+++ linux/drivers/sound/msnd_pinnacle.c	Tue May 11 23:40:50 1999
@@ -1913,9 +1913,9 @@
 	if (digital)
 		set_bit(F_HAVEDIGITAL, &dev.flags);
 #endif
-	init_waitqueue(&dev.writeblock);
-	init_waitqueue(&dev.readblock);
-	init_waitqueue(&dev.writeflush);
+	init_waitqueue_head(&dev.writeblock);
+	init_waitqueue_head(&dev.readblock);
+	init_waitqueue_head(&dev.writeflush);
 	msnd_fifo_init(&dev.DAPF);
 	msnd_fifo_init(&dev.DARF);
 #ifndef LINUX20
diff -u --recursive --new-file v2.3.0/linux/drivers/sound/sequencer.c linux/drivers/sound/sequencer.c
--- v2.3.0/linux/drivers/sound/sequencer.c	Sun Mar  7 15:22:06 1999
+++ linux/drivers/sound/sequencer.c	Tue May 11 23:40:50 1999
@@ -53,8 +53,8 @@
 #define SEQ_2	2
 static int      seq_mode = SEQ_1;
 
-static struct wait_queue *seq_sleeper = NULL;
-static struct wait_queue *midi_sleeper = NULL;
+static DECLARE_WAIT_QUEUE_HEAD(seq_sleeper);
+static DECLARE_WAIT_QUEUE_HEAD(midi_sleeper);
 
 static int      midi_opened[MAX_MIDI_DEV] = {
 	0
@@ -1117,8 +1117,8 @@
 	if (seq_mode == SEQ_2)
 		tmr->open(tmr_no, seq_mode);
 
- 	init_waitqueue(&seq_sleeper);
- 	init_waitqueue(&midi_sleeper);
+ 	init_waitqueue_head(&seq_sleeper);
+ 	init_waitqueue_head(&midi_sleeper);
 	output_threshold = SEQ_MAX_QUEUE / 2;
 
 	return 0;
diff -u --recursive --new-file v2.3.0/linux/drivers/sound/sonicvibes.c linux/drivers/sound/sonicvibes.c
--- v2.3.0/linux/drivers/sound/sonicvibes.c	Mon Apr 12 16:18:27 1999
+++ linux/drivers/sound/sonicvibes.c	Wed May 12 13:27:37 1999
@@ -286,7 +286,7 @@
 	spinlock_t lock;
 	struct semaphore open_sem;
 	mode_t open_mode;
-	struct wait_queue *open_wait;
+	wait_queue_head_t open_wait;
 
 	struct dmabuf {
 		void *rawbuf;
@@ -297,7 +297,7 @@
 		unsigned total_bytes;
 		int count;
 		unsigned error; /* over/underrun */
-		struct wait_queue *wait;
+		wait_queue_head_t wait;
 		/* redundant, but makes calculations easier */
 		unsigned fragsize;
 		unsigned dmasize;
@@ -315,8 +315,8 @@
 	struct {
 		unsigned ird, iwr, icnt;
 		unsigned ord, owr, ocnt;
-		struct wait_queue *iwait;
-		struct wait_queue *owait;
+		wait_queue_head_t iwait;
+		wait_queue_head_t owait;
 		struct timer_list timer;
 		unsigned char ibuf[MIDIINBUF];
 		unsigned char obuf[MIDIOUTBUF];
@@ -1241,7 +1241,7 @@
 
 static int drain_dac(struct sv_state *s, int nonblock)
 {
-        struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 	unsigned long flags;
 	int count, tmo;
 
@@ -2043,7 +2043,7 @@
 static int sv_midi_release(struct inode *inode, struct file *file)
 {
 	struct sv_state *s = (struct sv_state *)file->private_data;
-        struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 	unsigned long flags;
 	unsigned count, tmo;
 
@@ -2344,12 +2344,12 @@
 			continue;
 		}
 		memset(s, 0, sizeof(struct sv_state));
-		init_waitqueue(&s->dma_adc.wait);
-		init_waitqueue(&s->dma_dac.wait);
-		init_waitqueue(&s->open_wait);
-		init_waitqueue(&s->midi.iwait);
-		init_waitqueue(&s->midi.owait);
-		s->open_sem = MUTEX;
+		init_waitqueue_head(&s->dma_adc.wait);
+		init_waitqueue_head(&s->dma_dac.wait);
+		init_waitqueue_head(&s->open_wait);
+		init_waitqueue_head(&s->midi.iwait);
+		init_waitqueue_head(&s->midi.owait);
+		init_MUTEX(&s->open_sem);
 		s->magic = SV_MAGIC;
 		s->iosb = pcidev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;
 		s->ioenh = pcidev->base_address[1] & PCI_BASE_ADDRESS_IO_MASK;
diff -u --recursive --new-file v2.3.0/linux/drivers/sound/wavfront.c linux/drivers/sound/wavfront.c
--- v2.3.0/linux/drivers/sound/wavfront.c	Thu Jan 14 22:59:47 1999
+++ linux/drivers/sound/wavfront.c	Tue May 11 23:40:50 1999
@@ -290,7 +290,7 @@
 	int samples_used;                  /* how many */
 	char interrupts_on;                /* h/w MPU interrupts enabled ? */
 	char rom_samples_rdonly;           /* can we write on ROM samples */
-	struct wait_queue *interrupt_sleeper; 
+	wait_queue_head_t interrupt_sleeper; 
 } dev;
 
 static int  detect_wffx(void);
@@ -2535,7 +2535,7 @@
 
 	}
 
-	init_waitqueue (&dev.interrupt_sleeper);
+	init_waitqueue_head (&dev.interrupt_sleeper);
 
 	if (wavefront_hw_reset ()) {
 		printk (KERN_WARNING LOGNAME "hardware reset failed\n");
diff -u --recursive --new-file v2.3.0/linux/drivers/usb/Config.in linux/drivers/usb/Config.in
--- v2.3.0/linux/drivers/usb/Config.in	Mon May 10 10:18:34 1999
+++ linux/drivers/usb/Config.in	Thu May 13 14:14:18 1999
@@ -11,20 +11,18 @@
 mainmenu_option next_comment
 comment 'USB drivers - not for the faint of heart'
 
-if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-  tristate 'Support for USB (EXPERIMENTAL!)' CONFIG_USB
-  if [ ! "$CONFIG_USB" = "n" ]; then
-    bool 'UHCI (intel PIIX4 and others) support?' CONFIG_USB_UHCI
-    bool 'OHCI (compaq and some others) support?' CONFIG_USB_OHCI
-    bool 'OHCI-HCD (other OHCI opt. Virt. Root Hub) support?' CONFIG_USB_OHCI_HCD
-    if [ "$CONFIG_USB_OHCI_HCD" = "y" ]; then
-       bool 'OHCI-HCD Virtual Root Hub' CONFIG_USB_OHCI_VROOTHUB
-    fi
-
-    bool 'USB mouse support' CONFIG_USB_MOUSE
-    bool 'USB keyboard support' CONFIG_USB_KBD
-    bool 'USB audio parsing support' CONFIG_USB_AUDIO
+tristate 'Support for USB (EXPERIMENTAL!)' CONFIG_USB
+if [ ! "$CONFIG_USB" = "n" ]; then
+  bool 'UHCI (intel PIIX4 and others) support?' CONFIG_USB_UHCI
+  bool 'OHCI (compaq and some others) support?' CONFIG_USB_OHCI
+  bool 'OHCI-HCD (other OHCI opt. Virt. Root Hub) support?' CONFIG_USB_OHCI_HCD
+  if [ "$CONFIG_USB_OHCI_HCD" = "y" ]; then
+     bool 'OHCI-HCD Virtual Root Hub' CONFIG_USB_OHCI_VROOTHUB
   fi
+
+  bool 'USB mouse support' CONFIG_USB_MOUSE
+  bool 'USB keyboard support' CONFIG_USB_KBD
+  bool 'USB audio parsing support' CONFIG_USB_AUDIO
 fi
 
 endmenu
diff -u --recursive --new-file v2.3.0/linux/drivers/usb/Makefile linux/drivers/usb/Makefile
--- v2.3.0/linux/drivers/usb/Makefile	Mon May 10 10:18:34 1999
+++ linux/drivers/usb/Makefile	Thu May 13 14:32:06 1999
@@ -32,6 +32,10 @@
   USBX_OBJS += audio.o
 endif
 
+ifeq ($(CONFIG_USB_CPIA),y)
+  USBX_OBJS += cpia.o
+endif
+
 ifeq ($(CONFIG_USB), y)
   L_OBJS += $(USBX_OBJS)
 endif
diff -u --recursive --new-file v2.3.0/linux/drivers/usb/cpia.c linux/drivers/usb/cpia.c
--- v2.3.0/linux/drivers/usb/cpia.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/usb/cpia.c	Thu May 13 14:19:00 1999
@@ -0,0 +1,1255 @@
+/*
+ * USB CPiA Video Camera driver
+ *
+ * Supports CPiA based Video Camera's. Many manufacturers use this chipset.
+ * There's a good chance, if you have a USB video camera, it's a CPiA based
+ * one
+ *
+ * (C) Copyright 1999 Johannes Erdfelt
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/list.h>
+#include <linux/malloc.h>
+#include <linux/mm.h>
+#include <linux/smp_lock.h>
+#include <linux/videodev.h>
+#include <linux/vmalloc.h>
+#include <linux/wrapper.h>
+
+#include <asm/spinlock.h>
+#include <asm/io.h>
+
+#include "usb.h"
+#include "uhci.h"
+#include "cpia.h"
+
+#define MAX_FRAME_SIZE (384 * 288 * 3)
+
+/*******************************/
+/* Memory management functions */
+/*******************************/
+
+/* convert virtual user memory address to physical address */
+/* (virt_to_phys only works for kmalloced kernel memory) */
+
+static inline unsigned long uvirt_to_phys(unsigned long adr)
+{
+        pgd_t *pgd;
+        pmd_t *pmd;
+        pte_t *ptep, pte;
+  
+        pgd = pgd_offset(current->mm, adr);
+        if (pgd_none(*pgd))
+                return 0;
+        pmd = pmd_offset(pgd, adr);
+        if (pmd_none(*pmd))
+                return 0;
+        ptep = pte_offset(pmd, adr/*&(~PGDIR_MASK)*/);
+        pte = *ptep;
+        if(pte_present(pte))
+                return 
+                  virt_to_phys((void *)(pte_page(pte)|(adr&(PAGE_SIZE-1))));
+        return 0;
+}
+
+static inline unsigned long uvirt_to_bus(unsigned long adr) 
+{
+        return virt_to_bus(phys_to_virt(uvirt_to_phys(adr)));
+}
+
+/* convert virtual kernel memory address to physical address */
+/* (virt_to_phys only works for kmalloced kernel memory) */
+
+static inline unsigned long kvirt_to_phys(unsigned long adr) 
+{
+        return uvirt_to_phys(VMALLOC_VMADDR(adr));
+}
+
+static inline unsigned long kvirt_to_bus(unsigned long adr) 
+{
+        return uvirt_to_bus(VMALLOC_VMADDR(adr));
+}
+
+
+static void * rvmalloc(unsigned long size)
+{
+	void * mem;
+	unsigned long adr, page;
+        
+	size += (PAGE_SIZE - 1);
+	size &= ~(PAGE_SIZE - 1);
+
+	mem=vmalloc(size);
+	if (mem) 
+	{
+		memset(mem, 0, size); /* Clear the ram out, no junk to the user */
+		adr=(unsigned long) mem;
+		while (size > 0) 
+		{
+			page = kvirt_to_phys(adr);
+			mem_map_reserve(MAP_NR(phys_to_virt(page)));
+			adr+=PAGE_SIZE;
+			if (size > PAGE_SIZE)
+				size-=PAGE_SIZE;
+			else
+				size=0;
+		}
+	}
+	return mem;
+}
+
+static void rvfree(void * mem, unsigned long size)
+{
+	unsigned long adr, page;
+        
+	size += (PAGE_SIZE - 1);
+	size &= ~(PAGE_SIZE - 1);
+
+	if (mem) 
+	{
+		adr=(unsigned long) mem;
+		while (size > 0) 
+		{
+ 			page = kvirt_to_phys(adr);
+			mem_map_unreserve(MAP_NR(phys_to_virt(page)));
+			adr+=PAGE_SIZE;
+			if (size > PAGE_SIZE)
+				size-=PAGE_SIZE;
+			else
+				size=0;
+		}
+		vfree(mem);
+	}
+}
+
+int usb_cpia_get_version(struct usb_device *dev, void *buf)
+{
+	devrequest dr;
+
+	dr.requesttype = (USB_TYPE_VENDOR | USB_RECIP_DEVICE) | 0x80;
+	dr.request = USB_REQ_CPIA_GET_VERSION;
+	dr.value = 0;
+	dr.index = 0;
+	dr.length = 4;
+
+	return dev->bus->op->control_msg(dev, usb_rcvctrlpipe(dev,0), &dr, buf, 4);
+}
+
+int usb_cpia_get_pnp_id(struct usb_device *dev, void *buf)
+{
+	devrequest dr;
+
+	dr.requesttype = (USB_TYPE_VENDOR | USB_RECIP_DEVICE) | 0x80;
+	dr.request = USB_REQ_CPIA_GET_PNP_ID;
+	dr.value = 0;
+	dr.index = 0;
+ 	dr.length = 6;
+
+	return dev->bus->op->control_msg(dev, usb_rcvctrlpipe(dev,0), &dr, buf, 6);
+}
+
+int usb_cpia_get_camera_status(struct usb_device *dev, void *buf)
+{
+	devrequest dr;
+
+	dr.requesttype = (USB_TYPE_VENDOR | USB_RECIP_DEVICE) | 0x80;
+	dr.request = USB_REQ_CPIA_GET_CAMERA_STATUS;
+	dr.value = 0;
+	dr.index = 0;
+	dr.length = 8;
+
+	return dev->bus->op->control_msg(dev, usb_rcvctrlpipe(dev,0), &dr, buf, 8);
+}
+
+int usb_cpia_goto_hi_power(struct usb_device *dev)
+{
+	devrequest dr;
+
+	dr.requesttype = (USB_TYPE_VENDOR | USB_RECIP_DEVICE);
+	dr.request = USB_REQ_CPIA_GOTO_HI_POWER;
+	dr.value = 0;
+	dr.index = 0;
+	dr.length = 0;
+
+	return dev->bus->op->control_msg(dev, usb_sndctrlpipe(dev,0), &dr, NULL, 0);
+}
+
+int usb_cpia_get_vp_version(struct usb_device *dev, void *buf)
+{
+	devrequest dr;
+
+	dr.requesttype = (USB_TYPE_VENDOR | USB_RECIP_DEVICE);
+	dr.request = USB_REQ_CPIA_GET_VP_VERSION;
+	dr.value = 0;
+	dr.index = 0;
+	dr.length = 4;
+
+	return dev->bus->op->control_msg(dev, usb_sndctrlpipe(dev,0), &dr, buf, 4);
+}
+
+int usb_cpia_set_sensor_fps(struct usb_device *dev, int sensorbaserate, int sensorclkdivisor)
+{
+	devrequest dr;
+
+	dr.requesttype = (USB_TYPE_VENDOR | USB_RECIP_DEVICE);
+	dr.request = USB_REQ_CPIA_SET_SENSOR_FPS;
+	dr.value = (sensorclkdivisor << 8) + sensorbaserate;
+	dr.index = 0;
+	dr.length = 0;
+
+	return dev->bus->op->control_msg(dev, usb_sndctrlpipe(dev,0), &dr, NULL, 0);
+}
+
+int usb_cpia_grab_frame(struct usb_device *dev, int streamstartline)
+{
+	devrequest dr;
+
+	dr.requesttype = (USB_TYPE_VENDOR | USB_RECIP_DEVICE);
+	dr.request = USB_REQ_CPIA_GRAB_FRAME;
+	dr.value = streamstartline << 8;
+	dr.index = 0;
+	dr.length = 0;
+
+	return dev->bus->op->control_msg(dev, usb_sndctrlpipe(dev,0), &dr, NULL, 0);
+}
+
+int usb_cpia_upload_frame(struct usb_device *dev, int forceupload)
+{
+	devrequest dr;
+
+	dr.requesttype = (USB_TYPE_VENDOR | USB_RECIP_DEVICE);
+	dr.request = USB_REQ_CPIA_UPLOAD_FRAME;
+	dr.value = forceupload;
+	dr.index = 0;
+	dr.length = 0;
+
+	return dev->bus->op->control_msg(dev, usb_sndctrlpipe(dev,0), &dr, NULL, 0);
+}
+
+int usb_cpia_set_grab_mode(struct usb_device *dev, int continuousgrab)
+{
+	devrequest dr;
+
+	dr.requesttype = (USB_TYPE_VENDOR | USB_RECIP_DEVICE);
+	dr.request = USB_REQ_CPIA_SET_GRAB_MODE;
+	dr.value = continuousgrab;
+	dr.index = 0;
+	dr.length = 0;
+
+	return dev->bus->op->control_msg(dev, usb_sndctrlpipe(dev,0), &dr, NULL, 0);
+}
+
+int usb_cpia_set_format(struct usb_device *dev, int size, int subsample, int order)
+{
+	devrequest dr;
+
+	dr.requesttype = (USB_TYPE_VENDOR | USB_RECIP_DEVICE);
+	dr.request = USB_REQ_CPIA_SET_FORMAT;
+	dr.value = (subsample << 8) + size;
+	dr.index = order;
+	dr.length = 0;
+
+	return dev->bus->op->control_msg(dev, usb_sndctrlpipe(dev,0), &dr, NULL, 0);
+}
+
+int usb_cpia_set_compression(struct usb_device *dev, int compmode, int decimation)
+{
+	devrequest dr;
+
+	dr.requesttype = (USB_TYPE_VENDOR | USB_RECIP_DEVICE);
+	dr.request = USB_REQ_CPIA_SET_COMPRESSION;
+	dr.value = (decimation << 8) + compmode;
+	dr.index = 0;
+	dr.length = 0;
+
+	return dev->bus->op->control_msg(dev, usb_sndctrlpipe(dev,0), &dr, NULL, 0);
+}
+
+int usb_cpia_initstreamcap(struct usb_device *dev, int skipframes, int streamstartline)
+{
+	devrequest dr;
+
+	dr.requesttype = (USB_TYPE_VENDOR | USB_RECIP_DEVICE);
+	dr.request = USB_REQ_CPIA_INIT_STREAM_CAP;
+	dr.value = (streamstartline << 8) + skipframes;
+	dr.index = 0;
+	dr.length = 0;
+
+	return dev->bus->op->control_msg(dev, usb_sndctrlpipe(dev,0), &dr, NULL, 0);
+}
+
+int usb_cpia_finistreamcap(struct usb_device *dev)
+{
+	devrequest dr;
+
+	dr.requesttype = (USB_TYPE_VENDOR | USB_RECIP_DEVICE);
+	dr.request = USB_REQ_CPIA_FINI_STREAM_CAP;
+	dr.value = 0;
+	dr.index = 0;
+	dr.length = 0;
+
+	return dev->bus->op->control_msg(dev, usb_sndctrlpipe(dev,0), &dr, NULL, 0);
+}
+
+int usb_cpia_startstreamcap(struct usb_device *dev)
+{
+	devrequest dr;
+
+	dr.requesttype = (USB_TYPE_VENDOR | USB_RECIP_DEVICE);
+	dr.request = USB_REQ_CPIA_START_STREAM_CAP;
+	dr.value = 0;
+	dr.index = 0;
+	dr.length = 0;
+
+	return dev->bus->op->control_msg(dev, usb_sndctrlpipe(dev,0), &dr, NULL, 0);
+}
+
+int usb_cpia_endstreamcap(struct usb_device *dev)
+{
+	devrequest dr;
+
+	dr.requesttype = (USB_TYPE_VENDOR | USB_RECIP_DEVICE);
+	dr.request = USB_REQ_CPIA_END_STREAM_CAP;
+	dr.value = 0;
+	dr.index = 0;
+	dr.length = 0;
+
+	return dev->bus->op->control_msg(dev, usb_sndctrlpipe(dev,0), &dr, NULL, 0);
+}
+
+#define scratch_left(x)	(cpia->scratchlen - (int)((char *)x - (char *)cpia->scratch))
+
+static void cpia_parse_data(struct usb_cpia *cpia)
+{
+	unsigned char *data = cpia->scratch;
+	int done;
+
+	done = 0;
+	while (!done && scratch_left(data)) {
+		switch (cpia->state) {
+		case STATE_SCANNING:
+		{
+			unsigned char *begin = data;
+
+			/* We need atleast 2 bytes for the magic value */
+			if (scratch_left(data) < 2) {
+				done = 1;
+				break;
+			}
+
+			printk("header: %X\n", (*data << 8) + *(data + 1));
+			if ((*data == 0x19) && (*(data + 1) == 0x68)) {
+				cpia->state = STATE_HEADER;
+				printk("moving to header\n");
+				break;
+			}
+
+			if (scratch_left(data) < 4) {
+				done = 1;
+				break;
+			}
+
+			printk("Scanning for end of frame\n");
+			while (scratch_left(data) >= 4) {
+				if ((*data == 0xFF) &&
+					(*(data + 1) == 0xFF) &&
+					(*(data + 2) == 0xFF) &&
+					(*(data + 3) == 0xFF)) {
+					data += 4;
+					break;
+				}
+				data++;
+			}
+printk("scan: scanned %d bytes\n", data-begin);
+			break;
+		}
+		case STATE_HEADER:
+			/* We need atleast 64 bytes for the header */
+			if (scratch_left(data) < 64) {
+				done = 1;
+				break;
+			}
+
+printk("header: framerate %d\n", data[41]);
+
+			data += 64;
+
+			cpia->state = STATE_LINES;
+				
+			break;
+		case STATE_LINES:
+		{
+			unsigned char *begin = data;
+			int found = 0;
+
+			while (scratch_left(data)) {
+				if (*data == 0xFD) {
+					data++;
+					found = 1;
+					break;
+				} else if ((*data == 0xFF) &&
+					(scratch_left(data) >= 3) &&
+					(*(data + 1) == 0xFF) &&
+					(*(data + 2) == 0xFF) &&
+					(*(data + 3) == 0xFF)) {
+					data+=4;
+					cpia->curline = 144;
+					found = 1;
+					break;
+				}
+
+				data++;
+			}
+#if 0
+printk("line %d: scanned %d bytes\n", cpia->curline, data-begin);
+#endif
+if (data-begin == 355 && cpia->frame[cpia->curframe].width != 64) {
+	int i;
+	char *f = cpia->frame[cpia->curframe].data, *b = begin;
+
+#if 0
+printk("copying\n");
+#endif
+
+	b+=2;
+	f+=(cpia->frame[cpia->curframe].width*3)*cpia->curline;
+	for (i = 0; i < 176; i++)
+		f[(i * 3) + 0] =
+		f[(i * 3) + 1] =
+		f[(i * 3) + 2] =
+			b[(i * 2)];
+}
+			if (found) {
+				cpia->curline++;
+				if (cpia->curline >= 144) {
+					wake_up(&cpia->wq);
+					cpia->state = STATE_SCANNING;
+					cpia->curline = 0;
+					cpia->curframe = -1;
+					done = 1;
+				}
+			} else {
+				data = begin;
+				done = 1;
+			}
+			
+			break;
+		}
+		}
+	}
+
+	{
+	int l;
+
+	l = scratch_left(data);
+	memmove(cpia->scratch, data, l);
+	cpia->scratchlen = l;
+	}
+}
+
+static int cpia_isoc_irq(int status, void *__buffer, void *dev_id)
+{
+	struct usb_cpia *cpia = dev_id;
+	struct usb_device *dev = cpia->dev;
+	struct cpia_sbuf *sbuf;
+	int i;
+	char *p;
+
+	if (!cpia->streaming) {
+		printk("oops, not streaming, but interrupt\n");
+		return 0;
+	}
+	
+	if (cpia->curframe < 0) {
+		if (cpia->frame[0].state == FRAME_READY) {
+			cpia->curframe = 0;
+			cpia->frame[0].state = FRAME_GRABBING;
+printk("capturing to frame 0\n");
+		} else if (cpia->frame[1].state == FRAME_READY) {
+			cpia->curframe = 1;
+			cpia->frame[1].state = FRAME_GRABBING;
+printk("capturing to frame 1\n");
+		} else
+printk("no frame available\n");
+	}
+
+	sbuf = &cpia->sbuf[cpia->receivesbuf];
+
+	uhci_unsched_isochronous(dev, sbuf->isodesc);
+
+	/* Do something to it now */
+	sbuf->len = uhci_compress_isochronous(dev, sbuf->isodesc);
+
+	if (sbuf->len)
+	printk("%d bytes received\n", sbuf->len);
+
+	if (sbuf->len && cpia->curframe >= 0) {
+		if (sbuf->len > (SCRATCH_BUF_SIZE - cpia->scratchlen)) {
+			printk("overflow!\n");
+			return 0;
+		}
+		memcpy(cpia->scratch + cpia->scratchlen, sbuf->data, sbuf->len);
+		cpia->scratchlen += sbuf->len;
+
+		cpia_parse_data(cpia);
+	}
+
+	/* Reschedule this block of Isochronous desc */
+	uhci_sched_isochronous(dev, sbuf->isodesc, cpia->sbuf[(cpia->receivesbuf + 2) % 3].isodesc);
+
+	/* Move to the next one */
+	cpia->receivesbuf = (cpia->receivesbuf + 1) % 3;
+
+	return 1;
+}
+
+int cpia_init_isoc(struct usb_cpia *cpia)
+{
+	struct usb_device *dev = cpia->dev;
+
+	cpia->receivesbuf = 0;
+
+#if 0
+	cpia->parsesbuf = 0;
+	cpia->parsepos = 0;
+#endif
+	cpia->scratchlen = 0;
+	cpia->curline = 0;
+	cpia->state = STATE_SCANNING;
+
+	/* Allocate all of the memory necessary */
+	cpia->sbuf[0].isodesc = uhci_alloc_isochronous(dev, usb_rcvisocpipe(dev,1), cpia->sbuf[0].data, STREAM_BUF_SIZE, 960, cpia_isoc_irq, cpia);
+	cpia->sbuf[1].isodesc = uhci_alloc_isochronous(dev, usb_rcvisocpipe(dev,1), cpia->sbuf[1].data, STREAM_BUF_SIZE, 960, cpia_isoc_irq, cpia);
+	cpia->sbuf[2].isodesc = uhci_alloc_isochronous(dev, usb_rcvisocpipe(dev,1), cpia->sbuf[2].data, STREAM_BUF_SIZE, 960, cpia_isoc_irq, cpia);
+
+	printk("isodesc[0] @ %p\n", cpia->sbuf[0].isodesc);
+	printk("isodesc[1] @ %p\n", cpia->sbuf[1].isodesc);
+	printk("isodesc[2] @ %p\n", cpia->sbuf[2].isodesc);
+
+	/* Schedule the queues */
+	uhci_sched_isochronous(dev, cpia->sbuf[0].isodesc, NULL);
+	uhci_sched_isochronous(dev, cpia->sbuf[1].isodesc, cpia->sbuf[0].isodesc);
+	uhci_sched_isochronous(dev, cpia->sbuf[2].isodesc, cpia->sbuf[1].isodesc);
+
+	if (usb_set_interface(cpia->dev, 1, 3)) {
+		printk("cpia_set_interface error\n");
+		return -EINVAL;
+	}
+
+	usb_cpia_startstreamcap(cpia->dev);
+
+	cpia->streaming = 1;
+
+	return 0;
+}
+
+void cpia_stop_isoc(struct usb_cpia *cpia)
+{
+	struct usb_device *dev = cpia->dev;
+
+	if (!cpia->streaming)
+		return;
+
+	cpia->streaming = 0;
+
+	/* Stop the streaming */
+	usb_cpia_endstreamcap(cpia->dev);
+
+	/* Set packet size to 0 */
+	if (usb_set_interface(cpia->dev, 1, 0)) {
+		printk("cpia_set_interface error\n");
+		return -EINVAL;
+	}
+
+	/* Unschedule all of the iso td's */
+	uhci_unsched_isochronous(dev, cpia->sbuf[2].isodesc);
+	uhci_unsched_isochronous(dev, cpia->sbuf[1].isodesc);
+	uhci_unsched_isochronous(dev, cpia->sbuf[0].isodesc);
+
+	/* Delete them all */
+	uhci_delete_isochronous(dev, cpia->sbuf[2].isodesc);
+	uhci_delete_isochronous(dev, cpia->sbuf[1].isodesc);
+	uhci_delete_isochronous(dev, cpia->sbuf[0].isodesc);
+}
+
+/* Video 4 Linux API */
+static int cpia_open(struct video_device *dev, int flags)
+{
+	struct usb_cpia *cpia = (struct usb_cpia *)dev;
+
+printk("cpia_open\n");
+
+	cpia->fbuf = rvmalloc(2 * MAX_FRAME_SIZE);
+	if (!cpia->fbuf)
+		return -ENOMEM;
+
+	cpia->frame[0].state = FRAME_DONE;
+	cpia->frame[1].state = FRAME_DONE;
+
+	cpia->frame[0].data = cpia->fbuf;
+	cpia->frame[1].data = cpia->fbuf + MAX_FRAME_SIZE;
+	printk("frame [0] @ %p\n", cpia->frame[0].data);
+	printk("frame [1] @ %p\n", cpia->frame[1].data);
+
+	cpia->sbuf[0].data = kmalloc(STREAM_BUF_SIZE, GFP_KERNEL);
+	if (!cpia->sbuf[0].data)
+		return -ENOMEM;
+
+	cpia->sbuf[1].data = kmalloc(STREAM_BUF_SIZE, GFP_KERNEL);
+	if (!cpia->sbuf[1].data)
+		return -ENOMEM;
+
+	cpia->sbuf[2].data = kmalloc(STREAM_BUF_SIZE, GFP_KERNEL);
+	if (!cpia->sbuf[2].data)
+		return -ENOMEM;
+
+	printk("sbuf[0] @ %p\n", cpia->sbuf[0].data);
+	printk("sbuf[1] @ %p\n", cpia->sbuf[1].data);
+	printk("sbuf[2] @ %p\n", cpia->sbuf[2].data);
+
+	cpia->curframe = -1;
+	cpia->receivesbuf = 0;
+
+	usb_cpia_initstreamcap(cpia->dev, 0, 60);
+
+	cpia_init_isoc(cpia);
+
+	return 0;
+}
+
+static void cpia_close(struct video_device *dev)
+{
+	struct usb_cpia *cpia = (struct usb_cpia *)dev;
+
+printk("cpia_close\n");
+
+	cpia_stop_isoc(cpia);
+
+	usb_cpia_finistreamcap(cpia->dev);
+
+	rvfree(cpia->fbuf, 2 * MAX_FRAME_SIZE);
+
+	kfree(cpia->sbuf[2].data);
+	kfree(cpia->sbuf[1].data);
+	kfree(cpia->sbuf[0].data);
+}
+
+static int cpia_init_done(struct video_device *dev)
+{
+	return 0;
+}
+
+static long cpia_write(struct video_device *dev, const char *buf, unsigned long count, int noblock)
+{
+	return -EINVAL;
+}
+
+#if 0
+	if (usb_set_interface(dev, 1, 3)) {
+		printk("cpia_set_interface error\n");
+		return -EINVAL;
+	}
+
+	if (usb_cpia_grab_frame(dev, 0)) {
+		printk("cpia_grab_frame error\n");
+		return -EINVAL;
+	}
+
+	if (usb_cpia_upload_frame(dev, 0)) {
+		printk("cpia_upload_frame error\n");
+		return -EINVAL;
+	}
+
+	buf = cpia->ibuf;
+	uhci_receive_isochronous(dev, usb_rcvisocpipe(dev,1), buf, 176*144*4);
+
+	{
+	printk("header magic: %X\n", (buf[0] << 8) + buf[1]);
+
+	while ((buf[0] != 0x19) || (buf[1] != 0x68)) {
+		int i;
+
+		printk("resync'ing\n");
+		for (i=0;i<(176*144*4)-4;i++, buf++)
+			if (
+				(buf[0] == 0xFF) &&
+				(buf[1] == 0xFF) &&
+				(buf[2] == 0xFF) &&
+				(buf[3] == 0xFF)) {
+				buf+=4;
+				i+=4;
+				break;
+			}
+
+		memmove(cpia->ibuf, buf, (176*144*4) - i);
+		uhci_receive_isochronous(dev, usb_rcvisocpipe(dev,1), cpia->ibuf + (176*144*4) - i, i);
+		buf = cpia->ibuf;
+
+#if 0
+		printk("header magic: %X\n", (buf[0] << 8) + buf[1]);
+#endif
+	}
+
+	printk("size: %d, sample: %d, order: %d\n", buf[16], buf[17], buf[18]);
+	printk("comp: %d, decimation: %d\n", buf[28], buf[29]);
+	printk("roi: top left: %d, %d bottom right: %d, %d\n",
+		buf[26] * 4, buf[24] * 8,
+		buf[27] * 4, buf[25] * 8);
+
+	printk("vm->frame: %d\n", vm->frame);
+
+	{
+	int i, i1;
+	char *b = buf + 64, *fbuf = &cpia->fbuffer[MAX_FRAME_SIZE * (vm->frame & 1)];
+	for (i=0;i<144;i++) {
+#if 0
+		printk("line len: %d\n", (b[1] << 8) + b[0]);
+#endif
+		b += 2;
+		for (i1=0;i1<176;i1++) {
+			fbuf[(i * vm->width * 3) + (i1 * 3)] = 
+			fbuf[(i * vm->width * 3) + (i1 * 3) + 1] = 
+			fbuf[(i * vm->width * 3) + (i1 * 3) + 2] = 
+				b[i1 * 2];
+#if 0
+			*((short *)&fbuf[(i * vm->width * 2) + (i1 * 2)]) =
+				((b[i1 * 2] >> 3) << 11) + ((b[i1 * 2] >> 2) << 6) + (b[i1 * 2] >> 3);
+#endif
+		}
+		b += (176 * 2) + 1;
+	}
+	}
+
+	}
+
+	if (usb_set_interface(dev, 1, 0)) {
+		printk("cpia_set_interface error\n");
+		return -EINVAL;
+	}
+#endif
+
+static int cpia_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
+{
+	struct usb_cpia *cpia = (struct usb_cpia *)dev;
+
+	switch (cmd) {
+		case VIDIOCGCAP:
+		{
+			struct video_capability b;
+
+			strcpy(b.name, "CPiA USB Camera");
+			b.type = VID_TYPE_CAPTURE /* | VID_TYPE_SUBCAPTURE */;
+			b.channels = 1;
+			b.audios = 0;
+			b.maxwidth = 176 /* 352 */;
+			b.maxheight = 144 /* 240 */;
+			b.minwidth = 176 /* (Something small?) */;
+			b.minheight = 144 /* "         " */;
+
+			if (copy_to_user(arg, &b, sizeof(b)))
+				return -EFAULT;
+			return 0;
+		}
+		case VIDIOCGCHAN:
+		{
+			struct video_channel v;
+
+			if (copy_from_user(&v, arg, sizeof(v)))
+				return -EFAULT;
+			if (v.channel != 0)
+				return -EINVAL;
+
+			v.flags = 0;
+			v.tuners = 0;
+			v.type = VIDEO_TYPE_CAMERA;
+			strcpy(v.name, "Camera");
+
+			if (copy_to_user(arg, &v, sizeof(v)))
+				return -EFAULT;
+			return 0;
+		}
+		case VIDIOCSCHAN:
+		{
+			int v;
+
+			if (copy_from_user(&v, arg, sizeof(v)))
+				return -EFAULT;
+
+			if (v != 0)
+				return -EINVAL;
+
+			return 0;
+		}
+		case VIDIOCGTUNER:
+		{
+			struct video_tuner v;
+
+			if (copy_from_user(&v, arg, sizeof(v)))
+				return -EFAULT;
+
+			if (v.tuner)
+				return -EINVAL;
+
+			strcpy(v.name, "Format");
+
+			v.rangelow = 0;
+			v.rangehigh = 0;
+			v.flags = 0;
+			v.mode = VIDEO_MODE_AUTO;
+
+			if (copy_to_user(arg, &v, sizeof(v)))
+				return -EFAULT;
+
+			return 0;
+		}
+		case VIDIOCSTUNER:
+		{
+			struct video_tuner v;
+
+			if (copy_from_user(&v, arg, sizeof(v)))
+				return -EFAULT;
+
+			if (v.tuner)
+				return -EINVAL;
+
+			if (v.mode != VIDEO_MODE_AUTO)
+				return -EINVAL;
+
+			return 0;
+		}
+		case VIDIOCGPICT:
+		{
+			struct video_picture p;
+
+			p.colour = 0x8000;	/* Damn British people :) */
+			p.hue = 0x8000;
+			p.brightness = 180 << 8;	/* XXX */
+			p.contrast = 192 << 8;		/* XXX */
+			p.whiteness = 105 << 8;		/* XXX */
+#if 0
+			p.depth = 24;
+#endif
+			p.depth = 16;
+			p.palette = VIDEO_PALETTE_YUYV;
+
+			if (copy_to_user(arg, &p, sizeof(p)))
+				return -EFAULT;
+
+			return 0;
+		}
+		case VIDIOCSPICT:
+		{
+			struct video_picture p;
+
+			if (copy_from_user(&p, arg, sizeof(p)))
+				return -EFAULT;
+
+printk("Attempting to set palette %d, depth %d\n", p.palette, p.depth);
+
+#if 0
+			if (p.palette != VIDEO_PALETTE_YUYV)
+				return -EINVAL;
+			if (p.depth != 16)
+				return -EINVAL;
+#endif
+
+			return 0;
+		}
+		case VIDIOCSWIN:
+		{
+			struct video_window vw;
+
+printk("VIDIOCSWIN\n");
+			if (copy_from_user(&vw, arg, sizeof(vw)))
+				return -EFAULT;
+			if (vw.flags)
+				return -EINVAL;
+			if (vw.clipcount)
+				return -EINVAL;
+			if (vw.height != 176)
+				return -EINVAL;
+			if (vw.width != 144)
+				return -EINVAL;
+
+			return 0;
+		}
+		case VIDIOCGWIN:
+		{
+			struct video_window vw;
+
+printk("VIDIOCGWIN\n");
+			vw.x = 0;
+			vw.y = 0;
+			vw.width = 176;
+			vw.height = 144;
+			vw.chromakey = 0;
+			vw.flags = 0;
+
+			if (copy_to_user(arg, &vw, sizeof(vw)))
+				return -EFAULT;
+
+			return 0;
+		}
+		case VIDIOCGMBUF:
+		{
+			struct video_mbuf vm;
+
+			memset(&vm, 0, sizeof(vm));
+			vm.size = MAX_FRAME_SIZE * 2;
+			vm.frames = 2;
+			vm.offsets[0] = 0;
+			vm.offsets[1] = MAX_FRAME_SIZE;
+
+			if (copy_to_user((void *)arg, (void *)&vm, sizeof(vm)))
+				return -EFAULT;
+
+			return 0;
+		}
+		case VIDIOCMCAPTURE:
+		{
+			struct video_mmap vm;
+
+			if (copy_from_user((void *)&vm, (void *)arg, sizeof(vm)))
+				return -EFAULT;
+
+printk("MCAPTURE\n");
+printk("frame: %d, size: %dx%d, format: %d\n", vm.frame, vm.width, vm.height, vm.format);
+
+			if (vm.format != VIDEO_PALETTE_RGB24)
+				return -EINVAL;
+
+			if ((vm.frame != 0) && (vm.frame != 1))
+				return -EINVAL;
+
+			cpia->frame[vm.frame].width = vm.width;
+			cpia->frame[vm.frame].height = vm.height;
+
+			/* Mark it as free */
+			cpia->frame[vm.frame].state = FRAME_READY;
+
+			return 0;
+		}
+		case VIDIOCSYNC:
+		{
+			int frame;
+
+			if (copy_from_user((void *)&frame, arg, sizeof(int)))
+				return -EFAULT;
+
+			printk("syncing to frame %d\n", frame);
+			switch (cpia->frame[frame].state) {
+				case FRAME_UNUSED:
+					return -EINVAL;
+				case FRAME_READY:
+				case FRAME_GRABBING:
+					interruptible_sleep_on(&cpia->wq);
+				case FRAME_DONE:
+					cpia->frame[frame].state = FRAME_UNUSED;
+					break;
+			}
+			printk("synced to frame %d\n", frame);
+			return 0;
+		}
+		case VIDIOCCAPTURE:
+			return -EINVAL;
+		case VIDIOCGFBUF:
+			return -EINVAL;
+		case VIDIOCSFBUF:
+			return -EINVAL;
+		case VIDIOCKEY:
+			return 0;
+		case VIDIOCGFREQ:
+			return -EINVAL;
+		case VIDIOCSFREQ:
+			return -EINVAL;
+		case VIDIOCGAUDIO:
+			return -EINVAL;
+		case VIDIOCSAUDIO:
+			return -EINVAL;
+		default:
+			return -ENOIOCTLCMD;
+	}
+	return 0;
+}
+
+static long cpia_read(struct video_device *dev, char *buf, unsigned long count, int noblock)
+{
+	struct usb_cpia *cpia = (struct usb_cpia *)dev;
+	int len;
+
+	printk("cpia_read: %d bytes\n", count);
+#if 0
+	len = cpia_capture(cpia, buf, count);
+
+	return len;
+#endif
+	return 0;
+}
+
+static int cpia_mmap(struct video_device *dev, const char *adr, unsigned long size)
+{
+	struct usb_cpia *cpia = (struct usb_cpia *)dev;
+	unsigned long start = (unsigned long)adr;
+	unsigned long page, pos;
+
+	printk("mmap: %d (%X) bytes\n", size, size);
+	if (size > (((2 * MAX_FRAME_SIZE) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)))
+		return -EINVAL;
+
+#if 0
+	if (!cpia->fbuffer) {
+		if ((cpia->fbuffer = rvmalloc(2 * MAX_FRAME_SIZE)) == NULL)
+			return -EINVAL;
+	}
+#endif
+
+	pos = (unsigned long)cpia->fbuf;
+	while (size > 0)
+	{
+		page = kvirt_to_phys(pos);
+		if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED))
+			return -EAGAIN;
+		start+=PAGE_SIZE;
+		pos+=PAGE_SIZE;
+		if (size > PAGE_SIZE)
+			size-=PAGE_SIZE;
+		else
+			size=0;
+	}
+
+	return 0;
+}
+
+static struct video_device cpia_template = {
+	"CPiA USB Camera",
+	VID_TYPE_CAPTURE,
+	VID_HARDWARE_CPIA,
+	cpia_open,
+	cpia_close,
+	cpia_read,
+	cpia_write,
+	NULL,
+	cpia_ioctl,
+	cpia_mmap,
+	cpia_init_done,
+	NULL,
+	0,
+	0
+};
+
+static void usb_cpia_configure(struct usb_cpia *cpia)
+{
+	struct usb_device *dev = cpia->dev;
+	unsigned char version[4];
+	unsigned char pnpid[6];
+	unsigned char camerastat[8];
+	unsigned char *buf;
+
+	usb_set_configuration(dev, dev->config[0].bConfigurationValue);
+
+	if (usb_cpia_get_version(dev, version)) {
+		printk("cpia_get_version error\n");
+		return;
+	}
+
+	printk("cpia: Firmware v%d.%d, VC Hardware v%d.%d\n",
+		version[0], version[1], version[2], version[3]);
+
+	if (usb_cpia_get_pnp_id(dev, pnpid)) {
+		printk("cpia_get_pnp_id error\n");
+		return;
+	}
+
+	printk("cpia: PnP Id: Vendor: %X, Product: %X, Revision: %X\n",
+		(pnpid[1] << 8) + pnpid[0], (pnpid[3] << 8) + pnpid[2],
+		(pnpid[5] << 8) + pnpid[4]);
+
+	memcpy(&cpia->vdev, &cpia_template, sizeof(cpia_template));
+
+	init_waitqueue_head(&cpia->wq);
+
+	if (video_register_device(&cpia->vdev, VFL_TYPE_GRABBER) == -1) {
+		printk("video_register_device failed\n");
+		return;
+	}
+
+	if (usb_cpia_goto_hi_power(dev)) {
+		printk("cpia_goto_hi_power error\n");
+		return;
+	}
+
+	if (usb_cpia_get_vp_version(dev, version)) {
+		printk("cpia_get_vp_version error\n");
+		return;
+	}
+
+	printk("cpia: VP v%d rev %d\n", version[0], version[1]);
+	printk("cpia: Camera Head ID %04X\n", (version[3] << 8) + version[2]);
+
+	/* Turn off continuous grab */
+	if (usb_cpia_set_grab_mode(dev, 1)) {
+		printk("cpia_set_grab_mode error\n");
+		return;
+	}
+
+	/* Set up the sensor to be 30fps */
+	if (usb_cpia_set_sensor_fps(dev, 1, 0)) {
+		printk("cpia_set_sensor_fps error\n");
+		return;
+	}
+
+	/* Set video into QCIF mode, and order into YUYV mode */
+	if (usb_cpia_set_format(dev, CPIA_QCIF, 1, CPIA_YUYV)) {
+		printk("cpia_set_format error\n");
+		return;
+	}
+
+	/* Turn off compression */
+	if (usb_cpia_set_compression(dev, 0, 0)) {
+		printk("cpia_set_compression error\n");
+		return;
+	}
+
+#if 0
+	if (usb_cpia_grab_frame(dev, 0)) {
+		printk("cpia_grab_frame error\n");
+		return;
+	}
+
+	if (usb_cpia_upload_frame(dev, 1)) {
+		printk("cpia_upload_frame error\n");
+		return;
+	}
+
+	buf = (void *)__get_free_page(GFP_KERNEL);
+
+	{
+	int i;
+	for (i=0;i<448;i++)
+		buf[i]=0;
+	}
+	uhci_receive_isochronous(dev, usb_rcvisocpipe(dev,1), buf, 448);
+
+	{
+	int i;
+	for (i=0;i<448;i++) {
+		printk("%02X ", buf[i]);
+		if ((i % 16) == 15)
+			printk("\n");
+	}
+	printk("\n");
+	}
+
+	free_page((unsigned long)buf);
+#endif
+}
+
+static int cpia_probe(struct usb_device *dev)
+{
+	struct usb_interface_descriptor *interface;
+	struct usb_endpoint_descriptor *endpoint;
+	struct usb_cpia *cpia;
+
+	/* We don't handle multi-config cameras */
+	if (dev->descriptor.bNumConfigurations != 1)
+		return -1;
+
+#if 0
+	/* We don't handle multi-interface hubs */
+	if (dev->config[0].bNumInterfaces != 1)
+		return -1;
+#endif
+
+	interface = &dev->config[0].interface[0];
+
+	/* Is it a CPiA? */
+/*
+Apr 24 17:49:04 bjorn kernel:   Vendor:  0545 
+Apr 24 17:49:04 bjorn kernel:   Product: 8080 
+*/
+/*
+	if (dev->descriptor.idVendor != 0x0545)
+		return -1;
+	if (dev->descriptor.idProduct != 0x8080)
+		return -1;
+	if (interface->bInterfaceClass != 0xFF)
+		return -1;
+	if (interface->bInterfaceSubClass != 0xFF)
+		return -1;
+*/
+	if (dev->descriptor.idVendor != 0x0553)
+		return -1;
+	if (dev->descriptor.idProduct != 0x0002)
+		return -1;
+	if (interface->bInterfaceClass != 0xFF)
+		return -1;
+	if (interface->bInterfaceSubClass != 0x00)
+		return -1;
+
+#if 0
+	/* Multiple endpoints? What kind of mutant ninja-hub is this? */
+	if (interface->bNumEndpoints != 1)
+		return -1;
+
+	endpoint = &interface->endpoint[0];
+
+	/* Output endpoint? Curiousier and curiousier.. */
+	if (!(endpoint->bEndpointAddress & 0x80))
+		return -1;
+
+	/* If it's not an interrupt endpoint, we'd better punt! */
+	if ((endpoint->bmAttributes & 3) != 3)
+		return -1;
+#endif
+
+	/* We found a CPiA */
+	printk("USB CPiA camera found\n");
+
+	if ((cpia = kmalloc(sizeof(*cpia), GFP_KERNEL)) == NULL) {
+		printk("couldn't kmalloc cpia struct\n");
+		return -1;
+	}
+
+	memset(cpia, 0, sizeof(*cpia));
+
+	dev->private = cpia;
+	cpia->dev = dev;
+
+	usb_cpia_configure(cpia);
+
+#if 0
+	usb_request_irq(dev, usb_rcvctrlpipe(dev, endpoint->bEndpointAddress), pport_irq, endpoint->bInterval, pport);
+#endif
+
+	return 0;
+}
+
+static void cpia_disconnect(struct usb_device *dev)
+{
+	struct usb_cpia *cpia = dev->private;
+
+	video_unregister_device(&cpia->vdev);
+
+	/* Free the memory */
+	kfree(cpia);
+}
+
+static struct usb_driver cpia_driver = {
+	"cpia",
+	cpia_probe,
+	cpia_disconnect,
+	{ NULL, NULL }
+};
+
+/*
+ * This should be a separate module.
+ */
+int cpia_init(void)
+{
+	usb_register(&cpia_driver);
+
+	return 0;
+}
+
diff -u --recursive --new-file v2.3.0/linux/drivers/usb/cpia.h linux/drivers/usb/cpia.h
--- v2.3.0/linux/drivers/usb/cpia.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/usb/cpia.h	Thu May 13 14:18:09 1999
@@ -0,0 +1,139 @@
+#ifndef __LINUX_CPIA_H
+#define __LINUX_CPIA_H
+
+#include <linux/list.h>
+
+#define USB_REQ_CPIA_GET_VERSION		0x01
+#define USB_REQ_CPIA_GET_PNP_ID			0x02
+#define USB_REQ_CPIA_GET_CAMERA_STATUS		0x03
+#define USB_REQ_CPIA_GOTO_HI_POWER		0x04
+#define USB_REQ_CPIA_GOTO_LO_POWER		0x05
+/* No 0x06 */
+#define USB_REQ_CPIA_GOTO_SUSPEND		0x07
+#define USB_REQ_CPIA_GOTO_PASS_THROUGH		0x08
+/* No 0x09 */
+#define USB_REQ_CPIA_MODIFY_CAMERA_STATUS	0x0A
+
+#define USB_REQ_CPIA_READ_VC_REGS		0x21
+#define USB_REQ_CPIA_WRITE_BC_REG		0x22
+#define USB_REQ_CPIA_READ_MC_PORTS		0x23
+#define USB_REQ_CPIA_WRITE_MC_PORT		0x24
+#define USB_REQ_CPIA_SET_BAUD_RATE		0x25
+#define USB_REQ_CPIA_SET_ECP_TIMING		0x26
+#define USB_REQ_CPIA_READ_IDATA			0x27
+#define USB_REQ_CPIA_WRITE_IDATA		0x28
+#define USB_REQ_CPIA_GENERIC_CALL		0x29
+#define USB_REQ_CPIA_I2CSTART			0x2A
+#define USB_REQ_CPIA_I2CSTOP			0x2B
+#define USB_REQ_CPIA_I2CWRITE			0x2C
+#define USB_REQ_CPIA_I2CREAD			0x2D
+
+#define USB_REQ_CPIA_GET_VP_VERSION		0xA1
+#define USB_REQ_CPIA_SET_COLOUR_PARAMS		0xA3
+#define USB_REQ_CPIA_SET_EXPOSURE		0xA4
+/* No 0xA5 */
+#define USB_REQ_CPIA_SET_COLOUR_BALANCE		0xA6
+#define USB_REQ_CPIA_SET_SENSOR_FPS		0xA7
+#define USB_REQ_CPIA_SET_VP_DEFAULTS		0xA8
+#define USB_REQ_CPIA_SET_APCOR			0xA9
+#define USB_REQ_CPIA_SET_FLICKER_CTRL		0xAA
+#define USB_REQ_CPIA_SET_VL_OFFSET		0xAB
+
+#define USB_REQ_CPIA_GET_COLOUR_PARAMETERS	0xB0
+#define USB_REQ_CPIA_GET_COLOUR_BALANCE		0xB1
+#define USB_REQ_CPIA_GET_EXPOSURE		0xB2
+#define USB_REQ_CPIA_SET_SENSOR_MATRIX		0xB3
+
+#define USB_REQ_CPIA_COLOUR_BARS		0xBD
+#define USB_REQ_CPIA_READ_VP_REGS		0xBE
+#define USB_REQ_CPIA_WRITE_VP_REGS		0xBF
+
+#define USB_REQ_CPIA_GRAB_FRAME			0xC1
+#define USB_REQ_CPIA_UPLOAD_FRAME		0xC2
+#define USB_REQ_CPIA_SET_GRAB_MODE		0xC3
+#define USB_REQ_CPIA_INIT_STREAM_CAP		0xC4
+#define USB_REQ_CPIA_FINI_STREAM_CAP		0xC5
+#define USB_REQ_CPIA_START_STREAM_CAP		0xC6
+#define USB_REQ_CPIA_END_STREAM_CAP		0xC7
+#define USB_REQ_CPIA_SET_FORMAT			0xC8
+#define USB_REQ_CPIA_SET_ROI			0xC9
+#define USB_REQ_CPIA_SET_COMPRESSION		0xCA
+#define USB_REQ_CPIA_SET_COMPRESSION_TARGET	0xCB
+#define USB_REQ_CPIA_SET_YUV_THRESH		0xCC
+#define USB_REQ_CPIA_SET_COMPRESSION_PARAMS	0xCD
+#define USB_REQ_CPIA_DISCARD_FRAME		0xCE
+
+#define USB_REQ_CPIA_OUTPUT_RS232		0xE1
+#define USB_REQ_CPIA_ABORT_PROCESS		0xE4
+#define USB_REQ_CPIA_SET_DRAM_PAGE		0xE5
+#define USB_REQ_CPIA_START_DRAM_UPLOAD		0xE6
+#define USB_REQ_CPIA_START_DUMMY_STREAM		0xE8
+#define USB_REQ_CPIA_ABORT_STREAM		0xE9
+#define USB_REQ_CPIA_DOWNLOAD_DRAM		0xEA
+/* #define USB_REQ_CPIA_NULL_CMD		0x?? */
+
+#define CPIA_QCIF	0
+#define CPIA_CIF	1
+
+#define CPIA_YUYV	0
+#define CPIA_UYVY	1
+
+#define STREAM_BUF_SIZE	(PAGE_SIZE * 4)
+
+#define SCRATCH_BUF_SIZE (STREAM_BUF_SIZE * 2)
+
+enum {
+	STATE_SCANNING,		/* Scanning for start */
+	STATE_HEADER,		/* Parsing header */
+	STATE_LINES,		/* Parsing lines */
+};
+
+struct usb_device;
+
+struct cpia_sbuf {
+	char *data;
+	int len;
+	void *isodesc;
+};
+
+enum {
+	FRAME_READY,		/* Ready to grab into */
+	FRAME_GRABBING,		/* In the process of being grabbed into */
+	FRAME_DONE,		/* Finished grabbing, but not been synced yet */
+	FRAME_UNUSED,		/* Unused (no MCAPTURE) */
+};
+
+struct cpia_frame {
+	char *data;
+	int width;
+	int height;
+	int state;
+};
+
+struct usb_cpia {
+	struct video_device vdev;
+
+	/* Device structure */
+	struct usb_device *dev;
+
+	int streaming;
+
+	char *fbuf;			/* Videodev buffer area */
+
+	int curframe;
+	struct cpia_frame frame[2];	/* Double buffering */
+
+	int receivesbuf;		/* Current receiving sbuf */
+	struct cpia_sbuf sbuf[3];	/* Triple buffering */
+
+	int state;			/* Current scanning state */
+	int curline;
+
+	char scratch[SCRATCH_BUF_SIZE];
+	int scratchlen;
+
+	wait_queue_head_t wq;
+};
+
+#endif
+
diff -u --recursive --new-file v2.3.0/linux/drivers/usb/hub.c linux/drivers/usb/hub.c
--- v2.3.0/linux/drivers/usb/hub.c	Fri Apr 30 08:20:01 1999
+++ linux/drivers/usb/hub.c	Tue May 11 23:09:42 1999
@@ -24,7 +24,7 @@
 extern struct usb_operations uhci_device_operations;
 
 /* Wakes up khubd */
-static struct wait_queue *usb_hub_wait = NULL;
+static DECLARE_WAIT_QUEUE_HEAD(usb_hub_wait);
 static spinlock_t hub_event_lock = SPIN_LOCK_UNLOCKED;
 
 /* List of hubs needing servicing */
diff -u --recursive --new-file v2.3.0/linux/drivers/usb/mouse.c linux/drivers/usb/mouse.c
--- v2.3.0/linux/drivers/usb/mouse.c	Fri Apr 30 08:20:49 1999
+++ linux/drivers/usb/mouse.c	Thu May 13 14:17:20 1999
@@ -48,7 +48,7 @@
 	int present; /* this mouse is plugged in */
 	int active; /* someone is has this mouse's device open */
 	int ready; /* the mouse has changed state since the last read */
-	struct wait_queue *wait; /* for polling */
+	wait_queue_head_t wait; /* for polling */
 	struct fasync_struct *fasync;
 	/* later, add a list here to support multiple mice */
 	/* but we will also need a list of file pointers to identify it */
@@ -277,7 +277,7 @@
 	misc_register(&usb_mouse);
 
 	mouse->present = mouse->active = 0;
-	mouse->wait = NULL;
+	init_waitqueue_head(&mouse->wait);
 	mouse->fasync = NULL;
 
 	usb_register(&mouse_driver);
diff -u --recursive --new-file v2.3.0/linux/drivers/usb/ohci-hcd.c linux/drivers/usb/ohci-hcd.c
--- v2.3.0/linux/drivers/usb/ohci-hcd.c	Tue May 11 09:55:45 1999
+++ linux/drivers/usb/ohci-hcd.c	Tue May 11 23:18:20 1999
@@ -63,8 +63,8 @@
 
  
 
-static struct wait_queue *control_wakeup;         
-static struct wait_queue *root_hub = NULL;
+static DECLARE_WAIT_QUEUE_HEAD(control_wakeup);
+static DECLARE_WAIT_QUEUE_HEAD(root_hub);
  
 static __u8 cc_to_status[16] = { /* mapping of the OHCI CC to the UHCI status codes; first guess */
 /* Activ, Stalled, Data Buffer Err, Babble Detected : NAK recvd, CRC/Timeout, Bitstuff, reservd */
@@ -145,7 +145,7 @@
 
 static int sohci_control_msg(struct usb_device *usb_dev, unsigned int pipe, void *cmd, void *data, int len)
 {
-	struct wait_queue wait = { current, NULL }; 
+	DECLARE_WAITQUEUE(wait, current);
 	struct ohci * ohci = usb_dev->bus->hcpriv;
 	int status;
 	union ep_addr_ ep_addr;
diff -u --recursive --new-file v2.3.0/linux/drivers/usb/ohci.c linux/drivers/usb/ohci.c
--- v2.3.0/linux/drivers/usb/ohci.c	Tue May 11 10:27:04 1999
+++ linux/drivers/usb/ohci.c	Tue May 11 23:17:31 1999
@@ -57,7 +57,7 @@
 static int apm_resume = 0;
 #endif
 
-static struct wait_queue *ohci_configure = NULL;
+static DECLARE_WAIT_QUEUE_HEAD(ohci_configure);
 
 #ifdef OHCI_TIMER
 static struct timer_list ohci_timer;	/* timer for root hub polling */
@@ -476,7 +476,7 @@
 /*
  * Control thread operations:
  */
-static struct wait_queue *control_wakeup;
+static DECLARE_WAIT_QUEUE_HEAD(control_wakeup);
 
 /*
  *  This is the handler that gets called when a control transaction
@@ -515,7 +515,7 @@
 	 */
 	struct ohci_ed *control_ed = &dev->ohci->root_hub->ed[ED_CONTROL];
 	struct ohci_td *setup_td, *data_td, *status_td;
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 
 #if 0
 	printk(KERN_DEBUG "entering ohci_control_msg %p (ohci_dev: %p) pipe 0x%x, cmd %p, data %p, len %d\n", usb, dev, pipe, cmd, data, len);
diff -u --recursive --new-file v2.3.0/linux/drivers/usb/uhci.c linux/drivers/usb/uhci.c
--- v2.3.0/linux/drivers/usb/uhci.c	Fri Apr 30 08:20:53 1999
+++ linux/drivers/usb/uhci.c	Thu May 13 14:34:01 1999
@@ -47,7 +47,7 @@
 
 #define compile_assert(x) do { switch (0) { case 1: case !(x): } } while (0)
 
-static struct wait_queue *uhci_configure = NULL;
+static DECLARE_WAIT_QUEUE_HEAD(uhci_configure);
 
 /*
  * Return the result of a TD..
@@ -61,15 +61,17 @@
 	/* Some debugging code */
 	if (status) {
 		int i = 10;
-		struct uhci_td *tmp = dev->control_td;
+		struct uhci_td *tmp = td->first;
 		printk("uhci_td_result() failed with status %d\n", status);
 		show_status(dev->uhci);
 		do {
 			show_td(tmp);
-			tmp++;
+			if ((tmp->link & 1) || (tmp->link & 2))
+				break;
+			tmp = bus_to_virt(tmp->link & ~0xF);
 			if (!--i)
 				break;
-		} while (tmp <= td);
+		} while (1);
 	}
 	return status;		
 }
@@ -279,7 +281,7 @@
 	unsigned int destination, status;
 
 	/* Destination: pipe destination with INPUT */
-	destination = (pipe & 0x0007ff00)  |  0x69;
+	destination = (pipe & 0x0007ff00) | 0x69;
 
 	/* Status:    slow/fast,      Interrupt,   Active,    Short Packet Detect     Infinite Errors */
 	status = (pipe & (1 << 26)) | (1 << 24) | (1 << 23)   |   (1 << 29)       |    (0 << 27);
@@ -292,6 +294,7 @@
 	td->status = status;			/* In */
 	td->info = destination | (7 << 21);	/* 8 bytes of data */
 	td->buffer = virt_to_bus(dev->data);
+	td->first = td;
 	td->qh = interrupt_qh;
 	interrupt_qh->skel = &dev->uhci->root_hub->skel_int8_qh;
 
@@ -305,6 +308,202 @@
 }
 
 /*
+ * Isochronous thread operations
+ */
+
+int uhci_compress_isochronous(struct usb_device *usb_dev, void *_isodesc)
+{
+	struct uhci_iso_td *isodesc = (struct uhci_iso_td *)_isodesc;
+	char *data = isodesc->data;
+	int i, totlen = 0;
+
+	for (i = 0; i < isodesc->num; i++) {
+		char *cdata = bus_to_virt(isodesc->td[i].buffer & ~0xF);
+		int n = (isodesc->td[i].status + 1) & 0x7FF;
+
+		if ((cdata != data) && (n))
+			memmove(data, cdata, n);
+
+#if 0
+if (n && n != 960)
+	printk("underrun: %d %d\n", i, n);
+#endif
+if ((isodesc->td[i].status >> 16) & 0xFF)
+	printk("error: %d %X\n", i, (isodesc->td[i].status >> 16));
+
+		data += n;
+		totlen += n;
+	}
+
+	return totlen;
+}
+
+int uhci_unsched_isochronous(struct usb_device *usb_dev, void *_isodesc)
+{
+	struct uhci_device *dev = usb_to_uhci(usb_dev);
+	struct uhci *uhci = dev->uhci;
+	struct uhci_iso_td *isodesc = (struct uhci_iso_td *)_isodesc;
+	int i;
+
+	if ((isodesc->frame < 0) || (isodesc->frame > 1023))
+		return 1;
+
+	/* Remove from previous frames */
+	for (i = 0; i < isodesc->num; i++) {
+		/* Turn off Active and IOC bits */
+		isodesc->td[i].status &= ~(3 << 23);
+		uhci->fl->frame[(isodesc->frame + i) % 1024] = isodesc->td[i].link;
+	}
+
+	isodesc->frame = -1;
+
+	return 0;
+}
+	
+/* td points to the one td we allocated for isochronous transfers */
+int uhci_sched_isochronous(struct usb_device *usb_dev, void *_isodesc, void *_pisodesc)
+{
+	struct uhci_device *dev = usb_to_uhci(usb_dev);
+	struct uhci *uhci = dev->uhci;
+	struct uhci_iso_td *isodesc = (struct uhci_iso_td *)_isodesc;
+	struct uhci_iso_td *pisodesc = (struct uhci_iso_td *)_pisodesc;
+	int frame, i;
+
+	if (isodesc->frame != -1) {
+		printk("isoc queue not removed\n");
+		uhci_unsched_isochronous(usb_dev, isodesc);
+	}
+
+	/* Insert TD into list */
+	if (!pisodesc) {
+		frame = inw(uhci->io_addr + USBFRNUM) % 1024;
+		/* HACK: Start 2 frames from now */
+		frame = (frame + 2) % 1024;
+	} else
+		frame = (pisodesc->endframe + 1) % 1024;
+
+#if 0
+printk("scheduling first at frame %d\n", frame);
+#endif
+
+	for (i = 0; i < isodesc->num; i++) {
+		/* Active */
+		isodesc->td[i].status |= (1 << 23);
+		isodesc->td[i].backptr = &uhci->fl->frame[(frame + i) % 1024];
+		isodesc->td[i].link = uhci->fl->frame[(frame + i) % 1024];
+		uhci->fl->frame[(frame + i) % 1024] = virt_to_bus(&isodesc->td[i]);
+	}
+
+#if 0
+printk("last at frame %d\n", (frame + i - 1) % 1024);
+#endif
+
+	/* Interrupt */
+	isodesc->td[i - 1].status |= (1 << 24);
+
+	isodesc->frame = frame;
+	isodesc->endframe = (frame + isodesc->num - 1) % 1024;
+
+#if 0
+	return uhci_td_result(dev, td[num - 1]);
+#endif
+	return 0;
+}
+
+/*
+ * Initialize isochronous queue
+ */
+void *uhci_alloc_isochronous(struct usb_device *usb_dev, unsigned int pipe, void *data, int len, int maxsze, usb_device_irq completed, void *dev_id)
+{
+	struct uhci_device *dev = usb_to_uhci(usb_dev);
+	unsigned long destination, status;
+	struct uhci_td *td;
+	int ret, i;
+	struct uhci_iso_td *isodesc;
+
+	isodesc = kmalloc(sizeof(*isodesc), GFP_KERNEL);
+	if (!isodesc) {
+		printk("Couldn't allocate isodesc!\n");
+		return NULL;
+	}
+	memset(isodesc, 0, sizeof(*isodesc));
+
+	/* Carefully work around the non contiguous pages */
+	isodesc->num = (len / PAGE_SIZE) * (PAGE_SIZE / maxsze);
+	isodesc->td = kmalloc(sizeof(struct uhci_td) * isodesc->num, GFP_KERNEL);
+	isodesc->frame = isodesc->endframe = -1;
+	isodesc->data = data;
+	isodesc->maxsze = maxsze;
+	
+	if (!isodesc->td) {
+		printk("Couldn't allocate td's\n");
+		kfree(isodesc);
+		return NULL;
+	}
+
+	isodesc->frame = isodesc->endframe = -1;
+
+	/*
+	 * Build the DATA TD's
+	 */
+	i = 0;
+	do {
+		/* Build the TD for control status */
+		td = &isodesc->td[i];
+
+		/* The "pipe" thing contains the destination in bits 8--18 */
+		destination = (pipe & 0x0007ff00);
+
+		if (usb_pipeout(pipe))
+			destination |= 0xE1;	/* OUT */
+		else
+			destination |= 0x69;	/* IN */
+
+		/* Status:    slow/fast,       Active,       Isochronous */
+		status = (pipe & (1 << 26)) | (1 << 23)   |   (1 << 25);
+
+		/*
+		 * Build the TD for the control request
+		 */
+		td->status = status;
+		td->info = destination | ((maxsze - 1) << 21);
+		td->buffer = virt_to_bus(data);
+		td->first = td;
+		td->backptr = NULL;
+
+		i++;
+
+		data += maxsze;
+
+		if (((int)data % PAGE_SIZE) + maxsze >= PAGE_SIZE)
+			data = (char *)(((int)data + maxsze) & ~(PAGE_SIZE - 1));
+		
+		len -= maxsze;
+	} while (i < isodesc->num);
+
+	/* IOC on the last TD */
+	td->status |= (1 << 24);
+	uhci_add_irq_list(dev->uhci, td, completed, dev_id);
+
+	return isodesc;
+}
+
+void uhci_delete_isochronous(struct usb_device *usb_dev, void *_isodesc)
+{
+	struct uhci_iso_td *isodesc = (struct uhci_iso_td *)_isodesc;
+
+	/* If it's still scheduled, unschedule them */
+	if (isodesc->frame)
+		uhci_unsched_isochronous(usb_dev, isodesc);
+
+	/* Remove it from the IRQ list */
+	uhci_remove_irq_list(&isodesc->td[isodesc->num - 1]);
+
+	kfree(isodesc->td);
+	kfree(isodesc);
+}
+
+/*
  * Control thread operations: we just mark the last TD
  * in a control thread as an interrupt TD, and wake up
  * the front-end on completion.
@@ -312,7 +511,7 @@
  * We need to remove the TD from the lists (both interrupt
  * list and TD lists) by hand if something bad happens!
  */
-static struct wait_queue *control_wakeup;
+static DECLARE_WAIT_QUEUE_HEAD(control_wakeup);
 
 static int uhci_control_completed(int status, void *buffer, void *dev_id)
 {
@@ -323,7 +522,7 @@
 /* td points to the last td in the list, which interrupts on completion */
 static int uhci_run_control(struct uhci_device *dev, struct uhci_td *first, struct uhci_td *last)
 {
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 	struct uhci_qh *ctrl_qh = uhci_qh_allocate(dev);
 	struct uhci_td *curtd;
 
@@ -420,6 +619,7 @@
 	td->status = status;				/* Try forever */
 	td->info = destination | (7 << 21);		/* 8 bytes of data */
 	td->buffer = virt_to_bus(cmd);
+	td->first = td;
 
 	/*
 	 * If direction is "send", change the frame from SETUP (0x2D)
@@ -450,6 +650,7 @@
 		td->status = status;					/* Status */
 		td->info = destination | ((pktsze-1) << 21);		/* pktsze bytes of data */
 		td->buffer = virt_to_bus(data);
+		td->first = first;
 		td->backptr = &prevtd->link;
 
 		prevtd = td;
@@ -470,6 +671,7 @@
 	td->status = status | (1 << 24);		/* IOC */
 	td->info = destination | (0x7ff << 21);		/* 0 bytes of data */
 	td->buffer = 0;
+	td->first = first;
 	td->backptr = &prevtd->link;
 
 	/* Start it up.. */
@@ -554,12 +756,16 @@
 	for (i = 0; i < UHCI_MAXTD; ++i) {
 		struct uhci_td *td = dev->td + i;
 
-		/* And remove it from the irq list, if it's active */
-		if (td->status & (1 << 23))
-			uhci_remove_irq_list(td);
-
-		if (td->inuse)
+		if (td->inuse) {
 			uhci_remove_td(td);
+
+			/* And remove it from the irq list, if it's active */
+			if (td->status & (1 << 23))
+				td->status &= ~(1 << 23);
+#if 0
+				uhci_remove_irq_list(td);
+#endif
+		}
 	}
 
 	/* Remove the td from any queues */
@@ -710,15 +916,18 @@
 			__list_del(tmp->prev, next);
 			INIT_LIST_HEAD(tmp);
 			if (td->completed(td->status, bus_to_virt(td->buffer), td->dev_id)) {
-				struct uhci_qh *interrupt_qh = td->qh;
-
 				list_add(&td->irq_list, &uhci->interrupt_list);
-				td->info ^= 1 << 19; /* toggle between data0 and data1 */
-				td->status = (td->status & 0x2f000000) | (1 << 23) | (1 << 24);	/* active */
 
-				/* Remove then readd? Is that necessary */
-				uhci_remove_td(td);
-				uhci_insert_td_in_qh(interrupt_qh, td);
+				if (!(td->status & (1 << 25))) {
+					struct uhci_qh *interrupt_qh = td->qh;
+
+					td->info ^= 1 << 19; /* toggle between data0 and data1 */
+					td->status = (td->status & 0x2f000000) | (1 << 23) | (1 << 24);	/* active */
+
+					/* Remove then readd? Is that necessary */
+					uhci_remove_td(td);
+					uhci_insert_td_in_qh(interrupt_qh, td);
+				}
 			}
 			/* If completed wants to not reactivate, then it's */
 			/* responsible for free'ing the TD's and QH's */
@@ -764,6 +973,9 @@
 	status = inw(io_addr + USBSTS);
 	outw(status, io_addr + USBSTS);
 
+	if ((status & ~0x21) != 0)
+		printk("interrupt: %X\n", status);
+
 	/* Walk the list of pending TD's to see which ones completed.. */
 	uhci_interrupt_notify(uhci);
 
@@ -787,6 +999,7 @@
 	td->status = (1 << 24);					/* interrupt on completion */
 	td->info = (15 << 21) | 0x7f69;				/* (ignored) input packet, 16 bytes, device 127 */
 	td->buffer = 0;
+	td->first = td;
 	td->qh = NULL;
 
 	uhci->fl->frame[0] = virt_to_bus(td);
@@ -1047,11 +1260,12 @@
 		}
 	}
 
-#if 0
+	{
+	int i;
 	if(uhci->root_hub)
 		for(i = 0; i < uhci->root_hub->usb->maxchild; i++)
 			usb_disconnect(uhci->root_hub->usb->children + i);
-#endif
+	}
 
 	cleanup_drivers();
 
@@ -1195,6 +1409,9 @@
 #ifdef CONFIG_USB_AUDIO		
 		usb_audio_init();
 #endif		
+#ifdef CONFIG_USB_CPIA
+		cpia_init();
+#endif
 #ifdef CONFIG_APM
 		apm_register_callback(&handle_apm_event);
 #endif
diff -u --recursive --new-file v2.3.0/linux/drivers/usb/uhci.h linux/drivers/usb/uhci.h
--- v2.3.0/linux/drivers/usb/uhci.h	Wed Apr 28 11:14:03 1999
+++ linux/drivers/usb/uhci.h	Thu May 13 14:42:51 1999
@@ -91,8 +91,20 @@
 	void *dev_id;
 	int inuse;			/* Inuse? */
 	struct uhci_qh *qh;
+	struct uhci_td *first;
 } __attribute__((aligned(32)));
 
+struct uhci_iso_td {
+	int num;
+	char *data;
+	int maxsze;
+
+	struct uhci_td *td;
+
+	int frame;
+	int endframe;
+};
+
 /*
  * Note the alignment requirements of the entries
  *
@@ -102,7 +114,7 @@
  */
 struct uhci;
 
-#define UHCI_MAXTD 64
+#define UHCI_MAXTD	64
 
 #define UHCI_MAXQH	16
 
@@ -124,9 +136,11 @@
  * The root hub pre-allocated QH's and TD's have
  * some special global uses..
  */
+#if 0
 #define control_td	td		/* Td's 0-30 */
 /* This is only for the root hub's TD list */
 #define tick_td		td[31]
+#endif
 
 /*
  * There are various standard queues. We set up several different
@@ -224,6 +238,12 @@
 void show_td(struct uhci_td * td);
 void show_status(struct uhci *uhci);
 void show_queues(struct uhci *uhci);
+
+int uhci_compress_isochronous(struct usb_device *usb_dev, void *_isodesc);
+int uhci_unsched_isochronous(struct usb_device *usb_dev, void *_isodesc);
+int uhci_sched_isochronous(struct usb_device *usb_dev, void *_isodesc, void *_pisodesc);
+void *uhci_alloc_isochronous(struct usb_device *usb_dev, unsigned int pipe, void *data, int len, int maxsze, usb_device_irq completed, void *dev_id);
+void uhci_delete_isochronous(struct usb_device *dev, void *_isodesc);
 
 #endif
 
diff -u --recursive --new-file v2.3.0/linux/drivers/usb/usb.c linux/drivers/usb/usb.c
--- v2.3.0/linux/drivers/usb/usb.c	Fri May  7 15:16:04 1999
+++ linux/drivers/usb/usb.c	Thu May 13 11:31:31 1999
@@ -124,7 +124,7 @@
 			
 		if (n_len < 2 || n_len > len)
 		{
-			printk("Short descriptor.\n");
+			printk("Short descriptor\n");
 			return -1;
 		}
 		printk(
@@ -152,9 +152,12 @@
 {
 	int n_len = ptr[0];
 
+	if (len <= 0)
+		return -1;
+
 	if (n_len < 2 || n_len > len)
 	{
-		printk("Short descriptor.\n");
+		printk("Short descriptor. (%d, %d)\n", len, n_len);
 		return -1;
 	}
 
@@ -247,6 +250,11 @@
 	len -= *ptr;
 	parsed += *ptr;
 
+	if (config->MaxPower == 200) {
+		printk("bNumInterfaces kludge\n");
+		config->bNumInterfaces += 3;
+	}
+
 	if (config->bNumInterfaces > USB_MAXINTERFACES)
 	{
 		printk(KERN_WARNING "usb: too many interfaces.\n");
@@ -298,8 +306,10 @@
 		if (retval < 0)
 			return retval;
 		ptr += retval;
-		bytes += retval;
+		bytes -= retval;
 	}
+	if (bytes)
+		printk(KERN_WARNING "usb: %d bytes of extra configuration data left\n", bytes);
 	return 0;
 }
 
@@ -533,6 +543,23 @@
 
 	return 0;
 }
+
+int usb_set_interface(struct usb_device *dev, int interface, int alternate)
+{
+	devrequest dr;
+
+	dr.requesttype = 1;
+	dr.request = USB_REQ_SET_INTERFACE;
+	dr.value = alternate;
+	dr.index = interface;
+	dr.length = 0;
+
+	if (dev->bus->op->control_msg(dev, usb_sndctrlpipe(dev, 0), &dr, NULL, 0))
+		return -1;
+
+	return 0;
+}
+
 
 int usb_set_configuration(struct usb_device *dev, int configuration)
 {
diff -u --recursive --new-file v2.3.0/linux/drivers/usb/usb.h linux/drivers/usb/usb.h
--- v2.3.0/linux/drivers/usb/usb.h	Tue May 11 10:04:03 1999
+++ linux/drivers/usb/usb.h	Thu May 13 14:42:48 1999
@@ -326,6 +326,8 @@
 /* Create control pipes.. */
 #define usb_sndctrlpipe(dev,endpoint)	((2 << 30) | __create_pipe(dev,endpoint))
 #define usb_rcvctrlpipe(dev,endpoint)	((2 << 30) | __create_pipe(dev,endpoint) | 0x80)
+#define usb_sndisocpipe(dev,endpoint)	((0 << 30) | __create_pipe(dev,endpoint))
+#define usb_rcvisocpipe(dev,endpoint)	((0 << 30) | __create_pipe(dev,endpoint) | 0x80)
 #define usb_snddefctrl(dev)		((2 << 30) | __default_pipe(dev))
 #define usb_rcvdefctrl(dev)		((2 << 30) | __default_pipe(dev) | 0x80)
 
diff -u --recursive --new-file v2.3.0/linux/drivers/video/Config.in linux/drivers/video/Config.in
--- v2.3.0/linux/drivers/video/Config.in	Wed Mar 17 09:17:22 1999
+++ linux/drivers/video/Config.in	Tue May 11 16:30:45 1999
@@ -21,6 +21,9 @@
   if [ "$CONFIG_ARCH_ACORN" = "y" ]; then
     bool 'Acorn VIDC support' CONFIG_FB_ACORN
   fi
+  if [ "$CONFIG_ARCH_NETWINDER" = "y" ]; then
+    tristate 'Cyber2000 support' CONFIG_FB_CYBER2000
+  fi
   if [ "$CONFIG_APOLLO" = "y" ]; then
     define_bool CONFIG_FB_APOLLO y
   fi
@@ -177,8 +180,8 @@
 	 "$CONFIG_FB_VIRGE" = "y" -o "$CONFIG_FB_CYBER" = "y" -o \
 	 "$CONFIG_FB_VALKYRIE" = "y" -o "$CONFIG_FB_PLATINUM" = "y" -o \
          "$CONFIG_FB_IGA" = "y" -o "$CONFIG_FB_MATROX" = "y" -o \
-         "$CONFIG_FB_CT65550" = "y" -o "$CONFIG_FB_PM2" = "y" -o \
-         "$CONFIG_FB_SGIVW" = "y" ]; then
+	 "$CONFIG_FB_CT65550" = "y" -o "$CONFIG_FB_PM2" = "y" -o \
+	 "$CONFIG_FB_SGIVW" = "y" -o "$CONFIG_FB_CYBER2000" = "y" ]; then
       define_bool CONFIG_FBCON_CFB8 y
     else
       if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_ATARI" = "m" -o \
@@ -191,8 +194,8 @@
 	   "$CONFIG_FB_VIRGE" = "m" -o "$CONFIG_FB_CYBER" = "m" -o \
 	   "$CONFIG_FB_VALKYRIE" = "m" -o "$CONFIG_FB_PLATINUM" = "m" -o \
            "$CONFIG_FB_IGA" = "m" -o "$CONFIG_FB_MATROX" = "m" -o \
-           "$CONFIG_FB_CT65550" = "m" -o "$CONFIG_FB_PM2" = "m" -o \
-           "$CONFIG_FB_SGIVW" = "m" ]; then
+	   "$CONFIG_FB_CT65550" = "m" -o "$CONFIG_FB_PM2" = "m" -o \
+	   "$CONFIG_FB_SGIVW" = "m" -o "$CONFIG_FB_CYBER2000" = "m" ]; then
 	define_bool CONFIG_FBCON_CFB8 m
       fi
     fi
@@ -204,7 +207,8 @@
 	 "$CONFIG_FB_VIRGE" = "y" -o "$CONFIG_FB_CYBER" = "y" -o \
 	 "$CONFIG_FB_VALKYRIE" = "y" -o "$CONFIG_FB_PLATINUM" = "y" -o \
 	 "$CONFIG_FB_CT65550" = "y" -o "$CONFIG_FB_MATROX" = "y" -o \
-	 "$CONFIG_FB_PM2" = "y" -o "$CONFIG_FB_SGIVW" = "y" ]; then
+	 "$CONFIG_FB_PM2" = "y" -o "$CONFIG_FB_SGIVW" = "y" -o \
+	 "$CONFIG_FB_CYBER2000" = "y" ]; then
       define_bool CONFIG_FBCON_CFB16 y
     else
       if [ "$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_ATY" = "m" -o \
@@ -214,19 +218,22 @@
 	   "$CONFIG_FB_CONTROL" = "m" -o "$CONFIG_FB_CLGEN" = "m" -o \
 	   "$CONFIG_FB_VIRGE" = "m" -o "$CONFIG_FB_CYBER" = "m" -o \
  	   "$CONFIG_FB_VALKYRIE" = "m" -o "$CONFIG_FB_PLATINUM" = "m" -o \
- 	   "$CONFIG_FB_CT65550" = "m" -o "$CONFIG_FB_MATROX" = "m" -o \
-	   "$CONFIG_FB_PM2" = "m" -o "$CONFIG_FB_SGIVW" = "m" ]; then
+	   "$CONFIG_FB_CT65550" = "m" -o "$CONFIG_FB_MATROX" = "m" -o \
+	   "$CONFIG_FB_PM2" = "y" -o "$CONFIG_FB_SGIVW" = "m" -o \
+	   "$CONFIG_FB_CYBER2000" = "m" ]; then
 	define_bool CONFIG_FBCON_CFB16 m
       fi
     fi
     if [ "$CONFIG_FB_ATY" = "y" -o "$CONFIG_FB_VIRTUAL" = "y" -o \
 	 "$CONFIG_FB_CLGEN" = "y" -o "$CONFIG_FB_VESA" = "y" -o \
-	  "$CONFIG_FB_MATROX" = "y" -o "$CONFIG_FB_PM2" = "y" ]; then
+	  "$CONFIG_FB_MATROX" = "y" -o "$CONFIG_FB_PM2" = "y" -o \
+	 "$CONFIG_FB_CYBER2000" = "y" ]; then
       define_bool CONFIG_FBCON_CFB24 y
     else
       if [ "$CONFIG_FB_ATY" = "m" -o "$CONFIG_FB_VIRTUAL" = "m" -o \
 	   "$CONFIG_FB_CLGEN" = "m" -o "$CONFIG_FB_VESA" = "m" -o \
-	   "$CONFIG_FB_MATROX" = "m" -o "$CONFIG_FB_PM2" = "m" ]; then
+	   "$CONFIG_FB_MATROX" = "m" -o "$CONFIG_FB_PM2" = "m" -o \
+	   "$CONFIG_FB_CYBER2000" = "m" ]; then
 	define_bool CONFIG_FBCON_CFB24 m
       fi
     fi
@@ -323,7 +330,7 @@
       if [ "$CONFIG_AMIGA" = "y" ]; then
         define_bool CONFIG_FONT_PEARL_8x8 y
       fi
-      if [ "$CONFIG_ARM" = "y" ]; then
+      if [ "$CONFIG_ARM" = "y" -a "$CONFIG_ARCH_ACORN" = "y" ]; then
         define_bool CONFIG_FONT_ACORN_8x8 y
       fi
     fi
diff -u --recursive --new-file v2.3.0/linux/drivers/video/Makefile linux/drivers/video/Makefile
--- v2.3.0/linux/drivers/video/Makefile	Wed Mar 17 09:17:22 1999
+++ linux/drivers/video/Makefile	Tue May 11 16:30:45 1999
@@ -132,6 +132,14 @@
   endif
 endif
 
+ifeq ($(CONFIG_FB_CYBER2000),y)
+L_OBJS += cyber2000fb.o
+else
+  ifeq ($(CONFIG_FB_CYBER2000),m)
+  M_OBJS += cyber2000fb.o
+  endif
+endif
+
 ifeq ($(CONFIG_FB_SGIVW),y)
 L_OBJS += sgivwfb.o
 else
diff -u --recursive --new-file v2.3.0/linux/drivers/video/acornfb.c linux/drivers/video/acornfb.c
--- v2.3.0/linux/drivers/video/acornfb.c	Thu Oct  1 10:02:21 1998
+++ linux/drivers/video/acornfb.c	Tue May 11 16:30:45 1999
@@ -1,15 +1,22 @@
 /*
  * linux/drivers/video/acorn.c
  *
- * Copyright (C) 1998 Russell King
+ * Copyright (C) 1998,1999 Russell King
  *
  * Frame buffer code for Acorn platforms
+ *
+ * NOTE: Most of the modes with X!=640 will disappear shortly.
+ * NOTE: Startup setting of HS & VS polarity not supported.
+ *       (do we need to support it if we're coming up in 640x480?)
  */
+
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/string.h>
+#include <linux/ctype.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
 #include <linux/malloc.h>
@@ -21,245 +28,898 @@
 #include <asm/irq.h>
 #include <asm/uaccess.h>
 
+#include <video/fbcon.h>
 #include <video/fbcon-mfb.h>
 #include <video/fbcon-cfb2.h>
 #include <video/fbcon-cfb4.h>
 #include <video/fbcon-cfb8.h>
+#include <video/fbcon-cfb16.h>
+
+/*
+ * Default resolution.
+ * NOTE that it has to be supported in the table towards
+ * the end of this file.
+ */
+#define DEFAULT_XRES	640
+#define DEFAULT_YRES	480
+
+/*
+ * define this to debug the video mode selection
+ */
+#undef DEBUG_MODE_SELECTION
+
+#if defined(HAS_VIDC20)
+#define VIDC_PALETTE_SIZE	256
+#define VIDC_NAME		"VIDC20"
+#elif defined(HAS_VIDC)
+#include <asm/memc.h>
+#define VIDC_PALETTE_SIZE	16
+#define VIDC_NAME		"VIDC"
+#endif
 
-#define MAX_VIDC20_PALETTE	256
-#define MAX_VIDC_PALETTE	16
+#define EXTEND8(x) ((x)|(x)<<8)
+#define EXTEND4(x) ((x)|(x)<<4|(x)<<8|(x)<<16)
+
+struct vidc20_palette {
+	u_int red:8;
+	u_int green:8;
+	u_int blue:8;
+	u_int ext:4;
+	u_int unused:4;
+};
+
+struct vidc_palette {
+	u_int red:4;
+	u_int green:4;
+	u_int blue:4;
+	u_int trans:1;
+	u_int sbz1:13;
+	u_int reg:4;
+	u_int sbz2:2;
+};
+
+union palette {
+	struct vidc20_palette	vidc20;
+	struct vidc_palette	vidc;
+	u_int	p;
+};
 
 struct acornfb_par {
-	unsigned long screen_base;
-	unsigned int xres;
-	unsigned int yres;
-	unsigned char bits_per_pixel;
-	unsigned int palette_size;
+	unsigned long	screen_base;
+	unsigned long	screen_base_p;
+	unsigned long	screen_end;
+	unsigned long	screen_size;
+	unsigned int	dram_size;
+	unsigned int	vram_half_sam;
+	unsigned int	palette_size;
+	  signed int	montype;
+	  signed int	currcon;
+	unsigned int	allow_modeset	: 1;
+	unsigned int	using_vram	: 1;
+	unsigned int	dpms		: 1;
+
+	union palette palette[VIDC_PALETTE_SIZE];
 
 	union {
-		union {
-			struct {
-				unsigned long red:8;
-				unsigned long green:8;
-				unsigned long blue:8;
-				unsigned long ext:4;
-				unsigned long unused:4;
-			} d;
-			unsigned long p;
-		} vidc20[MAX_VIDC20_PALETTE];
-		union {
-			struct {
-				unsigned long red:4;
-				unsigned long green:4;
-				unsigned long blue:4;
-				unsigned long trans:1;
-				unsigned long unused:19;
-			} d;
-			unsigned long p;
-		} vidc[MAX_VIDC_PALETTE];
-	} palette;
+		unsigned short cfb16[16];
+		unsigned long  cfb32[16];
+	} cmap;
 };
 
-static int currcon = 0;
-static struct display disp;
+/*
+ * Translation from RISC OS monitor types to actual
+ * HSYNC and VSYNC frequency ranges.  These are
+ * probably not right...
+ */
+#define NR_MONTYPES	6
+static struct fb_monspecs monspecs[NR_MONTYPES] __initdata = {
+	{ 15625, 15625, 50, 50, 0 },	/* TV		*/
+	{     0, 99999,  0, 99, 0 },	/* Multi Freq	*/
+	{ 58608, 58608, 64, 64, 0 },	/* Hi-res mono	*/
+	{ 30000, 70000, 60, 60, 0 },	/* VGA		*/
+	{ 30000, 70000, 56, 75, 0 },	/* SVGA		*/
+	{ 30000, 70000, 60, 60, 0 }
+};
+
+static struct display global_disp;
 static struct fb_info fb_info;
 static struct acornfb_par current_par;
+static struct fb_var_screeninfo __initdata init_var = {};
 
-static int
-acornfb_open(struct fb_info *info, int user)
+extern int acornfb_depth;	/* set by setup.c */
+extern unsigned int vram_size;	/* set by setup.c */
+
+
+static struct vidc_timing {
+	u_int	h_cycle;
+	u_int	h_sync_width;
+	u_int	h_border_start;
+	u_int	h_display_start;
+	u_int	h_display_end;
+	u_int	h_border_end;
+	u_int	h_interlace;
+
+	u_int	v_cycle;
+	u_int	v_sync_width;
+	u_int	v_border_start;
+	u_int	v_display_start;
+	u_int	v_display_end;
+	u_int	v_border_end;
+
+	u_int	control;
+
+	/* VIDC20 only */
+	u_int	pll_ctl;
+} current_vidc;
+
+#ifdef HAS_VIDC
+
+#define VID_CTL_VS_NVSYNC	(1 << 3)
+#define VID_CTL_HS_NHSYNC	(1 << 2)
+#define VID_CTL_24MHz		(0)
+#define VID_CTL_25MHz		(1)
+#define VID_CTL_36MHz		(2)
+
+#define VIDC_CTRL_INTERLACE	(1 << 6)
+#define VIDC_CTRL_FIFO_0_4	(0 << 4)
+#define VIDC_CTRL_FIFO_1_5	(1 << 4)
+#define VIDC_CTRL_FIFO_2_6	(2 << 4)
+#define VIDC_CTRL_FIFO_3_7	(3 << 4)
+#define VIDC_CTRL_1BPP		(0 << 2)
+#define VIDC_CTRL_2BPP		(1 << 2)
+#define VIDC_CTRL_4BPP		(2 << 2)
+#define VIDC_CTRL_8BPP		(3 << 2)
+#define VIDC_CTRL_DIV3		(0 << 0)
+#define VIDC_CTRL_DIV2		(1 << 0)
+#define VIDC_CTRL_DIV1_5	(2 << 0)
+#define VIDC_CTRL_DIV1		(3 << 0)
+
+/* CTL     VIDC	Actual
+ * 24.000  0	 8.000
+ * 25.175  0	 8.392
+ * 36.000  0	12.000
+ * 24.000  1	12.000
+ * 25.175  1	12.588
+ * 24.000  2	16.000
+ * 25.175  2	16.783
+ * 36.000  1	18.000
+ * 24.000  3	24.000
+ * 36.000  2	24.000
+ * 25.175  3	25.175
+ * 36.000  3	36.000
+ */
+static struct pixclock {
+	u_long	min_clock;
+	u_long	max_clock;
+	u_int	vidc_ctl;
+	u_int	vid_ctl;
+} pixclocks[] = {
+	/* we allow +/-1% on these */
+	{ 123750, 126250, VIDC_CTRL_DIV3,   VID_CTL_24MHz },	/*  8.000MHz */
+	{  82500,  84167, VIDC_CTRL_DIV2,   VID_CTL_24MHz },	/* 12.000MHz */
+	{  61875,  63125, VIDC_CTRL_DIV1_5, VID_CTL_24MHz },	/* 16.000MHz */
+	{  41250,  42083, VIDC_CTRL_DIV1,   VID_CTL_24MHz },	/* 24.000MHz */
+#ifdef CONFIG_ARCH_A5K
+	{ 117974, 120357, VIDC_CTRL_DIV3,   VID_CTL_25MHz },	/*  8.392MHz */
+	{  78649,  80238, VIDC_CTRL_DIV2,   VID_CTL_25MHz },	/* 12.588MHz */
+	{  58987,  60178, VIDC_CTRL_DIV1_5, VID_CTL_25MHz },	/* 16.588MHz */
+	{  55000,  56111, VIDC_CTRL_DIV2,   VID_CTL_36MHz },	/* 18.000MHz */
+	{  39325,  40119, VIDC_CTRL_DIV1,   VID_CTL_25MHz },	/* 25.175MHz */
+	{  27500,  28055, VIDC_CTRL_DIV1,   VID_CTL_36MHz },	/* 36.000MHz */
+#endif
+	{ 0, }
+};
+
+static struct pixclock *
+acornfb_valid_pixrate(u_long pixclock)
 {
-	MOD_INC_USE_COUNT;
-	return 0;
+	u_int i;
+
+	for (i = 0; pixclocks[i].min_clock; i++)
+		if (pixclock > pixclocks[i].min_clock &&
+		    pixclock < pixclocks[i].max_clock)
+			return pixclocks + i;
+
+	return NULL;
 }
 
-static int
-acornfb_release(struct fb_info *info, int user)
+/* VIDC Rules:
+ * hcr  : must be even (interlace, hcr/2 must be even)
+ * hswr : must be even
+ * hdsr : must be odd
+ * hder : must be odd
+ *
+ * vcr  : must be odd
+ * vswr : >= 1
+ * vdsr : >= 1
+ * vder : >= vdsr
+ * if interlaced, then hcr/2 must be even
+ */
+static void
+acornfb_set_timing(struct fb_var_screeninfo *var)
 {
-	MOD_DEC_USE_COUNT;
-	return 0;
+	struct pixclock *pclk;
+	struct vidc_timing vidc;
+	u_int horiz_correction;
+	u_int sync_len, display_start, display_end, cycle;
+	u_int is_interlaced;
+	u_int vid_ctl, vidc_ctl;
+	u_int bandwidth;
+
+	memset(&vidc, 0, sizeof(vidc));
+
+	pclk = acornfb_valid_pixrate(var->pixclock);
+	vidc_ctl = pclk->vidc_ctl;
+	vid_ctl  = pclk->vid_ctl;
+
+	bandwidth = var->pixclock * 8 / var->bits_per_pixel;
+	/* 25.175, 4bpp = 79.444ns per byte, 317.776ns per word: fifo = 2,6 */
+	if (bandwidth > 71750)
+		vidc_ctl |= VIDC_CTRL_FIFO_2_6;
+	else if (bandwidth > 35875)
+		vidc_ctl |= VIDC_CTRL_FIFO_1_5;
+	else
+		vidc_ctl |= VIDC_CTRL_FIFO_0_4;
+
+	switch (var->bits_per_pixel) {
+	case 1:
+		horiz_correction = 19;
+		vidc_ctl |= VIDC_CTRL_1BPP;
+		break;
+
+	case 2:
+		horiz_correction = 11;
+		vidc_ctl |= VIDC_CTRL_2BPP;
+		break;
+
+	case 4:
+		horiz_correction = 7;
+		vidc_ctl |= VIDC_CTRL_4BPP;
+		break;
+
+	default:
+	case 8:
+		horiz_correction = 5;
+		vidc_ctl |= VIDC_CTRL_8BPP;
+		break;
+	}
+
+	if (!(var->sync & FB_SYNC_HOR_HIGH_ACT))
+		vid_ctl |= VID_CTL_HS_NHSYNC;
+
+	if (!(var->sync & FB_SYNC_VERT_HIGH_ACT))
+		vid_ctl |= VID_CTL_VS_NVSYNC;
+
+	sync_len	= var->hsync_len;
+	display_start	= sync_len + var->left_margin;
+	display_end	= display_start + var->xres;
+	cycle		= display_end + var->right_margin;
+
+	/* if interlaced, then hcr/2 must be even */
+	is_interlaced = (var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED;
+
+	if (is_interlaced) {
+		vidc_ctl |= VIDC_CTRL_INTERLACE;
+		if (cycle & 2) {
+			cycle += 2;
+			var->right_margin += 2;
+		}
+	}
+
+	vidc.h_cycle		= (cycle - 2) / 2;
+	vidc.h_sync_width	= (sync_len - 2) / 2;
+	vidc.h_border_start	= (display_start - 1) / 2;
+	vidc.h_display_start	= (display_start - horiz_correction) / 2;
+	vidc.h_display_end	= (display_end - horiz_correction) / 2;
+	vidc.h_border_end	= (display_end - 1) / 2;
+	vidc.h_interlace	= (vidc.h_cycle + 1) / 2;
+
+	sync_len	= var->vsync_len;
+	display_start	= sync_len + var->upper_margin;
+	display_end	= display_start + var->yres;
+	cycle		= display_end + var->lower_margin;
+
+	if (is_interlaced)
+		cycle = (cycle - 3) / 2;
+	else
+		cycle = cycle - 1;
+
+	vidc.v_cycle		= cycle;
+	vidc.v_sync_width	= sync_len - 1;
+	vidc.v_border_start	= display_start - 1;
+	vidc.v_display_start	= vidc.v_border_start;
+	vidc.v_display_end	= display_end - 1;
+	vidc.v_border_end	= vidc.v_display_end;
+
+#ifdef CONFIG_ARCH_A5K
+	outb(vid_ctl, IOEB_VID_CTL);
+#endif
+	if (memcmp(&current_vidc, &vidc, sizeof(vidc))) {
+		current_vidc = vidc;
+
+		outl(0xe0000000 | vidc_ctl,			IO_VIDC_BASE);
+		outl(0x80000000 | (vidc.h_cycle << 14),		IO_VIDC_BASE);
+		outl(0x84000000 | (vidc.h_sync_width << 14),	IO_VIDC_BASE);
+		outl(0x88000000 | (vidc.h_border_start << 14),	IO_VIDC_BASE);
+		outl(0x8c000000 | (vidc.h_display_start << 14),	IO_VIDC_BASE);
+		outl(0x90000000 | (vidc.h_display_end << 14),	IO_VIDC_BASE);
+		outl(0x94000000 | (vidc.h_border_end << 14),	IO_VIDC_BASE);
+		outl(0x98000000,				IO_VIDC_BASE);
+		outl(0x9c000000 | (vidc.h_interlace << 14),	IO_VIDC_BASE);
+		outl(0xa0000000 | (vidc.v_cycle << 14),		IO_VIDC_BASE);
+		outl(0xa4000000 | (vidc.v_sync_width << 14),	IO_VIDC_BASE);
+		outl(0xa8000000 | (vidc.v_border_start << 14),	IO_VIDC_BASE);
+		outl(0xac000000 | (vidc.v_display_start << 14),	IO_VIDC_BASE);
+		outl(0xb0000000 | (vidc.v_display_end << 14),	IO_VIDC_BASE);
+		outl(0xb4000000 | (vidc.v_border_end << 14),	IO_VIDC_BASE);
+		outl(0xb8000000,				IO_VIDC_BASE);
+		outl(0xbc000000,				IO_VIDC_BASE);
+	}
+#ifdef DEBUG_MODE_SELECTION
+	printk(KERN_DEBUG "VIDC registers for %dx%dx%d:\n", var->xres,
+	       var->yres, var->bits_per_pixel);
+	printk(KERN_DEBUG " H-cycle          : %d\n", vidc.h_cycle);
+	printk(KERN_DEBUG " H-sync-width     : %d\n", vidc.h_sync_width);
+	printk(KERN_DEBUG " H-border-start   : %d\n", vidc.h_border_start);
+	printk(KERN_DEBUG " H-display-start  : %d\n", vidc.h_display_start);
+	printk(KERN_DEBUG " H-display-end    : %d\n", vidc.h_display_end);
+	printk(KERN_DEBUG " H-border-end     : %d\n", vidc.h_border_end);
+	printk(KERN_DEBUG " H-interlace      : %d\n", vidc.h_interlace);
+	printk(KERN_DEBUG " V-cycle          : %d\n", vidc.v_cycle);
+	printk(KERN_DEBUG " V-sync-width     : %d\n", vidc.v_sync_width);
+	printk(KERN_DEBUG " V-border-start   : %d\n", vidc.v_border_start);
+	printk(KERN_DEBUG " V-display-start  : %d\n", vidc.v_display_start);
+	printk(KERN_DEBUG " V-display-end    : %d\n", vidc.v_display_end);
+	printk(KERN_DEBUG " V-border-end     : %d\n", vidc.v_border_end);
+	printk(KERN_DEBUG " VIDC Ctrl (E)    : 0x%08X\n", vidc_ctl);
+	printk(KERN_DEBUG " IOEB Ctrl        : 0x%08X\n", vid_ctl);
+#endif
+}
+
+static inline void
+acornfb_palette_write(u_int regno, union palette pal)
+{
+	outl(pal.p, IO_VIDC_BASE);
+}
+
+static inline union palette
+acornfb_palette_encode(u_int regno, u_int red, u_int green, u_int blue,
+		       u_int trans)
+{
+	union palette pal;
+
+	pal.p = 0;
+	pal.vidc.reg   = regno;
+	pal.vidc.red   = red >> 12;
+	pal.vidc.green = green >> 12;
+	pal.vidc.blue  = blue >> 12;
+	return pal;
 }
 
 static void
-acornfb_encode_var(struct fb_var_screeninfo *var, struct acornfb_par *par)
+acornfb_palette_decode(u_int regno, u_int *red, u_int *green, u_int *blue,
+		       u_int *trans)
 {
-	var->xres		= par->xres;
-	var->yres		= par->yres;
-	var->xres_virtual	= par->xres;
-	var->yres_virtual	= par->yres;
-	var->xoffset		= 0;
-	var->yoffset		= 0;
-	var->bits_per_pixel	= par->bits_per_pixel;
-	var->grayscale		= 0;
-	var->red.offset		= 0;
-	var->red.length		= 8;
-	var->red.msb_right	= 0;
-	var->green.offset	= 0;
-	var->green.length	= 8;
-	var->green.msb_right	= 0;
-	var->blue.offset	= 0;
-	var->blue.length	= 8;
-	var->blue.msb_right	= 0;
-	var->transp.offset	= 0;
-	var->transp.length	= 4;
-	var->transp.msb_right	= 0;
-	var->nonstd		= 0;
-	var->activate		= FB_ACTIVATE_NOW;
-	var->height		= -1;
-	var->width		= -1;
-	var->vmode		= FB_VMODE_NONINTERLACED;
-	var->pixclock		= 1;
-	var->sync		= 0;
-	var->left_margin	= 0;
-	var->right_margin	= 0;
-	var->upper_margin	= 0;
-	var->lower_margin	= 0;
-	var->hsync_len		= 0;
-	var->vsync_len		= 0;
+	*red   = EXTEND4(current_par.palette[regno].vidc.red);
+	*green = EXTEND4(current_par.palette[regno].vidc.green);
+	*blue  = EXTEND4(current_par.palette[regno].vidc.blue);
+	*trans = current_par.palette[regno].vidc.trans ? -1 : 0;
 }
+#endif
 
-static int
-acornfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
+#ifdef HAS_VIDC20
+/*
+ * VIDC20 registers
+ */
+#define VIDC20_CTRL		0xe0000000
+#define VIDC20_CTRL_PIX_VCLK	(0 << 0)
+#define VIDC20_CTRL_PIX_HCLK	(1 << 0)
+#define VIDC20_CTRL_PIX_RCLK	(2 << 0)
+#define VIDC20_CTRL_PIX_CK	(0 << 2)
+#define VIDC20_CTRL_PIX_CK2	(1 << 2)
+#define VIDC20_CTRL_PIX_CK3	(2 << 2)
+#define VIDC20_CTRL_PIX_CK4	(3 << 2)
+#define VIDC20_CTRL_PIX_CK5	(4 << 2)
+#define VIDC20_CTRL_PIX_CK6	(5 << 2)
+#define VIDC20_CTRL_PIX_CK7	(6 << 2)
+#define VIDC20_CTRL_PIX_CK8	(7 << 2)
+#define VIDC20_CTRL_1BPP	(0 << 5)
+#define VIDC20_CTRL_2BPP	(1 << 5)
+#define VIDC20_CTRL_4BPP	(2 << 5)
+#define VIDC20_CTRL_8BPP	(3 << 5)
+#define VIDC20_CTRL_16BPP	(4 << 5)
+#define VIDC20_CTRL_32BPP	(6 << 5)
+#define VIDC20_CTRL_FIFO_NS	(0 << 8)
+#define VIDC20_CTRL_FIFO_4	(1 << 8)
+#define VIDC20_CTRL_FIFO_8	(2 << 8)
+#define VIDC20_CTRL_FIFO_12	(3 << 8)
+#define VIDC20_CTRL_FIFO_16	(4 << 8)
+#define VIDC20_CTRL_FIFO_20	(5 << 8)
+#define VIDC20_CTRL_FIFO_24	(6 << 8)
+#define VIDC20_CTRL_FIFO_28	(7 << 8)
+#define VIDC20_CTRL_INT		(1 << 12)
+#define VIDC20_CTRL_DUP		(1 << 13)
+#define VIDC20_CTRL_PDOWN	(1 << 14)
+
+#define VIDC20_ECTL		0xc0000000
+#define VIDC20_ECTL_REG(x)	((x) & 0xf3)
+#define VIDC20_ECTL_ECK		(1 << 2)
+#define VIDC20_ECTL_REDPED	(1 << 8)
+#define VIDC20_ECTL_GREENPED	(1 << 9)
+#define VIDC20_ECTL_BLUEPED	(1 << 10)
+#define VIDC20_ECTL_DAC		(1 << 12)
+#define VIDC20_ECTL_LCDGS	(1 << 13)
+#define VIDC20_ECTL_HRM		(1 << 14)
+
+#define VIDC20_ECTL_HS_MASK	(3 << 16)
+#define VIDC20_ECTL_HS_HSYNC	(0 << 16)
+#define VIDC20_ECTL_HS_NHSYNC	(1 << 16)
+#define VIDC20_ECTL_HS_CSYNC	(2 << 16)
+#define VIDC20_ECTL_HS_NCSYNC	(3 << 16)
+
+#define VIDC20_ECTL_VS_MASK	(3 << 18)
+#define VIDC20_ECTL_VS_VSYNC	(0 << 18)
+#define VIDC20_ECTL_VS_NVSYNC	(1 << 18)
+#define VIDC20_ECTL_VS_CSYNC	(2 << 18)
+#define VIDC20_ECTL_VS_NCSYNC	(3 << 18)
+
+#define VIDC20_DCTL		0xf0000000
+/* 0-9 = number of words in scanline */
+#define VIDC20_DCTL_SNA		(1 << 12)
+#define VIDC20_DCTL_HDIS	(1 << 13)
+#define VIDC20_DCTL_BUS_NS	(0 << 16)
+#define VIDC20_DCTL_BUS_D31_0	(1 << 16)
+#define VIDC20_DCTL_BUS_D63_32	(2 << 16)
+#define VIDC20_DCTL_BUS_D63_0	(3 << 16)
+#define VIDC20_DCTL_VRAM_DIS	(0 << 18)
+#define VIDC20_DCTL_VRAM_PXCLK	(1 << 18)
+#define VIDC20_DCTL_VRAM_PXCLK2	(2 << 18)
+#define VIDC20_DCTL_VRAM_PXCLK4	(3 << 18)
+
+#define acornfb_valid_pixrate(rate) (1)
+
+/*
+ * Try to find the best PLL parameters for the pixel clock.
+ * This algorithm seems to give best predictable results,
+ * and produces the same values as detailed in the VIDC20
+ * data sheet.
+ */
+static inline u_int
+acornfb_vidc20_find_pll(u_int pixclk)
 {
-	struct acornfb_par *par = &current_par;
-	unsigned int line_length;
+	u_int r, best_r = 2, best_v = 2;
+	int best_d = 0x7fffffff;
 
-	memset(fix, 0, sizeof(struct fb_fix_screeninfo));
-	strcpy(fix->id, "Acorn");
+	for (r = 2; r <= 32; r++) {
+		u_int rr, v, p;
+		int d;
 
-	line_length = par->xres * par->bits_per_pixel / 8;
+		rr = 41667 * r;
 
-	fix->smem_start	 = (char *)SCREEN2_BASE;
-	fix->smem_len	 = (((line_length * par->yres) - 1) | (PAGE_SIZE - 1)) + 1;
-	fix->type	 = FB_TYPE_PACKED_PIXELS;
-	fix->type_aux	 = 0;
-	fix->visual	 = FB_VISUAL_PSEUDOCOLOR;
-	fix->xpanstep	 = 0;
-	fix->ypanstep	 = 0;
-	fix->ywrapstep	 = 1;
-	fix->line_length = line_length;
-	fix->accel	 = FB_ACCEL_NONE;
+		v = (rr + pixclk / 2) / pixclk;
 
-	return 0;
+		if (v > 32 || v < 2)
+			continue;
+
+		p = (rr + v / 2) / v;
+
+		d = pixclk - p;
+
+		if (d < 0)
+			d = -d;
+
+		if (d < best_d) {
+			best_d = d;
+			best_v = v - 1;
+			best_r = r - 1;
+		}
+
+		if (d == 0)
+			break;
+	}
+
+	return best_v << 8 | best_r;
 }
 
-static int
-acornfb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
+static inline void
+acornfb_vidc20_find_rates(struct vidc_timing *vidc,
+			  struct fb_var_screeninfo *var)
 {
-	if (con == -1) {
-		acornfb_encode_var(var, &current_par);
+	u_int div, bandwidth;
+
+	/* Select pixel-clock divisor to keep PLL in range */
+	div = var->pixclock / 9090; /*9921*/
+
+	/* Limit divisor */
+	if (div == 0)
+		div = 1;
+	if (div > 8)
+		div = 8;
+
+	/* Encode divisor to VIDC20 setting */
+	switch (div) {
+	case 1:	vidc->control |= VIDC20_CTRL_PIX_CK;  break;
+	case 2:	vidc->control |= VIDC20_CTRL_PIX_CK2; break;
+	case 3:	vidc->control |= VIDC20_CTRL_PIX_CK3; break;
+	case 4:	vidc->control |= VIDC20_CTRL_PIX_CK4; break;
+	case 5:	vidc->control |= VIDC20_CTRL_PIX_CK5; break;
+	case 6:	vidc->control |= VIDC20_CTRL_PIX_CK6; break;
+	case 7:	vidc->control |= VIDC20_CTRL_PIX_CK7; break;
+	case 8: vidc->control |= VIDC20_CTRL_PIX_CK8; break;
+	}
+
+	/* Calculate bandwidth */
+	bandwidth = var->pixclock * 8 / var->bits_per_pixel;
+
+	/* Encode bandwidth as VIDC20 setting */
+	if (bandwidth > 16667*2)
+		vidc->control |= VIDC20_CTRL_FIFO_16;
+	else if (bandwidth > 13333*2)
+		vidc->control |= VIDC20_CTRL_FIFO_20;
+	else if (bandwidth > 11111*2)
+		vidc->control |= VIDC20_CTRL_FIFO_24;
+	else
+		vidc->control |= VIDC20_CTRL_FIFO_28;
+
+	/* Find the PLL values */
+	vidc->pll_ctl  = acornfb_vidc20_find_pll(var->pixclock / div);
+}
+
+/* VIDC20 has a different set of rules from the VIDC:
+ *  hcr  : must be multiple of 4
+ *  hswr : must be even
+ *  hdsr : must be even
+ *  hder : must be even
+ *  vcr  : >= 2, (interlace, must be odd)
+ *  vswr : >= 1
+ *  vdsr : >= 1
+ *  vder : >= vdsr
+ */
+static void
+acornfb_set_timing(struct fb_var_screeninfo *var)
+{
+	struct vidc_timing vidc;
+	u_int vcr, fsize;
+	u_int ext_ctl, dat_ctl;
+	u_int words_per_line;
+
+	memset(&vidc, 0, sizeof(vidc));
+
+	vidc.h_sync_width	= var->hsync_len - 8;
+	vidc.h_border_start	= vidc.h_sync_width + var->left_margin + 8 - 12;
+	vidc.h_display_start	= vidc.h_border_start + 12 - 18;
+	vidc.h_display_end	= vidc.h_display_start + var->xres;
+	vidc.h_border_end	= vidc.h_display_end + 18 - 12;
+	vidc.h_cycle		= vidc.h_border_end + var->right_margin + 12 - 8;
+	vidc.h_interlace	= vidc.h_cycle / 2;
+	vidc.v_sync_width	= var->vsync_len - 1;
+	vidc.v_border_start	= vidc.v_sync_width + var->upper_margin;
+	vidc.v_display_start	= vidc.v_border_start;
+	vidc.v_display_end	= vidc.v_display_start + var->yres;
+	vidc.v_border_end	= vidc.v_display_end;
+	vidc.control		= VIDC20_CTRL_PIX_VCLK;
+
+	vcr = var->vsync_len + var->upper_margin + var->yres +
+	      var->lower_margin;
+
+	if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
+		vidc.v_cycle = (vcr - 3) / 2;
+		vidc.control |= VIDC20_CTRL_INT;
 	} else
-		*var = fb_display[con].var;
-	return 0;
+		vidc.v_cycle = vcr - 2;
+
+	switch (var->bits_per_pixel) {
+	case  1: vidc.control |= VIDC20_CTRL_1BPP;	break;
+	case  2: vidc.control |= VIDC20_CTRL_2BPP;	break;
+	case  4: vidc.control |= VIDC20_CTRL_4BPP;	break;
+	default:
+	case  8: vidc.control |= VIDC20_CTRL_8BPP;	break;
+	case 16: vidc.control |= VIDC20_CTRL_16BPP;	break;
+	case 32: vidc.control |= VIDC20_CTRL_32BPP;	break;
+	}
+
+	acornfb_vidc20_find_rates(&vidc, var);
+	fsize = var->vsync_len + var->upper_margin + var->lower_margin - 1;
+
+	if (memcmp(&current_vidc, &vidc, sizeof(vidc))) {
+		current_vidc = vidc;
+
+		outl(VIDC20_CTRL| vidc.control,		IO_VIDC_BASE);
+		outl(0xd0000000 | vidc.pll_ctl,		IO_VIDC_BASE);
+		outl(0x80000000 | vidc.h_cycle,		IO_VIDC_BASE);
+		outl(0x81000000 | vidc.h_sync_width,	IO_VIDC_BASE);
+		outl(0x82000000 | vidc.h_border_start,	IO_VIDC_BASE);
+		outl(0x83000000 | vidc.h_display_start,	IO_VIDC_BASE);
+		outl(0x84000000 | vidc.h_display_end,	IO_VIDC_BASE);
+		outl(0x85000000 | vidc.h_border_end,	IO_VIDC_BASE);
+		outl(0x86000000,			IO_VIDC_BASE);
+		outl(0x87000000 | vidc.h_interlace,	IO_VIDC_BASE);
+		outl(0x90000000 | vidc.v_cycle,		IO_VIDC_BASE);
+		outl(0x91000000 | vidc.v_sync_width,	IO_VIDC_BASE);
+		outl(0x92000000 | vidc.v_border_start,	IO_VIDC_BASE);
+		outl(0x93000000 | vidc.v_display_start,	IO_VIDC_BASE);
+		outl(0x94000000 | vidc.v_display_end,	IO_VIDC_BASE);
+		outl(0x95000000 | vidc.v_border_end,	IO_VIDC_BASE);
+		outl(0x96000000,			IO_VIDC_BASE);
+		outl(0x97000000,			IO_VIDC_BASE);
+	}
+
+	outl(fsize, IOMD_FSIZE);
+
+	ext_ctl = VIDC20_ECTL_DAC | VIDC20_ECTL_REG(3);
+
+	if (var->sync & FB_SYNC_HOR_HIGH_ACT)
+		ext_ctl |= VIDC20_ECTL_HS_HSYNC;
+	else
+		ext_ctl |= VIDC20_ECTL_HS_NHSYNC;
+
+	if (var->sync & FB_SYNC_VERT_HIGH_ACT)
+		ext_ctl |= VIDC20_ECTL_VS_VSYNC;
+	else
+		ext_ctl |= VIDC20_ECTL_VS_NVSYNC;
+
+	outl(VIDC20_ECTL | ext_ctl, IO_VIDC_BASE);
+
+	words_per_line = var->xres * var->bits_per_pixel / 32;
+
+	if (current_par.using_vram && current_par.screen_size == 2048*1024)
+		words_per_line /= 2;
+
+	/* RiscPC doesn't use the VIDC's VRAM control. */
+	dat_ctl = VIDC20_DCTL_VRAM_DIS | VIDC20_DCTL_SNA | words_per_line;
+
+	/* The data bus width is dependent on both the type
+	 * and amount of video memory.
+	 *     DRAM	32bit low
+	 * 1MB VRAM	32bit
+	 * 2MB VRAM	64bit
+	 */
+	if (current_par.using_vram && current_par.vram_half_sam == 2048) {
+		dat_ctl |= VIDC20_DCTL_BUS_D63_0;
+	} else 
+		dat_ctl |= VIDC20_DCTL_BUS_D31_0;
+
+	outl(VIDC20_DCTL | dat_ctl, IO_VIDC_BASE);
+
+#ifdef DEBUG_MODE_SELECTION
+	printk(KERN_DEBUG "VIDC registers for %dx%dx%d:\n", var->xres,
+	       var->yres, var->bits_per_pixel);
+	printk(KERN_DEBUG " H-cycle          : %d\n", vidc.h_cycle);
+	printk(KERN_DEBUG " H-sync-width     : %d\n", vidc.h_sync_width);
+	printk(KERN_DEBUG " H-border-start   : %d\n", vidc.h_border_start);
+	printk(KERN_DEBUG " H-display-start  : %d\n", vidc.h_display_start);
+	printk(KERN_DEBUG " H-display-end    : %d\n", vidc.h_display_end);
+	printk(KERN_DEBUG " H-border-end     : %d\n", vidc.h_border_end);
+	printk(KERN_DEBUG " H-interlace      : %d\n", vidc.h_interlace);
+	printk(KERN_DEBUG " V-cycle          : %d\n", vidc.v_cycle);
+	printk(KERN_DEBUG " V-sync-width     : %d\n", vidc.v_sync_width);
+	printk(KERN_DEBUG " V-border-start   : %d\n", vidc.v_border_start);
+	printk(KERN_DEBUG " V-display-start  : %d\n", vidc.v_display_start);
+	printk(KERN_DEBUG " V-display-end    : %d\n", vidc.v_display_end);
+	printk(KERN_DEBUG " V-border-end     : %d\n", vidc.v_border_end);
+	printk(KERN_DEBUG " Ext Ctrl  (C)    : 0x%08X\n", ext_ctl);
+	printk(KERN_DEBUG " PLL Ctrl  (D)    : 0x%08X\n", vidc.pll_ctl);
+	printk(KERN_DEBUG " Ctrl      (E)    : 0x%08X\n", vidc.control);
+	printk(KERN_DEBUG " Data Ctrl (F)    : 0x%08X\n", dat_ctl);
+	printk(KERN_DEBUG " Fsize            : 0x%08X\n", fsize);
+#endif
 }
 
-static int
-acornfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
+static inline void
+acornfb_palette_write(u_int regno, union palette pal)
 {
-	return 0;
+	outl(0x10000000 | regno, IO_VIDC_BASE);
+	outl(pal.p, IO_VIDC_BASE);
+}
+
+static inline union palette
+acornfb_palette_encode(u_int regno, u_int red, u_int green, u_int blue,
+		       u_int trans)
+{
+	union palette pal;
+
+	pal.p = 0;
+	pal.vidc20.red   = red >> 8;
+	pal.vidc20.green = green >> 8;
+	pal.vidc20.blue  = blue >> 8;
+	return pal;
 }
 
 static void
-acornfb_set_disp(int con)
+acornfb_palette_decode(u_int regno, u_int *red, u_int *green, u_int *blue,
+		       u_int *trans)
 {
-	struct fb_fix_screeninfo fix;
-	struct display *display;
+	*red   = EXTEND8(current_par.palette[regno].vidc20.red);
+	*green = EXTEND8(current_par.palette[regno].vidc20.green);
+	*blue  = EXTEND8(current_par.palette[regno].vidc20.blue);
+	*trans = EXTEND4(current_par.palette[regno].vidc20.ext);
+}
+#endif
 
-	if (con >= 0)
-		display = &fb_display[con];
+/*
+ * Before selecting the timing parameters, adjust
+ * the resolution to fit the rules.
+ */
+static void
+acornfb_pre_adjust_timing(struct fb_var_screeninfo *var, int con)
+{
+	u_int font_line_len;
+	u_int fontht;
+	u_int sam_size, min_size, size;
+	u_int nr_y;
+
+	/* xres must be even */
+	var->xres = (var->xres + 1) & ~1;
+
+	/*
+	 * We don't allow xres_virtual to differ from xres
+	 */
+	var->xres_virtual = var->xres;
+	var->xoffset = 0;
+
+	/*
+	 * Find the font height
+	 */
+	if (con == -1)
+		fontht = fontheight(&global_disp);
 	else
-		display = &disp;
+		fontht = fontheight(fb_display + con);
 
-	current_par.xres = 8 * ORIG_VIDEO_COLS;
-	current_par.yres = 8 * ORIG_VIDEO_LINES;
-	current_par.bits_per_pixel = 8;
-	current_par.palette_size = MAX_VIDC20_PALETTE;
-
-	acornfb_get_fix(&fix, con, 0);
-
-	acornfb_get_var(&display->var, con, 0);
-
-	display->cmap.start	= 0;
-	display->cmap.len	= 0;
-	display->cmap.red	= NULL;
-	display->cmap.green	= NULL;
-	display->cmap.blue	= NULL;
-	display->cmap.transp	= NULL;
-	display->screen_base	= fix.smem_start;
-	display->visual		= fix.visual;
-	display->type		= fix.type;
-	display->type_aux	= fix.type_aux;
-	display->ypanstep	= fix.ypanstep;
-	display->ywrapstep	= fix.ywrapstep;
-	display->line_length	= fix.line_length;
-	display->can_soft_blank	= 0;
-	display->inverse	= 0;
+	if (fontht == 0)
+		fontht = 8;
 
-	outl(SCREEN_START, VDMA_START);
-	outl(SCREEN_START + fix.smem_len - VDMA_XFERSIZE, VDMA_END);
-	outl(SCREEN_START, VDMA_INIT);
+	if (current_par.using_vram)
+		sam_size = current_par.vram_half_sam * 2;
+	else
+		sam_size = 16;
 
-	switch (display->var.bits_per_pixel) {
-#ifdef FBCON_HAS_MFB
-	case 1:
-		display->dispsw = &fbcon_mfb;
-		break;
-#endif
-#ifdef FBCON_HAS_CFB2
-	case 2:
-		display->dispsw = &fbcon_cfb2;
-		break;
-#endif
-#ifdef FBCON_HAS_CFB4
-	case 4:
-		display->dispsw = &fbcon_cfb4;
-		break;
+	/*
+	 * Now, find a value for yres_virtual which allows
+	 * us to do ywrap scrolling.  The value of
+	 * yres_virtual must be such that the end of the
+	 * displayable frame buffer must be aligned with
+	 * the start of a font line.
+	 */
+	font_line_len = var->xres * var->bits_per_pixel * fontht / 8;
+	min_size = var->xres * var->yres * var->bits_per_pixel / 8;
+
+	/* Find int 'y', such that y * fll == s * sam < maxsize
+	 * y = s * sam / fll; s = maxsize / sam
+	 */
+	for (size = current_par.screen_size; min_size <= size;
+	     size -= sam_size) {
+		nr_y = size / font_line_len;
+
+		if (nr_y * font_line_len == size)
+			break;
+	}
+
+	if (min_size > size) {
+		/*
+		 * failed, use ypan
+		 */
+		size = current_par.screen_size;
+		var->yres_virtual = size / (font_line_len / fontht);
+	} else
+		var->yres_virtual = nr_y * fontht;
+
+	current_par.screen_end = current_par.screen_base_p + size;
+
+	/*
+	 * Fix yres & yoffset if needed.
+	 */
+	if (var->yres > var->yres_virtual)
+		var->yres = var->yres_virtual;
+
+	if (var->vmode & FB_VMODE_YWRAP) {
+		if (var->yoffset > var->yres_virtual)
+			var->yoffset = var->yres_virtual;
+	} else {
+		if (var->yoffset + var->yres > var->yres_virtual)
+			var->yoffset = var->yres_virtual - var->yres;
+	}
+}
+
+/*
+ * After selecting the timing parameters, adjust
+ * the timing to suit the chip.
+ * NOTE! Only minor adjustments should be made here.
+ */
+static void
+acornfb_post_adjust_timing(struct fb_var_screeninfo *var)
+{
+	/* hsync_len must be even */
+	var->hsync_len = (var->hsync_len + 1) & ~1;
+
+#ifdef HAS_VIDC
+	/* left_margin must be odd */
+	if ((var->left_margin & 1) == 0) {
+		var->left_margin -= 1;
+		var->right_margin += 1;
+	}
+
+	/* right_margin must be odd */
+	var->right_margin |= 1;
+#elif defined(HAS_VIDC20)
+	/* left_margin must be even */
+	if (var->left_margin & 1) {
+		var->left_margin += 1;
+		var->right_margin -= 1;
+	}
+
+	/* right_margin must be even */
+	if (var->right_margin & 1)
+		var->right_margin += 1;
 #endif
-#ifdef FBCON_HAS_CFB8
-	case 8:
-		display->dispsw = &fbcon_cfb8;
-		break;
+
+	if (var->vsync_len < 1)
+		var->vsync_len = 1;
+}
+
+static inline void
+acornfb_update_dma(struct fb_var_screeninfo *var)
+{
+	int off = (var->yoffset * var->xres_virtual *
+		   var->bits_per_pixel) >> 3;
+
+#if defined(HAS_MEMC)
+	memc_write(VDMA_INIT, off >> 2);
+#elif defined(HAS_IOMD)
+	outl(current_par.screen_base_p + off, IOMD_VIDINIT);
 #endif
-	default:
-		display->dispsw = &fbcon_dummy;
-		break;
-	}
 }
 
 static int
-acornfb_vidc20_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, u_int *trans, struct fb_info *info)
+acornfb_open(struct fb_info *info, int user)
 {
-	int t;
+	MOD_INC_USE_COUNT;
+	return 0;
+}
+
+static int
+acornfb_release(struct fb_info *info, int user)
+{
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
 
+static int
+acornfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
+		  u_int *trans, struct fb_info *info)
+{
 	if (regno >= current_par.palette_size)
 		return 1;
-	t = current_par.palette.vidc20[regno].d.red;
-	*red = (t << 8) | t;
-	t = current_par.palette.vidc20[regno].d.green;
-	*green = (t << 8) | t;
-	t = current_par.palette.vidc20[regno].d.blue;
-	*blue = (t << 8) | t;
-	t = current_par.palette.vidc20[regno].d.ext;
-	t |= t << 4;
-	*transp = (t << 8) | t;
+
+	acornfb_palette_decode(regno, red, green, blue, trans);
+
 	return 0;
 }
 
 static int
-acornfb_vidc20_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int trans, struct fb_info *info)
+acornfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+		  u_int trans, struct fb_info *info)
 {
+	union palette pal;
+
 	if (regno >= current_par.palette_size)
 		return 1;
 
-	red >>= 8;
-	green >>= 8;
-	blue >>= 8;
-	current_par.palette.vidc20[regno].p = 0;
-	current_par.palette.vidc20[regno].d.red   = red;
-	current_par.palette.vidc20[regno].d.green = green;
-	current_par.palette.vidc20[regno].d.blue  = blue;
+	pal = acornfb_palette_encode(regno, red, green, blue, trans);
+	acornfb_palette_write(regno, pal);
+	current_par.palette[regno] = pal;
+
+	if (regno < 16) {
+		switch (info->disp->var.bits_per_pixel) {
+#ifdef FBCON_HAS_CFB16
+		case 16:	/* RGB555 */
+			current_par.cmap.cfb16[regno] = (regno << 10) | (regno << 5) | regno;
+			break;
+#endif
 
-	outl(0x10000000 | regno, VIDC_BASE);
-	outl(current_par.palette.vidc20[regno].p, VIDC_BASE);
+		default:
+			break;
+		}
+	}
 
 	return 0;
 }
@@ -270,8 +930,8 @@
 {
 	int err = 0;
 
-	if (con == currcon)
-		err = fb_get_cmap(cmap, kspc, acornfb_vidc20_getcolreg, info);
+	if (con == current_par.currcon)
+		err = fb_get_cmap(cmap, kspc, acornfb_getcolreg, info);
 	else if (fb_display[con].cmap.len)
 		fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
 	else
@@ -290,8 +950,8 @@
 		err = fb_alloc_cmap(&fb_display[con].cmap,
 				    current_par.palette_size, 0);
 	if (!err) {
-		if (con == currcon)
-			err = fb_set_cmap(cmap, kspc, acornfb_vidc20_setcolreg,
+		if (con == current_par.currcon)
+			err = fb_set_cmap(cmap, kspc, acornfb_setcolreg,
 					  info);
 		else
 			fb_copy_cmap(cmap, &fb_display[con].cmap,
@@ -301,13 +961,279 @@
 }
 
 static int
+acornfb_decode_var(struct fb_var_screeninfo *var, int con, int *visual)
+{
+	switch (var->bits_per_pixel) {
+#ifdef FBCON_HAS_MFB
+	case 1:
+		*visual = FB_VISUAL_MONO10;
+		break;
+#endif
+#ifdef FBCON_HAS_CFB8
+	case 8:
+#ifdef HAS_VIDC
+		*visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
+#else
+		*visual = FB_VISUAL_PSEUDOCOLOR;
+#endif
+		break;
+#endif
+#ifdef FBCON_HAS_CFB4
+	case 4:
+		*visual = FB_VISUAL_PSEUDOCOLOR;
+		break;
+#endif
+#ifdef FBCON_HAS_CFB2
+	case 2:
+		*visual = FB_VISUAL_PSEUDOCOLOR;
+		break;
+#endif
+	case 16:
+	case 24:
+	case 32:
+		*visual = FB_VISUAL_TRUECOLOR;
+	default:
+		return -EINVAL;
+	}
+
+	if (!acornfb_valid_pixrate(var->pixclock))
+		return -EINVAL;
+
+	/*
+	 * Adjust the resolution before using it.
+	 */
+	acornfb_pre_adjust_timing(var, con);
+
+#if defined(HAS_VIDC20)
+	var->red.length	   = 8;
+	var->transp.length = 4;
+#elif defined(HAS_VIDC)
+	var->red.length	   = 4;
+	var->transp.length = 1;
+#endif
+	var->green = var->red;
+	var->blue  = var->red;
+
+	/*
+	 * Now adjust the timing parameters
+	 */
+	acornfb_post_adjust_timing(var);
+
+	return 0;
+}
+
+static int
+acornfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
+{
+	struct display *display;
+
+	memset(fix, 0, sizeof(struct fb_fix_screeninfo));
+	strcpy(fix->id, "Acorn");
+
+	if (con >= 0)
+		display = fb_display + con;
+	else
+		display = &global_disp;
+
+	fix->smem_start	 = (char *)current_par.screen_base_p;
+	fix->smem_len	 = current_par.screen_size;
+	fix->type	 = display->type;
+	fix->type_aux	 = display->type_aux;
+	fix->xpanstep	 = 0;
+	fix->ypanstep	 = display->ypanstep;
+	fix->ywrapstep	 = display->ywrapstep;
+	fix->visual	 = display->visual;
+	fix->line_length = display->line_length;
+	fix->accel	 = FB_ACCEL_NONE;
+
+	return 0;
+}
+
+static int
+acornfb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
+{
+	if (con == -1) {
+		*var = global_disp.var;
+	} else
+		*var = fb_display[con].var;
+
+	return 0;
+}
+
+static int
+acornfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
+{
+	struct display *display;
+	int err, chgvar = 0, visual;
+
+	if (con >= 0)
+		display = fb_display + con;
+	else
+		display = &global_disp;
+
+	if (!current_par.allow_modeset && con != -1)
+		return -EINVAL;
+
+	err = acornfb_decode_var(var, con, &visual);
+	if (err)
+		return err;
+
+	switch (var->activate & FB_ACTIVATE_MASK) {
+	case FB_ACTIVATE_TEST:
+		return 0;
+
+	case FB_ACTIVATE_NXTOPEN:
+	case FB_ACTIVATE_NOW:
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	if (con >= 0) {
+		if (display->var.xres != var->xres)
+			chgvar = 1;
+		if (display->var.yres != var->yres)
+			chgvar = 1;
+		if (display->var.xres_virtual != var->xres_virtual)
+			chgvar = 1;
+		if (display->var.yres_virtual != var->yres_virtual)
+			chgvar = 1;
+		if (memcmp(&display->var.red, &var->red, sizeof(var->red)))
+			chgvar = 1;
+		if (memcmp(&display->var.green, &var->green, sizeof(var->green)))
+			chgvar = 1;
+		if (memcmp(&display->var.blue, &var->blue, sizeof(var->blue)))
+			chgvar = 1;
+	}
+
+	display->var = *var;
+	display->var.activate &= ~FB_ACTIVATE_ALL;
+
+	if (var->activate & FB_ACTIVATE_ALL)
+		global_disp.var = display->var;
+
+	display->screen_base	= (char *)current_par.screen_base;
+	display->visual		= visual;
+	display->type		= FB_TYPE_PACKED_PIXELS;
+	display->type_aux	= 0;
+	display->ypanstep	= 1;
+	display->ywrapstep	= 1;
+	display->line_length	=
+	display->next_line      = (var->xres * var->bits_per_pixel) / 8;
+	display->can_soft_blank	= visual == FB_VISUAL_PSEUDOCOLOR ? 1 : 0;
+	display->inverse	= 0;
+
+	switch (display->var.bits_per_pixel) {
+#ifdef FBCON_HAS_MFB
+	case 1:
+		current_par.palette_size = 2;
+		display->dispsw = &fbcon_mfb;
+		break;
+#endif
+#ifdef FBCON_HAS_CFB2
+	case 2:
+		current_par.palette_size = 4;
+		display->dispsw = &fbcon_cfb2;
+		break;
+#endif
+#ifdef FBCON_HAS_CFB4
+	case 4:
+		current_par.palette_size = 16;
+		display->dispsw = &fbcon_cfb4;
+		break;
+#endif
+#ifdef FBCON_HAS_CFB8
+	case 8:
+		current_par.palette_size = VIDC_PALETTE_SIZE;
+		display->dispsw = &fbcon_cfb8;
+		break;
+#endif
+#ifdef FBCON_HAS_CFB16
+	case 16:
+		current_par.palette_size = VIDC_PALETTE_SIZE;
+		display->dispsw = &fbcon_cfb16;
+		display->dispsw_data = current_par.cmap.cfb16;
+		break;
+#endif
+	default:
+		display->dispsw = &fbcon_dummy;
+		break;
+	}
+
+	if (chgvar && info && info->changevar)
+		info->changevar(con);
+
+	if (con == current_par.currcon) {
+		struct fb_cmap *cmap;
+		unsigned long start, size;
+		int control;
+
+#if defined(HAS_MEMC)
+		start   = 0;
+		size    = current_par.screen_size - VDMA_XFERSIZE;
+		control = 0;
+
+		memc_write(VDMA_START, start);
+		memc_write(VDMA_END, size >> 2);
+#elif defined(HAS_IOMD)
+
+		start = current_par.screen_base_p;
+		size  = current_par.screen_end;
+
+		if (current_par.using_vram) {
+			size -= current_par.vram_half_sam;
+			control = DMA_CR_E | (current_par.vram_half_sam / 256);
+		} else {
+			size -= 16;
+			control = DMA_CR_E | DMA_CR_D | 16;
+		}
+
+		outl(start,   IOMD_VIDSTART);
+		outl(size,    IOMD_VIDEND);
+		outl(control, IOMD_VIDCR);
+#endif
+		acornfb_update_dma(var);
+
+		if (current_par.allow_modeset)
+			acornfb_set_timing(var);
+
+		if (display->cmap.len)
+			cmap = &display->cmap;
+		else
+			cmap = fb_default_cmap(current_par.palette_size);
+
+		fb_set_cmap(cmap, 1, acornfb_setcolreg, info);
+	}
+	return 0;
+}
+
+static int
 acornfb_pan_display(struct fb_var_screeninfo *var, int con,
 		    struct fb_info *info)
 {
-	if (var->xoffset || var->yoffset)
+	u_int y_bottom;
+
+	if (var->xoffset)
 		return -EINVAL;
+
+	y_bottom = var->yoffset;
+
+	if (!(var->vmode & FB_VMODE_YWRAP))
+		y_bottom += var->yres;
+
+	if (y_bottom > fb_display[con].var.yres_virtual)
+		return -EINVAL;
+
+	acornfb_update_dma(var);
+
+	fb_display[con].var.yoffset = var->yoffset;
+	if (var->vmode & FB_VMODE_YWRAP)
+		fb_display[con].var.vmode |= FB_VMODE_YWRAP;
 	else
-		return 0;
+		fb_display[con].var.vmode &= ~FB_VMODE_YWRAP;
+
+	return 0;
 }
 
 static int
@@ -329,64 +1255,652 @@
 	acornfb_ioctl
 };
 
-void
-acornfb_setup(char *options, int *ints)
+static int
+acornfb_updatevar(int con, struct fb_info *info)
 {
+	if (con == current_par.currcon)
+		acornfb_update_dma(&fb_display[con].var);
+
+	return 0;
 }
 
 static int
-acornfb_update_var(int con, struct fb_info *info)
+acornfb_switch(int con, struct fb_info *info)
 {
-	if (con == currcon) {
-		int off = fb_display[con].var.yoffset *
-			  fb_display[con].var.xres_virtual *
-			  fb_display[con].var.bits_per_pixel >> 3;
-		unsigned long base;
+	struct fb_cmap *cmap;
 
-		base = current_par.screen_base = SCREEN_START + off;
+	if (current_par.currcon >= 0) {
+		cmap = &fb_display[current_par.currcon].cmap;
 
-		outl (SCREEN_START + base, VDMA_INIT);
+		if (cmap->len)
+			fb_get_cmap(cmap, 1, acornfb_getcolreg, info);
 	}
 
-	return 0;
-}
+	current_par.currcon = con;
+
+	fb_display[con].var.activate = FB_ACTIVATE_NOW;
+
+	acornfb_set_var(&fb_display[con].var, con, info);
 
-static int
-acornfb_switch(int con, struct fb_info *info)
-{
-	currcon = con;
-	acornfb_update_var(con, info);
 	return 0;
 }
 
 static void
 acornfb_blank(int blank, struct fb_info *info)
 {
+	int i;
+
+	if (blank)
+		for (i = 0; i < current_par.palette_size; i++) {
+			union palette p;
+
+			p = acornfb_palette_encode(i, 0, 0, 0, 0);
+
+			acornfb_palette_write(i, p);
+		}
+	else
+		for (i = 0; i < current_par.palette_size; i++)
+			acornfb_palette_write(i, current_par.palette[i]);
+}
+
+/*
+ * Everything after here is initialisation!!!
+ */
+struct modey_params {
+	u_int	y_res;
+	u_int	u_margin;
+	u_int	b_margin;
+	u_int	vsync_len;
+	u_int	vf;
+};
+
+struct modex_params {
+	u_int	x_res;
+	u_int	l_margin;
+	u_int	r_margin;
+	u_int	hsync_len;
+	u_int	clock;
+	u_int	hf;
+	const struct modey_params *modey;
+};
+
+static const struct modey_params modey_640_15600[] __initdata = {
+	{  250,  38,  21,  3,  50 },	/*  640x 250, 50Hz */
+	{  256,  35,  18,  3,  50 },	/*  640x 256, 50Hz */
+	{    0,   0,   0,  0,   0 }
+};
+
+static const struct modey_params modey_640_26800[] __initdata = {
+	{  512,  18,   1,  3,  50 },	/*  640x 512, 50Hz */
+	{    0,   0,   0,  0,   0 }
+};
+
+static const struct modey_params modey_640_31500[] __initdata = {
+	{  250, 109,  88,  2,  70 },	/*  640x 250, 70Hz */
+	{  256, 106,  85,  2,  70 },	/*  640x 256, 70Hz */
+	{  352,  58,  37,  2,  70 },	/*  640x 352, 70Hz */
+	{  480,  32,  11,  2,  60 },	/*  640x 480, 60Hz */
+	{    0,   0,   0,  0,   0 }
+};
+
+static const struct modey_params modey_800_35200[] __initdata = {
+	{  600,  22,   1,  2,  56 },	/*  800x 600, 56Hz */
+	{    0,   0,   0,  0,   0 }
+};
+
+static const struct modey_params modey_896_21800[] __initdata = {
+	{  352,   9,   0,  3,  60 },	/*  896x 352, 60Hz */
+	{    0,   0,   0,  0,   0 }
+};
+
+/* everything after here is not supported */
+static const struct modey_params modey_1024_uk[] __initdata = {
+	{  768,   0,   0,  0,   0 },	/* 1024x 768 */
+	{    0,   0,   0,  0,   0 }
+};
+
+static const struct modey_params modey_1056_uk[] __initdata = {
+	{  250,   0,   0,  0,   0 },	/* 1056x 250 */
+	{  256,   0,   0,  0,   0 },	/* 1056x 256 */
+	{    0,   0,   0,  0,   0 }
+};
+
+static const struct modey_params modey_1152_uk[] __initdata = {
+	{  896,   0,   0,  0,   0 },	/* 1152x 896 */
+	{    0,   0,   0,  0,   0 }
+};
+
+static const struct modey_params modey_1280_63600[] __initdata = {
+	{ 1024,   0,   0,  0,  60 },	/* 1280x1024, 60Hz */
+	{    0,   0,   0,  0,   0 }
+};
+
+static const struct modey_params modey_1600_uk[] __initdata = {
+	{ 1280,   0,   0,  0,   0 },	/* 1600x1280 */
+	{    0,   0,   0,  0,   0 }
+};
+
+/*
+ * Horizontal video programming requirements.
+ * This table is searched for the required horizontal
+ * and required frequency, and then the tables above
+ * are then searched for the required vertical
+ * resolution.
+ *
+ * NOTE! we can match multiple entries, so we search
+ * all horizontal entries for which the hfreq is within
+ * the monitor's range.
+ */
+static const struct modex_params modex_params[] __initdata = {
+	{						/* X:  640, 15.6kHz */
+		 640,  185, 123,  76, 16000, 15625, modey_640_15600
+	},
+	{						/* X:  640, 26.8kHz */
+		 640,  113,  87,  56, 24000, 26800, modey_640_26800
+	},
+	{						/* X:  640, 31.5kHz */
+		 640,   48,  16,  96, 25175, 31500, modey_640_31500
+	},
+	{						/* X:  800, 35.2kHz */
+		 800,  101,  23, 100, 36000, 35200, modey_800_35200
+	},
+	{						/* X:  896, 21.8kHz */
+		 896,   59,  27, 118, 24000, 21800, modey_896_21800
+	},
+	{						/* X: 1024 */
+		1024,    0,   0,   0,     0,     0, modey_1024_uk
+	},
+	{						/* X: 1056 */
+		1056,    0,   0,   0,     0,     0, modey_1056_uk
+	},
+	{						/* X: 1152 */
+		1152,    0,   0,   0,     0,     0, modey_1152_uk
+	},
+	{						/* X: 1280, 63.6kHz */
+		1280,    0,   0,   0,     0, 63600, modey_1280_63600
+	},
+	{						/* X: 1600 */
+		1600,    0,   0,   0,     0,     0, modey_1600_uk
+	},
+	{
+		0,
+	}
+};
+
+__initfunc(static int
+acornfb_lookup_timing(struct fb_var_screeninfo *var))
+{
+	const struct modex_params *x;
+	const struct modey_params *y;
+
+	/*
+	 * We must adjust the resolution parameters
+	 * before selecting the timing parameters.
+	 */
+	acornfb_pre_adjust_timing(var, -1);
+
+	for (x = modex_params; x->x_res; x++) {
+
+		/*
+		 * Is this resolution one we're looking for?
+		 */
+		if (x->x_res != var->xres)
+			continue;
+
+		/*
+		 * Is the hsync frequency ok for our monitor?
+		 */
+		if (x->hf > fb_info.monspecs.hfmax ||
+		    x->hf < fb_info.monspecs.hfmin)
+			continue;
+
+		/*
+		 * Try to find a vertical resolution
+		 */
+		for (y = x->modey; y->y_res; y++) {
+			/*
+			 * Is this resolution one we're looking for?
+			 */
+			if (y->y_res != var->yres)
+				continue;
+
+			/*
+			 * Is the vsync frequency ok for our monitor?
+			 */
+			if (y->vf > fb_info.monspecs.vfmax ||
+			    y->vf < fb_info.monspecs.vfmin)
+				continue;
+
+			goto found;
+		}
+	}
+
+	var->pixclock = 0;
+
+	return -EINVAL;
+
+found:
+	/*
+	 * Why is pixclock in picoseconds?
+	 */
+	switch (x->clock) {
+	case 36000: var->pixclock =  27778;	break;
+	case 25175: var->pixclock =  39722;	break;
+	case 24000: var->pixclock =  41667;	break;
+	case 16000: var->pixclock =  62500;	break;
+	case 12000: var->pixclock =  83333;	break;
+	case  8000: var->pixclock = 125000;	break;
+	default:    var->pixclock =      0;     break;
+	}
+
+#ifdef DEBUG_MODE_SELECTION
+	printk(KERN_DEBUG "Found %dx%d at %d.%3dkHz, %dHz, pix %d\n",
+		x->x_res, y->y_res,
+		x->hf / 1000, x->hf % 1000,
+		y->vf, var->pixclock);
+#endif
+
+	var->left_margin	= x->l_margin;
+	var->right_margin	= x->r_margin;
+	var->upper_margin	= y->u_margin;
+	var->lower_margin	= y->b_margin;
+	var->hsync_len		= x->hsync_len;
+	var->vsync_len		= y->vsync_len;
+	var->sync		= 0;
+
+	/*
+	 * Now adjust the parameters we found
+	 */
+	acornfb_post_adjust_timing(var);
+
+	return 0;
 }
 
-__initfunc(unsigned long
-acornfb_init(unsigned long mem_start))
+__initfunc(static void
+acornfb_init_fbinfo(void))
 {
+	static int first = 1;
+
+	if (!first)
+		return;
+	first = 0;
+
 	strcpy(fb_info.modename, "Acorn");
-	fb_info.node		= -1;
-	fb_info.fbops		= &acornfb_ops;
-	fb_info.disp		= &disp;
-	fb_info.monspecs.hfmin	= 0;
-	fb_info.monspecs.hfmax	= 0;
-	fb_info.monspecs.vfmin	= 0;
-	fb_info.monspecs.vfmax	= 0;
-	fb_info.monspecs.dpms	= 0;
 	strcpy(fb_info.fontname, "Acorn8x8");
-	fb_info.changevar	= NULL;
-	fb_info.switch_con	= acornfb_switch;
-	fb_info.updatevar	= acornfb_update_var;
-	fb_info.blank		= acornfb_blank;
-	fb_info.flags		= FBINFO_FLAG_DEFAULT;
-
-	acornfb_set_disp(-1);
-	fb_set_cmap(fb_default_cmap(current_par.palette_size),
-		    1, acornfb_vidc20_setcolreg, &fb_info);
-	register_framebuffer(&fb_info);
 
-	return mem_start;
+	fb_info.node		   = -1;
+	fb_info.fbops		   = &acornfb_ops;
+	fb_info.disp		   = &global_disp;
+	fb_info.changevar	   = NULL;
+	fb_info.switch_con	   = acornfb_switch;
+	fb_info.updatevar	   = acornfb_updatevar;
+	fb_info.blank		   = acornfb_blank;
+	fb_info.flags		   = FBINFO_FLAG_DEFAULT;
+
+	global_disp.dispsw	   = &fbcon_dummy;
+
+	/*
+	 * setup initial parameters
+	 */
+	memset(&init_var, 0, sizeof(init_var));
+	init_var.xres		   = DEFAULT_XRES;
+	init_var.yres		   = DEFAULT_YRES;
+
+#if   defined(FBCON_HAS_CFB4)
+	init_var.bits_per_pixel	   = 4;
+#elif defined(FBCON_HAS_CFB8)
+	init_var.bits_per_pixel    = 8;
+#elif defined(FBCON_HAS_CFB2)
+	init_var.bits_per_pixel    = 2;
+#elif defined(FBCON_HAS_MFB)
+	init_var.bits_per_pixel    = 1;
+#else
+#error No suitable framebuffers configured
+#endif
+
+#if defined(HAS_VIDC20)
+	init_var.red.length	   = 8;
+	init_var.transp.length	   = 4;
+#elif defined(HAS_VIDC)
+	init_var.red.length	   = 4;
+	init_var.transp.length	   = 1;
+#endif
+	init_var.green		   = init_var.red;
+	init_var.blue		   = init_var.red;
+	init_var.nonstd		   = 0;
+	init_var.activate	   = FB_ACTIVATE_NOW;
+	init_var.height		   = -1;
+	init_var.width		   = -1;
+	init_var.vmode		   = FB_VMODE_NONINTERLACED;
+
+	current_par.dram_size	   = 0;
+	current_par.montype	   = -1;
+	current_par.dpms	   = 0;
+}
+
+/*
+ * setup acornfb options:
+ *
+ *  font:fontname
+ *	Set fontname
+ *
+ *  mon:hmin-hmax:vmin-vmax:dpms:width:height
+ *	Set monitor parameters:
+ *		hmin   = horizontal minimum frequency (Hz)
+ *		hmax   = horizontal maximum frequency (Hz)	(optional)
+ *		vmin   = vertical minimum frequency (Hz)
+ *		vmax   = vertical maximum frequency (Hz)	(optional)
+ *		dpms   = DPMS supported?			(optional)
+ *		width  = width of picture in mm.		(optional)
+ *		height = height of picture in mm.		(optional)
+ *
+ * montype:type
+ *	Set RISC-OS style monitor type:
+ *		0 (or tv)	- TV frequency
+ *		1 (or multi)	- Multi frequency
+ *		2 (or hires)	- Hi-res monochrome
+ *		3 (or vga)	- VGA
+ *		4 (or svga)	- SVGA
+ *		auto, or option missing
+ *				- try hardware detect
+ *
+ * dram:size
+ *	Set the amount of DRAM to use for the frame buffer
+ *	(even if you have VRAM).
+ *	size can optionally be followed by 'M' or 'K' for
+ *	MB or KB respectively.
+ */
+__initfunc(static void
+acornfb_parse_font(char *opt))
+{
+	strcpy(fb_info.fontname, opt);
+}
+
+__initfunc(static void
+acornfb_parse_mon(char *opt))
+{
+	fb_info.monspecs.hfmin = simple_strtoul(opt, &opt, 0);
+	if (*opt == '-')
+		fb_info.monspecs.hfmax = simple_strtoul(opt + 1, &opt, 0);
+	else
+		fb_info.monspecs.hfmax = fb_info.monspecs.hfmin;
+
+	if (*opt != ':')
+		return;
+
+	fb_info.monspecs.vfmin = simple_strtoul(opt + 1, &opt, 0);
+	if (*opt == '-')
+		fb_info.monspecs.vfmax = simple_strtoul(opt + 1, &opt, 0);
+	else
+		fb_info.monspecs.vfmax = fb_info.monspecs.vfmin;
+
+	if (*opt != ':')
+		return;
+
+	fb_info.monspecs.dpms = simple_strtoul(opt + 1, &opt, 0);
+
+	if (*opt != ':')
+		return;
+
+	init_var.width = simple_strtoul(opt + 1, &opt, 0);
+
+	if (*opt != ':')
+		return;
+
+	init_var.height = simple_strtoul(opt + 1, NULL, 0);
+}
+
+__initfunc(static void
+acornfb_parse_montype(char *opt))
+{
+	current_par.montype = -2;
+
+	if (strncmp(opt, "tv", 2) == 0) {
+		opt += 2;
+		current_par.montype = 0;
+	} else if (strncmp(opt, "multi", 5) == 0) {
+		opt += 5;
+		current_par.montype = 1;
+	} else if (strncmp(opt, "hires", 5) == 0) {
+		opt += 5;
+		current_par.montype = 2;
+	} else if (strncmp(opt, "vga", 3) == 0) {
+		opt += 3;
+		current_par.montype = 3;
+	} else if (strncmp(opt, "svga", 4) == 0) {
+		opt += 4;
+		current_par.montype = 4;
+	} else if (strncmp(opt, "auto", 4) == 0) {
+		opt += 4;
+		current_par.montype = -1;
+	} else if (isdigit(*opt))
+		current_par.montype = simple_strtoul(opt, &opt, 0);
+
+	if (current_par.montype == -2 ||
+	    current_par.montype > NR_MONTYPES) {
+		printk(KERN_ERR "acornfb: unknown monitor type: %s\n",
+			opt);
+		current_par.montype = -1;
+	} else
+	if (opt && *opt) {
+		if (strcmp(opt, ",dpms") == 0)
+			current_par.dpms = 1;
+		else
+			printk(KERN_ERR
+			       "acornfb: unknown monitor option: %s\n",
+			       opt);
+	}
+}
+
+__initfunc(static void
+acornfb_parse_dram(char *opt))
+{
+	unsigned int size;
+
+	size = simple_strtoul(opt, &opt, 0);
+
+	if (opt) {
+		switch (*opt) {
+		case 'M':
+		case 'm':
+			size *= 1024;
+		case 'K':
+		case 'k':
+			size *= 1024;
+		default:
+			break;
+		}
+	}
+
+	current_par.dram_size = size;
+}
+
+static struct options {
+	char *name;
+	void (*parse)(char *opt);
+} opt_table[] __initdata = {
+	{ "font",    acornfb_parse_font    },
+	{ "mon",     acornfb_parse_mon     },
+	{ "montype", acornfb_parse_montype },
+	{ "dram",    acornfb_parse_dram    },
+	{ NULL, NULL }
+};
+
+__initfunc(void
+acornfb_setup(char *options, int *ints))
+{
+	struct options *optp;
+	char *opt;
+
+	if (!options || !*options)
+		return;
+
+	acornfb_init_fbinfo();
+
+	for (opt = strtok(options, ","); opt; opt = strtok(NULL, ",")) {
+		if (!*opt)
+			continue;
+
+		for (optp = opt_table; optp->name; optp++) {
+			int optlen;
+
+			optlen = strlen(optp->name);
+
+			if (strncmp(opt, optp->name, optlen) == 0 &&
+			    opt[optlen] == ':') {
+				optp->parse(opt + optlen + 1);
+				break;
+			}
+		}
+
+		if (!optp->name)
+			printk(KERN_ERR "acornfb: unknown parameter: %s\n",
+			       opt);
+	}
+}
+
+/*
+ * Detect type of monitor connected
+ *  For now, we just assume SVGA
+ */
+__initfunc(static int
+acornfb_detect_monitortype(void))
+{
+	return 4;
+}
+
+/*
+ * This enables the unused memory to be freed on older Acorn machines.
+ */
+static inline void
+free_unused_pages(unsigned int virtual_start, unsigned int virtual_end)
+{
+	int mb_freed = 0;
+
+	/*
+	 * Align addresses
+	 */
+	virtual_start = PAGE_ALIGN(virtual_start);
+	virtual_end = PAGE_ALIGN(virtual_end);
+
+	while (virtual_start < virtual_end) {
+		/*
+		 * Clear page reserved bit,
+		 * set count to 1, and free
+		 * the page.
+		 */
+		clear_bit(PG_reserved, &mem_map[MAP_NR(virtual_start)].flags);
+		atomic_set(&mem_map[MAP_NR(virtual_start)].count, 1);
+		free_page(virtual_start);
+
+		virtual_start += PAGE_SIZE;
+		mb_freed += PAGE_SIZE / 1024;
+	}
+
+	printk("acornfb: freed %dK memory\n", mb_freed);
+}
+
+__initfunc(void
+acornfb_init(void))
+{
+	unsigned long size;
+	u_int h_sync, v_sync;
+
+	acornfb_init_fbinfo();
+
+	if (current_par.montype == -1)
+		current_par.montype = acornfb_detect_monitortype();
+
+	if (current_par.montype < 0 || current_par.montype > NR_MONTYPES)
+		current_par.montype = 4;
+
+	fb_info.monspecs = monspecs[current_par.montype];
+	fb_info.monspecs.dpms = current_par.dpms;
+
+	current_par.currcon	   = -1;
+	current_par.screen_base	   = SCREEN2_BASE;
+	current_par.screen_base_p  = SCREEN_START;
+	current_par.using_vram     = 0;
+
+	/*
+	 * If vram_size is set, we are using VRAM in
+	 * a Risc PC.  However, if the user has specified
+	 * an amount of DRAM then use that instead.
+	 */
+	if (vram_size && !current_par.dram_size) {
+		size = vram_size;
+		current_par.vram_half_sam = vram_size / 1024;
+		current_par.using_vram = 1;
+	} else if (current_par.dram_size)
+		size = current_par.dram_size;
+	else
+		size = (init_var.xres * init_var.yres *
+			init_var.bits_per_pixel) / 8;
+
+	size = PAGE_ALIGN(size);
+
+#ifdef CONFIG_ARCH_RPC
+	if (!current_par.using_vram) {
+		/*
+		 * RiscPC needs to allocate the DRAM memory
+		 * for the framebuffer if we are not using
+		 * VRAM.  Archimedes/A5000 machines use a
+		 * fixed address for their framebuffers.
+		 */
+		current_par.screen_base = (unsigned long)kmalloc(size, GFP_KERNEL);
+		if (current_par.screen_base == 0) {
+			printk(KERN_ERR "acornfb: unable to allocate screen "
+			       "memory\n");
+			return;
+		}
+		current_par.screen_base_p =
+			virt_to_phys(current_par.screen_base);
+	}
+#endif
+#if defined(CONFIG_ARCH_A5K) || defined(CONFIG_ARCH_ARC)
+#define MAX_SIZE	480*1024
+	/*
+	 * Limit maximum screen size.
+	 */
+	if (size > MAX_SIZE)
+		size = MAX_SIZE;
+
+	/*
+	 * Free unused pages
+	 */
+	free_unused_pages(PAGE_OFFSET + size, PAGE_OFFSET + MAX_SIZE);
+#endif
+	
+	current_par.screen_size	   = size;
+	current_par.palette_size   = VIDC_PALETTE_SIZE;
+	current_par.allow_modeset  = 1;
+
+	/*
+	 * Lookup the timing for this resolution.  If we can't
+	 * find it, then we can't restore it if we change
+	 * the resolution, so we disable this feature.
+	 */
+	if (acornfb_lookup_timing(&init_var))
+		current_par.allow_modeset = 0;
+
+	/*
+	 * Again, if this does not succeed, then we disallow
+	 * changes to the resolution parameters.
+	 */
+	if (acornfb_set_var(&init_var, -1, &fb_info))
+		current_par.allow_modeset = 0;
+
+	h_sync = 1953125000 / init_var.pixclock;
+	h_sync = h_sync * 512 / (init_var.xres + init_var.left_margin +
+		 init_var.right_margin + init_var.hsync_len);
+	v_sync = h_sync / (init_var.yres + init_var.upper_margin +
+		 init_var.lower_margin + init_var.vsync_len);
+
+	printk("Acornfb: %ldkB %cRAM, %s, using %dx%d, %d.%03dkHz, %dHz\n",
+		current_par.screen_size / 1024,
+		current_par.using_vram ? 'V' : 'D',
+		VIDC_NAME, init_var.xres, init_var.yres,
+		h_sync / 1000, h_sync % 1000, v_sync);
+
+	register_framebuffer(&fb_info);
 }
diff -u --recursive --new-file v2.3.0/linux/drivers/video/cyber2000fb.c linux/drivers/video/cyber2000fb.c
--- v2.3.0/linux/drivers/video/cyber2000fb.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/video/cyber2000fb.c	Tue May 11 16:30:45 1999
@@ -0,0 +1,1057 @@
+/*
+ * linux/drivers/video/cyber2000fb.c
+ *
+ * Integraphics Cyber2000 frame buffer device
+ *
+ * Based on cyberfb.c
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/malloc.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+
+#include <video/fbcon.h>
+#include <video/fbcon-cfb8.h>
+#include <video/fbcon-cfb16.h>
+#include <video/fbcon-cfb24.h>
+
+/*
+ *    Some defaults
+ */
+#define DEFAULT_XRES	640
+#define DEFAULT_YRES	480
+#define DEFAULT_BPP	8
+
+static volatile unsigned char	*CyberRegs;
+
+#include "cyber2000fb.h"
+
+static struct display		global_disp;
+static struct fb_info		fb_info;
+static struct cyber2000fb_par	current_par;
+static struct display_switch	*dispsw;
+static struct fb_var_screeninfo __initdata init_var = {};
+
+#ifdef DEBUG
+static void debug_printf(char *fmt, ...)
+{
+	char buffer[128];
+	va_list ap;
+
+	va_start(ap, fmt);
+	vsprintf(buffer, fmt, ap);
+	va_end(ap);
+
+	printascii(buffer);
+}
+#else
+#define debug_printf(x...) do { } while (0)
+#endif
+
+/*
+ *    Predefined Video Modes
+ */
+static const struct res cyber2000_res[] = {
+	{
+		640, 480,
+		{
+			0x5f, 0x4f, 0x50, 0x80, 0x52, 0x9d, 0x0b, 0x3e,
+			0x00, 0x40,
+			0xe9, 0x8b, 0xdf, 0x50, 0x00, 0xe6, 0x04, 0xc3
+		},
+		0x00,
+		{ 0xd2, 0xce, 0xdb, 0x54 }
+	},
+
+	{
+		800, 600,
+		{
+			0x7f, 0x63, 0x64, 0x00, 0x66, 0x10, 0x6f, 0xf0,
+			0x00, 0x60,
+			0x5b, 0x8f, 0x57, 0x64, 0x00, 0x59, 0x6e, 0xe3
+		},
+		0x00,
+		{ 0x52, 0x85, 0xdb, 0x54 }
+	},
+
+	{
+		1024, 768,
+		{
+			0x9f, 0x7f, 0x80, 0x80, 0x8b, 0x94, 0x1e, 0xfd,
+			0x00, 0x60,
+			0x03, 0x86, 0xff, 0x80, 0x0f, 0x00, 0x1e, 0xe3
+		},
+		0x00,
+		{ 0xd0, 0x52, 0xdb, 0x54 }
+	},
+#if 0
+	{
+		1152, 886,
+		{
+		},
+		{
+		}
+	},
+#endif
+	{
+		1280, 1024,
+		{
+			0xce, 0x9f, 0xa0, 0x8f, 0xa2, 0x1f, 0x28, 0x52,
+			0x00, 0x40,
+			0x08, 0x8f, 0xff, 0xa0, 0x00, 0x03, 0x27, 0xe3
+		},
+		0x1d,
+		{ 0xb4, 0x4b, 0xdb, 0x54 }
+	},
+
+	{
+		1600, 1200,
+		{
+			0xff, 0xc7, 0xc9, 0x9f, 0xcf, 0xa0, 0xfe, 0x10,
+			0x00, 0x40,
+			0xcf, 0x89, 0xaf, 0xc8, 0x00, 0xbc, 0xf1, 0xe3
+		},
+		0x1f,
+		{ 0xbd, 0x10, 0xdb, 0x54 }
+	}
+};
+
+#define NUM_TOTAL_MODES    arraysize(cyber2000_res)
+
+static const char igs_regs[] = {
+	0x10, 0x10,			0x12, 0x00,	0x13, 0x00,
+	0x30, 0x21,	0x31, 0x00,	0x32, 0x00,	0x33, 0x01,
+	0x50, 0x00,	0x51, 0x00,	0x52, 0x00,	0x53, 0x00,
+	0x54, 0x00,	0x55, 0x00,	0x56, 0x00,	0x57, 0x01,
+	0x58, 0x00,	0x59, 0x00,	0x5a, 0x00,
+	0x70, 0x0b,	0x71, 0x10,	0x72, 0x45,	0x73, 0x30,
+	0x74, 0x1b,	0x75, 0x1e,	0x76, 0x00,	0x7a, 0xc8
+};
+
+static const char crtc_idx[] = {
+	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+	0x08, 0x09,
+	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17
+};
+
+static void cyber2000_init_hw(const struct res *res)
+{
+	int i;
+
+	debug_printf("init vga hw for %dx%d\n", res->xres, res->yres);
+
+	cyber2000_outb(0xef, 0x3c2);
+	cyber2000_crtcw(0x0b, 0x11);
+	cyber2000_attrw(0x00, 0x11);
+
+	cyber2000_seqw(0x01, 0x00);
+	cyber2000_seqw(0x01, 0x01);
+	cyber2000_seqw(0x0f, 0x02);
+	cyber2000_seqw(0x00, 0x03);
+	cyber2000_seqw(0x0e, 0x04);
+	cyber2000_seqw(0x03, 0x00);
+
+	for (i = 0; i < sizeof(crtc_idx); i++)
+		cyber2000_crtcw(res->crtc_regs[i], crtc_idx[i]);
+
+	for (i = 0x0a; i < 0x10; i++)
+		cyber2000_crtcw(0, i);
+
+	cyber2000_crtcw(0xff, 0x18);
+
+	cyber2000_grphw(0x00, 0x00);
+	cyber2000_grphw(0x00, 0x01);
+	cyber2000_grphw(0x00, 0x02);
+	cyber2000_grphw(0x00, 0x03);
+	cyber2000_grphw(0x00, 0x04);
+	cyber2000_grphw(0x60, 0x05);
+	cyber2000_grphw(0x05, 0x06);
+	cyber2000_grphw(0x0f, 0x07);
+	cyber2000_grphw(0xff, 0x08);
+
+	for (i = 0; i < 16; i++)
+		cyber2000_attrw(i, i);
+
+	cyber2000_attrw(0x01, 0x10);
+	cyber2000_attrw(0x00, 0x11);
+	cyber2000_attrw(0x0f, 0x12);
+	cyber2000_attrw(0x00, 0x13);
+	cyber2000_attrw(0x00, 0x14);
+
+	for (i = 0; i < sizeof(igs_regs); i += 2)
+		cyber2000_grphw(igs_regs[i+1], igs_regs[i]);
+
+	cyber2000_grphw(res->crtc_ofl, 0x11);
+
+	for (i = 0; i < 4; i += 1)
+		cyber2000_grphw(res->clk_regs[i], 0xb0 + i);
+
+	cyber2000_grphw(0x01, 0x90);
+	cyber2000_grphw(0x80, 0xb9);
+	cyber2000_grphw(0x00, 0xb9);
+
+	cyber2000_outb(0x56, 0x3ce);
+	i = cyber2000_inb(0x3cf);
+	cyber2000_outb(i | 4, 0x3cf);
+	cyber2000_outb(0x04, 0x3c6);
+	cyber2000_outb(i,    0x3cf);
+
+	cyber2000_outb(0x20, 0x3c0);
+	cyber2000_outb(0xff, 0x3c6);
+
+	for (i = 0; i < 256; i++) {
+		cyber2000_outb(i, 0x3c8);
+		cyber2000_outb(0, 0x3c9);
+		cyber2000_outb(0, 0x3c9);
+		cyber2000_outb(0, 0x3c9);
+	}
+}
+
+
+static struct fb_ops cyber2000fb_ops;
+
+/* -------------------- Hardware specific routines ------------------------- */
+
+/*
+ * Hardware Cyber2000 Acceleration
+ */
+static void cyber2000_accel_wait(void)
+{
+	int count = 10000;
+
+	while (cyber2000_inb(0xbf011) & 0x80) {
+		if (!count--) {
+			debug_printf("accel_wait timed out\n");
+			cyber2000_outb(0, 0xbf011);
+			return;
+		}
+		udelay(10);
+	}
+}
+
+static void
+cyber2000_accel_setup(struct display *p)
+{
+	dispsw->setup(p);
+}
+
+static void
+cyber2000_accel_bmove(struct display *p, int sy, int sx, int dy, int dx,
+		int height, int width)
+{
+	unsigned long src, dst, chwidth = p->var.xres_virtual * fontheight(p);
+	int v = 0x8000;
+
+	if (sx < dx) {
+		sx += width - 1;
+		dx += width - 1;
+		v |= 4;
+	}
+
+	if (sy < dy) {
+		sy += height - 1;
+		dy += height - 1;
+		v |= 2;
+	}
+
+	sx *= fontwidth(p);
+	dx *= fontwidth(p);
+	src = sx + sy * chwidth;
+	dst = dx + dy * chwidth;
+	width = width * fontwidth(p) - 1;
+	height = height * fontheight(p) - 1;
+
+	cyber2000_accel_wait();
+	cyber2000_outb(0x00,   0xbf011);
+	cyber2000_outb(0x03,   0xbf048);
+	cyber2000_outw(width,  0xbf060);
+
+	if (p->var.bits_per_pixel != 24) {
+		cyber2000_outl(dst, 0xbf178);
+		cyber2000_outl(src, 0xbf170);
+	} else {
+		cyber2000_outl(dst * 3, 0xbf178);
+		cyber2000_outb(dst, 0xbf078);
+		cyber2000_outl(src * 3, 0xbf170);
+	}
+
+	cyber2000_outw(height, 0xbf062);
+	cyber2000_outw(v,      0xbf07c);
+	cyber2000_outw(0x2800, 0xbf07e);
+}
+
+static void
+cyber2000_accel_clear(struct vc_data *conp, struct display *p, int sy, int sx,
+		int height, int width)
+{
+	unsigned long dst;
+	u32 bgx = attr_bgcol_ec(p, conp);
+
+	dst = sx * fontwidth(p) + sy * p->var.xres_virtual * fontheight(p);
+	width = width * fontwidth(p) - 1;
+	height = height * fontheight(p) - 1;
+
+	cyber2000_accel_wait();
+	cyber2000_outb(0x00,   0xbf011);
+	cyber2000_outb(0x03,   0xbf048);
+	cyber2000_outw(width,  0xbf060);
+	cyber2000_outw(height, 0xbf062);
+
+	switch (p->var.bits_per_pixel) {
+	case 16:
+		bgx = ((u16 *)p->dispsw_data)[bgx];
+	case 8:
+		cyber2000_outl(dst, 0xbf178);
+		break;
+
+	case 24:
+		cyber2000_outl(dst * 3, 0xbf178);
+		cyber2000_outb(dst, 0xbf078);
+		bgx = ((u32 *)p->dispsw_data)[bgx];
+		break;
+	}
+
+	cyber2000_outl(bgx,    0xbf058);
+	cyber2000_outw(0x8000, 0xbf07c);
+	cyber2000_outw(0x0800, 0xbf07e);
+}
+
+static void
+cyber2000_accel_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx)
+{
+	cyber2000_accel_wait();
+	dispsw->putc(conp, p, c, yy, xx);
+}
+
+static void
+cyber2000_accel_putcs(struct vc_data *conp, struct display *p,
+		const unsigned short *s, int count, int yy, int xx)
+{
+	cyber2000_accel_wait();
+	dispsw->putcs(conp, p, s, count, yy, xx);
+}
+
+static void
+cyber2000_accel_revc(struct display *p, int xx, int yy)
+{
+	cyber2000_accel_wait();
+	dispsw->revc(p, xx, yy);
+}
+
+static void
+cyber2000_accel_clear_margins(struct vc_data *conp, struct display *p, int bottom_only)
+{
+	dispsw->clear_margins(conp, p, bottom_only);
+}
+
+static struct display_switch fbcon_cyber_accel = {
+	cyber2000_accel_setup,
+	cyber2000_accel_bmove,
+	cyber2000_accel_clear,
+	cyber2000_accel_putc,
+	cyber2000_accel_putcs,
+	cyber2000_accel_revc,
+	NULL,
+	NULL,
+	cyber2000_accel_clear_margins,
+	FONTWIDTH(8)|FONTWIDTH(16)
+};
+
+/*
+ * Palette
+ */
+static int
+cyber2000_getcolreg(u_int regno, u_int * red, u_int * green, u_int * blue,
+		    u_int * transp, struct fb_info *fb_info)
+{
+	int t;
+
+	if (regno >= 256)
+		return 1;
+
+	t = current_par.palette[regno].red;
+	*red = t << 10 | t << 4 | t >> 2;
+
+	t = current_par.palette[regno].green;
+	*green = t << 10 | t << 4 | t >> 2;
+
+	t = current_par.palette[regno].blue;
+	*blue = t << 10 | t << 4 | t >> 2;
+
+	*transp = 0;
+
+	return 0;
+}
+
+/*
+ *    Set a single color register. Return != 0 for invalid regno.
+ */
+static int
+cyber2000_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+		    u_int transp, struct fb_info *fb_info)
+{
+	if (regno > 255)
+		return 1;
+
+	red   >>= 10;
+	green >>= 10;
+	blue  >>= 10;
+
+	current_par.palette[regno].red   = red;
+	current_par.palette[regno].green = green;
+	current_par.palette[regno].blue  = blue;
+
+	switch (fb_display[current_par.currcon].var.bits_per_pixel) {
+	case 8:
+		cyber2000_outb(regno, 0x3c8);
+		cyber2000_outb(red,   0x3c9);
+		cyber2000_outb(green, 0x3c9);
+		cyber2000_outb(blue,  0x3c9);
+		break;
+
+#ifdef FBCON_HAS_CFB16
+	case 16:
+		if (regno < 64) {
+			/* write green */
+			cyber2000_outb(regno << 2, 0x3c8);
+			cyber2000_outb(current_par.palette[regno >> 1].red, 0x3c9);
+			cyber2000_outb(green, 0x3c9);
+			cyber2000_outb(current_par.palette[regno >> 1].blue, 0x3c9);
+		}
+
+		if (regno < 32) {
+			/* write red,blue */
+			cyber2000_outb(regno << 3, 0x3c8);
+			cyber2000_outb(red, 0x3c9);
+			cyber2000_outb(current_par.palette[regno << 1].green, 0x3c9);
+			cyber2000_outb(blue, 0x3c9);
+		}
+
+		if (regno < 16)
+			current_par.c_table.cfb16[regno] = regno | regno << 5 | regno << 11;
+		break;
+#endif
+
+#ifdef FBCON_HAS_CFB24
+	case 24:
+		cyber2000_outb(regno, 0x3c8);
+		cyber2000_outb(red,   0x3c9);
+		cyber2000_outb(green, 0x3c9);
+		cyber2000_outb(blue,  0x3c9);
+
+		if (regno < 16)
+			current_par.c_table.cfb24[regno] = regno | regno << 8 | regno << 16;
+		break;
+#endif
+
+	default:
+		return 1;
+	}
+
+	return 0;
+}
+
+static int cyber2000fb_set_timing(struct fb_var_screeninfo *var)
+{
+	int width = var->xres_virtual;
+	int scr_pitch, fetchrow;
+	int i;
+	char b, col;
+
+	switch (var->bits_per_pixel) {
+	case 8:	/* PSEUDOCOLOUR, 256 */
+		b = 0;
+		col = 1;
+		scr_pitch = var->xres_virtual / 8;
+		break;
+
+	case 16:/* DIRECTCOLOUR, 64k */
+		b = 1;
+		col = 2;
+		scr_pitch = var->xres_virtual / 8 * 2;
+		break;
+	case 24:/* TRUECOLOUR, 16m */
+		b = 2;
+		col = 4;
+		scr_pitch = var->xres_virtual / 8 * 3;
+		width *= 3;
+		break;
+
+	default:
+		return 1;
+	}
+
+	for (i = 0; i < NUM_TOTAL_MODES; i++)
+		if (var->xres == cyber2000_res[i].xres &&
+		    var->yres == cyber2000_res[i].yres)
+			break;
+
+	if (i < NUM_TOTAL_MODES)
+		cyber2000_init_hw(cyber2000_res + i);
+
+	fetchrow = scr_pitch + 1;
+
+	debug_printf("Setting regs: pitch=%X, fetchrow=%X, col=%X, b=%X\n",
+		     scr_pitch, fetchrow, col, b);
+
+	cyber2000_outb(0x13, 0x3d4);
+	cyber2000_outb(scr_pitch, 0x3d5);
+	cyber2000_outb(0x14, 0x3ce);
+	cyber2000_outb(fetchrow, 0x3cf);
+	cyber2000_outb(0x15, 0x3ce);
+					/* FIXME: is this the right way round? */
+	cyber2000_outb(((fetchrow >> 4) & 0xf0) | ((scr_pitch >> 8) & 0x0f), 0x3cf);
+	cyber2000_outb(0x77, 0x3ce);
+	cyber2000_outb(col, 0x3cf);
+
+
+	cyber2000_outb(0x33, 0x3ce);
+	cyber2000_outb(0x1c, 0x3cf);
+
+	cyber2000_outw(width - 1, 0xbf018);
+	cyber2000_outw(width - 1, 0xbf218);
+	cyber2000_outb(b, 0xbf01c);
+
+	return 0;
+}
+
+static inline void
+cyber2000fb_update_start(struct fb_var_screeninfo *var)
+{
+#if 0
+	unsigned int base;
+
+	base = var->yoffset * var->xres_virtual + var->xoffset;
+
+	cyber2000_outb(0x0c, 0x3d4);
+	cyber2000_outb(base, 0x3d5);
+	cyber2000_outb(0x0d, 0x3d4);
+	cyber2000_outb(base >> 8, 0x3d5);
+	/* FIXME: need the upper bits of the start offset */
+/*	cyber2000_outb(0x??, 0x3d4);
+	cyber2000_outb(base >> 16, 0x3d5);*/
+#endif
+}
+
+/*
+ *  Open/Release the frame buffer device
+ */
+static int cyber2000fb_open(struct fb_info *info, int user)
+{
+	MOD_INC_USE_COUNT;
+	return 0;
+}
+
+static int cyber2000fb_release(struct fb_info *info, int user)
+{
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+/*
+ *    Get the Colormap
+ */
+static int
+cyber2000fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
+		     struct fb_info *info)
+{
+	int err = 0;
+
+	if (con == current_par.currcon)	/* current console? */
+		err = fb_get_cmap(cmap, kspc, cyber2000_getcolreg, info);
+	else if (fb_display[con].cmap.len)	/* non default colormap? */
+		fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
+	else
+		fb_copy_cmap(fb_default_cmap(1 << fb_display[con].var.bits_per_pixel),
+			     cmap, kspc ? 0 : 2);
+	return err;
+}
+
+
+/*
+ *    Set the Colormap
+ */
+static int
+cyber2000fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
+		     struct fb_info *info)
+{
+	struct display *disp = &fb_display[con];
+	int err = 0;
+
+	if (!disp->cmap.len) {	/* no colormap allocated? */
+		int size;
+
+		if (disp->var.bits_per_pixel == 16)
+			size = 32;
+		else
+			size = 256;
+
+		err = fb_alloc_cmap(&disp->cmap, size, 0);
+	}
+	if (!err) {
+		if (con == current_par.currcon)	/* current console? */
+			err = fb_set_cmap(cmap, kspc, cyber2000_setcolreg,
+					  info);
+		else
+			fb_copy_cmap(cmap, &disp->cmap, kspc ? 0 : 1);
+	}
+
+	return err;
+}
+
+static int
+cyber2000fb_decode_var(struct fb_var_screeninfo *var, int con, int *visual)
+{
+	switch (var->bits_per_pixel) {
+#ifdef FBCON_HAS_CFB8
+	case 8:
+		*visual = FB_VISUAL_PSEUDOCOLOR;
+		break;
+#endif
+#ifdef FBCON_HAS_CFB16
+	case 16:
+		*visual = FB_VISUAL_DIRECTCOLOR;
+		break;
+#endif
+#ifdef FBCON_HAS_CFB24
+	case 24:
+		*visual = FB_VISUAL_TRUECOLOR;
+		break;
+#endif
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*
+ *    Get the Fixed Part of the Display
+ */
+static int
+cyber2000fb_get_fix(struct fb_fix_screeninfo *fix, int con,
+		    struct fb_info *fb_info)
+{
+	struct display *display;
+
+	memset(fix, 0, sizeof(struct fb_fix_screeninfo));
+	strcpy(fix->id, "Cyber2000");
+
+	if (con >= 0)
+		display = fb_display + con;
+	else
+		display = &global_disp;
+
+	fix->smem_start	 = (char *)current_par.screen_base_p;
+	fix->smem_len	 = current_par.screen_size;
+	fix->mmio_start	 = (char *)current_par.regs_base_p;
+	fix->mmio_len	 = 0x000c0000;
+	fix->type	 = display->type;
+	fix->type_aux	 = display->type_aux;
+	fix->xpanstep	 = 0;
+	fix->ypanstep	 = display->ypanstep;
+	fix->ywrapstep	 = display->ywrapstep;
+	fix->visual	 = display->visual;
+	fix->line_length = display->line_length;
+	fix->accel	 = 22; /*FB_ACCEL_IGS_CYBER2000*/
+
+	return 0;
+}
+
+
+/*
+ *    Get the User Defined Part of the Display
+ */
+static int
+cyber2000fb_get_var(struct fb_var_screeninfo *var, int con,
+		    struct fb_info *fb_info)
+{
+	if (con == -1)
+		*var = global_disp.var;
+	else
+		*var = fb_display[con].var;
+
+	return 0;
+}
+
+/*
+ *    Set the User Defined Part of the Display
+ */
+static int
+cyber2000fb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
+{
+	struct display *display;
+	int err, chgvar = 0, visual;
+
+	if (con >= 0)
+		display = fb_display + con;
+	else
+		display = &global_disp;
+
+	err = cyber2000fb_decode_var(var, con, &visual);
+	if (err)
+		return err;
+
+	switch (var->activate & FB_ACTIVATE_MASK) {
+	case FB_ACTIVATE_TEST:
+		return 0;
+
+	case FB_ACTIVATE_NXTOPEN:
+	case FB_ACTIVATE_NOW:
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	if (con >= 0) {
+		if (display->var.xres != var->xres)
+			chgvar = 1;
+		if (display->var.yres != var->yres)
+			chgvar = 1;
+		if (display->var.xres_virtual != var->xres_virtual)
+			chgvar = 1;
+		if (display->var.yres_virtual != var->yres_virtual)
+			chgvar = 1;
+		if (display->var.accel_flags != var->accel_flags)
+			chgvar = 1;
+		if (memcmp(&display->var.red, &var->red, sizeof(var->red)))
+			chgvar = 1;
+		if (memcmp(&display->var.green, &var->green, sizeof(var->green)))
+			chgvar = 1;
+		if (memcmp(&display->var.blue, &var->blue, sizeof(var->green)))
+			chgvar = 1;
+	}
+
+	display->var = *var;
+
+	display->screen_base	= (char *)current_par.screen_base;
+	display->visual		= visual;
+	display->type		= FB_TYPE_PACKED_PIXELS;
+	display->type_aux	= 0;
+	display->ypanstep	= 0;
+	display->ywrapstep	= 0;
+	display->line_length	=
+	display->next_line	= (var->xres_virtual * var->bits_per_pixel) / 8;
+	display->can_soft_blank = 1;
+	display->inverse	= 0;
+
+	switch (display->var.bits_per_pixel) {
+#ifdef FBCON_HAS_CFB8
+	case 8:
+		dispsw = &fbcon_cfb8;
+		display->dispsw_data = NULL;
+		break;
+#endif
+#ifdef FBCON_HAS_CFB16
+	case 16:
+		dispsw = &fbcon_cfb16;
+		display->dispsw_data = current_par.c_table.cfb16;
+		break;
+#endif
+#ifdef FBCON_HAS_CFB24
+	case 24:
+		dispsw = &fbcon_cfb24;
+		display->dispsw_data = current_par.c_table.cfb24;
+		break;
+#endif
+	default:
+		printk(KERN_WARNING "cyber2000: no support for %dbpp\n",
+		       display->var.bits_per_pixel);
+		dispsw = &fbcon_dummy;
+		break;
+	}
+
+	if (display->var.accel_flags & FB_ACCELF_TEXT &&
+	    dispsw != &fbcon_dummy)
+		display->dispsw = &fbcon_cyber_accel;
+	else
+		display->dispsw = dispsw;
+
+	if (chgvar && info && info->changevar)
+		info->changevar(con);
+
+	if (con == current_par.currcon) {
+		struct fb_cmap *cmap;
+
+		cyber2000fb_update_start(var);
+		cyber2000fb_set_timing(var);
+
+		if (display->cmap.len)
+			cmap = &display->cmap;
+		else
+			cmap = fb_default_cmap(current_par.palette_size);
+
+		fb_set_cmap(cmap, 1, cyber2000_setcolreg, info);
+	}
+	return 0;
+}
+
+
+/*
+ *    Pan or Wrap the Display
+ */
+static int cyber2000fb_pan_display(struct fb_var_screeninfo *var, int con,
+				   struct fb_info *info)
+{
+	u_int y_bottom;
+
+	y_bottom = var->yoffset;
+
+	if (!(var->vmode & FB_VMODE_YWRAP))
+		y_bottom += var->yres;
+
+	if (var->xoffset > (var->xres_virtual - var->xres))
+		return -EINVAL;
+	if (y_bottom > fb_display[con].var.yres_virtual)
+		return -EINVAL;
+return -EINVAL;
+
+	cyber2000fb_update_start(var);
+
+	fb_display[con].var.xoffset = var->xoffset;
+	fb_display[con].var.yoffset = var->yoffset;
+	if (var->vmode & FB_VMODE_YWRAP)
+		fb_display[con].var.vmode |= FB_VMODE_YWRAP;
+	else
+		fb_display[con].var.vmode &= ~FB_VMODE_YWRAP;
+
+	return 0;
+}
+
+
+static int cyber2000fb_ioctl(struct inode *inode, struct file *file,
+		    u_int cmd, u_long arg, int con, struct fb_info *info)
+{
+	return -EINVAL;
+}
+
+
+/*
+ *    Update the `var' structure (called by fbcon.c)
+ *
+ *    This call looks only at yoffset and the FB_VMODE_YWRAP flag in `var'.
+ *    Since it's called by a kernel driver, no range checking is done.
+ */
+static int
+cyber2000fb_updatevar(int con, struct fb_info *info)
+{
+	if (con == current_par.currcon)
+		cyber2000fb_update_start(&fb_display[con].var);
+	return 0;
+}
+
+static int
+cyber2000fb_switch(int con, struct fb_info *info)
+{
+	struct fb_cmap *cmap;
+
+	if (current_par.currcon >= 0) {
+		cmap = &fb_display[current_par.currcon].cmap;
+
+		if (cmap->len)
+			fb_get_cmap(cmap, 1, cyber2000_getcolreg, info);
+	}
+
+	current_par.currcon = con;
+
+	fb_display[con].var.activate = FB_ACTIVATE_NOW;
+
+	cyber2000fb_set_var(&fb_display[con].var, con, info);
+
+	return 0;
+}
+
+/*
+ *    (Un)Blank the display.
+ */
+static void cyber2000fb_blank(int blank, struct fb_info *fb_info)
+{
+	int i;
+
+	if (blank) {
+		for (i = 0; i < 256; i++) {
+			cyber2000_outb(i, 0x3c8);
+			cyber2000_outb(0, 0x3c9);
+			cyber2000_outb(0, 0x3c9);
+			cyber2000_outb(0, 0x3c9);
+		}
+	} else {
+		for (i = 0; i < 256; i++) {
+			cyber2000_outb(i, 0x3c8);
+			cyber2000_outb(current_par.palette[i].red, 0x3c9);
+			cyber2000_outb(current_par.palette[i].green, 0x3c9);
+			cyber2000_outb(current_par.palette[i].blue, 0x3c9);
+		}
+	}
+}
+
+__initfunc(void cyber2000fb_setup(char *options, int *ints))
+{
+}
+
+static struct fb_ops cyber2000fb_ops =
+{
+	cyber2000fb_open,
+	cyber2000fb_release,
+	cyber2000fb_get_fix,
+	cyber2000fb_get_var,
+	cyber2000fb_set_var,
+	cyber2000fb_get_cmap,
+	cyber2000fb_set_cmap,
+	cyber2000fb_pan_display,
+	cyber2000fb_ioctl
+};
+
+__initfunc(static void
+cyber2000fb_init_fbinfo(void))
+{
+	static int first = 1;
+
+	if (!first)
+		return;
+	first = 0;
+
+	strcpy(fb_info.modename, "Cyber2000");
+	strcpy(fb_info.fontname, "Acorn8x8");
+
+	fb_info.node			= -1;
+	fb_info.fbops			= &cyber2000fb_ops;
+	fb_info.disp			= &global_disp;
+	fb_info.changevar		= NULL;
+	fb_info.switch_con		= cyber2000fb_switch;
+	fb_info.updatevar		= cyber2000fb_updatevar;
+	fb_info.blank			= cyber2000fb_blank;
+	fb_info.flags			= FBINFO_FLAG_DEFAULT;
+
+	/*
+	 * setup initial parameters
+	 */
+	memset(&init_var, 0, sizeof(init_var));
+	init_var.xres_virtual		=
+	init_var.xres			= DEFAULT_XRES;
+	init_var.yres_virtual		=
+	init_var.yres			= DEFAULT_YRES;
+	init_var.bits_per_pixel		= DEFAULT_BPP;
+
+	init_var.red.msb_right		= 0;
+	init_var.green.msb_right	= 0;
+	init_var.blue.msb_right		= 0;
+
+	switch(init_var.bits_per_pixel) {
+	case 8:
+		init_var.bits_per_pixel	= 8;
+		init_var.red.offset	= 0;
+		init_var.red.length	= 8;
+		init_var.green.offset	= 0;
+		init_var.green.length	= 8;
+		init_var.blue.offset	= 0;
+		init_var.blue.length	= 8;
+		break;
+
+	case 16:
+		init_var.bits_per_pixel = 16;
+		init_var.red.offset	= 11;
+		init_var.red.length	= 5;
+		init_var.green.offset	= 5;
+		init_var.green.length	= 6;
+		init_var.blue.offset	= 0;
+		init_var.blue.length	= 5;
+		break;
+
+	case 24:
+		init_var.bits_per_pixel = 24;
+		init_var.red.offset	= 16;
+		init_var.red.length	= 8;
+		init_var.green.offset	= 8;
+		init_var.green.length	= 8;
+		init_var.blue.offset	= 0;
+		init_var.blue.length	= 8;
+		break;
+	}
+
+	init_var.nonstd			= 0;
+	init_var.activate		= FB_ACTIVATE_NOW;
+	init_var.height			= -1;
+	init_var.width			= -1;
+	init_var.accel_flags		= FB_ACCELF_TEXT;
+	init_var.sync			= FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT;
+	init_var.vmode			= FB_VMODE_NONINTERLACED;
+}
+
+/*
+ *    Initialization
+ */
+__initfunc(void cyber2000fb_init(void))
+{
+	struct pci_dev *dev;
+	u_int h_sync, v_sync;
+
+	dev = pci_find_device(PCI_VENDOR_ID_INTERG, 0x2000, NULL);
+	if (!dev)
+		return;
+
+	CyberRegs = bus_to_virt(dev->base_address[0]) + 0x00800000;/*FIXME*/
+
+	cyber2000_outb(0x18, 0x46e8);
+	cyber2000_outb(0x01, 0x102);
+	cyber2000_outb(0x08, 0x46e8);
+
+	cyber2000fb_init_fbinfo();
+
+	current_par.currcon		= -1;
+	current_par.screen_base_p	= 0x80000000 + dev->base_address[0];
+	current_par.screen_base		= (u_int)bus_to_virt(dev->base_address[0]);
+	current_par.screen_size		= 0x00200000;
+	current_par.regs_base_p		= 0x80800000 + dev->base_address[0];
+
+	cyber2000fb_set_var(&init_var, -1, &fb_info);
+
+	h_sync = 1953125000 / init_var.pixclock;
+	h_sync = h_sync * 512 / (init_var.xres + init_var.left_margin +
+		 init_var.right_margin + init_var.hsync_len);
+	v_sync = h_sync / (init_var.yres + init_var.upper_margin +
+		 init_var.lower_margin + init_var.vsync_len);
+
+	printk("Cyber2000: %ldkB VRAM, using %dx%d, %d.%03dkHz, %dHz\n",
+		current_par.screen_size >> 10,
+		init_var.xres, init_var.yres,
+		h_sync / 1000, h_sync % 1000, v_sync);
+
+	if (register_framebuffer(&fb_info) < 0)
+		return;
+
+	MOD_INC_USE_COUNT;	/* TODO: This driver cannot be unloaded yet */
+}
+
+
+
+#ifdef MODULE
+int init_module(void)
+{
+	cyber2000fb_init();
+	return 0;
+}
+
+void cleanup_module(void)
+{
+	/* Not reached because the usecount will never be
+	   decremented to zero */
+	unregister_framebuffer(&fb_info);
+	/* TODO: clean up ... */
+}
+
+#endif				/* MODULE */
diff -u --recursive --new-file v2.3.0/linux/drivers/video/cyber2000fb.h linux/drivers/video/cyber2000fb.h
--- v2.3.0/linux/drivers/video/cyber2000fb.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/video/cyber2000fb.h	Tue May 11 16:30:45 1999
@@ -0,0 +1,78 @@
+/*
+ * linux/drivers/video/cyber2000fb.h
+ *
+ * Integraphics Cyber2000 frame buffer device
+ */
+
+#define arraysize(x)    (sizeof(x)/sizeof(*(x)))
+#define cyber2000_outb(dat,reg)	(CyberRegs[reg] = dat)
+#define cyber2000_outw(dat,reg)	(*(unsigned short *)&CyberRegs[reg] = dat)
+#define cyber2000_outl(dat,reg)	(*(unsigned long *)&CyberRegs[reg] = dat)
+
+#define cyber2000_inb(reg)	(CyberRegs[reg])
+#define cyber2000_inw(reg)	(*(unsigned short *)&CyberRegs[reg])
+#define cyber2000_inl(reg)	(*(unsigned long *)&CyberRegs[reg])
+
+static inline void cyber2000_crtcw(int val, int reg)
+{
+	cyber2000_outb(reg, 0x3d4);
+	cyber2000_outb(val, 0x3d5);
+}
+
+static inline void cyber2000_grphw(int val, int reg)
+{
+	cyber2000_outb(reg, 0x3ce);
+	cyber2000_outb(val, 0x3cf);
+}
+
+static inline void cyber2000_attrw(int val, int reg)
+{
+	cyber2000_inb(0x3da);
+	cyber2000_outb(reg, 0x3c0);
+	cyber2000_inb(0x3c1);
+	cyber2000_outb(val, 0x3c0);
+}
+
+static inline void cyber2000_seqw(int val, int reg)
+{
+	cyber2000_outb(reg, 0x3c4);
+	cyber2000_outb(val, 0x3c5);
+}
+
+struct cyber2000fb_par {
+	unsigned long	screen_base;
+	unsigned long	screen_base_p;
+	unsigned long	regs_base;
+	unsigned long	regs_base_p;
+	unsigned long	screen_end;
+	unsigned long	screen_size;
+	unsigned int	palette_size;
+	  signed int	currcon;
+	/*
+	 * palette
+	 */
+	struct {
+		u8			red;
+		u8			green;
+		u8			blue;
+	} palette[256];
+	/*
+	 * colour mapping table
+	 */
+	union {
+#ifdef FBCON_HAS_CFB16
+		u16			cfb16[16];
+#endif
+#ifdef FBCON_HAS_CFB24
+		u32			cfb24[16];
+#endif
+	} c_table;
+};
+
+struct res {
+	int	xres;
+	int	yres;
+	unsigned char crtc_regs[18];
+	unsigned char crtc_ofl;
+	unsigned char clk_regs[4];
+};
diff -u --recursive --new-file v2.3.0/linux/drivers/video/dummycon.c linux/drivers/video/dummycon.c
--- v2.3.0/linux/drivers/video/dummycon.c	Fri Jul 31 23:19:40 1998
+++ linux/drivers/video/dummycon.c	Tue May 11 16:30:45 1999
@@ -5,7 +5,6 @@
  *  available, usually until fbcon takes console over.
  */
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/kdev_t.h>
 #include <linux/tty.h>
@@ -18,7 +17,7 @@
  *  Dummy console driver
  */
 
-#if defined(CONFIG_ARM)
+#if defined(__arm__)
 #define DUMMY_COLUMNS	ORIG_VIDEO_COLS
 #define DUMMY_ROWS	ORIG_VIDEO_LINES
 #else
diff -u --recursive --new-file v2.3.0/linux/drivers/video/fbmem.c linux/drivers/video/fbmem.c
--- v2.3.0/linux/drivers/video/fbmem.c	Thu Apr 22 19:30:08 1999
+++ linux/drivers/video/fbmem.c	Tue May 11 16:30:45 1999
@@ -44,7 +44,7 @@
      *  Frame buffer device initialization and setup routines
      */
 
-extern unsigned long acornfb_init(void);
+extern void acornfb_init(void);
 extern void acornfb_setup(char *options, int *ints);
 extern void amifb_init(void);
 extern void amifb_setup(char *options, int *ints);
@@ -56,6 +56,8 @@
 extern void cyberfb_setup(char *options, int *ints);
 extern void pm2fb_init(void);
 extern void pm2fb_setup(char *options, int *ints);
+extern void cyber2000fb_init(void);
+extern void cyber2000fb_setup(char *options, int *ints);
 extern void retz3fb_init(void);
 extern void retz3fb_setup(char *options, int *ints);
 extern void clgenfb_init(void);
@@ -120,6 +122,9 @@
 #ifdef CONFIG_FB_CYBER
 	{ "cyber", cyberfb_init, cyberfb_setup },
 #endif
+#ifdef CONFIG_FB_CYBER2000
+	{ "cyber2000", cyber2000fb_init, cyber2000fb_setup },
+#endif
 #ifdef CONFIG_FB_PM2
 	{ "pm2fb", pm2fb_init, pm2fb_setup },
 #endif
@@ -501,6 +506,13 @@
 #elif defined(__mips__)
 	pgprot_val(vma->vm_page_prot) &= ~_CACHE_MASK;
 	pgprot_val(vma->vm_page_prot) |= _CACHE_UNCACHED;
+#elif defined(__arm__)
+#if defined(CONFIG_CPU_32) && !defined(CONFIG_ARCH_ACORN)
+	/* On Acorn architectures, we want to keep the framebuffer
+	 * cached.
+	 */
+	pgprot_val(vma->vm_page_prot) &= ~(PTE_CACHEABLE | PTE_BUFFERABLE);
+#endif
 #else
 #warning What do we have to do here??
 #endif
diff -u --recursive --new-file v2.3.0/linux/drivers/video/vgacon.c linux/drivers/video/vgacon.c
--- v2.3.0/linux/drivers/video/vgacon.c	Thu Sep 17 09:35:03 1998
+++ linux/drivers/video/vgacon.c	Tue May 11 16:30:45 1999
@@ -153,7 +153,7 @@
 __initfunc(static const char *vgacon_startup(void))
 {
 	const char *display_desc = NULL;
-	u16 saved;
+	u16 saved1, saved2;
 	u16 *p;
 
 	if (ORIG_VIDEO_ISVGA == VIDEO_TYPE_VLFB) {
@@ -267,18 +267,24 @@
 	 *	Are there smarter methods around?
 	 */
 	p = (u16 *)vga_vram_base;
-	saved = scr_readw(p);
+	saved1 = scr_readw(p);
+	saved2 = scr_readw(p + 1);
 	scr_writew(0xAA55, p);
-	if (scr_readw(p) != 0xAA55) {
-		scr_writew(saved, p);
+	scr_writew(0x55AA, p + 1);
+	if (scr_readw(p) != 0xAA55 || scr_readw(p + 1) != 0x55AA) {
+		scr_writew(saved1, p);
+		scr_writew(saved2, p + 1);
 		goto no_vga;
 	}
 	scr_writew(0x55AA, p);
-	if (scr_readw(p) != 0x55AA) {
-		scr_writew(saved, p);
+	scr_writew(0xAA55, p + 1);
+	if (scr_readw(p) != 0x55AA || scr_readw(p + 1) != 0xAA55) {
+		scr_writew(saved1, p);
+		scr_writew(saved2, p + 1);
 		goto no_vga;
 	}
-	scr_writew(saved, p);
+	scr_writew(saved1, p);
+	scr_writew(saved2, p + 1);
 
 	if (vga_video_type == VIDEO_TYPE_EGAC
 	    || vga_video_type == VIDEO_TYPE_VGAC
diff -u --recursive --new-file v2.3.0/linux/fs/adfs/dir.c linux/fs/adfs/dir.c
--- v2.3.0/linux/fs/adfs/dir.c	Fri Apr 23 21:20:37 1999
+++ linux/fs/adfs/dir.c	Thu May 13 10:53:59 1999
@@ -76,13 +76,34 @@
 	return val;
 }
 
+static unsigned int adfs_filetype (unsigned int load)
+{
+	if ((load & 0xfff00000) != 0xfff00000)
+		return (unsigned int) -1;
+	return (load >> 8) & 0xfff;
+}
+
 static unsigned int adfs_time (unsigned int load, unsigned int exec)
 {
 	unsigned int high, low;
 
-	high = ((load << 24) | (exec >> 8)) - 0x336e996a;
+	/* Check for unstamped files.  */
+	if ((load & 0xfff00000) != 0xfff00000)
+		return 0;
+
+	high = ((load << 24) | (exec >> 8));
 	low  =  exec & 255;
 
+	/* Files dated pre 1970.  */
+	if (high < 0x336e996a)
+		return 0;
+
+	high -= 0x336e996a;
+
+	/* Files dated post 2038 ish.  */
+	if (high > 0x31ffffff)
+		return 0x7fffffff;
+
 	/* 65537 = h256,l1
 	 * (h256 % 100) = 56         h256 / 100 = 2
 	 *    56 << 8 = 14336           2 * 256 = 512
@@ -117,9 +138,6 @@
 	struct super_block *sb;
 	int i, size;
 
-	if (!inode)
-		return 0;
-
 	sb = inode->i_sb;
 
 	size = 2048 >> sb->s_blocksize_bits;
@@ -204,6 +222,18 @@
 		brelse (bhp[i]);
 }
 
+/* convert a disk-based directory entry to a Linux ADFS directory entry */
+static inline void
+adfs_dirent_to_idirent(struct adfs_idir_entry *ide, struct adfs_direntry *de)
+{
+	ide->name_len =	adfs_readname(ide->name, de->dirobname, ADFS_NAME_LEN);
+	ide->file_id  = adfs_val(de->dirinddiscadd, 3);
+	ide->size     = adfs_val(de->dirlen, 4);
+	ide->mode     = de->newdiratts;
+	ide->mtime    = adfs_time(adfs_val(de->dirload, 4), adfs_val(de->direxec, 4));
+	ide->filetype = adfs_filetype(adfs_val(de->dirload, 4));
+}
+
 int adfs_dir_get (struct super_block *sb, struct buffer_head **bhp,
 		  int buffers, int pos, unsigned long parent_object_id,
 		  struct adfs_idir_entry *ide)
@@ -228,13 +258,8 @@
 	if (!de.dirobname[0])
 		return 0;
 
-	ide->name_len =	adfs_readname (ide->name, de.dirobname, ADFS_NAME_LEN);
 	ide->inode_no = adfs_inode_generate (parent_object_id, pos);
-	ide->file_id  = adfs_val (de.dirinddiscadd, 3);
-	ide->size     = adfs_val (de.dirlen, 4);
-	ide->mode     = de.newdiratts;
-	ide->mtime    = adfs_time (adfs_val (de.dirload, 4), adfs_val (de.direxec, 4));
-	ide->filetype = (adfs_val (de.dirload, 4) >> 8) & 0xfff;
+	adfs_dirent_to_idirent(ide, &de);
 	return 1;
 }
 
@@ -262,12 +287,7 @@
 	if (!de.dirobname[0])
 		return 0;
 
-	ide->name_len =	adfs_readname (ide->name, de.dirobname, ADFS_NAME_LEN);
-	ide->size     = adfs_val (de.dirlen, 4);
-	ide->mode     = de.newdiratts;
-	ide->file_id  = adfs_val (de.dirinddiscadd, 3);
-	ide->mtime    = adfs_time (adfs_val (de.dirload, 4), adfs_val (de.direxec, 4));
-	ide->filetype = (adfs_val (de.dirload, 4) >> 8) & 0xfff;
+	adfs_dirent_to_idirent(ide, &de);
 	return 1;
 }	
 
diff -u --recursive --new-file v2.3.0/linux/fs/adfs/namei.c linux/fs/adfs/namei.c
--- v2.3.0/linux/fs/adfs/namei.c	Mon May 10 14:14:28 1999
+++ linux/fs/adfs/namei.c	Thu May 13 10:53:59 1999
@@ -46,9 +46,6 @@
 	unsigned long parent_object_id, dir_object_id;
 	int buffers, pos;
 
-	if (!S_ISDIR(dir->i_mode))
-		return 0;
-
 	sb = dir->i_sb;
 
 	if (adfs_inode_validate (dir)) {
@@ -56,9 +53,6 @@
 			    "invalid inode number: %lu", dir->i_ino);
 		return 0;
 	}
-
-	if (namelen > ADFS_NAME_LEN)
-		return 0;
 
 	if (!(buffers = adfs_dir_read (dir, bh))) {
 		adfs_error (sb, "adfs_find_entry", "unable to read directory");
diff -u --recursive --new-file v2.3.0/linux/fs/autofs/autofs_i.h linux/fs/autofs/autofs_i.h
--- v2.3.0/linux/fs/autofs/autofs_i.h	Tue May 11 13:04:44 1999
+++ linux/fs/autofs/autofs_i.h	Thu May 13 14:42:48 1999
@@ -66,7 +66,7 @@
 };
 
 struct autofs_wait_queue {
-	struct wait_queue *queue;
+	wait_queue_head_t queue;
 	struct autofs_wait_queue *next;
 	autofs_wqt_t wait_queue_token;
 	/* We use the following to see what we are waiting for */
diff -u --recursive --new-file v2.3.0/linux/fs/autofs/dir.c linux/fs/autofs/dir.c
--- v2.3.0/linux/fs/autofs/dir.c	Fri Apr 23 21:20:37 1999
+++ linux/fs/autofs/dir.c	Thu May 13 10:53:59 1999
@@ -16,8 +16,6 @@
 			       void *dirent, filldir_t filldir)
 {
 	struct inode *inode=filp->f_dentry->d_inode;
-	if (!inode || !S_ISDIR(inode->i_mode))
-		return -ENOTDIR;
 
 	switch((unsigned long) filp->f_pos)
 	{
diff -u --recursive --new-file v2.3.0/linux/fs/autofs/root.c linux/fs/autofs/root.c
--- v2.3.0/linux/fs/autofs/root.c	Sat May  8 17:56:37 1999
+++ linux/fs/autofs/root.c	Thu May 13 10:53:59 1999
@@ -72,9 +72,6 @@
 	struct inode * inode = filp->f_dentry->d_inode;
 	off_t onr, nr;
 
-	if (!inode || !S_ISDIR(inode->i_mode))
-		return -ENOTDIR;
-
 	sbi = autofs_sbi(inode->i_sb);
 	dirhash = &sbi->dirhash;
 	nr = filp->f_pos;
diff -u --recursive --new-file v2.3.0/linux/fs/autofs/waitq.c linux/fs/autofs/waitq.c
--- v2.3.0/linux/fs/autofs/waitq.c	Sun Feb 21 10:59:14 1999
+++ linux/fs/autofs/waitq.c	Tue May 11 14:57:04 1999
@@ -131,7 +131,7 @@
 			return -ENOMEM;
 		}
 		wq->wait_queue_token = autofs_next_wait_queue++;
-		init_waitqueue(&wq->queue);
+		init_waitqueue_head(&wq->queue);
 		wq->hash = name->hash;
 		wq->len = name->len;
 		wq->status = -EINTR; /* Status return if interrupted */
diff -u --recursive --new-file v2.3.0/linux/fs/buffer.c linux/fs/buffer.c
--- v2.3.0/linux/fs/buffer.c	Tue May 11 09:55:49 1999
+++ linux/fs/buffer.c	Thu May 13 13:47:39 1999
@@ -70,7 +70,7 @@
 
 static struct buffer_head * unused_list = NULL;
 static struct buffer_head * reuse_list = NULL;
-static struct wait_queue * buffer_wait = NULL;
+static DECLARE_WAIT_QUEUE_HEAD(buffer_wait);
 
 static int nr_buffers = 0;
 static int nr_buffers_type[NR_LIST] = {0,};
@@ -100,8 +100,7 @@
 				each time we call refill */
 		int nref_dirt; /* Dirty buffer threshold for activating bdflush
 				  when trying to refill buffers. */
-		int interval;  /* Interval (seconds) between spontaneous
-				  bdflush runs */
+		int dummy1;    /* unused */
 		int age_buffer;  /* Time for normal buffer to age before 
 				    we flush it */
 		int age_super;  /* Time for superblock to age before we 
@@ -110,10 +109,10 @@
 		int dummy3;    /* unused */
 	} b_un;
 	unsigned int data[N_PARAM];
-} bdf_prm = {{40, 500, 64, 256, 5, 30*HZ, 5*HZ, 1884, 2}};
+} bdf_prm = {{40, 500, 64, 256, 15, 30*HZ, 5*HZ, 1884, 2}};
 
 /* These are the min and max parameter values that we will allow to be assigned */
-int bdflush_min[N_PARAM] = {  0,  10,    5,   25,  1,   1*HZ,   1*HZ, 1, 1};
+int bdflush_min[N_PARAM] = {  0,  10,    5,   25,  0,   1*HZ,   1*HZ, 1, 1};
 int bdflush_max[N_PARAM] = {100,5000, 2000, 2000,100, 600*HZ, 600*HZ, 2047, 5};
 
 void wakeup_bdflush(int);
@@ -130,10 +129,9 @@
 void __wait_on_buffer(struct buffer_head * bh)
 {
 	struct task_struct *tsk = current;
-	struct wait_queue wait;
+	DECLARE_WAITQUEUE(wait, tsk);
 
 	bh->b_count++;
-	wait.task = tsk;
 	add_wait_queue(&bh->b_wait, &wait);
 repeat:
 	tsk->state = TASK_UNINTERRUPTIBLE;
@@ -929,6 +927,7 @@
 	}
 
 	memset(bh,0,sizeof(*bh));
+	init_waitqueue_head(&bh->b_wait);
 	nr_unused_buffer_heads++;
 	bh->b_next_free = unused_list;
 	unused_list = bh;
@@ -986,6 +985,7 @@
 	 */
 	if((bh = kmem_cache_alloc(bh_cachep, SLAB_BUFFER)) != NULL) {
 		memset(bh, 0, sizeof(*bh));
+		init_waitqueue_head(&bh->b_wait);
 		nr_buffer_heads++;
 		return bh;
 	}
@@ -1010,6 +1010,7 @@
 	if(!async &&
 	   (bh = kmem_cache_alloc(bh_cachep, SLAB_KERNEL)) != NULL) {
 		memset(bh, 0, sizeof(*bh));
+		init_waitqueue_head(&bh->b_wait);
 		nr_buffer_heads++;
 		return bh;
 	}
@@ -1030,7 +1031,7 @@
 static struct buffer_head * create_buffers(unsigned long page, 
 						unsigned long size, int async)
 {
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 	struct buffer_head *bh, *head;
 	long offset;
 
@@ -1554,14 +1555,15 @@
  * response to dirty buffers.  Once this process is activated, we write back
  * a limited number of buffers to the disks and then go back to sleep again.
  */
-static struct wait_queue * bdflush_done = NULL;
+static DECLARE_WAIT_QUEUE_HEAD(bdflush_wait);
+static DECLARE_WAIT_QUEUE_HEAD(bdflush_done);
 struct task_struct *bdflush_tsk = 0;
 
 void wakeup_bdflush(int wait)
 {
 	if (current == bdflush_tsk)
 		return;
-	wake_up_process(bdflush_tsk);
+	wake_up(&bdflush_wait);
 	if (wait) {
 		run_task_queue(&tq_disk);
 		sleep_on(&bdflush_done);
@@ -1570,107 +1572,82 @@
 
 
 /* 
- * Here we attempt to write back old buffers.
- * To prevent deadlocks for a loop device:
- * 1) Do non-blocking writes to loop (avoids deadlock with running
- *	out of request blocks).
- * 2) But do a blocking write if the only dirty buffers are loop buffers
- *	(otherwise we go into an infinite busy-loop).
- * 3) Quit writing loop blocks if a freelist went low (avoids deadlock
- *	with running out of free buffers for loop's "real" device).
-*/
+ * Here we attempt to write back old buffers.  We also try to flush inodes 
+ * and supers as well, since this function is essentially "update", and 
+ * otherwise there would be no way of ensuring that these quantities ever 
+ * get written back.  Ideally, we would have a timestamp on the inodes
+ * and superblocks so that we could write back only the old ones as well
+ */
 
-static inline void sync_old_buffers(void)
+static int sync_old_buffers(void)
 {
 	int i;
-	int ndirty = 0;
-	int wrta_cmd = WRITEA;
-#ifdef DEBUG
-	int ncount = 0, nwritten = 0;
-#endif
+	int ndirty, nwritten;
+	int nlist;
+	int ncount;
 	struct buffer_head * bh, *next;
 
-#ifdef DEBUG
-	bh = lru_list[BUF_CLEAN];
-	if(bh)
-		for(i = nr_buffers_type[BUF_CLEAN]; --i > 0; bh = next) {
-			next = bh->b_next_free;
+	sync_supers(0);
+	sync_inodes(0);
 
-			/* Dirty/locked buffer on clean list?  Refile it */
-			if (buffer_locked(bh) || buffer_dirty(bh)) {
-				ncount++;
-				refile_buffer(bh);
-			}
-		}
+	ncount = 0;
+#ifdef DEBUG
+	for(nlist = 0; nlist < NR_LIST; nlist++)
+#else
+	for(nlist = BUF_LOCKED; nlist <= BUF_DIRTY; nlist++)
 #endif
+	{
+		ndirty = 0;
+		nwritten = 0;
+	repeat:
 
-	bh = lru_list[BUF_LOCKED];
-	if(bh)
-		for(i = nr_buffers_type[BUF_LOCKED]; --i > 0; bh = next) {
-			next = bh->b_next_free;
-
-			/* Unlocked buffer on locked list?  Refile it */
-			if (!buffer_locked(bh))
-				refile_buffer(bh);
-		}
-
- restart:
-	bh = lru_list[BUF_DIRTY];
-	if(bh) 
-		for (i = nr_buffers_type[BUF_DIRTY];
-		     i-- > 0 && ndirty < bdf_prm.b_un.ndirty; 
-		     bh = next) {
-			/* We may have stalled while waiting for
-			   I/O to complete. */
-			if(bh->b_list != BUF_DIRTY)
-				goto restart;
-			next = bh->b_next_free;
-			if(!lru_list[BUF_DIRTY]) {
-				printk("Dirty list empty %d\n", i);
-				break;
-			}
-					  
-			/* Clean buffer on dirty list?  Refile it */
-			if (!buffer_dirty(bh)) {
-				refile_buffer(bh);
-				continue;
-			}
-					  
-			if (buffer_locked(bh))
-				continue;
-			/* Should we write back buffers that are
-			   shared or not??  Currently dirty buffers
-			   are not shared, so it does not matter */
-			next->b_count++;
-			bh->b_count++;
-			ndirty++;
-			bh->b_flushtime = 0;
-			if (MAJOR(bh->b_dev) == LOOP_MAJOR) {
-				ll_rw_block(wrta_cmd,1, &bh);
-				wrta_cmd = WRITEA;
-				if (buffer_dirty(bh))
-					--ndirty;
-			}
-			else
-				ll_rw_block(WRITE, 1, &bh);
-			bh->b_count--;
-			next->b_count--;
-		}
-	/* If we didn't write anything, but there are still
-	 * dirty buffers, then make the next write to a
-	 * loop device to be a blocking write.
-	 * This lets us block--which we _must_ do! */
-	if (ndirty == 0
-	    && nr_buffers_type[BUF_DIRTY] > 0 && wrta_cmd != WRITE) {
-		wrta_cmd = WRITE;
-		goto restart;
+		bh = lru_list[nlist];
+		if(bh) 
+			 for (i = nr_buffers_type[nlist]; i-- > 0; bh = next) {
+				 /* We may have stalled while waiting for I/O to complete. */
+				 if(bh->b_list != nlist) goto repeat;
+				 next = bh->b_next_free;
+				 if(!lru_list[nlist]) {
+					 printk("Dirty list empty %d\n", i);
+					 break;
+				 }
+				 
+				 /* Clean buffer on dirty list?  Refile it */
+				 if (nlist == BUF_DIRTY && !buffer_dirty(bh) && !buffer_locked(bh)) {
+					 refile_buffer(bh);
+					 continue;
+				 }
+				  
+				  /* Unlocked buffer on locked list?  Refile it */
+				  if (nlist == BUF_LOCKED && !buffer_locked(bh)) {
+					  refile_buffer(bh);
+					  continue;
+				  }
+				 
+				 if (buffer_locked(bh) || !buffer_dirty(bh))
+					  continue;
+				 ndirty++;
+				 if(time_before(jiffies, bh->b_flushtime))
+					continue;
+				 nwritten++;
+				 next->b_count++;
+				 bh->b_count++;
+				 bh->b_flushtime = 0;
+#ifdef DEBUG
+				 if(nlist != BUF_DIRTY) ncount++;
+#endif
+				 ll_rw_block(WRITE, 1, &bh);
+				 bh->b_count--;
+				 next->b_count--;
+			 }
 	}
-
+	run_task_queue(&tq_disk);
 #ifdef DEBUG
 	if (ncount) printk("sync_old_buffers: %d dirty buffers not on dirty list\n", ncount);
-	printk("wrote %d/%d buffers...", nwritten, ndirty);
+	printk("Wrote %d/%d buffers\n", nwritten, ndirty);
 #endif
 	run_task_queue(&tq_disk);
+	return 0;
 }
 
 
@@ -1687,12 +1664,10 @@
 	if (!capable(CAP_SYS_ADMIN))
 		goto out;
 
-	if (func == 1)
-		/* Func 1 used to call sync_old_buffers; a user space
-		   daemon would call it periodically.  This is no
-		   longer necessary.  Returning -EPERM here makes the
-		   daemon silently exit.  */
-		goto out;
+	if (func == 1) {
+		 error = sync_old_buffers();
+		 goto out;
+	}
 
 	/* Basically func 1 means read param 1, 2 means write param 1, etc */
 	if (func >= 2) {
@@ -1721,17 +1696,27 @@
 	return error;
 }
 
-/* This is the actual bdflush daemon itself. It used to be started
- * from the syscall above, but now we launch it ourselves internally
- * with kernel_thread(...)  directly after the first thread in
- * init/main.c.  Every so often, or when woken up by another task that
- * needs memory, we call sync_old_buffers to partially clear the dirty list.
- */
+/* This is the actual bdflush daemon itself. It used to be started from
+ * the syscall above, but now we launch it ourselves internally with
+ * kernel_thread(...)  directly after the first thread in init/main.c */
 
+/* To prevent deadlocks for a loop device:
+ * 1) Do non-blocking writes to loop (avoids deadlock with running
+ *	out of request blocks).
+ * 2) But do a blocking write if the only dirty buffers are loop buffers
+ *	(otherwise we go into an infinite busy-loop).
+ * 3) Quit writing loop blocks if a freelist went low (avoids deadlock
+ *	with running out of free buffers for loop's "real" device).
+*/
 int bdflush(void * unused) 
 {
-	long remaining = HZ * bdf_prm.b_un.interval;
-	struct task_struct *tsk = current;
+	int i;
+	int ndirty;
+	int nlist;
+	int ncount;
+	struct buffer_head * bh, *next;
+	int major;
+	int wrta_cmd = WRITEA;	/* non-blocking write for LOOP */
 
 	/*
 	 *	We have a bare-bones task_struct, and really should fill
@@ -1739,12 +1724,10 @@
 	 *	display semi-sane things. Not real crucial though...  
 	 */
 
-	tsk->session = 1;
-	tsk->pgrp = 1;
-	tsk->dumpable = 0;  /* inhibit ptrace() */
-	strcpy(tsk->comm, "kflushd");
-	sigfillset(&tsk->blocked);
-	bdflush_tsk = tsk;
+	current->session = 1;
+	current->pgrp = 1;
+	sprintf(current->comm, "kflushd");
+	bdflush_tsk = current;
 
 	/*
 	 *	As a kernel thread we want to tamper with system buffers
@@ -1754,36 +1737,93 @@
 	lock_kernel();
 		 
 	for (;;) {
-		tsk->state = TASK_INTERRUPTIBLE;
-		remaining = schedule_timeout(remaining);
-
 #ifdef DEBUG
 		printk("bdflush() activated...");
 #endif
-		CHECK_EMERGENCY_SYNC
 
-		if (remaining == 0) {
-			/*
-			 * Also try to flush inodes and supers, since
-			 * otherwise there would be no way of ensuring
-			 * that these quantities ever get written
-			 * back.  Ideally, we would have a timestamp
-			 * on the inodes and superblocks so that we
-			 * could write back only the old ones.
-			 */
-			sync_supers(0);
-			sync_inodes(0);
-			remaining = HZ * bdf_prm.b_un.interval;
-		}
-			
-		/* Keep flushing till there aren't very many dirty buffers */
-		do {
-			sync_old_buffers();
-		} while(nr_buffers_type[BUF_DIRTY] > nr_buffers * bdf_prm.b_un.nfract/100);
+		CHECK_EMERGENCY_SYNC
 
-		wake_up(&bdflush_done);
+		ncount = 0;
 #ifdef DEBUG
+		for(nlist = 0; nlist < NR_LIST; nlist++)
+#else
+		for(nlist = BUF_LOCKED; nlist <= BUF_DIRTY; nlist++)
+#endif
+		 {
+			 ndirty = 0;
+		 repeat:
+
+			 bh = lru_list[nlist];
+			 if(bh) 
+				  for (i = nr_buffers_type[nlist]; i-- > 0 && ndirty < bdf_prm.b_un.ndirty; 
+				       bh = next) {
+					  /* We may have stalled while waiting for I/O to complete. */
+					  if(bh->b_list != nlist) goto repeat;
+					  next = bh->b_next_free;
+					  if(!lru_list[nlist]) {
+						  printk("Dirty list empty %d\n", i);
+						  break;
+					  }
+					  
+					  /* Clean buffer on dirty list?  Refile it */
+					  if (nlist == BUF_DIRTY && !buffer_dirty(bh)) {
+						  refile_buffer(bh);
+						  continue;
+					  }
+					  
+					  /* Unlocked buffer on locked list?  Refile it */
+					  if (nlist == BUF_LOCKED && !buffer_locked(bh)) {
+						  refile_buffer(bh);
+						  continue;
+					  }
+					  
+					  if (buffer_locked(bh) || !buffer_dirty(bh))
+						   continue;
+					  major = MAJOR(bh->b_dev);
+					  /* Should we write back buffers that are shared or not??
+					     currently dirty buffers are not shared, so it does not matter */
+					  next->b_count++;
+					  bh->b_count++;
+					  ndirty++;
+					  bh->b_flushtime = 0;
+					  if (major == LOOP_MAJOR) {
+						  ll_rw_block(wrta_cmd,1, &bh);
+						  wrta_cmd = WRITEA;
+						  if (buffer_dirty(bh))
+							  --ndirty;
+					  }
+					  else
+					  ll_rw_block(WRITE, 1, &bh);
+#ifdef DEBUG
+					  if(nlist != BUF_DIRTY) ncount++;
+#endif
+					  bh->b_count--;
+					  next->b_count--;
+				  }
+		 }
+#ifdef DEBUG
+		if (ncount) printk("sys_bdflush: %d dirty buffers not on dirty list\n", ncount);
 		printk("sleeping again.\n");
 #endif
+		/* If we didn't write anything, but there are still
+		 * dirty buffers, then make the next write to a
+		 * loop device to be a blocking write.
+		 * This lets us block--which we _must_ do! */
+		if (ndirty == 0 && nr_buffers_type[BUF_DIRTY] > 0 && wrta_cmd != WRITE) {
+			wrta_cmd = WRITE;
+			continue;
+		}
+		run_task_queue(&tq_disk);
+		wake_up(&bdflush_done);
+		
+		/* If there are still a lot of dirty buffers around, skip the sleep
+		   and flush some more */
+		if(ndirty == 0 || nr_buffers_type[BUF_DIRTY] <= nr_buffers * bdf_prm.b_un.nfract/100) {
+			spin_lock_irq(&current->sigmask_lock);
+			flush_signals(current);
+			spin_unlock_irq(&current->sigmask_lock);
+
+			interruptible_sleep_on(&bdflush_wait);
+		}
 	}
 }
diff -u --recursive --new-file v2.3.0/linux/fs/coda/cnode.c linux/fs/coda/cnode.c
--- v2.3.0/linux/fs/coda/cnode.c	Mon Jan 25 10:28:35 1999
+++ linux/fs/coda/cnode.c	Tue May 11 23:01:40 1999
@@ -29,21 +29,8 @@
                 inode->i_op = &coda_dir_inode_operations;
         else if (S_ISLNK(inode->i_mode))
                 inode->i_op = &coda_symlink_inode_operations;
-        else if (S_ISCHR(inode->i_mode)) {
-                inode->i_op = &chrdev_inode_operations;
-                inode->i_rdev = to_kdev_t(attr->va_rdev);
-        } else if (S_ISBLK(inode->i_mode)) {
-                inode->i_op = &blkdev_inode_operations;
-                inode->i_rdev = to_kdev_t(attr->va_rdev);
-        } else if (S_ISFIFO(inode->i_mode))
-                init_fifo(inode);
-	else if (S_ISSOCK(inode->i_mode))
-		inode->i_op = NULL;
-        else {
-                printk ("coda_fill_inode: what's this? i_mode = %o\n", 
-			inode->i_mode);
-                inode->i_op = NULL;
-        }
+        else
+                init_special_inode(inode, inode->i_mode, attr->va_rdev);
 }
 
 /* this is effectively coda_iget:
diff -u --recursive --new-file v2.3.0/linux/fs/coda/psdev.c linux/fs/coda/psdev.c
--- v2.3.0/linux/fs/coda/psdev.c	Thu Jan  7 13:40:57 1999
+++ linux/fs/coda/psdev.c	Wed May 12 08:41:15 1999
@@ -361,6 +361,7 @@
 	}
 	memset(&coda_upc_comm, 0, sizeof(coda_upc_comm));
 	memset(&coda_super_info, 0, sizeof(coda_super_info));
+	init_waitqueue_head(&coda_upc_comm.vc_waitq);
 
 	coda_sysctl_init();
 
diff -u --recursive --new-file v2.3.0/linux/fs/coda/upcall.c linux/fs/coda/upcall.c
--- v2.3.0/linux/fs/coda/upcall.c	Wed Mar 10 17:03:52 1999
+++ linux/fs/coda/upcall.c	Tue May 11 23:04:59 1999
@@ -587,7 +587,7 @@
 
 static inline unsigned long coda_waitfor_upcall(struct upc_req *vmp)
 {
-	struct wait_queue	wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 	unsigned long posttime;
 
 	vmp->uc_posttime = jiffies;
@@ -662,7 +662,7 @@
 	req->uc_outSize = *outSize ? *outSize : inSize;
 	req->uc_opcode = ((union inputArgs *)buffer)->ih.opcode;
 	req->uc_unique = ++vcommp->vc_seq;
-        req->uc_sleep = NULL;
+	init_waitqueue_head(&req->uc_sleep);
 	
 	/* Fill in the common input args. */
 	((union inputArgs *)buffer)->ih.unique = req->uc_unique;
diff -u --recursive --new-file v2.3.0/linux/fs/devices.c linux/fs/devices.c
--- v2.3.0/linux/fs/devices.c	Wed Dec 23 11:39:49 1998
+++ linux/fs/devices.c	Tue May 11 23:01:41 1999
@@ -370,3 +370,21 @@
 	sprintf(buffer, "%s(%d,%d)", name, MAJOR(dev), MINOR(dev));
 	return buffer;
 }
+
+void init_special_inode(struct inode *inode, umode_t mode, int rdev)
+{
+	inode->i_mode = mode;
+	inode->i_op = NULL;
+	if (S_ISCHR(mode)) {
+		inode->i_op = &chrdev_inode_operations;
+		inode->i_rdev = to_kdev_t(rdev);
+	} else if (S_ISBLK(mode)) {
+		inode->i_op = &blkdev_inode_operations;
+		inode->i_rdev = to_kdev_t(rdev);
+	} else if (S_ISFIFO(mode))
+		init_fifo(inode);
+	else if (S_ISSOCK(mode))
+		;
+	else
+		printk(KERN_DEBUG "init_special_inode: bogus imode (%o)\n", mode);
+}
diff -u --recursive --new-file v2.3.0/linux/fs/dquot.c linux/fs/dquot.c
--- v2.3.0/linux/fs/dquot.c	Fri May  7 18:04:12 1999
+++ linux/fs/dquot.c	Thu May 13 14:31:27 1999
@@ -79,8 +79,8 @@
 static int dquot_updating[NR_DQHASH];
 
 static struct dqstats dqstats;
-static struct wait_queue *dquot_wait = (struct wait_queue *)NULL,
-                         *update_wait = (struct wait_queue *)NULL;
+static DECLARE_WAIT_QUEUE_HEAD(dquot_wait);
+static DECLARE_WAIT_QUEUE_HEAD(update_wait);
 
 static inline char is_enabled(struct vfsmount *vfsmnt, short type)
 {
@@ -195,7 +195,7 @@
 
 static void __wait_on_dquot(struct dquot *dquot)
 {
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 
 	add_wait_queue(&dquot->dq_wait, &wait);
 repeat:
@@ -429,6 +429,7 @@
 
 		nr_dquots++;
 		memset((caddr_t)dquot, 0, sizeof(struct dquot));
+		init_waitqueue_head(&dquot->dq_wait);
 		/* all dquots go on the inuse_list */
 		put_inuse(dquot);
 		put_dquot_head(dquot);
diff -u --recursive --new-file v2.3.0/linux/fs/ext2/ialloc.c linux/fs/ext2/ialloc.c
--- v2.3.0/linux/fs/ext2/ialloc.c	Tue Oct 20 14:08:14 1998
+++ linux/fs/ext2/ialloc.c	Tue May 11 14:37:47 1999
@@ -268,21 +268,6 @@
 }
 
 /*
- * This function increments the inode version number
- *
- * This may be used one day by the NFS server
- */
-static void inc_inode_version (struct inode * inode,
-			       struct ext2_group_desc *gdp,
-			       int mode)
-{
-	inode->u.ext2_i.i_version++;
-	mark_inode_dirty(inode);
-
-	return;
-}
-
-/*
  * There are two policies for allocating an inode.  If the new inode is
  * a directory, then a forward search is made for a block group with both
  * free space and a low directory-to-inode ratio; if that fails, then of
@@ -493,8 +478,8 @@
 	if (inode->u.ext2_i.i_flags & EXT2_SYNC_FL)
 		inode->i_flags |= MS_SYNCHRONOUS;
 	insert_inode_hash(inode);
+	inode->i_generation++;
 	mark_inode_dirty(inode);
-	inc_inode_version (inode, gdp, mode);
 
 	unlock_super (sb);
 	if(DQUOT_ALLOC_INODE(sb, inode)) {
diff -u --recursive --new-file v2.3.0/linux/fs/ext2/inode.c linux/fs/ext2/inode.c
--- v2.3.0/linux/fs/ext2/inode.c	Tue May  4 16:27:07 1999
+++ linux/fs/ext2/inode.c	Tue May 11 23:01:41 1999
@@ -562,22 +562,18 @@
 			<< 32;
 #endif
 	}
-	inode->u.ext2_i.i_version = le32_to_cpu(raw_inode->i_version);
+	inode->i_generation = le32_to_cpu(raw_inode->i_generation);
 	inode->u.ext2_i.i_block_group = block_group;
 	inode->u.ext2_i.i_next_alloc_block = 0;
 	inode->u.ext2_i.i_next_alloc_goal = 0;
 	if (inode->u.ext2_i.i_prealloc_count)
 		ext2_error (inode->i_sb, "ext2_read_inode",
 			    "New inode has non-zero prealloc count!");
-	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
-		inode->i_rdev = to_kdev_t(le32_to_cpu(raw_inode->i_block[0]));
-	else if (S_ISLNK(inode->i_mode) && !inode->i_blocks)
+	if (S_ISLNK(inode->i_mode) && !inode->i_blocks)
 		for (block = 0; block < EXT2_N_BLOCKS; block++)
 			inode->u.ext2_i.i_data[block] = raw_inode->i_block[block];
 	else for (block = 0; block < EXT2_N_BLOCKS; block++)
 		inode->u.ext2_i.i_data[block] = le32_to_cpu(raw_inode->i_block[block]);
-	brelse (bh);
-	inode->i_op = NULL;
 	if (inode->i_ino == EXT2_ACL_IDX_INO ||
 	    inode->i_ino == EXT2_ACL_DATA_INO)
 		/* Nothing to do */ ;
@@ -587,12 +583,10 @@
 		inode->i_op = &ext2_dir_inode_operations;
 	else if (S_ISLNK(inode->i_mode))
 		inode->i_op = &ext2_symlink_inode_operations;
-	else if (S_ISCHR(inode->i_mode))
-		inode->i_op = &chrdev_inode_operations;
-	else if (S_ISBLK(inode->i_mode))
-		inode->i_op = &blkdev_inode_operations;
-	else if (S_ISFIFO(inode->i_mode))
-		init_fifo(inode);
+	else 
+		init_special_inode(inode, inode->i_mode,
+				   le32_to_cpu(raw_inode->i_block[0]));
+	brelse (bh);
 	inode->i_attr_flags = 0;
 	if (inode->u.ext2_i.i_flags & EXT2_SYNC_FL) {
 		inode->i_attr_flags |= ATTR_FLAG_SYNCRONOUS;
@@ -692,7 +686,7 @@
 		raw_inode->i_size_high = cpu_to_le32(inode->i_size >> 32);
 #endif
 	}
-	raw_inode->i_version = cpu_to_le32(inode->u.ext2_i.i_version);
+	raw_inode->i_generation = cpu_to_le32(inode->i_generation);
 	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
 		raw_inode->i_block[0] = cpu_to_le32(kdev_t_to_nr(inode->i_rdev));
 	else if (S_ISLNK(inode->i_mode) && !inode->i_blocks)
diff -u --recursive --new-file v2.3.0/linux/fs/ext2/ioctl.c linux/fs/ext2/ioctl.c
--- v2.3.0/linux/fs/ext2/ioctl.c	Wed May  6 10:56:05 1998
+++ linux/fs/ext2/ioctl.c	Tue May 11 14:37:47 1999
@@ -69,13 +69,13 @@
 		mark_inode_dirty(inode);
 		return 0;
 	case EXT2_IOC_GETVERSION:
-		return put_user(inode->u.ext2_i.i_version, (int *) arg);
+		return put_user(inode->i_generation, (int *) arg);
 	case EXT2_IOC_SETVERSION:
 		if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
 			return -EPERM;
 		if (IS_RDONLY(inode))
 			return -EROFS;
-		if (get_user(inode->u.ext2_i.i_version, (int *) arg))
+		if (get_user(inode->i_generation, (int *) arg))
 			return -EFAULT;	
 		inode->i_ctime = CURRENT_TIME;
 		mark_inode_dirty(inode);
diff -u --recursive --new-file v2.3.0/linux/fs/ext2/namei.c linux/fs/ext2/namei.c
--- v2.3.0/linux/fs/ext2/namei.c	Mon May 10 14:14:28 1999
+++ linux/fs/ext2/namei.c	Thu May 13 10:53:59 1999
@@ -347,6 +347,25 @@
 	return -ENOENT;
 }
 
+static inline void ext2_set_de_type(struct super_block *sb,
+				struct ext2_dir_entry_2 *de,
+				umode_t mode) {
+	if (!EXT2_HAS_INCOMPAT_FEATURE(sb, EXT2_FEATURE_INCOMPAT_FILETYPE))
+		return;
+	if (S_ISCHR(mode))
+		de->file_type = EXT2_FT_CHRDEV;
+	else if (S_ISBLK(mode))
+		de->file_type = EXT2_FT_BLKDEV;
+	else if (S_ISFIFO(mode))  
+		de->file_type = EXT2_FT_FIFO;
+	else if (S_ISLNK(mode))
+		de->file_type = EXT2_FT_SYMLINK;
+	else if (S_ISREG(mode))
+		de->file_type = EXT2_FT_REG_FILE;
+	else if (S_ISDIR(mode))  
+		de->file_type = EXT2_FT_DIR;
+}
+
 /*
  * By the time this is called, we already have created
  * the directory cache entry for the new file, but it
@@ -380,9 +399,7 @@
 		return err;
 	}
 	de->inode = cpu_to_le32(inode->i_ino);
-	if (EXT2_HAS_INCOMPAT_FEATURE(dir->i_sb,
-				      EXT2_FEATURE_INCOMPAT_FILETYPE))
-		de->file_type = EXT2_FT_REG_FILE;
+	ext2_set_de_type(dir->i_sb, de, S_IFREG);
 	dir->i_version = ++event;
 	mark_buffer_dirty(bh, 1);
 	if (IS_SYNC(dir)) {
@@ -406,36 +423,13 @@
 		goto out;
 
 	inode->i_uid = current->fsuid;
-	inode->i_mode = mode;
-	inode->i_op = NULL;
+	init_special_inode(inode, mode, rdev);
 	bh = ext2_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err);
 	if (!bh)
 		goto out_no_entry;
 	de->inode = cpu_to_le32(inode->i_ino);
 	dir->i_version = ++event;
-	if (S_ISREG(inode->i_mode)) {
-		inode->i_op = &ext2_file_inode_operations;
-		if (EXT2_HAS_INCOMPAT_FEATURE(dir->i_sb,
-					      EXT2_FEATURE_INCOMPAT_FILETYPE))
-			de->file_type = EXT2_FT_REG_FILE;
-	} else if (S_ISCHR(inode->i_mode)) {
-		inode->i_op = &chrdev_inode_operations;
-		if (EXT2_HAS_INCOMPAT_FEATURE(dir->i_sb,
-					      EXT2_FEATURE_INCOMPAT_FILETYPE))
-			de->file_type = EXT2_FT_CHRDEV;
-	} else if (S_ISBLK(inode->i_mode)) {
-		inode->i_op = &blkdev_inode_operations;
-		if (EXT2_HAS_INCOMPAT_FEATURE(dir->i_sb,
-					      EXT2_FEATURE_INCOMPAT_FILETYPE))
-			de->file_type = EXT2_FT_BLKDEV;
-	} else if (S_ISFIFO(inode->i_mode))  {
-		init_fifo(inode);
-		if (EXT2_HAS_INCOMPAT_FEATURE(dir->i_sb,
-					      EXT2_FEATURE_INCOMPAT_FILETYPE))
-			de->file_type = EXT2_FT_FIFO;
-	}
-	if (S_ISBLK(mode) || S_ISCHR(mode))
-		inode->i_rdev = to_kdev_t(rdev);
+	ext2_set_de_type(dir->i_sb, de, inode->i_mode);
 	mark_inode_dirty(inode);
 	mark_buffer_dirty(bh, 1);
 	if (IS_SYNC(dir)) {
@@ -486,17 +480,13 @@
 	de->name_len = 1;
 	de->rec_len = cpu_to_le16(EXT2_DIR_REC_LEN(de->name_len));
 	strcpy (de->name, ".");
-	if (EXT2_HAS_INCOMPAT_FEATURE(dir->i_sb,
-				      EXT2_FEATURE_INCOMPAT_FILETYPE))
-		de->file_type = EXT2_FT_DIR;
+	ext2_set_de_type(dir->i_sb, de, S_IFDIR);
 	de = (struct ext2_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len));
 	de->inode = cpu_to_le32(dir->i_ino);
 	de->rec_len = cpu_to_le16(inode->i_sb->s_blocksize - EXT2_DIR_REC_LEN(1));
 	de->name_len = 2;
 	strcpy (de->name, "..");
-	if (EXT2_HAS_INCOMPAT_FEATURE(dir->i_sb,
-				      EXT2_FEATURE_INCOMPAT_FILETYPE))
-		de->file_type = EXT2_FT_DIR;
+	ext2_set_de_type(dir->i_sb, de, S_IFDIR);
 	inode->i_nlink = 2;
 	mark_buffer_dirty(dir_block, 1);
 	brelse (dir_block);
@@ -508,9 +498,7 @@
 	if (!bh)
 		goto out_no_entry;
 	de->inode = cpu_to_le32(inode->i_ino);
-	if (EXT2_HAS_INCOMPAT_FEATURE(dir->i_sb,
-				      EXT2_FEATURE_INCOMPAT_FILETYPE))
-		de->file_type = EXT2_FT_DIR;
+	ext2_set_de_type(dir->i_sb, de, S_IFDIR);
 	dir->i_version = ++event;
 	mark_buffer_dirty(bh, 1);
 	if (IS_SYNC(dir)) {
@@ -744,9 +732,7 @@
 	if (!bh)
 		goto out_no_entry;
 	de->inode = cpu_to_le32(inode->i_ino);
-	if (EXT2_HAS_INCOMPAT_FEATURE(dir->i_sb,
-				      EXT2_FEATURE_INCOMPAT_FILETYPE))
-		de->file_type = EXT2_FT_SYMLINK;
+	ext2_set_de_type(dir->i_sb, de, S_IFLNK);
 	dir->i_version = ++event;
 	mark_buffer_dirty(bh, 1);
 	if (IS_SYNC(dir)) {
@@ -785,21 +771,7 @@
 		return err;
 
 	de->inode = cpu_to_le32(inode->i_ino);
-	if (EXT2_HAS_INCOMPAT_FEATURE(inode->i_sb,
-				      EXT2_FEATURE_INCOMPAT_FILETYPE)) {
-		if (S_ISREG(inode->i_mode))
-			de->file_type = EXT2_FT_REG_FILE;
-		else if (S_ISDIR(inode->i_mode))
-			de->file_type = EXT2_FT_DIR;
-		else if (S_ISLNK(inode->i_mode))
-			de->file_type = EXT2_FT_SYMLINK;
-		else if (S_ISCHR(inode->i_mode))
-			de->file_type = EXT2_FT_CHRDEV;
-		else if (S_ISBLK(inode->i_mode))
-			de->file_type = EXT2_FT_BLKDEV;
-		else if (S_ISFIFO(inode->i_mode))  
-			de->file_type = EXT2_FT_FIFO;
-	}
+	ext2_set_de_type(dir->i_sb, de, inode->i_mode);
 	dir->i_version = ++event;
 	mark_buffer_dirty(bh, 1);
 	if (IS_SYNC(dir)) {
@@ -869,7 +841,8 @@
 		if (le32_to_cpu(PARENT_INO(dir_bh->b_data)) != old_dir->i_ino)
 			goto end_rename;
 		retval = -EMLINK;
-		if (!new_inode && new_dir->i_nlink >= EXT2_LINK_MAX)
+		if (!new_inode && new_dir!=old_dir &&
+				new_dir->i_nlink >= EXT2_LINK_MAX)
 			goto end_rename;
 	}
 	if (!new_bh) {
diff -u --recursive --new-file v2.3.0/linux/fs/fat/inode.c linux/fs/fat/inode.c
--- v2.3.0/linux/fs/fat/inode.c	Fri Apr 23 21:20:37 1999
+++ linux/fs/fat/inode.c	Wed May 12 08:41:15 1999
@@ -464,7 +464,7 @@
 
 	sb->s_magic = MSDOS_SUPER_MAGIC;
 	/* set up enough so that it can read an inode */
-	MSDOS_SB(sb)->fat_wait = NULL;
+	init_waitqueue_head(&MSDOS_SB(sb)->fat_wait);
 	MSDOS_SB(sb)->fat_lock = 0;
 	MSDOS_SB(sb)->prev_free = 0;
 
diff -u --recursive --new-file v2.3.0/linux/fs/fat/misc.c linux/fs/fat/misc.c
--- v2.3.0/linux/fs/fat/misc.c	Tue Apr 20 14:37:10 1999
+++ linux/fs/fat/misc.c	Tue May 11 23:03:31 1999
@@ -79,7 +79,7 @@
 /* File creation lock. This is system-wide to avoid deadlocks in rename. */
 /* (rename might deadlock before detecting cross-FS moves.) */
 
-static struct wait_queue *creation_wait = NULL;
+static DECLARE_WAIT_QUEUE_HEAD(creation_wait);
 static int creation_lock = 0;
 
 
diff -u --recursive --new-file v2.3.0/linux/fs/fifo.c linux/fs/fifo.c
--- v2.3.0/linux/fs/fifo.c	Fri Nov 13 10:07:26 1998
+++ linux/fs/fifo.c	Tue May 11 14:37:40 1999
@@ -155,6 +155,6 @@
 	PIPE_BASE(*inode) = NULL;
 	PIPE_START(*inode) = PIPE_LEN(*inode) = 0;
 	PIPE_RD_OPENERS(*inode) = PIPE_WR_OPENERS(*inode) = 0;
-	PIPE_WAIT(*inode) = NULL;
+	init_waitqueue_head(&PIPE_WAIT(*inode));
 	PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 0;
 }
diff -u --recursive --new-file v2.3.0/linux/fs/hfs/ChangeLog linux/fs/hfs/ChangeLog
--- v2.3.0/linux/fs/hfs/ChangeLog	Mon Feb 15 23:55:00 1999
+++ linux/fs/hfs/ChangeLog	Wed May 12 13:26:20 1999
@@ -1,3 +1,19 @@
+1999-04-12  a sun  <asun@hecate.darksunrising.blah>
+
+	* file_hdr.c (hdr_read): added rootinfo behaviour for DID header.
+
+1999-04-11  a sun  <asun@hecate.darksunrising.blah>
+
+	* super.c (parse_options): added s_version so that we can select
+	between different versions of the same layout.
+
+1999-04-05  a sun  <asun@hecate.darksunrising.blah>
+
+	* linux/hfs_fs.h: unified netatalk and appledouble header format. 
+	added in all of the AFP attribute bits.
+
+	* file_hdr.c: added netatalk appledouble v2 compatible headers. 
+
 1999-01-30  a sun  <asun@hecate.darksunrising.blah>
 
 	* catalog.c (hfs_cat_move): fixed corruption problem with
diff -u --recursive --new-file v2.3.0/linux/fs/hfs/bnode.c linux/fs/hfs/bnode.c
--- v2.3.0/linux/fs/hfs/bnode.c	Mon Nov  2 09:35:16 1998
+++ linux/fs/hfs/bnode.c	Wed May 12 13:27:37 1999
@@ -228,7 +228,7 @@
 			break;
 
 		case HFS_LOCK_NONE:
-			while (bn->lock || bn->wqueue) {
+			while (bn->lock || witqueue_active(&bn->wqueue)) {
 				hfs_sleep_on(&bn->rqueue);
 			}
 			++bn->count;
@@ -382,7 +382,7 @@
 	/* We update the lock state of the node if it is still in use
 	   or if it is "sticky" (such as the B-tree head and root).
 	   Otherwise we just delete it.	 */
-	if ((bn->count > 1) || (bn->rqueue) || (bn->sticky != HFS_NOT_STICKY)) {
+	if ((bn->count > 1) || (waitqueue_active(&bn->rqueue)) || (bn->sticky != HFS_NOT_STICKY)) {
 		hfs_bnode_lock(bnr, HFS_LOCK_NONE);
 	} else {
 		/* dirty buffer if we (might) have modified it */
diff -u --recursive --new-file v2.3.0/linux/fs/hfs/btree.c linux/fs/hfs/btree.c
--- v2.3.0/linux/fs/hfs/btree.c	Sun Nov 15 11:11:44 1998
+++ linux/fs/hfs/btree.c	Wed May 12 13:27:37 1999
@@ -173,7 +173,7 @@
 	bt->sys_mdb = mdb->sys_mdb;
 	bt->reserved = 0;
 	bt->lock = 0;
-	bt->wait = NULL;
+	init_waitqueue_head(&bt->wait);
 	bt->dirt = 0;
 	memset(bt->cache, 0, sizeof(bt->cache));
 
diff -u --recursive --new-file v2.3.0/linux/fs/hfs/catalog.c linux/fs/hfs/catalog.c
--- v2.3.0/linux/fs/hfs/catalog.c	Mon Feb 15 23:55:00 1999
+++ linux/fs/hfs/catalog.c	Wed May 12 13:27:37 1999
@@ -647,7 +647,7 @@
  */
 static inline void start_write(struct hfs_cat_entry *dir)
 {
-	if (dir->u.dir.readers || dir->u.dir.read_wait) {
+	if (dir->u.dir.readers || wait_queue_active(&dir->u.dir.read_wait)) {
 		hfs_sleep_on(&dir->u.dir.write_wait);
 	}
 	++dir->u.dir.writers;
@@ -658,7 +658,7 @@
  */
 static inline void start_read(struct hfs_cat_entry *dir)
 {
-	if (dir->u.dir.writers || dir->u.dir.write_wait) {
+	if (dir->u.dir.writers || wait_queue_active(&dir->u.dir.write_wait)) {
 		hfs_sleep_on(&dir->u.dir.read_wait);
 	}
 	++dir->u.dir.readers;
diff -u --recursive --new-file v2.3.0/linux/fs/hfs/dir.c linux/fs/hfs/dir.c
--- v2.3.0/linux/fs/hfs/dir.c	Mon Apr 12 10:03:45 1999
+++ linux/fs/hfs/dir.c	Tue May 11 23:01:41 1999
@@ -255,31 +255,6 @@
 }
 
 /*
- * hfs_mknod()
- *
- * This is the mknod() entry in the inode_operations structure for
- * regular HFS directories.  The purpose is to create a new entry
- * in a directory, given the inode for the parent directory and the
- * name (and its length) and the mode of the new entry (and the device
- * number if the entry is to be a device special file).
- *
- * HFS only supports regular files and directories and Linux disallows
- * using mknod() to create directories.  Thus we just check the arguments
- * and call hfs_create().
- */
-int hfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int rdev)
-{
-	if (!dir) 
-		return -ENOENT;
-
-	/* the only thing we currently do. */
-	if (S_ISREG(mode)) 
-		return hfs_create(dir, dentry, mode);
-
-	return -EPERM;
-}
-
-/*
  * hfs_unlink()
  *
  * This is the unlink() entry in the inode_operations structure for
diff -u --recursive --new-file v2.3.0/linux/fs/hfs/dir_cap.c linux/fs/hfs/dir_cap.c
--- v2.3.0/linux/fs/hfs/dir_cap.c	Fri Apr 23 21:20:37 1999
+++ linux/fs/hfs/dir_cap.c	Thu May 13 10:53:59 1999
@@ -83,7 +83,7 @@
 	NULL,			/* symlink */
 	hfs_mkdir,		/* mkdir */
 	hfs_rmdir,		/* rmdir */
-	hfs_mknod,		/* mknod */
+	NULL,			/* mknod */
 	hfs_rename,		/* rename */
 	NULL,			/* readlink */
 	NULL,			/* follow_link */
@@ -236,10 +236,6 @@
 	struct hfs_brec brec;
         struct hfs_cat_entry *entry;
 	struct inode *dir = filp->f_dentry->d_inode;
-
-	if (!dir || !dir->i_sb || !S_ISDIR(dir->i_mode)) {
-		return -EBADF;
-	}
 
 	entry = HFS_I(dir)->entry;
 	type = HFS_ITYPE(dir->i_ino);
diff -u --recursive --new-file v2.3.0/linux/fs/hfs/dir_dbl.c linux/fs/hfs/dir_dbl.c
--- v2.3.0/linux/fs/hfs/dir_dbl.c	Fri Apr 23 21:20:37 1999
+++ linux/fs/hfs/dir_dbl.c	Thu May 13 10:53:59 1999
@@ -27,7 +27,6 @@
 static int dbl_readdir(struct file *, void *, filldir_t);
 static int dbl_create(struct inode *, struct dentry *, int);
 static int dbl_mkdir(struct inode *, struct dentry *, int);
-static int dbl_mknod(struct inode *, struct dentry *, int, int);
 static int dbl_unlink(struct inode *, struct dentry *);
 static int dbl_rmdir(struct inode *, struct dentry *);
 static int dbl_rename(struct inode *, struct dentry *,
@@ -83,7 +82,7 @@
 	NULL,			/* symlink */
 	dbl_mkdir,		/* mkdir */
 	dbl_rmdir,		/* rmdir */
-	dbl_mknod,		/* mknod */
+	NULL,			/* mknod */
 	dbl_rename,		/* rename */
 	NULL,			/* readlink */
 	NULL,			/* follow_link */
@@ -202,10 +201,6 @@
         struct hfs_cat_entry *entry;
 	struct inode *dir = filp->f_dentry->d_inode;
 
-	if (!dir || !dir->i_sb || !S_ISDIR(dir->i_mode)) {
-		return -EBADF;
-	}
-
 	entry = HFS_I(dir)->entry;
 
 	if (filp->f_pos == 0) {
@@ -318,28 +313,6 @@
 		error = -EEXIST;
 	} else {
 		error = hfs_mkdir(parent, dentry, mode);
-	}
-	return error;
-}
-
-/*
- * dbl_mknod()
- *
- * This is the mknod() entry in the inode_operations structure for
- * regular HFS directories.  The purpose is to create a new entry
- * in a directory, given the inode for the parent directory and the
- * name (and its length) and the mode of the new entry (and the device
- * number if the entry is to be a device special file).
- */
-static int dbl_mknod(struct inode *dir, struct dentry *dentry,
-		     int mode, int rdev)
-{
-	int error;
-
-	if (is_hdr(dir, dentry->d_name.name, dentry->d_name.len)) {
-		error = -EEXIST;
-	} else {
-		error = hfs_mknod(dir, dentry, mode, rdev);
 	}
 	return error;
 }
diff -u --recursive --new-file v2.3.0/linux/fs/hfs/dir_nat.c linux/fs/hfs/dir_nat.c
--- v2.3.0/linux/fs/hfs/dir_nat.c	Fri Apr 23 21:20:37 1999
+++ linux/fs/hfs/dir_nat.c	Thu May 13 10:53:59 1999
@@ -89,7 +89,7 @@
 	NULL,			/* symlink */
 	hfs_mkdir,		/* mkdir */
 	nat_rmdir,		/* rmdir */
-	hfs_mknod,		/* mknod */
+	NULL,			/* mknod */
 	hfs_rename,		/* rename */
 	NULL,			/* readlink */
 	NULL,			/* follow_link */
@@ -224,10 +224,6 @@
 	struct hfs_brec brec;
         struct hfs_cat_entry *entry;
 	struct inode *dir = filp->f_dentry->d_inode;
-
-	if (!dir || !dir->i_sb || !S_ISDIR(dir->i_mode)) {
-		return -EBADF;
-	}
 
 	entry = HFS_I(dir)->entry;
 	type = HFS_ITYPE(dir->i_ino);
diff -u --recursive --new-file v2.3.0/linux/fs/hfs/file_hdr.c linux/fs/hfs/file_hdr.c
--- v2.3.0/linux/fs/hfs/file_hdr.c	Mon Feb 15 23:55:00 1999
+++ linux/fs/hfs/file_hdr.c	Wed May 12 13:26:20 1999
@@ -30,6 +30,14 @@
 #include <linux/hfs_fs_i.h>
 #include <linux/hfs_fs.h>
 
+/* prodos types */
+#define PRODOSI_FTYPE_DIR   0x0F
+#define PRODOSI_FTYPE_TEXT  0x04
+#define PRODOSI_FTYPE_8BIT  0xFF
+#define PRODOSI_FTYPE_16BIT 0xB3
+
+#define PRODOSI_AUXTYPE_DIR 0x0200
+
 /*================ Forward declarations ================*/
 
 static hfs_rwret_t hdr_read(struct file *, char *, hfs_rwarg_t, loff_t *);
@@ -84,13 +92,14 @@
 const struct hfs_hdr_layout hfs_dbl_fil_hdr_layout = {
 	__constant_htonl(HFS_DBL_MAGIC),	/* magic   */
 	__constant_htonl(HFS_HDR_VERSION_2),	/* version */
-	5,					/* entries */
+	6,					/* entries */
 	{					/* descr[] */
+		{HFS_HDR_FNAME, offsetof(struct hfs_dbl_hdr, real_name),   ~0},
 		{HFS_HDR_DATES, offsetof(struct hfs_dbl_hdr, create_time), 16},
 		{HFS_HDR_FINFO, offsetof(struct hfs_dbl_hdr, finderinfo),  32},
-		{HFS_HDR_MACI,  offsetof(struct hfs_dbl_hdr, fileinfo),    4},
-		{HFS_HDR_FNAME, offsetof(struct hfs_dbl_hdr, real_name),   ~0},
-		{HFS_HDR_RSRC,  HFS_DBL_HDR_LEN,                           ~0},
+		{HFS_HDR_MACI,  offsetof(struct hfs_dbl_hdr, fileinfo),     4},
+		{HFS_HDR_DID,   offsetof(struct hfs_dbl_hdr, cnid),         4},
+		{HFS_HDR_RSRC,  HFS_DBL_HDR_LEN,                           ~0}
 	},
 	{					/* order[] */
 		(struct hfs_hdr_descr *)&hfs_dbl_fil_hdr_layout.descr[0],
@@ -98,24 +107,55 @@
 		(struct hfs_hdr_descr *)&hfs_dbl_fil_hdr_layout.descr[2],
 		(struct hfs_hdr_descr *)&hfs_dbl_fil_hdr_layout.descr[3],
 		(struct hfs_hdr_descr *)&hfs_dbl_fil_hdr_layout.descr[4],
+		(struct hfs_hdr_descr *)&hfs_dbl_fil_hdr_layout.descr[5]
 	}
 };
 
 const struct hfs_hdr_layout hfs_dbl_dir_hdr_layout = {
 	__constant_htonl(HFS_DBL_MAGIC),	/* magic   */
 	__constant_htonl(HFS_HDR_VERSION_2),	/* version */
-	4,					/* entries */
+	5,					/* entries */
 	{					/* descr[] */
+		{HFS_HDR_FNAME, offsetof(struct hfs_dbl_hdr, real_name),   ~0},
 		{HFS_HDR_DATES, offsetof(struct hfs_dbl_hdr, create_time), 16},
 		{HFS_HDR_FINFO, offsetof(struct hfs_dbl_hdr, finderinfo),  32},
-		{HFS_HDR_MACI,  offsetof(struct hfs_dbl_hdr, fileinfo),    4},
-		{HFS_HDR_FNAME, offsetof(struct hfs_dbl_hdr, real_name),   ~0},
+		{HFS_HDR_MACI,  offsetof(struct hfs_dbl_hdr, fileinfo),     4},
+		{HFS_HDR_DID,   offsetof(struct hfs_dbl_hdr, cnid),         4}
 	},
 	{					/* order[] */
 		(struct hfs_hdr_descr *)&hfs_dbl_dir_hdr_layout.descr[0],
 		(struct hfs_hdr_descr *)&hfs_dbl_dir_hdr_layout.descr[1],
 		(struct hfs_hdr_descr *)&hfs_dbl_dir_hdr_layout.descr[2],
 		(struct hfs_hdr_descr *)&hfs_dbl_dir_hdr_layout.descr[3],
+		(struct hfs_hdr_descr *)&hfs_dbl_dir_hdr_layout.descr[4]
+	}
+};
+
+const struct hfs_hdr_layout hfs_nat2_hdr_layout = {
+	__constant_htonl(HFS_DBL_MAGIC),	/* magic   */
+	__constant_htonl(HFS_HDR_VERSION_2),	/* version */
+	9,					/* entries */
+	{					/* descr[] */
+		{HFS_HDR_FNAME, offsetof(struct hfs_dbl_hdr, real_name),   ~0},
+		{HFS_HDR_COMNT, offsetof(struct hfs_dbl_hdr, comment),      0},
+		{HFS_HDR_DATES, offsetof(struct hfs_dbl_hdr, create_time), 16},
+		{HFS_HDR_FINFO, offsetof(struct hfs_dbl_hdr, finderinfo),  32},
+		{HFS_HDR_AFPI,  offsetof(struct hfs_dbl_hdr, fileinfo),     4},
+		{HFS_HDR_DID,   offsetof(struct hfs_dbl_hdr, cnid),         4},
+		{HFS_HDR_SNAME,  offsetof(struct hfs_dbl_hdr, short_name), ~0},
+		{HFS_HDR_PRODOSI,  offsetof(struct hfs_dbl_hdr, prodosi),   8},
+		{HFS_HDR_RSRC,  HFS_NAT_HDR_LEN,                           ~0}
+	},
+	{					/* order[] */
+		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[0],
+		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[1],
+		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[2],
+		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[3],
+		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[4],
+		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[5],
+		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[6],
+		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[7],
+		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[8]
 	}
 };
 
@@ -124,18 +164,18 @@
 	__constant_htonl(HFS_HDR_VERSION_1),	/* version */
 	5,					/* entries */
 	{					/* descr[] */
+		{HFS_HDR_FNAME, offsetof(struct hfs_dbl_hdr, real_name),   ~0},
+		{HFS_HDR_COMNT, offsetof(struct hfs_dbl_hdr, comment),      0},
+		{HFS_HDR_OLDI,  offsetof(struct hfs_dbl_hdr, create_time), 16},
+		{HFS_HDR_FINFO, offsetof(struct hfs_dbl_hdr, finderinfo),  32},
 		{HFS_HDR_RSRC,  HFS_NAT_HDR_LEN,                           ~0},
-		{HFS_HDR_FNAME, offsetof(struct hfs_nat_hdr, real_name),   ~0},
-		{HFS_HDR_COMNT, offsetof(struct hfs_nat_hdr, comment),     0},
-		{HFS_HDR_OLDI,  offsetof(struct hfs_nat_hdr, create_time), 16},
-		{HFS_HDR_FINFO, offsetof(struct hfs_nat_hdr, finderinfo),  32},
 	},
 	{					/* order[] */
+		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[0],
 		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[1],
 		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[2],
 		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[3],
-		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[4],
-		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[0],
+		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[4]
 	}
 };
 
@@ -187,6 +227,7 @@
 			length = entry->key.CName.Len;
 			break;
 
+		case HFS_HDR_SNAME:
 		default:
 			length = 0;
 		}
@@ -456,6 +497,8 @@
 		case HFS_HDR_DATES:
 			get_dates(entry, inode, (hfs_u32 *)tmp);
 			if (descr->id == HFS_HDR_DATES) {
+				/* XXX: access date. hfsplus actually
+                                   has this. */
 				memcpy(tmp + 12, tmp + 4, 4);
 			} else if ((entry->type == HFS_CDR_FIL) &&
 				   (entry->u.file.flags & HFS_FIL_LOCK)) {
@@ -472,6 +515,31 @@
 			limit = 32;
 			break;
 
+		case HFS_HDR_AFPI:
+			/* XXX: this needs to do more mac->afp mappings */
+			hfs_put_ns(0, tmp);
+			if ((entry->type == HFS_CDR_FIL) &&
+			    (entry->u.file.flags & HFS_FIL_LOCK)) {
+				hfs_put_hs(HFS_AFP_RDONLY, tmp + 2);
+			} else {
+				hfs_put_ns(0, tmp + 2);
+			}
+			p = tmp;
+			limit = 4;
+		        break;
+
+		case HFS_HDR_PRODOSI:
+			/* XXX: this needs to do mac->prodos translations */
+			memset(tmp, 0, 8);
+#if 0
+			hfs_put_ns(0, tmp); /* access */
+			hfs_put_ns(0, tmp); /* type */
+			hfs_put_nl(0, tmp); /* aux type */
+#endif
+			p = tmp;
+			limit = 8;
+		        break;
+
 		case HFS_HDR_MACI:
 			hfs_put_ns(0, tmp);
 			if (entry->type == HFS_CDR_FIL) {
@@ -483,6 +551,32 @@
 			limit = 4;
 			break;
 
+		case HFS_HDR_DID:
+		        /* if it's rootinfo, stick the next available did in
+			 * the did slot. */
+			limit = 4;
+			if (entry->cnid == htonl(HFS_ROOT_CNID)) {
+				struct hfs_mdb *mdb = entry->mdb;
+				const struct hfs_name *reserved = 
+				HFS_SB(mdb->sys_mdb)->s_reserved2;
+				
+				while (reserved->Len) {
+					if (hfs_streq(reserved->Name,
+						      reserved->Len,
+						      entry->key.CName.Name,
+						      entry->key.CName.Len)) {
+						hfs_put_hl(mdb->next_id, tmp);
+						p = tmp;
+						goto hfs_did_done;
+					}
+					reserved++;
+				}
+			}
+			p = (char *) &entry->cnid;
+hfs_did_done:
+			break;
+
+		case HFS_HDR_SNAME:
 		default:
 			limit = 0;
 		}
@@ -724,6 +818,30 @@
 			limit = 32;
 			break;
 
+		case HFS_HDR_AFPI:
+			hfs_put_ns(0, tmp);
+			if ((entry->type == HFS_CDR_FIL) &&
+			    (entry->u.file.flags & HFS_FIL_LOCK)) {
+				hfs_put_hs(HFS_AFP_RDONLY, tmp + 2);
+			} else {
+				hfs_put_ns(0, tmp + 2);
+			}			
+			p = tmp;
+			limit = 4;
+			break;
+
+		case HFS_HDR_PRODOSI:
+			/* XXX: this needs to do mac->prodos translations */
+			memset(tmp, 0, 8); 
+#if 0
+			hfs_put_ns(0, tmp); /* access */
+			hfs_put_ns(0, tmp); /* type */
+			hfs_put_nl(0, tmp); /* aux type */
+#endif
+			p = tmp;
+			limit = 8;
+		        break;
+
 		case HFS_HDR_MACI:
 			hfs_put_ns(0, tmp);
 			if (entry->type == HFS_CDR_FIL) {
@@ -736,6 +854,7 @@
 			break;
 
 		case HFS_HDR_FNAME:	/* Can't rename a file this way */
+		case HFS_HDR_DID:       /* can't specify a did this way */
 		default:
 			limit = 0;
 		}
@@ -826,6 +945,9 @@
 			break;
 
 		case HFS_HDR_FNAME:	/* Can't rename a file this way */
+		case HFS_HDR_DID:       /* Can't specify a did this way */
+		case HFS_HDR_PRODOSI:   /* not implemented yet */
+		case HFS_HDR_AFPI:      /* ditto */
 		default:
 			break;
 		}
diff -u --recursive --new-file v2.3.0/linux/fs/hfs/hfs.h linux/fs/hfs/hfs.h
--- v2.3.0/linux/fs/hfs/hfs.h	Wed Dec 23 14:10:36 1998
+++ linux/fs/hfs/hfs.h	Wed May 12 13:26:20 1999
@@ -80,9 +80,24 @@
 #define HFS_FK_RSRC	0xFF
 
 /* bits in hfs_fil_entry.Flags */
-#define HFS_FIL_LOCK	0x01
-#define HFS_FIL_THD	0x02
-#define HFS_FIL_USED	0x80
+#define HFS_FIL_LOCK	0x01  /* locked */
+#define HFS_FIL_THD	0x02  /* file thread */
+#define HFS_FIL_DOPEN   0x04  /* data fork open */
+#define HFS_FIL_ROPEN   0x08  /* resource fork open */
+#define HFS_FIL_DIR     0x10  /* directory (always clear) */
+#define HFS_FIL_RSRV1   0x20  /* reserved */
+#define HFS_FIL_NOCOPY  0x40  /* copy-protected file */
+#define HFS_FIL_USED	0x80  /* open */
+
+/* bits in hfs_dir_entry.Flags. dirflags is 16 bits. */
+#define HFS_DIR_LOCK        0x01  /* locked */
+#define HFS_DIR_THD         0x02  /* directory thread */
+#define HFS_DIR_INEXPFOLDER 0x04  /* in a shared area */
+#define HFS_DIR_MOUNTED     0x08  /* mounted */
+#define HFS_DIR_DIR         0x10  /* directory (always set) */
+#define HFS_DIR_EXPFOLDER   0x20  /* share point */
+#define HFS_DIR_RSRV1       0x40  /* reserved */
+#define HFS_DIR_RSRV2       0x80  /* reserved */
 
 /* Access types used when requesting access to a B-node */
 #define HFS_LOCK_NONE	0x0000	/* Illegal */
diff -u --recursive --new-file v2.3.0/linux/fs/hfs/inode.c linux/fs/hfs/inode.c
--- v2.3.0/linux/fs/hfs/inode.c	Wed Dec 23 14:10:36 1998
+++ linux/fs/hfs/inode.c	Wed May 12 13:26:20 1999
@@ -262,7 +262,7 @@
 		HFS_I(inode)->entry = entry;
 		HFS_I(inode)->tz_secondswest = hfs_to_utc(0);
 
-		hsb->s_ifill(inode, type);
+		hsb->s_ifill(inode, type, hsb->s_version);
 		if (!hsb->s_afpd && (entry->type == HFS_CDR_FIL) &&
 		    (entry->u.file.flags & HFS_FIL_LOCK)) {
 			inode->i_mode &= ~S_IWUGO;
@@ -289,7 +289,7 @@
  * in other filesystems.  It is called by __hfs_iget() to fill in
  * the missing fields of an uninitialized inode under the CAP scheme.
  */
-void hfs_cap_ifill(struct inode * inode, ino_t type)
+void hfs_cap_ifill(struct inode * inode, ino_t type, const int version)
 {
 	struct hfs_cat_entry *entry = HFS_I(inode)->entry;
 
@@ -337,7 +337,7 @@
  * the missing fields of an uninitialized inode under the AppleDouble
  * scheme.
  */
-void hfs_dbl_ifill(struct inode * inode, ino_t type)
+void hfs_dbl_ifill(struct inode * inode, ino_t type, const int version)
 {
 	struct hfs_cat_entry *entry = HFS_I(inode)->entry;
 
@@ -378,7 +378,7 @@
  * the missing fields of an uninitialized inode under the Netatalk
  * scheme.
  */
-void hfs_nat_ifill(struct inode * inode, ino_t type)
+void hfs_nat_ifill(struct inode * inode, ino_t type, const int version)
 {
 	struct hfs_cat_entry *entry = HFS_I(inode)->entry;
 
@@ -393,7 +393,8 @@
 			inode->i_nlink = 1;
 		}
 		inode->i_op = &hfs_hdr_inode_operations;
-		HFS_I(inode)->default_layout = &hfs_nat_hdr_layout;
+		HFS_I(inode)->default_layout = (version == 2) ?
+			&hfs_nat2_hdr_layout : &hfs_nat_hdr_layout;
 	} else if (entry->type == HFS_CDR_FIL) {
 		init_file_inode(inode, HFS_FK_DATA);
 		inode->i_op = &hfs_file_inode_operations;
diff -u --recursive --new-file v2.3.0/linux/fs/hfs/super.c linux/fs/hfs/super.c
--- v2.3.0/linux/fs/hfs/super.c	Mon Nov  2 09:35:17 1998
+++ linux/fs/hfs/super.c	Wed May 12 13:26:20 1999
@@ -183,6 +183,8 @@
 	hsb->s_lowercase = 0;
 	hsb->s_quiet     = 0;
 	hsb->s_afpd      = 0;
+        /* default version. 0 just selects the defaults */
+	hsb->s_version   = 0; 
 	hsb->s_conv = 'b';
 	names = '?';
 	fork = '?';
@@ -197,7 +199,15 @@
 			*value++ = 0;
 		}
 	/* Numeric-valued options */
-		if (!strcmp(this_char,"uid")) {
+		if (!strcmp(this_char, "version")) {
+			if (!value || !*value) {
+				return 0;
+			}
+			hsb->s_version = simple_strtoul(value,&value,0);
+			if (*value) {
+				return 0;
+			}
+		} else if (!strcmp(this_char,"uid")) {
 			if (!value || !*value) {
 				return 0;
 			}
diff -u --recursive --new-file v2.3.0/linux/fs/inode.c linux/fs/inode.c
--- v2.3.0/linux/fs/inode.c	Tue May  4 10:57:12 1999
+++ linux/fs/inode.c	Tue May 11 14:37:40 1999
@@ -99,7 +99,7 @@
 
 static void __wait_on_inode(struct inode * inode)
 {
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 
 	add_wait_queue(&inode->i_wait, &wait);
 repeat:
@@ -126,7 +126,7 @@
 static inline void init_once(struct inode * inode)
 {
 	memset(inode, 0, sizeof(*inode));
-	init_waitqueue(&inode->i_wait);
+	init_waitqueue_head(&inode->i_wait);
 	INIT_LIST_HEAD(&inode->i_hash);
 	INIT_LIST_HEAD(&inode->i_dentry);
 	sema_init(&inode->i_sem, 1);
diff -u --recursive --new-file v2.3.0/linux/fs/isofs/inode.c linux/fs/isofs/inode.c
--- v2.3.0/linux/fs/isofs/inode.c	Tue Dec 29 11:40:35 1998
+++ linux/fs/isofs/inode.c	Tue May 11 23:01:41 1999
@@ -423,6 +423,7 @@
        */
       mm_segment_t old_fs=get_fs();
       inode_fake.i_rdev=dev;
+      init_waitqueue_head(&inode_fake.i_wait);
       ms_info.addr_format=CDROM_LBA;
       set_fs(KERNEL_DS);
       i=get_blkfops(MAJOR(dev))->ioctl(&inode_fake,
@@ -1210,12 +1211,9 @@
 	    inode->i_op = &isofs_dir_inode_operations;
 	  else if (S_ISLNK(inode->i_mode))
 	    inode->i_op = &isofs_symlink_inode_operations;
-	  else if (S_ISCHR(inode->i_mode))
-	    inode->i_op = &chrdev_inode_operations;
-	  else if (S_ISBLK(inode->i_mode))
-	    inode->i_op = &blkdev_inode_operations;
-	  else if (S_ISFIFO(inode->i_mode))
-	    init_fifo(inode);
+	  else
+	    /* XXX - parse_rock_ridge_inode() had already set i_rdev. */
+	    init_special_inode(inode, inode->i_mode, kdev_t_to_nr(inode->i_rdev));
 	}
 	return;
 
diff -u --recursive --new-file v2.3.0/linux/fs/lockd/clntlock.c linux/fs/lockd/clntlock.c
--- v2.3.0/linux/fs/lockd/clntlock.c	Mon Jan  4 10:23:42 1999
+++ linux/fs/lockd/clntlock.c	Tue May 11 14:37:40 1999
@@ -34,7 +34,7 @@
  */
 struct nlm_wait {
 	struct nlm_wait *	b_next;		/* linked list */
-	struct wait_queue *	b_wait;		/* where to wait on */
+	wait_queue_head_t	b_wait;		/* where to wait on */
 	struct nlm_host *	b_host;
 	struct file_lock *	b_lock;		/* local file lock */
 	unsigned short		b_reclaim;	/* got to reclaim lock */
@@ -55,7 +55,7 @@
 
 	block.b_host   = host;
 	block.b_lock   = fl;
-	block.b_wait   = NULL;
+	init_waitqueue_head(&block.b_wait);
 	block.b_status = NLM_LCK_BLOCKED;
 	block.b_next   = nlm_blocked;
 	nlm_blocked    = &block;
diff -u --recursive --new-file v2.3.0/linux/fs/lockd/host.c linux/fs/lockd/host.c
--- v2.3.0/linux/fs/lockd/host.c	Mon Mar  1 10:34:56 1999
+++ linux/fs/lockd/host.c	Tue May 11 14:37:40 1999
@@ -30,7 +30,7 @@
 static struct nlm_host *	nlm_hosts[NLM_HOST_NRHASH];
 static unsigned long		next_gc = 0;
 static int			nrhosts = 0;
-static struct semaphore		nlm_host_sema = MUTEX;
+static DECLARE_MUTEX(nlm_host_sema);
 
 
 static void			nlm_gc_hosts(void);
@@ -136,7 +136,7 @@
 	host->h_proto      = proto;
 	host->h_authflavor = RPC_AUTH_UNIX;
 	host->h_rpcclnt    = NULL;
-	host->h_sema	   = MUTEX;
+	init_MUTEX(&host->h_sema);
 	host->h_nextrebind = jiffies + NLM_HOST_REBIND;
 	host->h_expires    = jiffies + NLM_HOST_EXPIRE;
 	host->h_count      = 1;
diff -u --recursive --new-file v2.3.0/linux/fs/lockd/svc.c linux/fs/lockd/svc.c
--- v2.3.0/linux/fs/lockd/svc.c	Sat Feb  6 12:46:21 1999
+++ linux/fs/lockd/svc.c	Thu May 13 14:53:04 1999
@@ -40,14 +40,14 @@
 
 extern struct svc_program	nlmsvc_program;
 struct nlmsvc_binding *		nlmsvc_ops = NULL;
-static struct semaphore 	nlmsvc_sema = MUTEX;
+static DECLARE_MUTEX(nlmsvc_sema);
 static unsigned int		nlmsvc_users = 0;
 static pid_t			nlmsvc_pid = 0;
 unsigned long			nlmsvc_grace_period = 0;
 unsigned long			nlmsvc_timeout = 0;
 
-static struct semaphore lockd_start = MUTEX_LOCKED;
-static struct wait_queue *	lockd_exit = NULL;
+static DECLARE_MUTEX_LOCKED(lockd_start);
+static DECLARE_WAIT_QUEUE_HEAD(lockd_exit);
 
 /*
  * Currently the following can be set only at insmod time.
@@ -319,10 +319,9 @@
 init_module(void)
 {
 	/* Init the static variables */
-	nlmsvc_sema = MUTEX;
+	init_MUTEX(&nlmsvc_sema);
 	nlmsvc_users = 0;
 	nlmsvc_pid = 0;
-	lockd_exit = NULL;
 	nlmxdr_init();
 	return 0;
 }
diff -u --recursive --new-file v2.3.0/linux/fs/lockd/svcsubs.c linux/fs/lockd/svcsubs.c
--- v2.3.0/linux/fs/lockd/svcsubs.c	Thu Mar 25 09:23:34 1999
+++ linux/fs/lockd/svcsubs.c	Tue May 11 14:37:40 1999
@@ -26,7 +26,7 @@
 #define FILE_NRHASH		32
 #define FILE_HASH_BITS		5
 static struct nlm_file *	nlm_files[FILE_NRHASH];
-static struct semaphore		nlm_file_sema = MUTEX;
+static DECLARE_MUTEX(nlm_file_sema);
 
 static unsigned int file_hash(dev_t dev, ino_t ino)
 {
@@ -76,7 +76,7 @@
 
 	memset(file, 0, sizeof(*file));
 	file->f_handle = *fh;
-	file->f_sema   = MUTEX;
+	init_MUTEX(&file->f_sema);
 
 	/* Open the file. Note that this must not sleep for too long, else
 	 * we would lock up lockd:-) So no NFS re-exports, folks.
diff -u --recursive --new-file v2.3.0/linux/fs/locks.c linux/fs/locks.c
--- v2.3.0/linux/fs/locks.c	Tue May 11 08:52:14 1999
+++ linux/fs/locks.c	Tue May 11 14:37:40 1999
@@ -597,6 +597,7 @@
 	tfl.fl_flags = FL_POSIX | FL_ACCESS;
 	tfl.fl_owner = current->files;
 	tfl.fl_pid = current->pid;
+	init_waitqueue_head(&tfl.fl_wait);
 	tfl.fl_type = (read_write == FLOCK_VERIFY_WRITE) ? F_WRLCK : F_RDLCK;
 	tfl.fl_start = offset;
 	tfl.fl_end = offset + count - 1;
@@ -646,6 +647,7 @@
 
 	memset(fl, 0, sizeof(*fl));
 	
+	init_waitqueue_head(&fl->fl_wait);
 	fl->fl_flags = FL_POSIX;
 
 	switch (l->l_type) {
@@ -693,6 +695,7 @@
 {
 	memset(fl, 0, sizeof(*fl));
 
+	init_waitqueue_head(&fl->fl_wait);
 	if (!filp->f_dentry)	/* just in case */
 		return (0);
 
@@ -1111,6 +1114,7 @@
 		memset(new, 0, sizeof(*new));
 		new->fl_owner = fl->fl_owner;
 		new->fl_pid = fl->fl_pid;
+		init_waitqueue_head(&new->fl_wait);
 		new->fl_file = fl->fl_file;
 		new->fl_flags = fl->fl_flags;
 		new->fl_type = fl->fl_type;
diff -u --recursive --new-file v2.3.0/linux/fs/minix/inode.c linux/fs/minix/inode.c
--- v2.3.0/linux/fs/minix/inode.c	Sat Apr 24 12:45:37 1999
+++ linux/fs/minix/inode.c	Tue May 11 23:01:41 1999
@@ -756,23 +756,17 @@
 	inode->i_size = raw_inode->i_size;
 	inode->i_mtime = inode->i_atime = inode->i_ctime = raw_inode->i_time;
 	inode->i_blocks = inode->i_blksize = 0;
-	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
-		inode->i_rdev = to_kdev_t(raw_inode->i_zone[0]);
-	else for (block = 0; block < 9; block++)
+	for (block = 0; block < 9; block++)
 		inode->u.minix_i.u.i1_data[block] = raw_inode->i_zone[block];
-	brelse(bh);
 	if (S_ISREG(inode->i_mode))
 		inode->i_op = &minix_file_inode_operations;
 	else if (S_ISDIR(inode->i_mode))
 		inode->i_op = &minix_dir_inode_operations;
 	else if (S_ISLNK(inode->i_mode))
 		inode->i_op = &minix_symlink_inode_operations;
-	else if (S_ISCHR(inode->i_mode))
-		inode->i_op = &chrdev_inode_operations;
-	else if (S_ISBLK(inode->i_mode))
-		inode->i_op = &blkdev_inode_operations;
-	else if (S_ISFIFO(inode->i_mode))
-		init_fifo(inode);
+	else
+		init_special_inode(inode, inode->i_mode, raw_inode->i_zone[0]);
+	brelse(bh);
 }
 
 /*
@@ -812,23 +806,17 @@
 	inode->i_atime = raw_inode->i_atime;
 	inode->i_ctime = raw_inode->i_ctime;
 	inode->i_blocks = inode->i_blksize = 0;
-	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
-		inode->i_rdev = to_kdev_t(raw_inode->i_zone[0]);
-	else for (block = 0; block < 10; block++)
+	for (block = 0; block < 10; block++)
 		inode->u.minix_i.u.i2_data[block] = raw_inode->i_zone[block];
-	brelse(bh);
 	if (S_ISREG(inode->i_mode))
 		inode->i_op = &minix_file_inode_operations;
 	else if (S_ISDIR(inode->i_mode))
 		inode->i_op = &minix_dir_inode_operations;
 	else if (S_ISLNK(inode->i_mode))
 		inode->i_op = &minix_symlink_inode_operations;
-	else if (S_ISCHR(inode->i_mode))
-		inode->i_op = &chrdev_inode_operations;
-	else if (S_ISBLK(inode->i_mode))
-		inode->i_op = &blkdev_inode_operations;
-	else if (S_ISFIFO(inode->i_mode))
-		init_fifo(inode);
+	else
+		init_special_inode(inode, inode->i_mode, raw_inode->i_zone[0]);
+	brelse(bh);
 }
 
 /*
diff -u --recursive --new-file v2.3.0/linux/fs/minix/namei.c linux/fs/minix/namei.c
--- v2.3.0/linux/fs/minix/namei.c	Mon May 10 14:15:16 1999
+++ linux/fs/minix/namei.c	Thu May 13 10:53:59 1999
@@ -45,8 +45,6 @@
 	struct minix_dir_entry *de;
 
 	*res_dir = NULL;
-	if (!dir->i_sb)
-		return NULL;
 	info = &dir->i_sb->u.minix_sb;
 	if (namelen > info->s_namelen) {
 #ifdef NO_TRUNCATE
@@ -161,8 +159,6 @@
 
 	*res_buf = NULL;
 	*res_dir = NULL;
-	if (!dir || !dir->i_sb)
-		return -ENOENT;
 	info = &dir->i_sb->u.minix_sb;
 	if (namelen > info->s_namelen) {
 #ifdef NO_TRUNCATE
@@ -253,18 +249,7 @@
 	if (!inode)
 		return -ENOSPC;
 	inode->i_uid = current->fsuid;
-	inode->i_mode = mode;
-	inode->i_op = NULL;
-	if (S_ISREG(inode->i_mode))
-		inode->i_op = &minix_file_inode_operations;
-	else if (S_ISCHR(inode->i_mode))
-		inode->i_op = &chrdev_inode_operations;
-	else if (S_ISBLK(inode->i_mode))
-		inode->i_op = &blkdev_inode_operations;
-	else if (S_ISFIFO(inode->i_mode))
-		init_fifo(inode);
-	if (S_ISBLK(mode) || S_ISCHR(mode))
-		inode->i_rdev = to_kdev_t(rdev);
+	init_special_inode(inode, mode, rdev);
 	mark_inode_dirty(inode);
 	error = minix_add_entry(dir, dentry->d_name.name, dentry->d_name.len, &bh, &de);
 	if (error) {
@@ -342,8 +327,6 @@
 	struct minix_dir_entry * de;
 	struct minix_sb_info * info;
 
-	if (!inode || !inode->i_sb)
-		return 1;
 	info = &inode->i_sb->u.minix_sb;
 	block = 0;
 	bh = NULL;
@@ -442,26 +425,12 @@
 	struct buffer_head * bh;
 	struct minix_dir_entry * de;
 
-repeat:
 	retval = -ENOENT;
-	inode = NULL;
+	inode = dentry->d_inode;
 	bh = minix_find_entry(dir, dentry->d_name.name,
 			      dentry->d_name.len, &de);
-	if (!bh)
+	if (!bh || de->inode != inode->i_ino)
 		goto end_unlink;
-	inode = dentry->d_inode;
-
-	retval = -EPERM;
-	if (de->inode != inode->i_ino) {
-		brelse(bh);
-		current->counter = 0;
-		schedule();
-		goto repeat;
-	}
-	if (de->inode != inode->i_ino) {
-		retval = -ENOENT;
-		goto end_unlink;
-	}
 	if (!inode->i_nlink) {
 		printk("Deleting nonexistent file (%s:%lu), %d\n",
 			kdevname(inode->i_dev),
@@ -562,12 +531,6 @@
 (((struct minix_dir_entry *) ((buffer)+info->s_dirsize))->inode)
 
 /*
- * rename uses retrying to avoid race-conditions: at least they should be minimal.
- * it tries to allocate all the blocks, then sanity-checks, and if the sanity-
- * checks fail, it tries to restart itself again. Very practical - no changes
- * are done until we know everything works ok.. and then all the changes can be
- * done in one fell swoop when we have claimed all the buffers needed.
- *
  * Anybody can rename anything with this: the permission checks are left to the
  * higher-level routines.
  */
@@ -581,24 +544,15 @@
 	int retval;
 
 	info = &old_dir->i_sb->u.minix_sb;
-	goto start_up;
-try_again:
-	brelse(old_bh);
-	brelse(new_bh);
-	brelse(dir_bh);
-	current->counter = 0;
-	schedule();
-start_up:
-	old_inode = new_inode = NULL;
-	old_bh = new_bh = dir_bh = NULL;
+	new_bh = dir_bh = NULL;
+	old_inode = old_dentry->d_inode;
+	new_inode = new_dentry->d_inode;
 	old_bh = minix_find_entry(old_dir, old_dentry->d_name.name,
 				  old_dentry->d_name.len, &old_de);
 	retval = -ENOENT;
-	if (!old_bh)
+	if (!old_bh || old_de->inode != old_inode->i_ino)
 		goto end_rename;
-	old_inode = old_dentry->d_inode;
 	retval = -EPERM;
-	new_inode = new_dentry->d_inode;
 	new_bh = minix_find_entry(new_dir, new_dentry->d_name.name,
 				  new_dentry->d_name.len, &new_de);
 	if (new_bh) {
@@ -620,7 +574,8 @@
 		if (PARENT_INO(dir_bh->b_data) != old_dir->i_ino)
 			goto end_rename;
 		retval = -EMLINK;
-		if (!new_inode && new_dir->i_nlink >= info->s_link_max)
+		if (!new_inode && new_dir != old_dir &&
+				new_dir->i_nlink >= info->s_link_max)
 			goto end_rename;
 	}
 	if (!new_bh) {
@@ -631,22 +586,15 @@
 		if (retval)
 			goto end_rename;
 	}
-/* sanity checking before doing the rename - avoid races */
-	if (new_inode && (new_de->inode != new_inode->i_ino))
-		goto try_again;
-	if (new_de->inode && !new_inode)
-		goto try_again;
-	if (old_de->inode != old_inode->i_ino)
-		goto try_again;
 /* ok, that's it */
-	old_de->inode = 0;
 	new_de->inode = old_inode->i_ino;
+	old_de->inode = 0;
 	old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
-	mark_inode_dirty(old_dir);
 	old_dir->i_version = ++event;
+	mark_inode_dirty(old_dir);
 	new_dir->i_ctime = new_dir->i_mtime = CURRENT_TIME;
-	mark_inode_dirty(new_dir);
 	new_dir->i_version = ++event;
+	mark_inode_dirty(new_dir);
 	if (new_inode) {
 		new_inode->i_nlink--;
 		new_inode->i_ctime = CURRENT_TIME;
diff -u --recursive --new-file v2.3.0/linux/fs/namei.c linux/fs/namei.c
--- v2.3.0/linux/fs/namei.c	Sat May  8 20:46:08 1999
+++ linux/fs/namei.c	Tue May 11 23:01:41 1999
@@ -633,6 +633,24 @@
 	return retval;
 }
 
+int vfs_create(struct inode *dir, struct dentry *dentry, int mode)
+{
+	int error;
+
+	error = may_create(dir, dentry);
+	if (error)
+		goto exit_lock;
+
+	error = -EACCES;	/* shouldn't it be ENOSYS? */
+	if (!dir->i_op || !dir->i_op->create)
+		goto exit_lock;
+
+	DQUOT_INIT(dir);
+	error = dir->i_op->create(dir, dentry, mode);
+exit_lock:
+	return error;
+}
+
 /*
  *	open_namei()
  *
@@ -695,16 +713,11 @@
 			error = 0;
 			if (flag & O_EXCL)
 				error = -EEXIST;
-		} else if ((error = may_create(dir->d_inode, dentry)) == 0) {
-			if (!dir->d_inode->i_op || !dir->d_inode->i_op->create)
-				error = -EACCES;
-			else {
-				DQUOT_INIT(dir->d_inode);
-				error = dir->d_inode->i_op->create(dir->d_inode, dentry, mode);
-				/* Don't check for write permission, don't truncate */
-				acc_mode = 0;
-				flag &= ~O_TRUNC;
-			}
+		} else {
+			error = vfs_create(dir->d_inode, dentry,mode);
+			/* Don't check for write permission, don't truncate */
+			acc_mode = 0;
+			flag &= ~O_TRUNC;
 		}
 		unlock_dir(dir);
 		if (error)
@@ -825,32 +838,45 @@
 {
 	int error;
 	char * tmp;
+	struct dentry * dentry;
 
 	lock_kernel();
 	error = -EPERM;
 	if (S_ISDIR(mode) || (!S_ISFIFO(mode) && !capable(CAP_SYS_ADMIN)))
 		goto out;
+	tmp = getname(filename);
+	error = PTR_ERR(tmp);
+	if (IS_ERR(tmp))
+		goto out;
+
 	error = -EINVAL;
 	switch (mode & S_IFMT) {
 	case 0:
-		mode |= S_IFREG;
-		break;
-	case S_IFREG: case S_IFCHR: case S_IFBLK: case S_IFIFO: case S_IFSOCK:
+		mode |= S_IFREG;	/* fallthrough */
+	case S_IFREG:
+		mode &= ~current->fs->umask;
+		dentry = lookup_dentry(filename, NULL, LOOKUP_FOLLOW);
+		if (IS_ERR(dentry))
+			error = PTR_ERR(dentry);
+		else {
+			struct dentry *dir = lock_parent(dentry);
+			error = -ENOENT;
+			if (check_parent(dir, dentry))
+				error = vfs_create(dir->d_inode, dentry, mode);
+			dput(dentry);
+		}
 		break;
-	default:
-		goto out;
-	}
-	tmp = getname(filename);
-	error = PTR_ERR(tmp);
-	if (!IS_ERR(tmp)) {
-		struct dentry * dentry = do_mknod(tmp,mode,dev);
-		putname(tmp);
+	case S_IFCHR: case S_IFBLK: case S_IFIFO: case S_IFSOCK:
+		dentry = do_mknod(tmp,mode,dev);
 		error = PTR_ERR(dentry);
 		if (!IS_ERR(dentry)) {
 			dput(dentry);
 			error = 0;
 		}
+		break;
 	}
+	putname(tmp);
+
 out:
 	unlock_kernel();
 	return error;
diff -u --recursive --new-file v2.3.0/linux/fs/ncpfs/dir.c linux/fs/ncpfs/dir.c
--- v2.3.0/linux/fs/ncpfs/dir.c	Sat May  8 17:56:37 1999
+++ linux/fs/ncpfs/dir.c	Thu May 13 10:53:59 1999
@@ -39,7 +39,7 @@
 static int c_last_returned_index;
 static struct ncp_dirent *c_entry = NULL;
 static int c_lock = 0;
-static struct wait_queue *c_wait = NULL;
+static DECLARE_WAIT_QUEUE_HEAD(c_wait);
 
 static int ncp_read_volume_list(struct ncp_server *, int, int,
 					struct ncp_dirent *);
@@ -354,16 +354,7 @@
 	int len = dentry->d_name.len;      
 	struct ncpfs_inode_info finfo;
 	__u8 __name[dentry->d_name.len + 1];
-
-        if (!dentry->d_inode) {
-                DPRINTK(KERN_DEBUG "ncp_lookup_validate: called with dentry->d_inode already NULL.\n");
-                return 0;
-        }
         
-	if (!dir || !S_ISDIR(dir->i_mode)) {
-		printk(KERN_WARNING "ncp_lookup_validate: inode is NULL or not a directory.\n");
-		goto finished;
-	}
 	server = NCP_SERVER(dir);
 
 	if (!ncp_conn_valid(server))
diff -u --recursive --new-file v2.3.0/linux/fs/ncpfs/inode.c linux/fs/ncpfs/inode.c
--- v2.3.0/linux/fs/ncpfs/inode.c	Tue Apr 20 15:17:20 1999
+++ linux/fs/ncpfs/inode.c	Wed May 12 08:41:15 1999
@@ -57,7 +57,7 @@
 #endif
 
 static struct nw_file_info *read_nwinfo = NULL;
-static struct semaphore read_sem = MUTEX;
+static DECLARE_MUTEX(read_sem);
 
 /*
  * Fill in the ncpfs-specific information in the inode.
@@ -350,7 +350,7 @@
 
 	server->ncp_filp = ncp_filp;
 	server->lock = 0;
-	server->wait = NULL;
+	init_waitqueue_head(&server->wait);
 	server->packet = NULL;
 	server->buffer_size = 0;
 	server->conn_status = 0;
@@ -723,7 +723,7 @@
 {
 	DPRINTK(KERN_DEBUG "ncpfs: init_module called\n");
 
-	read_sem = MUTEX;
+	init_MUTEX(&read_sem);
 	read_nwinfo = NULL;
 
 #ifdef DEBUG_NCP_MALLOC
diff -u --recursive --new-file v2.3.0/linux/fs/nfs/dir.c linux/fs/nfs/dir.c
--- v2.3.0/linux/fs/nfs/dir.c	Sat May  8 23:18:22 1999
+++ linux/fs/nfs/dir.c	Tue May 11 14:37:40 1999
@@ -45,7 +45,7 @@
 	unsigned int		size;		/* # of entries */
 	unsigned long		age;		/* last used */
 	unsigned long		mtime;		/* last attr stamp */
-	struct wait_queue *	wait;
+	wait_queue_head_t	wait;
 	__u32 *			entry;		/* three __u32's per entry */
 };
 
@@ -124,8 +124,8 @@
 {
 	struct dentry 		*dentry = filp->f_dentry;
 	struct inode 		*inode = dentry->d_inode;
-	static struct wait_queue *readdir_wait = NULL;
-	struct wait_queue	**waitp = NULL;
+	static DECLARE_WAIT_QUEUE_HEAD(readdir_wait);
+	wait_queue_head_t	*waitp = NULL;
 	struct nfs_dirent	*cache, *free;
 	unsigned long		age, dead;
 	u32			cookie;
@@ -231,6 +231,7 @@
 		cache->valid  = 0;
 		cache->dev    = inode->i_dev;
 		cache->ino    = inode->i_ino;
+		init_waitqueue_head(&cache->wait);
 		if (!cache->entry) {
 			result = -ENOMEM;
 			cache->entry = (__u32 *) get_free_page(GFP_KERNEL);
diff -u --recursive --new-file v2.3.0/linux/fs/nfs/inode.c linux/fs/nfs/inode.c
--- v2.3.0/linux/fs/nfs/inode.c	Sat May  8 20:00:46 1999
+++ linux/fs/nfs/inode.c	Tue May 11 23:01:41 1999
@@ -470,16 +470,8 @@
 			inode->i_op = &nfs_dir_inode_operations;
 		else if (S_ISLNK(inode->i_mode))
 			inode->i_op = &nfs_symlink_inode_operations;
-		else if (S_ISCHR(inode->i_mode)) {
-			inode->i_op = &chrdev_inode_operations;
-			inode->i_rdev = to_kdev_t(fattr->rdev);
-		} else if (S_ISBLK(inode->i_mode)) {
-			inode->i_op = &blkdev_inode_operations;
-			inode->i_rdev = to_kdev_t(fattr->rdev);
-		} else if (S_ISFIFO(inode->i_mode))
-			init_fifo(inode);
 		else
-			inode->i_op = NULL;
+			init_special_inode(inode, inode->i_mode, fattr->rdev);
 		/*
 		 * Preset the size and mtime, as there's no need
 		 * to invalidate the caches.
diff -u --recursive --new-file v2.3.0/linux/fs/nfs/write.c linux/fs/nfs/write.c
--- v2.3.0/linux/fs/nfs/write.c	Wed Mar  3 11:17:02 1999
+++ linux/fs/nfs/write.c	Tue May 11 14:37:40 1999
@@ -292,6 +292,7 @@
 	wreq->wb_file = file;
 	wreq->wb_pid    = current->pid;
 	wreq->wb_page   = page;
+	init_waitqueue_head(&wreq->wb_wait);
 	wreq->wb_offset = offset;
 	wreq->wb_bytes  = bytes;
 	wreq->wb_count	= 2;		/* One for the IO, one for us */
@@ -363,7 +364,7 @@
 	struct dentry		*dentry = file->f_dentry;
 	struct inode		*inode = dentry->d_inode;
 	struct rpc_clnt		*clnt = NFS_CLIENT(inode);
-	struct wait_queue	wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 	sigset_t		oldmask;
 	int retval;
 
diff -u --recursive --new-file v2.3.0/linux/fs/nfsd/export.c linux/fs/nfsd/export.c
--- v2.3.0/linux/fs/nfsd/export.c	Tue Dec 29 11:42:25 1998
+++ linux/fs/nfsd/export.c	Tue May 11 23:07:46 1999
@@ -64,7 +64,7 @@
 static int			hash_lock = 0;
 static int			want_lock = 0;
 static int			hash_count = 0;
-static struct wait_queue *	hash_wait = NULL;
+static DECLARE_WAIT_QUEUE_HEAD(	hash_wait );
 
 #define READLOCK		0
 #define WRITELOCK		1
diff -u --recursive --new-file v2.3.0/linux/fs/pipe.c linux/fs/pipe.c
--- v2.3.0/linux/fs/pipe.c	Fri Nov 13 10:07:26 1998
+++ linux/fs/pipe.c	Tue May 11 14:37:40 1999
@@ -414,7 +414,7 @@
 		} else {
 			PIPE_BASE(*inode) = (char *) page;
 			inode->i_op = &pipe_inode_operations;
-			PIPE_WAIT(*inode) = NULL;
+			init_waitqueue_head(&PIPE_WAIT(*inode));
 			PIPE_START(*inode) = PIPE_LEN(*inode) = 0;
 			PIPE_RD_OPENERS(*inode) = PIPE_WR_OPENERS(*inode) = 0;
 			PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 1;
diff -u --recursive --new-file v2.3.0/linux/fs/proc/array.c linux/fs/proc/array.c
--- v2.3.0/linux/fs/proc/array.c	Mon May 10 10:05:18 1999
+++ linux/fs/proc/array.c	Tue May 11 16:30:45 1999
@@ -567,7 +567,7 @@
 			}
 		} while (count++ < 16);
 	}
-#elif defined (CONFIG_ARM)
+#elif defined(__arm__)
 	{
 		unsigned long fp, lr;
 		unsigned long stack_page;
@@ -623,7 +623,7 @@
 # define KSTK_EIP(tsk) \
     (*(unsigned long *)(PT_REG(pc) + PAGE_SIZE + (unsigned long)(tsk)))
 # define KSTK_ESP(tsk)	((tsk) == current ? rdusp() : (tsk)->tss.usp)
-#elif defined(CONFIG_ARM)
+#elif defined(__arm__)
 # define KSTK_EIP(tsk)	(((unsigned long *)(4096+(unsigned long)(tsk)))[1022])
 # define KSTK_ESP(tsk)	(((unsigned long *)(4096+(unsigned long)(tsk)))[1020])
 #elif defined(__mc68000__)
diff -u --recursive --new-file v2.3.0/linux/fs/proc/kmsg.c linux/fs/proc/kmsg.c
--- v2.3.0/linux/fs/proc/kmsg.c	Tue Nov 17 10:09:00 1998
+++ linux/fs/proc/kmsg.c	Tue May 11 14:37:40 1999
@@ -15,7 +15,7 @@
 #include <asm/io.h>
 
 extern unsigned long log_size;
-extern struct wait_queue * log_wait;
+extern wait_queue_head_t log_wait;
 
 extern int do_syslog(int type, char * bug, int count);
 
diff -u --recursive --new-file v2.3.0/linux/fs/proc/omirr.c linux/fs/proc/omirr.c
--- v2.3.0/linux/fs/proc/omirr.c	Mon Aug 24 13:14:09 1998
+++ linux/fs/proc/omirr.c	Tue May 11 23:07:08 1999
@@ -16,8 +16,8 @@
 static char * buffer = NULL;
 static int read_pos, write_pos;
 static int clip_pos, max_pos;
-static struct wait_queue * read_wait = NULL;
-static struct wait_queue * write_wait = NULL;
+static DECLARE_WAIT_QUEUE_HEAD(read_wait);
+static DECLARE_WAIT_QUEUE_HEAD(write_wait);
 
 static /*inline*/ int reserve_write_space(int len)
 {
diff -u --recursive --new-file v2.3.0/linux/fs/qnx4/inode.c linux/fs/qnx4/inode.c
--- v2.3.0/linux/fs/qnx4/inode.c	Sat Sep  5 17:01:45 1998
+++ linux/fs/qnx4/inode.c	Tue May 11 23:01:41 1999
@@ -408,29 +408,16 @@
 
 	memcpy(&inode->u.qnx4_i, (struct qnx4_inode_info *) raw_inode, QNX4_DIR_ENTRY_SIZE);
 	inode->i_op = &qnx4_file_inode_operations;
-	if (S_ISREG(inode->i_mode)) {
+	if (S_ISREG(inode->i_mode))
 		inode->i_op = &qnx4_file_inode_operations;
-	} else {
-		if (S_ISDIR(inode->i_mode)) {
-			inode->i_op = &qnx4_dir_inode_operations;
-		} else {
-			if (S_ISLNK(inode->i_mode)) {
-				inode->i_op = &qnx4_symlink_inode_operations;
-			} else {
-				if (S_ISCHR(inode->i_mode)) {
-					inode->i_op = &chrdev_inode_operations;
-				} else {
-					if (S_ISBLK(inode->i_mode)) {
-						inode->i_op = &blkdev_inode_operations;
-					} else {
-						if (S_ISFIFO(inode->i_mode)) {
-							init_fifo(inode);
-						}
-					}
-				}
-			}
-		}
-	}
+	else if (S_ISDIR(inode->i_mode))
+		inode->i_op = &qnx4_dir_inode_operations;
+	else if (S_ISLNK(inode->i_mode))
+		inode->i_op = &qnx4_symlink_inode_operations;
+	else
+		/* HUH??? Where is device number? Oh, well... */
+		init_special_inode(inode, inode->i_mode, 0);
+
 	brelse(bh);
 }
 
diff -u --recursive --new-file v2.3.0/linux/fs/select.c linux/fs/select.c
--- v2.3.0/linux/fs/select.c	Tue Jan 19 10:43:08 1999
+++ linux/fs/select.c	Tue May 11 14:37:40 1999
@@ -58,7 +58,7 @@
 	}
 }
 
-void __pollwait(struct file * filp, struct wait_queue ** wait_address, poll_table *p)
+void __pollwait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p)
 {
 	for (;;) {
 		if (p->nr < __MAX_POLL_TABLE_ENTRIES) {
@@ -68,8 +68,7 @@
 		 	entry->filp = filp;
 		 	filp->f_count++;
 			entry->wait_address = wait_address;
-			entry->wait.task = current;
-			entry->wait.next = NULL;
+			init_waitqueue_entry(&entry->wait, current);
 			add_wait_queue(wait_address,&entry->wait);
 			p->nr++;
 			return;
diff -u --recursive --new-file v2.3.0/linux/fs/smbfs/inode.c linux/fs/smbfs/inode.c
--- v2.3.0/linux/fs/smbfs/inode.c	Wed Dec 23 09:44:42 1998
+++ linux/fs/smbfs/inode.c	Thu May 13 11:31:31 1999
@@ -36,6 +36,7 @@
 static void smb_delete_inode(struct inode *);
 static void smb_put_super(struct super_block *);
 static int  smb_statfs(struct super_block *, struct statfs *, int);
+static void smb_set_inode_attr(struct inode *, struct smb_fattr *);
 
 static struct super_operations smb_sops =
 {
@@ -67,9 +68,7 @@
 	return ino;
 }
 
-static struct smb_fattr *read_fattr = NULL;
-static struct semaphore read_semaphore = MUTEX;
-
+/* We are always generating a new inode here */
 struct inode *
 smb_iget(struct super_block *sb, struct smb_fattr *fattr)
 {
@@ -77,11 +76,19 @@
 
 	pr_debug("smb_iget: %p\n", fattr);
 
-	down(&read_semaphore);
-	read_fattr = fattr;
-	result = iget(sb, fattr->f_ino);
-	read_fattr = NULL;
-	up(&read_semaphore);
+	result = get_empty_inode();
+	result->i_sb = sb;
+	result->i_dev = sb->s_dev;
+	result->i_ino = fattr->f_ino;
+	memset(&(result->u.smbfs_i), 0, sizeof(result->u.smbfs_i));
+	smb_set_inode_attr(result, fattr);
+	if (S_ISREG(result->i_mode))
+		result->i_op = &smb_file_inode_operations;
+	else if (S_ISDIR(result->i_mode))
+		result->i_op = &smb_dir_inode_operations;
+	else
+		result->i_op = NULL;
+	insert_inode_hash(result)
 	return result;
 }
 
@@ -147,24 +154,9 @@
 static void
 smb_read_inode(struct inode *inode)
 {
-	pr_debug("smb_iget: %p\n", read_fattr);
-
-	if (!read_fattr || inode->i_ino != read_fattr->f_ino)
-	{
-		printk("smb_read_inode called from invalid point\n");
-		return;
-	}
-
-	inode->i_dev = inode->i_sb->s_dev;
-	memset(&(inode->u.smbfs_i), 0, sizeof(inode->u.smbfs_i));
-	smb_set_inode_attr(inode, read_fattr);
-
-	if (S_ISREG(inode->i_mode))
-		inode->i_op = &smb_file_inode_operations;
-	else if (S_ISDIR(inode->i_mode))
-		inode->i_op = &smb_dir_inode_operations;
-	else
-		inode->i_op = NULL;
+	/* Now it can be called only by NFS */
+	printk("smb_read_inode called from invalid point\n");
+	return;
 }
 
 /*
@@ -362,8 +354,8 @@
 	sb->s_op = &smb_sops;
 
 	sb->u.smbfs_sb.sock_file = NULL;
-	sb->u.smbfs_sb.sem = MUTEX;
-	sb->u.smbfs_sb.wait = NULL;
+	init_MUTEX(&sb->u.smbfs_sb.sem);
+	init_waitqueue_head(&sb->u.smbfs_sb.wait);
 	sb->u.smbfs_sb.conn_pid = 0;
 	sb->u.smbfs_sb.state = CONN_INVALID; /* no connection yet */
 	sb->u.smbfs_sb.generation = 0;
@@ -608,8 +600,6 @@
 	smb_current_kmalloced = 0;
 	smb_current_vmalloced = 0;
 #endif
-
-	read_semaphore = MUTEX;
 
 	return init_smb_fs();
 }
diff -u --recursive --new-file v2.3.0/linux/fs/super.c linux/fs/super.c
--- v2.3.0/linux/fs/super.c	Mon May 10 10:08:51 1999
+++ linux/fs/super.c	Thu May 13 10:53:59 1999
@@ -42,7 +42,7 @@
  * unmounting a filesystem and re-mounting it (or something
  * else).
  */
-static struct semaphore mount_sem = MUTEX;
+static DECLARE_MUTEX(mount_sem);
 
 extern void wait_for_keypress(void);
 extern struct file_operations * get_blkfops(unsigned int major);
@@ -413,7 +413,7 @@
 
 void __wait_on_super(struct super_block * sb)
 {
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 
 	add_wait_queue(&sb->s_wait, &wait);
 repeat:
@@ -530,6 +530,7 @@
 		memset(s, 0, sizeof(struct super_block));
 		INIT_LIST_HEAD(&s->s_dirty);
 		list_add (&s->s_list, super_blocks.prev);
+		init_waitqueue_head(&s->s_wait);
 	}
 	return s;
 }
@@ -952,16 +953,19 @@
 	if (!IS_ERR(dentry)) {
 		struct super_block * sb = dentry->d_inode->i_sb;
 
-		retval = -EINVAL;
-		if (dentry == sb->s_root) {
-			/*
-			 * Shrink the dcache and sync the device.
-			 */
-			shrink_dcache_sb(sb);
-			fsync_dev(sb->s_dev);
-			if (flags & MS_RDONLY)
-				acct_auto_close(sb->s_dev);
-			retval = do_remount_sb(sb, flags, data);
+		retval = -ENODEV;
+		if (sb) {
+			retval = -EINVAL;
+			if (dentry == sb->s_root) {
+				/*
+				 * Shrink the dcache and sync the device.
+				 */
+				shrink_dcache_sb(sb);
+				fsync_dev(sb->s_dev);
+				if (flags & MS_RDONLY)
+					acct_auto_close(sb->s_dev);
+				retval = do_remount_sb(sb, flags, data);
+			}
 		}
 		dput(dentry);
 	}
diff -u --recursive --new-file v2.3.0/linux/fs/sysv/CHANGES linux/fs/sysv/CHANGES
--- v2.3.0/linux/fs/sysv/CHANGES	Wed Mar 24 12:34:35 1999
+++ linux/fs/sysv/CHANGES	Tue May 11 23:01:41 1999
@@ -53,3 +53,8 @@
 			_inode()'s job.
 	*    ialloc.c: (sysv_free_inode):
 			Fixed race.
+
+Sun, 30 Apr 1999   AV
+	*    namei.c (sysv_mknod):
+			Removed dead code (S_IFREG case is now passed to
+			->create() by VFS).
diff -u --recursive --new-file v2.3.0/linux/fs/sysv/inode.c linux/fs/sysv/inode.c
--- v2.3.0/linux/fs/sysv/inode.c	Sun Mar 21 07:11:37 1999
+++ linux/fs/sysv/inode.c	Thu May 13 10:53:59 1999
@@ -882,7 +882,7 @@
 	}
 	inode->i_blocks = inode->i_blksize = 0;
 	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
-		inode->i_rdev = to_kdev_t(raw_inode->i_a.i_rdev);
+		;
 	else
 	if (sb->sv_convert)
 		for (block = 0; block < 10+1+1+1; block++)
@@ -892,19 +892,15 @@
 		for (block = 0; block < 10+1+1+1; block++)
 			inode->u.sysv_i.i_data[block] =
 				read3byte(&raw_inode->i_a.i_addb[3*block]);
-	brelse(bh);
 	if (S_ISREG(inode->i_mode))
 		inode->i_op = &sysv_file_inode_operations;
 	else if (S_ISDIR(inode->i_mode))
 		inode->i_op = &sysv_dir_inode_operations;
 	else if (S_ISLNK(inode->i_mode))
 		inode->i_op = &sysv_symlink_inode_operations;
-	else if (S_ISCHR(inode->i_mode))
-		inode->i_op = &chrdev_inode_operations;
-	else if (S_ISBLK(inode->i_mode))
-		inode->i_op = &blkdev_inode_operations;
-	else if (S_ISFIFO(inode->i_mode))
-		init_fifo(inode);
+	else
+		init_special_inode(inode, inode->i_mode,raw_inode->i_a.i_rdev);
+	brelse(bh);
 }
 
 /* To avoid inconsistencies between inodes in memory and inodes on disk. */
diff -u --recursive --new-file v2.3.0/linux/fs/sysv/namei.c linux/fs/sysv/namei.c
--- v2.3.0/linux/fs/sysv/namei.c	Mon May 10 14:14:28 1999
+++ linux/fs/sysv/namei.c	Thu May 13 10:53:59 1999
@@ -144,8 +144,6 @@
 
 	*res_buf = NULL;
 	*res_dir = NULL;
-	if (!dir)
-		return -ENOENT;
 	sb = dir->i_sb;
 	if (namelen > SYSV_NAMELEN) {
 		if (sb->sv_truncate)
@@ -240,18 +238,7 @@
 	if (!inode)
 		return -ENOSPC;
 	inode->i_uid = current->fsuid;
-	inode->i_mode = mode;
-	inode->i_op = NULL;
-	if (S_ISREG(inode->i_mode))
-		inode->i_op = &sysv_file_inode_operations;
-	else if (S_ISCHR(inode->i_mode))
-		inode->i_op = &chrdev_inode_operations;
-	else if (S_ISBLK(inode->i_mode))
-		inode->i_op = &blkdev_inode_operations;
-	else if (S_ISFIFO(inode->i_mode))
-		init_fifo(inode);
-	if (S_ISBLK(mode) || S_ISCHR(mode))
-		inode->i_rdev = to_kdev_t(rdev);
+	init_special_inode(inode, mode, rdev);
 	mark_inode_dirty(inode);
 	error = sysv_add_entry(dir, dentry->d_name.name, 
 			       dentry->d_name.len, &bh, &de);
@@ -334,8 +321,6 @@
 	struct buffer_head * bh;
 	struct sysv_dir_entry * de;
 
-	if (!inode)
-		return 1;
 	block = 0;
 	bh = NULL;
 	pos = offset = 2*SYSV_DIRSIZE;
@@ -391,22 +376,16 @@
 	struct buffer_head * bh;
 	struct sysv_dir_entry * de;
 
-	inode = NULL;
-	bh = sysv_find_entry(dir, dentry->d_name.name,
-                             dentry->d_name.len, &de);
+	inode = dentry->d_inode;
+	bh = sysv_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de);
 	retval = -ENOENT;
-	if (!bh)
+	if (!bh || de->inode != inode->i_ino)
 		goto end_rmdir;
-	inode = dentry->d_inode;
 
 	if (!empty_dir(inode)) {
 		retval = -ENOTEMPTY;
 		goto end_rmdir;
 	}
-	if (de->inode != inode->i_ino) {
-		retval = -ENOENT;
-		goto end_rmdir;
-	}
 	if (!list_empty(&dentry->d_hash)) {
 		retval = -EBUSY;
 		goto end_rmdir;
@@ -416,9 +395,9 @@
 	de->inode = 0;
 	mark_buffer_dirty(bh, 1);
 	inode->i_nlink=0;
-	mark_inode_dirty(inode);
 	dir->i_nlink--;
 	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+	mark_inode_dirty(inode);
 	mark_inode_dirty(dir);
 	d_delete(dentry);
 	retval = 0;
@@ -434,26 +413,11 @@
 	struct buffer_head * bh;
 	struct sysv_dir_entry * de;
 
-repeat:
 	retval = -ENOENT;
-	inode = NULL;
-	bh = sysv_find_entry(dir, dentry->d_name.name,
-                             dentry->d_name.len, &de);
-	if (!bh)
-		goto end_unlink;
 	inode = dentry->d_inode;
-
-	retval = -EPERM;
-	if (de->inode != inode->i_ino) {
-		brelse(bh);
-		current->counter = 0;
-		schedule();
-		goto repeat;
-	}
-	if (de->inode != inode->i_ino) {
-		retval = -ENOENT;
+	bh = sysv_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de);
+	if (!bh || de->inode != inode->i_ino)
 		goto end_unlink;
-	}
 	if (!inode->i_nlink) {
 		printk("Deleting nonexistent file (%s:%lu), %d\n",
 		        kdevname(inode->i_dev), inode->i_ino, inode->i_nlink);
@@ -572,12 +536,6 @@
 (((struct sysv_dir_entry *) ((buffer) + 1*SYSV_DIRSIZE))->inode)
 
 /*
- * rename uses retrying to avoid race-conditions: at least they should be minimal.
- * it tries to allocate all the blocks, then sanity-checks, and if the sanity-
- * checks fail, it tries to restart itself again. Very practical - no changes
- * are done until we know everything works ok.. and then all the changes can be
- * done in one fell swoop when we have claimed all the buffers needed.
- *
  * Anybody can rename anything with this: the permission checks are left to the
  * higher-level routines.
  */
@@ -589,24 +547,15 @@
 	struct sysv_dir_entry * old_de, * new_de;
 	int retval;
 
-	goto start_up;
-try_again:
-	brelse(old_bh);
-	brelse(new_bh);
-	brelse(dir_bh);
-	current->counter = 0;
-	schedule();
-start_up:
-	old_inode = new_inode = NULL;
-	old_bh = new_bh = dir_bh = NULL;
+	old_inode = old_dentry->d_inode;
+	new_inode = new_dentry->d_inode;
+	new_bh = dir_bh = NULL;
 	old_bh = sysv_find_entry(old_dir, old_dentry->d_name.name,
 				old_dentry->d_name.len, &old_de);
 	retval = -ENOENT;
-	if (!old_bh)
+	if (!old_bh || old_de->inode != old_inode->i_ino)
 		goto end_rename;
-	old_inode = old_dentry->d_inode;	/* don't cross mnt-points */
 	retval = -EPERM;
-	new_inode = new_dentry->d_inode;
 	new_bh = sysv_find_entry(new_dir, new_dentry->d_name.name,
 				new_dentry->d_name.len, &new_de);
 	if (new_bh) {
@@ -628,7 +577,8 @@
 		if (PARENT_INO(dir_bh->b_data) != old_dir->i_ino)
 			goto end_rename;
 		retval = -EMLINK;
-		if (!new_inode && new_dir->i_nlink >= new_dir->i_sb->sv_link_max)
+		if (!new_inode && new_dir != old_dir &&
+				new_dir->i_nlink >= new_dir->i_sb->sv_link_max)
 			goto end_rename;
 	}
 	if (!new_bh) {
@@ -637,16 +587,8 @@
 		if (retval)
 			goto end_rename;
 	}
-/* sanity checking before doing the rename - avoid races */
-	if (new_inode && (new_de->inode != new_inode->i_ino))
-		goto try_again;
-	if (new_de->inode && !new_inode)
-		goto try_again;
-	if (old_de->inode != old_inode->i_ino)
-		goto try_again;
-/* ok, that's it */
-	old_de->inode = 0;
 	new_de->inode = old_inode->i_ino;
+	old_de->inode = 0;
 	old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
 	mark_inode_dirty(old_dir);
 	new_dir->i_ctime = new_dir->i_mtime = CURRENT_TIME;
diff -u --recursive --new-file v2.3.0/linux/fs/ufs/inode.c linux/fs/ufs/inode.c
--- v2.3.0/linux/fs/ufs/inode.c	Sun Jan 17 18:32:26 1999
+++ linux/fs/ufs/inode.c	Tue May 11 23:01:41 1999
@@ -518,7 +518,7 @@
 	inode->u.ufs_i.i_lastfrag = howmany (inode->i_size, uspi->s_fsize);
 	
 	if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
-		inode->i_rdev = to_kdev_t(SWAB32(ufs_inode->ui_u2.ui_addr.ui_db[0]));
+		;
 	else if (inode->i_blocks) {
 		for (i = 0; i < (UFS_NDADDR + UFS_NINDIR); i++)
 			inode->u.ufs_i.i_u1.i_data[i] = ufs_inode->ui_u2.ui_addr.ui_db[i];
@@ -528,7 +528,6 @@
 			inode->u.ufs_i.i_u1.i_symlink[i] = ufs_inode->ui_u2.ui_symlink[i];
 	}
 
-	brelse (bh);
 
 	inode->i_op = NULL;
 
@@ -538,12 +537,11 @@
 		inode->i_op = &ufs_dir_inode_operations;
 	else if (S_ISLNK(inode->i_mode))
 		inode->i_op = &ufs_symlink_inode_operations;
-	else if (S_ISCHR(inode->i_mode))
-		inode->i_op = &chrdev_inode_operations;
-	else if (S_ISBLK(inode->i_mode))
-		inode->i_op = &blkdev_inode_operations;
-	else if (S_ISFIFO(inode->i_mode))
-		init_fifo(inode);
+	else
+		init_special_inode(inode, inode->i_mode,
+				   SWAB32(ufs_inode->ui_u2.ui_addr.ui_db[0]));
+
+	brelse (bh);
 
 #ifdef UFS_INODE_DEBUG_MORE
 	ufs_print_inode (inode);
diff -u --recursive --new-file v2.3.0/linux/fs/ufs/namei.c linux/fs/ufs/namei.c
--- v2.3.0/linux/fs/ufs/namei.c	Mon May 10 14:14:28 1999
+++ linux/fs/ufs/namei.c	Tue May 11 23:01:41 1999
@@ -467,18 +467,7 @@
 		goto out;
 
 	inode->i_uid = current->fsuid;
-	inode->i_mode = mode;
-	inode->i_op = NULL;
-	if (S_ISREG(inode->i_mode))
-		inode->i_op = &ufs_file_inode_operations;
-	else if (S_ISCHR(inode->i_mode))
-		inode->i_op = &chrdev_inode_operations;
-	else if (S_ISBLK(inode->i_mode))
-		inode->i_op = &blkdev_inode_operations;
-	else if (S_ISFIFO(inode->i_mode)) 
-		init_fifo(inode);
-	if (S_ISBLK(mode) || S_ISCHR(mode))
-		inode->i_rdev = to_kdev_t(rdev);
+	init_special_inode(inode, mode, rdev);
 	mark_inode_dirty(inode);
 	bh = ufs_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err);
 	if (!bh)
diff -u --recursive --new-file v2.3.0/linux/fs/umsdos/inode.c linux/fs/umsdos/inode.c
--- v2.3.0/linux/fs/umsdos/inode.c	Mon Apr 12 10:03:45 1999
+++ linux/fs/umsdos/inode.c	Tue May 11 23:01:41 1999
@@ -163,13 +163,9 @@
 		umsdos_setup_dir(dentry);
 	} else if (S_ISLNK (inode->i_mode)) {
 		inode->i_op = &umsdos_symlink_inode_operations;
-	} else if (S_ISCHR (inode->i_mode)) {
-		inode->i_op = &chrdev_inode_operations;
-	} else if (S_ISBLK (inode->i_mode)) {
-		inode->i_op = &blkdev_inode_operations;
-	} else if (S_ISFIFO (inode->i_mode)) {
-		init_fifo (inode);
-	}
+	} else
+		init_special_inode(inode, inode->i_mode,
+					kdev_t_to_nr(inode->i_rdev));
 }
 
 
diff -u --recursive --new-file v2.3.0/linux/include/asm-alpha/hdreg.h linux/include/asm-alpha/hdreg.h
--- v2.3.0/linux/include/asm-alpha/hdreg.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-alpha/hdreg.h	Thu May 13 11:00:08 1999
@@ -0,0 +1,12 @@
+/*
+ *  linux/include/asm-alpha/hdreg.h
+ *
+ *  Copyright (C) 1994-1996  Linus Torvalds & authors
+ */
+
+#ifndef __ASMalpha_HDREG_H
+#define __ASMalpha_HDREG_H
+
+typedef unsigned short ide_ioreg_t;
+
+#endif /* __ASMalpha_HDREG_H */
diff -u --recursive --new-file v2.3.0/linux/include/asm-alpha/ide.h linux/include/asm-alpha/ide.h
--- v2.3.0/linux/include/asm-alpha/ide.h	Wed May  6 14:42:54 1998
+++ linux/include/asm-alpha/ide.h	Thu May 13 11:00:08 1999
@@ -13,8 +13,6 @@
 
 #ifdef __KERNEL__
 
-typedef unsigned short ide_ioreg_t;
-
 #ifndef MAX_HWIFS
 #define MAX_HWIFS	4
 #endif
@@ -45,18 +43,42 @@
 	}
 }
 
-static __inline__ void ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq)
+static __inline__ void ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq)
 {
-	ide_ioreg_t port = base;
-	int i = 8;
+	ide_ioreg_t reg = data_port;
+	int i;
 
-	while (i--)
-		*p++ = port++;
-	*p++ = base + 0x206;
+	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+		hw->io_ports[i] = reg;
+		reg += 1;
+	}
+	if (ctrl_port) {
+		hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
+	} else {
+		hw->io_ports[IDE_CONTROL_OFFSET] = hw->io_ports[IDE_DATA_OFFSET] + 0x206;
+	}
 	if (irq != NULL)
 		*irq = 0;
 }
 
+/*
+ * This registers the standard ports for this architecture with the IDE
+ * driver.
+ */
+static __inline__ void ide_init_default_hwifs(void)
+{
+#ifdef __DO_I_NEED_THIS
+	hw_regs_t hw;
+	int index;
+
+	for (index = 0; index < MAX_HWIFS; index++) {
+		ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, 0);
+		hw.irq = ide_default_irq(ide_default_io_base(index));
+		ide_register_hw(&hw, NULL);
+	}
+#endif /* __DO_I_NEED_THIS */
+}
+
 typedef union {
 	unsigned all			: 8;	/* all of the bits together */
 	struct {
@@ -68,51 +90,19 @@
 	} b;
 	} select_t;
 
-static __inline__ int ide_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
-			unsigned long flags, const char *device, void *dev_id)
-{
-	return request_irq(irq, handler, flags, device, dev_id);
-}			
-
-static __inline__ void ide_free_irq(unsigned int irq, void *dev_id)
-{
-	free_irq(irq, dev_id);
-}
-
-static __inline__ int ide_check_region (ide_ioreg_t from, unsigned int extent)
-{
-	return check_region(from, extent);
-}
-
-static __inline__ void ide_request_region (ide_ioreg_t from, unsigned int extent, const char *name)
-{
-	request_region(from, extent, name);
-}
-
-static __inline__ void ide_release_region (ide_ioreg_t from, unsigned int extent)
-{
-	release_region(from, extent);
-}
+#define ide_request_irq(irq,hand,flg,dev,id)	request_irq((irq),(hand),(flg),(dev),(id))
+#define ide_free_irq(irq,dev_id)		free_irq((irq), (dev_id))
+#define ide_check_region(from,extent)		check_region((from), (extent))
+#define ide_request_region(from,extent,name)	request_region((from), (extent), (name))
+#define ide_release_region(from,extent)		release_region((from), (extent))
 
 /*
  * The following are not needed for the non-m68k ports
  */
-static __inline__ int ide_ack_intr (ide_ioreg_t status_port, ide_ioreg_t irq_port)
-{
-	return(1);
-}
-
-static __inline__ void ide_fix_driveid(struct hd_driveid *id)
-{
-}
-
-static __inline__ void ide_release_lock (int *ide_lock)
-{
-}
-
-static __inline__ void ide_get_lock (int *ide_lock, void (*handler)(int, void *, struct pt_regs *), void *data)
-{
-}
+#define ide_ack_intr(hwif)		(1)
+#define ide_fix_driveid(id)		do {} while (0)
+#define ide_release_lock(lock)		do {} while (0)
+#define ide_get_lock(lock, hdlr, data)	do {} while (0)
 
 #endif /* __KERNEL__ */
 
diff -u --recursive --new-file v2.3.0/linux/include/asm-alpha/io.h linux/include/asm-alpha/io.h
--- v2.3.0/linux/include/asm-alpha/io.h	Thu Apr 15 05:42:31 1999
+++ linux/include/asm-alpha/io.h	Thu May 13 11:00:08 1999
@@ -356,6 +356,12 @@
 #endif
 #define RTC_ALWAYS_BCD	0
 
+/* Nothing to do */
+
+#define dma_cache_inv(_start,_size)		do { } while (0)
+#define dma_cache_wback(_start,_size)		do { } while (0)
+#define dma_cache_wback_inv(_start,_size)	do { } while (0)
+
 #endif /* __KERNEL__ */
 
 #endif /* __ALPHA_IO_H */
diff -u --recursive --new-file v2.3.0/linux/include/asm-arm/arch-arc/ide.h linux/include/asm-arm/arch-arc/ide.h
--- v2.3.0/linux/include/asm-arm/arch-arc/ide.h	Thu Dec 17 09:05:42 1998
+++ linux/include/asm-arm/arch-arc/ide.h	Thu May 13 11:00:08 1999
@@ -19,33 +19,32 @@
  * Set up a hw structure for a specified data port, control port and IRQ.
  * This should follow whatever the default interface uses.
  */
-static __inline__ void
-ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int irq)
+static __inline__ void ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int *irq)
 {
 	ide_ioreg_t reg = (ide_ioreg_t) data_port;
 	int i;
 
-	memset(hw, 0, sizeof(*hw));
-
 	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
 		hw->io_ports[i] = reg;
 		reg += 1;
 	}
 	hw->io_ports[IDE_CONTROL_OFFSET] = (ide_ioreg_t) ctrl_port;
-	hw->irq = irq;
+	hw->irq = *irq;
 }
 
 /*
  * This registers the standard ports for this architecture with the IDE
  * driver.
  */
-static __inline__ void
-ide_init_default_hwifs(void)
+static __inline__ void ide_init_default_hwifs(void)
 {
 #ifdef CONFIG_ARCH_A5K
 	hw_regs_t hw;
 
-	ide_init_hwif_ports(&hw, 0x1f0, 0x3f6, IRQ_HARDDISK);
+        memset(hw, 0, sizeof(*hw));
+
+	ide_init_hwif_ports(&hw, 0x1f0, 0x3f6, NULL);
+	hw.irq = IRQ_HARDDISK;
 	ide_register_hw(&hw, NULL);
 #endif
 }
diff -u --recursive --new-file v2.3.0/linux/include/asm-arm/arch-ebsa285/ide.h linux/include/asm-arm/arch-ebsa285/ide.h
--- v2.3.0/linux/include/asm-arm/arch-ebsa285/ide.h	Thu Dec 17 09:05:43 1998
+++ linux/include/asm-arm/arch-ebsa285/ide.h	Thu May 13 11:00:08 1999
@@ -12,27 +12,32 @@
  * Set up a hw structure for a specified data port, control port and IRQ.
  * This should follow whatever the default interface uses.
  */
-static __inline__ void
-ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int irq)
+static __inline__ void ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int *irq)
 {
 	ide_ioreg_t reg = (ide_ioreg_t) data_port;
 	int i;
 
-	memset(hw, 0, sizeof(*hw));
-
 	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
 		hw->io_ports[i] = reg;
 		reg += 1;
 	}
 	hw->io_ports[IDE_CONTROL_OFFSET] = (ide_ioreg_t) ctrl_port;
-	hw->irq = irq;
+	hw->irq = *irq;
 }
 
 /*
  * This registers the standard ports for this architecture with the IDE
  * driver.
  */
-static __inline__ void
-ide_init_default_hwifs(void)
+static __inline__ void ide_init_default_hwifs(void)
 {
+#if 0
+	hw_regs_t hw;
+
+	memset(hw, 0, sizeof(*hw));
+
+	ide_init_hwif_ports(&hw, 0x1f0, 0x3f6, NULL);
+	hw.irq = IRQ_HARDDISK;
+	ide_register_hw(&hw, NULL);
+#endif
 }
diff -u --recursive --new-file v2.3.0/linux/include/asm-arm/arch-rpc/ide.h linux/include/asm-arm/arch-rpc/ide.h
--- v2.3.0/linux/include/asm-arm/arch-rpc/ide.h	Thu Dec 17 09:05:43 1998
+++ linux/include/asm-arm/arch-rpc/ide.h	Thu May 13 11:00:08 1999
@@ -12,31 +12,30 @@
  * Set up a hw structure for a specified data port, control port and IRQ.
  * This should follow whatever the default interface uses.
  */
-static __inline__ void
-ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int irq)
+static __inline__ void ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int *irq)
 {
 	ide_ioreg_t reg = (ide_ioreg_t) data_port;
 	int i;
 
-	memset(hw, 0, sizeof(*hw));
-
 	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
 		hw->io_ports[i] = reg;
 		reg += 1;
 	}
 	hw->io_ports[IDE_CONTROL_OFFSET] = (ide_ioreg_t) ctrl_port;
-	hw->irq = irq;
+	hw->irq = *irq;
 }
 
 /*
  * This registers the standard ports for this architecture with the IDE
  * driver.
  */
-static __inline__ void
-ide_init_default_hwifs(void)
+static __inline__ void ide_init_default_hwifs(void)
 {
 	hw_regs_t hw;
 
-	ide_init_hwif_ports(&hw, 0x1f0, 0x3f6, IRQ_HARDDISK);
+        memset(hw, 0, sizeof(*hw));
+
+	ide_init_hwif_ports(&hw, 0x1f0, 0x3f6, NULL);
+	hw.irq = IRQ_HARDDISK;
 	ide_register_hw(&hw, NULL);
 }
diff -u --recursive --new-file v2.3.0/linux/include/asm-arm/arch-rpc/io.h linux/include/asm-arm/arch-rpc/io.h
--- v2.3.0/linux/include/asm-arm/arch-rpc/io.h	Thu Jan  7 15:51:33 1999
+++ linux/include/asm-arm/arch-rpc/io.h	Tue May 11 16:30:45 1999
@@ -28,18 +28,43 @@
  * Dynamic IO functions - let the compiler
  * optimize the expressions
  */
-#define DECLARE_DYN_OUT(fnsuffix,instr)						\
-extern __inline__ void __out##fnsuffix (unsigned int value, unsigned int port)	\
-{										\
-	unsigned long temp;							\
-	__asm__ __volatile__(							\
-	"tst	%2, #0x80000000\n\t"						\
-	"mov	%0, %4\n\t"							\
-	"addeq	%0, %0, %3\n\t"							\
-	"str" ##instr## "	%1, [%0, %2, lsl #2]	@ out"###fnsuffix	\
-	: "=&r" (temp)								\
-	: "r" (value), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)	\
-	: "cc");								\
+extern __inline__ void __outb (unsigned int value, unsigned int port)
+{
+	unsigned long temp;
+	__asm__ __volatile__(
+	"tst	%2, #0x80000000\n\t"
+	"mov	%0, %4\n\t"
+	"addeq	%0, %0, %3\n\t"
+	"strb	%1, [%0, %2, lsl #2]	@ outb"
+	: "=&r" (temp)
+	: "r" (value), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)
+	: "cc");
+}
+
+extern __inline__ void __outw (unsigned int value, unsigned int port)
+{
+	unsigned long temp;
+	__asm__ __volatile__(
+	"tst	%2, #0x80000000\n\t"
+	"mov	%0, %4\n\t"
+	"addeq	%0, %0, %3\n\t"
+	"str	%1, [%0, %2, lsl #2]	@ outw"
+	: "=&r" (temp)
+	: "r" (value|value<<16), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)
+	: "cc");
+}
+
+extern __inline__ void __outl (unsigned int value, unsigned int port)
+{
+	unsigned long temp;
+	__asm__ __volatile__(
+	"tst	%2, #0x80000000\n\t"
+	"mov	%0, %4\n\t"
+	"addeq	%0, %0, %3\n\t"
+	"str	%1, [%0, %2, lsl #2]	@ outl"
+	: "=&r" (temp)
+	: "r" (value), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)
+	: "cc");
 }
 
 #define DECLARE_DYN_IN(sz,fnsuffix,instr)					\
@@ -66,7 +91,6 @@
 }
 
 #define DECLARE_IO(sz,fnsuffix,instr)	\
-	DECLARE_DYN_OUT(fnsuffix,instr)	\
 	DECLARE_DYN_IN(sz,fnsuffix,instr)
 
 DECLARE_IO(char,b,"b")
@@ -74,7 +98,6 @@
 DECLARE_IO(long,l,"")
 
 #undef DECLARE_IO
-#undef DECLARE_DYN_OUT
 #undef DECLARE_DYN_IN
 
 /*
diff -u --recursive --new-file v2.3.0/linux/include/asm-arm/hdreg.h linux/include/asm-arm/hdreg.h
--- v2.3.0/linux/include/asm-arm/hdreg.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/hdreg.h	Thu May 13 11:00:08 1999
@@ -0,0 +1,13 @@
+/*
+ *  linux/include/asm-arm/hdreg.h
+ *
+ *  Copyright (C) 1994-1996  Linus Torvalds & authors
+ */
+
+#ifndef __ASMARM_HDREG_H
+#define __ASMARM_HDREG_H
+
+typedef unsigned long ide_ioreg_t;
+
+#endif /* __ASMARM_HDREG_H */
+
diff -u --recursive --new-file v2.3.0/linux/include/asm-arm/ide.h linux/include/asm-arm/ide.h
--- v2.3.0/linux/include/asm-arm/ide.h	Thu Dec 17 09:05:43 1998
+++ linux/include/asm-arm/ide.h	Thu May 13 11:00:08 1999
@@ -48,4 +48,4 @@
 
 #endif /* __KERNEL__ */
 
-#endif /* __ASMi386_IDE_H */
+#endif /* __ASMARM_IDE_H */
diff -u --recursive --new-file v2.3.0/linux/include/asm-arm/io.h linux/include/asm-arm/io.h
--- v2.3.0/linux/include/asm-arm/io.h	Sat May  8 11:06:57 1999
+++ linux/include/asm-arm/io.h	Thu May 13 11:00:08 1999
@@ -189,10 +189,21 @@
 #define inl_p(port) __inl_p((port))
 #endif
 
-#endif
+/* Nothing to do */
 
+#ifndef dma_cache_inv
+#define dma_cache_inv(_start,_size)		do { } while (0)
+#endif
+#ifndef dma_cache_wback
+#define dma_cache_wback(_start,_size)		do { } while (0)
 #ifndef ARCH_READWRITE
+#ifndef dma_cache_wback_inv
+#define dma_cache_wback_inv(_start,_size)	do { } while (0)
+#endif
+
+#endif /* __KERNEL__ */
 
+#endif /* __ASM_ARM_IO_H */
 /* for panic */
 #include <linux/kernel.h>
 
diff -u --recursive --new-file v2.3.0/linux/include/asm-arm/proc-fns.h linux/include/asm-arm/proc-fns.h
--- v2.3.0/linux/include/asm-arm/proc-fns.h	Sat May  8 11:07:16 1999
+++ linux/include/asm-arm/proc-fns.h	Tue May 11 16:30:45 1999
@@ -10,7 +10,7 @@
 
 #ifdef __KERNEL__
 
-/* forward-decare task_struct */
+/* forward-declare task_struct */
 struct task_struct;
 
 /*
diff -u --recursive --new-file v2.3.0/linux/include/asm-arm/semaphore.h linux/include/asm-arm/semaphore.h
--- v2.3.0/linux/include/asm-arm/semaphore.h	Sat May  8 11:06:58 1999
+++ linux/include/asm-arm/semaphore.h	Tue May 11 16:30:45 1999
@@ -5,7 +5,6 @@
 #define __ASM_ARM_SEMAPHORE_H
 
 #include <linux/linkage.h>
-#include <asm/system.h>
 #include <asm/atomic.h>
 
 struct semaphore {
diff -u --recursive --new-file v2.3.0/linux/include/asm-i386/hdreg.h linux/include/asm-i386/hdreg.h
--- v2.3.0/linux/include/asm-i386/hdreg.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-i386/hdreg.h	Thu May 13 11:00:08 1999
@@ -0,0 +1,12 @@
+/*
+ *  linux/include/asm-i386/hdreg.h
+ *
+ *  Copyright (C) 1994-1996  Linus Torvalds & authors
+ */
+
+#ifndef __ASMi386_HDREG_H
+#define __ASMi386_HDREG_H
+
+typedef unsigned short ide_ioreg_t;
+
+#endif /* __ASMi386_HDREG_H */
diff -u --recursive --new-file v2.3.0/linux/include/asm-i386/ide.h linux/include/asm-i386/ide.h
--- v2.3.0/linux/include/asm-i386/ide.h	Wed May  6 14:42:54 1998
+++ linux/include/asm-i386/ide.h	Thu May 13 11:00:09 1999
@@ -13,10 +13,8 @@
 
 #ifdef __KERNEL__
 
-typedef unsigned short ide_ioreg_t;
-
 #ifndef MAX_HWIFS
-#define MAX_HWIFS	6
+#define MAX_HWIFS	8
 #endif
 
 #define ide__sti()	__sti()
@@ -49,18 +47,38 @@
 	}
 }
 
-static __inline__ void ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq)
+static __inline__ void ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq)
 {
-	ide_ioreg_t port = base;
-	int i = 8;
+	ide_ioreg_t reg = data_port;
+	int i;
 
-	while (i--)
-		*p++ = port++;
-	*p++ = base + 0x206;
+	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+		hw->io_ports[i] = reg;
+		reg += 1;
+	}
+	if (ctrl_port) {
+		hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
+	} else {
+		hw->io_ports[IDE_CONTROL_OFFSET] = hw->io_ports[IDE_DATA_OFFSET] + 0x206;
+	}
 	if (irq != NULL)
 		*irq = 0;
 }
 
+static __inline__ void ide_init_default_hwifs(void)
+{
+#ifdef __DO_I_NEED_THIS
+	hw_regs_t hw;
+	int index;
+
+	for(index = 0; index < MAX_HWIFS; index++) {
+		ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL);
+		hw.irq = ide_default_irq(ide_default_io_base(index));
+		ide_register_hw(&hw, NULL);
+	}
+#endif /* __DO_I_NEED_THIS */
+}
+
 typedef union {
 	unsigned all			: 8;	/* all of the bits together */
 	struct {
@@ -72,51 +90,19 @@
 	} b;
 	} select_t;
 
-static __inline__ int ide_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
-			unsigned long flags, const char *device, void *dev_id)
-{
-	return request_irq(irq, handler, flags, device, dev_id);
-}			
-
-static __inline__ void ide_free_irq(unsigned int irq, void *dev_id)
-{
-	free_irq(irq, dev_id);
-}
-
-static __inline__ int ide_check_region (ide_ioreg_t from, unsigned int extent)
-{
-	return check_region(from, extent);
-}
-
-static __inline__ void ide_request_region (ide_ioreg_t from, unsigned int extent, const char *name)
-{
-	request_region(from, extent, name);
-}
-
-static __inline__ void ide_release_region (ide_ioreg_t from, unsigned int extent)
-{
-	release_region(from, extent);
-}
+#define ide_request_irq(irq,hand,flg,dev,id)	request_irq((irq),(hand),(flg),(dev),(id))
+#define ide_free_irq(irq,dev_id)		free_irq((irq), (dev_id))
+#define ide_check_region(from,extent)		check_region((from), (extent))
+#define ide_request_region(from,extent,name)	request_region((from), (extent), (name))
+#define ide_release_region(from,extent)		release_region((from), (extent))
 
 /*
  * The following are not needed for the non-m68k ports
  */
-static __inline__ int ide_ack_intr (ide_ioreg_t status_port, ide_ioreg_t irq_port)
-{
-	return(1);
-}
-
-static __inline__ void ide_fix_driveid(struct hd_driveid *id)
-{
-}
-
-static __inline__ void ide_release_lock (int *ide_lock)
-{
-}
-
-static __inline__ void ide_get_lock (int *ide_lock, void (*handler)(int, void *, struct pt_regs *), void *data)
-{
-}
+#define ide_ack_intr(hwif)		(1)
+#define ide_fix_driveid(id)		do {} while (0)
+#define ide_release_lock(lock)		do {} while (0)
+#define ide_get_lock(lock, hdlr, data)	do {} while (0)
 
 #endif /* __KERNEL__ */
 
diff -u --recursive --new-file v2.3.0/linux/include/asm-i386/io.h linux/include/asm-i386/io.h
--- v2.3.0/linux/include/asm-i386/io.h	Tue May 11 13:04:20 1999
+++ linux/include/asm-i386/io.h	Thu May 13 14:42:31 1999
@@ -183,6 +183,12 @@
 	return retval;
 }
 
+/* Nothing to do */
+
+#define dma_cache_inv(_start,_size)		do { } while (0)
+#define dma_cache_wback(_start,_size)		do { } while (0)
+#define dma_cache_wback_inv(_start,_size)	do { } while (0)
+
 #endif /* __KERNEL__ */
 
 #endif
diff -u --recursive --new-file v2.3.0/linux/include/asm-i386/semaphore.h linux/include/asm-i386/semaphore.h
--- v2.3.0/linux/include/asm-i386/semaphore.h	Tue May 11 13:03:59 1999
+++ linux/include/asm-i386/semaphore.h	Thu May 13 14:52:36 1999
@@ -27,15 +27,62 @@
 #include <asm/system.h>
 #include <asm/atomic.h>
 #include <asm/spinlock.h>
+#include <linux/wait.h>
 
 struct semaphore {
 	atomic_t count;
 	int waking;
-	struct wait_queue * wait;
+	wait_queue_head_t wait;
+#if WAITQUEUE_DEBUG
+	long __magic;
+#endif
 };
 
-#define MUTEX ((struct semaphore) { ATOMIC_INIT(1), 0, NULL })
-#define MUTEX_LOCKED ((struct semaphore) { ATOMIC_INIT(0), 0, NULL })
+#if WAITQUEUE_DEBUG
+# define __SEM_DEBUG_INIT(name) \
+		, (int)&(name).__magic
+#else
+# define __SEM_DEBUG_INIT(name)
+#endif
+
+#define __SEMAPHORE_INITIALIZER(name,count) \
+{ ATOMIC_INIT(count), 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
+	__SEM_DEBUG_INIT(name) }
+
+#define __MUTEX_INITIALIZER(name) \
+	__SEMAPHORE_INITIALIZER(name,1)
+
+#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+	struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+
+#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
+#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
+
+extern inline void sema_init (struct semaphore *sem, int val)
+{
+/*
+ *	*sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val);
+ *
+ * i'd rather use the more flexible initialization above, but sadly
+ * GCC 2.7.2.3 emits a bogus warning. EGCS doesnt. Oh well.
+ */
+	atomic_set(&sem->count, val);
+	sem->waking = 0;
+	init_waitqueue_head(&sem->wait);
+#if WAITQUEUE_DEBUG
+	sem->__magic = (int)&sem->__magic;
+#endif
+}
+
+static inline void init_MUTEX (struct semaphore *sem)
+{
+	sema_init(sem, 1);
+}
+
+static inline void init_MUTEX_LOCKED (struct semaphore *sem)
+{
+	sema_init(sem, 0);
+}
 
 asmlinkage void __down_failed(void /* special register calling convention */);
 asmlinkage int  __down_failed_interruptible(void  /* params in registers */);
@@ -49,8 +96,6 @@
 
 extern spinlock_t semaphore_wake_lock;
 
-#define sema_init(sem, val)	atomic_set(&((sem)->count), (val))
-
 /*
  * This is ugly, but we want the default case to fall through.
  * "down_failed" is a special asm handler that calls the C
@@ -58,6 +103,10 @@
  */
 extern inline void down(struct semaphore * sem)
 {
+#if WAITQUEUE_DEBUG
+	CHECK_MAGIC(sem->__magic);
+#endif
+
 	__asm__ __volatile__(
 		"# atomic down operation\n\t"
 #ifdef __SMP__
@@ -79,6 +128,10 @@
 {
 	int result;
 
+#if WAITQUEUE_DEBUG
+	CHECK_MAGIC(sem->__magic);
+#endif
+
 	__asm__ __volatile__(
 		"# atomic interruptible down operation\n\t"
 #ifdef __SMP__
@@ -102,6 +155,10 @@
 {
 	int result;
 
+#if WAITQUEUE_DEBUG
+	CHECK_MAGIC(sem->__magic);
+#endif
+
 	__asm__ __volatile__(
 		"# atomic interruptible down operation\n\t"
 #ifdef __SMP__
@@ -129,6 +186,9 @@
  */
 extern inline void up(struct semaphore * sem)
 {
+#if WAITQUEUE_DEBUG
+	CHECK_MAGIC(sem->__magic);
+#endif
 	__asm__ __volatile__(
 		"# atomic up operation\n\t"
 #ifdef __SMP__
diff -u --recursive --new-file v2.3.0/linux/include/asm-m68k/hdreg.h linux/include/asm-m68k/hdreg.h
--- v2.3.0/linux/include/asm-m68k/hdreg.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-m68k/hdreg.h	Thu May 13 11:00:09 1999
@@ -0,0 +1,13 @@
+/*
+ *  linux/include/asm-m68k/hdreg.h
+ *
+ *  Copyright (C) 1994-1996  Linus Torvalds & authors
+ */
+
+#ifndef _M68K_HDREG_H
+#define _M68K_HDREG_H
+
+typedef unsigned int   q40ide_ioreg_t;
+typedef unsigned char * ide_ioreg_t;
+
+#endif /* _M68K_HDREG_H */
diff -u --recursive --new-file v2.3.0/linux/include/asm-m68k/ide.h linux/include/asm-m68k/ide.h
--- v2.3.0/linux/include/asm-m68k/ide.h	Tue May 11 09:57:14 1999
+++ linux/include/asm-m68k/ide.h	Thu May 13 11:00:09 1999
@@ -45,13 +45,6 @@
 #include <asm/macints.h>
 #endif
 
-
-typedef unsigned int   q40ide_ioreg_t;
-
-
-typedef unsigned char * ide_ioreg_t;
-
-
 #ifndef MAX_HWIFS
 #define MAX_HWIFS	4	/* same as the other archs */
 #endif
@@ -65,19 +58,39 @@
 	else return 0;
 }
 
+int q40ide_default_io_base(int);
+
+static __inline__ ide_ioreg_t ide_default_io_base(int index)
+{
+	if (MACH_IS_Q40)
+		return q40ide_default_io_base(index);
+	else return 0;
+}
 
 /*
  *  Can we do this in a generic manner??
  */
-void q40_ide_init_hwif_ports (q40ide_ioreg_t *p, q40ide_ioreg_t base, int *irq);
+void q40_ide_init_hwif_ports (hw_regs_t *hw, q40ide_ioreg_t data_port, q40ide_ioreg_t ctrl_port, int *irq);
 
-static __inline__ void ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq)
+/*
+ * Set up a hw structure for a specified data port, control port and IRQ.
+ * This should follow whatever the default interface uses.
+ */
+static __inline__ void ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq)
 {
 #ifdef CONFIG_Q40
-    if (MACH_IS_Q40)
-      return q40_ide_init_hwif_ports((q40ide_ioreg_t *)p,(q40ide_ioreg_t)base,irq);
+	if (MACH_IS_Q40)
+		return q40_ide_init_hwif_ports(hw, (q40ide_ioreg_t) data_port, (q40ide_ioreg_t) ctrl_port, irq);
 #endif
-    printk("ide_init_hwif_ports: must not be called\n");
+	printk("ide_init_hwif_ports: must not be called\n");
+}
+
+/*
+ * This registers the standard ports for this architecture with the IDE
+ * driver.
+ */
+static __inline__ void ide_init_default_hwifs(void)
+{
 }
 
 typedef union {
@@ -487,7 +500,7 @@
 #endif /* CONFIG_ATARI */
 }
 
-#define ide_ack_intr(hwif)	((hwif)->ack_intr ? (hwif)->ack_intr(hwif) : 1)
+#define ide_ack_intr(hwif)	((hwif)->hw.ack_intr ? (hwif)->hw.ack_intr(hwif) : 1)
 
 /*
  * On the Atari, we sometimes can't enable interrupts:
diff -u --recursive --new-file v2.3.0/linux/include/asm-m68k/io.h linux/include/asm-m68k/io.h
--- v2.3.0/linux/include/asm-m68k/io.h	Tue Jan 19 10:58:34 1999
+++ linux/include/asm-m68k/io.h	Thu May 13 11:00:09 1999
@@ -72,6 +72,12 @@
 
 extern void iounmap(void *addr);
 
+/* Nothing to do */
+
+#define dma_cache_inv(_start,_size)		do { } while (0)
+#define dma_cache_wback(_start,_size)		do { } while (0)
+#define dma_cache_wback_inv(_start,_size)	do { } while (0)
+
 #endif /* __KERNEL__ */
 
 #endif /* _M68K_IO_H */
diff -u --recursive --new-file v2.3.0/linux/include/asm-m68k/page.h linux/include/asm-m68k/page.h
--- v2.3.0/linux/include/asm-m68k/page.h	Tue May 11 09:57:14 1999
+++ linux/include/asm-m68k/page.h	Wed May 12 08:50:00 1999
@@ -1,6 +1,8 @@
 #ifndef _M68K_PAGE_H
 #define _M68K_PAGE_H
 
+#include <linux/config.h>
+
 /* PAGE_SHIFT determines the page size */
 #define PAGE_SHIFT	12
 #define PAGE_SIZE	(1UL << PAGE_SHIFT)
diff -u --recursive --new-file v2.3.0/linux/include/asm-m68k/q40_keyboard.h linux/include/asm-m68k/q40_keyboard.h
--- v2.3.0/linux/include/asm-m68k/q40_keyboard.h	Tue May 11 09:57:14 1999
+++ linux/include/asm-m68k/q40_keyboard.h	Wed May 12 08:50:00 1999
@@ -9,10 +9,6 @@
  */
 
 
-#include <linux/config.h> /* CONFIG_MAGIC_SYSRQ */
-
-
-
 #ifdef __KERNEL__
 
 
diff -u --recursive --new-file v2.3.0/linux/include/asm-m68k/semaphore-helper.h linux/include/asm-m68k/semaphore-helper.h
--- v2.3.0/linux/include/asm-m68k/semaphore-helper.h	Tue May 11 09:57:14 1999
+++ linux/include/asm-m68k/semaphore-helper.h	Wed May 12 08:50:00 1999
@@ -9,6 +9,8 @@
  * m68k version by Andreas Schwab
  */
 
+#include <linux/config.h>
+
 /*
  * These two _must_ execute atomically wrt each other.
  */
diff -u --recursive --new-file v2.3.0/linux/include/asm-m68k/semaphore.h linux/include/asm-m68k/semaphore.h
--- v2.3.0/linux/include/asm-m68k/semaphore.h	Tue May 11 09:57:14 1999
+++ linux/include/asm-m68k/semaphore.h	Wed May 12 08:50:00 1999
@@ -1,7 +1,6 @@
 #ifndef _M68K_SEMAPHORE_H
 #define _M68K_SEMAPHORE_H
 
-#include <linux/config.h>
 #include <linux/linkage.h>
 
 #include <asm/system.h>
diff -u --recursive --new-file v2.3.0/linux/include/asm-mips/hdreg.h linux/include/asm-mips/hdreg.h
--- v2.3.0/linux/include/asm-mips/hdreg.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/hdreg.h	Thu May 13 11:00:09 1999
@@ -0,0 +1,18 @@
+/* $Id: hdreg.h,v 1.4 1998/05/08 21:05:26 davem Exp $
+ *
+ *  linux/include/asm-mips/hdreg.h
+ *
+ *  Copyright (C) 1994-1996  Linus Torvalds & authors
+ */
+
+/*
+ *  This file contains the MIPS architecture specific IDE code.
+ */
+
+#ifndef __ASM_MIPS_HDREG_H
+#define __ASM_MIPS_HDREG_H
+
+typedef unsigned short ide_ioreg_t;
+
+#endif /* __ASM_MIPS_HDREG_H */
+
diff -u --recursive --new-file v2.3.0/linux/include/asm-mips/ide.h linux/include/asm-mips/ide.h
--- v2.3.0/linux/include/asm-mips/ide.h	Tue Aug  4 16:06:57 1998
+++ linux/include/asm-mips/ide.h	Thu May 13 11:00:09 1999
@@ -14,8 +14,6 @@
 
 #ifdef __KERNEL__
 
-typedef unsigned short ide_ioreg_t;
-
 #ifndef MAX_HWIFS
 #define MAX_HWIFS	6
 #endif
@@ -25,7 +23,7 @@
 struct ide_ops {
 	int (*ide_default_irq)(ide_ioreg_t base);
 	ide_ioreg_t (*ide_default_io_base)(int index);
-	void (*ide_init_hwif_ports)(ide_ioreg_t *p, ide_ioreg_t base, int *irq);
+	void (*ide_init_hwif_ports)(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq);
 	int (*ide_request_irq)(unsigned int irq, void (*handler)(int, void *,
 	                       struct pt_regs *), unsigned long flags,
 	                       const char *device, void *dev_id);
@@ -48,10 +46,29 @@
 	return ide_ops->ide_default_io_base(index);
 }
 
-static __inline__ void ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base,
-                                           int *irq)
+static __inline__ void ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq)
 {
-	ide_ops->ide_init_hwif_ports(p, base, irq);
+	ide_ops->ide_init_hwif_ports(hw->io_ports, data_port, ctrl_port, &hw->irq);
+
+	hw->irq = ide_ops->ide_default_irq(data_port);
+}
+
+/*
+ * This registers the standard ports for this architecture with the IDE
+ * driver.
+ */
+static __inline__ void ide_init_default_hwifs(void)
+{
+#ifdef __DO_I_NEED_THIS
+	hw_regs_t hw;
+	int index;
+
+	for (index = 0; index < MAX_HWIFS; index++) {
+		ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, 0);
+		hw.irq = ide_default_irq(ide_default_io_base(index));
+		ide_register_hw(&hw, NULL);
+	}
+#endif /* __DO_I_NEED_THIS */
 }
 
 typedef union {
@@ -96,26 +113,10 @@
 /*
  * The following are not needed for the non-m68k ports
  */
-static __inline__ int ide_ack_intr (ide_ioreg_t status_port,
-                                    ide_ioreg_t irq_port)
-{
-	return 1;
-}
-
-static __inline__ void ide_fix_driveid(struct hd_driveid *id)
-{
-}
-
-static __inline__ void ide_release_lock (int *ide_lock)
-{
-}
-
-static __inline__ void ide_get_lock (int *ide_lock,
-                                     void (*handler)(int, void *,
-                                                    struct pt_regs *),
-                                     void *data)
-{
-}
+#define ide_ack_intr(hwif)		(1)
+#define ide_fix_driveid(id)		do {} while (0)
+#define ide_release_lock(lock)		do {} while (0)
+#define ide_get_lock(lock, hdlr, data)	do {} while (0)
 
 #endif /* __KERNEL__ */
 
diff -u --recursive --new-file v2.3.0/linux/include/asm-mips/io.h linux/include/asm-mips/io.h
--- v2.3.0/linux/include/asm-mips/io.h	Fri May  8 00:13:26 1998
+++ linux/include/asm-mips/io.h	Thu May 13 11:00:09 1999
@@ -389,4 +389,8 @@
 extern void (*dma_cache_wback_inv)(unsigned long start, unsigned long size);
 extern void (*dma_cache_inv)(unsigned long start, unsigned long size);
 
+/* Nothing to do */
+
+#define dma_cache_wback(_start,_size)		do { } while (0)
+
 #endif /* __ASM_MIPS_IO_H */
diff -u --recursive --new-file v2.3.0/linux/include/asm-ppc/hdreg.h linux/include/asm-ppc/hdreg.h
--- v2.3.0/linux/include/asm-ppc/hdreg.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ppc/hdreg.h	Thu May 13 11:00:09 1999
@@ -0,0 +1,17 @@
+/*
+ *  linux/include/asm-ppc/hdreg.h
+ *
+ *  Copyright (C) 1994-1996  Linus Torvalds & authors
+ */
+
+/*
+ *  This file contains the ppc architecture specific IDE code.
+ */
+
+#ifndef __ASMPPC_HDREG_H
+#define __ASMPPC_HDREG_H
+
+typedef unsigned int ide_ioreg_t;
+
+#endif /* __ASMPPC_HDREG_H */
+
diff -u --recursive --new-file v2.3.0/linux/include/asm-ppc/ide.h linux/include/asm-ppc/ide.h
--- v2.3.0/linux/include/asm-ppc/ide.h	Thu May  6 23:14:37 1999
+++ linux/include/asm-ppc/ide.h	Thu May 13 11:00:09 1999
@@ -18,7 +18,7 @@
 #define MAX_HWIFS	4
 #endif
 
-typedef unsigned int ide_ioreg_t;
+#include <asm/hdreg.h>
 
 #ifdef __KERNEL__
 
@@ -49,16 +49,17 @@
         void        (*release_region)(ide_ioreg_t from,
                                       unsigned int extent);
         void        (*fix_driveid)(struct hd_driveid *id);
-        void        (*ide_init_hwif)(ide_ioreg_t *p,
-                                     ide_ioreg_t base,
-                                     int *irq); 
+        void        (*ide_init_hwif)(hw_regs_t *hw,
+                                     ide_ioreg_t data_port,
+                                     ide_ioreg_t ctrl_port,
+                                     int *irq);
 
         int io_base;
 };
 
 extern struct ide_machdep_calls ppc_ide_md;
 
-void ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base, int *irq);
+void ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq);
 void ide_insw(ide_ioreg_t port, void *buf, int ns);
 void ide_outsw(ide_ioreg_t port, void *buf, int ns);
 void ppc_generic_ide_fix_driveid(struct hd_driveid *id);
@@ -90,6 +91,20 @@
 	return ppc_ide_md.default_io_base(index);
 }
 
+static __inline__ void ide_init_default_hwifs(void)
+{
+#ifdef __DO_I_NEED_THIS
+	hw_regs_t hw;
+	int index;
+
+	for(index = 0; index < MAX_HWIFS; index++) {
+		ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL);
+		hw.irq = ide_default_irq(ide_default_io_base(index));
+		ide_register_hw(&hw, NULL);
+	}
+#endif /* __DO_I_NEED_THIS */
+}
+
 static __inline__ int ide_check_region (ide_ioreg_t from, unsigned int extent)
 {
 	return ppc_ide_md.check_region(from, extent);
@@ -131,21 +146,13 @@
 	} b;
 } select_t;
 
-static __inline__ int ide_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
-			unsigned long flags, const char *device, void *dev_id)
-{
-	return request_irq(irq, handler, flags, device, dev_id);
-}			
-
-static __inline__ void ide_free_irq(unsigned int irq, void *dev_id)
-{
-	free_irq(irq, dev_id);
-}
+#define ide_request_irq(irq,hand,flg,dev,id)	request_irq((irq),(hand),(flg),(dev),(id))
+#define ide_free_irq(irq,dev_id)		free_irq((irq), (dev_id))
 
 /*
  * The following are not needed for the non-m68k ports
  */
-#define ide_ack_intr(base, irq)		(1)
+#define ide_ack_intr(hwif)		(1)
 #define ide_release_lock(lock)		do {} while (0)
 #define ide_get_lock(lock, hdlr, data)	do {} while (0)
 
diff -u --recursive --new-file v2.3.0/linux/include/asm-ppc/io.h linux/include/asm-ppc/io.h
--- v2.3.0/linux/include/asm-ppc/io.h	Thu Apr 29 12:39:01 1999
+++ linux/include/asm-ppc/io.h	Thu May 13 11:00:09 1999
@@ -277,6 +277,13 @@
 out:
 	return retval;
 }
+
+/* Nothing to do */
+
+#define dma_cache_inv(_start,_size)		do { } while (0)
+#define dma_cache_wback(_start,_size)		do { } while (0)
+#define dma_cache_wback_inv(_start,_size)	do { } while (0)
+
 #endif /* __KERNEL__ */
 
 #endif
diff -u --recursive --new-file v2.3.0/linux/include/asm-sparc/asm_offsets.h linux/include/asm-sparc/asm_offsets.h
--- v2.3.0/linux/include/asm-sparc/asm_offsets.h	Wed Mar 10 16:53:37 1999
+++ linux/include/asm-sparc/asm_offsets.h	Wed May 12 08:41:15 1999
@@ -77,110 +77,110 @@
 #define AOFF_task_tarray_ptr	0x0000008c
 #define ASIZ_task_tarray_ptr	0x00000004
 #define AOFF_task_wait_chldexit	0x00000090
-#define ASIZ_task_wait_chldexit	0x00000004
-#define AOFF_task_vfork_sem	0x00000094
+#define ASIZ_task_wait_chldexit	0x00000014
+#define AOFF_task_vfork_sem	0x000000a4
 #define ASIZ_task_vfork_sem	0x00000004
-#define AOFF_task_policy	0x00000098
+#define AOFF_task_policy	0x000000a8
 #define ASIZ_task_policy	0x00000004
-#define AOFF_task_rt_priority	0x0000009c
+#define AOFF_task_rt_priority	0x000000ac
 #define ASIZ_task_rt_priority	0x00000004
-#define AOFF_task_it_real_value	0x000000a0
+#define AOFF_task_it_real_value	0x000000b0
 #define ASIZ_task_it_real_value	0x00000004
-#define AOFF_task_it_prof_value	0x000000a4
+#define AOFF_task_it_prof_value	0x000000b4
 #define ASIZ_task_it_prof_value	0x00000004
-#define AOFF_task_it_virt_value	0x000000a8
+#define AOFF_task_it_virt_value	0x000000b8
 #define ASIZ_task_it_virt_value	0x00000004
-#define AOFF_task_it_real_incr	0x000000ac
+#define AOFF_task_it_real_incr	0x000000bc
 #define ASIZ_task_it_real_incr	0x00000004
-#define AOFF_task_it_prof_incr	0x000000b0
+#define AOFF_task_it_prof_incr	0x000000c0
 #define ASIZ_task_it_prof_incr	0x00000004
-#define AOFF_task_it_virt_incr	0x000000b4
+#define AOFF_task_it_virt_incr	0x000000c4
 #define ASIZ_task_it_virt_incr	0x00000004
-#define AOFF_task_real_timer	0x000000b8
+#define AOFF_task_real_timer	0x000000c8
 #define ASIZ_task_real_timer	0x00000014
-#define AOFF_task_times	0x000000cc
+#define AOFF_task_times	0x000000dc
 #define ASIZ_task_times	0x00000010
-#define AOFF_task_start_time	0x000000dc
+#define AOFF_task_start_time	0x000000ec
 #define ASIZ_task_start_time	0x00000004
-#define AOFF_task_per_cpu_utime	0x000000e0
+#define AOFF_task_per_cpu_utime	0x000000f0
 #define ASIZ_task_per_cpu_utime	0x00000004
-#define AOFF_task_min_flt	0x000000e8
+#define AOFF_task_min_flt	0x000000f8
 #define ASIZ_task_min_flt	0x00000004
-#define AOFF_task_maj_flt	0x000000ec
+#define AOFF_task_maj_flt	0x000000fc
 #define ASIZ_task_maj_flt	0x00000004
-#define AOFF_task_nswap	0x000000f0
+#define AOFF_task_nswap	0x00000100
 #define ASIZ_task_nswap	0x00000004
-#define AOFF_task_cmin_flt	0x000000f4
+#define AOFF_task_cmin_flt	0x00000104
 #define ASIZ_task_cmin_flt	0x00000004
-#define AOFF_task_cmaj_flt	0x000000f8
+#define AOFF_task_cmaj_flt	0x00000108
 #define ASIZ_task_cmaj_flt	0x00000004
-#define AOFF_task_cnswap	0x000000fc
+#define AOFF_task_cnswap	0x0000010c
 #define ASIZ_task_cnswap	0x00000004
-#define AOFF_task_uid	0x00000102
+#define AOFF_task_uid	0x00000112
 #define ASIZ_task_uid	0x00000002
-#define AOFF_task_euid	0x00000104
+#define AOFF_task_euid	0x00000114
 #define ASIZ_task_euid	0x00000002
-#define AOFF_task_suid	0x00000106
+#define AOFF_task_suid	0x00000116
 #define ASIZ_task_suid	0x00000002
-#define AOFF_task_fsuid	0x00000108
+#define AOFF_task_fsuid	0x00000118
 #define ASIZ_task_fsuid	0x00000002
-#define AOFF_task_gid	0x0000010a
+#define AOFF_task_gid	0x0000011a
 #define ASIZ_task_gid	0x00000002
-#define AOFF_task_egid	0x0000010c
+#define AOFF_task_egid	0x0000011c
 #define ASIZ_task_egid	0x00000002
-#define AOFF_task_sgid	0x0000010e
+#define AOFF_task_sgid	0x0000011e
 #define ASIZ_task_sgid	0x00000002
-#define AOFF_task_fsgid	0x00000110
+#define AOFF_task_fsgid	0x00000120
 #define ASIZ_task_fsgid	0x00000002
-#define AOFF_task_ngroups	0x00000114
+#define AOFF_task_ngroups	0x00000124
 #define ASIZ_task_ngroups	0x00000004
-#define AOFF_task_groups	0x00000118
+#define AOFF_task_groups	0x00000128
 #define ASIZ_task_groups	0x00000040
-#define AOFF_task_cap_effective	0x00000158
+#define AOFF_task_cap_effective	0x00000168
 #define ASIZ_task_cap_effective	0x00000004
-#define AOFF_task_cap_inheritable	0x0000015c
+#define AOFF_task_cap_inheritable	0x0000016c
 #define ASIZ_task_cap_inheritable	0x00000004
-#define AOFF_task_cap_permitted	0x00000160
+#define AOFF_task_cap_permitted	0x00000170
 #define ASIZ_task_cap_permitted	0x00000004
-#define AOFF_task_user	0x00000164
+#define AOFF_task_user	0x00000174
 #define ASIZ_task_user	0x00000004
-#define AOFF_task_rlim	0x00000168
+#define AOFF_task_rlim	0x00000178
 #define ASIZ_task_rlim	0x00000050
-#define AOFF_task_used_math	0x000001b8
+#define AOFF_task_used_math	0x000001c8
 #define ASIZ_task_used_math	0x00000002
-#define AOFF_task_comm	0x000001ba
+#define AOFF_task_comm	0x000001ca
 #define ASIZ_task_comm	0x00000010
-#define AOFF_task_link_count	0x000001cc
+#define AOFF_task_link_count	0x000001dc
 #define ASIZ_task_link_count	0x00000004
-#define AOFF_task_tty	0x000001d0
+#define AOFF_task_tty	0x000001e0
 #define ASIZ_task_tty	0x00000004
-#define AOFF_task_semundo	0x000001d4
+#define AOFF_task_semundo	0x000001e4
 #define ASIZ_task_semundo	0x00000004
-#define AOFF_task_semsleeping	0x000001d8
+#define AOFF_task_semsleeping	0x000001e8
 #define ASIZ_task_semsleeping	0x00000004
-#define AOFF_task_tss	0x000001e0
+#define AOFF_task_tss	0x000001f0
 #define ASIZ_task_tss	0x00000388
-#define AOFF_task_fs	0x00000568
+#define AOFF_task_fs	0x00000578
 #define ASIZ_task_fs	0x00000004
-#define AOFF_task_files	0x0000056c
+#define AOFF_task_files	0x0000057c
 #define ASIZ_task_files	0x00000004
-#define AOFF_task_mm	0x00000570
+#define AOFF_task_mm	0x00000580
 #define ASIZ_task_mm	0x00000004
-#define AOFF_task_sigmask_lock	0x00000574
+#define AOFF_task_sigmask_lock	0x00000584
 #define ASIZ_task_sigmask_lock	0x00000001
-#define AOFF_task_sig	0x00000578
+#define AOFF_task_sig	0x00000588
 #define ASIZ_task_sig	0x00000004
-#define AOFF_task_signal	0x0000057c
+#define AOFF_task_signal	0x0000058c
 #define ASIZ_task_signal	0x00000008
-#define AOFF_task_blocked	0x00000584
+#define AOFF_task_blocked	0x00000594
 #define ASIZ_task_blocked	0x00000008
-#define AOFF_task_sigqueue	0x0000058c
+#define AOFF_task_sigqueue	0x0000059c
 #define ASIZ_task_sigqueue	0x00000004
-#define AOFF_task_sigqueue_tail	0x00000590
+#define AOFF_task_sigqueue_tail	0x000005a0
 #define ASIZ_task_sigqueue_tail	0x00000004
-#define AOFF_task_sas_ss_sp	0x00000594
+#define AOFF_task_sas_ss_sp	0x000005a4
 #define ASIZ_task_sas_ss_sp	0x00000004
-#define AOFF_task_sas_ss_size	0x00000598
+#define AOFF_task_sas_ss_size	0x000005a8
 #define ASIZ_task_sas_ss_size	0x00000004
 #define AOFF_mm_mmap	0x00000000
 #define ASIZ_mm_mmap	0x00000004
@@ -195,46 +195,46 @@
 #define AOFF_mm_map_count	0x00000014
 #define ASIZ_mm_map_count	0x00000004
 #define AOFF_mm_mmap_sem	0x00000018
-#define ASIZ_mm_mmap_sem	0x0000000c
-#define AOFF_mm_context	0x00000024
+#define ASIZ_mm_mmap_sem	0x00000020
+#define AOFF_mm_context	0x00000038
 #define ASIZ_mm_context	0x00000004
-#define AOFF_mm_start_code	0x00000028
+#define AOFF_mm_start_code	0x0000003c
 #define ASIZ_mm_start_code	0x00000004
-#define AOFF_mm_end_code	0x0000002c
+#define AOFF_mm_end_code	0x00000040
 #define ASIZ_mm_end_code	0x00000004
-#define AOFF_mm_start_data	0x00000030
+#define AOFF_mm_start_data	0x00000044
 #define ASIZ_mm_start_data	0x00000004
-#define AOFF_mm_end_data	0x00000034
+#define AOFF_mm_end_data	0x00000048
 #define ASIZ_mm_end_data	0x00000004
-#define AOFF_mm_start_brk	0x00000038
+#define AOFF_mm_start_brk	0x0000004c
 #define ASIZ_mm_start_brk	0x00000004
-#define AOFF_mm_brk	0x0000003c
+#define AOFF_mm_brk	0x00000050
 #define ASIZ_mm_brk	0x00000004
-#define AOFF_mm_start_stack	0x00000040
+#define AOFF_mm_start_stack	0x00000054
 #define ASIZ_mm_start_stack	0x00000004
-#define AOFF_mm_arg_start	0x00000044
+#define AOFF_mm_arg_start	0x00000058
 #define ASIZ_mm_arg_start	0x00000004
-#define AOFF_mm_arg_end	0x00000048
+#define AOFF_mm_arg_end	0x0000005c
 #define ASIZ_mm_arg_end	0x00000004
-#define AOFF_mm_env_start	0x0000004c
+#define AOFF_mm_env_start	0x00000060
 #define ASIZ_mm_env_start	0x00000004
-#define AOFF_mm_env_end	0x00000050
+#define AOFF_mm_env_end	0x00000064
 #define ASIZ_mm_env_end	0x00000004
-#define AOFF_mm_rss	0x00000054
+#define AOFF_mm_rss	0x00000068
 #define ASIZ_mm_rss	0x00000004
-#define AOFF_mm_total_vm	0x00000058
+#define AOFF_mm_total_vm	0x0000006c
 #define ASIZ_mm_total_vm	0x00000004
-#define AOFF_mm_locked_vm	0x0000005c
+#define AOFF_mm_locked_vm	0x00000070
 #define ASIZ_mm_locked_vm	0x00000004
-#define AOFF_mm_def_flags	0x00000060
+#define AOFF_mm_def_flags	0x00000074
 #define ASIZ_mm_def_flags	0x00000004
-#define AOFF_mm_cpu_vm_mask	0x00000064
+#define AOFF_mm_cpu_vm_mask	0x00000078
 #define ASIZ_mm_cpu_vm_mask	0x00000004
-#define AOFF_mm_swap_cnt	0x00000068
+#define AOFF_mm_swap_cnt	0x0000007c
 #define ASIZ_mm_swap_cnt	0x00000004
-#define AOFF_mm_swap_address	0x0000006c
+#define AOFF_mm_swap_address	0x00000080
 #define ASIZ_mm_swap_address	0x00000004
-#define AOFF_mm_segments	0x00000070
+#define AOFF_mm_segments	0x00000084
 #define ASIZ_mm_segments	0x00000004
 #define AOFF_thread_uwinmask	0x00000000
 #define ASIZ_thread_uwinmask	0x00000004
@@ -352,110 +352,110 @@
 #define AOFF_task_tarray_ptr	0x0000008c
 #define ASIZ_task_tarray_ptr	0x00000004
 #define AOFF_task_wait_chldexit	0x00000090
-#define ASIZ_task_wait_chldexit	0x00000004
-#define AOFF_task_vfork_sem	0x00000094
+#define ASIZ_task_wait_chldexit	0x00000018
+#define AOFF_task_vfork_sem	0x000000a8
 #define ASIZ_task_vfork_sem	0x00000004
-#define AOFF_task_policy	0x00000098
+#define AOFF_task_policy	0x000000ac
 #define ASIZ_task_policy	0x00000004
-#define AOFF_task_rt_priority	0x0000009c
+#define AOFF_task_rt_priority	0x000000b0
 #define ASIZ_task_rt_priority	0x00000004
-#define AOFF_task_it_real_value	0x000000a0
+#define AOFF_task_it_real_value	0x000000b4
 #define ASIZ_task_it_real_value	0x00000004
-#define AOFF_task_it_prof_value	0x000000a4
+#define AOFF_task_it_prof_value	0x000000b8
 #define ASIZ_task_it_prof_value	0x00000004
-#define AOFF_task_it_virt_value	0x000000a8
+#define AOFF_task_it_virt_value	0x000000bc
 #define ASIZ_task_it_virt_value	0x00000004
-#define AOFF_task_it_real_incr	0x000000ac
+#define AOFF_task_it_real_incr	0x000000c0
 #define ASIZ_task_it_real_incr	0x00000004
-#define AOFF_task_it_prof_incr	0x000000b0
+#define AOFF_task_it_prof_incr	0x000000c4
 #define ASIZ_task_it_prof_incr	0x00000004
-#define AOFF_task_it_virt_incr	0x000000b4
+#define AOFF_task_it_virt_incr	0x000000c8
 #define ASIZ_task_it_virt_incr	0x00000004
-#define AOFF_task_real_timer	0x000000b8
+#define AOFF_task_real_timer	0x000000cc
 #define ASIZ_task_real_timer	0x00000014
-#define AOFF_task_times	0x000000cc
+#define AOFF_task_times	0x000000e0
 #define ASIZ_task_times	0x00000010
-#define AOFF_task_start_time	0x000000dc
+#define AOFF_task_start_time	0x000000f0
 #define ASIZ_task_start_time	0x00000004
-#define AOFF_task_per_cpu_utime	0x000000e0
+#define AOFF_task_per_cpu_utime	0x000000f4
 #define ASIZ_task_per_cpu_utime	0x00000080
-#define AOFF_task_min_flt	0x000001e0
+#define AOFF_task_min_flt	0x000001f4
 #define ASIZ_task_min_flt	0x00000004
-#define AOFF_task_maj_flt	0x000001e4
+#define AOFF_task_maj_flt	0x000001f8
 #define ASIZ_task_maj_flt	0x00000004
-#define AOFF_task_nswap	0x000001e8
+#define AOFF_task_nswap	0x000001fc
 #define ASIZ_task_nswap	0x00000004
-#define AOFF_task_cmin_flt	0x000001ec
+#define AOFF_task_cmin_flt	0x00000200
 #define ASIZ_task_cmin_flt	0x00000004
-#define AOFF_task_cmaj_flt	0x000001f0
+#define AOFF_task_cmaj_flt	0x00000204
 #define ASIZ_task_cmaj_flt	0x00000004
-#define AOFF_task_cnswap	0x000001f4
+#define AOFF_task_cnswap	0x00000208
 #define ASIZ_task_cnswap	0x00000004
-#define AOFF_task_uid	0x000001fa
+#define AOFF_task_uid	0x0000020e
 #define ASIZ_task_uid	0x00000002
-#define AOFF_task_euid	0x000001fc
+#define AOFF_task_euid	0x00000210
 #define ASIZ_task_euid	0x00000002
-#define AOFF_task_suid	0x000001fe
+#define AOFF_task_suid	0x00000212
 #define ASIZ_task_suid	0x00000002
-#define AOFF_task_fsuid	0x00000200
+#define AOFF_task_fsuid	0x00000214
 #define ASIZ_task_fsuid	0x00000002
-#define AOFF_task_gid	0x00000202
+#define AOFF_task_gid	0x00000216
 #define ASIZ_task_gid	0x00000002
-#define AOFF_task_egid	0x00000204
+#define AOFF_task_egid	0x00000218
 #define ASIZ_task_egid	0x00000002
-#define AOFF_task_sgid	0x00000206
+#define AOFF_task_sgid	0x0000021a
 #define ASIZ_task_sgid	0x00000002
-#define AOFF_task_fsgid	0x00000208
+#define AOFF_task_fsgid	0x0000021c
 #define ASIZ_task_fsgid	0x00000002
-#define AOFF_task_ngroups	0x0000020c
+#define AOFF_task_ngroups	0x00000220
 #define ASIZ_task_ngroups	0x00000004
-#define AOFF_task_groups	0x00000210
+#define AOFF_task_groups	0x00000224
 #define ASIZ_task_groups	0x00000040
-#define AOFF_task_cap_effective	0x00000250
+#define AOFF_task_cap_effective	0x00000264
 #define ASIZ_task_cap_effective	0x00000004
-#define AOFF_task_cap_inheritable	0x00000254
+#define AOFF_task_cap_inheritable	0x00000268
 #define ASIZ_task_cap_inheritable	0x00000004
-#define AOFF_task_cap_permitted	0x00000258
+#define AOFF_task_cap_permitted	0x0000026c
 #define ASIZ_task_cap_permitted	0x00000004
-#define AOFF_task_user	0x0000025c
+#define AOFF_task_user	0x00000270
 #define ASIZ_task_user	0x00000004
-#define AOFF_task_rlim	0x00000260
+#define AOFF_task_rlim	0x00000274
 #define ASIZ_task_rlim	0x00000050
-#define AOFF_task_used_math	0x000002b0
+#define AOFF_task_used_math	0x000002c4
 #define ASIZ_task_used_math	0x00000002
-#define AOFF_task_comm	0x000002b2
+#define AOFF_task_comm	0x000002c6
 #define ASIZ_task_comm	0x00000010
-#define AOFF_task_link_count	0x000002c4
+#define AOFF_task_link_count	0x000002d8
 #define ASIZ_task_link_count	0x00000004
-#define AOFF_task_tty	0x000002c8
+#define AOFF_task_tty	0x000002dc
 #define ASIZ_task_tty	0x00000004
-#define AOFF_task_semundo	0x000002cc
+#define AOFF_task_semundo	0x000002e0
 #define ASIZ_task_semundo	0x00000004
-#define AOFF_task_semsleeping	0x000002d0
+#define AOFF_task_semsleeping	0x000002e4
 #define ASIZ_task_semsleeping	0x00000004
-#define AOFF_task_tss	0x000002d8
+#define AOFF_task_tss	0x000002e8
 #define ASIZ_task_tss	0x00000388
-#define AOFF_task_fs	0x00000660
+#define AOFF_task_fs	0x00000670
 #define ASIZ_task_fs	0x00000004
-#define AOFF_task_files	0x00000664
+#define AOFF_task_files	0x00000674
 #define ASIZ_task_files	0x00000004
-#define AOFF_task_mm	0x00000668
+#define AOFF_task_mm	0x00000678
 #define ASIZ_task_mm	0x00000004
-#define AOFF_task_sigmask_lock	0x0000066c
+#define AOFF_task_sigmask_lock	0x0000067c
 #define ASIZ_task_sigmask_lock	0x00000008
-#define AOFF_task_sig	0x00000674
+#define AOFF_task_sig	0x00000684
 #define ASIZ_task_sig	0x00000004
-#define AOFF_task_signal	0x00000678
+#define AOFF_task_signal	0x00000688
 #define ASIZ_task_signal	0x00000008
-#define AOFF_task_blocked	0x00000680
+#define AOFF_task_blocked	0x00000690
 #define ASIZ_task_blocked	0x00000008
-#define AOFF_task_sigqueue	0x00000688
+#define AOFF_task_sigqueue	0x00000698
 #define ASIZ_task_sigqueue	0x00000004
-#define AOFF_task_sigqueue_tail	0x0000068c
+#define AOFF_task_sigqueue_tail	0x0000069c
 #define ASIZ_task_sigqueue_tail	0x00000004
-#define AOFF_task_sas_ss_sp	0x00000690
+#define AOFF_task_sas_ss_sp	0x000006a0
 #define ASIZ_task_sas_ss_sp	0x00000004
-#define AOFF_task_sas_ss_size	0x00000694
+#define AOFF_task_sas_ss_size	0x000006a4
 #define ASIZ_task_sas_ss_size	0x00000004
 #define AOFF_mm_mmap	0x00000000
 #define ASIZ_mm_mmap	0x00000004
@@ -470,46 +470,46 @@
 #define AOFF_mm_map_count	0x00000014
 #define ASIZ_mm_map_count	0x00000004
 #define AOFF_mm_mmap_sem	0x00000018
-#define ASIZ_mm_mmap_sem	0x0000000c
-#define AOFF_mm_context	0x00000024
+#define ASIZ_mm_mmap_sem	0x00000024
+#define AOFF_mm_context	0x0000003c
 #define ASIZ_mm_context	0x00000004
-#define AOFF_mm_start_code	0x00000028
+#define AOFF_mm_start_code	0x00000040
 #define ASIZ_mm_start_code	0x00000004
-#define AOFF_mm_end_code	0x0000002c
+#define AOFF_mm_end_code	0x00000044
 #define ASIZ_mm_end_code	0x00000004
-#define AOFF_mm_start_data	0x00000030
+#define AOFF_mm_start_data	0x00000048
 #define ASIZ_mm_start_data	0x00000004
-#define AOFF_mm_end_data	0x00000034
+#define AOFF_mm_end_data	0x0000004c
 #define ASIZ_mm_end_data	0x00000004
-#define AOFF_mm_start_brk	0x00000038
+#define AOFF_mm_start_brk	0x00000050
 #define ASIZ_mm_start_brk	0x00000004
-#define AOFF_mm_brk	0x0000003c
+#define AOFF_mm_brk	0x00000054
 #define ASIZ_mm_brk	0x00000004
-#define AOFF_mm_start_stack	0x00000040
+#define AOFF_mm_start_stack	0x00000058
 #define ASIZ_mm_start_stack	0x00000004
-#define AOFF_mm_arg_start	0x00000044
+#define AOFF_mm_arg_start	0x0000005c
 #define ASIZ_mm_arg_start	0x00000004
-#define AOFF_mm_arg_end	0x00000048
+#define AOFF_mm_arg_end	0x00000060
 #define ASIZ_mm_arg_end	0x00000004
-#define AOFF_mm_env_start	0x0000004c
+#define AOFF_mm_env_start	0x00000064
 #define ASIZ_mm_env_start	0x00000004
-#define AOFF_mm_env_end	0x00000050
+#define AOFF_mm_env_end	0x00000068
 #define ASIZ_mm_env_end	0x00000004
-#define AOFF_mm_rss	0x00000054
+#define AOFF_mm_rss	0x0000006c
 #define ASIZ_mm_rss	0x00000004
-#define AOFF_mm_total_vm	0x00000058
+#define AOFF_mm_total_vm	0x00000070
 #define ASIZ_mm_total_vm	0x00000004
-#define AOFF_mm_locked_vm	0x0000005c
+#define AOFF_mm_locked_vm	0x00000074
 #define ASIZ_mm_locked_vm	0x00000004
-#define AOFF_mm_def_flags	0x00000060
+#define AOFF_mm_def_flags	0x00000078
 #define ASIZ_mm_def_flags	0x00000004
-#define AOFF_mm_cpu_vm_mask	0x00000064
+#define AOFF_mm_cpu_vm_mask	0x0000007c
 #define ASIZ_mm_cpu_vm_mask	0x00000004
-#define AOFF_mm_swap_cnt	0x00000068
+#define AOFF_mm_swap_cnt	0x00000080
 #define ASIZ_mm_swap_cnt	0x00000004
-#define AOFF_mm_swap_address	0x0000006c
+#define AOFF_mm_swap_address	0x00000084
 #define ASIZ_mm_swap_address	0x00000004
-#define AOFF_mm_segments	0x00000070
+#define AOFF_mm_segments	0x00000088
 #define ASIZ_mm_segments	0x00000004
 #define AOFF_thread_uwinmask	0x00000000
 #define ASIZ_thread_uwinmask	0x00000004
diff -u --recursive --new-file v2.3.0/linux/include/asm-sparc/audioio.h linux/include/asm-sparc/audioio.h
--- v2.3.0/linux/include/asm-sparc/audioio.h	Wed Nov 18 09:06:05 1998
+++ linux/include/asm-sparc/audioio.h	Wed May 12 08:41:15 1999
@@ -275,7 +275,7 @@
         struct linux_sbus_device *dev;
 
 	/* Processes blocked on open() sit here. */
-	struct wait_queue *open_wait;
+	wait_queue_head_t open_wait;
 
 	/* Task queue for this driver's bottom half. */
 	struct tq_struct tqueue;
@@ -288,7 +288,7 @@
 	size_t *output_sizes, output_size, output_buffer_size;
 	int num_output_buffers, output_front, output_rear, output_offset;
 	int output_count, output_active, playing_count, output_eof;
-	struct wait_queue *output_write_wait, *output_drain_wait;
+	wait_queue_head_t output_write_wait, output_drain_wait;
         char *output_notify;
 
         /* Support for a circular queue of input buffers. */
@@ -296,7 +296,7 @@
 	size_t *input_sizes, input_size, input_buffer_size;
         int num_input_buffers, input_front, input_rear, input_offset;
         int input_count, input_active, recording_count;
-        struct wait_queue *input_read_wait;
+        wait_queue_head_t input_read_wait;
 
         /* Hack to make it look like we support variable size buffers. */
         int buffer_size;
diff -u --recursive --new-file v2.3.0/linux/include/asm-sparc/io.h linux/include/asm-sparc/io.h
--- v2.3.0/linux/include/asm-sparc/io.h	Sun Oct  4 10:22:44 1998
+++ linux/include/asm-sparc/io.h	Thu May 13 11:00:09 1999
@@ -162,4 +162,10 @@
 #define virt_to_phys(x) __pa((unsigned long)(x))
 #define phys_to_virt(x) __va((unsigned long)(x))
 
+/* Nothing to do */
+
+#define dma_cache_inv(_start,_size)		do { } while (0)
+#define dma_cache_wback(_start,_size)		do { } while (0)
+#define dma_cache_wback_inv(_start,_size)	do { } while (0)
+
 #endif /* !(__SPARC_IO_H) */
diff -u --recursive --new-file v2.3.0/linux/include/asm-sparc/semaphore.h linux/include/asm-sparc/semaphore.h
--- v2.3.0/linux/include/asm-sparc/semaphore.h	Wed Mar 10 16:53:37 1999
+++ linux/include/asm-sparc/semaphore.h	Wed May 12 08:41:15 1999
@@ -6,28 +6,71 @@
 #ifdef __KERNEL__
 
 #include <asm/atomic.h>
+#include <linux/wait.h>
 
 struct semaphore {
 	atomic_t count;
 	atomic_t waking;
-	struct wait_queue * wait;
+	wait_queue_head_t wait;
+#if WAITQUEUE_DEBUG
+	long __magic;
+#endif
 };
 
-#define MUTEX ((struct semaphore) { ATOMIC_INIT(1), ATOMIC_INIT(0), NULL })
-#define MUTEX_LOCKED ((struct semaphore) { ATOMIC_INIT(0), ATOMIC_INIT(0), NULL })
+#if WAITQUEUE_DEBUG
+# define __SEM_DEBUG_INIT(name) \
+		, (long)&(name).__magic
+#else
+# define __SEM_DEBUG_INIT(name)
+#endif
+
+#define __SEMAPHORE_INITIALIZER(name,count) \
+{ ATOMIC_INIT(count), ATOMIC_INIT(0), __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
+	__SEM_DEBUG_INIT(name) }
+
+#define __MUTEX_INITIALIZER(name) \
+	__SEMAPHORE_INITIALIZER(name,1)
+
+#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+	struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+
+#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
+#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
+
+extern inline void sema_init (struct semaphore *sem, int val)
+{
+	atomic_set(&sem->count, val);
+	atomic_set(&sem->waking, 0);
+	init_waitqueue_head(&sem->wait);
+#if WAITQUEUE_DEBUG
+	sem->__magic = (long)&sem->__magic;
+#endif
+}
+
+static inline void init_MUTEX (struct semaphore *sem)
+{
+	sema_init(sem, 1);
+}
+
+static inline void init_MUTEX_LOCKED (struct semaphore *sem)
+{
+	sema_init(sem, 0);
+}
 
 extern void __down(struct semaphore * sem);
 extern int __down_interruptible(struct semaphore * sem);
 extern int __down_trylock(struct semaphore * sem);
 extern void __up(struct semaphore * sem);
 
-#define sema_init(sem, val)	atomic_set(&((sem)->count), val)
-
 extern inline void down(struct semaphore * sem)
 {
 	register atomic_t *ptr asm("g1");
 	register int increment asm("g2");
 
+#if WAITQUEUE_DEBUG
+	CHECK_MAGIC(sem->__magic);
+#endif
+
 	ptr = (atomic_t *) __atomic_fool_gcc(sem);
 	increment = 1;
 
@@ -59,6 +102,10 @@
 	register atomic_t *ptr asm("g1");
 	register int increment asm("g2");
 
+#if WAITQUEUE_DEBUG
+	CHECK_MAGIC(sem->__magic);
+#endif
+
 	ptr = (atomic_t *) __atomic_fool_gcc(sem);
 	increment = 1;
 
@@ -93,6 +140,10 @@
 	register atomic_t *ptr asm("g1");
 	register int increment asm("g2");
 
+#if WAITQUEUE_DEBUG
+	CHECK_MAGIC(sem->__magic);
+#endif
+
 	ptr = (atomic_t *) __atomic_fool_gcc(sem);
 	increment = 1;
 
@@ -126,6 +177,10 @@
 {
 	register atomic_t *ptr asm("g1");
 	register int increment asm("g2");
+
+#if WAITQUEUE_DEBUG
+	CHECK_MAGIC(sem->__magic);
+#endif
 
 	ptr = (atomic_t *) __atomic_fool_gcc(sem);
 	increment = 1;
diff -u --recursive --new-file v2.3.0/linux/include/asm-sparc64/asm_offsets.h linux/include/asm-sparc64/asm_offsets.h
--- v2.3.0/linux/include/asm-sparc64/asm_offsets.h	Wed Mar 10 16:53:38 1999
+++ linux/include/asm-sparc64/asm_offsets.h	Wed May 12 08:41:15 1999
@@ -77,112 +77,112 @@
 #define AOFF_task_tarray_ptr	0x000000e8
 #define ASIZ_task_tarray_ptr	0x00000008
 #define AOFF_task_wait_chldexit	0x000000f0
-#define ASIZ_task_wait_chldexit	0x00000008
-#define AOFF_task_vfork_sem	0x000000f8
+#define ASIZ_task_wait_chldexit	0x00000028
+#define AOFF_task_vfork_sem	0x00000118
 #define ASIZ_task_vfork_sem	0x00000008
-#define AOFF_task_policy	0x00000100
+#define AOFF_task_policy	0x00000120
 #define ASIZ_task_policy	0x00000008
-#define AOFF_task_rt_priority	0x00000108
+#define AOFF_task_rt_priority	0x00000128
 #define ASIZ_task_rt_priority	0x00000008
-#define AOFF_task_it_real_value	0x00000110
+#define AOFF_task_it_real_value	0x00000130
 #define ASIZ_task_it_real_value	0x00000008
-#define AOFF_task_it_prof_value	0x00000118
+#define AOFF_task_it_prof_value	0x00000138
 #define ASIZ_task_it_prof_value	0x00000008
-#define AOFF_task_it_virt_value	0x00000120
+#define AOFF_task_it_virt_value	0x00000140
 #define ASIZ_task_it_virt_value	0x00000008
-#define AOFF_task_it_real_incr	0x00000128
+#define AOFF_task_it_real_incr	0x00000148
 #define ASIZ_task_it_real_incr	0x00000008
-#define AOFF_task_it_prof_incr	0x00000130
+#define AOFF_task_it_prof_incr	0x00000150
 #define ASIZ_task_it_prof_incr	0x00000008
-#define AOFF_task_it_virt_incr	0x00000138
+#define AOFF_task_it_virt_incr	0x00000158
 #define ASIZ_task_it_virt_incr	0x00000008
-#define AOFF_task_real_timer	0x00000140
+#define AOFF_task_real_timer	0x00000160
 #define ASIZ_task_real_timer	0x00000028
-#define AOFF_task_times	0x00000168
+#define AOFF_task_times	0x00000188
 #define ASIZ_task_times	0x00000020
-#define AOFF_task_start_time	0x00000188
+#define AOFF_task_start_time	0x000001a8
 #define ASIZ_task_start_time	0x00000008
-#define AOFF_task_per_cpu_utime	0x00000190
+#define AOFF_task_per_cpu_utime	0x000001b0
 #define ASIZ_task_per_cpu_utime	0x00000008
-#define AOFF_task_min_flt	0x000001a0
+#define AOFF_task_min_flt	0x000001c0
 #define ASIZ_task_min_flt	0x00000008
-#define AOFF_task_maj_flt	0x000001a8
+#define AOFF_task_maj_flt	0x000001c8
 #define ASIZ_task_maj_flt	0x00000008
-#define AOFF_task_nswap	0x000001b0
+#define AOFF_task_nswap	0x000001d0
 #define ASIZ_task_nswap	0x00000008
-#define AOFF_task_cmin_flt	0x000001b8
+#define AOFF_task_cmin_flt	0x000001d8
 #define ASIZ_task_cmin_flt	0x00000008
-#define AOFF_task_cmaj_flt	0x000001c0
+#define AOFF_task_cmaj_flt	0x000001e0
 #define ASIZ_task_cmaj_flt	0x00000008
-#define AOFF_task_cnswap	0x000001c8
+#define AOFF_task_cnswap	0x000001e8
 #define ASIZ_task_cnswap	0x00000008
-#define AOFF_task_uid	0x000001d4
+#define AOFF_task_uid	0x000001f4
 #define ASIZ_task_uid	0x00000004
-#define AOFF_task_euid	0x000001d8
+#define AOFF_task_euid	0x000001f8
 #define ASIZ_task_euid	0x00000004
-#define AOFF_task_suid	0x000001dc
+#define AOFF_task_suid	0x000001fc
 #define ASIZ_task_suid	0x00000004
-#define AOFF_task_fsuid	0x000001e0
+#define AOFF_task_fsuid	0x00000200
 #define ASIZ_task_fsuid	0x00000004
-#define AOFF_task_gid	0x000001e4
+#define AOFF_task_gid	0x00000204
 #define ASIZ_task_gid	0x00000004
-#define AOFF_task_egid	0x000001e8
+#define AOFF_task_egid	0x00000208
 #define ASIZ_task_egid	0x00000004
-#define AOFF_task_sgid	0x000001ec
+#define AOFF_task_sgid	0x0000020c
 #define ASIZ_task_sgid	0x00000004
-#define AOFF_task_fsgid	0x000001f0
+#define AOFF_task_fsgid	0x00000210
 #define ASIZ_task_fsgid	0x00000004
-#define AOFF_task_ngroups	0x000001f4
+#define AOFF_task_ngroups	0x00000214
 #define ASIZ_task_ngroups	0x00000004
-#define AOFF_task_groups	0x000001f8
+#define AOFF_task_groups	0x00000218
 #define ASIZ_task_groups	0x00000080
-#define AOFF_task_cap_effective	0x00000278
+#define AOFF_task_cap_effective	0x00000298
 #define ASIZ_task_cap_effective	0x00000004
-#define AOFF_task_cap_inheritable	0x0000027c
+#define AOFF_task_cap_inheritable	0x0000029c
 #define ASIZ_task_cap_inheritable	0x00000004
-#define AOFF_task_cap_permitted	0x00000280
+#define AOFF_task_cap_permitted	0x000002a0
 #define ASIZ_task_cap_permitted	0x00000004
-#define AOFF_task_user	0x00000288
+#define AOFF_task_user	0x000002a8
 #define ASIZ_task_user	0x00000008
-#define AOFF_task_rlim	0x00000290
+#define AOFF_task_rlim	0x000002b0
 #define ASIZ_task_rlim	0x000000a0
-#define AOFF_task_used_math	0x00000330
+#define AOFF_task_used_math	0x00000350
 #define ASIZ_task_used_math	0x00000002
-#define AOFF_task_comm	0x00000332
+#define AOFF_task_comm	0x00000352
 #define ASIZ_task_comm	0x00000010
-#define AOFF_task_link_count	0x00000344
+#define AOFF_task_link_count	0x00000364
 #define ASIZ_task_link_count	0x00000004
-#define AOFF_task_tty	0x00000348
+#define AOFF_task_tty	0x00000368
 #define ASIZ_task_tty	0x00000008
-#define AOFF_task_semundo	0x00000350
+#define AOFF_task_semundo	0x00000370
 #define ASIZ_task_semundo	0x00000008
-#define AOFF_task_semsleeping	0x00000358
+#define AOFF_task_semsleeping	0x00000378
 #define ASIZ_task_semsleeping	0x00000008
-#define AOFF_task_tss	0x00000360
+#define AOFF_task_tss	0x00000380
 #define ASIZ_task_tss	0x00000470
-#define AOFF_task_fs	0x000007d0
+#define AOFF_task_fs	0x000007f0
 #define ASIZ_task_fs	0x00000008
-#define AOFF_task_files	0x000007d8
+#define AOFF_task_files	0x000007f8
 #define ASIZ_task_files	0x00000008
-#define AOFF_task_mm	0x000007e0
+#define AOFF_task_mm	0x00000800
 #define ASIZ_task_mm	0x00000008
-#define AOFF_task_sigmask_lock	0x000007e8
+#define AOFF_task_sigmask_lock	0x00000808
 #define ASIZ_task_sigmask_lock	0x00000001
-#define AOFF_task_sig	0x000007f0
+#define AOFF_task_sig	0x00000810
 #define ASIZ_task_sig	0x00000008
-#define AOFF_task_signal	0x000007f8
+#define AOFF_task_signal	0x00000818
 #define ASIZ_task_signal	0x00000008
-#define AOFF_task_blocked	0x00000800
+#define AOFF_task_blocked	0x00000820
 #define ASIZ_task_blocked	0x00000008
-#define AOFF_task_sigqueue	0x00000808
+#define AOFF_task_sigqueue	0x00000828
 #define ASIZ_task_sigqueue	0x00000008
-#define AOFF_task_sigqueue_tail	0x00000810
+#define AOFF_task_sigqueue_tail	0x00000830
 #define ASIZ_task_sigqueue_tail	0x00000008
-#define AOFF_task_sas_ss_sp	0x00000818
+#define AOFF_task_sas_ss_sp	0x00000838
 #define ASIZ_task_sas_ss_sp	0x00000008
-#define AOFF_task_sas_ss_size	0x00000820
+#define AOFF_task_sas_ss_size	0x00000840
 #define ASIZ_task_sas_ss_size	0x00000008
-#define ASIZ_task	0x00000830
+#define ASIZ_task	0x00000850
 #define AOFF_mm_mmap	0x00000000
 #define ASIZ_mm_mmap	0x00000008
 #define AOFF_mm_mmap_avl	0x00000008
@@ -196,48 +196,48 @@
 #define AOFF_mm_map_count	0x00000024
 #define ASIZ_mm_map_count	0x00000004
 #define AOFF_mm_mmap_sem	0x00000028
-#define ASIZ_mm_mmap_sem	0x00000010
-#define AOFF_mm_context	0x00000038
+#define ASIZ_mm_mmap_sem	0x00000038
+#define AOFF_mm_context	0x00000060
 #define ASIZ_mm_context	0x00000008
-#define AOFF_mm_start_code	0x00000040
+#define AOFF_mm_start_code	0x00000068
 #define ASIZ_mm_start_code	0x00000008
-#define AOFF_mm_end_code	0x00000048
+#define AOFF_mm_end_code	0x00000070
 #define ASIZ_mm_end_code	0x00000008
-#define AOFF_mm_start_data	0x00000050
+#define AOFF_mm_start_data	0x00000078
 #define ASIZ_mm_start_data	0x00000008
-#define AOFF_mm_end_data	0x00000058
+#define AOFF_mm_end_data	0x00000080
 #define ASIZ_mm_end_data	0x00000008
-#define AOFF_mm_start_brk	0x00000060
+#define AOFF_mm_start_brk	0x00000088
 #define ASIZ_mm_start_brk	0x00000008
-#define AOFF_mm_brk	0x00000068
+#define AOFF_mm_brk	0x00000090
 #define ASIZ_mm_brk	0x00000008
-#define AOFF_mm_start_stack	0x00000070
+#define AOFF_mm_start_stack	0x00000098
 #define ASIZ_mm_start_stack	0x00000008
-#define AOFF_mm_arg_start	0x00000078
+#define AOFF_mm_arg_start	0x000000a0
 #define ASIZ_mm_arg_start	0x00000008
-#define AOFF_mm_arg_end	0x00000080
+#define AOFF_mm_arg_end	0x000000a8
 #define ASIZ_mm_arg_end	0x00000008
-#define AOFF_mm_env_start	0x00000088
+#define AOFF_mm_env_start	0x000000b0
 #define ASIZ_mm_env_start	0x00000008
-#define AOFF_mm_env_end	0x00000090
+#define AOFF_mm_env_end	0x000000b8
 #define ASIZ_mm_env_end	0x00000008
-#define AOFF_mm_rss	0x00000098
+#define AOFF_mm_rss	0x000000c0
 #define ASIZ_mm_rss	0x00000008
-#define AOFF_mm_total_vm	0x000000a0
+#define AOFF_mm_total_vm	0x000000c8
 #define ASIZ_mm_total_vm	0x00000008
-#define AOFF_mm_locked_vm	0x000000a8
+#define AOFF_mm_locked_vm	0x000000d0
 #define ASIZ_mm_locked_vm	0x00000008
-#define AOFF_mm_def_flags	0x000000b0
+#define AOFF_mm_def_flags	0x000000d8
 #define ASIZ_mm_def_flags	0x00000008
-#define AOFF_mm_cpu_vm_mask	0x000000b8
+#define AOFF_mm_cpu_vm_mask	0x000000e0
 #define ASIZ_mm_cpu_vm_mask	0x00000008
-#define AOFF_mm_swap_cnt	0x000000c0
+#define AOFF_mm_swap_cnt	0x000000e8
 #define ASIZ_mm_swap_cnt	0x00000008
-#define AOFF_mm_swap_address	0x000000c8
+#define AOFF_mm_swap_address	0x000000f0
 #define ASIZ_mm_swap_address	0x00000008
-#define AOFF_mm_segments	0x000000d0
+#define AOFF_mm_segments	0x000000f8
 #define ASIZ_mm_segments	0x00000008
-#define ASIZ_mm	0x000000d8
+#define ASIZ_mm	0x00000100
 #define AOFF_thread_ksp	0x00000000
 #define ASIZ_thread_ksp	0x00000008
 #define AOFF_thread_wstate	0x00000008
@@ -363,112 +363,112 @@
 #define AOFF_task_tarray_ptr	0x000000e8
 #define ASIZ_task_tarray_ptr	0x00000008
 #define AOFF_task_wait_chldexit	0x000000f0
-#define ASIZ_task_wait_chldexit	0x00000008
-#define AOFF_task_vfork_sem	0x000000f8
+#define ASIZ_task_wait_chldexit	0x00000028
+#define AOFF_task_vfork_sem	0x00000118
 #define ASIZ_task_vfork_sem	0x00000008
-#define AOFF_task_policy	0x00000100
+#define AOFF_task_policy	0x00000120
 #define ASIZ_task_policy	0x00000008
-#define AOFF_task_rt_priority	0x00000108
+#define AOFF_task_rt_priority	0x00000128
 #define ASIZ_task_rt_priority	0x00000008
-#define AOFF_task_it_real_value	0x00000110
+#define AOFF_task_it_real_value	0x00000130
 #define ASIZ_task_it_real_value	0x00000008
-#define AOFF_task_it_prof_value	0x00000118
+#define AOFF_task_it_prof_value	0x00000138
 #define ASIZ_task_it_prof_value	0x00000008
-#define AOFF_task_it_virt_value	0x00000120
+#define AOFF_task_it_virt_value	0x00000140
 #define ASIZ_task_it_virt_value	0x00000008
-#define AOFF_task_it_real_incr	0x00000128
+#define AOFF_task_it_real_incr	0x00000148
 #define ASIZ_task_it_real_incr	0x00000008
-#define AOFF_task_it_prof_incr	0x00000130
+#define AOFF_task_it_prof_incr	0x00000150
 #define ASIZ_task_it_prof_incr	0x00000008
-#define AOFF_task_it_virt_incr	0x00000138
+#define AOFF_task_it_virt_incr	0x00000158
 #define ASIZ_task_it_virt_incr	0x00000008
-#define AOFF_task_real_timer	0x00000140
+#define AOFF_task_real_timer	0x00000160
 #define ASIZ_task_real_timer	0x00000028
-#define AOFF_task_times	0x00000168
+#define AOFF_task_times	0x00000188
 #define ASIZ_task_times	0x00000020
-#define AOFF_task_start_time	0x00000188
+#define AOFF_task_start_time	0x000001a8
 #define ASIZ_task_start_time	0x00000008
-#define AOFF_task_per_cpu_utime	0x00000190
+#define AOFF_task_per_cpu_utime	0x000001b0
 #define ASIZ_task_per_cpu_utime	0x00000100
-#define AOFF_task_min_flt	0x00000390
+#define AOFF_task_min_flt	0x000003b0
 #define ASIZ_task_min_flt	0x00000008
-#define AOFF_task_maj_flt	0x00000398
+#define AOFF_task_maj_flt	0x000003b8
 #define ASIZ_task_maj_flt	0x00000008
-#define AOFF_task_nswap	0x000003a0
+#define AOFF_task_nswap	0x000003c0
 #define ASIZ_task_nswap	0x00000008
-#define AOFF_task_cmin_flt	0x000003a8
+#define AOFF_task_cmin_flt	0x000003c8
 #define ASIZ_task_cmin_flt	0x00000008
-#define AOFF_task_cmaj_flt	0x000003b0
+#define AOFF_task_cmaj_flt	0x000003d0
 #define ASIZ_task_cmaj_flt	0x00000008
-#define AOFF_task_cnswap	0x000003b8
+#define AOFF_task_cnswap	0x000003d8
 #define ASIZ_task_cnswap	0x00000008
-#define AOFF_task_uid	0x000003c4
+#define AOFF_task_uid	0x000003e4
 #define ASIZ_task_uid	0x00000004
-#define AOFF_task_euid	0x000003c8
+#define AOFF_task_euid	0x000003e8
 #define ASIZ_task_euid	0x00000004
-#define AOFF_task_suid	0x000003cc
+#define AOFF_task_suid	0x000003ec
 #define ASIZ_task_suid	0x00000004
-#define AOFF_task_fsuid	0x000003d0
+#define AOFF_task_fsuid	0x000003f0
 #define ASIZ_task_fsuid	0x00000004
-#define AOFF_task_gid	0x000003d4
+#define AOFF_task_gid	0x000003f4
 #define ASIZ_task_gid	0x00000004
-#define AOFF_task_egid	0x000003d8
+#define AOFF_task_egid	0x000003f8
 #define ASIZ_task_egid	0x00000004
-#define AOFF_task_sgid	0x000003dc
+#define AOFF_task_sgid	0x000003fc
 #define ASIZ_task_sgid	0x00000004
-#define AOFF_task_fsgid	0x000003e0
+#define AOFF_task_fsgid	0x00000400
 #define ASIZ_task_fsgid	0x00000004
-#define AOFF_task_ngroups	0x000003e4
+#define AOFF_task_ngroups	0x00000404
 #define ASIZ_task_ngroups	0x00000004
-#define AOFF_task_groups	0x000003e8
+#define AOFF_task_groups	0x00000408
 #define ASIZ_task_groups	0x00000080
-#define AOFF_task_cap_effective	0x00000468
+#define AOFF_task_cap_effective	0x00000488
 #define ASIZ_task_cap_effective	0x00000004
-#define AOFF_task_cap_inheritable	0x0000046c
+#define AOFF_task_cap_inheritable	0x0000048c
 #define ASIZ_task_cap_inheritable	0x00000004
-#define AOFF_task_cap_permitted	0x00000470
+#define AOFF_task_cap_permitted	0x00000490
 #define ASIZ_task_cap_permitted	0x00000004
-#define AOFF_task_user	0x00000478
+#define AOFF_task_user	0x00000498
 #define ASIZ_task_user	0x00000008
-#define AOFF_task_rlim	0x00000480
+#define AOFF_task_rlim	0x000004a0
 #define ASIZ_task_rlim	0x000000a0
-#define AOFF_task_used_math	0x00000520
+#define AOFF_task_used_math	0x00000540
 #define ASIZ_task_used_math	0x00000002
-#define AOFF_task_comm	0x00000522
+#define AOFF_task_comm	0x00000542
 #define ASIZ_task_comm	0x00000010
-#define AOFF_task_link_count	0x00000534
+#define AOFF_task_link_count	0x00000554
 #define ASIZ_task_link_count	0x00000004
-#define AOFF_task_tty	0x00000538
+#define AOFF_task_tty	0x00000558
 #define ASIZ_task_tty	0x00000008
-#define AOFF_task_semundo	0x00000540
+#define AOFF_task_semundo	0x00000560
 #define ASIZ_task_semundo	0x00000008
-#define AOFF_task_semsleeping	0x00000548
+#define AOFF_task_semsleeping	0x00000568
 #define ASIZ_task_semsleeping	0x00000008
-#define AOFF_task_tss	0x00000550
+#define AOFF_task_tss	0x00000570
 #define ASIZ_task_tss	0x00000470
-#define AOFF_task_fs	0x000009c0
+#define AOFF_task_fs	0x000009e0
 #define ASIZ_task_fs	0x00000008
-#define AOFF_task_files	0x000009c8
+#define AOFF_task_files	0x000009e8
 #define ASIZ_task_files	0x00000008
-#define AOFF_task_mm	0x000009d0
+#define AOFF_task_mm	0x000009f0
 #define ASIZ_task_mm	0x00000008
-#define AOFF_task_sigmask_lock	0x000009d8
+#define AOFF_task_sigmask_lock	0x000009f8
 #define ASIZ_task_sigmask_lock	0x00000001
-#define AOFF_task_sig	0x000009e0
+#define AOFF_task_sig	0x00000a00
 #define ASIZ_task_sig	0x00000008
-#define AOFF_task_signal	0x000009e8
+#define AOFF_task_signal	0x00000a08
 #define ASIZ_task_signal	0x00000008
-#define AOFF_task_blocked	0x000009f0
+#define AOFF_task_blocked	0x00000a10
 #define ASIZ_task_blocked	0x00000008
-#define AOFF_task_sigqueue	0x000009f8
+#define AOFF_task_sigqueue	0x00000a18
 #define ASIZ_task_sigqueue	0x00000008
-#define AOFF_task_sigqueue_tail	0x00000a00
+#define AOFF_task_sigqueue_tail	0x00000a20
 #define ASIZ_task_sigqueue_tail	0x00000008
-#define AOFF_task_sas_ss_sp	0x00000a08
+#define AOFF_task_sas_ss_sp	0x00000a28
 #define ASIZ_task_sas_ss_sp	0x00000008
-#define AOFF_task_sas_ss_size	0x00000a10
+#define AOFF_task_sas_ss_size	0x00000a30
 #define ASIZ_task_sas_ss_size	0x00000008
-#define ASIZ_task	0x00000a20
+#define ASIZ_task	0x00000a40
 #define AOFF_mm_mmap	0x00000000
 #define ASIZ_mm_mmap	0x00000008
 #define AOFF_mm_mmap_avl	0x00000008
@@ -482,48 +482,48 @@
 #define AOFF_mm_map_count	0x00000024
 #define ASIZ_mm_map_count	0x00000004
 #define AOFF_mm_mmap_sem	0x00000028
-#define ASIZ_mm_mmap_sem	0x00000010
-#define AOFF_mm_context	0x00000038
+#define ASIZ_mm_mmap_sem	0x00000038
+#define AOFF_mm_context	0x00000060
 #define ASIZ_mm_context	0x00000008
-#define AOFF_mm_start_code	0x00000040
+#define AOFF_mm_start_code	0x00000068
 #define ASIZ_mm_start_code	0x00000008
-#define AOFF_mm_end_code	0x00000048
+#define AOFF_mm_end_code	0x00000070
 #define ASIZ_mm_end_code	0x00000008
-#define AOFF_mm_start_data	0x00000050
+#define AOFF_mm_start_data	0x00000078
 #define ASIZ_mm_start_data	0x00000008
-#define AOFF_mm_end_data	0x00000058
+#define AOFF_mm_end_data	0x00000080
 #define ASIZ_mm_end_data	0x00000008
-#define AOFF_mm_start_brk	0x00000060
+#define AOFF_mm_start_brk	0x00000088
 #define ASIZ_mm_start_brk	0x00000008
-#define AOFF_mm_brk	0x00000068
+#define AOFF_mm_brk	0x00000090
 #define ASIZ_mm_brk	0x00000008
-#define AOFF_mm_start_stack	0x00000070
+#define AOFF_mm_start_stack	0x00000098
 #define ASIZ_mm_start_stack	0x00000008
-#define AOFF_mm_arg_start	0x00000078
+#define AOFF_mm_arg_start	0x000000a0
 #define ASIZ_mm_arg_start	0x00000008
-#define AOFF_mm_arg_end	0x00000080
+#define AOFF_mm_arg_end	0x000000a8
 #define ASIZ_mm_arg_end	0x00000008
-#define AOFF_mm_env_start	0x00000088
+#define AOFF_mm_env_start	0x000000b0
 #define ASIZ_mm_env_start	0x00000008
-#define AOFF_mm_env_end	0x00000090
+#define AOFF_mm_env_end	0x000000b8
 #define ASIZ_mm_env_end	0x00000008
-#define AOFF_mm_rss	0x00000098
+#define AOFF_mm_rss	0x000000c0
 #define ASIZ_mm_rss	0x00000008
-#define AOFF_mm_total_vm	0x000000a0
+#define AOFF_mm_total_vm	0x000000c8
 #define ASIZ_mm_total_vm	0x00000008
-#define AOFF_mm_locked_vm	0x000000a8
+#define AOFF_mm_locked_vm	0x000000d0
 #define ASIZ_mm_locked_vm	0x00000008
-#define AOFF_mm_def_flags	0x000000b0
+#define AOFF_mm_def_flags	0x000000d8
 #define ASIZ_mm_def_flags	0x00000008
-#define AOFF_mm_cpu_vm_mask	0x000000b8
+#define AOFF_mm_cpu_vm_mask	0x000000e0
 #define ASIZ_mm_cpu_vm_mask	0x00000008
-#define AOFF_mm_swap_cnt	0x000000c0
+#define AOFF_mm_swap_cnt	0x000000e8
 #define ASIZ_mm_swap_cnt	0x00000008
-#define AOFF_mm_swap_address	0x000000c8
+#define AOFF_mm_swap_address	0x000000f0
 #define ASIZ_mm_swap_address	0x00000008
-#define AOFF_mm_segments	0x000000d0
+#define AOFF_mm_segments	0x000000f8
 #define ASIZ_mm_segments	0x00000008
-#define ASIZ_mm	0x000000d8
+#define ASIZ_mm	0x00000100
 #define AOFF_thread_ksp	0x00000000
 #define ASIZ_thread_ksp	0x00000008
 #define AOFF_thread_wstate	0x00000008
@@ -647,112 +647,112 @@
 #define AOFF_task_tarray_ptr	0x000000e8
 #define ASIZ_task_tarray_ptr	0x00000008
 #define AOFF_task_wait_chldexit	0x000000f0
-#define ASIZ_task_wait_chldexit	0x00000008
-#define AOFF_task_vfork_sem	0x000000f8
+#define ASIZ_task_wait_chldexit	0x00000030
+#define AOFF_task_vfork_sem	0x00000120
 #define ASIZ_task_vfork_sem	0x00000008
-#define AOFF_task_policy	0x00000100
+#define AOFF_task_policy	0x00000128
 #define ASIZ_task_policy	0x00000008
-#define AOFF_task_rt_priority	0x00000108
+#define AOFF_task_rt_priority	0x00000130
 #define ASIZ_task_rt_priority	0x00000008
-#define AOFF_task_it_real_value	0x00000110
+#define AOFF_task_it_real_value	0x00000138
 #define ASIZ_task_it_real_value	0x00000008
-#define AOFF_task_it_prof_value	0x00000118
+#define AOFF_task_it_prof_value	0x00000140
 #define ASIZ_task_it_prof_value	0x00000008
-#define AOFF_task_it_virt_value	0x00000120
+#define AOFF_task_it_virt_value	0x00000148
 #define ASIZ_task_it_virt_value	0x00000008
-#define AOFF_task_it_real_incr	0x00000128
+#define AOFF_task_it_real_incr	0x00000150
 #define ASIZ_task_it_real_incr	0x00000008
-#define AOFF_task_it_prof_incr	0x00000130
+#define AOFF_task_it_prof_incr	0x00000158
 #define ASIZ_task_it_prof_incr	0x00000008
-#define AOFF_task_it_virt_incr	0x00000138
+#define AOFF_task_it_virt_incr	0x00000160
 #define ASIZ_task_it_virt_incr	0x00000008
-#define AOFF_task_real_timer	0x00000140
+#define AOFF_task_real_timer	0x00000168
 #define ASIZ_task_real_timer	0x00000028
-#define AOFF_task_times	0x00000168
+#define AOFF_task_times	0x00000190
 #define ASIZ_task_times	0x00000020
-#define AOFF_task_start_time	0x00000188
+#define AOFF_task_start_time	0x000001b0
 #define ASIZ_task_start_time	0x00000008
-#define AOFF_task_per_cpu_utime	0x00000190
+#define AOFF_task_per_cpu_utime	0x000001b8
 #define ASIZ_task_per_cpu_utime	0x00000100
-#define AOFF_task_min_flt	0x00000390
+#define AOFF_task_min_flt	0x000003b8
 #define ASIZ_task_min_flt	0x00000008
-#define AOFF_task_maj_flt	0x00000398
+#define AOFF_task_maj_flt	0x000003c0
 #define ASIZ_task_maj_flt	0x00000008
-#define AOFF_task_nswap	0x000003a0
+#define AOFF_task_nswap	0x000003c8
 #define ASIZ_task_nswap	0x00000008
-#define AOFF_task_cmin_flt	0x000003a8
+#define AOFF_task_cmin_flt	0x000003d0
 #define ASIZ_task_cmin_flt	0x00000008
-#define AOFF_task_cmaj_flt	0x000003b0
+#define AOFF_task_cmaj_flt	0x000003d8
 #define ASIZ_task_cmaj_flt	0x00000008
-#define AOFF_task_cnswap	0x000003b8
+#define AOFF_task_cnswap	0x000003e0
 #define ASIZ_task_cnswap	0x00000008
-#define AOFF_task_uid	0x000003c4
+#define AOFF_task_uid	0x000003ec
 #define ASIZ_task_uid	0x00000004
-#define AOFF_task_euid	0x000003c8
+#define AOFF_task_euid	0x000003f0
 #define ASIZ_task_euid	0x00000004
-#define AOFF_task_suid	0x000003cc
+#define AOFF_task_suid	0x000003f4
 #define ASIZ_task_suid	0x00000004
-#define AOFF_task_fsuid	0x000003d0
+#define AOFF_task_fsuid	0x000003f8
 #define ASIZ_task_fsuid	0x00000004
-#define AOFF_task_gid	0x000003d4
+#define AOFF_task_gid	0x000003fc
 #define ASIZ_task_gid	0x00000004
-#define AOFF_task_egid	0x000003d8
+#define AOFF_task_egid	0x00000400
 #define ASIZ_task_egid	0x00000004
-#define AOFF_task_sgid	0x000003dc
+#define AOFF_task_sgid	0x00000404
 #define ASIZ_task_sgid	0x00000004
-#define AOFF_task_fsgid	0x000003e0
+#define AOFF_task_fsgid	0x00000408
 #define ASIZ_task_fsgid	0x00000004
-#define AOFF_task_ngroups	0x000003e4
+#define AOFF_task_ngroups	0x0000040c
 #define ASIZ_task_ngroups	0x00000004
-#define AOFF_task_groups	0x000003e8
+#define AOFF_task_groups	0x00000410
 #define ASIZ_task_groups	0x00000080
-#define AOFF_task_cap_effective	0x00000468
+#define AOFF_task_cap_effective	0x00000490
 #define ASIZ_task_cap_effective	0x00000004
-#define AOFF_task_cap_inheritable	0x0000046c
+#define AOFF_task_cap_inheritable	0x00000494
 #define ASIZ_task_cap_inheritable	0x00000004
-#define AOFF_task_cap_permitted	0x00000470
+#define AOFF_task_cap_permitted	0x00000498
 #define ASIZ_task_cap_permitted	0x00000004
-#define AOFF_task_user	0x00000478
+#define AOFF_task_user	0x000004a0
 #define ASIZ_task_user	0x00000008
-#define AOFF_task_rlim	0x00000480
+#define AOFF_task_rlim	0x000004a8
 #define ASIZ_task_rlim	0x000000a0
-#define AOFF_task_used_math	0x00000520
+#define AOFF_task_used_math	0x00000548
 #define ASIZ_task_used_math	0x00000002
-#define AOFF_task_comm	0x00000522
+#define AOFF_task_comm	0x0000054a
 #define ASIZ_task_comm	0x00000010
-#define AOFF_task_link_count	0x00000534
+#define AOFF_task_link_count	0x0000055c
 #define ASIZ_task_link_count	0x00000004
-#define AOFF_task_tty	0x00000538
+#define AOFF_task_tty	0x00000560
 #define ASIZ_task_tty	0x00000008
-#define AOFF_task_semundo	0x00000540
+#define AOFF_task_semundo	0x00000568
 #define ASIZ_task_semundo	0x00000008
-#define AOFF_task_semsleeping	0x00000548
+#define AOFF_task_semsleeping	0x00000570
 #define ASIZ_task_semsleeping	0x00000008
-#define AOFF_task_tss	0x00000550
+#define AOFF_task_tss	0x00000580
 #define ASIZ_task_tss	0x00000470
-#define AOFF_task_fs	0x000009c0
+#define AOFF_task_fs	0x000009f0
 #define ASIZ_task_fs	0x00000008
-#define AOFF_task_files	0x000009c8
+#define AOFF_task_files	0x000009f8
 #define ASIZ_task_files	0x00000008
-#define AOFF_task_mm	0x000009d0
+#define AOFF_task_mm	0x00000a00
 #define ASIZ_task_mm	0x00000008
-#define AOFF_task_sigmask_lock	0x000009d8
+#define AOFF_task_sigmask_lock	0x00000a08
 #define ASIZ_task_sigmask_lock	0x0000000c
-#define AOFF_task_sig	0x000009e8
+#define AOFF_task_sig	0x00000a18
 #define ASIZ_task_sig	0x00000008
-#define AOFF_task_signal	0x000009f0
+#define AOFF_task_signal	0x00000a20
 #define ASIZ_task_signal	0x00000008
-#define AOFF_task_blocked	0x000009f8
+#define AOFF_task_blocked	0x00000a28
 #define ASIZ_task_blocked	0x00000008
-#define AOFF_task_sigqueue	0x00000a00
+#define AOFF_task_sigqueue	0x00000a30
 #define ASIZ_task_sigqueue	0x00000008
-#define AOFF_task_sigqueue_tail	0x00000a08
+#define AOFF_task_sigqueue_tail	0x00000a38
 #define ASIZ_task_sigqueue_tail	0x00000008
-#define AOFF_task_sas_ss_sp	0x00000a10
+#define AOFF_task_sas_ss_sp	0x00000a40
 #define ASIZ_task_sas_ss_sp	0x00000008
-#define AOFF_task_sas_ss_size	0x00000a18
+#define AOFF_task_sas_ss_size	0x00000a48
 #define ASIZ_task_sas_ss_size	0x00000008
-#define ASIZ_task	0x00000a20
+#define ASIZ_task	0x00000a50
 #define AOFF_mm_mmap	0x00000000
 #define ASIZ_mm_mmap	0x00000008
 #define AOFF_mm_mmap_avl	0x00000008
@@ -766,48 +766,48 @@
 #define AOFF_mm_map_count	0x00000024
 #define ASIZ_mm_map_count	0x00000004
 #define AOFF_mm_mmap_sem	0x00000028
-#define ASIZ_mm_mmap_sem	0x00000010
-#define AOFF_mm_context	0x00000038
+#define ASIZ_mm_mmap_sem	0x00000040
+#define AOFF_mm_context	0x00000068
 #define ASIZ_mm_context	0x00000008
-#define AOFF_mm_start_code	0x00000040
+#define AOFF_mm_start_code	0x00000070
 #define ASIZ_mm_start_code	0x00000008
-#define AOFF_mm_end_code	0x00000048
+#define AOFF_mm_end_code	0x00000078
 #define ASIZ_mm_end_code	0x00000008
-#define AOFF_mm_start_data	0x00000050
+#define AOFF_mm_start_data	0x00000080
 #define ASIZ_mm_start_data	0x00000008
-#define AOFF_mm_end_data	0x00000058
+#define AOFF_mm_end_data	0x00000088
 #define ASIZ_mm_end_data	0x00000008
-#define AOFF_mm_start_brk	0x00000060
+#define AOFF_mm_start_brk	0x00000090
 #define ASIZ_mm_start_brk	0x00000008
-#define AOFF_mm_brk	0x00000068
+#define AOFF_mm_brk	0x00000098
 #define ASIZ_mm_brk	0x00000008
-#define AOFF_mm_start_stack	0x00000070
+#define AOFF_mm_start_stack	0x000000a0
 #define ASIZ_mm_start_stack	0x00000008
-#define AOFF_mm_arg_start	0x00000078
+#define AOFF_mm_arg_start	0x000000a8
 #define ASIZ_mm_arg_start	0x00000008
-#define AOFF_mm_arg_end	0x00000080
+#define AOFF_mm_arg_end	0x000000b0
 #define ASIZ_mm_arg_end	0x00000008
-#define AOFF_mm_env_start	0x00000088
+#define AOFF_mm_env_start	0x000000b8
 #define ASIZ_mm_env_start	0x00000008
-#define AOFF_mm_env_end	0x00000090
+#define AOFF_mm_env_end	0x000000c0
 #define ASIZ_mm_env_end	0x00000008
-#define AOFF_mm_rss	0x00000098
+#define AOFF_mm_rss	0x000000c8
 #define ASIZ_mm_rss	0x00000008
-#define AOFF_mm_total_vm	0x000000a0
+#define AOFF_mm_total_vm	0x000000d0
 #define ASIZ_mm_total_vm	0x00000008
-#define AOFF_mm_locked_vm	0x000000a8
+#define AOFF_mm_locked_vm	0x000000d8
 #define ASIZ_mm_locked_vm	0x00000008
-#define AOFF_mm_def_flags	0x000000b0
+#define AOFF_mm_def_flags	0x000000e0
 #define ASIZ_mm_def_flags	0x00000008
-#define AOFF_mm_cpu_vm_mask	0x000000b8
+#define AOFF_mm_cpu_vm_mask	0x000000e8
 #define ASIZ_mm_cpu_vm_mask	0x00000008
-#define AOFF_mm_swap_cnt	0x000000c0
+#define AOFF_mm_swap_cnt	0x000000f0
 #define ASIZ_mm_swap_cnt	0x00000008
-#define AOFF_mm_swap_address	0x000000c8
+#define AOFF_mm_swap_address	0x000000f8
 #define ASIZ_mm_swap_address	0x00000008
-#define AOFF_mm_segments	0x000000d0
+#define AOFF_mm_segments	0x00000100
 #define ASIZ_mm_segments	0x00000008
-#define ASIZ_mm	0x000000d8
+#define ASIZ_mm	0x00000108
 #define AOFF_thread_ksp	0x00000000
 #define ASIZ_thread_ksp	0x00000008
 #define AOFF_thread_wstate	0x00000008
diff -u --recursive --new-file v2.3.0/linux/include/asm-sparc64/audioio.h linux/include/asm-sparc64/audioio.h
--- v2.3.0/linux/include/asm-sparc64/audioio.h	Wed Nov 18 09:06:05 1998
+++ linux/include/asm-sparc64/audioio.h	Wed May 12 08:41:15 1999
@@ -275,7 +275,7 @@
         struct linux_sbus_device *dev;
 
 	/* Processes blocked on open() sit here. */
-	struct wait_queue *open_wait;
+	wait_queue_head_t open_wait;
 
 	/* Task queue for this driver's bottom half. */
 	struct tq_struct tqueue;
@@ -288,7 +288,7 @@
 	size_t *output_sizes, output_size, output_buffer_size;
 	int num_output_buffers, output_front, output_rear, output_offset;
 	int output_count, output_active, playing_count, output_eof;
-	struct wait_queue *output_write_wait, *output_drain_wait;
+	wait_queue_head_t output_write_wait, output_drain_wait;
         char *output_notify;
 
         /* Support for a circular queue of input buffers. */
@@ -296,7 +296,7 @@
 	size_t *input_sizes, input_size, input_buffer_size;
         int num_input_buffers, input_front, input_rear, input_offset;
         int input_count, input_active, recording_count;
-        struct wait_queue *input_read_wait;
+        wait_queue_head_t input_read_wait;
 
         /* Hack to make it look like we support variable size buffers. */
         int buffer_size;
diff -u --recursive --new-file v2.3.0/linux/include/asm-sparc64/hdreg.h linux/include/asm-sparc64/hdreg.h
--- v2.3.0/linux/include/asm-sparc64/hdreg.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sparc64/hdreg.h	Thu May 13 11:00:09 1999
@@ -0,0 +1,13 @@
+/* $Id: hdreg.h,v 1.9 1998/05/08 21:05:28 davem Exp $
+ * hdreg.h: Ultra/PCI specific IDE glue.
+ *
+ * Copyright (C) 1997  David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1998  Eddie C. Dost   (ecd@skynet.be)
+ */
+
+#ifndef __SPARC64_HDREG_H
+#define __SPARC64_HDREG_H
+
+typedef unsigned long ide_ioreg_t;
+
+#endif /* __SPARC64_HDREG_H */
diff -u --recursive --new-file v2.3.0/linux/include/asm-sparc64/ide.h linux/include/asm-sparc64/ide.h
--- v2.3.0/linux/include/asm-sparc64/ide.h	Thu Apr 22 19:24:52 1999
+++ linux/include/asm-sparc64/ide.h	Thu May 13 11:00:09 1999
@@ -12,8 +12,6 @@
 
 #include <asm/pgtable.h>
 
-typedef unsigned long ide_ioreg_t;
-
 #undef  MAX_HWIFS
 #define MAX_HWIFS	2
 
@@ -29,21 +27,42 @@
 	return 0;
 }
 
-static __inline__ void ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base, int *irq)
+static __inline__ void ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq)
 {
+	ide_ioreg_t reg =  data_port;
 	int i;
 
-	/* These are simply offsets from base. */
-	for (i = 0; i < 8; i++)
-		*p++ = base++;
-	/* PCI code needs to figure out these. */
-	for ( ; i < 10; i++)
-		*p++ = 0;
-	/* PCI code needs to figure out this. */
+	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+		hw->io_ports[i] = reg;
+		reg += 1;
+	}
+	if (ctrl_port) {
+		hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
+	} else {
+		hw->io_ports[IDE_CONTROL_OFFSET] = 0;
+	}
 	if (irq != NULL)
 		*irq = 0;
 }
 
+/*
+ * This registers the standard ports for this architecture with the IDE
+ * driver.
+ */
+static __inline__ void ide_init_default_hwifs(void)
+{
+#ifdef __DO_I_NEED_THIS
+	hw_regs_t hw;
+	int index;
+
+	for (index = 0; index < MAX_HWIFS; index++) {
+		ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, 0);
+		hw.irq = ide_default_irq(ide_default_io_base(index));
+		ide_register_hw(&hw, NULL);
+	}
+#endif /* __DO_I_NEED_THIS */
+}
+
 typedef union {
 	unsigned int		all	: 8;	/* all of the bits together */
 	struct {
@@ -92,11 +111,6 @@
 #undef  HD_DATA
 #define HD_DATA ((ide_ioreg_t)0)
 
-static __inline__ int ide_ack_intr(ide_ioreg_t status_port, ide_ioreg_t irq_port)
-{
-	return 1;
-}
-
 /* From m68k code... */
 
 #ifdef insl
@@ -255,13 +269,12 @@
 	}
 }
 
-static __inline__ void ide_release_lock (int *ide_lock)
-{
-}
-
-static __inline__ void ide_get_lock (int *ide_lock, void (*handler)(int, void *, struct pt_regs *), void *data)
-{
-}
+/*
+ * The following are not needed for the non-m68k ports
+ */
+#define ide_ack_intr(hwif)		(1)
+#define ide_release_lock(lock)		do {} while (0)
+#define ide_get_lock(lock, hdlr, data)	do {} while (0)
 
 #endif /* __KERNEL__ */
 
diff -u --recursive --new-file v2.3.0/linux/include/asm-sparc64/io.h linux/include/asm-sparc64/io.h
--- v2.3.0/linux/include/asm-sparc64/io.h	Sun Oct  4 10:22:44 1998
+++ linux/include/asm-sparc64/io.h	Thu May 13 11:00:09 1999
@@ -226,4 +226,10 @@
 extern void sparc_free_io (void *va, int sz);
 extern void *sparc_dvma_malloc (int sz, char *name, __u32 *dvma_addr);
 
+/* Nothing to do */
+
+#define dma_cache_inv(_start,_size)		do { } while (0)
+#define dma_cache_wback(_start,_size)		do { } while (0)
+#define dma_cache_wback_inv(_start,_size)	do { } while (0)
+
 #endif /* !(__SPARC64_IO_H) */
diff -u --recursive --new-file v2.3.0/linux/include/asm-sparc64/sab82532.h linux/include/asm-sparc64/sab82532.h
--- v2.3.0/linux/include/asm-sparc64/sab82532.h	Tue Oct 27 09:52:21 1998
+++ linux/include/asm-sparc64/sab82532.h	Wed May 12 08:41:15 1999
@@ -1,4 +1,4 @@
-/* $Id: sab82532.h,v 1.4 1998/10/25 23:04:29 ecd Exp $
+/* $Id: sab82532.h,v 1.5 1999/05/12 11:21:22 davem Exp $
  * sab82532.h: Register Definitions for the Siemens SAB82532 DUSCC
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -173,9 +173,9 @@
 	struct async_icount		 icount;
 	struct termios			 normal_termios;
 	struct termios			 callout_termios;
-	struct wait_queue		*open_wait;
-	struct wait_queue		*close_wait;
-	struct wait_queue		*delta_msr_wait;
+	wait_queue_head_t		 open_wait;
+	wait_queue_head_t		 close_wait;
+	wait_queue_head_t		 delta_msr_wait;
 	struct sab82532			*next;
 	struct sab82532			*prev;
 };
diff -u --recursive --new-file v2.3.0/linux/include/asm-sparc64/semaphore.h linux/include/asm-sparc64/semaphore.h
--- v2.3.0/linux/include/asm-sparc64/semaphore.h	Wed Mar 10 16:53:38 1999
+++ linux/include/asm-sparc64/semaphore.h	Wed May 12 08:41:15 1999
@@ -10,21 +10,62 @@
 struct semaphore {
 	atomic_t count;
 	atomic_t waking;
-	struct wait_queue * wait;
+	wait_queue_head_t wait;
+#if WAITQUEUE_DEBUG
+	long __magic;
+#endif
 };
 
-#define MUTEX ((struct semaphore) { ATOMIC_INIT(1), ATOMIC_INIT(0), NULL })
-#define MUTEX_LOCKED ((struct semaphore) { ATOMIC_INIT(0), ATOMIC_INIT(0), NULL })
+#if WAITQUEUE_DEBUG
+# define __SEM_DEBUG_INIT(name) \
+		, (long)&(name).__magic
+#else
+# define __SEM_DEBUG_INIT(name)
+#endif
+
+#define __SEMAPHORE_INITIALIZER(name,count) \
+{ ATOMIC_INIT(count), ATOMIC_INIT(0), __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
+	__SEM_DEBUG_INIT(name) }
+
+#define __MUTEX_INITIALIZER(name) \
+	__SEMAPHORE_INITIALIZER(name,1)
+
+#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+	struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+
+#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
+#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
+
+extern inline void sema_init (struct semaphore *sem, int val)
+{
+	atomic_set(&sem->count, val);
+	atomic_set(&sem->waking, 0);
+	init_waitqueue_head(&sem->wait);
+#if WAITQUEUE_DEBUG
+	sem->__magic = (long)&sem->__magic;
+#endif
+}
+
+static inline void init_MUTEX (struct semaphore *sem)
+{
+	sema_init(sem, 1);
+}
+
+static inline void init_MUTEX_LOCKED (struct semaphore *sem)
+{
+	sema_init(sem, 0);
+}
 
 extern void __down(struct semaphore * sem);
 extern int  __down_interruptible(struct semaphore * sem);
 extern int  __down_trylock(struct semaphore * sem);
 extern void __up(struct semaphore * sem);
 
-#define sema_init(sem, val)	atomic_set(&((sem)->count), val)
-
 extern __inline__ void down(struct semaphore * sem)
 {
+#if WAITQUEUE_DEBUG
+	CHECK_MAGIC(sem->__magic);
+#endif
         __asm__ __volatile__("
 	1:	lduw	[%0], %%g5
 		sub	%%g5, 1, %%g7
@@ -56,6 +97,9 @@
 {
 	int ret = 0;
 	
+#if WAITQUEUE_DEBUG
+	CHECK_MAGIC(sem->__magic);
+#endif
         __asm__ __volatile__("
 	1:	lduw	[%2], %%g5
 		sub	%%g5, 1, %%g7
@@ -89,6 +133,9 @@
 extern inline int down_trylock(struct semaphore *sem)
 {
 	int ret = 0;
+#if WAITQUEUE_DEBUG
+	CHECK_MAGIC(sem->__magic);
+#endif
         __asm__ __volatile__("
 	1:	lduw	[%2], %%g5
 		sub	%%g5, 1, %%g7
@@ -121,6 +168,9 @@
 
 extern __inline__ void up(struct semaphore * sem)
 {
+#if WAITQUEUE_DEBUG
+	CHECK_MAGIC(sem->__magic);
+#endif
 	__asm__ __volatile__("
 		membar	#StoreLoad | #LoadLoad
 	1:	lduw	[%0], %%g5
diff -u --recursive --new-file v2.3.0/linux/include/asm-sparc64/spinlock.h linux/include/asm-sparc64/spinlock.h
--- v2.3.0/linux/include/asm-sparc64/spinlock.h	Wed Mar 10 16:53:38 1999
+++ linux/include/asm-sparc64/spinlock.h	Wed May 12 08:41:15 1999
@@ -186,11 +186,11 @@
 	unsigned char lock;
 	unsigned int owner_pc, owner_cpu;
 } spinlock_t;
-#define SPIN_LOCK_UNLOCKED (spinlock_t) { 0, 0, NO_PROC_ID }
+#define SPIN_LOCK_UNLOCKED (spinlock_t) { 0, 0, 0xff }
 #define spin_lock_init(__lock)	\
 do {	(__lock)->lock = 0; \
 	(__lock)->owner_pc = 0; \
-	(__lock)->owner_cpu = NO_PROC_ID; \
+	(__lock)->owner_cpu = 0xff; \
 } while(0)
 #define spin_is_locked(__lock)	(*((volatile unsigned char *)(&((__lock)->lock))) != 0)
 #define spin_unlock_wait(__lock)	\
@@ -322,7 +322,7 @@
 	unsigned int writer_pc, writer_cpu;
 	unsigned int reader_pc[4];
 } rwlock_t;
-#define RW_LOCK_UNLOCKED	(rwlock_t) { 0, 0, NO_PROC_ID, { 0, 0, 0, 0 } }
+#define RW_LOCK_UNLOCKED	(rwlock_t) { 0, 0, 0xff, { 0, 0, 0, 0 } }
 
 extern void _do_read_lock(rwlock_t *rw, char *str);
 extern void _do_read_unlock(rwlock_t *rw, char *str);
diff -u --recursive --new-file v2.3.0/linux/include/linux/blkdev.h linux/include/linux/blkdev.h
--- v2.3.0/linux/include/linux/blkdev.h	Tue May 11 13:04:02 1999
+++ linux/include/linux/blkdev.h	Thu May 13 14:42:16 1999
@@ -55,7 +55,7 @@
 
 extern struct sec_size * blk_sec[MAX_BLKDEV];
 extern struct blk_dev_struct blk_dev[MAX_BLKDEV];
-extern struct wait_queue * wait_for_request;
+extern wait_queue_head_t wait_for_request;
 extern void resetup_one_dev(struct gendisk *dev, int drive);
 extern void unplug_device(void * data);
 extern void make_request(int major,int rw, struct buffer_head * bh);
diff -u --recursive --new-file v2.3.0/linux/include/linux/busmouse.h linux/include/linux/busmouse.h
--- v2.3.0/linux/include/linux/busmouse.h	Wed Dec 13 22:16:53 1995
+++ linux/include/linux/busmouse.h	Wed May 12 13:27:37 1999
@@ -94,7 +94,7 @@
 	int 		present;
 	int		ready;
 	int		active;
-	struct wait_queue *wait;
+	wait_queue_head_t wait;
 	struct fasync_struct *fasyncptr;
 };
 
diff -u --recursive --new-file v2.3.0/linux/include/linux/coda_psdev.h linux/include/linux/coda_psdev.h
--- v2.3.0/linux/include/linux/coda_psdev.h	Mon Dec 21 14:23:28 1998
+++ linux/include/linux/coda_psdev.h	Wed May 12 08:41:15 1999
@@ -23,7 +23,7 @@
 /* communication pending/processing queues */
 struct venus_comm {
 	u_long		    vc_seq;
-	struct wait_queue  *vc_waitq; /* Venus wait queue */
+	wait_queue_head_t   vc_waitq; /* Venus wait queue */
 	struct list_head    vc_pending;
 	struct list_head    vc_processing;
 	int                 vc_inuse;
@@ -93,7 +93,7 @@
 	u_short	            uc_outSize;
 	u_short	            uc_opcode;  /* copied from data to save lookup */
 	int		    uc_unique;
-	struct wait_queue  *uc_sleep;   /* process' wait queue */
+	wait_queue_head_t   uc_sleep;   /* process' wait queue */
 	unsigned long       uc_posttime;
 };
 
diff -u --recursive --new-file v2.3.0/linux/include/linux/cyclades.h linux/include/linux/cyclades.h
--- v2.3.0/linux/include/linux/cyclades.h	Mon Apr 12 10:09:47 1999
+++ linux/include/linux/cyclades.h	Wed May 12 13:27:37 1999
@@ -570,9 +570,9 @@
 	struct tq_struct	tqueue;
 	struct termios		normal_termios;
 	struct termios		callout_termios;
-	struct wait_queue	*open_wait;
-	struct wait_queue	*close_wait;
-	struct wait_queue	*shutdown_wait;
+	wait_queue_head_t	open_wait;
+	wait_queue_head_t	close_wait;
+	wait_queue_head_t	shutdown_wait;
         struct cyclades_monitor mon;
 	unsigned long		jiffies[3];
 	unsigned long		rflush_count;
diff -u --recursive --new-file v2.3.0/linux/include/linux/epca.h linux/include/linux/epca.h
--- v2.3.0/linux/include/linux/epca.h	Tue May 13 22:41:18 1997
+++ linux/include/linux/epca.h	Wed May 12 13:27:37 1999
@@ -140,8 +140,8 @@
 	struct tty_struct           *tty;
 	struct termios              normal_termios;
 	struct termios              callout_termios;
-	struct wait_queue           *open_wait;
-	struct wait_queue           *close_wait;
+	wait_queue_head_t           open_wait;
+	wait_queue_head_t           close_wait;
 	struct tq_struct            tqueue;
 	volatile struct global_data *mailbox;
 };
diff -u --recursive --new-file v2.3.0/linux/include/linux/ext2_fs.h linux/include/linux/ext2_fs.h
--- v2.3.0/linux/include/linux/ext2_fs.h	Fri Apr 23 21:20:38 1999
+++ linux/include/linux/ext2_fs.h	Tue May 11 14:37:47 1999
@@ -238,7 +238,7 @@
 		} masix1;
 	} osd1;				/* OS dependent 1 */
 	__u32	i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
-	__u32	i_version;	/* File version (for NFS) */
+	__u32	i_generation;	/* File version (for NFS) */
 	__u32	i_file_acl;	/* File ACL */
 	__u32	i_dir_acl;	/* Directory ACL */
 	__u32	i_faddr;	/* Fragment address */
diff -u --recursive --new-file v2.3.0/linux/include/linux/ext2_fs_i.h linux/include/linux/ext2_fs_i.h
--- v2.3.0/linux/include/linux/ext2_fs_i.h	Thu Apr  2 13:39:51 1998
+++ linux/include/linux/ext2_fs_i.h	Tue May 11 14:37:47 1999
@@ -29,7 +29,7 @@
 	__u32	i_file_acl;
 	__u32	i_dir_acl;
 	__u32	i_dtime;
-	__u32	i_version;
+	__u32	not_used_1;	/* FIX: not used/ 2.2 placeholder */
 	__u32	i_block_group;
 	__u32	i_next_alloc_block;
 	__u32	i_next_alloc_goal;
diff -u --recursive --new-file v2.3.0/linux/include/linux/fs.h linux/include/linux/fs.h
--- v2.3.0/linux/include/linux/fs.h	Tue May 11 13:04:00 1999
+++ linux/include/linux/fs.h	Thu May 13 14:42:14 1999
@@ -213,7 +213,7 @@
 	unsigned int b_list;		/* List that this buffer appears */
 	unsigned long b_flushtime;      /* Time when this (dirty) buffer
 					 * should be written */
-	struct wait_queue * b_wait;
+	wait_queue_head_t b_wait;
 	struct buffer_head ** b_pprev;		/* doubly linked list of hash-queue */
 	struct buffer_head * b_prev_free;	/* doubly linked list of buffers */
 	struct buffer_head * b_reqnext;		/* request queue */
@@ -353,7 +353,7 @@
 	struct semaphore	i_atomic_write;
 	struct inode_operations	*i_op;
 	struct super_block	*i_sb;
-	struct wait_queue	*i_wait;
+	wait_queue_head_t	i_wait;
 	struct file_lock	*i_flock;
 	struct vm_area_struct	*i_mmap;
 	struct page		*i_pages;
@@ -453,7 +453,7 @@
 	struct file_lock *fl_prevblock;
 	fl_owner_t fl_owner;
 	unsigned int fl_pid;
-	struct wait_queue *fl_wait;
+	wait_queue_head_t fl_wait;
 	struct file *fl_file;
 	unsigned char fl_flags;
 	unsigned char fl_type;
@@ -529,7 +529,7 @@
 	unsigned long		s_magic;
 	unsigned long		s_time;
 	struct dentry		*s_root;
-	struct wait_queue	*s_wait;
+	wait_queue_head_t	s_wait;
 
 	struct inode		*s_ibasket;
 	short int		s_ibasket_count;
@@ -719,6 +719,7 @@
 extern char * bdevname(kdev_t dev);
 extern char * cdevname(kdev_t dev);
 extern char * kdevname(kdev_t dev);
+extern void init_special_inode(struct inode *, umode_t, int);
 
 
 extern void init_fifo(struct inode * inode);
diff -u --recursive --new-file v2.3.0/linux/include/linux/hayesesp.h linux/include/linux/hayesesp.h
--- v2.3.0/linux/include/linux/hayesesp.h	Fri Jul 24 11:10:16 1998
+++ linux/include/linux/hayesesp.h	Wed May 12 13:27:37 1999
@@ -106,10 +106,10 @@
 	struct tq_struct	tqueue_hangup;
 	struct termios		normal_termios;
 	struct termios		callout_termios;
-	struct wait_queue	*open_wait;
-	struct wait_queue	*close_wait;
-	struct wait_queue	*delta_msr_wait;
-	struct wait_queue	*break_wait;
+	wait_queue_head_t	open_wait;
+	wait_queue_head_t	close_wait;
+	wait_queue_head_t	delta_msr_wait;
+	wait_queue_head_t	break_wait;
 	struct async_icount	icount;	/* kernel counters for the 4 input interrupts */
 	struct hayes_esp_config config; /* port configuration */
 	struct esp_struct	*next_port; /* For the linked list */
diff -u --recursive --new-file v2.3.0/linux/include/linux/hdreg.h linux/include/linux/hdreg.h
--- v2.3.0/linux/include/linux/hdreg.h	Tue May 11 13:03:59 1999
+++ linux/include/linux/hdreg.h	Thu May 13 14:42:14 1999
@@ -93,7 +93,43 @@
 #define SMART_STATUS		0xda
 #define SMART_AUTO_OFFLINE	0xdb
 
+/* WIN_SETFEATURES sub-commands */
+
+#define SETFEATURES_EN_WCACHE	0x02	/* Enable write cache */
+#define SETFEATURES_XFER	0x03	/* Set transfer mode */
+#	define XFER_UDMA_4	0x44	/* 0100|0100 */
+#	define XFER_UDMA_3	0x43	/* 0100|0011 */
+#	define XFER_UDMA_2	0x42	/* 0100|0010 */
+#	define XFER_UDMA_1	0x41	/* 0100|0001 */
+#	define XFER_UDMA_0	0x40	/* 0100|0000 */
+#	define XFER_MW_DMA_2	0x22	/* 0010|0010 */
+#	define XFER_MW_DMA_1	0x21	/* 0010|0001 */
+#	define XFER_MW_DMA_0	0x20	/* 0010|0000 */
+#	define XFER_SW_DMA_2	0x12	/* 0001|0010 */
+#	define XFER_SW_DMA_1	0x11	/* 0001|0001 */
+#	define XFER_SW_DMA_0	0x10	/* 0001|0000 */
+#	define XFER_PIO_4	0x0C	/* 0000|1100 */
+#	define XFER_PIO_3	0x0B	/* 0000|1011 */
+#	define XFER_PIO_2	0x0A	/* 0000|1010 */
+#	define XFER_PIO_1	0x09	/* 0000|1001 */
+#	define XFER_PIO_0	0x08	/* 0000|1000 */
+#	define XFER_PIO_SLOW	0x00	/* 0000|0000 */
+#define SETFEATURES_EN_APM	0x05	/* Enable advanced power management */
+#define SETFEATURES_DIS_MSN	0x31	/* Disable Media Status Notification */
+#define SETFEATURES_DIS_RLA	0x55	/* Disable read look-ahead feature */
+#define SETFEATURES_EN_RI	0x5D	/* Enable release interrupt */
+#define SETFEATURES_EN_SI	0x5E	/* Enable SERVICE interrupt */
+#define SETFEATURES_DIS_RPOD	0x66	/* Disable reverting to power on defaults */
+#define SETFEATURES_DIS_WCACHE	0x82	/* Disable write cache */
+#define SETFEATURES_DIS_APM	0x85	/* Disable advanced power management */
+#define SETFEATURES_EN_MSN	0x95	/* Enable Media Status Notification */
+#define SETFEATURES_EN_RLA	0xAA	/* Enable read look-ahead feature */
+#define SETFEATURES_EN_RPOD	0xCC	/* Enable reverting to power on defaults */
+#define SETFEATURES_DIS_RI	0xDD	/* Disable release interrupt */
+#define SETFEATURES_DIS_SI	0xDE	/* Disable SERVICE interrupt */
+
 /* WIN_SECURITY sub-commands */
+
 #define SECURITY_SET_PASSWORD		0xBA	/* 0xF1 */
 #define SECURITY_UNLOCK			0xBB	/* 0xF2 */
 #define SECURITY_ERASE_PREPARE		0xBC	/* 0xF3 */
diff -u --recursive --new-file v2.3.0/linux/include/linux/hdsmart.h linux/include/linux/hdsmart.h
--- v2.3.0/linux/include/linux/hdsmart.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/hdsmart.h	Thu May 13 11:00:09 1999
@@ -0,0 +1,61 @@
+#ifndef _LINUX_HDSMART_H
+#define _LINUX_HDSMART_H
+
+/*
+ * This file contains some defines for the AT-hd-controller.
+ * Various sources.  
+ */
+
+#define NR_ATTRIBUTES	30
+
+typedef struct threshold_s {
+	unsigned char	id;
+	unsigned char	threshold;
+	unsigned char	reserved[10];
+} __attribute__ ((packed)) threshold_t;
+
+typedef struct thresholds_s {
+	unsigned short	revision;
+	threshold_t	thresholds[NR_ATTRIBUTES];
+	unsigned char	reserved[18];
+	unsigned char	vendor[131];
+	unsigned char	checksum;
+} __attribute__ ((packed)) thresholds_t;
+
+typedef struct value_s {
+	unsigned char	id;
+	unsigned short	status;
+	unsigned char	value;
+	unsigned char	vendor[8];
+} __attribute__ ((packed)) value_t;
+
+typedef struct values_s {
+	unsigned short	revision;
+	value_t		values[NR_ATTRIBUTES];
+	unsigned char	offline_status;
+	unsigned char	vendor1;
+	unsigned short	offline_timeout;
+	unsigned char	vendor2;
+	unsigned char	offline_capability;
+	unsigned short	smart_capability;
+	unsigned char	reserved[16];
+	unsigned char	vendor[125];
+	unsigned char	checksum;
+} __attribute__ ((packed)) values_t;
+
+#if !defined(__KERNEL__) || defined(_IDE_DISK_C)
+ 
+#define NR_OFFLINE_TEXTS	5
+struct {
+	unsigned char	value;
+	char		*text;
+} offline_status_text[NR_OFFLINE_TEXTS] = {
+	{ 0x00, "NeverStarted" },
+	{ 0x02, "Completed" },
+	{ 0x04, "Suspended" },
+	{ 0x05, "Aborted" },
+	{ 0x06, "Failed" }
+};
+#endif /* !defined(__KERNEL__) || defined(_IDE_DISK_C) */
+
+#endif	/* _LINUX_HDSMART_H */
diff -u --recursive --new-file v2.3.0/linux/include/linux/hfmodem.h linux/include/linux/hfmodem.h
--- v2.3.0/linux/include/linux/hfmodem.h	Sun Nov 30 10:30:19 1997
+++ linux/include/linux/hfmodem.h	Wed May 12 13:27:37 1999
@@ -155,7 +155,7 @@
 	} clk;
 
 	int active;
-	struct wait_queue *wait;
+	wait_queue_head_t wait;
 
 	struct {
 		__s16 *kbuf;
diff -u --recursive --new-file v2.3.0/linux/include/linux/hfs_fs.h linux/include/linux/hfs_fs.h
--- v2.3.0/linux/include/linux/hfs_fs.h	Tue May 11 13:05:49 1999
+++ linux/include/linux/hfs_fs.h	Thu May 13 14:44:02 1999
@@ -82,17 +82,22 @@
 #define HFS_SGL_DINF	HFS_ITYPE_1	/* %DirInfo for directory */
 
 /* IDs for elements of an AppleDouble or AppleSingle header */
-#define HFS_HDR_DATA	1
-#define HFS_HDR_RSRC	2
-#define HFS_HDR_FNAME	3
-#define HFS_HDR_COMNT	4
-#define HFS_HDR_BWICN	5
-#define HFS_HDR_CICON	6
-#define HFS_HDR_OLDI	7
-#define HFS_HDR_DATES	8
-#define HFS_HDR_FINFO	9
-#define HFS_HDR_MACI	10
-#define HFS_HDR_MAX	10
+#define HFS_HDR_DATA	1   /* data fork */
+#define HFS_HDR_RSRC	2   /* resource fork */
+#define HFS_HDR_FNAME	3   /* full (31-character) name */
+#define HFS_HDR_COMNT	4   /* comment */
+#define HFS_HDR_BWICN	5   /* b/w icon */
+#define HFS_HDR_CICON	6   /* color icon info */
+#define HFS_HDR_OLDI	7   /* old file info */
+#define HFS_HDR_DATES	8   /* file dates info */
+#define HFS_HDR_FINFO	9   /* Finder info */
+#define HFS_HDR_MACI	10  /* Macintosh info */
+#define HFS_HDR_PRODOSI 11  /* ProDOS info */
+#define HFS_HDR_MSDOSI  12  /* MSDOS info */
+#define HFS_HDR_SNAME   13  /* short name */
+#define HFS_HDR_AFPI    14  /* AFP file info */
+#define HFS_HDR_DID     15  /* directory id */
+#define HFS_HDR_MAX	16
 
 /*
  * There are three time systems.  All three are based on seconds since
@@ -136,26 +141,7 @@
 };
 
 /* 
- * Default header layout for Netatalk
- */
-struct hfs_nat_hdr {
-	hfs_lword_t	magic;
-	hfs_lword_t	version;
-	hfs_byte_t	homefs[16];
-	hfs_word_t	entries;
-	hfs_byte_t	descrs[60];
-	hfs_byte_t	real_name[255];	/* id=3 */
-	hfs_byte_t	comment[200];	/* id=4 XXX: not yet implemented */
-	hfs_lword_t	create_time;	/* \       */
-	hfs_lword_t	modify_time;	/*  |      */
-	hfs_lword_t	backup_time;	/*  | id=7 */
-	hfs_word_t	filler;		/*  |      */
-	hfs_word_t	attr;		/* /       */
-	hfs_byte_t	finderinfo[32]; /* id=9 */
-};
-
-/* 
- * Default header layout for AppleDouble
+ * Default header layout for Netatalk and AppleDouble
  */
 struct hfs_dbl_hdr {
 	hfs_lword_t	magic;
@@ -163,23 +149,37 @@
 	hfs_byte_t	filler[16];
 	hfs_word_t	entries;
 	hfs_byte_t	descrs[12*HFS_HDR_MAX];
-	hfs_u32		create_time;	/* \	   */
-	hfs_u32		modify_time;	/*  | id=8 */
-	hfs_u32		backup_time;	/*  |	   */
-	hfs_u32		access_time;	/* /	   */
+	hfs_byte_t	real_name[255];	/* id=3 */
+	hfs_byte_t	comment[200];	/* id=4 XXX: not yet implemented */
+	hfs_u32		create_time;	/* \	          */
+	hfs_u32		modify_time;	/*  | id=8 (or 7) */
+	hfs_u32		backup_time;	/*  |	          */
+	hfs_u32         access_time;    /* /  (attributes with id=7) */
 	hfs_u8		finderinfo[32]; /* id=9 */
 	hfs_u32		fileinfo;	/* id=10 */
-	hfs_u8		real_name[32];	/* id=3 */
-	hfs_u8		comment[200];	/* id=4 XXX: not yet implemented */
+        hfs_u32         cnid;           /* id=15 */
+	hfs_u8          short_name[12]; /* id=13 */
+	hfs_u8          prodosi[8];     /* id=11 */
 };
 
+
 /* finder metadata for CAP */
 struct hfs_cap_info {
 	hfs_byte_t	fi_fndr[32];	/* Finder's info */
-	hfs_word_t	fi_attr;	/* AFP attributes */
-#define HFS_AFP_WRI		0x020	/* Write inhibit bit */
-#define HFS_AFP_RNI		0x080	/* Rename inhibit bit (AFP >= 2.0) */
-#define HFS_AFP_DEI		0x100	/* Delete inhibit bit (AFP >= 2.0) */
+	hfs_word_t	fi_attr;	/* AFP attributes (f=file/d=dir) */
+#define HFS_AFP_INV             0x001   /* Invisible bit (f/d) */
+#define HFS_AFP_EXPFOLDER       0x002   /* exported folder (d) */
+#define HFS_AFP_MULTI           0x002   /* Multiuser bit (f) */
+#define HFS_AFP_SYS             0x004   /* System bit (f/d) */
+#define HFS_AFP_DOPEN           0x008   /* data fork already open (f) */
+#define HFS_AFP_MOUNTED         0x008   /* mounted folder (d) */
+#define HFS_AFP_ROPEN           0x010   /* resource fork already open (f) */
+#define HFS_AFP_INEXPFOLDER     0x010   /* folder in shared area (d) */
+#define HFS_AFP_WRI		0x020	/* Write inhibit bit (readonly) (f) */
+#define HFS_AFP_BACKUP          0x040   /* backup needed bit (f/d)  */
+#define HFS_AFP_RNI		0x080	/* Rename inhibit bit (f/d) */
+#define HFS_AFP_DEI		0x100	/* Delete inhibit bit (f/d) */
+#define HFS_AFP_NOCOPY          0x400   /* Copy protect bit (f) */
 #define HFS_AFP_RDONLY	(	HFS_AFP_WRI|HFS_AFP_RNI|HFS_AFP_DEI)
 	hfs_byte_t	fi_magic1;	/* Magic number: */
 #define HFS_CAP_MAGIC1		0xFF
@@ -225,7 +225,6 @@
 				loff_t *);
 extern int hfs_create(struct inode *, struct dentry *, int);
 extern int hfs_mkdir(struct inode *, struct dentry *, int);
-extern int hfs_mknod(struct inode *, struct dentry *, int, int);
 extern int hfs_unlink(struct inode *, struct dentry *);
 extern int hfs_rmdir(struct inode *, struct dentry *);
 extern int hfs_rename(struct inode *, struct dentry *,
@@ -273,6 +272,7 @@
 extern const struct hfs_hdr_layout hfs_dbl_fil_hdr_layout;
 extern const struct hfs_hdr_layout hfs_dbl_dir_hdr_layout;
 extern const struct hfs_hdr_layout hfs_nat_hdr_layout;
+extern const struct hfs_hdr_layout hfs_nat2_hdr_layout;
 extern const struct hfs_hdr_layout hfs_sngl_hdr_layout;
 
 /* inode.c */
@@ -280,10 +280,10 @@
 extern int hfs_notify_change(struct dentry *, struct iattr *);
 extern struct inode *hfs_iget(struct hfs_cat_entry *, ino_t, struct dentry *);
 
-extern void hfs_cap_ifill(struct inode *, ino_t);
-extern void hfs_dbl_ifill(struct inode *, ino_t);
-extern void hfs_nat_ifill(struct inode *, ino_t);
-extern void hfs_sngl_ifill(struct inode *, ino_t);
+extern void hfs_cap_ifill(struct inode *, ino_t, const int);
+extern void hfs_dbl_ifill(struct inode *, ino_t, const int);
+extern void hfs_nat_ifill(struct inode *, ino_t, const int);
+extern void hfs_sngl_ifill(struct inode *, ino_t, const int);
 
 /* super.c */
 extern struct super_block *hfs_read_super(struct super_block *,void *,int);
diff -u --recursive --new-file v2.3.0/linux/include/linux/hfs_fs_sb.h linux/include/linux/hfs_fs_sb.h
--- v2.3.0/linux/include/linux/hfs_fs_sb.h	Sun Jan  4 10:40:17 1998
+++ linux/include/linux/hfs_fs_sb.h	Wed May 12 13:26:20 1999
@@ -16,7 +16,7 @@
 
 typedef int (*hfs_namein_fn) (char *, const struct hfs_name *);
 typedef void (*hfs_nameout_fn) (struct hfs_name *, const char *, int);
-typedef void (*hfs_ifill_fn) (struct inode *, ino_t);
+typedef void (*hfs_ifill_fn) (struct inode *, ino_t, const int);
 
 /*
  * struct hfs_sb_info
@@ -30,6 +30,7 @@
 						   changing owner or mode? */
 	int			s_lowercase;	/* Map names to lowercase? */
 	int			s_afpd;		/* AFPD compatible mode? */
+	int                     s_version;      /* version info */
 	hfs_namein_fn		s_namein;	/* The function used to
 						   map Mac filenames to
 						   Linux filenames */
diff -u --recursive --new-file v2.3.0/linux/include/linux/hfs_sysdep.h linux/include/linux/hfs_sysdep.h
--- v2.3.0/linux/include/linux/hfs_sysdep.h	Tue May 11 13:05:32 1999
+++ linux/include/linux/hfs_sysdep.h	Thu May 13 14:43:49 1999
@@ -93,10 +93,10 @@
 /*
  * hfs_wait_queue 
  */
-typedef struct wait_queue *hfs_wait_queue;
+typedef wait_queue_head_t hfs_wait_queue;
 
 extern inline void hfs_init_waitqueue(hfs_wait_queue *queue) {
-        init_waitqueue(queue);
+        init_waitqueue_head(queue);
 }
 
 extern inline void hfs_sleep_on(hfs_wait_queue *queue) {
diff -u --recursive --new-file v2.3.0/linux/include/linux/ide.h linux/include/linux/ide.h
--- v2.3.0/linux/include/linux/ide.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/ide.h	Thu May 13 14:42:24 1999
@@ -0,0 +1,821 @@
+#ifndef _IDE_H
+#define _IDE_H
+/*
+ *  linux/drivers/block/ide.h
+ *
+ *  Copyright (C) 1994-1998  Linus Torvalds & authors
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/hdreg.h>
+#include <linux/hdsmart.h>
+#include <linux/blkdev.h>
+#include <linux/proc_fs.h>
+#include <asm/hdreg.h>
+
+/*
+ * This is the multiple IDE interface driver, as evolved from hd.c.
+ * It supports up to four IDE interfaces, on one or more IRQs (usually 14 & 15).
+ * There can be up to two drives per interface, as per the ATA-2 spec.
+ *
+ * Primary i/f:    ide0: major=3;  (hda)         minor=0; (hdb)         minor=64
+ * Secondary i/f:  ide1: major=22; (hdc or hd1a) minor=0; (hdd or hd1b) minor=64
+ * Tertiary i/f:   ide2: major=33; (hde)         minor=0; (hdf)         minor=64
+ * Quaternary i/f: ide3: major=34; (hdg)         minor=0; (hdh)         minor=64
+ */
+
+/******************************************************************************
+ * IDE driver configuration options (play with these as desired):
+ *
+ * REALLY_SLOW_IO can be defined in ide.c and ide-cd.c, if necessary
+ */
+#undef REALLY_FAST_IO			/* define if ide ports are perfect */
+#define INITIAL_MULT_COUNT	0	/* off=0; on=2,4,8,16,32, etc.. */
+
+#ifndef SUPPORT_SLOW_DATA_PORTS		/* 1 to support slow data ports */
+#define SUPPORT_SLOW_DATA_PORTS	1	/* 0 to reduce kernel size */
+#endif
+#ifndef SUPPORT_VLB_SYNC		/* 1 to support weird 32-bit chips */
+#define SUPPORT_VLB_SYNC	1	/* 0 to reduce kernel size */
+#endif
+#ifndef DISK_RECOVERY_TIME		/* off=0; on=access_delay_time */
+#define DISK_RECOVERY_TIME	0	/*  for hardware that needs it */
+#endif
+#ifndef OK_TO_RESET_CONTROLLER		/* 1 needed for good error recovery */
+#define OK_TO_RESET_CONTROLLER	1	/* 0 for use with AH2372A/B interface */
+#endif
+#ifndef FAKE_FDISK_FOR_EZDRIVE		/* 1 to help linux fdisk with EZDRIVE */
+#define FAKE_FDISK_FOR_EZDRIVE 	1	/* 0 to reduce kernel size */
+#endif
+#ifndef FANCY_STATUS_DUMPS		/* 1 for human-readable drive errors */
+#define FANCY_STATUS_DUMPS	1	/* 0 to reduce kernel size */
+#endif
+
+#ifdef CONFIG_BLK_DEV_CMD640
+#if 0	/* change to 1 when debugging cmd640 problems */
+void cmd640_dump_regs (void);
+#define CMD640_DUMP_REGS cmd640_dump_regs() /* for debugging cmd640 chipset */
+#endif
+#endif  /* CONFIG_BLK_DEV_CMD640 */
+
+/*
+ * IDE_DRIVE_CMD is used to implement many features of the hdparm utility
+ */
+#define IDE_DRIVE_CMD		99	/* (magic) undef to reduce kernel size*/
+
+/*
+ *  "No user-serviceable parts" beyond this point  :)
+ *****************************************************************************/
+
+typedef unsigned char	byte;	/* used everywhere */
+
+/*
+ * Probably not wise to fiddle with these
+ */
+#define ERROR_MAX	8	/* Max read/write errors per sector */
+#define ERROR_RESET	3	/* Reset controller every 4th retry */
+#define ERROR_RECAL	1	/* Recalibrate every 2nd retry */
+
+/*
+ * Ensure that various configuration flags have compatible settings
+ */
+#ifdef REALLY_SLOW_IO
+#undef REALLY_FAST_IO
+#endif
+
+#define HWIF(drive)		((ide_hwif_t *)((drive)->hwif))
+#define HWGROUP(drive)		((ide_hwgroup_t *)(HWIF(drive)->hwgroup))
+
+/*
+ * Definitions for accessing IDE controller registers
+ */
+#define IDE_NR_PORTS		(10)
+
+#define IDE_DATA_OFFSET		(0)
+#define IDE_ERROR_OFFSET	(1)
+#define IDE_NSECTOR_OFFSET	(2)
+#define IDE_SECTOR_OFFSET	(3)
+#define IDE_LCYL_OFFSET		(4)
+#define IDE_HCYL_OFFSET		(5)
+#define IDE_SELECT_OFFSET	(6)
+#define IDE_STATUS_OFFSET	(7)
+#define IDE_CONTROL_OFFSET	(8)
+#define IDE_IRQ_OFFSET		(9)
+
+#define IDE_FEATURE_OFFSET	IDE_ERROR_OFFSET
+#define IDE_COMMAND_OFFSET	IDE_STATUS_OFFSET
+
+#define IDE_DATA_REG		(HWIF(drive)->io_ports[IDE_DATA_OFFSET])
+#define IDE_ERROR_REG		(HWIF(drive)->io_ports[IDE_ERROR_OFFSET])
+#define IDE_NSECTOR_REG		(HWIF(drive)->io_ports[IDE_NSECTOR_OFFSET])
+#define IDE_SECTOR_REG		(HWIF(drive)->io_ports[IDE_SECTOR_OFFSET])
+#define IDE_LCYL_REG		(HWIF(drive)->io_ports[IDE_LCYL_OFFSET])
+#define IDE_HCYL_REG		(HWIF(drive)->io_ports[IDE_HCYL_OFFSET])
+#define IDE_SELECT_REG		(HWIF(drive)->io_ports[IDE_SELECT_OFFSET])
+#define IDE_STATUS_REG		(HWIF(drive)->io_ports[IDE_STATUS_OFFSET])
+#define IDE_CONTROL_REG		(HWIF(drive)->io_ports[IDE_CONTROL_OFFSET])
+#define IDE_IRQ_REG		(HWIF(drive)->io_ports[IDE_IRQ_OFFSET])
+
+#define IDE_FEATURE_REG		IDE_ERROR_REG
+#define IDE_COMMAND_REG		IDE_STATUS_REG
+#define IDE_ALTSTATUS_REG	IDE_CONTROL_REG
+#define IDE_IREASON_REG		IDE_NSECTOR_REG
+#define IDE_BCOUNTL_REG		IDE_LCYL_REG
+#define IDE_BCOUNTH_REG		IDE_HCYL_REG
+
+#ifdef REALLY_FAST_IO
+#define OUT_BYTE(b,p)		outb((b),(p))
+#define IN_BYTE(p)		(byte)inb(p)
+#else
+#define OUT_BYTE(b,p)		outb_p((b),(p))
+#define IN_BYTE(p)		(byte)inb_p(p)
+#endif /* REALLY_FAST_IO */
+
+#define GET_ERR()		IN_BYTE(IDE_ERROR_REG)
+#define GET_STAT()		IN_BYTE(IDE_STATUS_REG)
+#define OK_STAT(stat,good,bad)	(((stat)&((good)|(bad)))==(good))
+#define BAD_R_STAT		(BUSY_STAT   | ERR_STAT)
+#define BAD_W_STAT		(BAD_R_STAT  | WRERR_STAT)
+#define BAD_STAT		(BAD_R_STAT  | DRQ_STAT)
+#define DRIVE_READY		(READY_STAT  | SEEK_STAT)
+#define DATA_READY		(DRQ_STAT)
+
+/*
+ * Some more useful definitions
+ */
+#define IDE_MAJOR_NAME	"ide"	/* the same for all i/f; see also genhd.c */
+#define MAJOR_NAME	IDE_MAJOR_NAME
+#define PARTN_BITS	6	/* number of minor dev bits for partitions */
+#define PARTN_MASK	((1<<PARTN_BITS)-1)	/* a useful bit mask */
+#define MAX_DRIVES	2	/* per interface; 2 assumed by lots of code */
+#define SECTOR_WORDS	(512 / 4)	/* number of 32bit words per sector */
+#define IDE_LARGE_SEEK(b1,b2,t)	(((b1) > (b2) + (t)) || ((b2) > (b1) + (t)))
+#define IDE_MIN(a,b)	((a)<(b) ? (a):(b))
+#define IDE_MAX(a,b)	((a)>(b) ? (a):(b))
+
+/*
+ * Timeouts for various operations:
+ */
+#define WAIT_DRQ	(5*HZ/100)	/* 50msec - spec allows up to 20ms */
+#ifdef CONFIG_APM
+#define WAIT_READY	(5*HZ)		/* 5sec - some laptops are very slow */
+#else
+#define WAIT_READY	(3*HZ/100)	/* 30msec - should be instantaneous */
+#endif /* CONFIG_APM */
+#define WAIT_PIDENTIFY	(10*HZ)	/* 10sec  - should be less than 3ms (?)
+				            if all ATAPI CD is closed at boot */
+#define WAIT_WORSTCASE	(30*HZ)	/* 30sec  - worst case when spinning up */
+#define WAIT_CMD	(10*HZ)	/* 10sec  - maximum wait for an IRQ to happen */
+#define WAIT_MIN_SLEEP	(2*HZ/100)	/* 20msec - minimum sleep time */
+
+#define SELECT_DRIVE(hwif,drive)				\
+{								\
+	if (hwif->selectproc)					\
+		hwif->selectproc(drive);			\
+	OUT_BYTE((drive)->select.all, hwif->io_ports[IDE_SELECT_OFFSET]); \
+}
+
+/*
+ * Check for an interrupt and acknowledge the interrupt status
+ */
+struct hwif_s;
+typedef int (ide_ack_intr_t)(struct hwif_s *);
+
+/*
+ * Structure to hold all information about the location of this port
+ */
+typedef struct hw_regs_s {
+	ide_ioreg_t	io_ports[IDE_NR_PORTS];	/* task file registers */
+	int		irq;			/* our irq number */
+	ide_ack_intr_t	*ack_intr;		/* acknowledge interrupt */
+	void		*priv;			/* interface specific data */
+} hw_regs_t;
+
+/*
+ * Register new hardware with ide
+ */
+int ide_register_hw(hw_regs_t *hw, struct hwif_s **hwifp);
+
+/*
+ * Set up hw_regs_t structure before calling ide_register_hw (optional)
+ */
+void ide_setup_ports(	hw_regs_t *hw,
+			ide_ioreg_t base,
+			int *offsets,
+			ide_ioreg_t ctrl,
+			ide_ioreg_t intr,
+			ide_ack_intr_t *ack_intr,
+			int irq);
+
+#include <asm/ide.h>
+
+/*
+ * Now for the data we need to maintain per-drive:  ide_drive_t
+ */
+
+#define ide_scsi	0x21
+#define ide_disk	0x20
+#define ide_optical	0x7
+#define ide_cdrom	0x5
+#define ide_tape	0x1
+#define ide_floppy	0x0
+
+typedef union {
+	unsigned all			: 8;	/* all of the bits together */
+	struct {
+		unsigned set_geometry	: 1;	/* respecify drive geometry */
+		unsigned recalibrate	: 1;	/* seek to cyl 0      */
+		unsigned set_multmode	: 1;	/* set multmode count */
+		unsigned set_tune	: 1;	/* tune interface for drive */
+		unsigned reserved	: 4;	/* unused */
+		} b;
+	} special_t;
+
+typedef struct ide_drive_s {
+	struct request		*queue;	/* request queue */
+	struct ide_drive_s 	*next;	/* circular list of hwgroup drives */
+	unsigned long sleep;		/* sleep until this time */
+	unsigned long service_start;	/* time we started last request */
+	unsigned long service_time;	/* service time of last request */
+	special_t	special;	/* special action flags */
+	byte     keep_settings;		/* restore settings after drive reset */
+	byte     using_dma;		/* disk is using dma for read/write */
+	byte     waiting_for_dma;	/* dma currently in progress */
+	byte     unmask;		/* flag: okay to unmask other irqs */
+	byte     slow;			/* flag: slow data port */
+	byte     bswap;			/* flag: byte swap data */
+	byte     dsc_overlap;		/* flag: DSC overlap */
+	byte     nice1;			/* flag: give potential excess bandwidth */
+	unsigned present	: 1;	/* drive is physically present */
+	unsigned noprobe 	: 1;	/* from:  hdx=noprobe */
+	unsigned busy		: 1;	/* currently doing revalidate_disk() */
+	unsigned removable	: 1;	/* 1 if need to do check_media_change */
+	unsigned forced_geom	: 1;	/* 1 if hdx=c,h,s was given at boot */
+	unsigned no_unmask	: 1;	/* disallow setting unmask bit */
+	unsigned no_io_32bit	: 1;	/* disallow enabling 32bit I/O */
+	unsigned nobios		: 1;	/* flag: do not probe bios for drive */
+	unsigned revalidate	: 1;	/* request revalidation */
+	unsigned atapi_overlap	: 1;	/* flag: ATAPI overlap (not supported) */
+	unsigned nice0		: 1;	/* flag: give obvious excess bandwidth */
+	unsigned nice2		: 1;	/* flag: give a share in our own bandwidth */
+	unsigned doorlocking	: 1;	/* flag: for removable only: door lock/unlock works */
+	unsigned autotune	: 2;	/* 1=autotune, 2=noautotune, 0=default */
+#if FAKE_FDISK_FOR_EZDRIVE
+	unsigned remap_0_to_1	: 1;	/* flag: partitioned with ezdrive */
+#endif /* FAKE_FDISK_FOR_EZDRIVE */
+	byte		media;		/* disk, cdrom, tape, floppy, ... */
+	select_t	select;		/* basic drive/head select reg value */
+	byte		ctl;		/* "normal" value for IDE_CONTROL_REG */
+	byte		ready_stat;	/* min status value for drive ready */
+	byte		mult_count;	/* current multiple sector setting */
+	byte 		mult_req;	/* requested multiple sector setting */
+	byte 		tune_req;	/* requested drive tuning setting */
+	byte		io_32bit;	/* 0=16-bit, 1=32-bit, 2/3=32bit+sync */
+	byte		bad_wstat;	/* used for ignoring WRERR_STAT */
+	byte		nowerr;		/* used for ignoring WRERR_STAT */
+	byte		sect0;		/* offset of first sector for DM6:DDO */
+	byte 		usage;		/* current "open()" count for drive */
+	byte 		head;		/* "real" number of heads */
+	byte		sect;		/* "real" sectors per track */
+	byte		bios_head;	/* BIOS/fdisk/LILO number of heads */
+	byte		bios_sect;	/* BIOS/fdisk/LILO sectors per track */
+	unsigned short	bios_cyl;	/* BIOS/fdisk/LILO number of cyls */
+	unsigned short	cyl;		/* "real" number of cyls */
+	unsigned int	drive_data;	/* for use by tuneproc/selectproc as needed */
+	void		  *hwif;	/* actually (ide_hwif_t *) */
+	wait_queue_head_t wqueue;	/* used to wait for drive in open() */
+	struct hd_driveid *id;		/* drive model identification info */
+	struct hd_struct  *part;	/* drive partition table */
+	char		name[4];	/* drive name, such as "hda" */
+	void 		*driver;	/* (ide_driver_t *) */
+	void		*driver_data;	/* extra driver data */
+	struct proc_dir_entry *proc;	/* /proc/ide/ directory entry */
+	void		*settings;	/* /proc/ide/ drive settings */
+	char		driver_req[10];	/* requests specific driver */
+#if 1
+	struct thresholds_s	*smart_thresholds;
+	struct values_s		*smart_values;
+#else
+	thresholds_t		smart_thresholds;
+	values_t		smart_values;
+#endif
+	} ide_drive_t;
+
+/*
+ * An ide_dmaproc_t() initiates/aborts DMA read/write operations on a drive.
+ *
+ * The caller is assumed to have selected the drive and programmed the drive's
+ * sector address using CHS or LBA.  All that remains is to prepare for DMA
+ * and then issue the actual read/write DMA/PIO command to the drive.
+ *
+ * Returns 0 if all went well.
+ * Returns 1 if DMA read/write could not be started, in which case the caller
+ * should either try again later, or revert to PIO for the current request.
+ */
+typedef enum {	ide_dma_read,	ide_dma_write,		ide_dma_begin,
+		ide_dma_end,	ide_dma_check,		ide_dma_on,
+		ide_dma_off,	ide_dma_off_quietly,	ide_dma_test_irq,
+		ide_dma_bad_drive,			ide_dma_good_drive
+	} ide_dma_action_t;
+
+typedef int (ide_dmaproc_t)(ide_dma_action_t, ide_drive_t *);
+
+
+/*
+ * An ide_tuneproc_t() is used to set the speed of an IDE interface
+ * to a particular PIO mode.  The "byte" parameter is used
+ * to select the PIO mode by number (0,1,2,3,4,5), and a value of 255
+ * indicates that the interface driver should "auto-tune" the PIO mode
+ * according to the drive capabilities in drive->id;
+ *
+ * Not all interface types support tuning, and not all of those
+ * support all possible PIO settings.  They may silently ignore
+ * or round values as they see fit.
+ */
+typedef void (ide_tuneproc_t)(ide_drive_t *, byte);
+
+/*
+ * This is used to provide support for strange interfaces
+ */
+typedef void (ide_selectproc_t) (ide_drive_t *);
+
+/*
+ * hwif_chipset_t is used to keep track of the specific hardware
+ * chipset used by each IDE interface, if known.
+ */
+typedef enum {	ide_unknown,	ide_generic,	ide_pci,
+		ide_cmd640,	ide_dtc2278,	ide_ali14xx,
+		ide_qd6580,	ide_umc8672,	ide_ht6560b,
+		ide_pdc4030,	ide_rz1000,	ide_trm290,
+		ide_cmd646,	ide_cy82c693,	ide_4drives
+	} hwif_chipset_t;
+
+typedef struct ide_pci_devid_s {
+	unsigned short	vid;
+	unsigned short	did;
+} ide_pci_devid_t;
+
+#define IDE_PCI_DEVID_NULL	((ide_pci_devid_t){0,0})
+#define IDE_PCI_DEVID_EQ(a,b)	(a.vid == b.vid && a.did == b.did)
+
+typedef struct hwif_s {
+	struct hwif_s	*next;		/* for linked-list in ide_hwgroup_t */
+	void		*hwgroup;	/* actually (ide_hwgroup_t *) */
+	ide_ioreg_t	io_ports[IDE_NR_PORTS];	/* task file registers */
+	hw_regs_t	hw;		/* Hardware info */
+	ide_drive_t	drives[MAX_DRIVES];	/* drive info */
+	struct gendisk	*gd;		/* gendisk structure */
+	ide_tuneproc_t	*tuneproc;	/* routine to tune PIO mode for drives */
+	ide_selectproc_t *selectproc;	/* tweaks hardware to select drive */
+	ide_dmaproc_t	*dmaproc;	/* dma read/write/abort routine */
+	unsigned long	*dmatable;	/* dma physical region descriptor table */
+	struct hwif_s	*mate;		/* other hwif from same PCI chip */
+	unsigned long	dma_base;	/* base addr for dma ports */
+	unsigned	dma_extra;	/* extra addr for dma ports */
+	unsigned long	config_data;	/* for use by chipset-specific code */
+	unsigned long	select_data;	/* for use by chipset-specific code */
+	struct proc_dir_entry *proc;	/* /proc/ide/ directory entry */
+	int		irq;		/* our irq number */
+	byte		major;		/* our major number */
+	char 		name[6];	/* name of interface, eg. "ide0" */
+	byte		index;		/* 0 for ide0; 1 for ide1; ... */
+	hwif_chipset_t	chipset;	/* sub-module for tuning.. */
+	unsigned	noprobe    : 1;	/* don't probe for this interface */
+	unsigned	present    : 1;	/* this interface exists */
+	unsigned	serialized : 1;	/* serialized operation with mate hwif */
+	unsigned	sharing_irq: 1;	/* 1 = sharing irq with another hwif */
+	unsigned	reset      : 1;	/* reset after probe */
+	unsigned	autodma    : 1;	/* automatically try to enable DMA at boot */
+	byte		channel;	/* for dual-port chips: 0=primary, 1=secondary */
+	struct pci_dev	*pci_dev;	/* for pci chipsets */
+	ide_pci_devid_t	pci_devid;	/* for pci chipsets: {VID,DID} */
+#if (DISK_RECOVERY_TIME > 0)
+	unsigned long	last_time;	/* time when previous rq was done */
+#endif
+	} ide_hwif_t;
+
+/*
+ *  internal ide interrupt handler type
+ */
+typedef void (ide_handler_t)(ide_drive_t *);
+
+typedef struct hwgroup_s {
+	spinlock_t		spinlock; /* protects "busy" and "handler" */
+	ide_handler_t		*handler;/* irq handler, if active */
+	int			busy;	/* BOOL: protects all fields below */
+	ide_drive_t		*drive;	/* current drive */
+	ide_hwif_t		*hwif;	/* ptr to current hwif in linked-list */
+	struct request		*rq;	/* current request */
+	struct timer_list	timer;	/* failsafe timer */
+	struct request		wrq;	/* local copy of current write rq */
+	unsigned long		poll_timeout;	/* timeout value during long polls */
+	} ide_hwgroup_t;
+
+/*
+ * configurable drive settings
+ */
+
+#define TYPE_INT	0
+#define TYPE_INTA	1
+#define TYPE_BYTE	2
+#define TYPE_SHORT	3
+
+#define SETTING_READ	(1 << 0)
+#define SETTING_WRITE	(1 << 1)
+#define SETTING_RW	(SETTING_READ | SETTING_WRITE)
+
+typedef int (ide_procset_t)(ide_drive_t *, int);
+typedef struct ide_settings_s {
+	char			*name;
+	int			rw;
+	int			read_ioctl;
+	int			write_ioctl;
+	int			data_type;
+	int			min;
+	int			max;
+	int			mul_factor;
+	int			div_factor;
+	void			*data;
+	ide_procset_t		*set;
+	int			auto_remove;
+	struct ide_settings_s	*next;
+} ide_settings_t;
+
+void ide_add_setting(ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set);
+void ide_remove_setting(ide_drive_t *drive, char *name);
+ide_settings_t *ide_find_setting_by_name(ide_drive_t *drive, char *name);
+int ide_read_setting(ide_drive_t *t, ide_settings_t *setting);
+int ide_write_setting(ide_drive_t *drive, ide_settings_t *setting, int val);
+void ide_add_generic_settings(ide_drive_t *drive);
+
+/*
+ * /proc/ide interface
+ */
+typedef struct {
+	const char	*name;
+	mode_t		mode;
+	read_proc_t	*read_proc;
+	write_proc_t	*write_proc;
+} ide_proc_entry_t;
+
+#ifdef CONFIG_PROC_FS
+void proc_ide_create(void);
+void proc_ide_destroy(void);
+void ide_add_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t *p, void *data);
+void ide_remove_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t *p);
+read_proc_t proc_ide_read_capacity;
+read_proc_t proc_ide_read_geometry;
+
+/*
+ * Standard exit stuff:
+ */
+#define PROC_IDE_READ_RETURN(page,start,off,count,eof,len) \
+{					\
+	len -= off;			\
+	if (len < count) {		\
+		*eof = 1;		\
+		if (len <= 0)		\
+			return 0;	\
+	} else				\
+		len = count;		\
+	*start = page + off;		\
+	return len;			\
+}
+#else
+#define PROC_IDE_READ_RETURN(page,start,off,count,eof,len) return 0;
+#endif
+
+/*
+ * Subdrivers support.
+ */
+#define IDE_SUBDRIVER_VERSION	1
+
+typedef int	(ide_cleanup_proc)(ide_drive_t *);
+typedef void 	(ide_do_request_proc)(ide_drive_t *, struct request *, unsigned long);
+typedef void	(ide_end_request_proc)(byte, ide_hwgroup_t *);
+typedef int 	(ide_ioctl_proc)(ide_drive_t *, struct inode *, struct file *, unsigned int, unsigned long);
+typedef int	(ide_open_proc)(struct inode *, struct file *, ide_drive_t *);
+typedef void 	(ide_release_proc)(struct inode *, struct file *, ide_drive_t *);
+typedef int	(ide_check_media_change_proc)(ide_drive_t *);
+typedef void	(ide_pre_reset_proc)(ide_drive_t *);
+typedef unsigned long (ide_capacity_proc)(ide_drive_t *);
+typedef void	(ide_special_proc)(ide_drive_t *);
+typedef void	(ide_setting_proc)(ide_drive_t *);
+
+typedef struct ide_driver_s {
+	const char			*name;
+	const char			*version;
+	byte				media;
+	unsigned busy			: 1;
+	unsigned supports_dma		: 1;
+	unsigned supports_dsc_overlap	: 1;
+	ide_cleanup_proc		*cleanup;
+	ide_do_request_proc		*do_request;
+	ide_end_request_proc		*end_request;
+	ide_ioctl_proc			*ioctl;
+	ide_open_proc			*open;
+	ide_release_proc		*release;
+	ide_check_media_change_proc	*media_change;
+	ide_pre_reset_proc		*pre_reset;
+	ide_capacity_proc		*capacity;
+	ide_special_proc		*special;
+	ide_proc_entry_t		*proc;
+	} ide_driver_t;
+
+#define DRIVER(drive)		((ide_driver_t *)((drive)->driver))
+
+/*
+ * IDE modules.
+ */
+#define IDE_CHIPSET_MODULE		0	/* not supported yet */
+#define IDE_PROBE_MODULE		1
+#define IDE_DRIVER_MODULE		2
+
+typedef int	(ide_module_init_proc)(void);
+
+typedef struct ide_module_s {
+	int				type;
+	ide_module_init_proc		*init;
+	void				*info;
+	struct ide_module_s		*next;
+} ide_module_t;
+
+/*
+ * ide_hwifs[] is the master data structure used to keep track
+ * of just about everything in ide.c.  Whenever possible, routines
+ * should be using pointers to a drive (ide_drive_t *) or
+ * pointers to a hwif (ide_hwif_t *), rather than indexing this
+ * structure directly (the allocation/layout may change!).
+ *
+ */
+#ifndef _IDE_C
+extern	ide_hwif_t	ide_hwifs[];		/* master data repository */
+extern  ide_module_t	*ide_modules;
+#endif
+
+/*
+ * We need blk.h, but we replace its end_request by our own version.
+ */
+#define IDE_DRIVER		/* Toggle some magic bits in blk.h */
+#define LOCAL_END_REQUEST	/* Don't generate end_request in blk.h */
+#include <linux/blk.h>
+
+void ide_end_request(byte uptodate, ide_hwgroup_t *hwgroup);
+
+/*
+ * This is used for (nearly) all data transfers from/to the IDE interface
+ */
+void ide_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount);
+void ide_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount);
+
+/*
+ * This is used for (nearly) all ATAPI data transfers from/to the IDE interface
+ */
+void atapi_input_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount);
+void atapi_output_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount);
+
+/*
+ * This is used on exit from the driver, to designate the next irq handler
+ * and also to start the safety timer.
+ */
+void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, unsigned int timeout);
+
+/*
+ * Error reporting, in human readable form (luxurious, but a memory hog).
+ */
+byte ide_dump_status (ide_drive_t *drive, const char *msg, byte stat);
+
+/*
+ * ide_error() takes action based on the error returned by the controller.
+ * The calling function must return afterwards, to restart the request.
+ */
+void ide_error (ide_drive_t *drive, const char *msg, byte stat);
+
+/*
+ * Issue a simple drive command
+ * The drive must be selected beforehand.
+ */
+void ide_cmd(ide_drive_t *drive, byte cmd, byte nsect, ide_handler_t *handler);
+
+/*
+ * ide_fixstring() cleans up and (optionally) byte-swaps a text string,
+ * removing leading/trailing blanks and compressing internal blanks.
+ * It is primarily used to tidy up the model name/number fields as
+ * returned by the WIN_[P]IDENTIFY commands.
+ */
+void ide_fixstring (byte *s, const int bytecount, const int byteswap);
+
+/*
+ * This routine busy-waits for the drive status to be not "busy".
+ * It then checks the status for all of the "good" bits and none
+ * of the "bad" bits, and if all is okay it returns 0.  All other
+ * cases return 1 after invoking ide_error() -- caller should return.
+ *
+ */
+int ide_wait_stat (ide_drive_t *drive, byte good, byte bad, unsigned long timeout);
+
+/*
+ * This routine is called from the partition-table code in genhd.c
+ * to "convert" a drive to a logical geometry with fewer than 1024 cyls.
+ *
+ * The second parameter, "xparm", determines exactly how the translation
+ * will be handled:
+ *		 0 = convert to CHS with fewer than 1024 cyls
+ *			using the same method as Ontrack DiskManager.
+ *		 1 = same as "0", plus offset everything by 63 sectors.
+ *		-1 = similar to "0", plus redirect sector 0 to sector 1.
+ *		>1 = convert to a CHS geometry with "xparm" heads.
+ *
+ * Returns 0 if the translation was not possible, if the device was not
+ * an IDE disk drive, or if a geometry was "forced" on the commandline.
+ * Returns 1 if the geometry translation was successful.
+ */
+int ide_xlate_1024 (kdev_t, int, const char *);
+
+/*
+ * Start a reset operation for an IDE interface.
+ * The caller should return immediately after invoking this.
+ */
+void ide_do_reset (ide_drive_t *);
+
+/*
+ * This function is intended to be used prior to invoking ide_do_drive_cmd().
+ */
+void ide_init_drive_cmd (struct request *rq);
+
+/*
+ * "action" parameter type for ide_do_drive_cmd() below.
+ */
+typedef enum
+	{ide_wait,	/* insert rq at end of list, and wait for it */
+	 ide_next,	/* insert rq immediately after current request */
+	 ide_preempt,	/* insert rq in front of current request */
+	 ide_end}	/* insert rq at end of list, but don't wait for it */
+ ide_action_t;
+
+/*
+ * This function issues a special IDE device request
+ * onto the request queue.
+ *
+ * If action is ide_wait, then the rq is queued at the end of the
+ * request queue, and the function sleeps until it has been processed.
+ * This is for use when invoked from an ioctl handler.
+ *
+ * If action is ide_preempt, then the rq is queued at the head of
+ * the request queue, displacing the currently-being-processed
+ * request and this function returns immediately without waiting
+ * for the new rq to be completed.  This is VERY DANGEROUS, and is
+ * intended for careful use by the ATAPI tape/cdrom driver code.
+ *
+ * If action is ide_next, then the rq is queued immediately after
+ * the currently-being-processed-request (if any), and the function
+ * returns without waiting for the new rq to be completed.  As above,
+ * This is VERY DANGEROUS, and is intended for careful use by the
+ * ATAPI tape/cdrom driver code.
+ *
+ * If action is ide_end, then the rq is queued at the end of the
+ * request queue, and the function returns immediately without waiting
+ * for the new rq to be completed. This is again intended for careful
+ * use by the ATAPI tape/cdrom driver code.
+ */
+int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t action);
+
+/*
+ * Clean up after success/failure of an explicit drive cmd.
+ * stat/err are used only when (HWGROUP(drive)->rq->cmd == IDE_DRIVE_CMD).
+ */
+void ide_end_drive_cmd (ide_drive_t *drive, byte stat, byte err);
+
+/*
+ * Issue ATA command and wait for completion.
+ */
+int ide_wait_cmd (ide_drive_t *drive, int cmd, int nsect, int feature, int sectors, byte *buf);
+
+void ide_delay_50ms (void);
+
+/*
+ * ide_system_bus_speed() returns what we think is the system VESA/PCI
+ * bus speed (in MHz).  This is used for calculating interface PIO timings.
+ * The default is 40 for known PCI systems, 50 otherwise.
+ * The "idebus=xx" parameter can be used to override this value.
+ */
+int ide_system_bus_speed (void);
+
+/*
+ * ide_multwrite() transfers a block of up to mcount sectors of data
+ * to a drive as part of a disk multwrite operation.
+ */
+void ide_multwrite (ide_drive_t *drive, unsigned int mcount);
+
+/*
+ * ide_stall_queue() can be used by a drive to give excess bandwidth back
+ * to the hwgroup by sleeping for timeout jiffies.
+ */
+void ide_stall_queue (ide_drive_t *drive, unsigned long timeout);
+
+/*
+ * ide_get_queue() returns the queue which corresponds to a given device.
+ */
+struct request **ide_get_queue (kdev_t dev);
+
+/*
+ * CompactFlash cards and their brethern pretend to be removable hard disks,
+ * but they never have a slave unit, and they don't have doorlock mechanisms.
+ * This test catches them, and is invoked elsewhere when setting appropriate config bits.
+ */
+int drive_is_flashcard (ide_drive_t *drive);
+
+int  ide_spin_wait_hwgroup(ide_drive_t *drive, unsigned long *flags);
+void ide_timer_expiry (unsigned long data);
+void ide_intr (int irq, void *dev_id, struct pt_regs *regs);
+void ide_geninit (struct gendisk *gd);
+void do_ide0_request (void);
+#if MAX_HWIFS > 1
+void do_ide1_request (void);
+#endif
+#if MAX_HWIFS > 2
+void do_ide2_request (void);
+#endif
+#if MAX_HWIFS > 3
+void do_ide3_request (void);
+#endif
+#if MAX_HWIFS > 4
+void do_ide4_request (void);
+#endif
+#if MAX_HWIFS > 5
+void do_ide5_request (void);
+#endif
+#if MAX_HWIFS > 6
+void do_ide6_request (void);
+#endif
+#if MAX_HWIFS > 7
+void do_ide7_request (void);
+#endif
+void ide_init_subdrivers (void);
+
+#ifndef _IDE_C
+extern struct file_operations ide_fops[];
+#endif
+
+#ifdef _IDE_C
+#ifdef CONFIG_BLK_DEV_IDE
+int ideprobe_init (void);
+#endif /* CONFIG_BLK_DEV_IDE */
+#ifdef CONFIG_BLK_DEV_IDEDISK
+int idedisk_init (void);
+#endif /* CONFIG_BLK_DEV_IDEDISK */
+#ifdef CONFIG_BLK_DEV_IDECD
+int ide_cdrom_init (void);
+#endif /* CONFIG_BLK_DEV_IDECD */
+#ifdef CONFIG_BLK_DEV_IDETAPE
+int idetape_init (void);
+#endif /* CONFIG_BLK_DEV_IDETAPE */
+#ifdef CONFIG_BLK_DEV_IDEFLOPPY
+int idefloppy_init (void);
+#endif /* CONFIG_BLK_DEV_IDEFLOPPY */
+#ifdef CONFIG_BLK_DEV_IDESCSI
+int idescsi_init (void);
+#endif /* CONFIG_BLK_DEV_IDESCSI */
+#endif /* _IDE_C */
+
+int ide_register_module (ide_module_t *module);
+void ide_unregister_module (ide_module_t *module);
+ide_drive_t *ide_scan_devices (byte media, const char *name, ide_driver_t *driver, int n);
+int ide_register_subdriver (ide_drive_t *drive, ide_driver_t *driver, int version);
+int ide_unregister_subdriver (ide_drive_t *drive);
+int ide_replace_subdriver(ide_drive_t *drive, const char *driver);
+
+#ifdef CONFIG_BLK_DEV_IDEPCI
+#define ON_BOARD		1
+#define NEVER_BOARD		0
+#ifdef CONFIG_BLK_DEV_OFFBOARD
+#  define OFF_BOARD		ON_BOARD
+#else /* CONFIG_BLK_DEV_OFFBOARD */
+#  define OFF_BOARD		NEVER_BOARD
+#endif /* CONFIG_BLK_DEV_OFFBOARD */
+unsigned long ide_find_free_region (unsigned short size) __init;
+void ide_scan_pcibus (void) __init;
+#endif
+#ifdef CONFIG_BLK_DEV_IDEDMA
+#define BAD_DMA_DRIVE		0
+#define GOOD_DMA_DRIVE		1
+int ide_build_dmatable (ide_drive_t *drive, ide_dma_action_t func);
+void ide_dma_intr  (ide_drive_t *drive);
+int check_drive_lists (ide_drive_t *drive, int good_bad);
+int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive);
+int ide_release_dma (ide_hwif_t *hwif);
+void ide_setup_dma (ide_hwif_t *hwif, unsigned long dmabase, unsigned int num_ports) __init;
+unsigned long ide_get_or_set_dma_base (ide_hwif_t *hwif, int extra, const char *name) __init;
+#endif
+
+/* This is too ugly to live! */
+#ifdef CONFIG_BLK_DEV_PDC4030
+#include "pdc4030.h"
+#define IS_PDC4030_DRIVE (HWIF(drive)->chipset == ide_pdc4030)
+#else
+#define IS_PDC4030_DRIVE (0)	/* auto-NULLs out pdc4030 code */
+#endif /* CONFIG_BLK_DEV_PDC4030 */
+
+#endif /* _IDE_H */
diff -u --recursive --new-file v2.3.0/linux/include/linux/if_pppvar.h linux/include/linux/if_pppvar.h
--- v2.3.0/linux/include/linux/if_pppvar.h	Tue Apr 27 00:38:28 1999
+++ linux/include/linux/if_pppvar.h	Wed May 12 08:41:15 1999
@@ -109,7 +109,7 @@
 	__u16		rfcs;		/* FCS so far of rpkt		*/
 
 	/* Queues for select() functionality */
-	struct wait_queue *read_wait;	/* queue for reading processes	*/
+	wait_queue_head_t read_wait;	/* queue for reading processes	*/
 
 	/* info for detecting idle channels */
 	unsigned long	last_xmit;	/* time of last transmission	*/
diff -u --recursive --new-file v2.3.0/linux/include/linux/if_shaper.h linux/include/linux/if_shaper.h
--- v2.3.0/linux/include/linux/if_shaper.h	Wed Feb 24 16:27:53 1999
+++ linux/include/linux/if_shaper.h	Wed May 12 13:27:37 1999
@@ -37,7 +37,7 @@
 	int (*hard_header_cache)(struct neighbour *neigh, struct hh_cache *hh);
 	void (*header_cache_update)(struct hh_cache *hh, struct device *dev, unsigned char *  haddr);
 	struct net_device_stats* (*get_stats)(struct device *dev);
-	struct wait_queue *wait_queue;
+	wait_queue_head_t  wait_queue;
 	struct timer_list timer;
 };
 
diff -u --recursive --new-file v2.3.0/linux/include/linux/isdn.h linux/include/linux/isdn.h
--- v2.3.0/linux/include/linux/isdn.h	Tue Jan 19 11:06:52 1999
+++ linux/include/linux/isdn.h	Thu May 13 10:53:34 1999
@@ -626,8 +626,7 @@
   atemu                 emu;             /* AT-emulator data               */
   struct termios	normal_termios;  /* For saving termios structs     */
   struct termios	callout_termios;
-  struct wait_queue	*open_wait;
-  struct wait_queue	*close_wait;
+  wait_queue_head_t 	open_wait, close_wait;
 } modem_info;
 
 #define ISDN_MODEM_WINSIZE 8
@@ -683,8 +682,8 @@
   struct ippp_buf_queue rq[NUM_RCV_BUFFS]; /* packet queue for isdn_ppp_read() */
   struct ippp_buf_queue *first;  /* pointer to (current) first packet */
   struct ippp_buf_queue *last;   /* pointer to (current) last used packet in queue */
-  struct wait_queue *wq;
-  struct wait_queue *wq1;
+  wait_queue_head_t wq;
+  wait_queue_head_t wql;
   struct task_struct *tk;
   unsigned int mpppcfg;
   unsigned int pppcfg;
@@ -748,7 +747,7 @@
   ulong               flags;            /* Flags                            */
   int                 channels;         /* Number of channels               */
   int                 reject_bus;       /* Flag: Reject rejected call on bus*/
-  struct wait_queue  *st_waitq;         /* Wait-Queue for status-read's     */
+  wait_queue_head_t   st_waitq;         /* Wait-Queue for status-read's     */
   int                 maxbufsize;       /* Maximum Buffersize supported     */
   unsigned long       pktcount;         /* Until now: unused                */
   int                 running;          /* Flag: Protocolcode running       */
@@ -761,8 +760,8 @@
   unsigned long      DLEflag;           /* Flags: Insert DLE at next read   */
 #endif
   struct sk_buff_head *rpqueue;         /* Pointers to start of Rcv-Queue   */
-  struct wait_queue  **rcv_waitq;       /* Wait-Queues for B-Channel-Reads  */
-  struct wait_queue  **snd_waitq;       /* Wait-Queue for B-Channel-Send's  */
+  wait_queue_head_t  *rcv_waitq;  /* array of Wait-Queues for B-Channel-Reads  */
+  wait_queue_head_t  *snd_waitq;  /* array of Wait-Queue for B-Channel-Sends  */
   char               msn2eaz[10][ISDN_MSNLEN];  /* Mapping-Table MSN->EAZ   */
 } driver;
 
@@ -778,7 +777,7 @@
 				               /*  see ISDN_TIMER_..defines  */
   int               global_flags;
   infostruct        *infochain;                /* List of open info-devs.    */
-  struct wait_queue *info_waitq;               /* Wait-Queue for isdninfo    */
+  wait_queue_head_t info_waitq;               /* Wait-Queue for isdninfo    */
   struct timer_list timer;		       /* Misc.-function Timer       */
   int               chanmap[ISDN_MAX_CHANNELS];/* Map minor->device-channel  */
   int               drvmap[ISDN_MAX_CHANNELS]; /* Map minor->driver-index    */
diff -u --recursive --new-file v2.3.0/linux/include/linux/isicom.h linux/include/linux/isicom.h
--- v2.3.0/linux/include/linux/isicom.h	Thu Dec 17 16:21:29 1998
+++ linux/include/linux/isicom.h	Wed May 12 13:27:37 1999
@@ -144,8 +144,8 @@
 	long			pgrp;
 	struct isi_board	* card;
 	struct tty_struct 	* tty;
-	struct wait_queue	* close_wait;
-	struct wait_queue	* open_wait;
+	wait_queue_head_t	close_wait;
+	wait_queue_head_t	open_wait;
 	struct tq_struct	hangup_tq;
 	struct tq_struct	bh_tqueue;
 	unsigned char		* xmit_buf;
diff -u --recursive --new-file v2.3.0/linux/include/linux/joystick.h linux/include/linux/joystick.h
--- v2.3.0/linux/include/linux/joystick.h	Tue May 11 13:05:00 1999
+++ linux/include/linux/joystick.h	Thu May 13 14:43:17 1999
@@ -217,7 +217,7 @@
 	struct js_dev *next;
 	struct js_list *list;
 	struct js_port *port;
-	struct wait_queue *wait;
+	wait_queue_head_t wait;
 	struct js_data cur;
 	struct js_data new;
 	struct js_corr *corr;
diff -u --recursive --new-file v2.3.0/linux/include/linux/keyboard.h linux/include/linux/keyboard.h
--- v2.3.0/linux/include/linux/keyboard.h	Thu Jul 30 11:17:12 1998
+++ linux/include/linux/keyboard.h	Thu May 13 14:42:14 1999
@@ -1,6 +1,8 @@
 #ifndef __LINUX_KEYBOARD_H
 #define __LINUX_KEYBOARD_H
 
+#include <linux/wait.h>
+
 #define KG_SHIFT	0
 #define KG_CTRL		2
 #define KG_ALT		3
@@ -24,7 +26,7 @@
 extern const int max_vals[];
 extern unsigned short *key_maps[MAX_NR_KEYMAPS];
 extern unsigned short plain_map[NR_KEYS];
-extern struct wait_queue * keypress_wait;
+extern wait_queue_head_t keypress_wait;
 extern unsigned char keyboard_type;
 #endif
 
diff -u --recursive --new-file v2.3.0/linux/include/linux/lockd/lockd.h linux/include/linux/lockd/lockd.h
--- v2.3.0/linux/include/linux/lockd/lockd.h	Tue May 11 13:04:34 1999
+++ linux/include/linux/lockd/lockd.h	Thu May 13 14:42:47 1999
@@ -44,7 +44,7 @@
 	unsigned short		h_reclaiming : 1,
 				h_inuse      : 1,
 				h_monitored  : 1;
-	struct wait_queue *	h_gracewait;	/* wait while reclaiming */
+	wait_queue_head_t	h_gracewait;	/* wait while reclaiming */
 	u32			h_state;	/* pseudo-state counter */
 	u32			h_nsmstate;	/* true remote NSM state */
 	unsigned int		h_count;	/* reference count */
diff -u --recursive --new-file v2.3.0/linux/include/linux/lp.h linux/include/linux/lp.h
--- v2.3.0/linux/include/linux/lp.h	Fri Nov 27 10:23:11 1998
+++ linux/include/linux/lp.h	Tue May 11 23:39:11 1999
@@ -123,7 +123,7 @@
 	unsigned int runchars;
 	struct lp_stats stats;
 #endif
-	struct wait_queue *wait_q;
+	wait_queue_head_t wait_q;
 	unsigned int last_error;
 	volatile unsigned int irq_detected:1;
 	volatile unsigned int irq_missed:1;
diff -u --recursive --new-file v2.3.0/linux/include/linux/major.h linux/include/linux/major.h
--- v2.3.0/linux/include/linux/major.h	Wed Oct 14 11:43:14 1998
+++ linux/include/linux/major.h	Thu May 13 11:00:09 1999
@@ -92,6 +92,9 @@
 #define SPECIALIX_NORMAL_MAJOR 75
 #define SPECIALIX_CALLOUT_MAJOR 76
 
+#define IDE6_MAJOR	88
+#define IDE7_MAJOR	89
+
 #define UNIX98_PTY_MASTER_MAJOR	128
 #define UNIX98_PTY_MAJOR_COUNT	8
 #define UNIX98_PTY_SLAVE_MAJOR	(UNIX98_PTY_MASTER_MAJOR+UNIX98_PTY_MAJOR_COUNT)
diff -u --recursive --new-file v2.3.0/linux/include/linux/md.h linux/include/linux/md.h
--- v2.3.0/linux/include/linux/md.h	Fri May  8 00:17:13 1998
+++ linux/include/linux/md.h	Tue May 11 14:46:24 1999
@@ -274,7 +274,7 @@
 struct md_thread {
 	void			(*run) (void *data);
 	void			*data;
-	struct wait_queue	*wqueue;
+	wait_queue_head_t	wqueue;
 	unsigned long           flags;
 	struct semaphore	*sem;
 	struct task_struct	*tsk;
diff -u --recursive --new-file v2.3.0/linux/include/linux/mm.h linux/include/linux/mm.h
--- v2.3.0/linux/include/linux/mm.h	Tue May 11 13:04:01 1999
+++ linux/include/linux/mm.h	Thu May 13 14:42:18 1999
@@ -126,7 +126,7 @@
 	struct page *next_hash;
 	atomic_t count;
 	unsigned long flags;	/* atomic flags, some possibly updated asynchronously */
-	struct wait_queue *wait;
+	wait_queue_head_t wait;
 	struct page **pprev_hash;
 	struct buffer_head * buffers;
 } mem_map_t;
diff -u --recursive --new-file v2.3.0/linux/include/linux/msdos_fs_sb.h linux/include/linux/msdos_fs_sb.h
--- v2.3.0/linux/include/linux/msdos_fs_sb.h	Sun Dec 27 10:47:18 1998
+++ linux/include/linux/msdos_fs_sb.h	Wed May 12 08:41:15 1999
@@ -43,7 +43,7 @@
 	unsigned long clusters;      /* number of clusters */
 	unsigned long root_cluster;  /* first cluster of the root directory */
 	unsigned long fsinfo_offset; /* FAT32 fsinfo offset from start of disk */
-	struct wait_queue *fat_wait;
+	wait_queue_head_t fat_wait;
 	int fat_lock;
 	int prev_free;               /* previously returned free cluster number */
 	int free_clusters;           /* -1 if undefined */
diff -u --recursive --new-file v2.3.0/linux/include/linux/msg.h linux/include/linux/msg.h
--- v2.3.0/linux/include/linux/msg.h	Sun Dec 27 22:19:28 1998
+++ linux/include/linux/msg.h	Tue May 11 14:37:40 1999
@@ -19,8 +19,8 @@
 	__kernel_time_t msg_stime;	/* last msgsnd time */
 	__kernel_time_t msg_rtime;	/* last msgrcv time */
 	__kernel_time_t msg_ctime;	/* last change time */
-	struct wait_queue *wwait;
-	struct wait_queue *rwait;
+	wait_queue_head_t wwait;
+	wait_queue_head_t rwait;
 	unsigned short msg_cbytes;	/* current number of bytes on queue */
 	unsigned short msg_qnum;	/* number of messages in queue */
 	unsigned short msg_qbytes;	/* max number of bytes on queue */
diff -u --recursive --new-file v2.3.0/linux/include/linux/ncp_fs_sb.h linux/include/linux/ncp_fs_sb.h
--- v2.3.0/linux/include/linux/ncp_fs_sb.h	Tue May 11 13:05:50 1999
+++ linux/include/linux/ncp_fs_sb.h	Thu May 13 14:44:03 1999
@@ -44,7 +44,7 @@
 				   receive replies */
 
 	int lock;		/* To prevent mismatch in protocols. */
-	struct wait_queue *wait;
+	wait_queue_head_t wait;
 
 	int current_size;	/* for packet preparation */
 	int has_subfunction;
diff -u --recursive --new-file v2.3.0/linux/include/linux/net.h linux/include/linux/net.h
--- v2.3.0/linux/include/linux/net.h	Thu Apr 15 16:28:55 1999
+++ linux/include/linux/net.h	Thu May 13 14:42:13 1999
@@ -19,6 +19,7 @@
 #define _LINUX_NET_H
 
 #include <linux/socket.h>
+#include <linux/wait.h>
 
 struct poll_table_struct;
 
@@ -68,7 +69,7 @@
 	struct fasync_struct	*fasync_list;	/* Asynchronous wake up list	*/
 	struct file		*file;		/* File back pointer for gc	*/
 	struct sock		*sk;
-	struct wait_queue	*wait;
+	wait_queue_head_t	wait;
 
 	short			type;
 	unsigned char		passcred;
diff -u --recursive --new-file v2.3.0/linux/include/linux/nfs_fs.h linux/include/linux/nfs_fs.h
--- v2.3.0/linux/include/linux/nfs_fs.h	Tue May 11 13:04:16 1999
+++ linux/include/linux/nfs_fs.h	Thu May 13 14:42:18 1999
@@ -100,7 +100,7 @@
 	struct rpc_task		wb_task;	/* RPC task */
 	struct file *		wb_file;	/* dentry referenced */
 	struct page *		wb_page;	/* page to be written */
-	struct wait_queue *	wb_wait;	/* wait for completion */
+	wait_queue_head_t	wb_wait;	/* wait for completion */
 	unsigned int		wb_offset;	/* offset within page */
 	unsigned int		wb_bytes;	/* dirty range */
 	unsigned int		wb_count;	/* user count */
diff -u --recursive --new-file v2.3.0/linux/include/linux/nfsd/nfsfh.h linux/include/linux/nfsd/nfsfh.h
--- v2.3.0/linux/include/linux/nfsd/nfsfh.h	Tue May 11 13:04:33 1999
+++ linux/include/linux/nfsd/nfsfh.h	Thu May 13 14:42:46 1999
@@ -33,6 +33,7 @@
 	__u32		fb_dev;		/* our device */
 	__u32		fb_xdev;
 	__u32		fb_xino;
+	__u32		fb_generation;
 };
 
 #define NFS_FH_PADDING		(NFS_FHSIZE - sizeof(struct nfs_fhbase))
@@ -47,6 +48,7 @@
 #define fh_dev			fh_base.fb_dev
 #define fh_xdev			fh_base.fb_xdev
 #define fh_xino			fh_base.fb_xino
+#define fh_generation		fh_base.fb_generation
 
 #ifdef __KERNEL__
 
diff -u --recursive --new-file v2.3.0/linux/include/linux/nfsiod.h linux/include/linux/nfsiod.h
--- v2.3.0/linux/include/linux/nfsiod.h	Thu Feb  6 02:58:05 1997
+++ linux/include/linux/nfsiod.h	Tue May 11 17:23:36 1999
@@ -26,7 +26,7 @@
 struct nfsiod_req {
 	struct nfsiod_req *	rq_next;
 	struct nfsiod_req *	rq_prev;
-	struct wait_queue *	rq_wait;
+	wait_queue_head_t	rq_wait;
 	struct rpc_ioreq	rq_rpcreq;
 	nfsiod_callback_t	rq_callback;
 	struct nfs_server *	rq_server;
diff -u --recursive --new-file v2.3.0/linux/include/linux/parport.h linux/include/linux/parport.h
--- v2.3.0/linux/include/linux/parport.h	Tue May 11 13:04:59 1999
+++ linux/include/linux/parport.h	Thu May 13 14:43:16 1999
@@ -163,7 +163,7 @@
 	struct pardevice *next;
 	struct pardevice *prev;
 	struct parport_state *state;     /* saved status over preemption */
-	struct wait_queue *wait_q;
+	wait_queue_head_t wait_q;
 	unsigned long int time;
 	unsigned long int timeslice;
 	unsigned int waiting;
diff -u --recursive --new-file v2.3.0/linux/include/linux/pci.h linux/include/linux/pci.h
--- v2.3.0/linux/include/linux/pci.h	Tue May 11 13:03:59 1999
+++ linux/include/linux/pci.h	Thu May 13 14:42:14 1999
@@ -516,6 +516,7 @@
 
 #define PCI_VENDOR_ID_PROMISE		0x105a
 #define PCI_DEVICE_ID_PROMISE_20246	0x4d33
+#define PCI_DEVICE_ID_PROMISE_20262	0x4d38
 #define PCI_DEVICE_ID_PROMISE_5300	0x5300
 
 #define PCI_VENDOR_ID_N9		0x105d
@@ -659,11 +660,14 @@
 #define PCI_DEVICE_ID_AL_M1523		0x1523
 #define PCI_DEVICE_ID_AL_M1531		0x1531
 #define PCI_DEVICE_ID_AL_M1533		0x1533
+#define PCI_DEVICE_ID_AL_M1541		0x1541
+#define PCI_DEVICE_ID_AL_M1543		0x1543
 #define PCI_DEVICE_ID_AL_M3307		0x3307
 #define PCI_DEVICE_ID_AL_M4803		0x5215
 #define PCI_DEVICE_ID_AL_M5219		0x5219
 #define PCI_DEVICE_ID_AL_M5229		0x5229
 #define PCI_DEVICE_ID_AL_M5237		0x5237
+#define PCI_DEVICE_ID_AL_M5243		0x5243
 #define PCI_DEVICE_ID_AL_M7101		0x7101
 
 #define PCI_VENDOR_ID_MITSUBISHI	0x10ba
diff -u --recursive --new-file v2.3.0/linux/include/linux/pipe_fs_i.h linux/include/linux/pipe_fs_i.h
--- v2.3.0/linux/include/linux/pipe_fs_i.h	Wed Jul 16 10:26:21 1997
+++ linux/include/linux/pipe_fs_i.h	Tue May 11 14:37:40 1999
@@ -2,7 +2,7 @@
 #define _LINUX_PIPE_FS_I_H
 
 struct pipe_inode_info {
-	struct wait_queue * wait;
+	wait_queue_head_t wait;
 	char * base;
 	unsigned int start;
 	unsigned int lock;
diff -u --recursive --new-file v2.3.0/linux/include/linux/poll.h linux/include/linux/poll.h
--- v2.3.0/linux/include/linux/poll.h	Tue May 11 13:04:26 1999
+++ linux/include/linux/poll.h	Thu May 13 14:42:21 1999
@@ -13,8 +13,8 @@
 
 struct poll_table_entry {
 	struct file * filp;
-	struct wait_queue wait;
-	struct wait_queue ** wait_address;
+	wait_queue_t wait;
+	wait_queue_head_t * wait_address;
 };
 
 typedef struct poll_table_struct {
@@ -25,9 +25,9 @@
 
 #define __MAX_POLL_TABLE_ENTRIES ((PAGE_SIZE - sizeof (poll_table)) / sizeof (struct poll_table_entry))
 
-extern void __pollwait(struct file * filp, struct wait_queue ** wait_address, poll_table *p);
+extern void __pollwait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p);
 
-extern inline void poll_wait(struct file * filp, struct wait_queue ** wait_address, poll_table *p)
+extern inline void poll_wait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p)
 {
 	if (p && wait_address)
 		__pollwait(filp, wait_address, p);
diff -u --recursive --new-file v2.3.0/linux/include/linux/quota.h linux/include/linux/quota.h
--- v2.3.0/linux/include/linux/quota.h	Thu Jan 14 22:56:06 1999
+++ linux/include/linux/quota.h	Thu May 13 14:29:31 1999
@@ -170,7 +170,7 @@
 	struct list_head dq_free;	/* free list element */
 	struct dquot *dq_hash_next;	/* Pointer to next in dquot_hash */
 	struct dquot **dq_hash_pprev;	/* Pointer to previous in dquot_hash */
-	struct wait_queue *dq_wait;	/* Pointer to waitqueue */
+	wait_queue_head_t dq_wait;	/* Pointer to waitqueue */
 	int dq_count;			/* Reference count */
 
 	/* fields after this point are cleared when invalidating */
diff -u --recursive --new-file v2.3.0/linux/include/linux/raid5.h linux/include/linux/raid5.h
--- v2.3.0/linux/include/linux/raid5.h	Fri May  8 00:17:13 1998
+++ linux/include/linux/raid5.h	Wed May 12 08:41:15 1999
@@ -35,7 +35,7 @@
 	int			count;			/* nr of waiters */
 	int			write_method;		/* reconstruct-write / read-modify-write */
 	int			phase;			/* PHASE_BEGIN, ..., PHASE_COMPLETE */
-	struct wait_queue	*wait;			/* processes waiting for this stripe */
+	wait_queue_head_t	wait;			/* processes waiting for this stripe */
 };
 
 /*
@@ -94,7 +94,7 @@
 	 */
 	int			nr_free_sh;
 	struct stripe_head	*free_sh_list;
-	struct wait_queue	*wait_for_stripe;
+	wait_queue_head_t	wait_for_stripe;
 };
 
 #endif
diff -u --recursive --new-file v2.3.0/linux/include/linux/rtnetlink.h linux/include/linux/rtnetlink.h
--- v2.3.0/linux/include/linux/rtnetlink.h	Sun Mar 21 07:22:00 1999
+++ linux/include/linux/rtnetlink.h	Tue May 11 14:37:40 1999
@@ -511,7 +511,7 @@
 #ifdef __KERNEL__
 
 extern atomic_t rtnl_rlockct;
-extern struct wait_queue *rtnl_wait;
+extern wait_queue_head_t rtnl_wait;
 
 extern __inline__ int rtattr_strcmp(struct rtattr *rta, char *str)
 {
diff -u --recursive --new-file v2.3.0/linux/include/linux/sched.h linux/include/linux/sched.h
--- v2.3.0/linux/include/linux/sched.h	Tue May 11 13:04:01 1999
+++ linux/include/linux/sched.h	Thu May 13 14:42:16 1999
@@ -79,6 +79,7 @@
 #define TASK_ZOMBIE		4
 #define TASK_STOPPED		8
 #define TASK_SWAPPING		16
+#define TASK_EXCLUSIVE		32
 
 /*
  * Scheduling policies
@@ -184,11 +185,11 @@
 	void * segments;
 };
 
-#define INIT_MM {					\
+#define INIT_MM(name) {					\
 		&init_mmap, NULL, NULL,			\
 		swapper_pg_dir, 			\
 		ATOMIC_INIT(1), 1,			\
-		MUTEX,					\
+		__MUTEX_INITIALIZER(name.mmap_sem),	\
 		0,					\
 		0, 0, 0, 0,				\
 		0, 0, 0, 				\
@@ -267,7 +268,7 @@
 	/* Pointer to task[] array linkage. */
 	struct task_struct **tarray_ptr;
 
-	struct wait_queue *wait_chldexit;	/* for wait4() */
+	wait_queue_head_t wait_chldexit;	/* for wait4() */
 	struct semaphore *vfork_sem;		/* for vfork() */
 	unsigned long policy, rt_priority;
 	unsigned long it_real_value, it_prof_value, it_virt_value;
@@ -345,7 +346,7 @@
  *  INIT_TASK is used to set up the first task table, touch at
  * your own risk!. Base=0, limit=0x1fffff (=2MB)
  */
-#define INIT_TASK \
+#define INIT_TASK(name) \
 /* state etc */	{ 0,0,0,KERNEL_DS,&default_exec_domain,0, \
 /* counter */	DEF_PRIORITY,DEF_PRIORITY,0, \
 /* SMP */	0,0,0,-1, \
@@ -356,7 +357,7 @@
 /* proc links*/ &init_task,&init_task,NULL,NULL,NULL, \
 /* pidhash */	NULL, NULL, \
 /* tarray */	&task[0], \
-/* chld wait */	NULL, NULL, \
+/* chld wait */	__WAIT_QUEUE_HEAD_INITIALIZER(name.wait_chldexit), NULL, \
 /* timeout */	SCHED_OTHER,0,0,0,0,0,0,0, \
 /* timer */	{ NULL, NULL, 0, 0, it_real_fn }, \
 /* utime */	{0,0,0,0},0, \
@@ -464,12 +465,12 @@
 
 #define CURRENT_TIME (xtime.tv_sec)
 
-extern void FASTCALL(__wake_up(struct wait_queue ** p, unsigned int mode));
-extern void FASTCALL(sleep_on(struct wait_queue ** p));
-extern long FASTCALL(sleep_on_timeout(struct wait_queue ** p,
+extern void FASTCALL(__wake_up(wait_queue_head_t *q, unsigned int mode));
+extern void FASTCALL(sleep_on(wait_queue_head_t *q));
+extern long FASTCALL(sleep_on_timeout(wait_queue_head_t *q,
 				      signed long timeout));
-extern void FASTCALL(interruptible_sleep_on(struct wait_queue ** p));
-extern long FASTCALL(interruptible_sleep_on_timeout(struct wait_queue ** p,
+extern void FASTCALL(interruptible_sleep_on(wait_queue_head_t *q));
+extern long FASTCALL(interruptible_sleep_on_timeout(wait_queue_head_t *q,
 						    signed long timeout));
 extern void FASTCALL(wake_up_process(struct task_struct * tsk));
 
@@ -630,54 +631,39 @@
 extern int do_execve(char *, char **, char **, struct pt_regs *);
 extern int do_fork(unsigned long, unsigned long, struct pt_regs *);
 
-/*
- * The wait-queues are circular lists, and you have to be *very* sure
- * to keep them correct. Use only these two functions to add/remove
- * entries in the queues.
- */
-extern inline void __add_wait_queue(struct wait_queue ** p, struct wait_queue * wait)
-{
-	wait->next = *p ? : WAIT_QUEUE_HEAD(p);
-	*p = wait;
-}
-
-extern rwlock_t waitqueue_lock;
-
-extern inline void add_wait_queue(struct wait_queue ** p, struct wait_queue * wait)
+extern inline void add_wait_queue(wait_queue_head_t *q, wait_queue_t * wait)
 {
 	unsigned long flags;
 
-	write_lock_irqsave(&waitqueue_lock, flags);
-	__add_wait_queue(p, wait);
-	write_unlock_irqrestore(&waitqueue_lock, flags);
+	wq_write_lock_irqsave(&q->lock, flags);
+	__add_wait_queue(q, wait);
+	wq_write_unlock_irqrestore(&q->lock, flags);
 }
 
-extern inline void __remove_wait_queue(struct wait_queue ** p, struct wait_queue * wait)
+extern inline void add_wait_queue_exclusive(wait_queue_head_t *q,
+							wait_queue_t * wait)
 {
-	struct wait_queue * next = wait->next;
-	struct wait_queue * head = next;
-	struct wait_queue * tmp;
+	unsigned long flags;
 
-	while ((tmp = head->next) != wait) {
-		head = tmp;
-	}
-	head->next = next;
+	wq_write_lock_irqsave(&q->lock, flags);
+	__add_wait_queue_tail(q, wait);
+	wq_write_unlock_irqrestore(&q->lock, flags);
 }
 
-extern inline void remove_wait_queue(struct wait_queue ** p, struct wait_queue * wait)
+extern inline void remove_wait_queue(wait_queue_head_t *q, wait_queue_t * wait)
 {
 	unsigned long flags;
 
-	write_lock_irqsave(&waitqueue_lock, flags);
-	__remove_wait_queue(p, wait);
-	write_unlock_irqrestore(&waitqueue_lock, flags); 
+	wq_write_lock_irqsave(&q->lock, flags);
+	__remove_wait_queue(q, wait);
+	wq_write_unlock_irqrestore(&q->lock, flags);
 }
 
 #define __wait_event(wq, condition) 					\
 do {									\
-	struct wait_queue __wait;					\
+	wait_queue_t __wait;						\
+	init_waitqueue_entry(&__wait, current);				\
 									\
-	__wait.task = current;						\
 	add_wait_queue(&wq, &__wait);					\
 	for (;;) {							\
 		current->state = TASK_UNINTERRUPTIBLE;			\
@@ -698,9 +684,9 @@
 
 #define __wait_event_interruptible(wq, condition, ret)			\
 do {									\
-	struct wait_queue __wait;					\
+	wait_queue_t __wait;						\
+	init_waitqueue_entry(&__wait, current);				\
 									\
-	__wait.task = current;						\
 	add_wait_queue(&wq, &__wait);					\
 	for (;;) {							\
 		current->state = TASK_INTERRUPTIBLE;			\
diff -u --recursive --new-file v2.3.0/linux/include/linux/sem.h linux/include/linux/sem.h
--- v2.3.0/linux/include/linux/sem.h	Sun Dec 27 22:18:29 1998
+++ linux/include/linux/sem.h	Tue May 11 14:37:40 1999
@@ -85,7 +85,7 @@
 struct sem_queue {
 	struct sem_queue *	next;	 /* next entry in the queue */
 	struct sem_queue **	prev;	 /* previous entry in the queue, *(q->prev) == q */
-	struct wait_queue *	sleeper; /* sleeping process */
+	wait_queue_head_t	sleeper; /* sleeping process */
 	struct sem_undo *	undo;	 /* undo structure */
 	int    			pid;	 /* process id of requesting process */
 	int    			status;	 /* completion status of operation */
diff -u --recursive --new-file v2.3.0/linux/include/linux/serialP.h linux/include/linux/serialP.h
--- v2.3.0/linux/include/linux/serialP.h	Tue May 11 13:04:00 1999
+++ linux/include/linux/serialP.h	Thu May 13 14:42:14 1999
@@ -80,9 +80,9 @@
 	int			xmit_tail;
 	int			xmit_cnt;
 	struct tq_struct	tqueue;
-	struct wait_queue	*open_wait;
-	struct wait_queue	*close_wait;
-	struct wait_queue	*delta_msr_wait;
+	wait_queue_head_t	open_wait;
+	wait_queue_head_t	close_wait;
+	wait_queue_head_t	delta_msr_wait;
 	struct async_struct	*next_port; /* For the linked list */
 	struct async_struct	*prev_port;
 };
diff -u --recursive --new-file v2.3.0/linux/include/linux/skbuff.h linux/include/linux/skbuff.h
--- v2.3.0/linux/include/linux/skbuff.h	Tue May 11 13:04:59 1999
+++ linux/include/linux/skbuff.h	Thu May 13 14:42:54 1999
@@ -449,6 +449,14 @@
  *	Add data to an sk_buff
  */
  
+extern __inline__ unsigned char *__skb_put(struct sk_buff *skb, unsigned int len)
+{
+	unsigned char *tmp=skb->tail;
+	skb->tail+=len;
+	skb->len+=len;
+	return tmp;
+}
+
 extern __inline__ unsigned char *skb_put(struct sk_buff *skb, unsigned int len)
 {
 	unsigned char *tmp=skb->tail;
@@ -461,6 +469,13 @@
 here:		;
 	}
 	return tmp;
+}
+
+extern __inline__ unsigned char *__skb_push(struct sk_buff *skb, unsigned int len)
+{
+	skb->data-=len;
+	skb->len+=len;
+	return skb->data;
 }
 
 extern __inline__ unsigned char *skb_push(struct sk_buff *skb, unsigned int len)
diff -u --recursive --new-file v2.3.0/linux/include/linux/smb_fs_sb.h linux/include/linux/smb_fs_sb.h
--- v2.3.0/linux/include/linux/smb_fs_sb.h	Sun Dec 27 22:18:28 1998
+++ linux/include/linux/smb_fs_sb.h	Wed May 12 08:41:15 1999
@@ -34,7 +34,7 @@
 	struct smb_conn_opt opt;
 
 	struct semaphore sem;
-	struct wait_queue * wait;
+	wait_queue_head_t wait;
 
 	__u32              packet_size;
 	unsigned char *    packet;
diff -u --recursive --new-file v2.3.0/linux/include/linux/sunrpc/sched.h linux/include/linux/sunrpc/sched.h
--- v2.3.0/linux/include/linux/sunrpc/sched.h	Tue May 11 13:04:01 1999
+++ linux/include/linux/sunrpc/sched.h	Thu May 13 14:42:15 1999
@@ -12,6 +12,7 @@
 #include <linux/timer.h>
 #include <linux/tqueue.h>
 #include <linux/sunrpc/types.h>
+#include <linux/wait.h>
 
 /*
  * Define this if you want to test the fast scheduler for async calls.
@@ -63,7 +64,7 @@
 	 * you have a pathological interest in kernel oopses.
 	 */
 	struct timer_list	tk_timer;	/* kernel timer */
-	struct wait_queue *	tk_wait;	/* sync: sleep on this q */
+	wait_queue_head_t	tk_wait;	/* sync: sleep on this q */
 	unsigned long		tk_timeout;	/* timeout for rpc_sleep() */
 	unsigned short		tk_flags;	/* misc flags */
 #ifdef RPC_DEBUG
diff -u --recursive --new-file v2.3.0/linux/include/linux/sunrpc/svc.h linux/include/linux/sunrpc/svc.h
--- v2.3.0/linux/include/linux/sunrpc/svc.h	Tue May 11 13:04:29 1999
+++ linux/include/linux/sunrpc/svc.h	Thu May 13 14:42:41 1999
@@ -116,7 +116,7 @@
 	struct svc_client *	rq_client;	/* RPC peer info */
 	struct svc_cacherep *	rq_cacherep;	/* cache info */
 
-	struct wait_queue *	rq_wait;	/* synchronozation */
+	wait_queue_head_t	rq_wait;	/* synchronozation */
 };
 
 /*
diff -u --recursive --new-file v2.3.0/linux/include/linux/tty.h linux/include/linux/tty.h
--- v2.3.0/linux/include/linux/tty.h	Tue May 11 13:04:00 1999
+++ linux/include/linux/tty.h	Thu May 13 14:42:15 1999
@@ -272,8 +272,8 @@
 	struct tty_flip_buffer flip;
 	int max_flip_cnt;
 	int alt_speed;		/* For magic substitution of 38400 bps */
-	struct wait_queue *write_wait;
-	struct wait_queue *read_wait;
+	wait_queue_head_t write_wait;
+	wait_queue_head_t read_wait;
 	struct tq_struct tq_hangup;
 	void *disc_data;
 	void *driver_data;
diff -u --recursive --new-file v2.3.0/linux/include/linux/videodev.h linux/include/linux/videodev.h
--- v2.3.0/linux/include/linux/videodev.h	Fri May  7 11:05:30 1999
+++ linux/include/linux/videodev.h	Thu May 13 14:28:30 1999
@@ -278,6 +278,7 @@
 #define VID_HARDWARE_TYPHOON	19
 #define VID_HARDWARE_VINO	20	/* Reserved for SGI Indy Vino */
 #define VID_HARDWARE_CADET	21	/* Cadet radio */
+#define VID_HARDWARE_CPIA	22
 
 /*
  *	Initialiser list
diff -u --recursive --new-file v2.3.0/linux/include/linux/vt_kern.h linux/include/linux/vt_kern.h
--- v2.3.0/linux/include/linux/vt_kern.h	Tue May 11 13:03:59 1999
+++ linux/include/linux/vt_kern.h	Thu May 13 14:42:14 1999
@@ -27,7 +27,7 @@
 	struct vt_mode	vt_mode;
 	int		vt_pid;
 	int		vt_newvt;
-	struct wait_queue *paste_wait;
+	wait_queue_head_t paste_wait;
 } *vt_cons[MAX_NR_CONSOLES];
 
 void (*kd_mksound)(unsigned int hz, unsigned int ticks);
diff -u --recursive --new-file v2.3.0/linux/include/linux/wait.h linux/include/linux/wait.h
--- v2.3.0/linux/include/linux/wait.h	Tue Jan 26 15:19:44 1999
+++ linux/include/linux/wait.h	Thu May 13 14:42:12 1999
@@ -9,23 +9,190 @@
 #ifdef __KERNEL__
 
 #include <asm/page.h>
+#include <asm/spinlock.h>
+#include <linux/list.h>
+#include <linux/stddef.h>
 
-struct wait_queue {
+/*
+ * Temporary debugging help until all code is converted to the new
+ * waitqueue usage.
+ */
+#define WAITQUEUE_DEBUG 1
+
+#if WAITQUEUE_DEBUG
+extern int printk(const char *fmt, ...);
+#define WQ_BUG() do { \
+	printk("wq bug, forcing oops.\n"); \
+	*(int*)0 = 0; \
+} while (0)
+
+#define CHECK_MAGIC(x) if (x != (long)&(x)) \
+	{ printk("bad magic %lx (should be %lx), ", (long)x, (long)&(x)); WQ_BUG(); }
+
+#define CHECK_MAGIC_WQHEAD(x) do { \
+	if (x->__magic != (long)&(x->__magic)) { \
+		printk("bad magic %lx (should be %lx, creator %lx), ", \
+			x->__magic, (long)&(x->__magic), x->__creator); \
+		WQ_BUG(); \
+	} \
+} while (0)
+#endif
+
+struct __wait_queue {
+	unsigned int compiler_warning;
 	struct task_struct * task;
-	struct wait_queue * next;
+	struct list_head task_list;
+#if WAITQUEUE_DEBUG
+	long __magic;
+	long __waker;
+#endif
 };
+typedef struct __wait_queue wait_queue_t;
+
+/*
+ * 'dual' spinlock architecture. Can be switched between spinlock_t and
+ * rwlock_t locks via changing this define. Since waitqueues are quite
+ * decoupled in the new architecture, lightweight 'simple' spinlocks give
+ * us slightly better latencies and smaller waitqueue structure size.
+ */
+#define USE_RW_WAIT_QUEUE_SPINLOCK 0
+
+#if USE_RW_WAIT_QUEUE_SPINLOCK
+# define wq_lock_t rwlock_t
+# define WAITQUEUE_RW_LOCK_UNLOCKED RW_LOCK_UNLOCKED
+
+# define wq_read_lock read_lock
+# define wq_read_lock_irqsave read_lock_irqsave
+# define wq_read_unlock_irqrestore read_unlock_irqrestore
+# define wq_read_unlock read_unlock
+# define wq_write_lock_irq write_lock_irq
+# define wq_write_lock_irqsave write_lock_irqsave
+# define wq_write_unlock_irqrestore write_unlock_irqrestore
+# define wq_write_unlock write_unlock
+#else
+# define wq_lock_t spinlock_t
+# define WAITQUEUE_RW_LOCK_UNLOCKED SPIN_LOCK_UNLOCKED
+
+# define wq_read_lock spin_lock
+# define wq_read_lock_irqsave spin_lock_irqsave
+# define wq_read_unlock spin_unlock
+# define wq_read_unlock_irqrestore spin_unlock_irqrestore
+# define wq_write_lock_irq spin_lock_irq
+# define wq_write_lock_irqsave spin_lock_irqsave
+# define wq_write_unlock_irqrestore spin_unlock_irqrestore
+# define wq_write_unlock spin_unlock
+#endif
+
+struct __wait_queue_head {
+	wq_lock_t lock;
+	struct list_head task_list;
+#if WAITQUEUE_DEBUG
+	long __magic;
+	long __creator;
+#endif
+};
+typedef struct __wait_queue_head wait_queue_head_t;
+
+#if WAITQUEUE_DEBUG
+# define __WAITQUEUE_DEBUG_INIT(name) \
+		, (long)&(name).__magic, 0
+# define __WAITQUEUE_HEAD_DEBUG_INIT(name) \
+		, (long)&(name).__magic, (long)&(name).__magic
+#else
+# define __WAITQUEUE_DEBUG_INIT(name)
+# define __WAITQUEUE_HEAD_DEBUG_INIT(name)
+#endif
+
+#define __WAITQUEUE_INITIALIZER(name,task) \
+	{ 0x1234567, task, { NULL, NULL } __WAITQUEUE_DEBUG_INIT(name)}
+#define DECLARE_WAITQUEUE(name,task) \
+	wait_queue_t name = __WAITQUEUE_INITIALIZER(name,task)
+
+#define __WAIT_QUEUE_HEAD_INITIALIZER(name) \
+{ WAITQUEUE_RW_LOCK_UNLOCKED, { &(name).task_list, &(name).task_list } \
+		__WAITQUEUE_HEAD_DEBUG_INIT(name)}
 
-#define WAIT_QUEUE_HEAD(x) ((struct wait_queue *)((x)-1))
+#define DECLARE_WAIT_QUEUE_HEAD(name) \
+	wait_queue_head_t name = __WAIT_QUEUE_HEAD_INITIALIZER(name)
+
+static inline void init_waitqueue_head(wait_queue_head_t *q)
+{
+#if WAITQUEUE_DEBUG
+	__label__ __x;
+	if (!q)
+		WQ_BUG();
+#endif
+	q->lock = WAITQUEUE_RW_LOCK_UNLOCKED;
+	INIT_LIST_HEAD(&q->task_list);
+#if WAITQUEUE_DEBUG
+	q->__magic = (long)&q->__magic;
+	__x: q->__creator = (long)&&__x;
+#endif
+}
+
+static inline void init_waitqueue_entry(wait_queue_t *q,
+				 struct task_struct *p)
+{
+#if WAITQUEUE_DEBUG
+	if (!q || !p)
+		WQ_BUG();
+#endif
+	q->task = p;
+#if WAITQUEUE_DEBUG
+	q->__magic = (long)&q->__magic;
+#endif
+}
+
+static inline int waitqueue_active(wait_queue_head_t *q)
+{
+#if WAITQUEUE_DEBUG
+	if (!q)
+		WQ_BUG();
+	CHECK_MAGIC_WQHEAD(q);
+#endif
+
+	return !list_empty(&q->task_list);
+}
+
+extern inline void __add_wait_queue(wait_queue_head_t *head, wait_queue_t *new)
+{
+#if WAITQUEUE_DEBUG
+	if (!head || !new)
+		WQ_BUG();
+	CHECK_MAGIC_WQHEAD(head);
+	CHECK_MAGIC(new->__magic);
+	if (!head->task_list.next || !head->task_list.prev)
+		WQ_BUG();
+#endif
+	list_add(&new->task_list, &head->task_list);
+}
 
-static inline void init_waitqueue(struct wait_queue **q)
+/*
+ * Used for wake-one threads:
+ */
+extern inline void __add_wait_queue_tail(wait_queue_head_t *head,
+						wait_queue_t *new)
 {
-	*q = WAIT_QUEUE_HEAD(q);
+#if WAITQUEUE_DEBUG
+	if (!head || !new)
+		WQ_BUG();
+	CHECK_MAGIC_WQHEAD(head);
+	CHECK_MAGIC(new->__magic);
+	if (!head->task_list.next || !head->task_list.prev)
+		WQ_BUG();
+#endif
+	list_add(&new->task_list, head->task_list.prev);
 }
 
-static inline int waitqueue_active(struct wait_queue **q)
+extern inline void __remove_wait_queue(wait_queue_head_t *head,
+							wait_queue_t *old)
 {
-	struct wait_queue *head = *q;
-	return head && head != WAIT_QUEUE_HEAD(q);
+#if WAITQUEUE_DEBUG
+	if (!old)
+		WQ_BUG();
+	CHECK_MAGIC(old->__magic);
+#endif
+	list_del(&old->task_list);
 }
 
 #endif /* __KERNEL__ */
diff -u --recursive --new-file v2.3.0/linux/include/net/irda/ircomm_common.h linux/include/net/irda/ircomm_common.h
--- v2.3.0/linux/include/net/irda/ircomm_common.h	Sat Apr 24 17:50:05 1999
+++ linux/include/net/irda/ircomm_common.h	Wed May 12 13:27:37 1999
@@ -201,8 +201,8 @@
 				see Irlmp.c or somewhere :p)*/ 
 	int peer_cap;        /* capability of peer device */
 
-	struct wait_queue   *discovery_wait;
-	struct wait_queue   *ias_wait;
+	wait_queue_head_t   discovery_wait;
+	wait_queue_head_t   ias_wait;
 
 	/* statistics */
 	int                 tx_packets;
diff -u --recursive --new-file v2.3.0/linux/include/net/irda/irda.h linux/include/net/irda/irda.h
--- v2.3.0/linux/include/net/irda/irda.h	Tue May 11 13:05:03 1999
+++ linux/include/net/irda/irda.h	Thu May 13 14:43:11 1999
@@ -122,7 +122,7 @@
 	int errno;
 
 	struct sock *sk;
-	struct wait_queue *ias_wait;       /* Wait for LM-IAS answer */
+	wait_queue_head_t ias_wait;       /* Wait for LM-IAS answer */
 
 	LOCAL_FLOW tx_flow;
 	LOCAL_FLOW rx_flow;
diff -u --recursive --new-file v2.3.0/linux/include/net/irda/irlpt_common.h linux/include/net/irda/irlpt_common.h
--- v2.3.0/linux/include/net/irda/irlpt_common.h	Sun Mar  7 15:26:43 1999
+++ linux/include/net/irda/irlpt_common.h	Wed May 12 13:27:37 1999
@@ -46,7 +46,7 @@
 extern char *irlpt_server_fsm_state[];
 extern char *irlpt_fsm_event[];
 
-extern struct wait_queue *lpt_wait;
+extern wait_queue_head_t lpt_wait;
 
 extern struct irlpt_cb *irlpt_find_handle(unsigned int minor);
 extern void irlpt_flow_control(struct sk_buff *skb);
@@ -161,9 +161,9 @@
 	int irlap_data_size;	/* max frame size we can send */
 	int pkt_count;		/* how many packets are queued up */
 
-	struct wait_queue *read_wait;	/* wait queues */
-	struct wait_queue *write_wait;
-	struct wait_queue *ex_wait;
+	wait_queue_head_t read_wait;	/* wait queues */
+	wait_queue_head_t write_wait;
+	wait_queue_head_t ex_wait;
 
 	/* this is used to remove the printer when it's gone */
 	struct timer_list lpt_timer;
diff -u --recursive --new-file v2.3.0/linux/include/net/irda/irmod.h linux/include/net/irda/irmod.h
--- v2.3.0/linux/include/net/irda/irmod.h	Sat Apr 24 17:50:06 1999
+++ linux/include/net/irda/irmod.h	Wed May 12 13:27:37 1999
@@ -90,7 +90,7 @@
  */
 struct irda_cb {
 	struct miscdevice dev;	
-	struct wait_queue *wait_queue;
+	wait_queue_head_t *wait_queue;
 
 	int in_use;
 
diff -u --recursive --new-file v2.3.0/linux/include/net/irda/irvtd.h linux/include/net/irda/irvtd.h
--- v2.3.0/linux/include/net/irda/irvtd.h	Thu Apr 15 05:42:42 1999
+++ linux/include/net/irda/irvtd.h	Wed May 12 13:27:37 1999
@@ -64,10 +64,10 @@
 	int line;
 	int count;                /* open count */
 	int blocked_open;
-	struct wait_queue       *open_wait;
-	struct wait_queue       *close_wait;
-	struct wait_queue       *delta_msr_wait;
-	struct wait_queue       *tx_wait;
+	wait_queue_head_t       open_wait;
+	wait_queue_head_t       close_wait;
+	wait_queue_head_t       delta_msr_wait;
+	wait_queue_head_t       tx_wait;
 
 	struct timer_list       timer;
 
diff -u --recursive --new-file v2.3.0/linux/include/net/sock.h linux/include/net/sock.h
--- v2.3.0/linux/include/net/sock.h	Tue May 11 13:05:13 1999
+++ linux/include/net/sock.h	Thu May 13 14:43:15 1999
@@ -384,7 +384,7 @@
 	atomic_t		sock_readers;	/* User count				*/
 	int			rcvbuf;		/* Size of receive buffer in bytes	*/
 
-	struct wait_queue	**sleep;	/* Sock wait queue			*/
+	wait_queue_head_t	*sleep;	/* Sock wait queue			*/
 	struct dst_entry	*dst_cache;	/* Destination cache			*/
 	atomic_t		rmem_alloc;	/* Receive queue bytes committed	*/
 	struct sk_buff_head	receive_queue;	/* Incoming packets			*/
diff -u --recursive --new-file v2.3.0/linux/include/net/tcp.h linux/include/net/tcp.h
--- v2.3.0/linux/include/net/tcp.h	Tue May 11 13:05:25 1999
+++ linux/include/net/tcp.h	Thu May 13 14:43:21 1999
@@ -728,7 +728,7 @@
  */
 extern __inline__ __u32 tcp_recalc_ssthresh(struct tcp_opt *tp)
 {
-	__u32 snd_wnd_packets = tp->snd_wnd / tp->mss_cache;
+	__u32 snd_wnd_packets = tp->snd_wnd / max(tp->mss_cache, 1);
 
 	return max(min(snd_wnd_packets, tp->snd_cwnd) >> 1, 2);
 }
diff -u --recursive --new-file v2.3.0/linux/init/main.c linux/init/main.c
--- v2.3.0/linux/init/main.c	Tue May 11 09:57:14 1999
+++ linux/init/main.c	Thu May 13 11:00:09 1999
@@ -416,6 +416,10 @@
 	{ "hdj",     0x3840 },
 	{ "hdk",     0x3900 },
 	{ "hdl",     0x3940 },
+	{ "hdm",     0x5800 },
+	{ "hdn",     0x5840 },
+	{ "hdo",     0x5900 },
+	{ "hdp",     0x5940 },
 #endif
 #ifdef CONFIG_BLK_DEV_SD
 	{ "sda",     0x0800 },
@@ -929,7 +933,11 @@
 
 #ifdef CONFIG_BLK_DEV_IDE
 	/* ide driver needs the basic string, rather than pre-processed values */
-	if (!strncmp(line,"ide",3) || (!strncmp(line,"hd",2) && line[2] != '=')) {
+	if (!strncmp(line,"ide",3) ||
+#ifdef CONFIG_BLK_DEV_VIA82C586
+	    !strncmp(line,"splitfifo",9) ||
+#endif /* CONFIG_BLK_DEV_VIA82C586 */
+	    (!strncmp(line,"hd",2) && line[2] != '=')) {
 		ide_setup(line);
 		return 1;
 	}
diff -u --recursive --new-file v2.3.0/linux/ipc/msg.c linux/ipc/msg.c
--- v2.3.0/linux/ipc/msg.c	Fri Nov 20 11:43:19 1998
+++ linux/ipc/msg.c	Tue May 11 14:37:40 1999
@@ -30,7 +30,7 @@
 static unsigned short msg_seq = 0;
 static int used_queues = 0;
 static int max_msqid = 0;
-static struct wait_queue *msg_lock = NULL;
+static DECLARE_WAIT_QUEUE_HEAD(msg_lock);
 
 void __init msg_init (void)
 {
@@ -39,7 +39,7 @@
 	for (id = 0; id < MSGMNI; id++) 
 		msgque[id] = (struct msqid_ds *) IPC_UNUSED;
 	msgbytes = msghdrs = msg_seq = max_msqid = used_queues = 0;
-	msg_lock = NULL;
+	init_waitqueue_head(&msg_lock);
 	return;
 }
 
@@ -284,7 +284,8 @@
 	ipcp->gid = ipcp->cgid = current->egid;
 	msq->msg_perm.seq = msg_seq;
 	msq->msg_first = msq->msg_last = NULL;
-	msq->rwait = msq->wwait = NULL;
+	init_waitqueue_head(&msq->wwait);
+	init_waitqueue_head(&msq->rwait);
 	msq->msg_cbytes = msq->msg_qnum = 0;
 	msq->msg_lspid = msq->msg_lrpid = 0;
 	msq->msg_stime = msq->msg_rtime = 0;
diff -u --recursive --new-file v2.3.0/linux/ipc/sem.c linux/ipc/sem.c
--- v2.3.0/linux/ipc/sem.c	Sat Jan  9 19:16:44 1999
+++ linux/ipc/sem.c	Tue May 11 14:37:40 1999
@@ -63,7 +63,7 @@
 
 static struct semid_ds *semary[SEMMNI];
 static int used_sems = 0, used_semids = 0;
-static struct wait_queue *sem_lock = NULL;
+static DECLARE_WAIT_QUEUE_HEAD(sem_lock);
 static int max_semid = 0;
 
 static unsigned short sem_seq = 0;
@@ -72,7 +72,7 @@
 {
 	int i;
 
-	sem_lock = NULL;
+	init_waitqueue_head(&sem_lock);
 	used_sems = used_semids = max_semid = sem_seq = 0;
 	for (i = 0; i < SEMMNI; i++)
 		semary[i] = (struct semid_ds *) IPC_UNUSED;
@@ -690,7 +690,7 @@
 
         for (;;) {
                 queue.status = -EINTR;
-                queue.sleeper = NULL;
+                init_waitqueue_head(&queue.sleeper);
                 interruptible_sleep_on(&queue.sleeper);
 
                 /*
diff -u --recursive --new-file v2.3.0/linux/ipc/shm.c linux/ipc/shm.c
--- v2.3.0/linux/ipc/shm.c	Tue May  4 16:58:15 1999
+++ linux/ipc/shm.c	Tue May 11 14:37:40 1999
@@ -31,7 +31,7 @@
 static int shm_rss = 0; /* number of shared memory pages that are in memory */
 static int shm_swp = 0; /* number of shared memory pages that are in swap */
 static int max_shmid = 0; /* every used id is <= max_shmid */
-static struct wait_queue *shm_lock = NULL; /* calling findkey() may need to wait */
+static DECLARE_WAIT_QUEUE_HEAD(shm_lock); /* calling findkey() may need to wait */
 static struct shmid_kernel *shm_segs[SHMMNI];
 
 static unsigned short shm_seq = 0; /* incremented, for recognizing stale ids */
@@ -48,7 +48,7 @@
 	for (id = 0; id < SHMMNI; id++)
 		shm_segs[id] = (struct shmid_kernel *) IPC_UNUSED;
 	shm_tot = shm_rss = shm_seq = max_shmid = used_segs = 0;
-	shm_lock = NULL;
+	init_waitqueue_head(&shm_lock);
 	return;
 }
 
diff -u --recursive --new-file v2.3.0/linux/kernel/exit.c linux/kernel/exit.c
--- v2.3.0/linux/kernel/exit.c	Fri Apr 30 08:13:37 1999
+++ linux/kernel/exit.c	Tue May 11 14:37:40 1999
@@ -406,7 +406,7 @@
 asmlinkage int sys_wait4(pid_t pid,unsigned int * stat_addr, int options, struct rusage * ru)
 {
 	int flag, retval;
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 	struct task_struct *p;
 
 	if (options & ~(WNOHANG|WUNTRACED|__WCLONE))
diff -u --recursive --new-file v2.3.0/linux/kernel/fork.c linux/kernel/fork.c
--- v2.3.0/linux/kernel/fork.c	Mon Apr 12 12:44:26 1999
+++ linux/kernel/fork.c	Tue May 11 14:37:40 1999
@@ -303,7 +303,7 @@
 		atomic_set(&mm->count, 1);
 		mm->map_count = 0;
 		mm->def_flags = 0;
-		mm->mmap_sem = MUTEX_LOCKED;
+		init_MUTEX_LOCKED(&mm->mmap_sem);
 		/*
 		 * Leave mm->pgd set to the parent's pgd
 		 * so that pgd_offset() is always valid.
@@ -536,7 +536,7 @@
 	int nr;
 	int retval = -ENOMEM;
 	struct task_struct *p;
-	struct semaphore sem = MUTEX_LOCKED;
+	DECLARE_MUTEX_LOCKED(sem);
 
 	current->vfork_sem = &sem;
 
@@ -589,7 +589,7 @@
 
 	p->p_pptr = p->p_opptr = current;
 	p->p_cptr = NULL;
-	init_waitqueue(&p->wait_chldexit);
+	init_waitqueue_head(&p->wait_chldexit);
 	p->vfork_sem = NULL;
 
 	p->sigpending = 0;
diff -u --recursive --new-file v2.3.0/linux/kernel/ksyms.c linux/kernel/ksyms.c
--- v2.3.0/linux/kernel/ksyms.c	Thu Apr 29 15:06:32 1999
+++ linux/kernel/ksyms.c	Tue May 11 23:01:41 1999
@@ -282,7 +282,6 @@
 #ifdef __SMP__
 /* Various random spinlocks we want to export */
 EXPORT_SYMBOL(tqueue_lock);
-EXPORT_SYMBOL(waitqueue_lock);
 #endif
 
 /* autoirq from  drivers/net/auto_irq.c */
@@ -359,6 +358,7 @@
 EXPORT_SYMBOL(refile_buffer);
 EXPORT_SYMBOL(nr_async_pages);
 EXPORT_SYMBOL(___strtok);
+EXPORT_SYMBOL(init_special_inode);
 EXPORT_SYMBOL(init_fifo);
 EXPORT_SYMBOL(fifo_inode_operations);
 EXPORT_SYMBOL(chrdev_inode_operations);
diff -u --recursive --new-file v2.3.0/linux/kernel/printk.c linux/kernel/printk.c
--- v2.3.0/linux/kernel/printk.c	Sat Mar  6 14:37:10 1999
+++ linux/kernel/printk.c	Tue May 11 14:37:40 1999
@@ -32,7 +32,7 @@
 #define DEFAULT_CONSOLE_LOGLEVEL 7 /* anything MORE serious than KERN_DEBUG */
 
 unsigned long log_size = 0;
-struct wait_queue * log_wait = NULL;
+DECLARE_WAIT_QUEUE_HEAD(log_wait);
 
 /* Keep together for sysctl support */
 int console_loglevel = DEFAULT_CONSOLE_LOGLEVEL;
diff -u --recursive --new-file v2.3.0/linux/kernel/sched.c linux/kernel/sched.c
--- v2.3.0/linux/kernel/sched.c	Mon May 10 09:55:21 1999
+++ linux/kernel/sched.c	Wed May 12 14:41:36 1999
@@ -866,52 +866,48 @@
 	return;
 }
 
-rwlock_t waitqueue_lock = RW_LOCK_UNLOCKED;
-
-/*
- * wake_up doesn't wake up stopped processes - they have to be awakened
- * with signals or similar.
- *
- * Note that we only need a read lock for the wait queue (and thus do not
- * have to protect against interrupts), as the actual removal from the
- * queue is handled by the process itself.
- */
-void __wake_up(struct wait_queue **q, unsigned int mode)
+void __wake_up(wait_queue_head_t *q, unsigned int mode)
 {
+	struct list_head *tmp, *head;
 	struct task_struct *p;
-	struct wait_queue *head, *next;
+	unsigned long flags;
 
         if (!q)
 		goto out;
-	/*
-	 * this is safe to be done before the check because it
-	 * means no deference, just pointer operations.
-	 */
-	head = WAIT_QUEUE_HEAD(q);
-
-	read_lock(&waitqueue_lock);
-	next = *q;
-	if (!next)
-		goto out_unlock;
-
-	while (next != head) {
-		p = next->task;
-		next = next->next;
-		if (p->state & mode) {
-			/*
-			 * We can drop the read-lock early if this
-			 * is the only/last process.
-			 */
-			if (next == head) {
-				read_unlock(&waitqueue_lock);
-				wake_up_process(p);
-				goto out;
-			}
+
+	wq_write_lock_irqsave(&q->lock, flags);
+
+#if WAITQUEUE_DEBUG
+	CHECK_MAGIC_WQHEAD(q);
+#endif
+
+	head = &q->task_list;
+#if WAITQUEUE_DEBUG
+        if (!head->next || !head->prev)
+                WQ_BUG();
+#endif
+	tmp = head->next;
+	while (tmp != head) {
+		unsigned int state;
+                wait_queue_t *curr = list_entry(tmp, wait_queue_t, task_list);
+
+		tmp = tmp->next;
+
+#if WAITQUEUE_DEBUG
+		CHECK_MAGIC(curr->__magic);
+#endif
+		p = curr->task;
+		state = p->state;
+		if (state & mode) {
+#if WAITQUEUE_DEBUG
+			curr->__waker = (long)__builtin_return_address(0);
+#endif
 			wake_up_process(p);
+			if (state & TASK_EXCLUSIVE)
+				break;
 		}
 	}
-out_unlock:
-	read_unlock(&waitqueue_lock);
+	wq_write_unlock_irqrestore(&q->lock, flags);
 out:
 	return;
 }
@@ -972,7 +968,8 @@
 
 #define DOWN_VAR				\
 	struct task_struct *tsk = current;	\
-	struct wait_queue wait = { tsk, NULL };
+	wait_queue_t wait;			\
+	init_waitqueue_entry(&wait, tsk);
 
 #define DOWN_HEAD(task_state)						\
 									\
@@ -1015,8 +1012,8 @@
 
 int __down_interruptible(struct semaphore * sem)
 {
-	DOWN_VAR
 	int ret = 0;
+	DOWN_VAR
 	DOWN_HEAD(TASK_INTERRUPTIBLE)
 
 	ret = waking_non_zero_interruptible(sem, tsk);
@@ -1039,20 +1036,20 @@
 
 #define	SLEEP_ON_VAR				\
 	unsigned long flags;			\
-	struct wait_queue wait;
+	wait_queue_t wait;			\
+	init_waitqueue_entry(&wait, current);
 
 #define	SLEEP_ON_HEAD					\
-	wait.task = current;				\
-	write_lock_irqsave(&waitqueue_lock,flags);	\
-	__add_wait_queue(p, &wait);			\
-	write_unlock(&waitqueue_lock);
+	wq_write_lock_irqsave(&q->lock,flags);		\
+	__add_wait_queue(q, &wait);			\
+	wq_write_unlock(&q->lock);
 
 #define	SLEEP_ON_TAIL						\
-	write_lock_irq(&waitqueue_lock);			\
-	__remove_wait_queue(p, &wait);				\
-	write_unlock_irqrestore(&waitqueue_lock,flags);
+	wq_write_lock_irq(&q->lock);				\
+	__remove_wait_queue(q, &wait);				\
+	wq_write_unlock_irqrestore(&q->lock,flags);
 
-void interruptible_sleep_on(struct wait_queue **p)
+void interruptible_sleep_on(wait_queue_head_t *q)
 {
 	SLEEP_ON_VAR
 
@@ -1063,7 +1060,7 @@
 	SLEEP_ON_TAIL
 }
 
-long interruptible_sleep_on_timeout(struct wait_queue **p, long timeout)
+long interruptible_sleep_on_timeout(wait_queue_head_t *q, long timeout)
 {
 	SLEEP_ON_VAR
 
@@ -1076,7 +1073,7 @@
 	return timeout;
 }
 
-void sleep_on(struct wait_queue **p)
+void sleep_on(wait_queue_head_t *q)
 {
 	SLEEP_ON_VAR
 	
@@ -1087,7 +1084,7 @@
 	SLEEP_ON_TAIL
 }
 
-long sleep_on_timeout(struct wait_queue **p, long timeout)
+long sleep_on_timeout(wait_queue_head_t *q, long timeout)
 {
 	SLEEP_ON_VAR
 	
@@ -1199,8 +1196,8 @@
 	read_lock(&tasklist_lock);
 	for_each_task(p) {
 		if ((p->state == TASK_RUNNING ||
-		     p->state == TASK_UNINTERRUPTIBLE ||
-		     p->state == TASK_SWAPPING))
+		     (p->state & TASK_UNINTERRUPTIBLE) ||
+		     (p->state & TASK_SWAPPING)))
 			nr += FIXED_1;
 	}
 	read_unlock(&tasklist_lock);
diff -u --recursive --new-file v2.3.0/linux/kernel/signal.c linux/kernel/signal.c
--- v2.3.0/linux/kernel/signal.c	Sun May  2 12:23:54 1999
+++ linux/kernel/signal.c	Tue May 11 14:37:40 1999
@@ -387,7 +387,7 @@
 
 out:
 	spin_unlock_irqrestore(&t->sigmask_lock, flags);
-        if (t->state == TASK_INTERRUPTIBLE && signal_pending(t))
+        if ((t->state & TASK_INTERRUPTIBLE) && signal_pending(t))
                 wake_up_process(t);
 
 out_nolock:
diff -u --recursive --new-file v2.3.0/linux/kernel/sys.c linux/kernel/sys.c
--- v2.3.0/linux/kernel/sys.c	Fri Nov 20 11:43:19 1998
+++ linux/kernel/sys.c	Tue May 11 14:37:40 1999
@@ -11,6 +11,7 @@
 #include <linux/notifier.h>
 #include <linux/reboot.h>
 #include <linux/prctl.h>
+#include <linux/init.h>
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
@@ -812,7 +813,7 @@
  * rather than a semaphore. Anybody want to implement
  * one?
  */
-struct semaphore uts_sem = MUTEX;
+DECLARE_MUTEX(uts_sem);
 
 asmlinkage int sys_newuname(struct new_utsname * name)
 {
diff -u --recursive --new-file v2.3.0/linux/mm/filemap.c linux/mm/filemap.c
--- v2.3.0/linux/mm/filemap.c	Tue May 11 08:51:13 1999
+++ linux/mm/filemap.c	Tue May 11 14:37:40 1999
@@ -48,7 +48,7 @@
 };
 static struct pio_request *pio_first = NULL, **pio_last = &pio_first;
 static kmem_cache_t *pio_request_cache;
-static struct wait_queue *pio_wait = NULL;
+static DECLARE_WAIT_QUEUE_HEAD(pio_wait);
 
 static inline void 
 make_pio_request(struct file *, unsigned long, unsigned long);
@@ -300,9 +300,8 @@
 void __wait_on_page(struct page *page)
 {
 	struct task_struct *tsk = current;
-	struct wait_queue wait;
+	DECLARE_WAITQUEUE(wait, tsk);
 
-	wait.task = tsk;
 	add_wait_queue(&page->wait, &wait);
 repeat:
 	tsk->state = TASK_UNINTERRUPTIBLE;
@@ -1677,7 +1676,7 @@
 int kpiod(void * unused)
 {
 	struct task_struct *tsk = current;
-	struct wait_queue wait = { tsk, };
+	DECLARE_WAITQUEUE(wait, tsk);
 	struct inode * inode;
 	struct dentry * dentry;
 	struct pio_request * p;
@@ -1686,7 +1685,6 @@
 	tsk->pgrp = 1;
 	strcpy(tsk->comm, "kpiod");
 	sigfillset(&tsk->blocked);
-	init_waitqueue(&pio_wait);
 	/*
 	 * Mark this task as a memory allocator - we don't want to get caught
 	 * up in the regular mm freeing frenzy if we have to allocate memory
diff -u --recursive --new-file v2.3.0/linux/mm/page_alloc.c linux/mm/page_alloc.c
--- v2.3.0/linux/mm/page_alloc.c	Thu May  6 14:32:06 1999
+++ linux/mm/page_alloc.c	Tue May 11 14:37:40 1999
@@ -323,6 +323,7 @@
 		--p;
 		atomic_set(&p->count, 0);
 		p->flags = (1 << PG_DMA) | (1 << PG_reserved);
+		init_waitqueue_head(&p->wait);
 	} while (p > mem_map);
 
 	for (i = 0 ; i < NR_MEM_LISTS ; i++) {
diff -u --recursive --new-file v2.3.0/linux/mm/page_io.c linux/mm/page_io.c
--- v2.3.0/linux/mm/page_io.c	Mon Dec 28 13:56:29 1998
+++ linux/mm/page_io.c	Tue May 11 14:37:40 1999
@@ -18,7 +18,7 @@
 
 #include <asm/pgtable.h>
 
-static struct wait_queue * lock_queue = NULL;
+static DECLARE_WAIT_QUEUE_HEAD(lock_queue);
 
 /*
  * Reads or writes a swap page.
diff -u --recursive --new-file v2.3.0/linux/mm/slab.c linux/mm/slab.c
--- v2.3.0/linux/mm/slab.c	Tue Nov 24 09:21:12 1998
+++ linux/mm/slab.c	Tue May 11 14:37:40 1999
@@ -428,7 +428,7 @@
 #undef	kmem_slab_offset
 #undef	kmem_slab_diff
 
-	cache_chain_sem = MUTEX;
+	init_MUTEX(&cache_chain_sem);
 
 	size = cache_cache.c_offset + sizeof(kmem_bufctl_t);
 	size += (L1_CACHE_BYTES-1);
diff -u --recursive --new-file v2.3.0/linux/net/core/datagram.c linux/net/core/datagram.c
--- v2.3.0/linux/net/core/datagram.c	Sun Oct  4 10:19:39 1998
+++ linux/net/core/datagram.c	Tue May 11 14:37:40 1999
@@ -54,7 +54,7 @@
 
 static inline void wait_for_packet(struct sock * sk)
 {
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 
 	add_wait_queue(sk->sleep, &wait);
 	current->state = TASK_INTERRUPTIBLE;
diff -u --recursive --new-file v2.3.0/linux/net/core/firewall.c linux/net/core/firewall.c
--- v2.3.0/linux/net/core/firewall.c	Tue Dec 29 11:21:49 1998
+++ linux/net/core/firewall.c	Wed May 12 08:31:44 1999
@@ -13,7 +13,7 @@
 #include <linux/interrupt.h>
 #include <asm/semaphore.h>
 
-struct semaphore firewall_sem = MUTEX; 
+DECLARE_MUTEX(firewall_sem);
 static int firewall_policy[NPROTO];
 static struct firewall_ops *firewall_chain[NPROTO];
 
diff -u --recursive --new-file v2.3.0/linux/net/core/rtnetlink.c linux/net/core/rtnetlink.c
--- v2.3.0/linux/net/core/rtnetlink.c	Sun Mar 21 07:22:00 1999
+++ linux/net/core/rtnetlink.c	Tue May 11 14:37:40 1999
@@ -51,7 +51,7 @@
 #include <net/pkt_sched.h>
 
 atomic_t rtnl_rlockct;
-struct wait_queue *rtnl_wait;
+DECLARE_WAIT_QUEUE_HEAD(rtnl_wait);
 
 
 void rtnl_lock()
diff -u --recursive --new-file v2.3.0/linux/net/core/sock.c linux/net/core/sock.c
--- v2.3.0/linux/net/core/sock.c	Mon May 10 09:55:25 1999
+++ linux/net/core/sock.c	Wed May 12 08:41:16 1999
@@ -7,7 +7,7 @@
  *		handler for protocols to use and generic option handler.
  *
  *
- * Version:	$Id: sock.c,v 1.80 1999/05/08 03:04:34 davem Exp $
+ * Version:	$Id: sock.c,v 1.81 1999/05/12 11:24:19 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -650,7 +650,7 @@
  */
 static void sock_wait_for_wmem(struct sock * sk)
 {
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 
 	sk->socket->flags &= ~SO_NOSPACE;
 	add_wait_queue(sk->sleep, &wait);
@@ -1036,7 +1036,8 @@
 		sk->type	=	sock->type;
 		sk->sleep	=	&sock->wait;
 		sock->sk	=	sk;
-	}
+	} else
+		sk->sleep	=	NULL;
 
 	sk->state_change	=	sock_def_wakeup;
 	sk->data_ready		=	sock_def_readable;
diff -u --recursive --new-file v2.3.0/linux/net/ipv4/af_inet.c linux/net/ipv4/af_inet.c
--- v2.3.0/linux/net/ipv4/af_inet.c	Thu Apr 22 19:45:19 1999
+++ linux/net/ipv4/af_inet.c	Wed May 12 08:41:16 1999
@@ -5,7 +5,7 @@
  *
  *		PF_INET protocol family socket handler.
  *
- * Version:	$Id: af_inet.c,v 1.87 1999/04/22 10:07:33 davem Exp $
+ * Version:	$Id: af_inet.c,v 1.88 1999/05/12 11:24:27 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -578,7 +578,7 @@
 
 static void inet_wait_for_connect(struct sock *sk)
 {
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 
 	add_wait_queue(sk->sleep, &wait);
 	current->state = TASK_INTERRUPTIBLE;
diff -u --recursive --new-file v2.3.0/linux/net/ipv4/icmp.c linux/net/ipv4/icmp.c
--- v2.3.0/linux/net/ipv4/icmp.c	Sun Mar 21 07:22:00 1999
+++ linux/net/ipv4/icmp.c	Wed May 12 08:41:16 1999
@@ -3,7 +3,7 @@
  *	
  *		Alan Cox, <alan@cymru.net>
  *
- *	Version: $Id: icmp.c,v 1.52 1999/03/21 12:04:11 davem Exp $
+ *	Version: $Id: icmp.c,v 1.53 1999/05/12 11:24:32 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License
@@ -1142,6 +1142,8 @@
 	icmp_inode.i_sock = 1;
 	icmp_inode.i_uid = 0;
 	icmp_inode.i_gid = 0;
+	init_waitqueue_head(&icmp_inode.i_wait);
+	init_waitqueue_head(&icmp_inode.u.socket_i.wait);
 
 	icmp_socket->inode = &icmp_inode;
 	icmp_socket->state = SS_UNCONNECTED;
diff -u --recursive --new-file v2.3.0/linux/net/ipv4/ip_masq_mfw.c linux/net/ipv4/ip_masq_mfw.c
--- v2.3.0/linux/net/ipv4/ip_masq_mfw.c	Mon Feb  8 09:26:29 1999
+++ linux/net/ipv4/ip_masq_mfw.c	Wed May 12 08:31:44 1999
@@ -79,7 +79,7 @@
 };
 
 
-static struct semaphore mfw_sema = MUTEX;
+static DECLARE_MUTEX(mfw_sema);
 #ifdef __SMP__
 static rwlock_t mfw_lock = RW_LOCK_UNLOCKED;
 #endif
diff -u --recursive --new-file v2.3.0/linux/net/ipv4/ip_masq_quake.c linux/net/ipv4/ip_masq_quake.c
--- v2.3.0/linux/net/ipv4/ip_masq_quake.c	Fri Feb 20 18:28:23 1998
+++ linux/net/ipv4/ip_masq_quake.c	Tue May 11 16:30:45 1999
@@ -44,7 +44,7 @@
 
 struct quake_priv_data {
 	/* Have we seen a client connect message */
-	char	cl_connect;
+	signed char	cl_connect;
 };
 
 static int
diff -u --recursive --new-file v2.3.0/linux/net/ipv4/tcp.c linux/net/ipv4/tcp.c
--- v2.3.0/linux/net/ipv4/tcp.c	Thu Apr 22 19:45:19 1999
+++ linux/net/ipv4/tcp.c	Wed May 12 14:50:26 1999
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp.c,v 1.140 1999/04/22 10:34:31 davem Exp $
+ * Version:	$Id: tcp.c,v 1.141 1999/05/12 11:24:40 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -660,7 +660,7 @@
 static int wait_for_tcp_connect(struct sock * sk, int flags)
 {
 	struct task_struct *tsk = current;
-	struct wait_queue wait = { tsk, NULL };
+	DECLARE_WAITQUEUE(wait, tsk);
 
 	while((1 << sk->state) & ~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT)) {
 		if(sk->err)
@@ -703,7 +703,7 @@
 {
 	release_sock(sk);
 	if (!tcp_memory_free(sk)) {
-		struct wait_queue wait = { current, NULL };
+		DECLARE_WAITQUEUE(wait, current);
 
 		sk->socket->flags &= ~SO_NOSPACE;
 		add_wait_queue(sk->sleep, &wait);
@@ -1117,7 +1117,7 @@
 		int len, int nonblock, int flags, int *addr_len)
 {
 	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 	int copied = 0;
 	u32 peek_seq;
 	volatile u32 *seq;	/* So gcc doesn't overoptimise */
@@ -1534,7 +1534,7 @@
 
 	if (timeout) {
 		struct task_struct *tsk = current;
-		struct wait_queue wait = { tsk, NULL };
+		DECLARE_WAITQUEUE(wait, current);
 
 		add_wait_queue(sk->sleep, &wait);
 		release_sock(sk);
@@ -1570,12 +1570,29 @@
 static struct open_request * wait_for_connect(struct sock * sk,
 					      struct open_request **pprev)
 {
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 	struct open_request *req;
 
-	add_wait_queue(sk->sleep, &wait);
+	/*
+	 * True wake-one mechanism for incoming connections: only
+	 * one process gets woken up, not the 'whole herd'.
+	 * Since we do not 'race & poll' for established sockets
+	 * anymore, the common case will execute the loop only once.
+	 *
+	 * Or rather, it _would_ execute only once if it wasn't for
+	 * some extraneous wakeups that currently happen.
+	 *
+	 * Subtle issue: "add_wait_queue_exclusive()" will be added
+	 * after any current non-exclusive waiters, and we know that
+	 * it will always _stay_ after any new non-exclusive waiters
+	 * because all non-exclusive waiters are added at the
+	 * beginning of the wait-queue. As such, it's ok to "drop"
+	 * our exclusiveness temporarily when we get woken up without
+	 * having to remove and re-insert us on the wait queue.
+	 */
+	add_wait_queue_exclusive(sk->sleep, &wait);
 	for (;;) {
-		current->state = TASK_INTERRUPTIBLE;
+		current->state = TASK_EXCLUSIVE | TASK_INTERRUPTIBLE;
 		release_sock(sk);
 		schedule();
 		lock_sock(sk);
diff -u --recursive --new-file v2.3.0/linux/net/ipv4/tcp_ipv4.c linux/net/ipv4/tcp_ipv4.c
--- v2.3.0/linux/net/ipv4/tcp_ipv4.c	Mon May 10 09:55:25 1999
+++ linux/net/ipv4/tcp_ipv4.c	Wed May 12 08:41:16 1999
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp_ipv4.c,v 1.175 1999/05/08 21:09:54 davem Exp $
+ * Version:	$Id: tcp_ipv4.c,v 1.176 1999/05/12 11:24:46 davem Exp $
  *
  *		IPv4 specific functions
  *
@@ -1944,6 +1944,8 @@
 	tcp_inode.i_sock = 1;
 	tcp_inode.i_uid = 0;
 	tcp_inode.i_gid = 0;
+	init_waitqueue_head(&tcp_inode.i_wait);
+	init_waitqueue_head(&tcp_inode.u.socket_i.wait);
 
 	tcp_socket->inode = &tcp_inode;
 	tcp_socket->state = SS_UNCONNECTED;
diff -u --recursive --new-file v2.3.0/linux/net/irda/af_irda.c linux/net/irda/af_irda.c
--- v2.3.0/linux/net/irda/af_irda.c	Sat Apr 24 17:50:06 1999
+++ linux/net/irda/af_irda.c	Wed May 12 13:27:37 1999
@@ -48,7 +48,7 @@
 
 static struct proto_ops irda_proto_ops;
 static hashbin_t *cachelog = NULL;
-static struct wait_queue *discovery_wait; /* Wait for discovery */
+static DECLARE_WAIT_QUEUE_HEAD(discovery_wait); /* Wait for discovery */
 
 #define IRDA_MAX_HEADER (TTP_HEADER+LMP_HEADER+LAP_HEADER)
 
diff -u --recursive --new-file v2.3.0/linux/net/irda/ircomm/irvtd_driver.c linux/net/irda/ircomm/irvtd_driver.c
--- v2.3.0/linux/net/irda/ircomm/irvtd_driver.c	Sat Apr 24 17:50:06 1999
+++ linux/net/irda/ircomm/irvtd_driver.c	Wed May 12 13:27:37 1999
@@ -607,7 +607,7 @@
 				 struct irvtd_cb *driver)
 {
 
- 	struct wait_queue wait = { current, NULL };
+ 	DECLARE_WAITQUEUE(wait,current);
 	int		retval = 0;
 	int		do_clocal = 0;
 
@@ -1930,6 +1930,10 @@
 		irvtd[i]->line = i;
 		irvtd[i]->closing_wait = 10*HZ ;
 		irvtd[i]->close_delay = 5*HZ/10 ; 
+		init_waitqueue_head(&irvtd[i]->open_wait);
+		init_waitqueue_head(&irvtd[i]->close_wait);
+		init_waitqueue_head(&irvtd[i]->tx_wait);
+		init_waitqueue_head(&irvtd[i]->delta_msr_wait);
 	}
 
 	/* 
diff -u --recursive --new-file v2.3.0/linux/net/netlink/af_netlink.c linux/net/netlink/af_netlink.c
--- v2.3.0/linux/net/netlink/af_netlink.c	Thu Apr 15 05:42:43 1999
+++ linux/net/netlink/af_netlink.c	Wed May 12 13:27:37 1999
@@ -45,7 +45,7 @@
 
 static struct sock *nl_table[MAX_LINKS];
 static atomic_t nl_table_lock[MAX_LINKS];
-static struct wait_queue *nl_table_wait;
+static DECLARE_WAIT_QUEUE_HEAD(nl_table_wait);
 
 #ifdef NL_EMULATE_DEV
 static struct socket *netlink_kernel[MAX_LINKS];
@@ -331,7 +331,7 @@
 	struct sock *sk;
 	int len = skb->len;
 	int protocol = ssk->protocol;
-	struct wait_queue wait = { current, NULL };
+        DECLARE_WAITQUEUE(wait, current);
 
 retry:
 	for (sk = nl_table[protocol]; sk; sk = sk->next) {
diff -u --recursive --new-file v2.3.0/linux/net/socket.c linux/net/socket.c
--- v2.3.0/linux/net/socket.c	Thu Apr 22 19:45:20 1999
+++ linux/net/socket.c	Tue May 11 14:37:40 1999
@@ -283,7 +283,7 @@
 	inode->i_gid = current->fsgid;
 
 	sock->inode = inode;
-	init_waitqueue(&sock->wait);
+	init_waitqueue_head(&sock->wait);
 	sock->fasync_list = NULL;
 	sock->state = SS_UNCONNECTED;
 	sock->flags = 0;
diff -u --recursive --new-file v2.3.0/linux/net/sunrpc/clnt.c linux/net/sunrpc/clnt.c
--- v2.3.0/linux/net/sunrpc/clnt.c	Tue Oct  6 09:39:44 1998
+++ linux/net/sunrpc/clnt.c	Tue May 11 14:37:40 1999
@@ -39,7 +39,7 @@
 # define RPCDBG_FACILITY	RPCDBG_CALL
 #endif
 
-static struct wait_queue *	destroy_wait = NULL;
+static DECLARE_WAIT_QUEUE_HEAD(destroy_wait);
 
 
 static void	call_bind(struct rpc_task *task);
diff -u --recursive --new-file v2.3.0/linux/net/sunrpc/sched.c linux/net/sunrpc/sched.c
--- v2.3.0/linux/net/sunrpc/sched.c	Fri May  7 11:19:11 1999
+++ linux/net/sunrpc/sched.c	Tue May 11 14:37:40 1999
@@ -60,9 +60,9 @@
 /*
  * rpciod-related stuff
  */
-static struct wait_queue *	rpciod_idle = NULL;
-static struct wait_queue *	rpciod_killer = NULL;
-static struct semaphore		rpciod_sema = MUTEX;
+static DECLARE_WAIT_QUEUE_HEAD(rpciod_idle);
+static DECLARE_WAIT_QUEUE_HEAD(rpciod_killer);
+static DECLARE_MUTEX(rpciod_sema);
 static unsigned int		rpciod_users = 0;
 static pid_t			rpciod_pid = 0;
 static int			rpc_inhibit = 0;
@@ -616,6 +616,7 @@
 	task->tk_client = clnt;
 	task->tk_flags  = RPC_TASK_RUNNING | flags;
 	task->tk_exit   = callback;
+	init_waitqueue_head(&task->tk_wait);
 	if (current->uid != current->fsuid || current->gid != current->fsgid)
 		task->tk_flags |= RPC_TASK_SETUID;
 
@@ -800,7 +801,7 @@
 	rpc_inhibit--;
 }
 
-static struct semaphore rpciod_running = MUTEX_LOCKED;
+static DECLARE_MUTEX_LOCKED(rpciod_running);
 
 /*
  * This is the rpciod kernel thread
@@ -808,7 +809,7 @@
 static int
 rpciod(void *ptr)
 {
-	struct wait_queue **assassin = (struct wait_queue **) ptr;
+	wait_queue_head_t *assassin = (wait_queue_head_t*) ptr;
 	unsigned long	oldflags;
 	int		rounds = 0;
 
diff -u --recursive --new-file v2.3.0/linux/net/sunrpc/svc.c linux/net/sunrpc/svc.c
--- v2.3.0/linux/net/sunrpc/svc.c	Tue Dec 29 11:42:25 1998
+++ linux/net/sunrpc/svc.c	Tue May 11 17:29:46 1999
@@ -123,6 +123,8 @@
 		goto out;
 
 	memset(rqstp, 0, sizeof(*rqstp));
+	init_waitqueue_head(&rqstp->rq_wait);
+
 	if (!(rqstp->rq_argp = (u32 *) kmalloc(serv->sv_xdrsize, GFP_KERNEL))
 	 || !(rqstp->rq_resp = (u32 *) kmalloc(serv->sv_xdrsize, GFP_KERNEL))
 	 || !svc_init_buffer(&rqstp->rq_defbuf, serv->sv_bufsz))
diff -u --recursive --new-file v2.3.0/linux/net/sunrpc/svcsock.c linux/net/sunrpc/svcsock.c
--- v2.3.0/linux/net/sunrpc/svcsock.c	Tue May  4 10:29:07 1999
+++ linux/net/sunrpc/svcsock.c	Tue May 11 14:37:40 1999
@@ -738,7 +738,7 @@
 {
 	struct svc_sock		*svsk;
 	int			len;
-	struct wait_queue	wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 
 	dprintk("svc: server %p waiting for data (to = %ld)\n",
 		rqstp, timeout);
diff -u --recursive --new-file v2.3.0/linux/net/unix/af_unix.c linux/net/unix/af_unix.c
--- v2.3.0/linux/net/unix/af_unix.c	Mon May 10 09:55:25 1999
+++ linux/net/unix/af_unix.c	Wed May 12 08:41:16 1999
@@ -8,7 +8,7 @@
  *		as published by the Free Software Foundation; either version
  *		2 of the License, or (at your option) any later version.
  *
- * Version:	$Id: af_unix.c,v 1.76 1999/05/08 05:54:55 davem Exp $
+ * Version:	$Id: af_unix.c,v 1.77 1999/05/12 11:25:07 davem Exp $
  *
  * Fixes:
  *		Linus Torvalds	:	Assorted bug cures.
@@ -114,8 +114,8 @@
 
 unix_socket *unix_socket_table[UNIX_HASH_SIZE+1];
 static atomic_t unix_nr_socks = ATOMIC_INIT(0);
-static struct wait_queue * unix_ack_wqueue = NULL;
-static struct wait_queue * unix_dgram_wqueue = NULL;
+static DECLARE_WAIT_QUEUE_HEAD(unix_ack_wqueue);
+static DECLARE_WAIT_QUEUE_HEAD(unix_dgram_wqueue);
 
 #define unix_sockets_unbound	(unix_socket_table[UNIX_HASH_SIZE])
 
@@ -433,7 +433,7 @@
 	sk->destruct = unix_destruct_addr;
 	sk->protinfo.af_unix.family=PF_UNIX;
 	sk->protinfo.af_unix.dentry=NULL;
-	sk->protinfo.af_unix.readsem=MUTEX;	/* single task reading lock */
+	init_MUTEX(&sk->protinfo.af_unix.readsem);/* single task reading lock */
 	sk->protinfo.af_unix.list=&unix_sockets_unbound;
 	unix_insert_socket(sk);
 
